Skip to content

feat(neighbors): navigate DECLARES.* composed edge types in one call#171

Merged
HumanBean17 merged 3 commits into
masterfrom
feat/neighbors-dot-key-traversal
May 16, 2026
Merged

feat(neighbors): navigate DECLARES.* composed edge types in one call#171
HumanBean17 merged 3 commits into
masterfrom
feat/neighbors-dot-key-traversal

Conversation

@HumanBean17
Copy link
Copy Markdown
Owner

Summary

  • neighbors accepts three DECLARES.* composed dot-keys (DECLARES.DECLARES_CLIENT, DECLARES.DECLARES_PRODUCER, DECLARES.EXPOSES) for type Symbol origins with direction="out" only; results echo the dot-key as edge_type and include via_id in attrs.
  • Shared _MEMBER_EDGE_COMPOSED_REL_MAP drives both member_edge_rollup_for (describe) and member_edge_traversal_for (neighbors) for count parity.
  • Describe hint templates (TPL_DESCRIBE_TYPE_*_VIA_MEMBERS) now prescribe single-call dot-key neighbors(...) — partial reversal of HINTS-ROAD-SIGNS decision plan: Tier 1B (B2b + B6) plan + per-PR Cursor prompts #11 for that family only; empty neighbors structural hints still filter dot-keys via _filter_neighbors_dotkey_hints.
  • OVERRIDDEN_BY / OVERRIDDEN_BY.* remain rejected at validation; wrong origin or inbound direction returns success=False with clear messages.

Implements propose/NEIGHBORS-DOT-KEY-TRAVERSAL-PROPOSE.md / #162. Plan: plans/PLAN-NEIGHBORS-DOT-KEY-TRAVERSAL.md § PR-1.

No ontology version bump or re-index (query-time / MCP only).

Manual evidence

KUZU=/tmp/dotkey-evidence/code_graph.kuzu
rm -rf /tmp/dotkey-evidence
.venv/bin/python build_ast_graph.py \
  --source-root tests/bank-chat-system \
  --kuzu-path "$KUZU" --verbose
.venv/bin/python -c "
from kuzu_queries import KuzuGraph
from mcp_v2 import describe_v2, neighbors_v2

g = KuzuGraph('$KUZU')
rows = g._rows(
    \"MATCH (t:Symbol)-[:DECLARES]->(:Symbol)-[:DECLARES_CLIENT]->() \"
    \"WHERE t.kind IN ['class','interface','enum','record','annotation'] \"
    'RETURN t.id AS id LIMIT 1', {})
tid = rows[0]['id']
d = describe_v2(tid, graph=g)
n = neighbors_v2(tid, direction='out', edge_types=['DECLARES.DECLARES_CLIENT'], graph=g, limit=500)
summary = d.record.edge_summary.get('DECLARES.DECLARES_CLIENT')
print('type_id', tid)
print('edge_summary', summary)
print('neighbors_count', len(n.results))
print('edge_type', n.results[0].edge_type)
print('via_id', n.results[0].attrs.get('via_id'))
assert n.success and summary and len(n.results) == summary['out']
"
type_id 82c3a8f3369d77290f1cc5e75cde575764f987e1
edge_summary {'in': 0, 'out': 1}
neighbors_count 1
edge_type DECLARES.DECLARES_CLIENT
via_id fd7df239339e3c95ee1e810e9fb596a189336308

Test plan

  • .venv/bin/ruff check .
  • PATH="$(pwd)/.venv/bin:$PATH" .venv/bin/python -m pytest tests -q (604 passed)
  • Targeted: pytest … -k "dot_key or declares_dot or overridden_by or composed_edge_summary or hints_describe_type or hv20"

Made with Cursor

Enable 2-hop DECLARES.DECLARES_CLIENT, DECLARES.DECLARES_PRODUCER, and
DECLARES.EXPOSES traversal for type Symbol origins (out only), with via_id
in attrs and count parity against describe edge_summary. Update describe
hint templates and docs; keep OVERRIDDEN_BY* rejected and empty neighbors
hints dot-key-free.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown
Owner Author

@HumanBean17 HumanBean17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

Solid PR-1 implementation: shared _MEMBER_EDGE_COMPOSED_REL_MAP for rollup + traversal, count-parity test, scoped hints reversal, and clear MCP contract (edge_type echoes dot-key, via_id in attrs, OVERRIDDEN_BY* still rejected at validation).

Recommend fixing one doc-generator bug before merge (details below). Happy path tests and manual evidence look good.


Blocking: EDGE-NAVIGATION.md duplicates the two-hop recipe

_COMPOSED_MEMBER_TYPE_TRAVERSAL in java_ontology.py already includes both the dot-key call and the two-hop alternative:

_COMPOSED_MEMBER_TYPE_TRAVERSAL = (
    "neighbors(['{id}'],'out',['DECLARES.{edge}']) — or "
    "neighbors(['{id}'],'out',['DECLARES']) then neighbors(member_ids,'{direction}',['{edge}'])"
)

But scripts/generate_edge_navigation.py appends the ontology type_subject again:

traversal = f"{composed} — or {traversal}"

Generated type_subject lines therefore read like:

dot-key — or two-hop — or two-hop

Plan §6 asked for dot-key alongside two-hop, not two-hop twice.

Suggested fix: for EXPOSES / DECLARES_CLIENT / DECLARES_PRODUCER, set traversal = composed only (drop the — or {traversal} suffix), then regenerate docs/EDGE-NAVIGATION.md.


Non-blocking (optional follow-ups)

  1. Mixed edge_types + pagination — when requesting e.g. ["DECLARES", "DECLARES.DECLARES_CLIENT"], all flat edges are appended before composed edges, then limit is applied; a small limit can return only member Symbols and zero Clients/Routes. Fine for v1 if documented or callers use the dot-key alone for terminals.

  2. Drift risk — composed keys live in kuzu_queries._MEMBER_EDGE_COMPOSED_REL_MAP, mcp_v2.ComposedEdgeType, and java_ontology._COMPOSED_MEMBER_TYPE_TRAVERSAL; a future fourth key needs three edits. Could derive ComposedEdgeType from the map later.

  3. Duplicate teststest_neighbors_rejects_composed_edge_summary_key and test_neighbors_dot_key_method_origin_rejected cover the same method-origin rejection; one could be dropped per plan §9.

  4. Merge housekeeping — move propose/NEIGHBORS-DOT-KEY-TRAVERSAL-PROPOSE.md to propose/completed/ when landed.


Otherwise LGTM on scope: no re-index, describe/neighbors parity, HV20 preserved for empty neighbors hints.

Use _COMPOSED_MEMBER_TYPE_TRAVERSAL alone in the doc generator (it
already includes the two-hop alternative). Document mixed flat+composed
pagination ordering; drop duplicate method-origin test covered in compose.

Co-authored-by: Cursor <cursoragent@cursor.com>
Move NEIGHBORS-DOT-KEY-TRAVERSAL propose and plan to completed/ with
landed status (PR #171). Follow-up #172 tracks unifying composed dot-key
constants across kuzu_queries, mcp_v2, and java_ontology.

Co-authored-by: Cursor <cursoragent@cursor.com>
@HumanBean17 HumanBean17 merged commit 343ccb4 into master May 16, 2026
1 check passed
@HumanBean17 HumanBean17 deleted the feat/neighbors-dot-key-traversal branch May 23, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant