Graph Topology Snapshot
kahn beginner 4 min read
ELI5
A floor plan that travels with the work order — the shape of the assembly line on the day the order ran, photographed and filed alongside the logbook so any later reviewer sees what was actually built against, not what’s been redrawn since.
Technical Deep Dive
contracts/schemas/graph.schema.json describes the static DAG that KAHN Scope renders alongside the event log. The orchestrator snapshots it into .kahn/archive/runs/<run_id>/graph.json once at run_start, closing open question O-3 (replay renderability).
Top-Level
| Field | Type | Constraint |
|---|---|---|
version | const | exactly 1 |
nodes | array | minItems: 1 |
Node Shape
classDiagram class GraphDoc { +int version +Node[] nodes } class Node { +string id +string deliverable +string[] depends_on +string[] touches +bool parallel_safe +string[] done_when +int max_ralph_iters +int estimated_loc } GraphDoc --> Node : 1..*Field Constraints
| Field | Constraint | Note |
|---|---|---|
id | ^[a-z0-9][a-z0-9-]{0,63}$ | kebab-case, stable across runs (I-10) |
deliverable | minLength: 1 | Human-readable goal sentence |
depends_on | unique items, same id pattern | [] = root |
touches | unique strings | File globs/paths driving conflict detection |
done_when | minItems: 1 | Each item is a non-empty shell command |
max_ralph_iters | int ≥ 1, default 6 | |
estimated_loc | int ≥ 0 | Optional planning hint |
Snapshot Discipline
- Read at
run_startfrom<graph_path>.json; written verbatim to<archive>/runs/<run_id>/graph.json. - Live
graph.jsonmay change after the run; the snapshot is immutable for the run’s lifetime. - A
versionbump (anything other than1) is a breaking change — KAHN bumps the wire path prefix when this happens.
Key Terms
- deliverable → The “what should be true when this node converges” sentence rendered in the node drawer.
- touches → Conflict-detection input for the scheduler; not the same as a real filesystem write list — the node may touch fewer files in practice, but never more.
- estimated_loc → Optional planning hint, never enforced.
Q&A
Q: Can a graph have a single node?
A: Yes. nodes: minItems: 1 permits it; the cycle guard only requires at least one root, which the lone node trivially is.
Q: What if the live graph.json drifts between run_start and a later replay? A: The replay reads the archived snapshot, not the live file. Replays remain renderable.
Q: Does the schema enforce that depends_on IDs exist in nodes?
A: No — only the regex pattern. The orchestrator’s cycle guard and ready_nodes() rely on the IDs lining up; an unknown dep silently keeps a node pending forever.
Examples
A two-node DAG that pairs an isolated migration with a dependent service:
{"version":1,"nodes":[ {"id":"auth-table","deliverable":"v2 schema applied", "depends_on":[],"touches":["migrations/0012_auth.sql"], "parallel_safe":true,"done_when":["psql -c 'select 1 from auth_v2'"]}, {"id":"auth-service","deliverable":"service reads v2", "depends_on":["auth-table"],"touches":["src/auth.ts"], "parallel_safe":true,"done_when":["pnpm test src/auth.test.ts"]}]}neighbors on the map
- Dependency DAG & Blast Radius estimating the impact of changing a shared rule
- End-to-End Chain Execution Request Flow tracing a chain execution through the entire system
- LORE Causality Graph & Decision Visualization understanding how decisions relate to each other