From One Symbol to the Real Blast Radius: How Synaptic’s `affected` Tool Works
See how Synaptic’s "affected" tool maps the blast radius of a code change using reverse-dependency analysis—and how Synaptic Cloud delivers that evidence securely through a graph-only MCP gateway.

What does Synaptic's affected tool do?
Synaptic's affected tool walks the code graph backward from a changed symbol to identify dependent code and relevant tests. It returns bounded, source-linked evidence, including relationship type and depth, so developers and coding agents can review the likely blast radius before editing.
Changing a function rarely affects only that function.
A shared authentication method may be called by several services. A database table may support multiple queries. An interface may connect implementations written in different languages. Before making a change, engineers need to understand this wider blast radius—not just find a few matching lines of code.
Synaptic’s affected tool answers a focused question:
What could depend on this symbol, directly or indirectly, if we change it?
The answer comes from Synaptic’s persistent code graph. It is calculated by the Rust engine and made available to developers and coding agents through Synaptic Cloud’s authenticated MCP gateway.
Callers are only the first step
A traditional “find callers” operation is useful, but it usually covers one relationship and one hop.
Real change impact can travel through many kinds of dependency:
- A function calls another function.
- A module imports or re-exports a symbol.
- A class implements an interface.
- An application reads from or writes to a database table.
- An HTTP client connects to a route and its handler.
- A process invokes another executable or crosses an FFI boundary.
- A service in one repository depends on behavior defined in another.
The affected tool follows these structural relationships transitively. That lets it identify both immediate dependents and the systems that depend on those dependents.
How the engine calculates impact
Inside the Synaptic engine, graph edges point from a dependent to its dependency. If checkout calls authorize, for example, the graph records that checkout depends on authorize.
To calculate the effect of changing authorize, the engine walks those relationships in reverse.
The implementation uses a bounded breadth-first traversal with three important controls:
-
Impact-bearing relationships only. The engine follows relationships such as calls, imports, inheritance, data access, service calls, handlers, native bindings, and selected dynamic references. Structural containment alone does not imply change impact, so relationships such as “contains” are excluded.
-
A defined hop limit. Every request has a maximum traversal depth. This keeps the result focused and prevents a highly connected symbol from expanding into an unbounded graph walk.
-
Deterministic deduplication. The engine tracks visited nodes, avoids cycles, and orders results consistently. Each result records its distance from the original symbol and the relationship through which it was reached.
For the common path, the server reuses a prebuilt reverse-impact index rather than reconstructing reverse adjacency for every request. The same index can also support multi-symbol forecasts and predictive test selection.
Classes require special treatment
A class can appear deceptively isolated when most of its incoming dependencies attach to its methods rather than to the class node itself.
Synaptic accounts for that distinction. When the selected symbol is a class, struct, interface, or similar type, the engine folds its members into the impact calculation. The result identifies that aggregation explicitly.
This prevents a class from being reported as a safe leaf merely because callers connect to ClassName.method() instead of directly to ClassName.
Static analysis should be honest about uncertainty
Dynamic behavior creates another important edge case.
Reflection, computed imports, event buses, IPC, and runtime dispatch can hide relationships that static analysis cannot resolve with certainty. If Synaptic finds no static dependents but detects relevant dynamic behavior, affected can return a dynamic caveat.
That distinction matters. “No static dependents found” is useful evidence, but it is not always the same as “safe to change.”
Rather than hiding that limitation, Synaptic includes it in the result so an engineer or agent knows where additional investigation is required.
A bounded, explainable result
A typical request can be as small as:
{
"label": "authorize_request@src/auth/policy.rs",
"depth": 3,
"limit": 25
}
The response includes:
- The resolved symbol and its qualified
label@pathidentity - The true number of affected nodes
- A breakdown by traversal depth
- Each returned dependent’s qualified identity
- The relationship used to reach it
- Whether the displayed list was truncated
- Type-member aggregation details, when applicable
- A dynamic-dispatch caveat, when static evidence may be incomplete
This is especially useful for coding agents. Instead of receiving an unexplained list of files, the agent receives a bounded structural answer with enough context to determine why each result matters.
How Synaptic Cloud enables the tool
The Rust engine performs the graph computation. Synaptic Cloud provides the controlled path that makes the result available to a team.
That path begins with graph creation.
An isolated worker checks out an authorized repository revision and runs the digest-verified Synaptic engine without external network access. The engine extracts symbols, dependencies, resources, SQL objects, and cross-language boundaries into a graph artifact.
The worker calculates the artifact’s SHA-256 digest, uploads it, and reports the completed snapshot. The control plane then promotes that exact graph generation.
Query serving is a separate stage. The hosted runtime receives the verified graph artifact—not the repository checkout or its credentials—and launches a project-scoped engine process against that immutable graph. Source-reading, worktree inspection, command execution, automatic refresh, and query logging are disabled at this boundary.
Before accepting a runtime binding, the control plane verifies that:
- The runtime serves the currently promoted snapshot.
- The graph artifact digest matches.
- The engine binary and version match the approved runtime identity.
- The MCP protocol handshake succeeds.
- The expected graph-query tools are available.
A stale or mismatched binding fails closed instead of silently querying another graph generation.
From an AI client to the engine
When a developer connects an MCP-compatible coding tool to Synaptic Cloud, requests first reach the platform gateway.
The gateway authenticates the developer’s personal MCP token, verifies project access, applies rate and session limits, and validates the request against Synaptic’s hosted graph-only policy.
The developer token stops at the gateway. A separate generation-specific service credential selects the project runtime, so the child engine is not chosen from a user-controlled project header or request body.
For affected, the hosted policy also bounds the symbol reference, hop depth, relationship list, result limit, and response shape. The returned JSON is validated before it is released to the client.
MCP sessions are pinned to the binding, runtime instance, and snapshot. If a new graph is promoted or the engine is rebound, the old session cannot continue against the new generation.
Better evidence before a change
The value of affected is not that it predicts every runtime behavior with certainty. Its value is that it turns a vague concern about change risk into inspectable structural evidence.
Before editing a shared symbol, an engineer can see the likely blast radius. Before proposing a refactor, a coding agent can identify the systems that require review. Before running an entire test suite, a team can use the same reverse-impact foundation to narrow the tests most likely to matter.
The Rust engine supplies the graph reasoning. Synaptic Cloud supplies the authenticated, generation-pinned, graph-only route that makes that reasoning available wherever software decisions are made.

