You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Phase 1 ticket T6. Depends on #652 (T4 index_repo).
Context
impact_analysis answers the refactoring question "what breaks if I change this symbol?" via transitive upstream traversal. This is the only MCP tool with no existing backing implementation in api/graph.py — it requires a new variable-depth Cypher query.
Scope
In:
New helper in api/graph.py (sync) and api/graph.py async (AsyncGraphQuery):
MATCH (n{id: $id})<-[:CALLS*1..$depth]-(impacted)
RETURNDISTINCTimpacted
For OUT direction, flip the arrow. DISTINCT provides cycle safety.
Defaults: direction="IN" (upstream callers), depth=3. Hard cap depth to 10 to prevent runaway queries — pass higher values silently clamp with no error.
New MCP tool registration in api/mcp/tools/structural.py:
Unit (mocked graph): depth clamp test (depth=999 → 10), direction validation (only IN and OUT accepted).
Cycle test: graph with A → B → A returns each node exactly once.
Linear chain: on a fixture with A→B→C→D, asserts impact_analysis("D", depth=3) returns {A, B, C}.
Depth boundary: same chain, impact_analysis("D", depth=2) returns {B, C}.
Integration: against the T3 fixture using expected.yaml impact assertions.
Protocol round-trip.
Out:
Cross-rel impact (only CALLS traversal in v1; future: CALLS|EXTENDS|IMPLEMENTS)
Weighted ranking
Cross-repo / cross-branch impact
Files to create / modify
api/graph.py — new Graph.impact_analysis() and AsyncGraphQuery.impact_analysis() methods
api/mcp/tools/structural.py — tool registration
new tests/mcp/test_impact_analysis.py
tests/mcp/fixtures/expected.yaml (T3) — extend with impact assertions for at least one symbol (this might already be in T3 if planned ahead; otherwise add here)
Acceptance criteria
Graph.impact_analysis and AsyncGraphQuery.impact_analysis methods exist and execute correct Cypher.
MCP tool registered with input schema symbol_id: str, direction: "IN"|"OUT" = "IN", depth: int = 3.
Linear chain test: on A→B→C→D, impact_analysis("D", depth=3, direction="IN") returns exactly {A, B, C}.
Linear chain test: direction="OUT" from A returns {B, C, D}.
Cycle test: A↔B returns each node exactly once (no infinite loop, no duplicates).
Depth clamp: depth=999 does not error; effective depth is 10. A unit test asserts the clamped Cypher parameter.
Direction validation: invalid values (e.g. "BOTH") raise a clear error before any query executes.
Integration test against T3 fixture using contract assertions.
Variable-depth Cypher in FalkorDB: [:CALLS*1..$depth] is supported. Pass $depth as a query parameter.
Use DISTINCT impacted in the RETURN to handle cycles and diamond dependencies in one shot. No need to track visited nodes manually.
Document the depth clamp in the tool docstring so the agent understands the limit.
Reuse the protocol-test helper from T4.
For the cycle test fixture, create a small temporary graph at test time rather than adding cycles to the main T3 fixture (cycles in the shared fixture would complicate other tests).
Phase 1 ticket T6. Depends on #652 (T4 index_repo).
Context
impact_analysisanswers the refactoring question "what breaks if I change this symbol?" via transitive upstream traversal. This is the only MCP tool with no existing backing implementation inapi/graph.py— it requires a new variable-depth Cypher query.Scope
In:
api/graph.py(sync) andapi/graph.pyasync (AsyncGraphQuery):INdirection):OUTdirection, flip the arrow.DISTINCTprovides cycle safety.direction="IN"(upstream callers),depth=3. Hard capdepthto10to prevent runaway queries — pass higher values silently clamp with no error.api/mcp/tools/structural.py:tests/mcp/test_impact_analysis.py:depth=999→ 10), direction validation (onlyINandOUTaccepted).A → B → Areturns each node exactly once.A→B→C→D, assertsimpact_analysis("D", depth=3)returns{A, B, C}.impact_analysis("D", depth=2)returns{B, C}.expected.yamlimpact assertions.Out:
CALLStraversal in v1; future:CALLS|EXTENDS|IMPLEMENTS)Files to create / modify
api/graph.py— newGraph.impact_analysis()andAsyncGraphQuery.impact_analysis()methodsapi/mcp/tools/structural.py— tool registrationtests/mcp/test_impact_analysis.pytests/mcp/fixtures/expected.yaml(T3) — extend with impact assertions for at least one symbol (this might already be in T3 if planned ahead; otherwise add here)Acceptance criteria
Graph.impact_analysisandAsyncGraphQuery.impact_analysismethods exist and execute correct Cypher.symbol_id: str, direction: "IN"|"OUT" = "IN", depth: int = 3.A→B→C→D,impact_analysis("D", depth=3, direction="IN")returns exactly{A, B, C}.direction="OUT"fromAreturns{B, C, D}.A↔Breturns each node exactly once (no infinite loop, no duplicates).depth=999does not error; effective depth is 10. A unit test asserts the clamped Cypher parameter."BOTH") raise a clear error before any query executes.Dependencies
index_repo).Out of scope (do NOT do in this PR)
CALLSfor v1).Notes for the implementer
[:CALLS*1..$depth]is supported. Pass$depthas a query parameter.DISTINCT impactedin the RETURN to handle cycles and diamond dependencies in one shot. No need to track visited nodes manually.