The doc set

Three documents, each with its own reader and its own pace. The value comes from four properties rather than from the file count, so if you'd rather keep one file, the properties are the part to copy.

The documents

DocumentAnswersReaderPace
ONTOLOGY.md What exists, what each thing carries, how things relate, the rules, the interface Implementer The working spec, read constantly
CRITERIA.md How you know it's correct, readable and good Tester, tuner Written with the rules; each row owns its tests
ARCHITECTURE_LOG.md What changed, when, why, what it replaced, and the alternatives you turned down Next maintainer A dated entry in the same change

Purpose goes at the top of ONTOLOGY as §0, so the tiebreaker sits on the document people actually open rather than in a file of its own.

One rule holds across both of the first two: describe the current state only. No "formerly", no "originally named", no before-and-after tuning notes. All of that lives in the log, along with the reasoning for each change and the alternatives you turned down. Otherwise a reader has to subtract the history to find out what the system does.

The four properties

Tagged provenance

You can tell your decisions from the model's guesses. [D] means you decided it, and only you can mark something that way. [P] means the model proposed it and it's awaiting review. [T] means a number that's expected to move once something measures it.

Decisions with alternatives

Each log entry records what else you considered and why this won. Writing the alternatives down turns out to find more bugs than reviewing the decision does. A number that came from a model rather than a measurement says so.

Criteria as tables

Rules arrive with their test cases as Given → Expect → Instrument rows, which makes writing the tests closer to transcription. If a criterion has no instrument yet, it's marked not yet covered rather than left looking covered.

Stable IDs

Goals are G-n, decisions D-n, open questions Q-n, criteria R-n. Code, tests, commits and docs all cite them, and they're never reused or renumbered. A retired criterion leaves a tombstone row behind so its number can't come back meaning something else.

Two mechanisms worth the trouble

Serves tags

Every entity and rule carries a Serves: line naming what it's there for: a goal from §0, a named quality, a driver. You can read it in both directions. Something that serves nothing is a candidate for removal, and a goal that nothing serves probably isn't being met.

The second reading is a question code can't answer at all. The first is why dead code survives in most projects: with no stated purpose, you can't show that a thing is no longer needed, so nobody takes it out.

A criteria row owns a test directory

An automated rule row owns test/R-n/, and the directory is the only link between them. Test files aren't listed in the criteria table, because two lists drift apart. Each test asserts one rule, so a failure points at one place.

A small coverage test then runs with the suite. It fails when an automated row has no tests, when a test/R-n/ directory exists for a row that isn't automated, or when an instrument cell isn't one of the four allowed forms.

That coverage test is 41 lines with no dependencies, and it's the piece I'd keep if I could only keep one.

When to skip it

Five entities and two rules don't need three files. For small CRUD work, write one SPEC.md and borrow the four properties above as sections — they compress into one file without losing much. The full set starts paying when the thing will be tuned, when the numbers are uncertain, when more than one person or session touches it, or when it'll outlive your memory of writing it.

That's the shape of it. The prompts cover how the cycle runs in practice: what order to write things in, and what to ask for at each step.