Son of Anton Docs
Code review

Context Graph

The per-repo, per-commit graph of symbols, imports and references that gives the review blast radius beyond the diff.

In son-of-anton-review (feat/cloudflare-native), preflight builds an in-memory graph of the checked-out repository. It estimates affected files, potential test coverage and risk beyond the diff. It is a bounded regex-based graph, not a type-resolved or multi-repository index.

What is built at preflight

Before any model call, the runner indexes the repo into a ContextGraph (src/context-graph.js). Per file it records:

FactHow it is extracted
importsextractImports: import, export ... from, dynamic import() and require(). Relative specifiers are resolved to repo paths; bare package names are dropped.
symbolsextractSymbols: regex matches for function, class, const, let, var declarations, including matches that are not exported or top-level
referencesEvery identifier in the file that is not one of its own symbols.
tests, isTestPaths under test/, tests/, __tests__/ or ending in .test.* / .spec.*.
hashSHA-256 of content, used to report whether an indexed fact changed; extraction is still performed before that comparison

Scope is JavaScript and TypeScript only (.js .mjs .cjs .jsx .ts .mts .cts .tsx). The walk caps at 1000 files and skips files over 512 KB. The graph is rebuilt per run from the checked-out head; it is not a long-lived index.

Blast radius

computeImpact(changedPaths) does a breadth-first walk from the changed files:

  1. Any file that imports a changed file is impacted (imports).
  2. Any file containing a reference token matching a symbol recorded on an impacted file is impacted (references_symbol).
  3. Repeat until no new files join.

The result carries changed, impacted, productionFiles, tests, blastRadius (count of impacted paths) and reasons, a per-path chain explaining why each file was pulled in.

analyzeChange layers intelligence on top:

  • testsToRun: impacted test files plus tests inferred from direct imports or symbol references to impacted production files, capped at 20. This is context for the reviewer, not an instruction that automatically runs those individual files.
  • missingTests: impacted production files with no inferred reaching test.
  • risk.score (0 to 10) and risk.level (low under 4, medium under 7, high at 7 and above), weighted by changed count, blast radius, fan-in of changed files, missing tests and orphan imports. risk.drivers lists the reasons in plain text.

Preflight summary lines and the graph brief expose health, blast radius, risk and inferred tests. The hypothesis-primary result builder puts a non-zero blast radius into Cross-Repo Impact. The normal semantic result supplies its own section, and the deterministic docs-only result leaves that section empty. Do not treat the heading as proof of a second-repository traversal.

Where it lives

Optional persistence targets the legacy queue Worker, cloudflare/src/worker.js, through cloudflare/src/context-graph-api.js. It is not the native ingress API. The legacy configuration names D1 gilf-context-graph and R2 gilf-context-graph-artifacts.

EndpointMethodPurpose
/context-graph/healthGETReports whether the D1 and R2 bindings are present
/context-graph/filesPOST / GETWrite or read per-file facts for a repo + commitSha
/context-graph/snapshotsPOST / GETWrite or read the impact, intelligence and hypotheses snapshot
/context-graph/artifactsPOST / GETWrite or read review artifacts by key

The client sends authorization: Bearer <token>. The legacy Worker validates it against its GILF_QUEUE_TOKEN, including for /context-graph/health. The binding names below come from cloudflare/wrangler.toml; provisioning also requires the actual database identifier.

[[d1_databases]]
binding = "CONTEXT_GRAPH_DB"
database_name = "gilf-context-graph"

[[r2_buckets]]
binding = "CONTEXT_GRAPH_BUCKET"
bucket_name = "gilf-context-graph-artifacts"

The table schema is cloudflare/schema/context-graph.sql. The runner sends at most 50 file facts, although graph analysis can scan up to 1000 files. Its snapshot includes impact, intelligence and hypotheses, not a complete persisted copy of every scanned file. A persistence exception emits context_graph_persist_failed and does not abort the review.

Configuration

# Defaults to GILF_QUEUE_URL / GILF_QUEUE_TOKEN when unset.
GILF_CONTEXT_GRAPH_URL=https://gilf-pr-review-queue.<your-subdomain>.workers.dev
GILF_CONTEXT_GRAPH_TOKEN=replace-with-context-graph-token

