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.
- package/CHANGELOG.md +129 -0
- package/NOTICE +7 -2
- package/README.md +16 -11
- package/bin/wdi-method.js +396 -87
- package/kit/.constitution/method/document/architecture-guide.md +217 -209
- package/kit/.constitution/method/document/bmad-skill-register.md +107 -104
- package/kit/.constitution/method/document/corpus-guide.md +522 -517
- package/kit/.constitution/method/document/decision-guide.md +236 -216
- package/kit/.constitution/method/document/delivery-flow-guide.md +20 -0
- package/kit/.constitution/method/document/prd-guide.md +245 -245
- package/kit/.constitution/method/document/templates/design-system.md +96 -66
- package/kit/.constitution/method/document/templates/experience.md +62 -0
- package/kit/.constitution/method/document/templates/structure-codebase.md +131 -129
- package/kit/.constitution/method/document/templates/ux.md +78 -76
- package/kit/.constitution/method/document/ux-guide.md +161 -115
- package/kit/.constitution/method/method-glossary.md +3 -0
- package/kit/.constitution/method/scripts/validate.py +3375 -3200
- package/kit/.constitution/method/structure-guide.md +204 -202
- package/kit/.constitution/method/why/README.md +1 -1
- package/kit/.constitution/method/why/artifact-map.md +158 -157
- package/kit/.constitution/method/why/portability.md +19 -2
- package/kit/skills/wdi-autopilot/SKILL.md +32 -19
- package/kit/skills/wdi-blueprint/SKILL.md +271 -264
- package/kit/skills/wdi-build/SKILL.md +28 -19
- package/kit/skills/wdi-component/SKILL.md +179 -174
- package/kit/skills/wdi-daily-autopilot/SKILL.md +24 -13
- package/kit/skills/wdi-daily-what-to-build/SKILL.md +9 -6
- package/kit/skills/wdi-daily-what-to-test/SKILL.md +2 -0
- package/kit/skills/wdi-decision/SKILL.md +206 -203
- package/kit/skills/wdi-explain-to-me/SKILL.md +2 -0
- package/kit/skills/wdi-help/SKILL.md +130 -125
- package/kit/skills/wdi-init/SKILL.md +10 -5
- package/kit/skills/wdi-problem/SKILL.md +114 -108
- package/kit/skills/wdi-product/SKILL.md +167 -162
- package/kit/skills/wdi-prune-or-archive/SKILL.md +2 -0
- package/kit/skills/wdi-reconcile/SKILL.md +170 -169
- package/kit/skills/wdi-upgrade/SKILL.md +234 -215
- package/kit/skills/wdi-ux/SKILL.md +187 -169
- package/kit-overlay/AGENTS.md +15 -2
- package/kit-overlay/portability.md +19 -2
- package/lib/platforms.mjs +420 -248
- package/package.json +1 -1
- package/scaffold/.control/registry/index.yaml +2 -1
|
@@ -1,245 +1,245 @@
|
|
|
1
|
-
---
|
|
2
|
-
status: Accepted
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# PRD Guide
|
|
6
|
-
|
|
7
|
-
**Loaded when:** writing, updating, or validating a PRD
|
|
8
|
-
|
|
9
|
-
A PRD states what the product promises a user for one functional area. It does not describe how the
|
|
10
|
-
system behaves — that is `SRS-<pc>.md` — and it does not describe how it is built — that is
|
|
11
|
-
`SDD-<pc>.md`. When a sentence here could only be checked by reading code, it is in the wrong file.
|
|
12
|
-
|
|
13
|
-
## Home and life cycle
|
|
14
|
-
|
|
15
|
-
- One PRD per **initiative / functional area**. It MUST live at `.what/_prd/<initiative>/prd.md`,
|
|
16
|
-
with `addendum.md` beside it. Set through `prd_output_path` and `run_folder_pattern` in
|
|
17
|
-
`_bmad/custom/bmad-prd.toml`.
|
|
18
|
-
- A PRD is a **living document**. It MUST NOT be frozen, archived, or superseded when a release
|
|
19
|
-
ships.
|
|
20
|
-
- Memlog MUST go to `.control/memlog/prd-<slug>.md` via `--path`, with the slug matching the folder.
|
|
21
|
-
`--workspace` MUST NOT be used; it would leave a `.memlog.md` inside `.what/`.
|
|
22
|
-
- `run_folder_pattern` ships as `ISI-slug-inisiatif`, which is deliberately unusable. A PRD found in
|
|
23
|
-
a folder by that name means the override was never pointed at a real initiative slug; `wdi-product`
|
|
24
|
-
check 1 catches it, and it MUST be moved before G2.
|
|
25
|
-
|
|
26
|
-
## Update, or a new PRD
|
|
27
|
-
|
|
28
|
-
This is the decision the guide exists for, and the default is **Update**.
|
|
29
|
-
|
|
30
|
-
| Situation | What to do |
|
|
31
|
-
|---|---|
|
|
32
|
-
| Behaviour of an existing promise changes | Update |
|
|
33
|
-
| A promise turns out to be wrong and must be withdrawn | Update — and the withdrawal MUST be visible in Revision History, not silently deleted. This is the one mandated history line in the method, and it survives because it is **business** history read by someone outside the room, not a record that a document changed |
|
|
34
|
-
| A new feature that a reader would expect to find in this PRD | Update |
|
|
35
|
-
| The next release extends what this PRD already promises | Update. A release is never a reason on its own |
|
|
36
|
-
| A functional area a reader would not think to look for here | New PRD |
|
|
37
|
-
|
|
38
|
-
The test is the reader, not the calendar: **would someone looking for this promise open this
|
|
39
|
-
document?** If yes, it belongs here however large the change. A PRD MUST NOT be split because it
|
|
40
|
-
grew long — length is what `addendum.md` and feature grouping are for. It is split only when the two
|
|
41
|
-
areas have different readers, different stakeholders, or no shared vocabulary.
|
|
42
|
-
|
|
43
|
-
When a split is genuinely right, the existing PRD MUST keep its own IDs. `FR-N` never moves between
|
|
44
|
-
PRDs; the sequence is global to the product.
|
|
45
|
-
|
|
46
|
-
## One home, and what `.what/<pc>/` may take from it
|
|
47
|
-
|
|
48
|
-
A PRD is the **reference** the blueprint and each component work from, not a quarry. `.what/<pc>/` is distilled from it — the
|
|
49
|
-
same promise restated as behaviour, at the altitude a builder needs — and the PRD stays the one place
|
|
50
|
-
that promise lives.
|
|
51
|
-
|
|
52
|
-
- One PRD per initiative. Its content MUST NOT be split into pieces spread across `.what/<pc>/`, and
|
|
53
|
-
a fragment MUST NOT be moved out of it. A promise with two homes drifts, and the copy people read
|
|
54
|
-
is whichever they open first.
|
|
55
|
-
- `.what/<pc>/` MUST cite the `FR`/`NFR` it realises by ID rather than restating its text. A use case
|
|
56
|
-
saying what the system does is derivation; a use case reproducing the PRD's paragraph is a second
|
|
57
|
-
copy.
|
|
58
|
-
- One initiative MAY span several Product Components, and one component MAY serve several PRDs. That
|
|
59
|
-
is why neither can absorb the other — `corpus-guide.md` owns the two-axis rule.
|
|
60
|
-
- When the distillation proves a promise cannot be behaved into, the PRD changes first, through
|
|
61
|
-
`wdi-product` intent `update`. The SRS MUST NOT narrow it quietly.
|
|
62
|
-
|
|
63
|
-
## Revision History
|
|
64
|
-
|
|
65
|
-
- Every `update` run MUST add **exactly one row**, appended at the bottom — one row per **pass**, never
|
|
66
|
-
one per correction.
|
|
67
|
-
- Rows MUST be written for someone who was not in the room — a client, a sponsor, an auditor. State
|
|
68
|
-
what the promise now is, not which section was edited. "Payment retries now cap at three attempts,
|
|
69
|
-
down from unlimited, because support could not explain the charges" is a row. "Updated §4.2" is
|
|
70
|
-
not.
|
|
71
|
-
- The `Releases affected` column names the releases whose promise changed. It MUST match
|
|
72
|
-
`target_release` on the affected `CAP` entries.
|
|
73
|
-
- A row MUST NOT be edited after the run that wrote it. A correction is a new row.
|
|
74
|
-
|
|
75
|
-
The boundary against the memlog matters and MUST NOT be collapsed:
|
|
76
|
-
|
|
77
|
-
| | Memlog | Revision History |
|
|
78
|
-
|---|---|---|
|
|
79
|
-
| Records | Every decision, change, override, assumption inside a run | What changed for the reader |
|
|
80
|
-
| Written | Continuously, by `memlog.py`, append-only | Once per run, by hand |
|
|
81
|
-
| Read by | The next run, and audits | Anyone opening the PRD |
|
|
82
|
-
| Lives in | `.control/memlog/` | The PRD itself |
|
|
83
|
-
|
|
84
|
-
Neither MUST be written in place of the other. A PRD whose only change record is the memlog is
|
|
85
|
-
unreadable to the people it was written for.
|
|
86
|
-
|
|
87
|
-
## Release lives in the registry
|
|
88
|
-
|
|
89
|
-
Release MUST NOT be expressed through this document's folder name, title, or frontmatter. It is
|
|
90
|
-
carried by:
|
|
91
|
-
|
|
92
|
-
| Field | Answers |
|
|
93
|
-
|---|---|
|
|
94
|
-
| `CAP.target_release` | Which release this capability is planned for. **The only place a promise's release is written** |
|
|
95
|
-
| `specs.yaml` `release` | Which release a spec of work belongs to — the execution side |
|
|
96
|
-
|
|
97
|
-
An `FR` MUST NOT carry a release of its own. It inherits one from its `CAP`, the same way it reaches
|
|
98
|
-
its `BG`: each child names only its parent. A capability whose requirements genuinely land in
|
|
99
|
-
different releases is two capabilities, and MUST be split rather than annotated.
|
|
100
|
-
|
|
101
|
-
Naming a release in prose as context MAY happen; the registry is what binds.
|
|
102
|
-
|
|
103
|
-
## Numbering
|
|
104
|
-
|
|
105
|
-
`BG-N` is allocated from `.control/registry/goals.yaml`; `CAP-N`, `FR-N`, `NFR-N`, and `UJ-N` from this initiative's own `.control/registry/requirements-<slug>.yaml` — one file, one writer, one gate
|
|
106
|
-
and MUST NOT restart at 1. The chain runs `BG → CAP → FR/NFR → UC → DEC → Ticket → Test`, and each
|
|
107
|
-
child names only its parent:
|
|
108
|
-
|
|
109
|
-
- Each feature in §3 MUST declare its `CAP-N` and the `BG-N` it serves.
|
|
110
|
-
- Each `FR` MUST declare its `capability`. Its goal is reached *through* the capability and MUST NOT
|
|
111
|
-
be restated on the FR.
|
|
112
|
-
- Each `NFR` attaches to `BG` directly — it does not pass through `CAP`.
|
|
113
|
-
|
|
114
|
-
`chain-links` checks both links. An FR with no capability is a promise nobody asked for.
|
|
115
|
-
|
|
116
|
-
## `FR`/`NFR` text lives in the registry, not in this document
|
|
117
|
-
|
|
118
|
-
The PRD cites `FR-N`/`NFR-N` under each feature's **Realizes:** line. It MUST NOT also write the
|
|
119
|
-
statement, the proof of done, or the enforcer in prose — those fields live on the id's own row in
|
|
120
|
-
`requirements-<slug>.yaml`, and landing them there is part of `wdi-product` producing this PRD, not a
|
|
121
|
-
follow-up. A promise written in both places is one fact with two homes, and the copy a reader trusts
|
|
122
|
-
is whichever they open first.
|
|
123
|
-
|
|
124
|
-
Every `FR` MUST carry **exactly one** proof of done: a sentence a Product Owner can check without opening
|
|
125
|
-
the code. It is what lets one `FR` become one testable unit of work, and it is why a spec is ideally one
|
|
126
|
-
`FR`.
|
|
127
|
-
|
|
128
|
-
**The double proof of done stays repealed.** A business sentence *and* a technical restatement naming
|
|
129
|
-
status codes, limits, and payloads meant writing the same acceptance twice, in two vocabularies that
|
|
130
|
-
then drifted. The technical form is represented by the **test name** recorded in `specs.yaml`, where it
|
|
131
|
-
is checked mechanically (`ticket-has-test`) instead of read.
|
|
132
|
-
|
|
133
|
-
A technical detail that genuinely has to be written down belongs in `addendum.md` or in the SDD, not in
|
|
134
|
-
a second proof of done — and not in this document's prose either.
|
|
135
|
-
|
|
136
|
-
## Wording versus promise — two different journeys
|
|
137
|
-
|
|
138
|
-
The distinction this guide exists to protect, and the one that produced three corrections that ended
|
|
139
|
-
"reported but not fixed":
|
|
140
|
-
|
|
141
|
-
| What changes | Route |
|
|
142
|
-
|---|---|
|
|
143
|
-
| The **wording** of an `FR` — a wrong cross-reference, a retired term, a word no longer consistent with an `applied` decision, while **the promise is the same** | The skill already at work fixes it directly. Recorded in the memlog, and **one** Revision History row per pass, not per correction |
|
|
144
|
-
| The **promise** of an `FR` — scope changes, the proof of done changes, an `FR` is retired or born | `wdi-product` intent `update`, and the change-control matrix in `delivery-flow-guide.md` says which gates reopen |
|
|
145
|
-
|
|
146
|
-
The guard against abuse is already in the Revision History rule: a row is written for someone who was not in
|
|
147
|
-
the room. A wording correction produces no row a client would find interesting, and that is precisely the
|
|
148
|
-
evidence it was not a change of promise.
|
|
149
|
-
|
|
150
|
-
Treating a wording fix as a promise change is not caution — it is what made three corrections queue behind a
|
|
151
|
-
gate and then get dropped.
|
|
152
|
-
|
|
153
|
-
## `owns:` — one entity, one writer
|
|
154
|
-
|
|
155
|
-
A domain entity MUST have exactly one owner authorised to write it. Usually that is a Product Component,
|
|
156
|
-
declared as `owns:` on its row in `components.yaml`; an `FR` from another PRD that needs to change the entity
|
|
157
|
-
MUST point at the owner's `FR` through `defers_to`, rather than promising to write it itself. `entity-one-writer` checks this.
|
|
158
|
-
|
|
159
|
-
**A few entities belong to no Product Component at all** — a product-wide setting, the trace of one shared
|
|
160
|
-
outbound channel. Those are owned by `_platform` through `platform_owns`, and the test for when that is
|
|
161
|
-
legitimate lives in `corpus-guide.md`. `_platform` has no `FR`, so an `FR` writing a platform-owned entity is
|
|
162
|
-
**not** asked for a `defers_to`; what binds instead is the shape documented in `cross-cutting.md`. Reaching
|
|
163
|
-
for `_platform` because the owner is hard to decide is the one use of it that the test refuses.
|
|
164
|
-
|
|
165
|
-
This is not theoretical: two PRDs have already collided semantically over one shared numbering series. Two
|
|
166
|
-
`FR` claiming write authority over the same entity, with neither pointing at the other, is a defect at the
|
|
167
|
-
moment it is written — not at the moment the code disagrees.
|
|
168
|
-
|
|
169
|
-
## Sections that stop being optional
|
|
170
|
-
|
|
171
|
-
BMad's Adapt-In Menu is conditional by design. Two clusters MUST always be present here, and are in
|
|
172
|
-
the Essential Spine rather than the Adapt-In menu for exactly that reason:
|
|
173
|
-
|
|
174
|
-
| Cluster | Section | Why it is required |
|
|
175
|
-
|---|---|---|
|
|
176
|
-
| **Cross-Cutting NFRs** | §6 | G2 passes on numbered FR **and NFR**. Each NFR MUST name `enforced_by` — an `AD-N`, a `DEC-`, or a test name. An NFR nothing enforces is decoration (`nfr-has-enforcer`) |
|
|
177
|
-
| **Constraints and Guardrails** | §7 | A constraint found at G4 costs a decision that one sentence here would have prevented |
|
|
178
|
-
|
|
179
|
-
Constraints MUST state only the delta beyond `.what/_product-brief/brief.md`, and MUST say "none
|
|
180
|
-
beyond the brief" when there is nothing. An absent section reads as "not checked".
|
|
181
|
-
|
|
182
|
-
Prerequisites MUST NOT be written as prose. An initiative blocked on another is a `depends_on`
|
|
183
|
-
between `CAP` entries.
|
|
184
|
-
|
|
185
|
-
## §1 Why This Initiative is a delta
|
|
186
|
-
|
|
187
|
-
BMad's default §1 Vision writes the product's vision from scratch, in the same 2-3 paragraph shape as
|
|
188
|
-
the brief's own narrative. On the first PRD a product ever gets, that duplicates `Why` in
|
|
189
|
-
`.what/_product-brief/brief.md` almost sentence for sentence — the same defect Executive Summary and
|
|
190
|
-
Vision had against each other inside the brief before they were merged.
|
|
191
|
-
|
|
192
|
-
§1 states only what THIS initiative changes, adds, or unlocks beyond what the brief's `Why` already
|
|
193
|
-
says. A product with a single initiative MAY reduce this to one sentence pointing back to the brief.
|
|
194
|
-
The full narrative is never written twice.
|
|
195
|
-
|
|
196
|
-
## Sections dropped from BMad's default, and where each fact actually lives
|
|
197
|
-
|
|
198
|
-
Four of BMad's default sections carry no content specific to this PRD, or duplicate a fact this method
|
|
199
|
-
already gives a home. Each is dropped rather than left conditional:
|
|
200
|
-
|
|
201
|
-
| Dropped section | Where the fact lives instead |
|
|
202
|
-
|---|---|
|
|
203
|
-
| Document Purpose | Nowhere — it explained what a PRD is in general, true of every PRD, so it held no information specific to this one |
|
|
204
|
-
| Glossary | `.control/product-glossary.md`. A term this PRD needs that is not there yet goes through `wdi-question` in the same pass — it is never added to a document-local glossary `wdi-blueprint` will not read at G3 |
|
|
205
|
-
| Non-Goals | The product's own Scope Out (`.what/_product-brief/brief.md`), for what the product never does, and §4.2 Out of Scope for MVP, for what this release defers. A third list restating both is the same fact twice |
|
|
206
|
-
| Open Questions | `.control/questions/`, the moment the question is found — not batched into a section read once at Finalize |
|
|
207
|
-
| Assumptions Index | `.control/questions/assumptions.md`, through `wdi-question`, before G2. The inline `[ASSUMPTION]` tag stays as a marker for the conversation that produced it; it is not also an index entry |
|
|
208
|
-
|
|
209
|
-
A reader who wants all of these assembled with the PRD's own content reads the generated deliverable —
|
|
210
|
-
see below — rather than a hand-maintained index inside this document.
|
|
211
|
-
|
|
212
|
-
## The generated deliverable
|
|
213
|
-
|
|
214
|
-
A complete, self-contained copy for a reader who should not need to open the registry or
|
|
215
|
-
`.control/questions/` lives at `.what-rendered/_prd/<slug>/prd.md` — written by `/wdi-report render prd`,
|
|
216
|
-
which runs `validate.py --generate`. It assembles this PRD's own prose verbatim, the
|
|
217
|
-
Vision from the brief's `Why` plus §1's delta, the `FR`/`NFR` rows from `requirements-<slug>.yaml`, the
|
|
218
|
-
Glossary terms this PRD actually uses, Non-Goals from the brief's Scope Out and §4.2, and the open
|
|
219
|
-
rows from `.control/questions/` that cite one of this PRD's ids. Nobody writes to it by hand.
|
|
220
|
-
|
|
221
|
-
## What goes to `addendum.md`
|
|
222
|
-
|
|
223
|
-
`addendum.md` is **not** a change log — Revision History is. It holds depth that belongs downstream
|
|
224
|
-
or earned its place but does not fit the narrative: rejected-alternative rationale, options matrices,
|
|
225
|
-
mechanism and transport decisions, technical how, in-depth personas, sizing data.
|
|
226
|
-
|
|
227
|
-
Content MUST be captured there *during* the conversation when the user volunteers it, not swept
|
|
228
|
-
there at Finalize. What in the addendum turns out to bind a later document MUST be written into that
|
|
229
|
-
document by the skill owning its layer, rather than cited from the addendum forever.
|
|
230
|
-
|
|
231
|
-
Audit and override information MUST NOT go to the addendum; it belongs in the memlog.
|
|
232
|
-
|
|
233
|
-
## Passing G2
|
|
234
|
-
|
|
235
|
-
- Every `[ASSUMPTION]` still unresolved at Finalize MUST be filed through `wdi-question` before the gate
|
|
236
|
-
opens — into `assumptions.md` by default, and into `blocking.md` only through the three tests that file
|
|
237
|
-
states. Filing one as blocking "to be safe" is the habit that produced 146 ids.
|
|
238
|
-
- `bmad-review` runs automatically through `doc_standards` on `prd.md` and `addendum.md`. It MUST
|
|
239
|
-
have run before the gate — a Product Owner's 45 minutes are for deciding, not proofreading.
|
|
240
|
-
- The gate reads `prd.md` and `EXPERIENCE.md`
|
|
241
|
-
is missing has answered only half of what G2 decides.
|
|
242
|
-
- Solution shape MUST NOT appear. If a sentence names a framework, a table, or a transport, it belongs in
|
|
243
|
-
`addendum.md` or in the spine.
|
|
244
|
-
- Invoke through `wdi-product`, never `bmad-prd` directly — the wrapper is what checks the rules on this
|
|
245
|
-
page and lands the memlog.
|
|
1
|
+
---
|
|
2
|
+
status: Accepted
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# PRD Guide
|
|
6
|
+
|
|
7
|
+
**Loaded when:** writing, updating, or validating a PRD
|
|
8
|
+
|
|
9
|
+
A PRD states what the product promises a user for one functional area. It does not describe how the
|
|
10
|
+
system behaves — that is `SRS-<pc>.md` — and it does not describe how it is built — that is
|
|
11
|
+
`SDD-<pc>.md`. When a sentence here could only be checked by reading code, it is in the wrong file.
|
|
12
|
+
|
|
13
|
+
## Home and life cycle
|
|
14
|
+
|
|
15
|
+
- One PRD per **initiative / functional area**. It MUST live at `.what/_prd/<initiative>/prd.md`,
|
|
16
|
+
with `addendum.md` beside it. Set through `prd_output_path` and `run_folder_pattern` in
|
|
17
|
+
`_bmad/custom/bmad-prd.toml`.
|
|
18
|
+
- A PRD is a **living document**. It MUST NOT be frozen, archived, or superseded when a release
|
|
19
|
+
ships.
|
|
20
|
+
- Memlog MUST go to `.control/memlog/prd-<slug>.md` via `--path`, with the slug matching the folder.
|
|
21
|
+
`--workspace` MUST NOT be used; it would leave a `.memlog.md` inside `.what/`.
|
|
22
|
+
- `run_folder_pattern` ships as `ISI-slug-inisiatif`, which is deliberately unusable. A PRD found in
|
|
23
|
+
a folder by that name means the override was never pointed at a real initiative slug; `wdi-product`
|
|
24
|
+
check 1 catches it, and it MUST be moved before G2.
|
|
25
|
+
|
|
26
|
+
## Update, or a new PRD
|
|
27
|
+
|
|
28
|
+
This is the decision the guide exists for, and the default is **Update**.
|
|
29
|
+
|
|
30
|
+
| Situation | What to do |
|
|
31
|
+
|---|---|
|
|
32
|
+
| Behaviour of an existing promise changes | Update |
|
|
33
|
+
| A promise turns out to be wrong and must be withdrawn | Update — and the withdrawal MUST be visible in Revision History, not silently deleted. This is the one mandated history line in the method, and it survives because it is **business** history read by someone outside the room, not a record that a document changed |
|
|
34
|
+
| A new feature that a reader would expect to find in this PRD | Update |
|
|
35
|
+
| The next release extends what this PRD already promises | Update. A release is never a reason on its own |
|
|
36
|
+
| A functional area a reader would not think to look for here | New PRD |
|
|
37
|
+
|
|
38
|
+
The test is the reader, not the calendar: **would someone looking for this promise open this
|
|
39
|
+
document?** If yes, it belongs here however large the change. A PRD MUST NOT be split because it
|
|
40
|
+
grew long — length is what `addendum.md` and feature grouping are for. It is split only when the two
|
|
41
|
+
areas have different readers, different stakeholders, or no shared vocabulary.
|
|
42
|
+
|
|
43
|
+
When a split is genuinely right, the existing PRD MUST keep its own IDs. `FR-N` never moves between
|
|
44
|
+
PRDs; the sequence is global to the product.
|
|
45
|
+
|
|
46
|
+
## One home, and what `.what/<pc>/` may take from it
|
|
47
|
+
|
|
48
|
+
A PRD is the **reference** the blueprint and each component work from, not a quarry. `.what/<pc>/` is distilled from it — the
|
|
49
|
+
same promise restated as behaviour, at the altitude a builder needs — and the PRD stays the one place
|
|
50
|
+
that promise lives.
|
|
51
|
+
|
|
52
|
+
- One PRD per initiative. Its content MUST NOT be split into pieces spread across `.what/<pc>/`, and
|
|
53
|
+
a fragment MUST NOT be moved out of it. A promise with two homes drifts, and the copy people read
|
|
54
|
+
is whichever they open first.
|
|
55
|
+
- `.what/<pc>/` MUST cite the `FR`/`NFR` it realises by ID rather than restating its text. A use case
|
|
56
|
+
saying what the system does is derivation; a use case reproducing the PRD's paragraph is a second
|
|
57
|
+
copy.
|
|
58
|
+
- One initiative MAY span several Product Components, and one component MAY serve several PRDs. That
|
|
59
|
+
is why neither can absorb the other — `corpus-guide.md` owns the two-axis rule.
|
|
60
|
+
- When the distillation proves a promise cannot be behaved into, the PRD changes first, through
|
|
61
|
+
`wdi-product` intent `update`. The SRS MUST NOT narrow it quietly.
|
|
62
|
+
|
|
63
|
+
## Revision History
|
|
64
|
+
|
|
65
|
+
- Every `update` run MUST add **exactly one row**, appended at the bottom — one row per **pass**, never
|
|
66
|
+
one per correction.
|
|
67
|
+
- Rows MUST be written for someone who was not in the room — a client, a sponsor, an auditor. State
|
|
68
|
+
what the promise now is, not which section was edited. "Payment retries now cap at three attempts,
|
|
69
|
+
down from unlimited, because support could not explain the charges" is a row. "Updated §4.2" is
|
|
70
|
+
not.
|
|
71
|
+
- The `Releases affected` column names the releases whose promise changed. It MUST match
|
|
72
|
+
`target_release` on the affected `CAP` entries.
|
|
73
|
+
- A row MUST NOT be edited after the run that wrote it. A correction is a new row.
|
|
74
|
+
|
|
75
|
+
The boundary against the memlog matters and MUST NOT be collapsed:
|
|
76
|
+
|
|
77
|
+
| | Memlog | Revision History |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| Records | Every decision, change, override, assumption inside a run | What changed for the reader |
|
|
80
|
+
| Written | Continuously, by `memlog.py`, append-only | Once per run, by hand |
|
|
81
|
+
| Read by | The next run, and audits | Anyone opening the PRD |
|
|
82
|
+
| Lives in | `.control/memlog/` | The PRD itself |
|
|
83
|
+
|
|
84
|
+
Neither MUST be written in place of the other. A PRD whose only change record is the memlog is
|
|
85
|
+
unreadable to the people it was written for.
|
|
86
|
+
|
|
87
|
+
## Release lives in the registry
|
|
88
|
+
|
|
89
|
+
Release MUST NOT be expressed through this document's folder name, title, or frontmatter. It is
|
|
90
|
+
carried by:
|
|
91
|
+
|
|
92
|
+
| Field | Answers |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `CAP.target_release` | Which release this capability is planned for. **The only place a promise's release is written** |
|
|
95
|
+
| `specs.yaml` `release` | Which release a spec of work belongs to — the execution side |
|
|
96
|
+
|
|
97
|
+
An `FR` MUST NOT carry a release of its own. It inherits one from its `CAP`, the same way it reaches
|
|
98
|
+
its `BG`: each child names only its parent. A capability whose requirements genuinely land in
|
|
99
|
+
different releases is two capabilities, and MUST be split rather than annotated.
|
|
100
|
+
|
|
101
|
+
Naming a release in prose as context MAY happen; the registry is what binds.
|
|
102
|
+
|
|
103
|
+
## Numbering
|
|
104
|
+
|
|
105
|
+
`BG-N` is allocated from `.control/registry/goals.yaml`; `CAP-N`, `FR-N`, `NFR-N`, and `UJ-N` from this initiative's own `.control/registry/requirements-<slug>.yaml` — one file, one writer, one gate
|
|
106
|
+
and MUST NOT restart at 1. The chain runs `BG → CAP → FR/NFR → UC → DEC → Ticket → Test`, and each
|
|
107
|
+
child names only its parent:
|
|
108
|
+
|
|
109
|
+
- Each feature in §3 MUST declare its `CAP-N` and the `BG-N` it serves.
|
|
110
|
+
- Each `FR` MUST declare its `capability`. Its goal is reached *through* the capability and MUST NOT
|
|
111
|
+
be restated on the FR.
|
|
112
|
+
- Each `NFR` attaches to `BG` directly — it does not pass through `CAP`.
|
|
113
|
+
|
|
114
|
+
`chain-links` checks both links. An FR with no capability is a promise nobody asked for.
|
|
115
|
+
|
|
116
|
+
## `FR`/`NFR` text lives in the registry, not in this document
|
|
117
|
+
|
|
118
|
+
The PRD cites `FR-N`/`NFR-N` under each feature's **Realizes:** line. It MUST NOT also write the
|
|
119
|
+
statement, the proof of done, or the enforcer in prose — those fields live on the id's own row in
|
|
120
|
+
`requirements-<slug>.yaml`, and landing them there is part of `wdi-product` producing this PRD, not a
|
|
121
|
+
follow-up. A promise written in both places is one fact with two homes, and the copy a reader trusts
|
|
122
|
+
is whichever they open first.
|
|
123
|
+
|
|
124
|
+
Every `FR` MUST carry **exactly one** proof of done: a sentence a Product Owner can check without opening
|
|
125
|
+
the code. It is what lets one `FR` become one testable unit of work, and it is why a spec is ideally one
|
|
126
|
+
`FR`.
|
|
127
|
+
|
|
128
|
+
**The double proof of done stays repealed.** A business sentence *and* a technical restatement naming
|
|
129
|
+
status codes, limits, and payloads meant writing the same acceptance twice, in two vocabularies that
|
|
130
|
+
then drifted. The technical form is represented by the **test name** recorded in `specs.yaml`, where it
|
|
131
|
+
is checked mechanically (`ticket-has-test`) instead of read.
|
|
132
|
+
|
|
133
|
+
A technical detail that genuinely has to be written down belongs in `addendum.md` or in the SDD, not in
|
|
134
|
+
a second proof of done — and not in this document's prose either.
|
|
135
|
+
|
|
136
|
+
## Wording versus promise — two different journeys
|
|
137
|
+
|
|
138
|
+
The distinction this guide exists to protect, and the one that produced three corrections that ended
|
|
139
|
+
"reported but not fixed":
|
|
140
|
+
|
|
141
|
+
| What changes | Route |
|
|
142
|
+
|---|---|
|
|
143
|
+
| The **wording** of an `FR` — a wrong cross-reference, a retired term, a word no longer consistent with an `applied` decision, while **the promise is the same** | The skill already at work fixes it directly. Recorded in the memlog, and **one** Revision History row per pass, not per correction |
|
|
144
|
+
| The **promise** of an `FR` — scope changes, the proof of done changes, an `FR` is retired or born | `wdi-product` intent `update`, and the change-control matrix in `delivery-flow-guide.md` says which gates reopen |
|
|
145
|
+
|
|
146
|
+
The guard against abuse is already in the Revision History rule: a row is written for someone who was not in
|
|
147
|
+
the room. A wording correction produces no row a client would find interesting, and that is precisely the
|
|
148
|
+
evidence it was not a change of promise.
|
|
149
|
+
|
|
150
|
+
Treating a wording fix as a promise change is not caution — it is what made three corrections queue behind a
|
|
151
|
+
gate and then get dropped.
|
|
152
|
+
|
|
153
|
+
## `owns:` — one entity, one writer
|
|
154
|
+
|
|
155
|
+
A domain entity MUST have exactly one owner authorised to write it. Usually that is a Product Component,
|
|
156
|
+
declared as `owns:` on its row in `components.yaml`; an `FR` from another PRD that needs to change the entity
|
|
157
|
+
MUST point at the owner's `FR` through `defers_to`, rather than promising to write it itself. `entity-one-writer` checks this.
|
|
158
|
+
|
|
159
|
+
**A few entities belong to no Product Component at all** — a product-wide setting, the trace of one shared
|
|
160
|
+
outbound channel. Those are owned by `_platform` through `platform_owns`, and the test for when that is
|
|
161
|
+
legitimate lives in `corpus-guide.md`. `_platform` has no `FR`, so an `FR` writing a platform-owned entity is
|
|
162
|
+
**not** asked for a `defers_to`; what binds instead is the shape documented in `cross-cutting.md`. Reaching
|
|
163
|
+
for `_platform` because the owner is hard to decide is the one use of it that the test refuses.
|
|
164
|
+
|
|
165
|
+
This is not theoretical: two PRDs have already collided semantically over one shared numbering series. Two
|
|
166
|
+
`FR` claiming write authority over the same entity, with neither pointing at the other, is a defect at the
|
|
167
|
+
moment it is written — not at the moment the code disagrees.
|
|
168
|
+
|
|
169
|
+
## Sections that stop being optional
|
|
170
|
+
|
|
171
|
+
BMad's Adapt-In Menu is conditional by design. Two clusters MUST always be present here, and are in
|
|
172
|
+
the Essential Spine rather than the Adapt-In menu for exactly that reason:
|
|
173
|
+
|
|
174
|
+
| Cluster | Section | Why it is required |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| **Cross-Cutting NFRs** | §6 | G2 passes on numbered FR **and NFR**. Each NFR MUST name `enforced_by` — an `AD-N`, a `DEC-`, or a test name. An NFR nothing enforces is decoration (`nfr-has-enforcer`) |
|
|
177
|
+
| **Constraints and Guardrails** | §7 | A constraint found at G4 costs a decision that one sentence here would have prevented |
|
|
178
|
+
|
|
179
|
+
Constraints MUST state only the delta beyond `.what/_product-brief/brief.md`, and MUST say "none
|
|
180
|
+
beyond the brief" when there is nothing. An absent section reads as "not checked".
|
|
181
|
+
|
|
182
|
+
Prerequisites MUST NOT be written as prose. An initiative blocked on another is a `depends_on`
|
|
183
|
+
between `CAP` entries.
|
|
184
|
+
|
|
185
|
+
## §1 Why This Initiative is a delta
|
|
186
|
+
|
|
187
|
+
BMad's default §1 Vision writes the product's vision from scratch, in the same 2-3 paragraph shape as
|
|
188
|
+
the brief's own narrative. On the first PRD a product ever gets, that duplicates `Why` in
|
|
189
|
+
`.what/_product-brief/brief.md` almost sentence for sentence — the same defect Executive Summary and
|
|
190
|
+
Vision had against each other inside the brief before they were merged.
|
|
191
|
+
|
|
192
|
+
§1 states only what THIS initiative changes, adds, or unlocks beyond what the brief's `Why` already
|
|
193
|
+
says. A product with a single initiative MAY reduce this to one sentence pointing back to the brief.
|
|
194
|
+
The full narrative is never written twice.
|
|
195
|
+
|
|
196
|
+
## Sections dropped from BMad's default, and where each fact actually lives
|
|
197
|
+
|
|
198
|
+
Four of BMad's default sections carry no content specific to this PRD, or duplicate a fact this method
|
|
199
|
+
already gives a home. Each is dropped rather than left conditional:
|
|
200
|
+
|
|
201
|
+
| Dropped section | Where the fact lives instead |
|
|
202
|
+
|---|---|
|
|
203
|
+
| Document Purpose | Nowhere — it explained what a PRD is in general, true of every PRD, so it held no information specific to this one |
|
|
204
|
+
| Glossary | `.control/product-glossary.md`. A term this PRD needs that is not there yet goes through `wdi-question` in the same pass — it is never added to a document-local glossary `wdi-blueprint` will not read at G3 |
|
|
205
|
+
| Non-Goals | The product's own Scope Out (`.what/_product-brief/brief.md`), for what the product never does, and §4.2 Out of Scope for MVP, for what this release defers. A third list restating both is the same fact twice |
|
|
206
|
+
| Open Questions | `.control/questions/`, the moment the question is found — not batched into a section read once at Finalize |
|
|
207
|
+
| Assumptions Index | `.control/questions/assumptions.md`, through `wdi-question`, before G2. The inline `[ASSUMPTION]` tag stays as a marker for the conversation that produced it; it is not also an index entry |
|
|
208
|
+
|
|
209
|
+
A reader who wants all of these assembled with the PRD's own content reads the generated deliverable —
|
|
210
|
+
see below — rather than a hand-maintained index inside this document.
|
|
211
|
+
|
|
212
|
+
## The generated deliverable
|
|
213
|
+
|
|
214
|
+
A complete, self-contained copy for a reader who should not need to open the registry or
|
|
215
|
+
`.control/questions/` lives at `.what-rendered/_prd/<slug>/prd.md` — written by `/wdi-report render prd`,
|
|
216
|
+
which runs `validate.py --generate`. It assembles this PRD's own prose verbatim, the
|
|
217
|
+
Vision from the brief's `Why` plus §1's delta, the `FR`/`NFR` rows from `requirements-<slug>.yaml`, the
|
|
218
|
+
Glossary terms this PRD actually uses, Non-Goals from the brief's Scope Out and §4.2, and the open
|
|
219
|
+
rows from `.control/questions/` that cite one of this PRD's ids. Nobody writes to it by hand.
|
|
220
|
+
|
|
221
|
+
## What goes to `addendum.md`
|
|
222
|
+
|
|
223
|
+
`addendum.md` is **not** a change log — Revision History is. It holds depth that belongs downstream
|
|
224
|
+
or earned its place but does not fit the narrative: rejected-alternative rationale, options matrices,
|
|
225
|
+
mechanism and transport decisions, technical how, in-depth personas, sizing data.
|
|
226
|
+
|
|
227
|
+
Content MUST be captured there *during* the conversation when the user volunteers it, not swept
|
|
228
|
+
there at Finalize. What in the addendum turns out to bind a later document MUST be written into that
|
|
229
|
+
document by the skill owning its layer, rather than cited from the addendum forever.
|
|
230
|
+
|
|
231
|
+
Audit and override information MUST NOT go to the addendum; it belongs in the memlog.
|
|
232
|
+
|
|
233
|
+
## Passing G2
|
|
234
|
+
|
|
235
|
+
- Every `[ASSUMPTION]` still unresolved at Finalize MUST be filed through `wdi-question` before the gate
|
|
236
|
+
opens — into `assumptions.md` by default, and into `blocking.md` only through the three tests that file
|
|
237
|
+
states. Filing one as blocking "to be safe" is the habit that produced 146 ids.
|
|
238
|
+
- `bmad-review` runs automatically through `doc_standards` on `prd.md` and `addendum.md`. It MUST
|
|
239
|
+
have run before the gate — a Product Owner's 45 minutes are for deciding, not proofreading.
|
|
240
|
+
- The gate reads `prd.md` and the experience together — `.what/experience.md` for what holds across components, the run's `EXPERIENCE.md` for the rest. A PRD that passes while the experience side
|
|
241
|
+
is missing has answered only half of what G2 decides.
|
|
242
|
+
- Solution shape MUST NOT appear. If a sentence names a framework, a table, or a transport, it belongs in
|
|
243
|
+
`addendum.md` or in the spine.
|
|
244
|
+
- Invoke through `wdi-product`, never `bmad-prd` directly — the wrapper is what checks the rules on this
|
|
245
|
+
page and lands the memlog.
|