Four linked columns — spec clause → plan step → task → diff hunk — over a worked “checkout redesign” example. Click any node and its full ancestor and descendant chain lights up across all four columns; everything else dims.
The two failure colors are the point: red marks code with no spec ancestor (scope creep — nobody asked for it), and dashed grey marks a spec clause with no code descendant (a promise nothing was built for). Both fall out of plain graph reachability, nothing more — “did we build what we said we would” turned into a layout problem over a small DAG.
Reuse
src/spec-ladder.js is domain-agnostic: buildGraph(nodes, edges) takes
{ id, col } nodes and { from, to } edges (edges only ever link adjacent
columns), and exposes ancestors, descendants, and classify — all three
are just BFS/DFS over the forward/backward adjacency built once. Swap in a
real dataset (spec clauses, plan steps, tasks, diff hunks scraped from an
actual repo) and the traversal and classification carry over unchanged.
Gotchas
classifyonly asks “is there a path,” not “is this the right path” — a diff hunk that coincidentally traces back to some spec clause still reads as normal even if it doesn’t actually satisfy it. It’s a reachability check, not a correctness check.- The demo bundles its own copy of
spec-ladder.js(self-contained by contract); re-copy after editingsrc/. - The four-column dataset here is a fixed illustrative example, not generated — the interesting part to reuse is the traversal, not this particular checkout story.