The Bottom Line
Your AI assistant doesn't know what your code depends on. It reads the file in front of it, infers a plausible change, and ships. The graph knows. Draft's graph engine treats blast radius as a first-class query — before code is written, while it's being written, and as memory after the track lands. Three loops, one shared answer to a question every senior engineer asks instinctively: what else does this break?
Below is a real run on a Go service refactor that started as "add audit logging to write paths" and ended as "extract a transaction-hook interface" — because the impact query said so before any code existed.
The Track: "Add Structured Audit Logging to Writes"
Existing system: a Go monorepo, ~80,000 lines, internal tooling for a fintech ops team. Writes go through internal/db/transaction.go: every Commit() ends up there. The spec landed in draft/tracks/audit-write-trail/spec.md:
# Structured Audit Logging on Writes
## Problem
Compliance review flagged that we cannot reconstruct who
mutated which row, when, or with what payload. Existing
log lines are unstructured and missing actor identity.
## Acceptance
- Every committed write produces one structured audit record
- Record contains: actor, table, op, row pk, before/after, ts
- No measurable latency regression on hot paths
- Records retained 7 years per compliance policy
The naive plan: open internal/db/transaction.go, wrap Commit(), write to an audit table inside the same transaction. One file. Two hours. Done.
The graph disagrees.
Step 1: The Hotspot Warning Fires Before Anything Runs
When /draft:implement picks up the first task, it loads draft/graph/hotspots.jsonl and checks every file the task plans to touch. internal/db/transaction.go is on the list:
⚠ Hotspot detected
File: internal/db/transaction.go
fanIn: 31
Lines: 412
Changes here affect many downstream files.
Consider running a graph impact query before writing code.
graph --repo . --out draft/graph \
--query --file internal/db/transaction.go \
--mode impact
This warning is in skills/implement/SKILL.md at line 48. The graph's hotspots.jsonl was built from lines + fanIn * 50 — complexity weighted by how many other files include or import the file. transaction.go isn't large; it's central. Thirty-one direct dependents.
Most AI assistants ignore this kind of signal. The Draft skill stops and waits.
Step 2: The Impact Query — What Actually Breaks
Run the suggested command:
graph --repo . --out draft/graph \
--query --file internal/db/transaction.go \
--mode impact
Output (trimmed for the post):
{
"target": "internal/db/transaction.go",
"impact": {
"files": 47,
"modules": 9,
"affected_modules": [
"internal/db", "internal/api/orders",
"internal/api/billing", "internal/api/users",
"internal/jobs/reconcile", "internal/audit",
"cmd/server", "deploy/charts",
"docs/runbooks"
],
"by_category": {
"code": 29,
"test": 12,
"doc": 3,
"config": 3
},
"files_by_depth": {
"1": 14, "2": 21, "3": 9, "4": 3
},
"files_by_category": {
"test": [
"internal/api/orders/orders_test.go",
"internal/api/billing/billing_test.go",
... (10 more)
],
"config": [
"deploy/charts/values.yaml",
"deploy/charts/templates/deployment.yaml",
"ops/migrations/0042_audit_index.sql"
],
"doc": [
"docs/runbooks/incident-rollback.md",
"docs/architecture/transactions.md",
"docs/api/audit-fields.md"
]
}
},
"warning": "High fanIn — review affected_modules before merging."
}
Read it once and the "two-hour change" plan dies:
- 47 downstream files reach
transaction.gothrough dependency chains up to four hops deep. WrappingCommit()changes the contract for every one of them. - 12 tests — that's the regression bill. Any change to commit semantics needs them re-asserted, not just re-run.
- 3 config files — the Helm chart and a migration. Adding an audit table means a deploy-time migration and a chart change. Easy to miss without the graph spelling it out.
- 3 doc files — the runbook references the current commit semantics. Stale docs after a refactor become an incident in six weeks.
- Nine affected modules, including
cmd/server— the binary entry point. Anything touchingtransaction.gorecompiles the world.
The categorization comes from scripts/tools/classify-files.sh — the same classifier the graph uses everywhere. The by_category bucket is the one to read first: it's the difference between "five-line change" and "regression sweep."
Step 3: Reshaping the Plan
Knowing this before writing code changes the plan. The original task — "wrap Commit()" — would have rippled through 47 files. The reshape:
- Extract a
TransactionHookinterface ininternal/db— one new file, zero touches totransaction.go's public surface. - Implement
AuditHookin the existinginternal/auditmodule — isolated unit with its own tests. - Wire the hook in
cmd/serverat construction time — one diff, one place.
Same outcome (every commit produces an audit record) with one structural touch on the hotspot instead of forty-seven cascading ones. The graph didn't write that plan — the engineer did. The graph stopped the engineer from accepting the worse one.
Step 4: The Memory — metadata.json.impact
Once the track's first phase passed review, /draft:implement snapshotted the actual blast radius into the track's metadata.json. The relevant block:
{
"id": "audit-write-trail",
"title": "Structured Audit Logging on Writes",
"status": "completed",
...
"impact": {
"files_touched": [
"internal/db/transaction.go",
"internal/db/hooks.go",
"internal/audit/recorder.go",
"internal/audit/recorder_test.go",
"cmd/server/main.go",
"deploy/charts/templates/deployment.yaml",
"ops/migrations/0042_audit_index.sql",
"docs/architecture/transactions.md"
],
"modules_touched": [
"internal/db", "internal/audit",
"cmd/server", "deploy/charts",
"ops/migrations", "docs/architecture"
],
"downstream_files": 47,
"downstream_modules": [
"internal/api/orders", "internal/api/billing",
"internal/api/users", "internal/jobs/reconcile",
...
],
"max_depth": 4,
"by_category": {
"code": 29, "test": 12, "doc": 3, "config": 3
},
"computed_at": "2026-05-08T14:32:11Z"
}
}
This isn't analytics. It's track memory. files_touched is computed from git diff --name-only <first_sha>^..HEAD — what the track actually changed, not what it was scoped to. downstream_* fields come from the same impact query rerun against every touched file. The full procedure is in skills/implement/SKILL.md §5.
Ten seconds of compute that a normal workflow throws away. Draft writes it down.
Step 5: Two Weeks Later, the Overlap Warning Fires
A different engineer, different sprint, different track. They run /draft:new-track "add row-level encryption to writes" and start the intake conversation. Before the spec is even drafted, the skill scans every draft/tracks/*/metadata.json updated in the last 30 days, reads each impact block, and builds a module → recent-tracks map. When the new track's candidate modules resolve to internal/db, the intake summary surfaces:
Overlap warning:
Track `audit-write-trail` recently touched modules
internal/db, internal/audit (completed 2026-05-08).
Review draft/tracks/audit-write-trail/metadata.json#impact
before proceeding.
Suggested actions:
• Coordinate with the prior track's owner
• Consider whether to extend the existing TransactionHook
interface rather than introduce a parallel mechanism
• Rebase scope to avoid touching internal/db/transaction.go
again within the same compliance window
This is informational, not blocking. The user decides. But the question that used to require tribal memory — "didn't somebody just touch this?" — is answered automatically. The procedure is in skills/new-track/SKILL.md at line 45.
The engineer chose to extend the existing hook interface. Both tracks shipped without trampling each other.
The Three Loops, Composed
Pull back and the architecture is one shared graph used in three places:
- Pre-change risk assessment. Before
/draft:implementtouches a hotspot, it loadshotspots.jsonl, warns, and points at the impact query. The query returns categorized blast radius — the actual answer to "what breaks?" - Post-completion memory. When a phase passes review,
/draft:implementsnapshotsfiles_touched+ downstream blast radius intometadata.json.impact. Ten extra seconds, written into git. - Cross-track overlap detection. When
/draft:new-trackopens, it reads recent impact memory and flags candidate modules already touched within 30 days. No coordination meeting required.
The same data structure threads through all three. by_category sized the regression bill in loop 1; the same field is preserved as memory in loop 2; the same touched-modules list keys overlap detection in loop 3.
What This Buys You
- The "small change" trap stops being free. Every hotspot touch costs an impact query. Most are still small. The ones that aren't — you find out before code is written, not at PR time.
- Test scope is sized, not guessed. The
testbucket is the regression list. No wondering if you missed something three modules over. - Config and doc drift gets surfaced. The graph's
configanddocbuckets catch the deploy chart and the runbook the file authors forgot. These are the post-merge incidents the team didn't connect to the original PR. - Tracks stop colliding silently. Two engineers refactoring adjacent code in adjacent weeks now find out at intake instead of at merge.
- Memory survives turnover. Six months later, when nobody remembers why
internal/db/hooks.goexists, the track that introduced it is onejqaway from telling you.
None of this requires the AI to be smarter. It requires the codebase to remember things.
Try It
# In a Draft-initialized repo with a built graph
graph --repo . --out draft/graph \
--query --file path/to/your/file.go \
--mode impact | jq
# Then start a track and let /draft:implement
# wire up the warning + memory loops
/draft:new-track "your next change"
/draft:implement
The graph is local, deterministic, and version-controlled — same engine the previous post walked through. Impact mode is one of six query modes; the rest are documented in core/shared/graph-query.md. No SaaS, no embeddings, no API key — just a JSON answer to the most expensive question in code review.
The graph is not a planner. It is a memory. Use it before you write code, after you ship code, and the next time someone is about to retrace your steps.