diff --git a/docs/rules/DEV-180.md b/docs/rules/DEV-180.md index e6b0fc0..d4bc528 100644 --- a/docs/rules/DEV-180.md +++ b/docs/rules/DEV-180.md @@ -9,29 +9,40 @@ depends_on: ["DEV-110", "DEV-170"] ## Problem -When a Spec describes behavior that already shipped, or `docs/product/` -describes behavior that was never built, a reader cannot tell what the product -actually does today. The backlog and the documentation rot into fiction. +A spec that stays behind after its behavior ships is indistinguishable from one +that is still a plan. Readers take shipped work for unbuilt, and the stale text +collides with the next spec written for the same feature. ## Solution -Split intended behavior from shipped behavior, and move sections across as work -lands. +Keep one source of truth for what the product does, and a separate one for what +stakeholders still want. The product is the app together with its end-user docs. +The spec is the plan, and holds only what is not built yet. -1. `docs/specs/.md` holds only unimplemented behavior for a Goal. - `docs/product/.md` holds only what currently ships. -1. Each PR that delivers behavior moves the corresponding sections out of the - spec and into the appropriate file under `docs/product/`. A spec may graduate - into more than one `docs/product/` file. -1. When scope is added after the Spec merges, open a new PR against the spec +A spec states what the business needs before anyone builds it. The product docs +are part of the product, not a description of it: they carry what a user cannot +work out from the screen alone. Once behavior ships it stops being a proposal +and becomes a fact in the source code, so it leaves the spec. What a user still +needs in order to use it moves to the product docs. What the UI already makes +obvious goes nowhere, because a field visible on the screen documents itself. + +1. `docs/specs/.md` holds only unimplemented behavior for a Goal. The + product docs hold only what ships today: `docs/product/.md` by + default, or the path the repo's docs README declares where it differs. +1. Each PR that delivers behavior moves the delivered sections out of the spec. + Graduate what a user cannot infer from the UI, drop the rest. A spec may + graduate into more than one file. +1. When scope is added after the spec merges, open a new PR against the spec file and create Problem issues for the added scope. -1. When every section has graduated, keep the spec file as frontmatter only. - Never delete it, so the Goal's `# Spec` link keeps working. +1. When every section has graduated or been dropped, keep the spec file as + frontmatter only. Never delete it, so the Goal's `# Spec` link keeps working. +1. Do not close a Goal while its spec still holds behavior that shipped. ### Acceptance Criteria - [ ] `docs/specs/` holds only unimplemented behavior -- [ ] `docs/product/` holds only shipped behavior -- [ ] Each shipping PR graduates the delivered sections from spec to - `docs/product/` +- [ ] The product docs hold only shipped behavior, and only what the UI does not + make obvious +- [ ] Each shipping PR graduates or drops the delivered sections - [ ] A fully graduated spec file is kept as frontmatter only, not deleted +- [ ] No Goal is closed while its spec still describes shipped behavior