Skip to content

feat(graph): add symbol callers, callees and impact tools - #124

Merged
balcsida merged 10 commits into
mainfrom
feat/codegraph/s1-07-symbol-tools
Sep 28, 2026
Merged

balcsida merged 10 commits into
mainfrom
feat/codegraph/s1-07-symbol-tools

Conversation

@balcsida

Copy link
Copy Markdown
Owner

Summary

This is the next S1.07 slice of the CodeGraph parity roadmap. CodeGraph's MCP surface has eight tools. GraphNest already covered search, explore, files and status; this PR adds callers, callees and impact, addressed by symbol name the way agents call them. The remaining tool, node, is a follow-up.

  • REST: POST /v1/graph/callers, /v1/graph/callees and /v1/graph/impact-radius.
  • MCP: graph_callers, graph_callees and graph_impact_radius, listed in the capability workflows.
  • Name matching: a port of upstream matchesSymbol:
    • an exact name, or a file name without its extension;
    • qualified forms (Class.method, module::fn, dir/module) matched by qualified-name suffix, or by path for Rust and Python modules;
    • crate::, super:: and self:: stripped;
    • Erlang arity (fn/3) must match;
    • Nix option paths resolved to their options. declaration first.
  • Grouping: one section per distinct definition (same path and qualified name). file narrows by path or suffix; when nothing matches, all definitions are returned with file_filter: unmatched.
  • Callers and callees: follow calls, imports, instantiates, navigates and references one hop, in the producer's edge order. Each neighbor appears once with its first edge. limit applies per definition (default 20, clamped to 1–100) and truncated reports when more exist.
  • Impact: merges each definition's existing ImpactRadius (depth default 2, clamped to 1–10).
  • Authorization: like the other v2 queries. Scope is one selected repository; entities and edges must belong to it; the credential and grant are rechecked before delivery.

Evidence

  • New reference answers. The pinned harness (b9ca4b7) now also runs upstream's real codegraph_callers, codegraph_callees and codegraph_impact handlers: 11 new answers, 52 in all. They cover grouping of same-named definitions (normalize ×3, greet ×4, identity ×2), file narrowing and its fallback, a qualified name, a limit, a depth, an absent symbol, and via instantiation and via import labels.
  • Timing baseline. workflow-baseline.json is refreshed because it pins the harness file's hash. It was measured on the same machine class.
  • Oracle comparison. TestGraphSymbolToolsMatchCodeGraph loads the real fixture into PostgreSQL, renders GraphNest's structured answers in upstream's markdown layout and compares them:
    • the eight callers and callees answers match exactly, apart from the order of same-named definition sections (see below);
    • the three impact answers match as sets.
  • Mutation check. Reversing the relation order fails five of the eleven cases.
  • Transports. TestGraphSymbolToolsRESTAndMCP shows REST and MCP return identical answers from PostgreSQL, and that an ungranted repository returns 404.

Known differences from upstream

Documented in docs/graph-exploration.md and the execution record:

  • No searchNodes port yet. Upstream's name search is SQLite FTS5 BM25 with LIKE and Levenshtein fallbacks and rescoring. GraphNest's Discover is exploration ranking: for example it matches Fixture for MissingFixtureSymbol987, where upstream finds nothing. So these tools use exact-name candidates with upstream's matching rules. Consequences:
    • same-named definitions are ordered by generated file last, then path and line, instead of by BM25 score;
    • a name with no exact match returns not_found instead of upstream's best non-exact guess.
  • Impact walks by shortest dependency depth. This is the existing, documented S1.06a3 behavior. At depth 2 it also reports consumer.ts and processGreeting, which upstream's depth-first walk omits, and order within a file differs.

Compatibility and security

No schema or migration change and no new dependency. New read-only routes and tools only. The edge-ordering option is internal (EntityNeighborQuery.ProducerOrder).

Verification

GOWORK=off go vet ./... && GOWORK=off go vet -tags=integration ./... && GOWORK=off go vet -tags=e2e ./...
go -C scanner vet -tags=e2e ./...
make test-race staticcheck parity-reference
make postgres-test   # with -race: postgres, authz, webhook, integration, indexer, server (603 passed)
python3 test/parity/generate_reference.py --upstream <pinned clone> --node <node 24.13.0> --check
docker run --rm -v "$PWD":/src -w /src ruby:3.4-alpine ruby scripts/check_openapi.rb

Not in this PR

codegraph_node (file and symbol modes), a searchNodes port, and the rest of S1.07, S1.09 and S1.10. The Stage 1 gate has not been run.

🤖 Generated with Claude Code

balcsida and others added 10 commits September 27, 2026 19:32
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@balcsida
balcsida merged commit 1778af0 into main Sep 28, 2026
11 of 12 checks passed
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