wdi-method 0.6.30 → 0.6.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/NOTICE +7 -2
  3. package/README.md +16 -11
  4. package/bin/wdi-method.js +396 -87
  5. package/kit/.constitution/method/document/architecture-guide.md +217 -209
  6. package/kit/.constitution/method/document/bmad-skill-register.md +107 -104
  7. package/kit/.constitution/method/document/corpus-guide.md +522 -517
  8. package/kit/.constitution/method/document/decision-guide.md +236 -216
  9. package/kit/.constitution/method/document/delivery-flow-guide.md +20 -0
  10. package/kit/.constitution/method/document/prd-guide.md +245 -245
  11. package/kit/.constitution/method/document/templates/design-system.md +96 -66
  12. package/kit/.constitution/method/document/templates/experience.md +62 -0
  13. package/kit/.constitution/method/document/templates/structure-codebase.md +131 -129
  14. package/kit/.constitution/method/document/templates/ux.md +78 -76
  15. package/kit/.constitution/method/document/ux-guide.md +161 -115
  16. package/kit/.constitution/method/method-glossary.md +3 -0
  17. package/kit/.constitution/method/scripts/validate.py +3375 -3200
  18. package/kit/.constitution/method/structure-guide.md +204 -202
  19. package/kit/.constitution/method/why/README.md +1 -1
  20. package/kit/.constitution/method/why/artifact-map.md +158 -157
  21. package/kit/.constitution/method/why/portability.md +19 -2
  22. package/kit/skills/wdi-autopilot/SKILL.md +32 -19
  23. package/kit/skills/wdi-blueprint/SKILL.md +271 -264
  24. package/kit/skills/wdi-build/SKILL.md +28 -19
  25. package/kit/skills/wdi-component/SKILL.md +179 -174
  26. package/kit/skills/wdi-daily-autopilot/SKILL.md +24 -13
  27. package/kit/skills/wdi-daily-what-to-build/SKILL.md +9 -6
  28. package/kit/skills/wdi-daily-what-to-test/SKILL.md +2 -0
  29. package/kit/skills/wdi-decision/SKILL.md +206 -203
  30. package/kit/skills/wdi-explain-to-me/SKILL.md +2 -0
  31. package/kit/skills/wdi-help/SKILL.md +130 -125
  32. package/kit/skills/wdi-init/SKILL.md +10 -5
  33. package/kit/skills/wdi-problem/SKILL.md +114 -108
  34. package/kit/skills/wdi-product/SKILL.md +167 -162
  35. package/kit/skills/wdi-prune-or-archive/SKILL.md +2 -0
  36. package/kit/skills/wdi-reconcile/SKILL.md +170 -169
  37. package/kit/skills/wdi-upgrade/SKILL.md +234 -215
  38. package/kit/skills/wdi-ux/SKILL.md +187 -169
  39. package/kit-overlay/AGENTS.md +15 -2
  40. package/kit-overlay/portability.md +19 -2
  41. package/lib/platforms.mjs +420 -248
  42. package/package.json +1 -1
  43. package/scaffold/.control/registry/index.yaml +2 -1
