wdi-method 0.6.0 → 0.6.2
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/README.md +14 -4
- package/bin/wdi-method.js +2 -0
- package/kit/.constitution/method/README.md +1 -1
- package/kit/.constitution/method/document/decision-guide.md +208 -199
- package/kit/.constitution/method/document/delivery-flow-guide.md +412 -409
- package/kit/.constitution/method/document/templates/decision.md +6 -1
- package/kit/.constitution/method/method-glossary.md +183 -182
- package/kit/.constitution/method/scripts/validate.py +102 -2
- package/kit/.constitution/method/why/README.md +3 -1
- package/kit/.constitution/method/why/artifact-map.md +1 -1
- package/kit/.constitution/method/why/portability.md +98 -98
- package/kit/skills/wdi-autopilot/SKILL.md +366 -0
- package/kit/skills/wdi-build/SKILL.md +371 -357
- package/kit/skills/wdi-decision/SKILL.md +197 -187
- package/kit/skills/wdi-explain-to-me/SKILL.md +84 -0
- package/kit/skills/wdi-help/SKILL.md +102 -99
- package/kit/skills/wdi-question/SKILL.md +176 -170
- package/kit-overlay/AGENTS.md +223 -216
- package/kit-overlay/README.md +1 -1
- package/kit-overlay/portability.md +98 -98
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -114,6 +114,16 @@ renders, decide — advance or refine.
|
|
|
114
114
|
| 6 | `wdi-report` intent `estimate` | `.control/generated/estimate.md` | which candidate row becomes the next spec |
|
|
115
115
|
| 7 | `wdi-build` — for that row | nothing: tickets are machine contracts. You answer `to-tickets`' quiz on granularity and blocking edges | **G5** — is it done and proven? Once per spec |
|
|
116
116
|
| 8 | `wdi-report` intent `progress` | the report it writes | what has moved, what is late, what is proven |
|
|
117
|
+
| 9 | `wdi-autopilot` — when you would rather review the result than walk steps 6–8 yourself | its preflight page, then its final report and ledger | one **mandate**: scope, what stays parked for you, smoke test by the agent or by you, loop interval, expiry |
|
|
118
|
+
|
|
119
|
+
**Unattended, on request.** `wdi-autopilot` moves owner time from the gates to two points: the mandate before,
|
|
120
|
+
the review after. From the gate you name it runs the same skills, answers what they would have asked, records
|
|
121
|
+
every answer in `.control/memlog/autopilot-<date>.md`, and stops only when every `FR` in scope is closed or the
|
|
122
|
+
mandate expires. It needs three things from the session: permission prompts bypassed (one prompt halts the
|
|
123
|
+
loop), a loop to fire it — `/loop 5m /wdi-autopilot` in Claude Code — and a way past the ticket engines'
|
|
124
|
+
`disable-model-invocation`, which the preflight names: a builder that reads and follows the engine's `SKILL.md`,
|
|
125
|
+
or a copy of the engines inside the repo. The validator `mandate-accept` keeps the one thing the method never
|
|
126
|
+
gives up: a person, dated, at the root of every delegated acceptance.
|
|
117
127
|
|
|
118
128
|
**Refine, do not advance.** When a page does not convince you, run the same skill again and say what is
|
|
119
129
|
wrong — it updates the document it owns. Nothing downstream exists yet, so nothing breaks. Advancing past a
|
|
@@ -282,7 +292,7 @@ which review lenses run, and which review traces a validator will demand.
|
|
|
282
292
|
|
|
283
293
|
---
|
|
284
294
|
|
|
285
|
-
## Five gates,
|
|
295
|
+
## Five gates, eighteen skills
|
|
286
296
|
|
|
287
297
|
| Gate | Decides | Skill |
|
|
288
298
|
|---|---|---|
|
|
@@ -293,7 +303,7 @@ which review lenses run, and which review traces a validator will demand.
|
|
|
293
303
|
| **G5 Release** | Whether it is done and proven | `wdi-build` |
|
|
294
304
|
|
|
295
305
|
Around them: `wdi-init` (scaffold, component birth, depth and risk settings, structure maps),
|
|
296
|
-
`wdi-decision`, `wdi-question`, `wdi-log`, `wdi-help`, `wdi-reconcile`, `wdi-review`, `wdi-report`,
|
|
306
|
+
`wdi-decision`, `wdi-question`, `wdi-log`, `wdi-help`, `wdi-explain-to-me`, `wdi-autopilot`, `wdi-reconcile`, `wdi-review`, `wdi-report`,
|
|
297
307
|
`wdi-systematic-debugging`, and `wdi-upgrade` (moves a corpus written under an older kit into the current
|
|
298
308
|
shape — content moves, nothing is invented).
|
|
299
309
|
|
|
@@ -382,9 +392,9 @@ English, whatever the settings say — it travels to every repo through this pac
|
|
|
382
392
|
|
|
383
393
|
| | |
|
|
384
394
|
|---|---|
|
|
385
|
-
| Overwrites | everything in `.constitution/method/` · the
|
|
395
|
+
| Overwrites | everything in `.constitution/method/` · the eighteen wrappers · `_bmad/custom/*.toml` · the marked block in `AGENTS.md` |
|
|
386
396
|
| Renames | a file whose content needs no judgment to move — `waves.yaml` → `specs.yaml`, the pre-0.5 registry names. Content is never rewritten |
|
|
387
|
-
| Removes | Wrappers the method has retired — a `wdi-*` folder with a `SKILL.md` that is no longer one of the
|
|
397
|
+
| Removes | Wrappers the method has retired — a `wdi-*` folder with a `SKILL.md` that is no longer one of the eighteen. Each removal is printed |
|
|
388
398
|
| Reports | what is still in the OLD shape, as an `upgrade` line — and names `wdi-upgrade` as the next step. The installer does not move content; that is a decision, and the skill's |
|
|
389
399
|
| Keeps | All of `.constitution/project/`, plus your initiative slug and your language choice. A setting somebody already chose is not the installer's to change behind their back |
|
|
390
400
|
| Never resurrects | A folder you retired. On update, absence is treated as a decision |
|
package/bin/wdi-method.js
CHANGED
|
@@ -29,7 +29,7 @@ Never a rule. When it disagrees with a guide, the guide wins and the disagreemen
|
|
|
29
29
|
|
|
30
30
|
| File | Opened when |
|
|
31
31
|
|---|---|
|
|
32
|
-
| [`why/README.md`](why/README.md) | You want the whole shape in five minutes — five gates, two settings,
|
|
32
|
+
| [`why/README.md`](why/README.md) | You want the whole shape in five minutes — five gates, two settings, eighteen skills, WDI ↔ BMad |
|
|
33
33
|
| [`why/artifact-map.md`](why/artifact-map.md) | "Where does this file go", or "does this document exist at my `mode`" |
|
|
34
34
|
| [`why/mode-risk-map.md`](why/mode-risk-map.md) | A `mode` and a `risk_accepted` are set and you want the two side by side — all twelve cells |
|
|
35
35
|
| [`why/rationale.md`](why/rationale.md) | Before changing a rule, to know what you would break |
|
|
@@ -1,199 +1,208 @@
|
|
|
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
|
-
## A decision's first home is the document it governs
|
|
15
|
-
|
|
16
|
-
**Changing a document NEVER requires a `DEC-`.** A `DEC-` is not permission to edit, not a record that
|
|
17
|
-
an edit happened, and not a step between deciding and writing. Where the answer has a home in a design
|
|
18
|
-
document — an `FR` in the PRD, a rule in `business-rules.md`, a boundary in an SDD, a line in the brief —
|
|
19
|
-
**it is written there and nowhere else**, and there is nothing further to do.
|
|
20
|
-
|
|
21
|
-
A `DEC-` is what you write for a decision with **no such home**. That is the whole of its job, plus the
|
|
22
|
-
one mandatory case below.
|
|
23
|
-
|
|
24
|
-
| The answer is about | Where it goes |
|
|
25
|
-
|---|---|
|
|
26
|
-
| What the product promises, does, or forbids | The design document that carries it |
|
|
27
|
-
| How this repo builds — a convention, a stack choice | `.constitution/project/`, once code ratifies it |
|
|
28
|
-
| Accepting a risk, cutting a scope, choosing between two paths **that no document holds** | A `DEC-` |
|
|
29
|
-
| Contradicting an `AD-N` | A `DEC-`, mandatory |
|
|
30
|
-
|
|
31
|
-
This matters most **early**. At G1 a brief is still being formed and at G2 a PRD is still being written;
|
|
32
|
-
almost nothing there is homeless, so almost nothing there is a `DEC-`. Demanding one before the artifact
|
|
33
|
-
it would govern even exists is ceremony at the moment the project can least afford it.
|
|
34
|
-
|
|
35
|
-
## Then one test decides whether to record it at all
|
|
36
|
-
|
|
37
|
-
> **If someone asks in three months why it is like this, is the answer readable from the code?**
|
|
38
|
-
|
|
39
|
-
Yes → it MUST NOT be recorded. No → it is recorded.
|
|
40
|
-
|
|
41
|
-
**A `DEC-` records a state, never an event.** It answers *why is it like this* for someone about to
|
|
42
|
-
change it — forward-looking, present tense. It is not a record that something changed, not a record that
|
|
43
|
-
a document used to say otherwise, and not a record that a review found a conflict. Those are document
|
|
44
|
-
history, and `corpus-guide.md` § The corpus is written in the present tense says they go nowhere.
|
|
45
|
-
|
|
46
|
-
The practical form of the test: **would this file save the next person from a mistake they were about to
|
|
47
|
-
make?** If the honest answer is *"no, but it explains what happened"*, there is no file.
|
|
48
|
-
|
|
49
|
-
**Recording is not mandatory, and a decision nobody recorded is normal rather than negligence.** It
|
|
50
|
-
MUST NOT be logged as debt, raised as a finding, or backfilled later from memory. Without this
|
|
51
|
-
sentence, "not mandatory" is read as "mandatory but allowed to be late".
|
|
52
|
-
|
|
53
|
-
**No case is mandatory any more, and one guard survives all of them.** Three rules used to demand a
|
|
54
|
-
`DEC-` file. Each was protecting something real, and in each the protection was the **stop**, never the
|
|
55
|
-
document:
|
|
56
|
-
|
|
57
|
-
| Was | Is now |
|
|
58
|
-
|---|---|
|
|
59
|
-
| Contradicting an `AD-N` demanded a `DEC-` | It **stops and reaches the owner**. Nobody narrows an invariant silently. The record is the edited `AD-N`, present tense, plus the commit — a `DEC-` only if the reason cannot be read from the spine |
|
|
60
|
-
| `risk_accepted: high` on a sensitive component demanded a risk-acceptance `DEC-` | `risk_accepted_by` names **a person and a date**, in `components.yaml` where the risk is set. `high-risk-named` checks it, and still resolves a `DEC-` id if one is given |
|
|
61
|
-
| Cancelling >30% of a spec's tickets demanded a `DEC-` | The spec is **re-cut** rather than patched. `specs.yaml` is the record |
|
|
62
|
-
|
|
63
|
-
What each of those bought was that a human made the call. That is preserved. What each of them also
|
|
64
|
-
cost — a file, written at the moment the work was blocked — is not.
|
|
65
|
-
|
|
66
|
-
An `AD-N` change stopping is the one that MUST NOT be softened further: it is what stops an architecture
|
|
67
|
-
being narrowed twice by two passes neither of which thought it was doing anything.
|
|
68
|
-
|
|
69
|
-
**Nothing else stops the work at all.** Where a change contradicts an `FR`, a `UC`, a business rule,
|
|
70
|
-
or a document's wording, the agent states the consequence once and the owner decides. If they proceed the
|
|
71
|
-
documents are edited to match — `delivery-flow-guide.md` § When something settled has to change owns the
|
|
72
|
-
matrix, and the survey behind that warning is spent the moment the owner answers.
|
|
73
|
-
|
|
74
|
-
## `AD-N` and `DEC-NNN` are not the same thing
|
|
75
|
-
|
|
76
|
-
| | `AD-N` | `DEC-NNN` |
|
|
77
|
-
|---|---|---|
|
|
78
|
-
| Is | A **living rule** in `ARCHITECTURE-SPINE.md` | A **decision event** |
|
|
79
|
-
| Lives in | The spine | `.control/decisions/` |
|
|
80
|
-
| Changes by | Being edited in place | Never, once `applied` — a new `DEC-` supersedes it |
|
|
81
|
-
| Answers | What is forbidden from now on | What was chosen, and what it cost |
|
|
82
|
-
|
|
83
|
-
An `AD-N` usually has a `DEC-` behind it. Neither MUST be written in place of the other, and one MUST
|
|
84
|
-
NOT be converted into the other.
|
|
85
|
-
|
|
86
|
-
## Shape — three sections, and no more required
|
|
87
|
-
|
|
88
|
-
| Section | States | Required |
|
|
89
|
-
|---|---|---|
|
|
90
|
-
| **Decision** | One sentence, present tense, quotable into a rule | always |
|
|
91
|
-
| **Why** | The context that forced it, in a few lines | always |
|
|
92
|
-
| **Cost** | What becomes harder. A decision with only benefits was not thought through | always |
|
|
93
|
-
| Alternatives | What else was considered, and why each lost | see below |
|
|
94
|
-
| Reversal trigger | The observable condition that makes revisiting this correct | see below |
|
|
95
|
-
| Trace | Where it came from, and what it landed in | see below |
|
|
96
|
-
|
|
97
|
-
The last three MUST be present when the decision reaches a Product Component whose `risk_accepted`
|
|
98
|
-
is `low` in `components.yaml`. Everywhere else they are optional, and an empty one MUST be dropped
|
|
99
|
-
rather than left as a heading with nothing under it.
|
|
100
|
-
|
|
101
|
-
**A `DEC-` MUST NOT hold an open question.** Those belong to `.control/questions/`.
|
|
102
|
-
|
|
103
|
-
**One page, and that is a bound, not a target.** A `DEC-` records **what was chosen and what it cost** —
|
|
104
|
-
not how the answer was reached, not the transcript of the reasoning, not every reading of every clause
|
|
105
|
-
that was weighed on the way. One real decision reached **124 lines** to record that one invariant does not
|
|
106
|
-
reach one artifact; the sentence that mattered was one line and the cost was two.
|
|
107
|
-
|
|
108
|
-
Three things MUST NOT appear in a `DEC-`, and each of them is the derivation leaking in:
|
|
109
|
-
|
|
110
|
-
- The search that found the answer — which files were grepped, which clause was read first.
|
|
111
|
-
- A meta-note about the decision itself: whether it should have been a `DEC-` at all, whether some other
|
|
112
|
-
mechanism was considered and rejected. If that reasoning matters it is the **Why**; usually it does not
|
|
113
|
-
matter and it is nothing.
|
|
114
|
-
- A correction of an earlier draft of the same decision. Drafts are git's.
|
|
115
|
-
|
|
116
|
-
`Alternatives` is the one place a rejected option belongs, it is a **line each**, and it is required only
|
|
117
|
-
where the section table above says so.
|
|
118
|
-
|
|
119
|
-
## Frontmatter
|
|
120
|
-
|
|
121
|
-
| Field | Rule |
|
|
122
|
-
|---|---|
|
|
123
|
-
| `id` | `DEC-NNN`, allocated from `.control/registry/decisions.yaml`, globally. MUST NOT restart per component or per release |
|
|
124
|
-
| `status` | `draft` · `accepted` · `applied` · `superseded` · `rejected` |
|
|
125
|
-
| `touches` | Empty at `draft`. Filled **when the decision is applied**, with the files it actually changed |
|
|
126
|
-
| `type` | Free text, and optional. Written when it is useful — `risk-acceptance`, `course-correction` |
|
|
127
|
-
| `
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
##
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
`
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
- `
|
|
198
|
-
|
|
199
|
-
|
|
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
|
+
## A decision's first home is the document it governs
|
|
15
|
+
|
|
16
|
+
**Changing a document NEVER requires a `DEC-`.** A `DEC-` is not permission to edit, not a record that
|
|
17
|
+
an edit happened, and not a step between deciding and writing. Where the answer has a home in a design
|
|
18
|
+
document — an `FR` in the PRD, a rule in `business-rules.md`, a boundary in an SDD, a line in the brief —
|
|
19
|
+
**it is written there and nowhere else**, and there is nothing further to do.
|
|
20
|
+
|
|
21
|
+
A `DEC-` is what you write for a decision with **no such home**. That is the whole of its job, plus the
|
|
22
|
+
one mandatory case below.
|
|
23
|
+
|
|
24
|
+
| The answer is about | Where it goes |
|
|
25
|
+
|---|---|
|
|
26
|
+
| What the product promises, does, or forbids | The design document that carries it |
|
|
27
|
+
| How this repo builds — a convention, a stack choice | `.constitution/project/`, once code ratifies it |
|
|
28
|
+
| Accepting a risk, cutting a scope, choosing between two paths **that no document holds** | A `DEC-` |
|
|
29
|
+
| Contradicting an `AD-N` | A `DEC-`, mandatory |
|
|
30
|
+
|
|
31
|
+
This matters most **early**. At G1 a brief is still being formed and at G2 a PRD is still being written;
|
|
32
|
+
almost nothing there is homeless, so almost nothing there is a `DEC-`. Demanding one before the artifact
|
|
33
|
+
it would govern even exists is ceremony at the moment the project can least afford it.
|
|
34
|
+
|
|
35
|
+
## Then one test decides whether to record it at all
|
|
36
|
+
|
|
37
|
+
> **If someone asks in three months why it is like this, is the answer readable from the code?**
|
|
38
|
+
|
|
39
|
+
Yes → it MUST NOT be recorded. No → it is recorded.
|
|
40
|
+
|
|
41
|
+
**A `DEC-` records a state, never an event.** It answers *why is it like this* for someone about to
|
|
42
|
+
change it — forward-looking, present tense. It is not a record that something changed, not a record that
|
|
43
|
+
a document used to say otherwise, and not a record that a review found a conflict. Those are document
|
|
44
|
+
history, and `corpus-guide.md` § The corpus is written in the present tense says they go nowhere.
|
|
45
|
+
|
|
46
|
+
The practical form of the test: **would this file save the next person from a mistake they were about to
|
|
47
|
+
make?** If the honest answer is *"no, but it explains what happened"*, there is no file.
|
|
48
|
+
|
|
49
|
+
**Recording is not mandatory, and a decision nobody recorded is normal rather than negligence.** It
|
|
50
|
+
MUST NOT be logged as debt, raised as a finding, or backfilled later from memory. Without this
|
|
51
|
+
sentence, "not mandatory" is read as "mandatory but allowed to be late".
|
|
52
|
+
|
|
53
|
+
**No case is mandatory any more, and one guard survives all of them.** Three rules used to demand a
|
|
54
|
+
`DEC-` file. Each was protecting something real, and in each the protection was the **stop**, never the
|
|
55
|
+
document:
|
|
56
|
+
|
|
57
|
+
| Was | Is now |
|
|
58
|
+
|---|---|
|
|
59
|
+
| Contradicting an `AD-N` demanded a `DEC-` | It **stops and reaches the owner**. Nobody narrows an invariant silently. The record is the edited `AD-N`, present tense, plus the commit — a `DEC-` only if the reason cannot be read from the spine |
|
|
60
|
+
| `risk_accepted: high` on a sensitive component demanded a risk-acceptance `DEC-` | `risk_accepted_by` names **a person and a date**, in `components.yaml` where the risk is set. `high-risk-named` checks it, and still resolves a `DEC-` id if one is given |
|
|
61
|
+
| Cancelling >30% of a spec's tickets demanded a `DEC-` | The spec is **re-cut** rather than patched. `specs.yaml` is the record |
|
|
62
|
+
|
|
63
|
+
What each of those bought was that a human made the call. That is preserved. What each of them also
|
|
64
|
+
cost — a file, written at the moment the work was blocked — is not.
|
|
65
|
+
|
|
66
|
+
An `AD-N` change stopping is the one that MUST NOT be softened further: it is what stops an architecture
|
|
67
|
+
being narrowed twice by two passes neither of which thought it was doing anything.
|
|
68
|
+
|
|
69
|
+
**Nothing else stops the work at all.** Where a change contradicts an `FR`, a `UC`, a business rule,
|
|
70
|
+
or a document's wording, the agent states the consequence once and the owner decides. If they proceed the
|
|
71
|
+
documents are edited to match — `delivery-flow-guide.md` § When something settled has to change owns the
|
|
72
|
+
matrix, and the survey behind that warning is spent the moment the owner answers.
|
|
73
|
+
|
|
74
|
+
## `AD-N` and `DEC-NNN` are not the same thing
|
|
75
|
+
|
|
76
|
+
| | `AD-N` | `DEC-NNN` |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| Is | A **living rule** in `ARCHITECTURE-SPINE.md` | A **decision event** |
|
|
79
|
+
| Lives in | The spine | `.control/decisions/` |
|
|
80
|
+
| Changes by | Being edited in place | Never, once `applied` — a new `DEC-` supersedes it |
|
|
81
|
+
| Answers | What is forbidden from now on | What was chosen, and what it cost |
|
|
82
|
+
|
|
83
|
+
An `AD-N` usually has a `DEC-` behind it. Neither MUST be written in place of the other, and one MUST
|
|
84
|
+
NOT be converted into the other.
|
|
85
|
+
|
|
86
|
+
## Shape — three sections, and no more required
|
|
87
|
+
|
|
88
|
+
| Section | States | Required |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| **Decision** | One sentence, present tense, quotable into a rule | always |
|
|
91
|
+
| **Why** | The context that forced it, in a few lines | always |
|
|
92
|
+
| **Cost** | What becomes harder. A decision with only benefits was not thought through | always |
|
|
93
|
+
| Alternatives | What else was considered, and why each lost | see below |
|
|
94
|
+
| Reversal trigger | The observable condition that makes revisiting this correct | see below |
|
|
95
|
+
| Trace | Where it came from, and what it landed in | see below |
|
|
96
|
+
|
|
97
|
+
The last three MUST be present when the decision reaches a Product Component whose `risk_accepted`
|
|
98
|
+
is `low` in `components.yaml`. Everywhere else they are optional, and an empty one MUST be dropped
|
|
99
|
+
rather than left as a heading with nothing under it.
|
|
100
|
+
|
|
101
|
+
**A `DEC-` MUST NOT hold an open question.** Those belong to `.control/questions/`.
|
|
102
|
+
|
|
103
|
+
**One page, and that is a bound, not a target.** A `DEC-` records **what was chosen and what it cost** —
|
|
104
|
+
not how the answer was reached, not the transcript of the reasoning, not every reading of every clause
|
|
105
|
+
that was weighed on the way. One real decision reached **124 lines** to record that one invariant does not
|
|
106
|
+
reach one artifact; the sentence that mattered was one line and the cost was two.
|
|
107
|
+
|
|
108
|
+
Three things MUST NOT appear in a `DEC-`, and each of them is the derivation leaking in:
|
|
109
|
+
|
|
110
|
+
- The search that found the answer — which files were grepped, which clause was read first.
|
|
111
|
+
- A meta-note about the decision itself: whether it should have been a `DEC-` at all, whether some other
|
|
112
|
+
mechanism was considered and rejected. If that reasoning matters it is the **Why**; usually it does not
|
|
113
|
+
matter and it is nothing.
|
|
114
|
+
- A correction of an earlier draft of the same decision. Drafts are git's.
|
|
115
|
+
|
|
116
|
+
`Alternatives` is the one place a rejected option belongs, it is a **line each**, and it is required only
|
|
117
|
+
where the section table above says so.
|
|
118
|
+
|
|
119
|
+
## Frontmatter
|
|
120
|
+
|
|
121
|
+
| Field | Rule |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `id` | `DEC-NNN`, allocated from `.control/registry/decisions.yaml`, globally. MUST NOT restart per component or per release |
|
|
124
|
+
| `status` | `draft` · `accepted` · `applied` · `superseded` · `rejected` |
|
|
125
|
+
| `touches` | Empty at `draft`. Filled **when the decision is applied**, with the files it actually changed |
|
|
126
|
+
| `type` | Free text, and optional. Written when it is useful — `risk-acceptance`, `course-correction`. One value has a fixed shape: `mandate`, opened by `wdi-autopilot`, whose parameters live under `mandate:` on the registry row and nowhere else |
|
|
127
|
+
| `accepted_by` | Who raised it to `accepted`. A person and a date, the way `risk_accepted_by` is written — or the `DEC-` of a `type: mandate` that delegated the acceptance. `mandate-accept` checks the second form |
|
|
128
|
+
| `supersedes` · `superseded_by` | Both sides of a supersession MUST exist |
|
|
129
|
+
|
|
130
|
+
**There is no `layer:` and no `component:`.** Both were classifications demanded before anything was
|
|
131
|
+
known, and both were guessed as often as they were derived. `touches:` replaces them, and it is filled
|
|
132
|
+
from what happened rather than from what was predicted.
|
|
133
|
+
|
|
134
|
+
The filename is `DEC-NNN-<slug>.md`. It MUST NOT carry a component name — a decision that turns out to
|
|
135
|
+
reach a second component would otherwise need renaming, and the rename breaks every link to it.
|
|
136
|
+
Filenames MUST obey the cross-OS naming rules in `structure-guide.md`.
|
|
137
|
+
|
|
138
|
+
## Status — and why `applied` exists
|
|
139
|
+
|
|
140
|
+
`draft` → `accepted` → `applied`. A change of mind after that produces a **new** `DEC-`.
|
|
141
|
+
|
|
142
|
+
| Status | Means |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `draft` | Being argued. It changes nothing, and that is the point — proposing is cheap |
|
|
145
|
+
| `accepted` | Ratified by the Product Owner. MAY still be corrected in place |
|
|
146
|
+
| `applied` | The documents it governs now say it. **Frozen from here** |
|
|
147
|
+
| `superseded` | Replaced. Names its replacement, and the replacement names it |
|
|
148
|
+
| `rejected` | Seriously considered and turned down. A real status, and it MUST be used — it is what stops the same argument being had twice |
|
|
149
|
+
|
|
150
|
+
**Applying is what freezes a decision, not accepting.** From `applied` onward nothing in the file MUST
|
|
151
|
+
be touched — not the Decision, not the Cost, not a typo in the Why. Documents cite it, and editing it
|
|
152
|
+
destroys the only evidence of what they were changed to match.
|
|
153
|
+
|
|
154
|
+
Before that, an `accepted` `DEC-` MAY be corrected in place. Nothing has been built on it, so there is
|
|
155
|
+
no divergent record to preserve, and **the correction is not recorded anywhere** — the file now reads
|
|
156
|
+
correctly and git holds the change. Logging it would be a second home for a fact git already has, and a
|
|
157
|
+
piece of document history that would save nobody.
|
|
158
|
+
|
|
159
|
+
An agent MUST NOT accept its own `DEC-`. When work is blocked waiting on one, the block is reported,
|
|
160
|
+
never resolved by self-approval.
|
|
161
|
+
|
|
162
|
+
**The one exception is a delegation the owner made in person.** A `DEC-` of `type: mandate`, accepted by
|
|
163
|
+
the owner with a name and a date and carrying an `expires`, lets `wdi-autopilot` accept decisions taken
|
|
164
|
+
under it — `accepted_by: DEC-<mandate>`. What each of the three guards above protected — *a human made
|
|
165
|
+
the call* — still holds: the human made one call, and it is on the record, dated, and ending. The mandate
|
|
166
|
+
itself MUST NOT be accepted by delegation, and `mandate-accept` refuses one that is, one with no
|
|
167
|
+
`expires`, and any decision dated after its mandate lapsed.
|
|
168
|
+
|
|
169
|
+
## Finding a decision
|
|
170
|
+
|
|
171
|
+
`.control/generated/decisions.md` carries a flat table of every `DEC-` with its status and what it
|
|
172
|
+
touches. It is generated, and MUST NOT be written by hand.
|
|
173
|
+
|
|
174
|
+
Searching the memlog for decisions is **retired**. The memlog is a run log again — the record of *why*
|
|
175
|
+
while an artifact was written, and a source when writing a `DEC-`, never an index of them.
|
|
176
|
+
|
|
177
|
+
## Where decisions come from
|
|
178
|
+
|
|
179
|
+
| Trigger | Route |
|
|
180
|
+
|---|---|
|
|
181
|
+
| A meeting reached one | `wdi-log` intent `meeting` writes the minutes; the decision still needs its own `DEC-` |
|
|
182
|
+
| An open question was answered | `wdi-question` closes it; the answer becomes a `DEC-` when it binds |
|
|
183
|
+
| `wdi-systematic-debugging` found a root cause in the design | A `DEC-`. It MUST NOT be absorbed as a code patch |
|
|
184
|
+
| A planning assumption turned out to be void | `wdi-decision`, which wraps `bmad-correct-course`. The result is a `DEC-` of `type: course-correction` |
|
|
185
|
+
| A ticket contradicts an `AD-N` | The ticket stops. This is the one mandatory case |
|
|
186
|
+
| `wdi-reconcile` found two documents disagreeing with no clear winner | That is a decision, not drift |
|
|
187
|
+
| `wdi-autopilot` took a decision with no home in any design document | A `DEC-`, accepted under the mandate. The ledger records every decision it took; only the homeless ones become a `DEC-` |
|
|
188
|
+
|
|
189
|
+
Minutes MUST NOT be treated as a decision record. They say what was discussed; a `DEC-` says what was
|
|
190
|
+
chosen and what it cost.
|
|
191
|
+
|
|
192
|
+
**`SCP-` is retired.** A course correction is a decision, and it is a `DEC-` with
|
|
193
|
+
`type: course-correction`. No second code names the same thing.
|
|
194
|
+
|
|
195
|
+
## Rules
|
|
196
|
+
|
|
197
|
+
- A `DEC-` MUST be opened **before** the code that depends on it, never written afterwards to explain
|
|
198
|
+
code that already exists.
|
|
199
|
+
- The applying pass MUST NOT improvise. When an `accepted` `DEC-` does not say clearly what a document
|
|
200
|
+
has to change, the decision is incomplete and is sent back.
|
|
201
|
+
- Applying MUST NOT widen beyond what the decision says. A neighbouring paragraph that now looks wrong
|
|
202
|
+
is a finding to report.
|
|
203
|
+
- `applied-dec-touches` checks that every `applied` `DEC-` names a non-empty `touches`. It MUST NOT check that a decision
|
|
204
|
+
serves an `FR` or `NFR` — *"the filter works like this"* serves none, and it is exactly the kind of
|
|
205
|
+
decision this guide exists to keep.
|
|
206
|
+
- `ADR-NNN` written inside a document frozen before 2026-08-18 is a **retired alias** for `DEC-NNN`
|
|
207
|
+
with the same number. It MUST NOT be read as a second, missing record, and those documents MUST NOT
|
|
208
|
+
be rewritten to change the prefix.
|