wdi-method 0.3.0
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.
- package/LICENSE +21 -0
- package/README.md +203 -0
- package/bin/wdi-method.js +906 -0
- package/kit/.constitution/README.md +66 -0
- package/kit/.constitution/codebase/brownfield-guide.md +18 -0
- package/kit/.constitution/codebase/conventions-guide.md +18 -0
- package/kit/.constitution/codebase/stack-guide.md +18 -0
- package/kit/.constitution/constitution.md +135 -0
- package/kit/.constitution/document/architecture-guide.md +209 -0
- package/kit/.constitution/document/bmad-guide.md +151 -0
- package/kit/.constitution/document/bmad-skill-register.md +71 -0
- package/kit/.constitution/document/brief-guide.md +94 -0
- package/kit/.constitution/document/corpus-guide.md +341 -0
- package/kit/.constitution/document/decision-guide.md +134 -0
- package/kit/.constitution/document/delivery-flow-guide.md +338 -0
- package/kit/.constitution/document/prd-guide.md +202 -0
- package/kit/.constitution/document/sdd-guide.md +206 -0
- package/kit/.constitution/document/srs-guide.md +147 -0
- package/kit/.constitution/document/templates/addendum.md +71 -0
- package/kit/.constitution/document/templates/architecture-spine.md +100 -0
- package/kit/.constitution/document/templates/brief.md +110 -0
- package/kit/.constitution/document/templates/c4.md +77 -0
- package/kit/.constitution/document/templates/contract.md +52 -0
- package/kit/.constitution/document/templates/cross-cutting.md +80 -0
- package/kit/.constitution/document/templates/decision.md +64 -0
- package/kit/.constitution/document/templates/design-system.md +67 -0
- package/kit/.constitution/document/templates/flow.md +51 -0
- package/kit/.constitution/document/templates/integration.md +69 -0
- package/kit/.constitution/document/templates/inventory.md +69 -0
- package/kit/.constitution/document/templates/lc.md +47 -0
- package/kit/.constitution/document/templates/lifecycle.md +52 -0
- package/kit/.constitution/document/templates/meeting.md +47 -0
- package/kit/.constitution/document/templates/model.md +55 -0
- package/kit/.constitution/document/templates/oq.md +45 -0
- package/kit/.constitution/document/templates/prd.md +226 -0
- package/kit/.constitution/document/templates/questions.md +75 -0
- package/kit/.constitution/document/templates/rtr.md +61 -0
- package/kit/.constitution/document/templates/rules.md +47 -0
- package/kit/.constitution/document/templates/scn.md +40 -0
- package/kit/.constitution/document/templates/sdd.md +146 -0
- package/kit/.constitution/document/templates/srs.md +149 -0
- package/kit/.constitution/document/templates/structure-codebase.md +129 -0
- package/kit/.constitution/document/templates/structure-document.md +90 -0
- package/kit/.constitution/document/templates/uc.md +69 -0
- package/kit/.constitution/document/templates/ux.md +77 -0
- package/kit/.constitution/document/ux-guide.md +99 -0
- package/kit/.constitution/language-guide.md +69 -0
- package/kit/.constitution/method/README.md +169 -0
- package/kit/.constitution/method/artifact-map.md +155 -0
- package/kit/.constitution/method/portability.md +91 -0
- package/kit/.constitution/method/rationale.md +246 -0
- package/kit/.constitution/method-glossary.md +169 -0
- package/kit/.constitution/project/README.md +68 -0
- package/kit/.constitution/repo-guide.md +97 -0
- package/kit/.constitution/scripts/inventory.py +527 -0
- package/kit/.constitution/scripts/timeline.py +665 -0
- package/kit/.constitution/scripts/validate.py +1579 -0
- package/kit/.constitution/structure-guide.md +202 -0
- package/kit/assets/bmad-custom/bmad-advanced-elicitation.toml +15 -0
- package/kit/assets/bmad-custom/bmad-architecture.toml +31 -0
- package/kit/assets/bmad-custom/bmad-build-auto.toml +10 -0
- package/kit/assets/bmad-custom/bmad-build.toml +52 -0
- package/kit/assets/bmad-custom/bmad-code-review.toml +12 -0
- package/kit/assets/bmad-custom/bmad-correct-course.toml +27 -0
- package/kit/assets/bmad-custom/bmad-deep-recon.toml +11 -0
- package/kit/assets/bmad-custom/bmad-prd.toml +42 -0
- package/kit/assets/bmad-custom/bmad-product-brief.toml +34 -0
- package/kit/assets/bmad-custom/bmad-retrospective.toml +9 -0
- package/kit/assets/bmad-custom/bmad-spec.toml +15 -0
- package/kit/assets/bmad-custom/bmad-ux.toml +19 -0
- package/kit/assets/bmad-custom/config.toml +6 -0
- package/kit/skills/wdi-blueprint/SKILL.md +203 -0
- package/kit/skills/wdi-build/SKILL.md +244 -0
- package/kit/skills/wdi-component/SKILL.md +172 -0
- package/kit/skills/wdi-decision/.gitkeep +0 -0
- package/kit/skills/wdi-decision/SKILL.md +183 -0
- package/kit/skills/wdi-help/.gitkeep +0 -0
- package/kit/skills/wdi-help/SKILL.md +98 -0
- package/kit/skills/wdi-init/SKILL.md +149 -0
- package/kit/skills/wdi-log/SKILL.md +107 -0
- package/kit/skills/wdi-problem/SKILL.md +90 -0
- package/kit/skills/wdi-product/SKILL.md +127 -0
- package/kit/skills/wdi-question/.gitkeep +0 -0
- package/kit/skills/wdi-question/SKILL.md +88 -0
- package/kit/skills/wdi-reconcile/.gitkeep +0 -0
- package/kit/skills/wdi-reconcile/SKILL.md +146 -0
- package/kit/skills/wdi-report/SKILL.md +205 -0
- package/kit/skills/wdi-review/SKILL.md +118 -0
- package/kit/skills/wdi-systematic-debugging/SKILL.md +193 -0
- package/kit/skills/wdi-systematic-debugging/references/condition-based-waiting.md +115 -0
- package/kit/skills/wdi-systematic-debugging/references/defense-in-depth.md +122 -0
- package/kit/skills/wdi-systematic-debugging/references/find-polluter.sh +72 -0
- package/kit/skills/wdi-systematic-debugging/references/root-cause-tracing.md +169 -0
- package/kit/skills/wdi-ux/SKILL.md +145 -0
- package/kit-overlay/AGENTS.md +196 -0
- package/kit-overlay/README.md +66 -0
- package/kit-overlay/constitution.md +135 -0
- package/kit-overlay/portability.md +91 -0
- package/kit-overlay/repo-guide.md +97 -0
- package/lib/agents-block.mjs +52 -0
- package/lib/identity.mjs +65 -0
- package/package.json +37 -0
- package/scaffold/.control/decisions/.gitkeep +0 -0
- package/scaffold/.control/generated/.gitkeep +2 -0
- package/scaffold/.control/meetings/.gitkeep +0 -0
- package/scaffold/.control/memlog/.gitkeep +0 -0
- package/scaffold/.control/product-glossary.md +21 -0
- package/scaffold/.control/project-non-technical-log.md +23 -0
- package/scaffold/.control/questions/answered.md +11 -0
- package/scaffold/.control/questions/assumptions.md +15 -0
- package/scaffold/.control/questions/blocking.md +21 -0
- package/scaffold/.control/questions/external.md +11 -0
- package/scaffold/.control/registry/components.yaml +21 -0
- package/scaffold/.control/registry/decisions.yaml +6 -0
- package/scaffold/.control/registry/defects.yaml +3 -0
- package/scaffold/.control/registry/index.yaml +46 -0
- package/scaffold/.control/registry/requirements.yaml +15 -0
- package/scaffold/.control/registry/risks.yaml +5 -0
- package/scaffold/.control/registry/usecases.yaml +6 -0
- package/scaffold/.control/registry/waves.yaml +5 -0
- package/scaffold/.control/structure-codebase.md +19 -0
- package/scaffold/.control/structure-document.md +25 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
status: Accepted
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# BMad Skill Register
|
|
6
|
+
|
|
7
|
+
**Loaded when:** deciding which BMad skill a piece of work needs, or checking what one writes
|
|
8
|
+
|
|
9
|
+
This used to be the full catalogue of all 59 installed BMad skills. **That catalogue is retired.** It was a
|
|
10
|
+
copy of somebody else's inventory, it went stale on every BMad update, and nothing in this method read more
|
|
11
|
+
than a dozen of its rows. What binds is the division of labour below; for anything about a BMad skill this
|
|
12
|
+
method does not invoke, ask `bmad-help`, which reads BMad's own documentation.
|
|
13
|
+
|
|
14
|
+
## Who writes what
|
|
15
|
+
|
|
16
|
+
| Artifact | Written by | Wrapped in |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| Product brief | `bmad-product-brief` | `wdi-problem` |
|
|
19
|
+
| PRD | `bmad-prd` | `wdi-product` |
|
|
20
|
+
| UX — `EXPERIENCE.md` + `DESIGN.md` | `bmad-ux` | `wdi-ux` |
|
|
21
|
+
| Architecture spine + the C4 set | `bmad-architecture` | `wdi-blueprint` intent `platform` |
|
|
22
|
+
| **UC catalogue · actors · entities · business rules** | **nothing in BMad** | `wdi-blueprint` writes it itself |
|
|
23
|
+
| **SRS and all of `.what/<pc>/`** | **nothing in BMad** | `wdi-component` writes it itself |
|
|
24
|
+
| **SDD and all of `.how/<pc>/`** | **nothing in BMad** | `wdi-component` writes it itself |
|
|
25
|
+
| `SPEC.md` + `stories.yaml` | `bmad-spec` | `wdi-build` |
|
|
26
|
+
| Code | `bmad-build` · `bmad-build-auto` | `wdi-build` |
|
|
27
|
+
| Retrospective | `bmad-retrospective` | `wdi-build` |
|
|
28
|
+
| Document review | `bmad-review` | `wdi-review` |
|
|
29
|
+
| Course correction | `bmad-correct-course` | `wdi-decision` |
|
|
30
|
+
|
|
31
|
+
**The three bold rows are why this method exists.** BMad stops at the promise and starts again at the
|
|
32
|
+
mechanism, and every behaviour in between had no author. Three consequences attach to those artifacts and
|
|
33
|
+
MUST be handled deliberately rather than discovered: no `doc_standards` fires a review, no memlog is born on
|
|
34
|
+
its own, and no template enforces itself.
|
|
35
|
+
|
|
36
|
+
## No BMad skill is invoked directly
|
|
37
|
+
|
|
38
|
+
Every one above has a wrapper, and the wrapper is what checks position, verifies the result against the
|
|
39
|
+
guide, and lands the memlog. Routing past it produces an artifact nothing verifies.
|
|
40
|
+
|
|
41
|
+
**One exception, and it is narrow:** `bmad-build` MAY be invoked directly on the Fast Path. A Fast Path that
|
|
42
|
+
turns out to touch an `FR` MUST stop and become a wave `S`, which puts it back inside `wdi-build`.
|
|
43
|
+
|
|
44
|
+
## What is available but writes nothing
|
|
45
|
+
|
|
46
|
+
| Skill | Use |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `bmad-advanced-elicitation` · `bmad-party-mode` | Thinking aids. They produce no artifact and MUST NOT be treated as authors |
|
|
49
|
+
| `bmad-deep-recon` | Research, before a brief rests on outside data. Its output stays in `_bmad-output/` permanently and MUST NOT be folded into the brief |
|
|
50
|
+
| `bmad-code-review` | The two-reviewer panel over code, dispatched by `wdi-build`. Not for documents |
|
|
51
|
+
| `bmad-help` | Questions about BMad itself. It MUST NOT be used to answer "where am I" — that is `wdi-help` |
|
|
52
|
+
|
|
53
|
+
## What is NOT USED, and MUST NOT be
|
|
54
|
+
|
|
55
|
+
| Skill | Why |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `bmad-create-epics-and-stories` · `bmad-sprint-planning` · `bmad-sprint-status` | They belong to the sprint route, which keeps status in a hand-edited file. This method reads status from story-file frontmatter — `bmad-guide.md` owns the reasoning |
|
|
58
|
+
| `bmad-create-story` · `bmad-dev-story` · `bmad-quick-dev` · `bmad-dev-auto` | Deprecated in BMad itself; `bmad-build` and `bmad-build-auto` replace them |
|
|
59
|
+
| `bmad-editorial-review*` · `bmad-review-*` | Shims onto `bmad-review` lenses. Ask for the lens, not the shim |
|
|
60
|
+
| `bmad-document-project` · `bmad-generate-project-context` | Forward to `bmad-project-context`. This repo's agent instructions are maintained by hand |
|
|
61
|
+
| Any skill named as a **gate condition** | A gate is passed by its checklist and its validators, never by a skill having run |
|
|
62
|
+
|
|
63
|
+
## The class that decides where output lands
|
|
64
|
+
|
|
65
|
+
`bmad-guide.md` owns the class definitions; what matters here is that **class B** exists because some skills
|
|
66
|
+
write several things at once that belong to different layers. `bmad-ux` is the case: `EXPERIENCE.md` is a
|
|
67
|
+
promise and `DESIGN.md` is a build detail, and no configuration can send them to two places. Its output
|
|
68
|
+
lands in a neutral folder first, and `wdi-ux` places it.
|
|
69
|
+
|
|
70
|
+
Which skill lands which output is the ownership table in `corpus-guide.md`, and it MUST NOT be duplicated
|
|
71
|
+
here.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
status: Accepted
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Brief Guide
|
|
6
|
+
|
|
7
|
+
**Loaded when:** writing, updating, or validating the product brief
|
|
8
|
+
|
|
9
|
+
The brief is the G1 artifact. It answers WHY — what problem exists, whose it is, and why it is worth
|
|
10
|
+
building. Its shape lives in `templates/brief.md`; the rules that shape MUST obey live here.
|
|
11
|
+
|
|
12
|
+
## Home and life cycle
|
|
13
|
+
|
|
14
|
+
- The brief MUST live at `.what/_product-brief/brief.md`, with `addendum.md` beside it. Both
|
|
15
|
+
filenames are fixed by `bmad-product-brief` and MUST NOT be expected to change; only the folder is
|
|
16
|
+
configurable.
|
|
17
|
+
- One brief per product, spanning every release. A second product MUST get its own repository — the
|
|
18
|
+
singleton is what makes "what did we set out to solve" answerable at all.
|
|
19
|
+
- The brief is amended, never re-run into a second folder. `run_folder_pattern` is a constant for
|
|
20
|
+
exactly this reason.
|
|
21
|
+
- The memlog MUST be written to `.control/memlog/brief.md` via `memlog.py --path`. `--workspace`
|
|
22
|
+
MUST NOT be used — it would drop a `.memlog.md` inside `.what/`, and no memlog belongs in the
|
|
23
|
+
corpus.
|
|
24
|
+
|
|
25
|
+
## Required sections
|
|
26
|
+
|
|
27
|
+
`templates/brief.md` carries the shape. Its preamble invites dropping sections that do not earn
|
|
28
|
+
their place; that invitation MUST NOT be applied to the eight below. Everything else in the template
|
|
29
|
+
MAY be dropped.
|
|
30
|
+
|
|
31
|
+
| Section | Why it cannot be dropped |
|
|
32
|
+
|---|---|
|
|
33
|
+
| The Problem | The gate decides on this. Without it there is nothing to approve |
|
|
34
|
+
| Who This Serves | Names who the problem belongs to |
|
|
35
|
+
| Goals | `BG-N` is the first link of the traceability chain; without it the chain has no root |
|
|
36
|
+
| Success Criteria | The measure that makes "done" checkable |
|
|
37
|
+
| Scope In / Scope Out | The boundary the PRD is later held against |
|
|
38
|
+
| Constraints | What design MUST NOT trade away |
|
|
39
|
+
| Assumptions | What the brief would be wrong without |
|
|
40
|
+
| Prerequisites | What blocks work before it starts |
|
|
41
|
+
|
|
42
|
+
## Decision rules
|
|
43
|
+
|
|
44
|
+
- The brief MUST name exactly one problem, one **primary** user, and one measure of success. Other
|
|
45
|
+
users and stakeholders are listed as secondary, not ranked away. If the primary cannot be chosen,
|
|
46
|
+
discovery is not finished and the gate MUST NOT open.
|
|
47
|
+
- Every user and stakeholder who touches the product MUST appear in the table, including those who
|
|
48
|
+
never open it — whoever pays for it, approves it, or is accountable for it.
|
|
49
|
+
- Goals MUST be numbered `BG-1`, `BG-2`, … and MUST NOT be numbered `G1`, `G2` — `G1`–`G5` name the
|
|
50
|
+
five gates. `BG` IDs are cited downstream and MUST stay stable once written.
|
|
51
|
+
- Scope Out MUST be written as items. Leaving it to be inferred from absence defeats its only
|
|
52
|
+
purpose, which is naming what someone will otherwise assume is coming.
|
|
53
|
+
- Per-release MVP scope belongs to the PRD, not here. This section states the product boundary.
|
|
54
|
+
|
|
55
|
+
## The three product-level sections
|
|
56
|
+
|
|
57
|
+
BMad has no home for these; they exist because of that gap, and each has a rule about where it goes
|
|
58
|
+
when it stops being a statement.
|
|
59
|
+
|
|
60
|
+
| Section | Boundary | When it moves |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| Constraints | What is fixed before design starts. Technical constraints that only shape implementation belong in `addendum.md` | A constraint that emerges from a design decision becomes `AD-N` in the spine and MUST NOT be appended here later |
|
|
63
|
+
| Assumptions | What is believed but unverified, stated so it could be proven false | An assumption that starts to wobble MUST become a row in `.control/registry/risks.yaml` with an owner |
|
|
64
|
+
| Prerequisites | What MUST exist or be granted before work can start | Any prerequisite not yet satisfied MUST have a row in `.control/questions/external.md` naming who is being waited on and by when |
|
|
65
|
+
|
|
66
|
+
An assumption nobody would act differently about is not worth listing.
|
|
67
|
+
|
|
68
|
+
## No Product Component list
|
|
69
|
+
|
|
70
|
+
The brief MUST NOT carry one, and MUST NOT fill `product_components`. The slicing is born at the
|
|
71
|
+
**tail of G2** through `wdi-init` intent `component`, which reads the brief and every PRD and
|
|
72
|
+
registers what the owner accepts. A list written at G1 is guessed before there is anything to guess
|
|
73
|
+
from, and every later gate inherits the guess.
|
|
74
|
+
|
|
75
|
+
## Raw material
|
|
76
|
+
|
|
77
|
+
- Research, brainstorming, forge, and PRFAQ output MUST stay in `_bmad-output/`. It MUST NOT be
|
|
78
|
+
folded into the brief, and MUST NOT be promoted into `.what/`.
|
|
79
|
+
- A `DEC-` or the PRD cites it by path instead. `_bmad-output/` is committed, so the path is stable.
|
|
80
|
+
- Those run folders MUST NOT be deleted **while an `update` intent still needs them** — it re-reads the
|
|
81
|
+
original inputs. Once what they were read for is written down, they are retired under the three conditions
|
|
82
|
+
in `corpus-guide.md`, and that retirement is a `DEC-`. "Never deleted" was never the rule; needing them
|
|
83
|
+
was.
|
|
84
|
+
|
|
85
|
+
## Passing G1
|
|
86
|
+
|
|
87
|
+
- Dying cheap is a pass. A brief concluding the idea is not worth building is a valid G1 outcome,
|
|
88
|
+
and the most profitable one.
|
|
89
|
+
- The brief MUST have been through `bmad-review` lenses structure + prose before it reaches the
|
|
90
|
+
gate. Gate time is for deciding, not for catching mistakes. This one fires on its own — it is the
|
|
91
|
+
*Polish* step of `bmad-product-brief`, driven by `doc_standards`, and nobody invokes it. Verifying
|
|
92
|
+
that it actually ran is check 9 in `wdi-problem`.
|
|
93
|
+
- Invoke through `wdi-problem`, not `bmad-product-brief` directly — the wrapper is what checks the
|
|
94
|
+
rules on this page.
|
|
@@ -0,0 +1,341 @@
|
|
|
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
|
+
|
|
27
|
+
`.control/` is the value of `{project_knowledge}` in BMad's configuration. There is no `docs/`.
|
|
28
|
+
|
|
29
|
+
## The placement test
|
|
30
|
+
|
|
31
|
+
One question decides everything: **is this file still correct after its wave has passed?**
|
|
32
|
+
|
|
33
|
+
Yes → the corpus. No → `_bmad-output/`.
|
|
34
|
+
|
|
35
|
+
`_bmad-output/` is committed but **not curated**. Committing it is what makes citation by path stable, so a
|
|
36
|
+
decision or a PRD MAY point into it. Research, brainstorming, forge, and PRFAQ reports are never promoted.
|
|
37
|
+
|
|
38
|
+
A run folder MUST NOT be deleted **while anything still needs it** — the `update` intents re-read the original
|
|
39
|
+
inputs in place. "Never deleted" is not the rule; the rule is a **retirement condition**, and it is below.
|
|
40
|
+
|
|
41
|
+
## Who lands what
|
|
42
|
+
|
|
43
|
+
There is no separate placement skill. A skill lands the output of the layer **it owns**, and the landing is
|
|
44
|
+
part of producing it — never a follow-up someone else performs.
|
|
45
|
+
|
|
46
|
+
| Output | Permanent home | Owner |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| The spine | `.how/_platform/ARCHITECTURE-SPINE.md` | `wdi-blueprint` |
|
|
49
|
+
| 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` |
|
|
50
|
+
| each container in C4 L2 | a `container` entry in `components.yaml` | `wdi-blueprint` |
|
|
51
|
+
| **The three inventories** | `.how/_platform/inventory-db.md` · `inventory-api.md` · `inventory-screen.md` | `wdi-blueprint` |
|
|
52
|
+
| The error envelope, and anything else defined once for the product | `.how/_platform/cross-cutting.md` | `wdi-blueprint` |
|
|
53
|
+
| UC catalogue · Actor Register · domain model | `.what/<pc>/SRS-<pc>.md` · `03-domain/domain-model.md` | `wdi-blueprint` |
|
|
54
|
+
| Business rules binding more than one PC | `.what/business-rules.md` | `wdi-blueprint` |
|
|
55
|
+
| A domain term | `.control/product-glossary.md` | `wdi-blueprint` |
|
|
56
|
+
| Full UC flows · local rules · state machines · scenarios | `.what/<pc>/` slots `02`–`05` | `wdi-component` intent `behaviour` |
|
|
57
|
+
| The SDD and its slots `02`–`06` | `.how/<pc>/` | `wdi-component` intent `design` |
|
|
58
|
+
| each Boundary and Control object drawn | an `LC` in `components.yaml` | `wdi-component` intent `design` |
|
|
59
|
+
| `EXPERIENCE.md` | `.what/<pc>/04-usecases/` | `wdi-ux` |
|
|
60
|
+
| `DESIGN.md` | `.how/<pc>/01-ux/` | `wdi-ux` |
|
|
61
|
+
| tokens and base components | `.how/_platform/design-system.md` | `wdi-ux` |
|
|
62
|
+
| each screen in `DESIGN.md` | an `LC` of type `ui-screen` in `components.yaml` | `wdi-ux` |
|
|
63
|
+
| `RETROSPECTIVE.md` | `RTR-<wave>.md` in `.control/reports/` | `wdi-build`, at wave close |
|
|
64
|
+
| `test-summary.md` | test names → `waves.yaml` | `wdi-build` |
|
|
65
|
+
| `stack.md` · `conventions.md` · `brownfield.md` | merged into `.constitution/codebase/*-guide.md` | `wdi-build`, at wave close |
|
|
66
|
+
| A sprint change proposal | a `DEC-` of `type: course-correction` | `wdi-decision` |
|
|
67
|
+
| The registry rows and skeletons a new PC needs | `components.yaml` · `.what/<pc>/` · `.how/<pc>/` | `wdi-init` intent `component` |
|
|
68
|
+
| `platform_owns` — an entity no component's promise explains | `components.yaml`, plus its description in `cross-cutting.md` | `wdi-blueprint` |
|
|
69
|
+
| The two structure maps | `.control/structure-codebase.md` · `structure-document.md` | `wdi-init` intent `structure` |
|
|
70
|
+
| An open question | `.control/questions/` — one of four files | `wdi-question` |
|
|
71
|
+
| A decision | `.control/decisions/DEC-NNN-<slug>.md` | `wdi-decision` |
|
|
72
|
+
| Minutes · a non-technical fact | `.control/meetings/` · `.control/project-non-technical-log.md` | `wdi-log` |
|
|
73
|
+
|
|
74
|
+
- A skill MUST NOT write into a layer it does not own.
|
|
75
|
+
- Registry conversion is part of landing, not a follow-up. A screen that lands in `01-ux/` without its
|
|
76
|
+
`components.yaml` entry has been half-landed, and V12 catches it **at wave close** — which is the
|
|
77
|
+
right moment to be caught, and a bad moment to be surprised.
|
|
78
|
+
- Content MUST NOT be edited while it is being landed. If it has to change to fit its new home, that is a
|
|
79
|
+
separate act — say so and stop. Splitting one output across the homes its row names is not editing.
|
|
80
|
+
- The C4 set's target files already exist and are **living**. Their owner MUST amend, MUST NOT overwrite; when
|
|
81
|
+
the incoming set contradicts an annotation already there, it MUST stop and report the finding.
|
|
82
|
+
- Nothing MAY be landed into a wave that is already closed. The wave is reopened through `wdi-build`, or the
|
|
83
|
+
gap is recorded as an open question.
|
|
84
|
+
- An output with **no row** in this table MUST NOT be given a guessed home. It stays in `_bmad-output/`, and
|
|
85
|
+
`wdi-reconcile` reports it — an output with no home is a gap in the method, and MUST surface as one.
|
|
86
|
+
|
|
87
|
+
## Landing that MUST be confirmed first
|
|
88
|
+
|
|
89
|
+
Most landings are mechanical and MAY be done without asking. Some change what other people already agreed to,
|
|
90
|
+
and those MUST be put to the owner before the file is written — not reported afterwards. The line is drawn by
|
|
91
|
+
**what the landing can invalidate**, never by how much text moves:
|
|
92
|
+
|
|
93
|
+
| | Light — act, then report | Heavy — confirm, then act |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| Layer | Stays inside the layer the skill owns | Crosses into another layer's consequences |
|
|
96
|
+
| ID chain | No `BG`/`CAP`/`FR`/`NFR`/`UC`/`LC` id is born, renamed, or retired | Any of them is |
|
|
97
|
+
| Depth and risk | `mode` and `risk_accepted` unchanged | Either would have to change |
|
|
98
|
+
| Existing text | Adds, or replaces content the same skill wrote | Overwrites or contradicts what another skill or a human wrote |
|
|
99
|
+
| Registry | Adds the entry its own output requires | Removes or re-points an entry something else already cites |
|
|
100
|
+
|
|
101
|
+
Any one heavy row makes the whole landing heavy. When confirmation cannot be obtained now, the landing MUST
|
|
102
|
+
NOT be split into a light half that goes ahead — half-landed output looks distributed and is worse than output
|
|
103
|
+
that waited.
|
|
104
|
+
|
|
105
|
+
A skill MUST NOT lighten a landing by narrowing what it writes. Dropping the contentious half to stay under
|
|
106
|
+
the bar is the same change, made invisible.
|
|
107
|
+
|
|
108
|
+
## Product Component — the naming and proposal rule
|
|
109
|
+
|
|
110
|
+
This rule lives here, beside the definition, and **not inside a skill**. If it lived in one skill, the second
|
|
111
|
+
skill that needed it would copy it, and the two copies would drift.
|
|
112
|
+
|
|
113
|
+
> The name of a Product Component MUST be a surface a user could name. A name that states a layer, a service,
|
|
114
|
+
> or a pattern MUST be rejected at proposal time, not corrected later. Additions, changes, and removals MUST
|
|
115
|
+
> be presented separately, each with the `FR` behind it.
|
|
116
|
+
|
|
117
|
+
A PC MUST NOT be created because a folder would look tidy. A PC that no `FR` points at is a folder with
|
|
118
|
+
nothing inside it.
|
|
119
|
+
|
|
120
|
+
Birthing is cheap and retiring is not: retiring or renaming a PC that already carries an SRS goes through
|
|
121
|
+
`wdi-decision`, never through the skill that births one.
|
|
122
|
+
|
|
123
|
+
## Product Component, Logical Component, container, `_platform`
|
|
124
|
+
|
|
125
|
+
Four words that are easy to blur and MUST NOT be:
|
|
126
|
+
|
|
127
|
+
| Term | Is | Registered in |
|
|
128
|
+
|---|---|---|
|
|
129
|
+
| **Product Component** | A surface a user can name — what they came to do | `product_components` |
|
|
130
|
+
| **Logical Component** | A unit inside the build — a screen, a service, an adapter, an entity | `logical_components` |
|
|
131
|
+
| **Container** | Something that runs or ships on its own | `containers` |
|
|
132
|
+
| **`_platform`** | **Not a component at all** — the home for what belongs to no Product Component | `platform_owns`, and the `_platform/` folder |
|
|
133
|
+
|
|
134
|
+
PC and container are **crossing axes**, not a hierarchy: one PC MAY be delivered by several containers, and one
|
|
135
|
+
container MAY serve several PCs. An `LC` names its container in a `container:` field, which is what lets
|
|
136
|
+
`structure-codebase.md` be checked against the registry rather than trusted.
|
|
137
|
+
|
|
138
|
+
## `_platform` — what belongs to no Product Component
|
|
139
|
+
|
|
140
|
+
`_platform` is **not a Product Component**, and it MUST NOT be registered as one. It fails the naming test on
|
|
141
|
+
purpose: nobody came to the product to use "the platform". It therefore carries **no `mode`, no
|
|
142
|
+
`risk_accepted`, no SRS, no SDD, and no G4** — its documents are the spine, the C4 set, `cross-cutting.md`,
|
|
143
|
+
and the three inventories, and all of those exist at every `mode`.
|
|
144
|
+
|
|
145
|
+
What it does carry is **ownership**. `_platform` is a legitimate value in **every** position that asks
|
|
146
|
+
*"which component owns this"* — the `platform_owns:` list for domain entities, the owning-component column
|
|
147
|
+
of any inventory row, an `LC`'s `component:` field, and any such column a later artifact adds. One test,
|
|
148
|
+
one cost, everywhere; there is no per-artifact special case to negotiate, and a new kind of thing arriving
|
|
149
|
+
next year needs no new discussion.
|
|
150
|
+
|
|
151
|
+
The test, and both halves MUST hold:
|
|
152
|
+
|
|
153
|
+
> Something belongs to `_platform` when **no single Product Component's promise is the reason it exists**,
|
|
154
|
+
> *and* more than one component reads, writes, or depends on it.
|
|
155
|
+
|
|
156
|
+
Four kinds qualify today and the list is open: **data** (a product-wide setting, the trace of a shared
|
|
157
|
+
outbound channel) · **endpoint** (`/health`, `robots.txt` — plumbing no `FR` promises and none should) ·
|
|
158
|
+
**job** (a scheduled cleaner whose data belongs to a component but whose machinery does not) · **screen**
|
|
159
|
+
(none yet).
|
|
160
|
+
|
|
161
|
+
Failing either half, it belongs to a Product Component — and the component is found by asking which `FR`
|
|
162
|
+
would have to be withdrawn for the entity to stop being needed. Two examples of the trap, both real:
|
|
163
|
+
|
|
164
|
+
| Entity | Looks platform-shaped | Actually |
|
|
165
|
+
|---|---|---|
|
|
166
|
+
| `member_activity_events` | member-wide telemetry, several components write it | **`referral`** — `FR-65` promises a Sponsor sees the login and click counts of their downline. One `FR` explains it |
|
|
167
|
+
| `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 |
|
|
168
|
+
|
|
169
|
+
**One guard, and it is what stops this becoming a drawer:** everything `_platform` owns — in any position —
|
|
170
|
+
MUST be described under `## Milik platform` in `cross-cutting.md`, with its kind and the shape every toucher
|
|
171
|
+
obeys. A platform that owns something documents it. V21 checks it, and skips only while that section has not
|
|
172
|
+
been born at G3.
|
|
173
|
+
|
|
174
|
+
That guard is the whole reason `_platform` can be a general answer rather than an escape hatch: reaching for
|
|
175
|
+
it costs a row somebody has to write, so it stays cheaper to find the real owner when one exists.
|
|
176
|
+
|
|
177
|
+
`_platform` has no `FR`, so an `FR` that writes something platform-owned has nothing to point `defers_to` at,
|
|
178
|
+
and MUST NOT be asked for one. What replaces "one writer" there is **one documented shape**: it is written the
|
|
179
|
+
way `cross-cutting.md` says, and a component wanting it written differently is proposing a change to that file.
|
|
180
|
+
|
|
181
|
+
Platform ownership sits with `wdi-blueprint` intent `platform`, beside the rest of `_platform/`. `wdi-init`
|
|
182
|
+
intent `component` MAY name a candidate and MUST NOT claim one.
|
|
183
|
+
|
|
184
|
+
**A decision the pattern cannot derive lives in the artifact it governs.** An inventory row owned by
|
|
185
|
+
`_platform`, and a route that is a *state* of another screen rather than a screen of its own, are both
|
|
186
|
+
judgements — so both are declared in that inventory's own frontmatter (`platform_rows:` and `states:`) and
|
|
187
|
+
survive every re-derivation. Putting either outside the file means the next derivation silently deletes the
|
|
188
|
+
owner's decision.
|
|
189
|
+
|
|
190
|
+
## Two axes inside `.what/`
|
|
191
|
+
|
|
192
|
+
| | `_prd/<initiative>/` | `<pc>/` |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| Slices by | **Initiative** — one functional area | **Space** — one Product Component |
|
|
195
|
+
| Answers | What is promised to a user | What this component can do |
|
|
196
|
+
| Written for | Outside readers — client, sponsor | People building the system |
|
|
197
|
+
|
|
198
|
+
Both are living. What separates them is **promise versus behaviour**, not lifetime. One functional area MAY
|
|
199
|
+
span several components, and one component MAY serve several PRDs, so neither can absorb the other.
|
|
200
|
+
|
|
201
|
+
**Time is not a folder axis.** Release lives in `CAP.target_release` and in `waves.yaml`.
|
|
202
|
+
|
|
203
|
+
## Slot numbering means two different things
|
|
204
|
+
|
|
205
|
+
| Layer | Slots | The number means |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `.what/<pc>/` | `02-rules` · `03-domain` · `04-usecases` · `05-scenarios` | **Reading order** — its rules → the things → how it is used → its branches |
|
|
208
|
+
| `.how/<pc>/` | `01-ux` … `06-flows` | **ABCE classification** — Boundary, Control, Entity, behaviour. Not a reading order |
|
|
209
|
+
|
|
210
|
+
Reading one as the other is the most common misfiling in this corpus, and it is silent: the file lands in a
|
|
211
|
+
plausible-looking folder and is simply never found again.
|
|
212
|
+
|
|
213
|
+
`.what/<pc>/01-requirements/` is **repealed** — permanently empty, because `FR` live in the PRD and the SRS
|
|
214
|
+
cites them. `supplements/` beside either kernel is repealed with the `ANX-` concept.
|
|
215
|
+
|
|
216
|
+
## Splitting slots
|
|
217
|
+
|
|
218
|
+
- A slot MAY stay empty. Content SHOULD stay in the kernel until that file grows past roughly 400 lines — a
|
|
219
|
+
suggestion, not a threshold, and a file that is clearer split earlier MAY be split earlier.
|
|
220
|
+
- The first slot to be split SHOULD be `04-usecases/` — it is always the largest part.
|
|
221
|
+
- One use case with many branches MUST put its branches in `05-scenarios/` rather than growing its own file.
|
|
222
|
+
- The `Actor Register` MUST stay in the SRS kernel. It is the SSOT the SDD mirrors, and it is short.
|
|
223
|
+
|
|
224
|
+
## Document codes
|
|
225
|
+
|
|
226
|
+
| Code | Is |
|
|
227
|
+
|---|---|
|
|
228
|
+
| `BG-` `CAP-` `FR-` `NFR-` `UJ-` `UC-` | The traceability chain, allocated from `requirements.yaml` and `usecases.yaml` |
|
|
229
|
+
| `AD-` | An invariant in the architecture spine — a living rule, edited in place |
|
|
230
|
+
| `DEC-` | A decision — an event, frozen when `applied`, only superseded |
|
|
231
|
+
| `LC-` | A Logical Component |
|
|
232
|
+
| `OQ-` `RTR-` | An open question · an archived retrospective |
|
|
233
|
+
| `BUG-` `HOT-` | A defect · a hotfix |
|
|
234
|
+
| `NT-` | A non-technical fact |
|
|
235
|
+
|
|
236
|
+
**Retired, and MUST NOT be coined again:** `ADR-` (renamed to `DEC-` on 2026-08-18; the old prefix inside a
|
|
237
|
+
document frozen before that date is an alias for the same number) · `ANX-` (zero annexes were ever born) ·
|
|
238
|
+
`SCP-` (a course correction is a `DEC-`) · `BRS-`, `PFQ-`, `RES-` (exploration output is never promoted).
|
|
239
|
+
|
|
240
|
+
IDs are allocated **globally** and never restart per document, per component, or per release.
|
|
241
|
+
|
|
242
|
+
### A record of the past MUST NOT be rewritten to match the present
|
|
243
|
+
|
|
244
|
+
A retired name appearing in a document that **records what happened** is a fact about the past, not
|
|
245
|
+
drift, and a sweep MUST NOT rename it. Four kinds, and all four are legitimate:
|
|
246
|
+
|
|
247
|
+
| Where | What it says | Why it stays |
|
|
248
|
+
|---|---|---|
|
|
249
|
+
| `.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 |
|
|
250
|
+
| `.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 |
|
|
251
|
+
| `.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 |
|
|
252
|
+
| `.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 |
|
|
253
|
+
|
|
254
|
+
The test is one question: **does this sentence describe what happened, or state what holds?** Describes
|
|
255
|
+
→ leave it. States → sweep it.
|
|
256
|
+
|
|
257
|
+
That distinction is why a sweep can be run repeatedly without churn. Without it, every pass rewrites
|
|
258
|
+
the same three dozen historical files and the diff stops carrying information.
|
|
259
|
+
|
|
260
|
+
File naming that must survive every OS is governed by `structure-guide.md` and MUST NOT be restated here.
|
|
261
|
+
|
|
262
|
+
## `.constitution/project/` — this product's custom rules
|
|
263
|
+
|
|
264
|
+
The rest of `.constitution/` **belongs to the method**: it ships in the `wdi-method` package and is
|
|
265
|
+
**overwritten** on every `update`. This folder is the only one that is not. `update` seeds it once and
|
|
266
|
+
never writes over it again, and `promote` **skips it**, so a rule that names a client cannot reach the
|
|
267
|
+
public package.
|
|
268
|
+
|
|
269
|
+
| Goes here | Does not, and its home |
|
|
270
|
+
|---|---|
|
|
271
|
+
| A review policy a client requires | product / client name → `index.yaml` `product:` |
|
|
272
|
+
| A process rule that came from a contract | code conventions → `codebase/*-guide.md` |
|
|
273
|
+
| A policy that differs from the method default | scope and ownership → `constitution.md` Art. 1, 2, 5 |
|
|
274
|
+
| A prohibition specific to this domain | agent instructions → `AGENTS.md`, outside the marked block |
|
|
275
|
+
|
|
276
|
+
**A generic rule MUST NOT be moved here.** If it holds in any project it belongs to the package — fix
|
|
277
|
+
it there, then `promote`. Using this room to bypass the package is how a method stops being generic
|
|
278
|
+
with nobody deciding it, and **an empty room is a valid state**: filling it so that it gets used is the
|
|
279
|
+
very failure this rule prevents.
|
|
280
|
+
|
|
281
|
+
Frontmatter is required and **V27** checks it: `scope: project` · a one-line `purpose:`. A file MAY
|
|
282
|
+
narrow or add with nothing further; to **contradict** a generic rule it MUST name that rule in
|
|
283
|
+
`overrides:` and carry `decision:` naming the `DEC-` that decided it. A method that can be contradicted
|
|
284
|
+
without a decision stops being trustworthy in the next repo.
|
|
285
|
+
|
|
286
|
+
**Whole files, not marked blocks.** `AGENTS.md` uses a marked block because it is one file;
|
|
287
|
+
`.constitution/` has fifty-odd, and blocks inside them would make `update` perform surgery in every
|
|
288
|
+
file — one broken marker and either the product's rule is erased or the generic rule freezes.
|
|
289
|
+
|
|
290
|
+
## Documents that predate the method
|
|
291
|
+
|
|
292
|
+
A repository that already had documentation keeps it in `_bmad-output/prior-knowledge/`. It follows the same
|
|
293
|
+
rules as the rest of `_bmad-output/`: committed, never curated, cited by path, never deleted.
|
|
294
|
+
|
|
295
|
+
The sorting happens once, at install, and the test is a single question: **is this file already the artifact
|
|
296
|
+
one corpus slot asks for, one file for one slot?** Yes → straight into that slot, carrying a provenance line
|
|
297
|
+
naming the gate that ratifies it. No → `prior-knowledge/`.
|
|
298
|
+
|
|
299
|
+
**A file in `prior-knowledge/` MUST NOT be copied into `.what/` or `.how/` afterwards.** It enters the corpus
|
|
300
|
+
only through the skill that owns the slot, which reads it as input. This is the rule the whole arrangement
|
|
301
|
+
exists for: moving a file is always cheaper than running the stage that should have produced it, so without a
|
|
302
|
+
rule the move always wins — and what lands then has no author, no input trail, and no gate behind it.
|
|
303
|
+
|
|
304
|
+
### Retiring `prior-knowledge/`, and the condition that makes it safe
|
|
305
|
+
|
|
306
|
+
A prior document is **input**, and input stops being needed once what it was read for is written down. Three
|
|
307
|
+
conditions, and **all three MUST hold** before the folder is deleted:
|
|
308
|
+
|
|
309
|
+
1. **Every promise it carried is mapped.** The old numbering has a complete old → new table, and that table
|
|
310
|
+
lives in the `addendum.md` beside the PRD it maps into — **not** in `prior-knowledge/`, precisely so the
|
|
311
|
+
source can be retired without taking the map with it.
|
|
312
|
+
2. **Every live citation into it has been re-pointed or dropped.** A glossary entry, a `risk_note`, an
|
|
313
|
+
`enforced_by` — anything that *states what holds*. Where the fact has a home in code or in `.control/`, the
|
|
314
|
+
citation points there instead.
|
|
315
|
+
3. **The retirement is recorded as a `DEC-`.** Deleting source material is expensive to reverse, and the
|
|
316
|
+
answer to *why is it gone* is not readable from the code.
|
|
317
|
+
|
|
318
|
+
**A citation left inside a record of the past is not condition 2's business.** A `DEC-`'s Trace naming the
|
|
319
|
+
document it was derived from, or a memlog naming what a run read, describes what happened — and the rule above
|
|
320
|
+
on records of the past applies. Those citations dangle by design, and `wdi-reconcile`'s Evidence check MUST NOT
|
|
321
|
+
report them: what makes it harmless is that the substance is already written into the document doing the
|
|
322
|
+
citing, so the path is provenance rather than a dependency.
|
|
323
|
+
|
|
324
|
+
The same three conditions govern `.work/`, with one difference: nothing there was ever authority, so condition
|
|
325
|
+
1 is usually already met.
|
|
326
|
+
|
|
327
|
+
Two consequences that MUST be expected rather than discovered:
|
|
328
|
+
|
|
329
|
+
- Internal numbering inside a prior document — `FR-3`, `§7` — is **not** a corpus ID. A mapping table MAY be
|
|
330
|
+
written once, and it lives in `prior-knowledge/`, never in `.control/`.
|
|
331
|
+
- A file placed straight into a slot MUST lose any claim of authority it makes about itself. In the corpus,
|
|
332
|
+
authority comes from the layer and the gate.
|
|
333
|
+
|
|
334
|
+
## Rules
|
|
335
|
+
|
|
336
|
+
- A file MUST NOT be moved between layers by a skill that owns neither end. Anything else is a misplacement,
|
|
337
|
+
and MUST be reported rather than fixed.
|
|
338
|
+
- A fact MUST have exactly one home. When two documents state the same thing, one of them MUST become a
|
|
339
|
+
reference — and the copy being replaced MUST be deleted, not left as a courtesy.
|
|
340
|
+
- Solution shape MUST NOT appear in `.what/`. Promises MUST NOT appear first in `.how/`.
|
|
341
|
+
- Superseded artifacts are not deleted. Their status becomes `superseded` and points at the replacement.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
status: Accepted
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Decision Guide
|
|
6
|
+
|
|
7
|
+
**Loaded when:** opening, accepting, or applying a `DEC-`
|
|
8
|
+
|
|
9
|
+
A `DEC-` records a decision worth remembering. The old name was ADR — *Architecture Decision Record*
|
|
10
|
+
— and the word "Architecture" forced the wrong question at the moment of writing: *"is this
|
|
11
|
+
architectural?"*. That question throws away the decisions most worth keeping, the ones that sound
|
|
12
|
+
small: *"the filter works like this"*, *"this list is sorted that way"*.
|
|
13
|
+
|
|
14
|
+
## One test decides whether to record
|
|
15
|
+
|
|
16
|
+
> **If someone asks in three months why it is like this, is the answer readable from the code?**
|
|
17
|
+
|
|
18
|
+
Yes → it MUST NOT be recorded. No → it is recorded.
|
|
19
|
+
|
|
20
|
+
**Recording is not mandatory, and a decision nobody recorded is normal rather than negligence.** It
|
|
21
|
+
MUST NOT be logged as debt, raised as a finding, or backfilled later from memory. Without this
|
|
22
|
+
sentence, "not mandatory" is read as "mandatory but allowed to be late".
|
|
23
|
+
|
|
24
|
+
One case remains mandatory: a decision that **contradicts or changes an `AD-N`** MUST be recorded
|
|
25
|
+
before the work that depends on it. That is the only one.
|
|
26
|
+
|
|
27
|
+
## `AD-N` and `DEC-NNN` are not the same thing
|
|
28
|
+
|
|
29
|
+
| | `AD-N` | `DEC-NNN` |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| Is | A **living rule** in `ARCHITECTURE-SPINE.md` | A **decision event** |
|
|
32
|
+
| Lives in | The spine | `.control/decisions/` |
|
|
33
|
+
| Changes by | Being edited in place | Never, once `applied` — a new `DEC-` supersedes it |
|
|
34
|
+
| Answers | What is forbidden from now on | What was chosen, and what it cost |
|
|
35
|
+
|
|
36
|
+
An `AD-N` usually has a `DEC-` behind it. Neither MUST be written in place of the other, and one MUST
|
|
37
|
+
NOT be converted into the other.
|
|
38
|
+
|
|
39
|
+
## Shape — three sections, and no more required
|
|
40
|
+
|
|
41
|
+
| Section | States | Required |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| **Decision** | One sentence, present tense, quotable into a rule | always |
|
|
44
|
+
| **Why** | The context that forced it, in a few lines | always |
|
|
45
|
+
| **Cost** | What becomes harder. A decision with only benefits was not thought through | always |
|
|
46
|
+
| Alternatives | What else was considered, and why each lost | see below |
|
|
47
|
+
| Reversal trigger | The observable condition that makes revisiting this correct | see below |
|
|
48
|
+
| Trace | Where it came from, and what it landed in | see below |
|
|
49
|
+
|
|
50
|
+
The last three MUST be present when the decision reaches a Product Component whose `risk_accepted`
|
|
51
|
+
is `low` in `components.yaml`. Everywhere else they are optional, and an empty one MUST be dropped
|
|
52
|
+
rather than left as a heading with nothing under it.
|
|
53
|
+
|
|
54
|
+
**A `DEC-` MUST NOT hold an open question.** Those belong to `.control/questions/`.
|
|
55
|
+
|
|
56
|
+
## Frontmatter
|
|
57
|
+
|
|
58
|
+
| Field | Rule |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `id` | `DEC-NNN`, allocated from `.control/registry/decisions.yaml`, globally. MUST NOT restart per component or per release |
|
|
61
|
+
| `status` | `draft` · `accepted` · `applied` · `superseded` · `rejected` |
|
|
62
|
+
| `touches` | Empty at `draft`. Filled **when the decision is applied**, with the files it actually changed |
|
|
63
|
+
| `type` | Free text, and optional. Written when it is useful — `risk-acceptance`, `course-correction` |
|
|
64
|
+
| `supersedes` · `superseded_by` | Both sides of a supersession MUST exist |
|
|
65
|
+
|
|
66
|
+
**There is no `layer:` and no `component:`.** Both were classifications demanded before anything was
|
|
67
|
+
known, and both were guessed as often as they were derived. `touches:` replaces them, and it is filled
|
|
68
|
+
from what happened rather than from what was predicted.
|
|
69
|
+
|
|
70
|
+
The filename is `DEC-NNN-<slug>.md`. It MUST NOT carry a component name — a decision that turns out to
|
|
71
|
+
reach a second component would otherwise need renaming, and the rename breaks every link to it.
|
|
72
|
+
Filenames MUST obey the cross-OS naming rules in `structure-guide.md`.
|
|
73
|
+
|
|
74
|
+
## Status — and why `applied` exists
|
|
75
|
+
|
|
76
|
+
`draft` → `accepted` → `applied`. A change of mind after that produces a **new** `DEC-`.
|
|
77
|
+
|
|
78
|
+
| Status | Means |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `draft` | Being argued. It changes nothing, and that is the point — proposing is cheap |
|
|
81
|
+
| `accepted` | Ratified by the Product Owner. MAY still be corrected in place |
|
|
82
|
+
| `applied` | The documents it governs now say it. **Frozen from here** |
|
|
83
|
+
| `superseded` | Replaced. Names its replacement, and the replacement names it |
|
|
84
|
+
| `rejected` | Seriously considered and turned down. A real status, and it MUST be used — it is what stops the same argument being had twice |
|
|
85
|
+
|
|
86
|
+
**Applying is what freezes a decision, not accepting.** From `applied` onward nothing in the file MUST
|
|
87
|
+
be touched — not the Decision, not the Cost, not a typo in the Why. Documents cite it, and editing it
|
|
88
|
+
destroys the only evidence of what they were changed to match.
|
|
89
|
+
|
|
90
|
+
Before that, an `accepted` `DEC-` MAY be corrected in place. Nothing has been built on it, so there is
|
|
91
|
+
no divergent record to preserve. The correction MUST be recorded in the memlog.
|
|
92
|
+
|
|
93
|
+
An agent MUST NOT accept its own `DEC-`. When work is blocked waiting on one, the block is reported,
|
|
94
|
+
never resolved by self-approval.
|
|
95
|
+
|
|
96
|
+
## Finding a decision
|
|
97
|
+
|
|
98
|
+
`.control/generated/decisions.md` carries a flat table of every `DEC-` with its status and what it
|
|
99
|
+
touches. It is generated, and MUST NOT be written by hand.
|
|
100
|
+
|
|
101
|
+
Searching the memlog for decisions is **retired**. The memlog is a run log again — the record of *why*
|
|
102
|
+
while an artifact was written, and a source when writing a `DEC-`, never an index of them.
|
|
103
|
+
|
|
104
|
+
## Where decisions come from
|
|
105
|
+
|
|
106
|
+
| Trigger | Route |
|
|
107
|
+
|---|---|
|
|
108
|
+
| A meeting reached one | `wdi-log` intent `meeting` writes the minutes; the decision still needs its own `DEC-` |
|
|
109
|
+
| An open question was answered | `wdi-question` closes it; the answer becomes a `DEC-` when it binds |
|
|
110
|
+
| `wdi-systematic-debugging` found a root cause in the design | A `DEC-`. It MUST NOT be absorbed as a code patch |
|
|
111
|
+
| A planning assumption turned out to be void | `wdi-decision`, which wraps `bmad-correct-course`. The result is a `DEC-` of `type: course-correction` |
|
|
112
|
+
| A story contradicts an `AD-N` | The story stops. This is the one mandatory case |
|
|
113
|
+
| `wdi-reconcile` found two documents disagreeing with no clear winner | That is a decision, not drift |
|
|
114
|
+
|
|
115
|
+
Minutes MUST NOT be treated as a decision record. They say what was discussed; a `DEC-` says what was
|
|
116
|
+
chosen and what it cost.
|
|
117
|
+
|
|
118
|
+
**`SCP-` is retired.** A course correction is a decision, and it is a `DEC-` with
|
|
119
|
+
`type: course-correction`. No second code names the same thing.
|
|
120
|
+
|
|
121
|
+
## Rules
|
|
122
|
+
|
|
123
|
+
- A `DEC-` MUST be opened **before** the code that depends on it, never written afterwards to explain
|
|
124
|
+
code that already exists.
|
|
125
|
+
- The applying pass MUST NOT improvise. When an `accepted` `DEC-` does not say clearly what a document
|
|
126
|
+
has to change, the decision is incomplete and is sent back.
|
|
127
|
+
- Applying MUST NOT widen beyond what the decision says. A neighbouring paragraph that now looks wrong
|
|
128
|
+
is a finding to report.
|
|
129
|
+
- V8 checks that every `applied` `DEC-` names a non-empty `touches`. It MUST NOT check that a decision
|
|
130
|
+
serves an `FR` or `NFR` — *"the filter works like this"* serves none, and it is exactly the kind of
|
|
131
|
+
decision this guide exists to keep.
|
|
132
|
+
- `ADR-NNN` written inside a document frozen before 2026-08-18 is a **retired alias** for `DEC-NNN`
|
|
133
|
+
with the same number. It MUST NOT be read as a second, missing record, and those documents MUST NOT
|
|
134
|
+
be rewritten to change the prefix.
|