@@ -1,517 +1,522 @@
1
- ---
2
- status: Accepted
3
- ---
4
-
5
- # Corpus Guide
6
-
7
- **Loaded when:** deciding where a file lives, or creating a new file in the corpus
8
-
9
- Four layers and one workspace. Every other guide describes one document; this one answers the question that
10
- comes before all of them — **where does this belong?**
11
-
12
- The quick answer for the thing actually in your hand is the "benda di tangan → folder" table in `AGENTS.md`.
13
- It is deliberately there rather than here: it is needed at the moment someone would otherwise have to reason
14
- about what `.what/` and `.how/` mean, and that moment comes before anyone thinks to open a guide. It MUST NOT
15
- be copied into this file.
16
-
17
- ## The four layers
18
-
19
- | Layer | Answers | Lifetime | Written by |
20
- |---|---|---|---|
21
- | `.constitution/` | How we work | Living, rarely changes | Us |
22
- | `.control/` | What currently holds, and what has been decided | Living, changes often | Us + generators |
23
- | `.what/` | What is promised | Living, amended | BMad class A + us |
24
- | `.how/` | How it is built | Living, amended | BMad class A + us |
25
- | `_bmad-output/` | Work in progress | Ends when the work does | BMad class B and C |
26
- | `.what-rendered/` · `.how-rendered/` | The same promise and shape, **assembled for a human to read** | Regenerated on every `render`; never edited | `validate.py --generate`, and nobody else |
27
-
28
- `.control/` is the value of `{project_knowledge}` in BMad's configuration. There is no `docs/`.
29
-
30
- ### Two audiences, two trees
31
-
32
- `.what/` and `.how/` are the **working** trees: prose that cannot be a row, pointers to the registry for
33
- everything that can. They are what an agent reads and what a skill writes. They are deliberately thin
34
- for a human — `Goals` is one line, an `FR` is an id — because completeness is not their job.
35
-
36
- `.what-rendered/` and `.how-rendered/` are the **reader's** trees. Every file in them sits at the mirror
37
- path of the working document it projects — `.what-rendered/<pc>/SRS-<pc>.md` is
38
- `.what/<pc>/SRS-<pc>.md` with every pointer opened: the goal statements, the UC rows, the
39
- `AD-N` text, the open questions, all pulled in from their own homes. That is what a gate reads, and
40
- what a client receives.
41
-
42
- Three rules keep the two trees honest:
43
-
44
- - **A skill MUST NOT read a `-rendered` file as input.** It is output. The working document and the
45
- registry are the source, and a skill that read the projection would be reading its own echo — a
46
- `kit-integrity` test fails when any `SKILL.md` lists one in its `Inputs`.
47
- - **Nobody edits a `-rendered` file.** A defect seen there is a defect in the working document or the
48
- registry, and that is where it is fixed. The next `render` overwrites the page.
49
- - **Every gate reads one rendered page, and that page MUST answer the gate's seven questions.** G1
50
- reads `.what-rendered/_product-brief/brief.md`; G2 `.what-rendered/_prd/<slug>/prd.md`; G3
51
- `.how-rendered/blueprint.md`; G4 `.how-rendered/<pc>/SDD-<pc>.md`. A question that cannot be
52
- answered from the page is a gap in the page, not a reason to open a working file.
53
-
54
- ## The placement test
55
-
56
- One question decides everything: **is this file still correct after its spec has passed?**
57
-
58
- Yes → the corpus. No → `_bmad-output/`.
59
-
60
- `_bmad-output/` is committed but **not curated**. Committing it is what makes citation by path stable, so a
61
- decision or a PRD MAY point into it. Research, brainstorming, forge, and PRFAQ reports are never promoted.
62
-
63
- A run folder MUST NOT be deleted **while anything still needs it** — the `update` intents re-read the original
64
- inputs in place. "Never deleted" is not the rule; the rule is a **retirement condition**, and it is below.
65
-
66
- **What git ignores is not corpus.** A vendored upstream checkout kept for reading, a scratch download, a
67
- build cache — if the product excludes it from git it is in no clone, nobody curates it, and the validators
68
- do not read it. The other half of that rule is `corpus-in-git`: a folder the method itself keeps MUST NOT be
69
- excluded, and the two lock together — material is either in git and checked, or ignored and not corpus. What
70
- `.gitignore` MUST NOT be used for is quieting a finding about a file that really is this product's.
71
-
72
- ### A withdrawn promise STAYS in the registry
73
-
74
- A `BG` · `CAP` · `FR` · `NFR` · `UC` the product stops promising is marked, never deleted:
75
-
76
- ```yaml
77
- - id: CAP-8
78
- title: "Publish an order as a public page"
79
- status: withdrawn
80
- withdrawn_by: DEC-026
81
- ```
82
-
83
- **Why the row stays.** One repo deleted two withdrawn capabilities and paid for it in twelve
84
- `refs-resolve` findings: eight `DEC-` rows still named them in `serves:`, and six of those eight
85
- genuinely served them at the time. The other repair — editing those decisions — is refused by the
86
- section above: a `DEC-` is a record of what happened, and a retired name inside one is a fact about
87
- the past.
88
-
89
- **So a withdrawn row is read two ways, and both matter.** It is still **defined**: every old
90
- reference resolves, and `id-allocated-once` still refuses the number to anything else — an id is
91
- allocated once, withdrawal included. It is no longer **promised**: no `UC` is owed, no ticket, no RTM
92
- row, and `promise_progress` is not dragged down by something nobody promises any more.
93
-
94
- **Two rules keep it honest**, and `withdrawn-recorded` is what enforces both:
95
-
96
- - `withdrawn_by` MUST name a `DEC-` that exists. Retiring an id is decision-worthy on this method's
97
- own terms — the **ID chain** row under § *Landing that MUST be confirmed first* says so outright —
98
- and without the pointer `withdrawn` is only a word that quiets a validator.
99
- - A live row MUST NOT hang off a withdrawn one. An `FR` under a withdrawn `CAP` still promises
100
- something whose capability nobody promises: withdraw it too, or move it under something live.
101
- Withdrawal that takes half a chain with it silently is worse than the deletion it replaced, because
102
- deletion at least went red.
103
-
104
- `wdi-product` owns the edit, because it owns the row. The withdrawal itself goes through
105
- `wdi-decision` first — the `DEC-` is what `withdrawn_by` points at.
106
-
107
- ## Who lands what
108
-
109
- There is no separate placement skill. A skill lands the output of the layer **it owns**, and the landing is
110
- part of producing it — never a follow-up someone else performs.
111
-
112
- | Output | Permanent home | Owner |
113
- |---|---|---|
114
- | The spine | `.how/_platform/ARCHITECTURE-SPINE.md` | `wdi-blueprint` |
115
- | C4 L1 · L2 · one L3 per container holding more than one PC | `.how/_platform/c4-l1-system-context.md` · `c4-l2-containers.md` · `c4-l3-<container>.md` | `wdi-blueprint` |
116
- | each container in C4 L2 | a `container` entry in `components.yaml` | `wdi-blueprint` |
117
- | **The three inventories** | `.how/_platform/inventory-db.md` · `inventory-api.md` · `inventory-screen.md` | `wdi-blueprint` |
118
- | The error envelope, and anything else defined once for the product | `.how/_platform/cross-cutting.md` | `wdi-blueprint` |
119
- | UC catalogue · Actor Register · domain model | `.what/<pc>/SRS-<pc>.md` · `03-domain/domain-model.md` | `wdi-blueprint` |
120
- | Business rules binding more than one PC | `.what/business-rules.md` | `wdi-blueprint` |
121
- | A domain term | `.control/product-glossary.md` | `wdi-blueprint` |
122
- | Full UC flows · local rules · state machines · scenarios | `.what/<pc>/` slots `02`–`05` | `wdi-component` intent `behaviour` |
123
- | The SDD and its slots `02`–`06` | `.how/<pc>/` | `wdi-component` intent `design` |
124
- | each Boundary and Control object drawn | an `LC` in `components.yaml` | `wdi-component` intent `design` |
125
- | `EXPERIENCE.md` | `.what/<pc>/04-usecases/` | `wdi-ux` |
126
- | `DESIGN.md` | `.how/<pc>/01-ux/` | `wdi-ux` |
127
- | tokens and base components | `.how/_platform/design-system.md` | `wdi-ux` |
128
- | each screen in `DESIGN.md` | an `LC` of type `ui-screen` in `components.yaml` | `wdi-ux` |
129
- | The names of the tests a ticket went green on | the ticket's `tests` in `specs.yaml` | `wdi-build` |
130
- | What the spec settled about the stack, the conventions, or the brownfield reality | merged into `.constitution/project/codebase-*-guide.md` | `wdi-build`, at spec close |
131
- | A sprint change proposal | a `DEC-` of `type: course-correction` | `wdi-decision` |
132
- | The registry rows and skeletons a new PC needs | `components.yaml` · `.what/<pc>/` · `.how/<pc>/` | `wdi-init` intent `component` |
133
- | `platform_owns` — an entity no component's promise explains | `components.yaml`, plus its description in `cross-cutting.md` | `wdi-blueprint` |
134
- | The two structure maps | `.control/structure-codebase.md` · `structure-document.md` | `wdi-init` intent `structure` |
135
- | An open question | `.control/questions/` — one of four files | `wdi-question` |
136
- | A decision | `.control/decisions/DEC-NNN-<slug>.md` | `wdi-decision` |
137
- | Minutes · a non-technical fact | `.control/meetings/` · `.control/project-non-technical-log.md` | `wdi-log` |
138
-
139
- - A skill MUST NOT write into a layer it does not own.
140
- - Registry conversion is part of landing, not a follow-up. A screen that lands in `01-ux/` without its
141
- `components.yaml` entry has been half-landed, and `lc-registered` catches it **at spec close** — which is the
142
- right moment to be caught, and a bad moment to be surprised.
143
- - Content MUST NOT be edited while it is being landed. If it has to change to fit its new home, that is a
144
- separate act — say so and stop. Splitting one output across the homes its row names is not editing.
145
- - The C4 set's target files already exist and are **living**. Their owner MUST amend, MUST NOT overwrite; when
146
- the incoming set contradicts an annotation already there, it MUST stop and report the finding.
147
- - Nothing MAY be landed into a spec that is already closed. The spec is reopened through `wdi-build`, or the
148
- gap is recorded as an open question.
149
- - An output with **no row** in this table MUST NOT be given a guessed home. It stays in `_bmad-output/`, and
150
- `wdi-reconcile` reports it — an output with no home is a gap in the method, and MUST surface as one.
151
-
152
- ## Landing that MUST be confirmed first
153
-
154
- Most landings are mechanical and MAY be done without asking. Some change what other people already agreed to,
155
- and those MUST be put to the owner before the file is written — not reported afterwards. The line is drawn by
156
- **what the landing can invalidate**, never by how much text moves:
157
-
158
- | | Light — act, then report | Heavy — confirm, then act |
159
- |---|---|---|
160
- | Layer | Stays inside the layer the skill owns | Crosses into another layer's consequences |
161
- | ID chain | No `BG`/`CAP`/`FR`/`NFR`/`UC`/`LC` id is born, renamed, or retired | Any of them is |
162
- | Depth and risk | `mode` and `risk_accepted` unchanged | Either would have to change |
163
- | Existing text | Adds, or replaces content the same skill wrote | Overwrites or contradicts what another skill or a human wrote |
164
- | Registry | Adds the entry its own output requires | Removes or re-points an entry something else already cites |
165
-
166
- Any one heavy row makes the whole landing heavy. When confirmation cannot be obtained now, the landing MUST
167
- NOT be split into a light half that goes ahead — half-landed output looks distributed and is worse than output
168
- that waited.
169
-
170
- A skill MUST NOT lighten a landing by narrowing what it writes. Dropping the contentious half to stay under
171
- the bar is the same change, made invisible.
172
-
173
- ## Product Component — the naming and proposal rule
174
-
175
- This rule lives here, beside the definition, and **not inside a skill**. If it lived in one skill, the second
176
- skill that needed it would copy it, and the two copies would drift.
177
-
178
- > The name of a Product Component MUST be a surface a user could name. A name that states a layer, a service,
179
- > or a pattern MUST be rejected at proposal time, not corrected later. Additions, changes, and removals MUST
180
- > be presented separately, each with the `FR` behind it.
181
-
182
- A PC MUST NOT be created because a folder would look tidy. A PC that no `FR` points at is a folder with
183
- nothing inside it.
184
-
185
- Birthing is cheap and retiring is not: retiring or renaming a PC that already carries an SRS goes through
186
- `wdi-decision`, never through the skill that births one.
187
-
188
- ## Product Component, Logical Component, container, `_platform`
189
-
190
- Four words that are easy to blur and MUST NOT be:
191
-
192
- | Term | Is | Registered in |
193
- |---|---|---|
194
- | **Product Component** | A surface a user can name — what they came to do | `product_components` |
195
- | **Logical Component** | A unit inside the build — a screen, a service, an adapter, an entity | `logical_components` |
196
- | **Container** | Something that runs or ships on its own | `containers` |
197
- | **`_platform`** | **Not a component at all** — the home for what belongs to no Product Component | `platform_owns`, and the `_platform/` folder |
198
-
199
- PC and container are **crossing axes**, not a hierarchy: one PC MAY be delivered by several containers, and one
200
- container MAY serve several PCs. An `LC` names its container in a `container:` field, which is what lets
201
- `structure-codebase.md` be checked against the registry rather than trusted.
202
-
203
- ## `_platform` — what belongs to no Product Component
204
-
205
- `_platform` is **not a Product Component**, and it MUST NOT be registered as one. It fails the naming test on
206
- purpose: nobody came to the product to use "the platform". It therefore carries **no `mode`, no
207
- `risk_accepted`, no SRS, no SDD, and no G4** — its documents are the spine, the C4 set, `cross-cutting.md`,
208
- and the three inventories, and all of those exist at every `mode`.
209
-
210
- What it does carry is **ownership**. `_platform` is a legitimate value in **every** position that asks
211
- *"which component owns this"* — the `platform_owns:` list for domain entities, the owning-component column
212
- of any inventory row, an `LC`'s `component:` field, and any such column a later artifact adds. One test,
213
- one cost, everywhere; there is no per-artifact special case to negotiate, and a new kind of thing arriving
214
- next year needs no new discussion.
215
-
216
- The test, and both halves MUST hold:
217
-
218
- > Something belongs to `_platform` when **no single Product Component's promise is the reason it exists**,
219
- > *and* more than one component reads, writes, or depends on it.
220
-
221
- Four kinds qualify today and the list is open: **data** (a product-wide setting, the trace of a shared
222
- outbound channel) · **endpoint** (`/health`, `robots.txt` — plumbing no `FR` promises and none should) ·
223
- **job** (a scheduled cleaner whose data belongs to a component but whose machinery does not) · **screen**
224
- (none yet).
225
-
226
- Failing either half, it belongs to a Product Component — and the component is found by asking which `FR`
227
- would have to be withdrawn for the entity to stop being needed. Two examples of the trap:
228
-
229
- | Entity | Looks platform-shaped | Actually |
230
- |---|---|---|
231
- | `activity_events` | product-wide telemetry, several components write it | **one component** — an `FR` promises somebody can SEE those counts, and withdrawing it is what would make the table unnecessary |
232
- | `email_logs` | one component sends first | **`_platform`** — it is the trace of one outbound channel that order notifications and password recovery both use, and neither promise is why the channel exists |
233
-
234
- **One guard, and it is what stops this becoming a drawer:** everything `_platform` owns — in any position —
235
- MUST be described under `## Platform-owned` in `cross-cutting.md`, with its kind and the shape every toucher
236
- obeys. A platform that owns something documents it. `entity-one-writer` checks it, and skips only while that section has not
237
- been born at G3.
238
-
239
- That guard is the whole reason `_platform` can be a general answer rather than an escape hatch: reaching for
240
- it costs a row somebody has to write, so it stays cheaper to find the real owner when one exists.
241
-
242
- `_platform` has no `FR`, so an `FR` that writes something platform-owned has nothing to point `defers_to` at,
243
- and MUST NOT be asked for one. What replaces "one writer" there is **one documented shape**: it is written the
244
- way `cross-cutting.md` says, and a component wanting it written differently is proposing a change to that file.
245
-
246
- Platform ownership sits with `wdi-blueprint` intent `platform`, beside the rest of `_platform/`. `wdi-init`
247
- intent `component` MAY name a candidate and MUST NOT claim one.
248
-
249
- **A decision the pattern cannot derive lives in the artifact it governs.** An inventory row owned by
250
- `_platform`, and a route that is a *state* of another screen rather than a screen of its own, are both
251
- judgements — so both are declared in that inventory's own frontmatter (`platform_rows:` and `states:`) and
252
- survive every re-derivation. Putting either outside the file means the next derivation silently deletes the
253
- owner's decision.
254
-
255
- ## A derived fact has exactly one home
256
-
257
- `why/rationale.md` has always carried this as principle 5 — *what can be derived is not written by hand.*
258
- It was never written as a rule anywhere, and that file binds nothing by its own terms. So it bound nothing,
259
- and only one field was ever actually protected: ticket status, by `ticket-status-one-home`.
260
-
261
- **A document MUST NOT state a fact that a registry, a generated file, or git already holds.** It cites the
262
- id and lets the reader follow it. The list is short and it is closed:
263
-
264
- | Never stated in prose | Where it lives |
265
- |---|---|
266
- | `mode` · `risk_accepted` · `g4_passed` | `components.yaml` |
267
- | Which `DEC-` bind this document — **including "none yet"** | `.control/generated/decisions.md` |
268
- | A count of `UC`, `FR`, `CAP`, or containers | the registry that holds them |
269
- | Which slots or files exist, and which are still empty | `.control/structure-document.md`, derived |
270
- | Whether an `OQ-` is open or answered | `.control/questions/` |
271
- | When the document last changed | git |
272
-
273
- **The remedy is DELETION, never correction.** This is the part that costs a corpus real time to learn: a
274
- restated fact that is corrected becomes a *second* stale fact, on a slower clock than the first. One SRS in a
275
- real repo carried three claims about its own `mode` on one page — the value, a correction block below it
276
- fixing an older value, and the slot list — and not one of the three was right. Correcting any of them would
277
- have added a fourth. Deleting all three ends it.
278
-
279
- A negative claim is the worst case and the easiest to miss, because it looks like diligence: *"No applied
280
- `DEC-` binds this component yet"* is true the day it is written and silently false forever after.
281
-
282
- **What is NOT a derived fact**, and MUST still be written where it belongs: a judgement the pattern cannot
283
- recompute (the paragraph above owns that), an `AD-N` citation — the spine's `binds:` is authored, not
284
- derived — and the *reason* something is the way it is, which no registry holds.
285
-
286
- ## A pass writes one artifact
287
-
288
- When a skill is writing or updating an artifact, **that artifact is the pass.** Hunting the rest of the
289
- corpus for things that disagree with it is not part of writing it, and MUST NOT be folded in: it is
290
- `wdi-reconcile`'s job, it runs at a gate, and `wdi-review` § Stale is not a finding decides what is even
291
- worth reporting when it does.
292
-
293
- Where a contradiction surfaces anyway — and it will, because writing a document is how you notice — there
294
- are exactly two outcomes:
295
-
296
- | The other document is | Do |
297
- |---|---|
298
- | **Load-bearing wrong** — a reader would make the wrong repair | Say it in **one line** in the output, naming the file and the edit it needs |
299
- | Anything else | Nothing. Not a line, not an `OQ-`, not a `DEC-` |
300
-
301
- It MUST NOT become an open question, and it MUST NOT become a decision. A contradiction between two
302
- documents is an **edit** waiting for whoever owns the file — never a thing to be adjudicated.
303
-
304
- **This binds hardest at G1 and G2.** A brief is being formed; a PRD is being written. There is barely a
305
- corpus to be consistent with yet, and a pass that spends its budget looking for one is spending it on
306
- nothing.
307
-
308
- ## One decided change is one edit pass
309
-
310
- Once the owner has decided, the chain is **applied**, not surveyed. The agent already knows what the
311
- change reaches — `touches:` names it, the ownership table in this file names who lands each part, and the
312
- RTM names the rows that move. It edits all of them in **one pass** and reports once.
313
-
314
- What MUST NOT happen: checking one document, reporting, waiting, checking the next; re-deriving the same
315
- relations in a later pass; or asking the owner to confirm the same decision at each file it touches. The
316
- documents are split for reading, not to be walked one at a time — and walking them is where the time and
317
- the tokens actually go.
318
-
319
- ## The corpus is written in the present tense
320
-
321
- A design document states **what is true now**: the latest state of the design, and what still has to be
322
- reached. It does not state how it got there. This governs `.what/<pc>/`, `.how/`, and
323
- `.constitution/project/`.
324
-
325
- ### Two kinds of history, and only one is worth writing
326
-
327
- Most history is not useful. What is useful is the current state — and the rare piece of history that
328
- **stops the same mistake happening twice**. One question separates them:
329
-
330
- > **Would someone about to make a change be saved by this line?**
331
-
332
- | Kind | Example | Where it goes |
333
- |---|---|---|
334
- | **Business or technical** — the mistake could recur | *"Files are removed before the record, and that left a document pointing at a deleted image"* | A `DEC-`, `why/`, or `answered.md`. Rarely, and only when it earns it |
335
- | **Document history** — a document said something else last week | *"This section was rewritten"* · *"withdrawn because a later pass found it wrong"* · *"this used to read X"* | **Nowhere.** git holds it, and git holds it better |
336
-
337
- The second kind is what fills a corpus and buys nothing. It arrives as a correction block, a
338
- `## Provenance` note, a document's own change log, a note about a conflict that has already been
339
- **resolved**, or a *"considered and rejected"* aside about the method itself. All of it MUST NOT be
340
- written in the three layers above.
341
-
342
- **And no step demands the first kind either.** History is never a checklist item, never a gate condition,
343
- and never a blocking finding. It is written when someone judges it worth writing, and skipping it is
344
- **not** a gap — nothing in this method MAY report a missing history line as a defect. That is the whole
345
- difference between a record and a ritual.
346
-
347
- **A mid-flight change lands as if it had been there from the start.** An idea arriving during G5 is
348
- written in the present tense — not appended, not annotated, not marked as late. The commit is that
349
- record, and it is a better one than a paragraph.
350
-
351
- **What this rule does NOT cut:**
352
-
353
- - **The PRD's Revision History.** Its reader is outside the room, and `prd-guide.md` already demands the
354
- business form of it: *state what the promise now is, not which section was edited.*
355
- - **`.control/questions/answered.md`.** This is the clearest case of history that pays: it is what stops
356
- the same question being asked again in three months.
357
- - **`ratified_by:`** on a room guide — evidence the rule is real, not a record that it changed.
358
- - **`why/`** and `.control/decisions/`, whose job is exactly the first kind.
359
- - **`superseded`** pointing at its replacement. A reader following an old id needs the pointer.
360
-
361
- Real cost of getting this wrong, from one repo: a codebase conventions guide — the file a developer opens
362
- to learn how to write code here — spent a quarter of its length explaining when it had been filled, why it
363
- was not a `DEC-`, and which alternative had been rejected. Not one line of that would save the next reader
364
- from anything.
365
-
366
- ## Two axes inside `.what/`
367
-
368
- | | `_prd/<initiative>/` | `<pc>/` |
369
- |---|---|---|
370
- | Slices by | **Initiative** — one functional area | **Space** — one Product Component |
371
- | Answers | What is promised to a user | What this component can do |
372
- | Written for | Outside readers — client, sponsor | People building the system |
373
-
374
- Both are living. What separates them is **promise versus behaviour**, not lifetime. One functional area MAY
375
- span several components, and one component MAY serve several PRDs, so neither can absorb the other.
376
-
377
- **Time is not a folder axis.** Release lives in `CAP.target_release` and in `specs.yaml`.
378
-
379
- ## Slot numbering means two different things
380
-
381
- | Layer | Slots | The number means |
382
- |---|---|---|
383
- | `.what/<pc>/` | `02-rules` · `03-domain` · `04-usecases` · `05-scenarios` | **Reading order** — its rules → the things → how it is used → its branches |
384
- | `.how/<pc>/` | `01-ux` … `06-flows` | **ABCE classification** — Boundary, Control, Entity, behaviour. Not a reading order |
385
-
386
- Reading one as the other is the most common misfiling in this corpus, and it is silent: the file lands in a
387
- plausible-looking folder and is simply never found again.
388
-
389
- `.what/<pc>/01-requirements/` is **repealed** — permanently empty, because `FR` live in the PRD and the SRS
390
- cites them. `supplements/` beside either kernel is repealed with the `ANX-` concept.
391
-
392
- ## Splitting slots
393
-
394
- - A slot MAY stay empty. Content SHOULD stay in the kernel until that file grows past roughly 400 lines — a
395
- suggestion, not a threshold, and a file that is clearer split earlier MAY be split earlier.
396
- - The first slot to be split SHOULD be `04-usecases/` — it is always the largest part.
397
- - One use case with many branches MUST put its branches in `05-scenarios/` rather than growing its own file.
398
- - The `Actor Register` MUST stay in the SRS kernel. It is the SSOT the SDD mirrors, and it is short.
399
-
400
- ## Document codes
401
-
402
- | Code | Is |
403
- |---|---|
404
- | `BG-` `CAP-` `FR-` `NFR-` `UJ-` `UC-` | The traceability chain. `BG` from `goals.yaml`; `CAP`/`FR`/`NFR`/`UJ` from that initiative's `requirements-<slug>.yaml`; `UC` from `usecases.yaml` |
405
- | `AD-` | An invariant in the architecture spine — a living rule, edited in place |
406
- | `DEC-` | A decision — an event, frozen when `applied`, only superseded |
407
- | `LC-` | A Logical Component |
408
- | `OQ-` | An open question. `RTR-` was the archived retrospective and is **retired** — a frozen `RTR-` file stays where it is |
409
- | `BUG-` `HOT-` | A defect · a hotfix |
410
- | `NT-` | A non-technical fact |
411
-
412
- **Retired, and MUST NOT be coined again:** `ADR-` (renamed to `DEC-` on 2026-08-18; the old prefix inside a
413
- document frozen before that date is an alias for the same number) · `ANX-` (zero annexes were ever born) ·
414
- `SCP-` (a course correction is a `DEC-`) · `BRS-`, `PFQ-`, `RES-` (exploration output is never promoted).
415
-
416
- IDs are allocated **globally** and never restart per document, per component, or per release.
417
-
418
- ### A record of the past MUST NOT be rewritten to match the present
419
-
420
- A retired name appearing in a document that **records what happened** is a fact about the past, not
421
- drift, and a sweep MUST NOT rename it. Four kinds, and all four are legitimate:
422
-
423
- | Where | What it says | Why it stays |
424
- |---|---|---|
425
- | `.control/decisions/DEC-*.md` — `Applied to`, `Temuan` | *"`wdi-apply` applied this on 2026-08-17"* | It did. Renaming it to today's skill claims a skill that did not exist then did the work |
426
- | `.control/memlog/*.md` | Which skill ran, and what it decided while running | A run log. Rewriting it destroys the only account of how an artifact got that way |
427
- | `.control/questions/answered.md` · `project-non-technical-log.md` | An answer, with its date and who gave it | Closed in place by rule; the wording is part of the record |
428
- | `.what/` and `.how/` frozen before a rename | Prose that cites the old name | Frozen by decision. `ADR-NNN` there is a retired alias for `DEC-NNN` with the same number |
429
-
430
- The test is one question: **does this sentence describe what happened, or state what holds?** Describes
431
- → leave it. States → sweep it.
432
-
433
- That distinction is why a sweep can be run repeatedly without churn. Without it, every pass rewrites
434
- the same three dozen historical files and the diff stops carrying information.
435
-
436
- File naming that must survive every OS is governed by `structure-guide.md` and MUST NOT be restated here.
437
-
438
- ## `.constitution/project/` — this product's custom rules
439
-
440
- The rest of `.constitution/` **belongs to the method**: it ships in the `wdi-method` package and is
441
- **overwritten** on every `update`. This folder is the only one that is not. `update` seeds it once and
442
- never writes over it again, and `promote` **skips it**, so a rule that names a client cannot reach the
443
- public package.
444
-
445
- | Goes here | Does not, and its home |
446
- |---|---|
447
- | A review policy a client requires | product / client name → `index.yaml` `product:` |
448
- | A process rule that came from a contract | code conventions → `.constitution/project/codebase-*-guide.md` |
449
- | A policy that differs from the method default | scope and ownership → `.constitution/project/constitution.md` Art. 1, 2, 5 |
450
- | A prohibition specific to this domain | agent instructions → `AGENTS.md`, outside the marked block |
451
-
452
- **A generic rule MUST NOT be moved here.** If it holds in any project it belongs to the package — fix
453
- it there, then `promote`. Using this room to bypass the package is how a method stops being generic
454
- with nobody deciding it, and **an empty room is a valid state**: filling it so that it gets used is the
455
- very failure this rule prevents.
456
-
457
- Frontmatter is required and **`custom-room-declared`** checks it: `scope: project` · a one-line `purpose:`. A file MAY
458
- narrow or add with nothing further; to **contradict** a generic rule it MUST name that rule in
459
- `overrides:` and carry `decision:` naming the `DEC-` that decided it. A method that can be contradicted
460
- without a decision stops being trustworthy in the next repo.
461
-
462
- **Whole files, not marked blocks.** `AGENTS.md` uses a marked block because it is one file;
463
- `.constitution/` has fifty-odd, and blocks inside them would make `update` perform surgery in every
464
- file — one broken marker and either the product's rule is erased or the generic rule freezes.
465
-
466
- ## Documents that predate the method
467
-
468
- A repository that already had documentation keeps it in `_bmad-output/prior-knowledge/`. It follows the same
469
- rules as the rest of `_bmad-output/`: committed, never curated, cited by path, never deleted.
470
-
471
- The sorting happens once, at install, and the test is a single question: **is this file already the artifact
472
- one corpus slot asks for, one file for one slot?** Yes → straight into that slot, carrying a provenance line
473
- naming the gate that ratifies it. No → `prior-knowledge/`.
474
-
475
- **A file in `prior-knowledge/` MUST NOT be copied into `.what/` or `.how/` afterwards.** It enters the corpus
476
- only through the skill that owns the slot, which reads it as input. This is the rule the whole arrangement
477
- exists for: moving a file is always cheaper than running the stage that should have produced it, so without a
478
- rule the move always wins — and what lands then has no author, no input trail, and no gate behind it.
479
-
480
- ### Retiring `prior-knowledge/`, and the condition that makes it safe
481
-
482
- A prior document is **input**, and input stops being needed once what it was read for is written down. Three
483
- conditions, and **all three MUST hold** before the folder is deleted:
484
-
485
- 1. **Every promise it carried is mapped.** The old numbering has a complete old → new table, and that table
486
- lives in the `addendum.md` beside the PRD it maps into — **not** in `prior-knowledge/`, precisely so the
487
- source can be retired without taking the map with it.
488
- 2. **Every live citation into it has been re-pointed or dropped.** A glossary entry, a `risk_note`, an
489
- `enforced_by` — anything that *states what holds*. Where the fact has a home in code or in `.control/`, the
490
- citation points there instead.
491
- 3. **The retirement is recorded as a `DEC-`.** Deleting source material is expensive to reverse, and the
492
- answer to *why is it gone* is not readable from the code.
493
-
494
- **A citation left inside a record of the past is not condition 2's business.** A `DEC-`'s Trace naming the
495
- document it was derived from, or a memlog naming what a run read, describes what happened — and the rule above
496
- on records of the past applies. Those citations dangle by design, and `wdi-reconcile`'s Evidence check MUST NOT
497
- report them: what makes it harmless is that the substance is already written into the document doing the
498
- citing, so the path is provenance rather than a dependency.
499
-
500
- The same three conditions govern `.work/`, with one difference: nothing there was ever authority, so condition
501
- 1 is usually already met.
502
-
503
- Two consequences that MUST be expected rather than discovered:
504
-
505
- - Internal numbering inside a prior document — `FR-3`, `§7` — is **not** a corpus ID. A mapping table MAY be
506
- written once, and it lives in `prior-knowledge/`, never in `.control/`.
507
- - A file placed straight into a slot MUST lose any claim of authority it makes about itself. In the corpus,
508
- authority comes from the layer and the gate.
509
-
510
- ## Rules
511
-
512
- - A file MUST NOT be moved between layers by a skill that owns neither end. Anything else is a misplacement,
513
- and MUST be reported rather than fixed.
514
- - A fact MUST have exactly one home. When two documents state the same thing, one of them MUST become a
515
- reference — and the copy being replaced MUST be deleted, not left as a courtesy.
516
- - Solution shape MUST NOT appear in `.what/`. Promises MUST NOT appear first in `.how/`.
517
- - Superseded artifacts are not deleted. Their status becomes `superseded` and points at the replacement.
1
+ ---
2
+ status: Accepted
3
+ ---
4
+
5
+ # Corpus Guide
6
+
7
+ **Loaded when:** deciding where a file lives, or creating a new file in the corpus
8
+
9
+ Four layers and one workspace. Every other guide describes one document; this one answers the question that
10
+ comes before all of them — **where does this belong?**
11
+
12
+ The quick answer for the thing actually in your hand is the "benda di tangan → folder" table in `AGENTS.md`.
13
+ It is deliberately there rather than here: it is needed at the moment someone would otherwise have to reason
14
+ about what `.what/` and `.how/` mean, and that moment comes before anyone thinks to open a guide. It MUST NOT
15
+ be copied into this file.
16
+
17
+ ## The four layers
18
+
19
+ | Layer | Answers | Lifetime | Written by |
20
+ |---|---|---|---|
21
+ | `.constitution/` | How we work | Living, rarely changes | Us |
22
+ | `.control/` | What currently holds, and what has been decided | Living, changes often | Us + generators |
23
+ | `.what/` | What is promised | Living, amended | BMad class A + us |
24
+ | `.how/` | How it is built | Living, amended | BMad class A + us |
25
+ | `_bmad-output/` | Work in progress | Ends when the work does | BMad class B and C |
26
+ | `.what-rendered/` · `.how-rendered/` | The same promise and shape, **assembled for a human to read** | Regenerated on every `render`; never edited | `validate.py --generate`, and nobody else |
27
+
28
+ `.control/` is the value of `{project_knowledge}` in BMad's configuration. There is no `docs/`.
29
+
30
+ ### Two audiences, two trees
31
+
32
+ `.what/` and `.how/` are the **working** trees: prose that cannot be a row, pointers to the registry for
33
+ everything that can. They are what an agent reads and what a skill writes. They are deliberately thin
34
+ for a human — `Goals` is one line, an `FR` is an id — because completeness is not their job.
35
+
36
+ `.what-rendered/` and `.how-rendered/` are the **reader's** trees. Every file in them sits at the mirror
37
+ path of the working document it projects — `.what-rendered/<pc>/SRS-<pc>.md` is
38
+ `.what/<pc>/SRS-<pc>.md` with every pointer opened: the goal statements, the UC rows, the
39
+ `AD-N` text, the open questions, all pulled in from their own homes. That is what a gate reads, and
40
+ what a client receives.
41
+
42
+ Three rules keep the two trees honest:
43
+
44
+ - **A skill MUST NOT read a `-rendered` file as input.** It is output. The working document and the
45
+ registry are the source, and a skill that read the projection would be reading its own echo — a
46
+ `kit-integrity` test fails when any `SKILL.md` lists one in its `Inputs`.
47
+ - **Nobody edits a `-rendered` file.** A defect seen there is a defect in the working document or the
48
+ registry, and that is where it is fixed. The next `render` overwrites the page.
49
+ - **Every gate reads one rendered page, and that page MUST answer the gate's seven questions.** G1
50
+ reads `.what-rendered/_product-brief/brief.md`; G2 `.what-rendered/_prd/<slug>/prd.md`; G3
51
+ `.how-rendered/blueprint.md`; G4 `.how-rendered/<pc>/SDD-<pc>.md`. A question that cannot be
52
+ answered from the page is a gap in the page, not a reason to open a working file.
53
+
54
+ ## The placement test
55
+
56
+ One question decides everything: **is this file still correct after its spec has passed?**
57
+
58
+ Yes → the corpus. No → `_bmad-output/`.
59
+
60
+ `_bmad-output/` is committed but **not curated**. Committing it is what makes citation by path stable, so a
61
+ decision or a PRD MAY point into it. One exception: once components exist, `.what/` and `.how/` MUST NOT
62
+ cite a UX run's `DESIGN.md`, `EXPERIENCE.md`, or `design-system.md` — the run has been distilled, and
63
+ `ux-guide.md` § Rules owns it. Research, brainstorming, forge, and PRFAQ reports are never promoted.
64
+
65
+ A run folder MUST NOT be deleted **while anything still needs it** — the `update` intents re-read the original
66
+ inputs in place. "Never deleted" is not the rule; the rule is a **retirement condition**, and it is below.
67
+
68
+ **What git ignores is not corpus.** A vendored upstream checkout kept for reading, a scratch download, a
69
+ build cache — if the product excludes it from git it is in no clone, nobody curates it, and the validators
70
+ do not read it. The other half of that rule is `corpus-in-git`: a folder the method itself keeps MUST NOT be
71
+ excluded, and the two lock together — material is either in git and checked, or ignored and not corpus. What
72
+ `.gitignore` MUST NOT be used for is quieting a finding about a file that really is this product's.
73
+
74
+ ### A withdrawn promise STAYS in the registry
75
+
76
+ A `BG` · `CAP` · `FR` · `NFR` · `UC` the product stops promising is marked, never deleted:
77
+
78
+ ```yaml
79
+ - id: CAP-8
80
+ title: "Publish an order as a public page"
81
+ status: withdrawn
82
+ withdrawn_by: DEC-026
83
+ ```
84
+
85
+ **Why the row stays.** One repo deleted two withdrawn capabilities and paid for it in twelve
86
+ `refs-resolve` findings: eight `DEC-` rows still named them in `serves:`, and six of those eight
87
+ genuinely served them at the time. The other repair — editing those decisions — is refused by the
88
+ section above: a `DEC-` is a record of what happened, and a retired name inside one is a fact about
89
+ the past.
90
+
91
+ **So a withdrawn row is read two ways, and both matter.** It is still **defined**: every old
92
+ reference resolves, and `id-allocated-once` still refuses the number to anything else — an id is
93
+ allocated once, withdrawal included. It is no longer **promised**: no `UC` is owed, no ticket, no RTM
94
+ row, and `promise_progress` is not dragged down by something nobody promises any more.
95
+
96
+ **Two rules keep it honest**, and `withdrawn-recorded` is what enforces both:
97
+
98
+ - `withdrawn_by` MUST name a `DEC-` that exists. Retiring an id is decision-worthy on this method's
99
+ own terms — the **ID chain** row under § *Landing that MUST be confirmed first* says so outright —
100
+ and without the pointer `withdrawn` is only a word that quiets a validator.
101
+ - A live row MUST NOT hang off a withdrawn one. An `FR` under a withdrawn `CAP` still promises
102
+ something whose capability nobody promises: withdraw it too, or move it under something live.
103
+ Withdrawal that takes half a chain with it silently is worse than the deletion it replaced, because
104
+ deletion at least went red.
105
+
106
+ `wdi-product` owns the edit, because it owns the row. The withdrawal itself goes through
107
+ `wdi-decision` first — the `DEC-` is what `withdrawn_by` points at.
108
+
109
+ ## Who lands what
110
+
111
+ There is no separate placement skill. A skill lands the output of the layer **it owns**, and the landing is
112
+ part of producing it — never a follow-up someone else performs.
113
+
114
+ | Output | Permanent home | Owner |
115
+ |---|---|---|
116
+ | The spine | `.how/_platform/ARCHITECTURE-SPINE.md` | `wdi-blueprint` |
117
+ | C4 L1 · L2 · one L3 per container holding more than one PC | `.how/_platform/c4-l1-system-context.md` · `c4-l2-containers.md` · `c4-l3-<container>.md` | `wdi-blueprint` |
118
+ | each container in C4 L2 | a `container` entry in `components.yaml` | `wdi-blueprint` |
119
+ | **The three inventories** | `.how/_platform/inventory-db.md` · `inventory-api.md` · `inventory-screen.md` | `wdi-blueprint` |
120
+ | The error envelope, and anything else defined once for the product | `.how/_platform/cross-cutting.md` | `wdi-blueprint` |
121
+ | UC catalogue · Actor Register · domain model | `.what/<pc>/SRS-<pc>.md` · `03-domain/domain-model.md` | `wdi-blueprint` |
122
+ | Business rules binding more than one PC | `.what/business-rules.md` | `wdi-blueprint` |
123
+ | A domain term | `.control/product-glossary.md` | `wdi-blueprint` |
124
+ | Full UC flows · local rules · state machines · scenarios | `.what/<pc>/` slots `02`–`05` | `wdi-component` intent `behaviour` |
125
+ | The SDD and its slots `02`–`06` | `.how/<pc>/` | `wdi-component` intent `design` |
126
+ | each Boundary and Control object drawn | an `LC` in `components.yaml` | `wdi-component` intent `design` |
127
+ | Experience that holds for every component — `ux-guide.md` § *Product level* | `.what/experience.md` | `wdi-ux` |
128
+ | `EXPERIENCE.md` | `.what/<pc>/04-usecases/` | `wdi-ux` |
129
+ | `DESIGN.md` | `.how/<pc>/01-ux/` | `wdi-ux` |
130
+ | tokens, base components, and build patterns every component shares | `.how/_platform/design-system.md` | `wdi-ux` |
131
+ | each screen in `DESIGN.md` | an `LC` of type `ui-screen` in `components.yaml` | `wdi-ux` |
132
+ | The names of the tests a ticket went green on | the ticket's `tests` in `specs.yaml` | `wdi-build` |
133
+ | What the spec settled about the stack, the conventions, or the brownfield reality | merged into `.constitution/project/codebase-*-guide.md` | `wdi-build`, at spec close |
134
+ | A sprint change proposal | a `DEC-` of `type: course-correction` | `wdi-decision` |
135
+ | The registry rows and skeletons a new PC needs | `components.yaml` · `.what/<pc>/` · `.how/<pc>/` | `wdi-init` intent `component` |
136
+ | `platform_owns` — an entity no component's promise explains | `components.yaml`, plus its description in `cross-cutting.md` | `wdi-blueprint` |
137
+ | The two structure maps | `.control/structure-codebase.md` · `structure-document.md` | `wdi-init` intent `structure` |
138
+ | An open question | `.control/questions/` — one of four files | `wdi-question` |
139
+ | A decision | `.control/decisions/DEC-NNN-<slug>.md` | `wdi-decision` |
140
+ | Minutes · a non-technical fact | `.control/meetings/` · `.control/project-non-technical-log.md` | `wdi-log` |
141
+
142
+ - A skill MUST NOT write into a layer it does not own.
143
+ - Registry conversion is part of landing, not a follow-up. A screen that lands in `01-ux/` without its
144
+ `components.yaml` entry has been half-landed, and `lc-registered` catches it **at spec close** — which is the
145
+ right moment to be caught, and a bad moment to be surprised.
146
+ - Content MUST NOT be edited while it is being landed. If it has to change to fit its new home, that is a
147
+ separate act — say so and stop. Splitting one output across the homes its row names is not editing.
148
+ - The C4 set's target files already exist and are **living**. Their owner MUST amend, MUST NOT overwrite; when
149
+ the incoming set contradicts an annotation already there, it MUST stop and report the finding.
150
+ - Nothing MAY be landed into a spec that is already closed. The spec is reopened through `wdi-build`, or the
151
+ gap is recorded as an open question.
152
+ - An output with **no row** in this table MUST NOT be given a guessed home. It stays in `_bmad-output/`, and
153
+ `wdi-reconcile` reports it — an output with no home is a gap in the method, and MUST surface as one.
154
+
155
+ ## Landing that MUST be confirmed first
156
+
157
+ Most landings are mechanical and MAY be done without asking. Some change what other people already agreed to,
158
+ and those MUST be put to the owner before the file is written — not reported afterwards. The line is drawn by
159
+ **what the landing can invalidate**, never by how much text moves:
160
+
161
+ | | Light — act, then report | Heavy — confirm, then act |
162
+ |---|---|---|
163
+ | Layer | Stays inside the layer the skill owns | Crosses into another layer's consequences |
164
+ | ID chain | No `BG`/`CAP`/`FR`/`NFR`/`UC`/`LC` id is born, renamed, or retired | Any of them is |
165
+ | Depth and risk | `mode` and `risk_accepted` unchanged | Either would have to change |
166
+ | Existing text | Adds, or replaces content the same skill wrote | Overwrites or contradicts what another skill or a human wrote |
167
+ | Registry | Adds the entry its own output requires | Removes or re-points an entry something else already cites |
168
+
169
+ Any one heavy row makes the whole landing heavy. When confirmation cannot be obtained now, the landing MUST
170
+ NOT be split into a light half that goes ahead — half-landed output looks distributed and is worse than output
171
+ that waited.
172
+
173
+ A skill MUST NOT lighten a landing by narrowing what it writes. Dropping the contentious half to stay under
174
+ the bar is the same change, made invisible.
175
+
176
+ ## Product Component — the naming and proposal rule
177
+
178
+ This rule lives here, beside the definition, and **not inside a skill**. If it lived in one skill, the second
179
+ skill that needed it would copy it, and the two copies would drift.
180
+
181
+ > The name of a Product Component MUST be a surface a user could name. A name that states a layer, a service,
182
+ > or a pattern MUST be rejected at proposal time, not corrected later. Additions, changes, and removals MUST
183
+ > be presented separately, each with the `FR` behind it.
184
+
185
+ A PC MUST NOT be created because a folder would look tidy. A PC that no `FR` points at is a folder with
186
+ nothing inside it.
187
+
188
+ Birthing is cheap and retiring is not: retiring or renaming a PC that already carries an SRS goes through
189
+ `wdi-decision`, never through the skill that births one.
190
+
191
+ ## Product Component, Logical Component, container, `_platform`
192
+
193
+ Four words that are easy to blur and MUST NOT be:
194
+
195
+ | Term | Is | Registered in |
196
+ |---|---|---|
197
+ | **Product Component** | A surface a user can name — what they came to do | `product_components` |
198
+ | **Logical Component** | A unit inside the build — a screen, a service, an adapter, an entity | `logical_components` |
199
+ | **Container** | Something that runs or ships on its own | `containers` |
200
+ | **`_platform`** | **Not a component at all** — the home for what belongs to no Product Component | `platform_owns`, and the `_platform/` folder |
201
+
202
+ PC and container are **crossing axes**, not a hierarchy: one PC MAY be delivered by several containers, and one
203
+ container MAY serve several PCs. An `LC` names its container in a `container:` field, which is what lets
204
+ `structure-codebase.md` be checked against the registry rather than trusted.
205
+
206
+ ## `_platform` — what belongs to no Product Component
207
+
208
+ `_platform` is **not a Product Component**, and it MUST NOT be registered as one. It fails the naming test on
209
+ purpose: nobody came to the product to use "the platform". It therefore carries **no `mode`, no
210
+ `risk_accepted`, no SRS, no SDD, and no G4** — its documents are the spine, the C4 set, `cross-cutting.md`,
211
+ and the three inventories, and all of those exist at every `mode`.
212
+
213
+ What it does carry is **ownership**. `_platform` is a legitimate value in **every** position that asks
214
+ *"which component owns this"* — the `platform_owns:` list for domain entities, the owning-component column
215
+ of any inventory row, an `LC`'s `component:` field, and any such column a later artifact adds. One test,
216
+ one cost, everywhere; there is no per-artifact special case to negotiate, and a new kind of thing arriving
217
+ next year needs no new discussion.
218
+
219
+ The test, and both halves MUST hold:
220
+
221
+ > Something belongs to `_platform` when **no single Product Component's promise is the reason it exists**,
222
+ > *and* more than one component reads, writes, or depends on it.
223
+
224
+ Four kinds qualify today and the list is open: **data** (a product-wide setting, the trace of a shared
225
+ outbound channel) · **endpoint** (`/health`, `robots.txt` — plumbing no `FR` promises and none should) ·
226
+ **job** (a scheduled cleaner whose data belongs to a component but whose machinery does not) · **screen**
227
+ (none yet).
228
+
229
+ Failing either half, it belongs to a Product Component — and the component is found by asking which `FR`
230
+ would have to be withdrawn for the entity to stop being needed. Two examples of the trap:
231
+
232
+ | Entity | Looks platform-shaped | Actually |
233
+ |---|---|---|
234
+ | `activity_events` | product-wide telemetry, several components write it | **one component** — an `FR` promises somebody can SEE those counts, and withdrawing it is what would make the table unnecessary |
235
+ | `email_logs` | one component sends first | **`_platform`** — it is the trace of one outbound channel that order notifications and password recovery both use, and neither promise is why the channel exists |
236
+
237
+ **One guard, and it is what stops this becoming a drawer:** everything `_platform` owns — in any position —
238
+ MUST be described under `## Platform-owned` in `cross-cutting.md`, with its kind and the shape every toucher
239
+ obeys. A platform that owns something documents it. `entity-one-writer` checks it, and skips only while that section has not
240
+ been born at G3.
241
+
242
+ That guard is the whole reason `_platform` can be a general answer rather than an escape hatch: reaching for
243
+ it costs a row somebody has to write, so it stays cheaper to find the real owner when one exists.
244
+
245
+ `_platform` has no `FR`, so an `FR` that writes something platform-owned has nothing to point `defers_to` at,
246
+ and MUST NOT be asked for one. What replaces "one writer" there is **one documented shape**: it is written the
247
+ way `cross-cutting.md` says, and a component wanting it written differently is proposing a change to that file.
248
+
249
+ Platform ownership sits with `wdi-blueprint` intent `platform`, beside the rest of `_platform/`. `wdi-init`
250
+ intent `component` MAY name a candidate and MUST NOT claim one.
251
+
252
+ **A decision the pattern cannot derive lives in the artifact it governs.** An inventory row owned by
253
+ `_platform`, and a route that is a *state* of another screen rather than a screen of its own, are both
254
+ judgements — so both are declared in that inventory's own frontmatter (`platform_rows:` and `states:`) and
255
+ survive every re-derivation. Putting either outside the file means the next derivation silently deletes the
256
+ owner's decision.
257
+
258
+ ## A derived fact has exactly one home
259
+
260
+ `why/rationale.md` has always carried this as principle 5 — *what can be derived is not written by hand.*
261
+ It was never written as a rule anywhere, and that file binds nothing by its own terms. So it bound nothing,
262
+ and only one field was ever actually protected: ticket status, by `ticket-status-one-home`.
263
+
264
+ **A document MUST NOT state a fact that a registry, a generated file, or git already holds.** It cites the
265
+ id and lets the reader follow it. The list is short and it is closed:
266
+
267
+ | Never stated in prose | Where it lives |
268
+ |---|---|
269
+ | `mode` · `risk_accepted` · `g4_passed` | `components.yaml` |
270
+ | Which `DEC-` bind this document — **including "none yet"** | `.control/generated/decisions.md` |
271
+ | A count of `UC`, `FR`, `CAP`, or containers | the registry that holds them |
272
+ | Which slots or files exist, and which are still empty | `.control/structure-document.md`, derived |
273
+ | Whether an `OQ-` is open or answered | `.control/questions/` |
274
+ | When the document last changed | git |
275
+
276
+ **The remedy is DELETION, never correction.** This is the part that costs a corpus real time to learn: a
277
+ restated fact that is corrected becomes a *second* stale fact, on a slower clock than the first. One SRS in a
278
+ real repo carried three claims about its own `mode` on one page — the value, a correction block below it
279
+ fixing an older value, and the slot list — and not one of the three was right. Correcting any of them would
280
+ have added a fourth. Deleting all three ends it.
281
+
282
+ A negative claim is the worst case and the easiest to miss, because it looks like diligence: *"No applied
283
+ `DEC-` binds this component yet"* is true the day it is written and silently false forever after.
284
+
285
+ **What is NOT a derived fact**, and MUST still be written where it belongs: a judgement the pattern cannot
286
+ recompute (the paragraph above owns that), an `AD-N` citation — the spine's `binds:` is authored, not
287
+ derived — and the *reason* something is the way it is, which no registry holds.
288
+
289
+ ## A pass writes one artifact
290
+
291
+ When a skill is writing or updating an artifact, **that artifact is the pass.** Hunting the rest of the
292
+ corpus for things that disagree with it is not part of writing it, and MUST NOT be folded in: it is
293
+ `wdi-reconcile`'s job, it runs at a gate, and `wdi-review` § Stale is not a finding decides what is even
294
+ worth reporting when it does.
295
+
296
+ Where a contradiction surfaces anyway — and it will, because writing a document is how you notice — there
297
+ are exactly two outcomes:
298
+
299
+ | The other document is | Do |
300
+ |---|---|
301
+ | **Load-bearing wrong** — a reader would make the wrong repair | Say it in **one line** in the output, naming the file and the edit it needs |
302
+ | Anything else | Nothing. Not a line, not an `OQ-`, not a `DEC-` |
303
+
304
+ It MUST NOT become an open question, and it MUST NOT become a decision. A contradiction between two
305
+ documents is an **edit** waiting for whoever owns the file — never a thing to be adjudicated.
306
+
307
+ **This binds hardest at G1 and G2.** A brief is being formed; a PRD is being written. There is barely a
308
+ corpus to be consistent with yet, and a pass that spends its budget looking for one is spending it on
309
+ nothing.
310
+
311
+ ## One decided change is one edit pass
312
+
313
+ Once the owner has decided, the chain is **applied**, not surveyed. The agent already knows what the
314
+ change reaches — `touches:` names it, the ownership table in this file names who lands each part, and the
315
+ RTM names the rows that move. It edits all of them in **one pass** and reports once.
316
+
317
+ What MUST NOT happen: checking one document, reporting, waiting, checking the next; re-deriving the same
318
+ relations in a later pass; or asking the owner to confirm the same decision at each file it touches. The
319
+ documents are split for reading, not to be walked one at a time — and walking them is where the time and
320
+ the tokens actually go.
321
+
322
+ ## The corpus is written in the present tense
323
+
324
+ A design document states **what is true now**: the latest state of the design, and what still has to be
325
+ reached. It does not state how it got there. This governs `.what/<pc>/`, `.how/`, and
326
+ `.constitution/project/`.
327
+
328
+ ### Two kinds of history, and only one is worth writing
329
+
330
+ Most history is not useful. What is useful is the current state — and the rare piece of history that
331
+ **stops the same mistake happening twice**. One question separates them:
332
+
333
+ > **Would someone about to make a change be saved by this line?**
334
+
335
+ | Kind | Example | Where it goes |
336
+ |---|---|---|
337
+ | **Business or technical** — the mistake could recur | *"Files are removed before the record, and that left a document pointing at a deleted image"* | A `DEC-`, `why/`, or `answered.md`. Rarely, and only when it earns it |
338
+ | **Document history** — a document said something else last week | *"This section was rewritten"* · *"withdrawn because a later pass found it wrong"* · *"this used to read X"* | **Nowhere.** git holds it, and git holds it better |
339
+
340
+ The second kind is what fills a corpus and buys nothing. It arrives as a correction block, a
341
+ `## Provenance` note, a document's own change log, a note about a conflict that has already been
342
+ **resolved**, or a *"considered and rejected"* aside about the method itself. All of it MUST NOT be
343
+ written in the three layers above.
344
+
345
+ **And no step demands the first kind either.** History is never a checklist item, never a gate condition,
346
+ and never a blocking finding. It is written when someone judges it worth writing, and skipping it is
347
+ **not** a gap — nothing in this method MAY report a missing history line as a defect. That is the whole
348
+ difference between a record and a ritual.
349
+
350
+ **A mid-flight change lands as if it had been there from the start.** An idea arriving during G5 is
351
+ written in the present tense — not appended, not annotated, not marked as late. The commit is that
352
+ record, and it is a better one than a paragraph.
353
+
354
+ **What this rule does NOT cut:**
355
+
356
+ - **The PRD's Revision History.** Its reader is outside the room, and `prd-guide.md` already demands the
357
+ business form of it: *state what the promise now is, not which section was edited.*
358
+ - **`.control/questions/answered.md`.** This is the clearest case of history that pays: it is what stops
359
+ the same question being asked again in three months.
360
+ - **`ratified_by:`** on a room guide — evidence the rule is real, not a record that it changed.
361
+ - **`why/`** and `.control/decisions/`, whose job is exactly the first kind.
362
+ - **`superseded`** pointing at its replacement. A reader following an old id needs the pointer.
363
+
364
+ Real cost of getting this wrong, from one repo: a codebase conventions guide — the file a developer opens
365
+ to learn how to write code here — spent a quarter of its length explaining when it had been filled, why it
366
+ was not a `DEC-`, and which alternative had been rejected. Not one line of that would save the next reader
367
+ from anything.
368
+
369
+ ## Two axes inside `.what/`
370
+
371
+ | | `_prd/<initiative>/` | `<pc>/` |
372
+ |---|---|---|
373
+ | Slices by | **Initiative** — one functional area | **Space** — one Product Component |
374
+ | Answers | What is promised to a user | What this component can do |
375
+ | Written for | Outside readers — client, sponsor | People building the system |
376
+
377
+ Both are living. What separates them is **promise versus behaviour**, not lifetime. One functional area MAY
378
+ span several components, and one component MAY serve several PRDs, so neither can absorb the other.
379
+
380
+ **Time is not a folder axis.** Release lives in `CAP.target_release` and in `specs.yaml`.
381
+
382
+ ## Slot numbering means two different things
383
+
384
+ | Layer | Slots | The number means |
385
+ |---|---|---|
386
+ | `.what/<pc>/` | `02-rules` · `03-domain` · `04-usecases` · `05-scenarios` | **Reading order** — its rules → the things → how it is used → its branches |
387
+ | `.how/<pc>/` | `01-ux` … `06-flows` | **ABCE classification** — Boundary, Control, Entity, behaviour. Not a reading order |
388
+
389
+ Reading one as the other is the most common misfiling in this corpus, and it is silent: the file lands in a
390
+ plausible-looking folder and is simply never found again.
391
+
392
+ `.what/<pc>/01-requirements/` is **repealed** — permanently empty, because `FR` live in the PRD and the SRS
393
+ cites them. `supplements/` beside either kernel is repealed with the `ANX-` concept.
394
+
395
+ ## Splitting slots
396
+
397
+ - A slot MAY stay empty. Content SHOULD stay in the kernel until that file grows past roughly 400 lines — a
398
+ suggestion, not a threshold, and a file that is clearer split earlier MAY be split earlier.
399
+ - The first slot to be split SHOULD be `04-usecases/` — it is always the largest part.
400
+ - One use case with many branches MUST put its branches in `05-scenarios/` rather than growing its own file.
401
+ - The `Actor Register` MUST stay in the SRS kernel. It is the SSOT the SDD mirrors, and it is short.
402
+
403
+ ## Document codes
404
+
405
+ | Code | Is |
406
+ |---|---|
407
+ | `BG-` `CAP-` `FR-` `NFR-` `UJ-` `UC-` | The traceability chain. `BG` from `goals.yaml`; `CAP`/`FR`/`NFR`/`UJ` from that initiative's `requirements-<slug>.yaml`; `UC` from `usecases.yaml` |
408
+ | `AD-` | An invariant in the architecture spine — a living rule, edited in place |
409
+ | `DEC-` | A decision — an event, frozen when `applied`, only superseded |
410
+ | `LC-` | A Logical Component |
411
+ | `OQ-` | An open question. `RTR-` was the archived retrospective and is **retired** — a frozen `RTR-` file stays where it is |
412
+ | `BUG-` `HOT-` | A defect · a hotfix |
413
+ | `NT-` | A non-technical fact |
414
+
415
+ **Retired, and MUST NOT be coined again:** `ADR-` (renamed to `DEC-` on 2026-08-18; the old prefix inside a
416
+ document frozen before that date is an alias for the same number) · `ANX-` (zero annexes were ever born) ·
417
+ `SCP-` (a course correction is a `DEC-`) · `BRS-`, `PFQ-`, `RES-` (exploration output is never promoted).
418
+
419
+ IDs are allocated **globally** and never restart per document, per component, or per release.
420
+
421
+ ### A record of the past MUST NOT be rewritten to match the present
422
+
423
+ A retired name appearing in a document that **records what happened** is a fact about the past, not
424
+ drift, and a sweep MUST NOT rename it. Four kinds, and all four are legitimate:
425
+
426
+ | Where | What it says | Why it stays |
427
+ |---|---|---|
428
+ | `.control/decisions/DEC-*.md` — `Applied to`, `Temuan` | *"`wdi-apply` applied this on 2026-08-17"* | It did. Renaming it to today's skill claims a skill that did not exist then did the work |
429
+ | `.control/memlog/*.md` | Which skill ran, and what it decided while running | A run log. Rewriting it destroys the only account of how an artifact got that way |
430
+ | `.control/questions/answered.md` · `project-non-technical-log.md` | An answer, with its date and who gave it | Closed in place by rule; the wording is part of the record |
431
+ | `.what/` and `.how/` frozen before a rename | Prose that cites the old name | Frozen by decision. `ADR-NNN` there is a retired alias for `DEC-NNN` with the same number |
432
+
433
+ The test is one question: **does this sentence describe what happened, or state what holds?** Describes
434
+ → leave it. States → sweep it.
435
+
436
+ That distinction is why a sweep can be run repeatedly without churn. Without it, every pass rewrites
437
+ the same three dozen historical files and the diff stops carrying information.
438
+
439
+ File naming that must survive every OS is governed by `structure-guide.md` and MUST NOT be restated here.
440
+
441
+ ## `.constitution/project/` — this product's custom rules
442
+
443
+ The rest of `.constitution/` **belongs to the method**: it ships in the `wdi-method` package and is
444
+ **overwritten** on every `update`. This folder is the only one that is not. `update` seeds it once and
445
+ never writes over it again, and `promote` **skips it**, so a rule that names a client cannot reach the
446
+ public package.
447
+
448
+ | Goes here | Does not, and its home |
449
+ |---|---|
450
+ | A review policy a client requires | product / client name → `index.yaml` `product:` |
451
+ | A process rule that came from a contract | code conventions → `.constitution/project/codebase-*-guide.md` |
452
+ | A policy that differs from the method default | scope and ownership → `.constitution/project/constitution.md` Art. 1, 2, 5 |
453
+ | A prohibition specific to this domain | agent instructions → `AGENTS.md`, outside the marked block |
454
+
455
+ **A generic rule MUST NOT be moved here.** If it holds in any project it belongs to the package — fix
456
+ it there, then `promote`. Using this room to bypass the package is how a method stops being generic
457
+ with nobody deciding it, and **an empty room is a valid state**: filling it so that it gets used is the
458
+ very failure this rule prevents.
459
+
460
+ Frontmatter is required and **`custom-room-declared`** checks it: `scope: project` · a one-line `purpose:`. A file MAY
461
+ narrow or add with nothing further; to **contradict** a generic rule it MUST name that rule in
462
+ `overrides:` and carry `decision:` naming the `DEC-` that decided it. A method that can be contradicted
463
+ without a decision stops being trustworthy in the next repo.
464
+
465
+ **Whole files, not marked blocks.** `AGENTS.md` uses a marked block because it is one file;
466
+ `.constitution/` has fifty-odd, and blocks inside them would make `update` perform surgery in every
467
+ file — one broken marker and either the product's rule is erased or the generic rule freezes.
468
+
469
+ ## Documents that predate the method
470
+
471
+ A repository that already had documentation keeps it in `_bmad-output/prior-knowledge/`. It follows the same
472
+ rules as the rest of `_bmad-output/`: committed, never curated, cited by path, never deleted.
473
+
474
+ The sorting happens once, at install, and the test is a single question: **is this file already the artifact
475
+ one corpus slot asks for, one file for one slot?** Yes → straight into that slot, carrying a provenance line
476
+ naming the gate that ratifies it. No → `prior-knowledge/`.
477
+
478
+ **A file in `prior-knowledge/` MUST NOT be copied into `.what/` or `.how/` afterwards.** It enters the corpus
479
+ only through the skill that owns the slot, which reads it as input. This is the rule the whole arrangement
480
+ exists for: moving a file is always cheaper than running the stage that should have produced it, so without a
481
+ rule the move always wins — and what lands then has no author, no input trail, and no gate behind it.
482
+
483
+ ### Retiring `prior-knowledge/`, and the condition that makes it safe
484
+
485
+ A prior document is **input**, and input stops being needed once what it was read for is written down. Three
486
+ conditions, and **all three MUST hold** before the folder is deleted:
487
+
488
+ 1. **Every promise it carried is mapped.** The old numbering has a complete old → new table, and that table
489
+ lives in the `addendum.md` beside the PRD it maps into — **not** in `prior-knowledge/`, precisely so the
490
+ source can be retired without taking the map with it.
491
+ 2. **Every live citation into it has been re-pointed or dropped.** A glossary entry, a `risk_note`, an
492
+ `enforced_by` — anything that *states what holds*. Where the fact has a home in code or in `.control/`, the
493
+ citation points there instead.
494
+ 3. **The retirement is recorded as a `DEC-`.** Deleting source material is expensive to reverse, and the
495
+ answer to *why is it gone* is not readable from the code.
496
+
497
+ **A citation left inside a record of the past is not condition 2's business.** A `DEC-`'s Trace naming the
498
+ document it was derived from, or a memlog naming what a run read, describes what happened — and the rule above
499
+ on records of the past applies. Those citations dangle by design, and `wdi-reconcile`'s Evidence check MUST NOT
500
+ report them: what makes it harmless is that the substance is already written into the document doing the
501
+ citing, so the path is provenance rather than a dependency.
502
+
503
+ **`.work/` is not governed by these three conditions.** Nothing there was ever authority, so there is no
504
+ promise to map and no citation to re-point, and deleting scratch needs no `DEC-`. `repo-guide.md` § `.work/`
505
+ owns its retirement: distil what lasts, then delete when the task closes. The two guides used to disagree
506
+ here, and a repo holding a month of committed scratch could read either as permission to keep it.
507
+
508
+ Two consequences that MUST be expected rather than discovered:
509
+
510
+ - Internal numbering inside a prior document — `FR-3`, `§7` — is **not** a corpus ID. A mapping table MAY be
511
+ written once, and it lives in `prior-knowledge/`, never in `.control/`.
512
+ - A file placed straight into a slot MUST lose any claim of authority it makes about itself. In the corpus,
513
+ authority comes from the layer and the gate.
514
+
515
+ ## Rules
516
+
517
+ - A file MUST NOT be moved between layers by a skill that owns neither end. Anything else is a misplacement,
518
+ and MUST be reported rather than fixed.
519
+ - A fact MUST have exactly one home. When two documents state the same thing, one of them MUST become a
520
+ reference — and the copy being replaced MUST be deleted, not left as a courtesy.
521
+ - Solution shape MUST NOT appear in `.what/`. Promises MUST NOT appear first in `.how/`.
522
+ - Superseded artifacts are not deleted. Their status becomes `superseded` and points at the replacement.