ApiaryActive
Try: pause · settings · learn · wipe
← Community / Reading Room
RD
apiary-foundation · 4 min read

Repository Dependency Graphs for Safer AI Edits

An AI coding agent should not decide that a change is safe from the edited file alone. A repository dependency graph gives the agent a typed map of what the…

An AI coding agent should not decide that a change is safe from the edited file alone. A repository dependency graph gives the agent a typed map of what the change may affect: builds, imports, symbols, tests, owners, configuration, and deployment surfaces.

The graph is a risk estimator, not an oracle. Static analysis cannot reliably see every runtime import, reflection path, generated file, configuration lookup, or external consumer. The useful promise is narrower: expose known dependencies, label uncertainty, and require stronger validation as uncertainty grows.

Build several small graphs, not one vague graph

A practical model combines four evidence layers:

  • Build and module edges: project references, package dependencies, imports, generated-code inputs, and deployment units. TypeScript project references are a concrete example: tsc --build discovers referenced projects, checks which are current, and builds them in dependency order.
  • Symbol and behavior edges: definitions, references, calls, inheritance, interface implementations, data-flow facts, and query dependencies. The Rust compiler's incremental query system records query-to-query dependencies so affected work can be recomputed.
  • Verification edges: which tests, linters, type checks, fixtures, and contract checks exercise a node or boundary.
  • Operational edges: code ownership, public APIs, schemas, migrations, feature flags, configuration, and services that consume an artifact.

Each node should have a stable-enough identity such as repository, commit, path, language, symbol kind, and signature. Each edge should record its type, extraction method, source commit, and confidence. A parsed import is stronger evidence than a guessed semantic relationship; the data model should preserve that distinction.

Use the graph before, during, and after an edit

For a proposed patch, a safe planner can follow a bounded sequence:

  1. Map changed ranges to files, symbols, interfaces, and configuration keys.
  2. Traverse reverse edges to find known consumers.
  3. Stop or widen the traversal at explicit boundaries: package, service, public API, schema, or deployment unit.
  4. Select checks associated with the affected subgraph.
  5. Raise the review level for low-confidence or high-impact paths.
  6. Apply the patch in an isolated branch or sandbox.
  7. Re-extract facts from the changed tree, compare the graph delta, and run the selected checks.
  8. Report evidence and blind spots instead of returning only "passed."

This supports targeted testing without pretending that targeted testing is complete. A change to an internal leaf function might need a narrow unit suite. A change to a public interface, migration, authentication boundary, or shared build configuration should expand to broader checks and human review.

Prefer compiler-native facts

Start with sources that already understand the language or build system:

  • compiler project graphs and incremental dependency data;
  • language-server definitions and references;
  • build manifests and lockfiles;
  • test-runner coverage or explicit test-to-component manifests;
  • code-analysis databases such as CodeQL;
  • ownership and deployment configuration.

CodeQL is useful here because it creates a queryable representation of a codebase. It is not a universal call graph, and results vary by language and build visibility. Treat its findings as typed evidence alongside compiler and repository facts.

Semantic search can help discover likely relationships, but it should not silently become a structural edge. Store a semantic match as a lower-confidence retrieval hint until another source confirms it.

Make uncertainty visible

Graph coverage should be measurable. Useful fields include:

  • extraction success by language and package;
  • unresolved imports and symbols;
  • dynamic-loading and reflection markers;
  • generated or vendored regions;
  • stale facts relative to the target commit;
  • unowned public boundaries;
  • tests selected, tests omitted, and the reason for each.

A simple policy can combine impact and confidence. High impact plus low confidence blocks automatic application. Low impact plus high confidence can allow an automated patch, but only with the required checks. The policy should be inspectable and versioned; an LLM should not invent it per request.

Minimal implementation

The first useful version does not need a global knowledge graph:

  1. Index one repository revision.
  2. Normalize packages, files, symbols, tests, and deployment units into typed nodes.
  3. Extract imports, references, build dependencies, ownership, and verification edges using existing tools.
  4. Implement reverse-reachability queries with depth and boundary limits.
  5. Associate repository checks with nodes or boundaries.
  6. Cache facts by content hash and invalidate them when their inputs change.
  7. Evaluate the planner on historical changes: affected tests found, relevant consumers missed, false-positive expansion, and review overrides.

Rebuild or incrementally update the graph from the exact commit under review. Mixing facts from different revisions produces confident-looking but unsafe plans.

Design constraints

  • Do not claim "safe" when the result means only "no known dependent failed."
  • Do not let a graph traversal authorize writes; authorization remains a separate policy.
  • Do not send proprietary graph data to an external model unless the repository's data policy permits it.
  • Keep provenance so a reviewer can explain why a file or test was included.
  • Preserve a full validation path for high-risk changes even when the graph proposes a smaller one.

A good repository graph makes an agent less surprising. Its value is not that it proves a patch harmless, but that it turns hidden impact into reviewable evidence and makes missing knowledge explicit.

Sources / further reading

Frequently asked
What is Repository Dependency Graphs for Safer AI Edits about?
An AI coding agent should not decide that a change is safe from the edited file alone. A repository dependency graph gives the agent a typed map of what the…
What should you know about build several small graphs, not one vague graph?
A practical model combines four evidence layers:
What should you know about use the graph before, during, and after an edit?
For a proposed patch, a safe planner can follow a bounded sequence:
What should you know about prefer compiler-native facts?
Start with sources that already understand the language or build system:
What should you know about make uncertainty visible?
Graph coverage should be measurable. Useful fields include:
References & sources
  1. Apiary Reading RoomOpen, cited knowledge base — funded to keep bee & practical research free.
From the Apiary Reading Room. Opinion & editorial — not financial advice. We don't overclaim.
More from the Reading Room