From 96abc3afef45943f3e1334e35179d0d7627e086d Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Fri, 21 Aug 2026 18:29:09 +0200 Subject: [PATCH] docs(specs): make "a spec becomes an architecture doc" the written rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- CLAUDE.md | 28 ++++++++++++++++++++++++++++ docs/specs/SPEC-REVIEW-CHECKLIST.md | 12 ++++++++++++ docs/specs/SPEC-TEMPLATE.md | 17 ++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index be343f61..1312d5ed 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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 diff --git a/docs/specs/SPEC-REVIEW-CHECKLIST.md b/docs/specs/SPEC-REVIEW-CHECKLIST.md index f6114b35..9f287814 100644 --- a/docs/specs/SPEC-REVIEW-CHECKLIST.md +++ b/docs/specs/SPEC-REVIEW-CHECKLIST.md @@ -53,6 +53,18 @@ Copy the boxes into the review comment (or the PR) and tick them. - [ ] Traceability coverage stays ≥ 88% (the CI gate — a ratchet, so check `bun run traces:coverage` rather than trusting this number). +## Lifecycle + +- [ ] **"Destination on completion" names a real architecture doc and section.** + This spec file is deleted when it ships; something has to absorb the + design. If nothing fits, the layer assignment is probably unclear — go back + to that table. +- [ ] The spec separates the **durable half** (invariants, rejected alternatives, + the defect a decision exists to prevent) from the **disposable half** + (phases, migration steps, acceptance criteria). Only the first is folded in. +- [ ] Anything listed as out of scope but still worth doing is written where it + will be found after this file is gone — beside the code it concerns. + ## Conflicts & hygiene - [ ] If this spec revises/supersedes another, the older spec gets a banner diff --git a/docs/specs/SPEC-TEMPLATE.md b/docs/specs/SPEC-TEMPLATE.md index e27df44b..61e28a5e 100644 --- a/docs/specs/SPEC-TEMPLATE.md +++ b/docs/specs/SPEC-TEMPLATE.md @@ -6,12 +6,27 @@ "Layer assignment" — read its comment before writing it. Before merging a spec, run it past docs/specs/SPEC-REVIEW-CHECKLIST.md. + + LIFECYCLE: this file is temporary. docs/specs/ holds only unshipped work — when + the last acceptance criterion is met, the design is folded into + docs/architecture/ and this file is deleted in the same commit. Write it + knowing that: the durable half is the reasoning (invariants, rejected + alternatives, the defect a decision prevents), and the disposable half is the + plan (phases, migration steps, acceptance criteria). --> -**Status:** Proposed +**Status:** Proposed **Requirements:** **UX spec:** **Supersedes / revises:** +**Destination on completion:** ## Summary