Scaffold docs for a new project
“Read the repo and write the docs” produces prose nobody can falsify. Six months later no one can tell which sentences are still true. So /dev-docs-init writes no prose: you record claims, each carrying the evidence that would show it false, and a renderer turns them into documents.
The set
Section titled “The set”The same eight documents in every project, defined once and configured with docs.set, which may only subset them.
| key | file | holds |
|---|---|---|
context |
docs/context.md |
why this exists, who it is for, what it deliberately does not do |
architecture |
docs/architecture.md |
components, boundaries, data flow |
domain |
docs/domain.md |
the glossary: terms, and what they mean here |
api |
docs/api.md |
the external contract: what callers may depend on |
ux |
docs/ux.md |
flows, screens, states, and their rules |
operations |
docs/operations.md |
run it, deploy it, what breaks |
testing |
docs/testing.md |
what is tested, how to run it, what deliberately is not |
security |
docs/security-model.md |
trust boundaries, secrets, what is assumed |
decisions is in the set as a pointer to docs.decisionsDir. Records are /dev-adr’s job.
There is no conventions.md. A deterministic guideline belongs in the linter, and a non-deterministic one is unfalsifiable. See Turn conventions into lint rules.
The flow
Section titled “The flow”/dev-docs-init- Stage.
docs initrefuses on a brownfield project and refuses with nostageset.dev.mjs assessproposes,/dev-initrecords. - Scaffold.
docs init [--only KEY,...]writes the missing documents as stubs and registers each in the ledger with its hash. Idempotent. - Record. Claims go in as JSON, each naming its
targetdocument.
{ "claims": [ { "text": "The HTTP entry point is src/server.ts", "kind": "observable", "anchor": "src/server.ts:12", "target": "architecture", "topic": "shape" }, { "text": "Sessions are in memory because the service is single-instance for now", "kind": "intent", "source": "ayoub", "target": "architecture", "topic": "storage" } ]}node _dev-workflow/scripts/dev.mjs docs record @claims.jsonnode _dev-workflow/scripts/dev.mjs docs render architecture- Check.
docs checkexits 1 for a document that is missing, still a stub, or no longer matches the ledger. Run it in CI once the documents are real.
$ node _dev-workflow/scripts/dev.mjs docsDOCUMENT CLAIMS STATE PATH------------------------------------------------------------------------context 0 missing docs/context.mdarchitecture 0 missing docs/architecture.md…decisions - pointer docs/decisions → dev.mjs adr new "<title>"On a young project, most claims are intent
Section titled “On a young project, most claims are intent”A two-week-old codebase yields a handful of anchored observable claims and a lot of attributed intent ones. That is the correct output. Six months later a reader can tell which sentences were ever checkable and which were one person’s belief on a Tuesday.
Hand edits survive
Section titled “Hand edits survive”A generated document is registered with its hash. Edit one by hand and docs render refuses to overwrite it, docs check names it as hand-edited, and the next ingest scan puts it back in the extraction queue so the edit is absorbed as claims. The edit is never lost.