docs(specs): make "a spec becomes an architecture doc" the written rule
The sixteen specs folded in last commit were folded because someone noticed they had gone stale, not because anything said they should be. Without the rule written down the directory drifts straight back to a mix of promises and descriptions, and neither can be trusted: you cannot tell from a file whether it describes the build or proposes a change to it. So: docs/specs/ holds only unshipped work, there is no "Implemented" resting state, and the fold-in and the deletion happen in the same commit. The template now asks for the destination architecture doc **up front**, which is a design check rather than bookkeeping — a feature that fits no existing doc usually has an unclear layer assignment, and it is cheaper to find that out at spec time. It also tells the author which half of what they are writing is durable (invariants, rejected alternatives, the defect a decision prevents) and which half dies with the file (phases, migration steps, acceptance criteria). The review checklist gains a Lifecycle section, including the case that gets lost otherwise: out-of-scope work worth doing has to be written where it will still be found after the spec is gone.
This commit is contained in:
@@ -227,6 +227,34 @@ Before accepting a spec, run it past
|
||||
a spec around "no Rust changes required" — correct layer placement is the goal,
|
||||
not minimal backend churn.
|
||||
|
||||
### 🔴 A spec becomes an architecture doc when it ships
|
||||
|
||||
`docs/specs/` holds **only work that has not shipped**. There is no "Implemented"
|
||||
resting state for a spec file: when the last acceptance criterion is met, fold
|
||||
the design into [docs/architecture/](docs/architecture/README.md) and **delete
|
||||
the spec in the same commit**.
|
||||
|
||||
This is not tidying. A directory that mixes promises with descriptions makes both
|
||||
unreliable — you cannot tell from a file whether it describes the build or
|
||||
proposes a change to it, and stale specs then quietly disagree with the code
|
||||
while reading as authority.
|
||||
|
||||
- **Every spec names its destination up front** — the template's "Destination on
|
||||
completion" line. Deciding at spec time which architecture doc will absorb it
|
||||
is a design check in itself: a feature that fits no existing doc is usually a
|
||||
feature whose layer assignment is unclear.
|
||||
- **Carry the reasoning, not the plan.** The architecture doc gets the *why* a
|
||||
future change still needs — invariants, rejected alternatives that would be
|
||||
re-attempted, the defect a piece of code exists to prevent. Acceptance
|
||||
criteria, phase breakdowns and migration steps die with the spec; git history
|
||||
keeps them.
|
||||
- **Deferred work outlives its spec.** Anything the spec listed as out-of-scope
|
||||
and still worth doing goes beside the code it concerns, not into the void.
|
||||
- **Rewrite inbound references before deleting** — source comments and CI
|
||||
scripts cite spec paths, and `check-doc-links` only sees markdown.
|
||||
- **Partially implemented is a real status.** A spec stays until *all* of it
|
||||
ships, with the header naming what is left.
|
||||
|
||||
## Conventions
|
||||
|
||||
### Rust Backend
|
||||
|
||||
Reference in New Issue
Block a user