v1.19.0 ·
The graph knows where, not why
The problem
Forty-two instances have left forty-two folders of requirements, designs and retrospectives. Not one of them answers the question a person actually asks: how does this thing work?
Three surfaces came close, and naming what each one misses turned out to be the whole scope.
There are 33 release posts. They are real prose, written when the work landed, and they are the closest thing that existed. But they are grouped by release tag and shaped as narrative — they answer "what happened in v1.8.0", not "how does cost tracking work now". The docs site documents the framework: phases, skills, templates, the CLI, the glossary. Six sections, none of them about anything built with it. And the knowledge graph, which is the surface AI agents actually read, is terse by design because it competes for prompt space with the task. It records shape. It cannot afford to record reason.
That third one is not a theoretical gap, and measuring it is what turned a documentation wish into a
defect report. The graph holds 64 module entries. Seventeen lines of them describe a package deleted
months ago at the website cutover — its directory does not exist, and aidlc knowledge context
compiles those lines into CLAUDE.md. So every agent that starts work in this repository is currently
told about code that is not there. Nothing reported it in the months since, because a stale entry and a
correct one are the same shape.
The concrete cost of missing reasons has a name here. The graph records that one function returns a
result type of ok or reason rather than null. True, and useful for finding it. What it has no room
for is why: a null could not distinguish "no transcript on disk" from "transcript found but no matching
turns", and a bugfix instance bought that distinction. An agent holding only the fact will simplify the
type back to null and reintroduce the bug — confidently, and with a smaller diff.
So the ask was not "write documentation". It was: agents already have a documentation surface, it is already wrong, and adding a second one without deciding which surface answers which question just produces two stale surfaces instead of one.
How it could be solved
Four decisions, and the cheapest answer was wrong in three of them.
One page per instance, or one per topic. The original suggestion was a document in each instance's own folder, written when the work finishes. Rejected, and the reason generalises past this repo: documentation describes the system as it is, while an instance describes one change. A bugfix instance later corrected what a feature instance built, so neither folder holds the truth alone and a reader has to stitch forty-two of them together to find it. Per-instance pages also go stale the moment the next instance touches the same code, and nobody browses that directory — each folder already holds two dozen files. Nine topic pages instead, which is also nine and not sixty-four: the module list is a code index, and seventeen of its entries point at a deleted package.
Repo root, or inside a package. Repo root. Shipping the pages inside the content package sounds like a bonus — installed users would get them — but it makes framework text forkable into every project, which is exactly what the glossary loader deliberately refuses on the grounds that a second copy is a thing that can drift. The consequence was recorded rather than waved away: agents in projects that merely installed the package cannot see these pages, and that gap is now its own backlog item with three candidate read paths priced.
A grep for the command name, or a declared mapping. The completeness check asks whether all twenty
CLI commands are documented. A text search for each name is one line shorter and passes on an incidental
mention — a page saying "unlike aidlc doctor, this…" would satisfy it while documenting nothing. So
each page declares which commands it covers, and the check compares the union against the real command
set as an exact set, in both directions. It catches the reverse too: a page still claiming a command that
has been removed.
A new gate, or a checklist line. The pages need something to keep them current, and the tempting answer is a gate. Refused. This project's own history is that features which watch the lifecycle are a tax on every future instance, and five of six bugfixes trace to them. What shipped is one step in the deployment skill and three structural guards — declared pages exist, required sections are non-empty, every path a page names resolves. Prose quietly going out of date is not caught by anything, and that is written down as an accepted risk rather than solved with a fourth check nobody asked for.
The fourth guard is the interesting one, because it nearly ate itself. A page explaining that the knowledge graph still references a deleted package has to name that package's path — so the guard forbidding unresolvable paths fails on the very page explaining unresolvable paths. This project has tripped over that six times before. The escape is an allowlist that demands a written reason, and the allowlist is itself checked: an entry that still resolves, or that no page mentions, fails as a stale exemption sitting in front of the next real failure.
How AIDLC solves it
A docs/ folder at the repo root: a landing page and nine topic pages explaining what this repo
built — why each part exists, what breaks without it, and how to use it. Written for two readers with
the same gap: a person trying to understand the system, and an AI agent about to change it.
The gap was real. Three surfaces came close and each missed. The 33 release posts under
packages/website/content/blog/ are genuine prose but grouped by release tag and written as
narrative-at-a-moment, so they answer "what happened in v1.8.0" and not "how does cost tracking work
now". The docs site documents the framework — phases, skills, templates, CLI, glossary — and nothing
built with it. And the knowledge graph, the surface agents actually read, is terse by design: it
records shape, not reason.
That last one is also the sharpest argument for these pages, because it is measurably wrong. Of its 64
module entries, 17 lines describe a package deleted at the website cutover, and aidlc knowledge context compiles them into CLAUDE.md — so every agent starting work here is currently told about
code that is not there. Structural rot is the half a test can catch, so this instance shipped that
test.
docs/index.yaml is the single declaration site. It turns four claims that would otherwise be
prose into data a test can compare: which pages exist, what code each documents, which CLI commands
each covers, and which broken-looking things are deliberate. It also states the boundary against the
knowledge graph — split by question, not audience: the graph answers where a thing is and what shape
it has, these pages answer why it exists and how to use it.
packages/cli/test/docs-topics.test.ts — 22 tests, structural only. Declared pages exist and
undeclared ones do not, in both directions. All three required section headings present and non-empty.
All 20 top-level CLI commands claimed, by exact set comparison over a declared mapping rather than a
text grep, so an incidental mention cannot pass for documentation. And every repo path a page names
resolves on disk or is allowlisted with a reason.
That allowlist is the interesting part. The page explaining the stale graph must name the deleted path to make its point, so without an escape the guard fails on its own explanation — a failure mode this project has hit six times. The escape is an allowlist requiring a written reason, and the allowlist is itself checked: an entry that still resolves, or that no page mentions, fails as a stale exemption.
packages/content/skills/60-deployment.md gains one checklist step — update the affected topic
page when a change alters how a documented topic behaves. Deliberately not a gate. Every gate is a tax
on all future work, and five of this project's six bugfixes trace to features that watch the lifecycle.
Nothing was added to packages/cli/src/, and no package's files array changed, so the published CLI
surface and package contents are unchanged. The only shipped-artifact change is the deployment skill
text.