Both URL and token must be non-empty to construct the default client. The client token must match the legacy server's queue token unless a separately implemented server uses a different authorization contract.

Native deployment limitation: neither GILF_CONTEXT_GRAPH_URL / GILF_CONTEXT_GRAPH_TOKEN nor their GILF_QUEUE_URL / GILF_QUEUE_TOKEN fallbacks are forwarded by cloudflare-native/src/container-env.js. The native entrypoint does not inject a graph store. The graph is still built in-process, but Worker vars alone do not enable persistence. Native src/main.js routes public fetches to ingress, which does not expose these endpoints.

Repo context files read at review time

Semantic review passes the listed paths to collectReviewCodeEvidence, which reads pinned Git blobs rather than following working-tree files. It accepts regular blob modes, recursively lists a context directory and clips each excerpt to at most 4000 bytes, within a separate default 32 KiB/60-file guidance budget. Oversized, non-regular or unavailable evidence becomes a limitation.

The optional buildReviewPrompt fallback helper behaves differently when no pinned packet is passed: it reads working-tree files, includes only immediate regular children of directories, trims content and slices 4000 JavaScript string code units. Do not treat that fallback as the normal pinned semantic-review path.

PathNotes
AGENTS.md, CLAUDE.mdAgent instruction files are read as review guidance
README.md, ARCHITECTURE.md, docs/ARCHITECTURE.mdProject overview
CONTRIBUTING.md, SECURITY.mdContribution and security rules
.github/CODEOWNERS, .github/copilot-instructions.mdOwnership and existing assistant rules
.cursor/rulesPinned evidence lists directory contents recursively, subject to the guidance budget
pr-review-agent.ymlRead as review guidance, not parsed here to apply runtime config
system-map.yaml, critical-paths.yaml, contract-catalog.yamlCross-repo relationships, critical paths, contracts

The fallback helper skips empty/missing files. The pinned evidence collector can include empty regular-file excerpts and reports read/size limitations rather than silently claiming complete guidance.

system-map.yaml shape

schemas/system-map.schema.json defines the cross-repo map. Top level is repos, keyed by repo name:

repos:
  billing-api:
    type: backend            # frontend | backend | mobile | library | infra | docs | worker | service
    owners: [payments-team]
    domains: [payments]
    deployTier: critical     # critical | high | normal | low
    depends_on: [shared-auth]
    dependents: [web-app]
    contracts:
      - kind: api            # api | event | schema | package | auth_boundary | db_model
        name: /v1/charges
        role: exposes        # consumes | exposes | owns | shares
    criticalPaths: [checkout]

The file is read as text into the review context. The schema is a contract for authors; nothing in the runner validates against it today.

Honest scope

  • Cross-Repo Impact is a result section, not evidence of a multi-repo graph. The deterministic hypothesis builder uses the local blast radius; semantic results may also reason from supplied text.
  • The repo context files are text guidance. They do not turn the graph into a cross-repo index. See Learning, memory and priors for the separate memory system.
  • Symbol references are identifier matches, not type-resolved. Expect some over-approximation on common names.

Observability

Graph construction emits context_graph_started / context_graph_completed, mapped to a context.graph retrieval span. The optional persistence events map to context.graph.read for preflight persistence and context.graph.write for hypothesis-artifact persistence, despite the former also writing data. These event names alone do not prove that a deployed graph store or dashboard view is available.

Source evidence

  • son-of-anton-review/src/context-graph.js:3-7,15-55,58-212,306-351.
  • son-of-anton-review/src/codex-review-runner.js:743-830,1485-1526,1618-1649,1758-1785,1795-1825,2517-2526.
  • son-of-anton-review/src/review-code-evidence.js:3-7,122-160; src/codex-review-runner.js:1573-1596,1828-1853,2963-2969,3090-3093.
  • son-of-anton-review/src/context-graph-storage.js:78-148; cloudflare/src/context-graph-api.js:57-160; cloudflare/src/worker.js:30-39,156-176.
  • son-of-anton-review/cloudflare/wrangler.toml:9-16; schemas/system-map.schema.json:5-42.
  • son-of-anton-review/cloudflare-native/src/container-env.js:15-85; cloudflare-native/src/main.js:26-29; cloudflare-native/container/entrypoint.mjs:345-374.

On this page