wdi-method 0.6.7 → 0.6.8

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.
@@ -1,187 +1,194 @@
1
- ---
2
- name: wdi-upgrade
3
- description: Use right after `wdi-method update` moved this repo to a newer method version. Finds every document and registry file still in the OLD shape, re-homes their content into the new one — registry rows out of prose, pointers where copies were, the rendered trees born — and verifies green. Runs once per version jump; safe to re-run.
4
- ---
5
-
6
- # WDI Upgrade
7
-
8
- `wdi-method update` does the mechanical half of a version jump: it overwrites the kit, renames files whose
9
- content needs no judgment, seeds what is new, prunes what is retired. It stops exactly where a decision
10
- about **content** begins — which PRD an `FR` belongs to, whether a sentence in the old brief was an
11
- assumption or a constraint. Those are this skill's half.
12
-
13
- **This skill's content is `.what/` and `.how/`** — the corpus a human reads. It does NOT cover
14
- `.control/memlog/` or a registry row: an autopilot ledger's filename is `update`'s own mechanical rename
15
- (the same way `waves.yaml` became `specs.yaml`), a stale mandate setting is a printed warning at `update`
16
- time because overwriting it would be overwriting a value the owner already chose, and a ledger's internal
17
- shape is healed by `wdi-autopilot` itself on its next run, because only it can read git and the registry to
18
- know where that run actually stands. Route those three there; this skill's report would have nothing to say
19
- about any of them.
20
-
21
- **This is the one skill allowed to edit `brief.md`, `prd.md`, an SRS, an SDD, or a C4 file directly.**
22
- Every other skill is forbidden, because a hand edit makes the memlog lie about how the document was
23
- produced. An upgrade produces nothing: it moves sentences that already exist into the home the new
24
- version gives them, word for word. The memlog stays true, and this skill's report is the record.
25
-
26
- ## Inputs
27
-
28
- | Source | What it answers |
29
- |---|---|
30
- | `.control/wdi-method.yaml` | The version now installed — the shape everything below MUST end in |
31
- | The `update` run's own output | The `upgrade` line lists what it detected as pending; start there |
32
- | `.control/registry/` | What is already a row, so nothing is landed twice |
33
- | `.what/_product-brief/brief.md` · `.what/_prd/*/prd.md` | The two documents whose shape changed most |
34
- | `.what/<pc>/SRS-<pc>.md` · `.how/<pc>/SDD-<pc>.md` · `.how/_platform/c4-l2-containers.md` | The three that used to carry a copy of a registry table |
35
- | `.constitution/method/document/templates/` | The target shape of every document above |
36
-
37
- ## Step 1 — Detect, and show the list before touching anything
38
-
39
- Probe each item below; a probe is a file or heading that exists only in the old shape. List every hit
40
- to the owner as a checklist, in the order below — it is a dependency order, and doing a later item
41
- before an earlier one lands content in a file that the earlier item is about to change.
42
-
43
- | # | Probe | Old shape | New home |
44
- |---|---|---|---|
45
- | 1 | `.control/registry/requirements.yaml` exists | one file for `BG` · `CAP` · `FR` · `NFR` · `UJ` | `goals.yaml` (`BG`) · `requirements-<slug>.yaml` per PRD (`CAP` · `FR` · `NFR` · `UJ`) |
46
- | 2 | `specs.yaml` has `W<n>` ids, or `epics:` / `stories:` keys | pre-rename plan | re-cut through `wdi-build` — **not this skill**; report it and move on |
47
- | 3 | `brief.md` has `## Executive Summary`, `## Vision`, `## Assumptions`, or `## Prerequisites`; or `## Goals` lists `BG-` statements | 14-section brief | 8 sections: `Why` merges Summary + Vision; Goals is a pointer, its rows in `goals.yaml`; Assumptions → `questions/assumptions.md`; Prerequisites → `questions/external.md` |
48
- | 4 | any `prd.md` has a section **named** Document Purpose, Glossary, Non-Goals, Open Questions, or Assumptions Index — under whatever number that kit gave it — or `**Proof of done:**` under a feature | 12-section PRD with `FR` blocks | 7 sections; `FR`/`NFR` text → `requirements-<slug>.yaml`, the PRD keeps `Realizes:` ids; Glossary → `product-glossary.md`; §8/§9 → `questions/`; §1 becomes a delta |
49
- | 5 | any `SRS-<pc>.md` `## UC Catalogue` has `\| UC-` rows | catalogue copied from `usecases.yaml` | one pointer line; the rows live in `usecases.yaml` |
50
- | 6 | any `SDD-<pc>.md` `## Inherited Constraints` has a `Quoted rule` column, or `> ` blockquote lines under an `**AD-N — …**` heading, or the sentence `Quoted verbatim from` | `AD-N` text copied from the spine, in either of the two shapes SDDs were written in | ids only; the rendered SDD shows the text |
51
- | 7 | `c4-l2-containers.md` has a `\| Container \| Product Components living in it \|` table | matrix copied from `components.yaml` | one pointer line |
52
- | 8 | `.control/generated/brief.md`, `blueprint.md`, or `prd-*.md` exist | human pages in the machine folder | `.what-rendered/` · `.how-rendered/` — `render` clears the old ones |
53
- | 9 | `.what-rendered/` or `.how-rendered/` absent | no reader's tree yet | born by `render` |
54
- | 10 | any `.md` outside `.constitution/` cites `.control/generated/brief.md`, `blueprint.md`, or `prd-<slug>.md` | a pointer at a page that moved | `.what-rendered/_product-brief/brief.md` · `.how-rendered/blueprint.md` · `.what-rendered/_prd/<slug>/prd.md` — `cites-resolve` fails until it is repointed |
55
-
56
- Anything not in the list is not this skill's. A brief that already has `## Why` is done; skip it.
57
-
58
- ## Step 2 Registry first
59
-
60
- **1 the requirement split.** A row written under an older kit carries `text:` where a newer one
61
- carries `title:`; both are the short label, the renderer and `timeline.py` read either, and one MUST
62
- NOT be copied into the other — that is two homes for one fact. Which PRD a row belongs to is read from
63
- the rows before it is read from the prose. A `CAP` or `UJ` with a `prd:` field goes to `requirements-<that slug>.yaml`; an `FR`
64
- follows its `capability:` to that CAP's file; an `NFR` follows its `component:` to the PRD whose CAPs
65
- own that componenta `BG` is product-level and never decides an NFR's home on its own, so `goal:` is
66
- only a tie-breaker when that component's CAPs span two PRDs. On a product with exactly **one** PRD every row belongs to that
67
- PRD by construction write them all to its file and skip the citation scan. Otherwise, only a row with
68
- none of those fields falls back to the PRD whose prose cites its id — and an id cited by **two** PRDs
69
- is reported, not placed. The citation scan still runs on every row as a cross-check: a row whose
70
- structural home and citing PRD disagree is reported with both names. Write the row, unchanged, into
71
- its file; `goals:` rows go to `goals.yaml`. A sentence moved into a YAML value keeps its punctuation
72
- and its markup: when it holds `: ` or `#` or starts with a quote, wrap the value in double quotes or a
73
- `>-` block — never trade a colon for a dash or strip `**` and backticks to make it a plain scalar. A row with no home is reported by id, not guessed: the
74
- owner names it. When every row has moved, delete `requirements.yaml`; `id-allocated-once` fails if a
75
- row was copied instead of moved.
76
-
77
- Run `validate.py --check`. Green here means the registry is whole before any document starts pointing
78
- at it.
79
-
80
- ## Step 3 Documents, oldest gate first
81
-
82
- **3 brief.** Merge `## Executive Summary` and `## Vision` into one `## Why`, keeping every sentence
83
- that says something the other did not. Each `BG-N` statement under `## Goals` MUST already be a row in
84
- `goals.yaml` (Step 2); replace the list with the pointer line from the template. Each `## Assumptions`
85
- item becomes a row in `.control/questions/assumptions.md` with `Whose: owner`; each `## Prerequisites`
86
- item a row in `external.md` — **after** checking that no `OQ-` row already states it, because a brief
87
- written under an earlier kit usually landed them already and a second row is a copy. A prerequisite
88
- the brief itself marks satisfied is dropped, not landed as open. A `questions/` table written before
89
- the `Whose` column existed (`| id | Assumption | Cost if wrong | Taken | By |`) gets the column added —
90
- header and separator, and an empty cell on every existing row, which the validator counts as
91
- `unstated`, which is what they are. The rows this skill lands say `owner`. `Cost if wrong` is `—` when
92
- the source never stated one; it is not invented. An open question the source never marked blocking is
93
- filed in `assumptions.md`, as the template's three tests say. Delete both sections, and say how many
94
- items were already rows. Check `## Success Criteria` names one measurable
95
- figure if it does not, that is a finding for the owner, not a sentence for this skill to invent.
96
-
97
- **4 each PRD.** Sections are matched **by name, never by number**: the numbers moved between kits
98
- (one kit numbers Non-Goals §5 and Open Questions §8; an older one numbers Non-Goals §7, MVP Scope §8,
99
- Open Questions §10), so a step that says "delete §8" deletes MVP Scope on the wrong corpus. Delete
100
- `Document Purpose`. Every `Glossary` term not yet in `.control/product-glossary.md` is added there,
101
- verbatim; then delete `Glossary`. Every `Non-Goals` item MUST already be in the brief's Scope Out or
102
- this PRD's `MVP Scope Out of Scope` if neither holds it, add it to the one it belongs to; then
103
- delete `Non-Goals`. Every `Open Questions` and `Assumptions Index` item becomes a `questions/` row
104
- (after the same already-a-row check as the brief's); delete both.
105
- Under each feature, every `FR` block is folded into its row in `requirements-<slug>.yaml` (Step 2)
106
- before the block goes: the block's description paragraph the prose between the `#### FR-N` heading
107
- and the first `**…:**` label becomes the row's `statement:` when the row has none (the row's `title`
108
- stays). **This is the one move with no validator behind it**, so count it: blocks with a paragraph
109
- versus rows that now carry `statement:` MUST match, and Step 5 reports both numbers. A run that deletes
110
- the blocks and lands zero statements has thrown the requirement's own sentence away; its `**Consequences (testable):**` bullets move verbatim to
111
- `addendum.md` under `## Technical how testable consequences per FR`, appended **after** the sections
112
- already there, one `### FR-N title` each,
113
- because `prd-guide.md` repealed the double proof of done and that is where the technical restatement
114
- lives now; its `**Proof of done:**` is compared with the row's `proof` when they differ, the
115
- **registry is kept** (it is the declared SSOT), the PRD's is dropped, and both texts are reported side
116
- by side for the owner, never merged. Then the block becomes `**Realizes:** FR-a, FR-b, NFR-c`, and a
117
- `**Functional Requirements:**` label left with nothing under it is deleted the rendered page rebuilds
118
- the blocks from the rows. When the deletions are done, **put the surviving `##` sections in the
119
- template's order and renumber them**moving a whole section is a move, not an edit, and a file whose
120
- `## 6` sits above its `## 4` tells the AI reader the numbers lie. The order 1 Why This Initiative · 2 Target User · 3 Features · 4 MVP Scope · 5 Success
121
- Metrics · 6 Cross-Cutting NFRs · 7 Constraints and Guardrails and the `###` beneath them to match
122
- (`### 8.2` `### 4.2`). Numbers are not sentences; leaving `## 4. Features` beside `## 8. MVP Scope`
123
- tells the next reader two sections went missing. A `UJ-N` the prose names that has no row in any requirement file is
124
- not given one it is marked with an HTML comment where it stands and reported; `wdi-product`
125
- allocates ids. A moved sentence that cites a section number (`§ 8`) of a section this step deletes
126
- keeps the numberit is reported as wording for the owner, not repointed, because its new home is a
127
- judgment. `## 1. Vision` becomes `## 1. Why This Initiative`: delete only the sentences
128
- that also appear, word for word, in the brief's `Why`; what remains is left whole under an HTML comment
129
- saying the new shape wants a delta, because deciding which paraphrases are copies is the owner's. On a
130
- single-initiative product that is one line pointing at the brief write it and say so.
131
-
132
- **5 each SRS.** Every `| UC-` row MUST already be in `usecases.yaml` with the same `critical`. A row
133
- missing there is landed first. Then the table becomes the template's pointer line.
134
-
135
- **6 each SDD.** In `## Inherited Constraints`, drop the `Quoted rule` column; keep `AD` and `How it
136
- lands here`. In the blockquote shape, drop the `> ` lines and the `Quoted verbatim from` sentence; keep
137
- the `**AD-N title**` heading and the landing prose under it, each heading on its own line. An `AD-N`
138
- cited here that is not in the spine is a finding.
139
-
140
- **7 C4 L2.** Every PC listed in the table MUST have that container in its `containers:`. Then the
141
- table becomes the pointer line.
142
-
143
- **8 pointers at the moved pages.** Every `.md` that cites `.control/generated/brief.md`,
144
- `blueprint.md`, or `prd-<slug>.md` **and that `cites-resolve` reads** is repointed to the new path a
145
- path substitution, nothing else in the sentence changes. That includes a product's own scratch and
146
- issue notes. It excludes what the validator excludes: `.control/memlog/`, `.control/decisions/`,
147
- `.control/reports/`, `questions/answered.md`, and `_bmad-output/` those describe the past, and a
148
- path rewritten there falsifies a record; the installer's probe skips them for the same reason.
149
-
150
- ## Step 4 Render, then validate
151
-
152
- ```bash
153
- uv run .constitution/method/scripts/validate.py --generate
154
- ```
155
-
156
- This writes every reader's page into `.what-rendered/` and `.how-rendered/`, and clears the human pages
157
- that used to sit in `.control/generated/`. Then `--check` MUST be green. Every finding at this point is
158
- either a row that moved wrong in Step 2 or a pointer that points at nothing — both are this skill's to
159
- fix before it reports done.
160
-
161
- ## Step 5 — Report, and commit once
162
-
163
- What moved, file by file · what was landed into the registry, by id · what could not be placed and
164
- needs the owner · the rendered pages now waiting to be read, one per gate · validators green. Then
165
- **one** commit: `chore(method): upgrade <from> <to>`. Not one per documentthe upgrade is one
166
- event.
167
-
168
- ## Rules
169
-
170
- - You MUST NOT change a sentence while moving it. Wording that reads wrong in its new home is a
171
- finding for the owning skill, later.
172
- - You MUST NOT invent a home. An `FR` no PRD cites, a Non-Goal neither boundary holds, an `AD-N` not
173
- in the spine — each is reported by id and left where it was.
174
- - You MUST NOT write your findings into the corpus. A registry file carries rows and nothing about
175
- the upgrade that produced them; a gap in this skill goes in the Step 5 report. The one exception is
176
- the HTML comment the steps above name, placed where the owner will read the document.
177
- - You MUST NOT re-cut `specs.yaml`. That is `wdi-build`'s, where a human can see it.
178
- - You MUST NOT touch `.control/decisions/` or `.control/reports/`. A frozen `DEC-` that cites `V26` or
179
- `W3` is history; the alias rule in `corpus-guide.md` covers it.
180
- - Re-running on an upgraded repo MUST find nothing and say so. Every probe in Step 1 is idempotent.
181
-
182
- ## Output
183
-
184
- The Step 1 checklist with each item marked done · skipped (already new shape) · left for the owner, with
185
- the id list for the last · the registry rows landed · **statements landed / FR blocks that had a
186
- paragraph** · consequences moved · `questions/` rows added and rows found already present · proof-of-done
187
- divergences, both texts · the path of every rendered page · the validator result · the commit.
1
+ ---
2
+ name: wdi-upgrade
3
+ description: Use right after `wdi-method update` moved this repo to a newer method version. Finds every document and registry file still in the OLD shape, re-homes their content into the new one — registry rows out of prose, pointers where copies were, the rendered trees born — and verifies green. Runs once per version jump; safe to re-run.
4
+ ---
5
+
6
+ # WDI Upgrade
7
+
8
+ `wdi-method update` does the mechanical half of a version jump: it overwrites the kit, renames files whose
9
+ content needs no judgment, seeds what is new, prunes what is retired. It stops exactly where a decision
10
+ about **content** begins — which PRD an `FR` belongs to, whether a sentence in the old brief was an
11
+ assumption or a constraint. Those are this skill's half.
12
+
13
+ **This skill's content is `.what/` and `.how/`** — the corpus a human reads. It does NOT cover
14
+ `.control/memlog/` or a registry row: an autopilot ledger's filename is `update`'s own mechanical rename
15
+ (the same way `waves.yaml` became `specs.yaml`), a stale mandate setting is a printed warning at `update`
16
+ time because overwriting it would be overwriting a value the owner already chose, and a ledger's internal
17
+ shape is healed by `wdi-autopilot` itself on its next run, because only it can read git and the registry to
18
+ know where that run actually stands. Route those three there; this skill's report would have nothing to say
19
+ about any of them.
20
+
21
+ **This is the one skill allowed to edit `brief.md`, `prd.md`, an SRS, an SDD, or a C4 file directly.**
22
+ Every other skill is forbidden, because a hand edit makes the memlog lie about how the document was
23
+ produced. An upgrade produces nothing: it moves sentences that already exist into the home the new
24
+ version gives them, word for word. The memlog stays true, and this skill's report is the record.
25
+
26
+ ## Inputs
27
+
28
+ | Source | What it answers |
29
+ |---|---|
30
+ | `.control/wdi-method.yaml` | The version now installed — the shape everything below MUST end in |
31
+ | The `update` run's own output | The `upgrade` line lists what it detected as pending; start there |
32
+ | `.control/registry/` | What is already a row, so nothing is landed twice |
33
+ | `.what/_product-brief/brief.md` · `.what/_prd/*/prd.md` | The two documents whose shape changed most |
34
+ | `.what/<pc>/SRS-<pc>.md` · `.how/<pc>/SDD-<pc>.md` · `.how/_platform/c4-l2-containers.md` | The three that used to carry a copy of a registry table |
35
+ | `.constitution/method/document/templates/` | The target shape of every document above |
36
+
37
+ ## Step 1 — Detect, and show the list before touching anything
38
+
39
+ Probe each item below; a probe is a file or heading that exists only in the old shape. List every hit
40
+ to the owner as a checklist, in the order below — it is a dependency order, and doing a later item
41
+ before an earlier one lands content in a file that the earlier item is about to change.
42
+
43
+ | # | Probe | Old shape | New home |
44
+ |---|---|---|---|
45
+ | 1 | `.control/registry/requirements.yaml` exists | one file for `BG` · `CAP` · `FR` · `NFR` · `UJ` | `goals.yaml` (`BG`) · `requirements-<slug>.yaml` per PRD (`CAP` · `FR` · `NFR` · `UJ`) |
46
+ | 2 | `specs.yaml` has `W<n>` ids, or `epics:` / `stories:` keys | pre-rename plan | re-cut through `wdi-build` — **not this skill**; report it and move on |
47
+ | 3 | `brief.md` has `## Executive Summary`, `## Vision`, `## Assumptions`, or `## Prerequisites`; or `## Goals` lists `BG-` statements | 14-section brief | 8 sections: `Why` merges Summary + Vision; Goals is a pointer, its rows in `goals.yaml`; Assumptions → `questions/assumptions.md`; Prerequisites → `questions/external.md` |
48
+ | 4 | any `prd.md` has a section **named** Document Purpose, Glossary, Non-Goals, Open Questions, or Assumptions Index — under whatever number that kit gave it — or `**Proof of done:**` under a feature | 12-section PRD with `FR` blocks | 7 sections; `FR`/`NFR` text → `requirements-<slug>.yaml`, the PRD keeps `Realizes:` ids; Glossary → `product-glossary.md`; §8/§9 → `questions/`; §1 becomes a delta |
49
+ | 5 | any `SRS-<pc>.md` `## UC Catalogue` has `\| UC-` rows | catalogue copied from `usecases.yaml` | one pointer line; the rows live in `usecases.yaml` |
50
+ | 6 | any `SDD-<pc>.md` `## Inherited Constraints` has a `Quoted rule` column, or `> ` blockquote lines under an `**AD-N — …**` heading, or the sentence `Quoted verbatim from` | `AD-N` text copied from the spine, in either of the two shapes SDDs were written in | ids only; the rendered SDD shows the text |
51
+ | 7 | `c4-l2-containers.md` has a `\| Container \| Product Components living in it \|` table | matrix copied from `components.yaml` | one pointer line |
52
+ | 8 | `.control/generated/brief.md`, `blueprint.md`, or `prd-*.md` exist | human pages in the machine folder | `.what-rendered/` · `.how-rendered/` — `render` clears the old ones |
53
+ | 9 | `.what-rendered/` or `.how-rendered/` absent | no reader's tree yet | born by `render` |
54
+ | 10 | any `.md` outside `.constitution/` cites `.control/generated/brief.md`, `blueprint.md`, or `prd-<slug>.md` | a pointer at a page that moved | `.what-rendered/_product-brief/brief.md` · `.how-rendered/blueprint.md` · `.what-rendered/_prd/<slug>/prd.md` — `cites-resolve` fails until it is repointed |
55
+ | 11 | `docs/agents/issue-tracker.md` does not contain the words `seeded by ``wdi-method``` | the engines' config as `/setup-matt-pocock-skills` wrote it: everything in `.scratch/` with no registry behind it, `specs.yaml` never mentioned | the method's own answer. **`npx wdi-method engines --fix`** rewrites it and keeps the old text as `issue-tracker.md.bak`. Two of four live repos still had upstream's, which is why their tickets landed wherever the engine guessed |
56
+ | 12 | any `spec_folder` in `specs.yaml` is outside `.scratch/`, or its leaf does not begin with the spec's own id | spec folders under `_bmad-output/specs/`, leaf named freely — four repos wrote it four ways, one of them all four inside itself | `.scratch/<spec-id>-<slug>/`. Move the directory, rewrite the `spec_folder` row, then repoint every cite — `cites-resolve` is red until you do, and it is how you find them all |
57
+
58
+ Items 11 and 12 are the engines' half of a version jump, and they come FIRST when both are hit:
59
+ item 11 writes where a spec's files belong, item 12 moves them there. Doing 12 first means moving
60
+ folders to a location the engines have not been told about, and the next `to-tickets` writes to the old
61
+ one anyway.
62
+
63
+ Anything not in the list is not this skill's. A brief that already has `## Why` is done; skip it.
64
+
65
+ ## Step 2Registry first
66
+
67
+ **1the requirement split.** A row written under an older kit carries `text:` where a newer one
68
+ carries `title:`; both are the short label, the renderer and `timeline.py` read either, and one MUST
69
+ NOT be copied into the other that is two homes for one fact. Which PRD a row belongs to is read from
70
+ the rows before it is read from the prose. A `CAP` or `UJ` with a `prd:` field goes to `requirements-<that slug>.yaml`; an `FR`
71
+ follows its `capability:` to that CAP's file; an `NFR` follows its `component:` to the PRD whose CAPs
72
+ own that component a `BG` is product-level and never decides an NFR's home on its own, so `goal:` is
73
+ only a tie-breaker when that component's CAPs span two PRDs. On a product with exactly **one** PRD every row belongs to that
74
+ PRD by construction write them all to its file and skip the citation scan. Otherwise, only a row with
75
+ none of those fields falls back to the PRD whose prose cites its id — and an id cited by **two** PRDs
76
+ is reported, not placed. The citation scan still runs on every row as a cross-check: a row whose
77
+ structural home and citing PRD disagree is reported with both names. Write the row, unchanged, into
78
+ its file; `goals:` rows go to `goals.yaml`. A sentence moved into a YAML value keeps its punctuation
79
+ and its markup: when it holds `: ` or `#` or starts with a quote, wrap the value in double quotes or a
80
+ `>-` blocknever trade a colon for a dash or strip `**` and backticks to make it a plain scalar. A row with no home is reported by id, not guessed: the
81
+ owner names it. When every row has moved, delete `requirements.yaml`; `id-allocated-once` fails if a
82
+ row was copied instead of moved.
83
+
84
+ Run `validate.py --check`. Green here means the registry is whole before any document starts pointing
85
+ at it.
86
+
87
+ ## Step 3 Documents, oldest gate first
88
+
89
+ **3 brief.** Merge `## Executive Summary` and `## Vision` into one `## Why`, keeping every sentence
90
+ that says something the other did not. Each `BG-N` statement under `## Goals` MUST already be a row in
91
+ `goals.yaml` (Step 2); replace the list with the pointer line from the template. Each `## Assumptions`
92
+ item becomes a row in `.control/questions/assumptions.md` with `Whose: owner`; each `## Prerequisites`
93
+ item a row in `external.md` **after** checking that no `OQ-` row already states it, because a brief
94
+ written under an earlier kit usually landed them already and a second row is a copy. A prerequisite
95
+ the brief itself marks satisfied is dropped, not landed as open. A `questions/` table written before
96
+ the `Whose` column existed (`| id | Assumption | Cost if wrong | Taken | By |`) gets the column added —
97
+ header and separator, and an empty cell on every existing row, which the validator counts as
98
+ `unstated`, which is what they are. The rows this skill lands say `owner`. `Cost if wrong` is `—` when
99
+ the source never stated one; it is not invented. An open question the source never marked blocking is
100
+ filed in `assumptions.md`, as the template's three tests say. Delete both sections, and say how many
101
+ items were already rows. Check `## Success Criteria` names one measurable
102
+ figure if it does not, that is a finding for the owner, not a sentence for this skill to invent.
103
+
104
+ **4 each PRD.** Sections are matched **by name, never by number**: the numbers moved between kits
105
+ (one kit numbers Non-Goals §5 and Open Questions §8; an older one numbers Non-Goals §7, MVP Scope §8,
106
+ Open Questions §10), so a step that says "delete §8" deletes MVP Scope on the wrong corpus. Delete
107
+ `Document Purpose`. Every `Glossary` term not yet in `.control/product-glossary.md` is added there,
108
+ verbatim; then delete `Glossary`. Every `Non-Goals` item MUST already be in the brief's Scope Out or
109
+ this PRD's `MVP Scope Out of Scope` if neither holds it, add it to the one it belongs to; then
110
+ delete `Non-Goals`. Every `Open Questions` and `Assumptions Index` item becomes a `questions/` row
111
+ (after the same already-a-row check as the brief's); delete both.
112
+ Under each feature, every `FR` block is folded into its row in `requirements-<slug>.yaml` (Step 2)
113
+ before the block goes: the block's description paragraph the prose between the `#### FR-N` heading
114
+ and the first `**…:**` label becomes the row's `statement:` when the row has none (the row's `title`
115
+ stays). **This is the one move with no validator behind it**, so count it: blocks with a paragraph
116
+ versus rows that now carry `statement:` MUST match, and Step 5 reports both numbers. A run that deletes
117
+ the blocks and lands zero statements has thrown the requirement's own sentence away; its `**Consequences (testable):**` bullets move verbatim to
118
+ `addendum.md` under `## Technical how testable consequences per FR`, appended **after** the sections
119
+ already there, one `### FR-Ntitle` each,
120
+ because `prd-guide.md` repealed the double proof of done and that is where the technical restatement
121
+ lives now; its `**Proof of done:**` is compared with the row's `proof` when they differ, the
122
+ **registry is kept** (it is the declared SSOT), the PRD's is dropped, and both texts are reported side
123
+ by side for the owner, never merged. Then the block becomes `**Realizes:** FR-a, FR-b, NFR-c`, and a
124
+ `**Functional Requirements:**` label left with nothing under it is deleted the rendered page rebuilds
125
+ the blocks from the rows. When the deletions are done, **put the surviving `##` sections in the
126
+ template's order and renumber them** moving a whole section is a move, not an edit, and a file whose
127
+ `## 6` sits above its `## 4` tells the AI reader the numbers lie. The order 1 Why This Initiative · 2 Target User · 3 Features · 4 MVP Scope · 5 Success
128
+ Metrics · 6 Cross-Cutting NFRs · 7 Constraints and Guardrails and the `###` beneath them to match
129
+ (`### 8.2` `### 4.2`). Numbers are not sentences; leaving `## 4. Features` beside `## 8. MVP Scope`
130
+ tells the next reader two sections went missing. A `UJ-N` the prose names that has no row in any requirement file is
131
+ not given one — it is marked with an HTML comment where it stands and reported; `wdi-product`
132
+ allocates ids. A moved sentence that cites a section number (`§ 8`) of a section this step deletes
133
+ keeps the number — it is reported as wording for the owner, not repointed, because its new home is a
134
+ judgment. `## 1. Vision` becomes `## 1. Why This Initiative`: delete only the sentences
135
+ that also appear, word for word, in the brief's `Why`; what remains is left whole under an HTML comment
136
+ saying the new shape wants a delta, because deciding which paraphrases are copies is the owner's. On a
137
+ single-initiative product that is one line pointing at the brief write it and say so.
138
+
139
+ **5 — each SRS.** Every `| UC-` row MUST already be in `usecases.yaml` with the same `critical`. A row
140
+ missing there is landed first. Then the table becomes the template's pointer line.
141
+
142
+ **6 — each SDD.** In `## Inherited Constraints`, drop the `Quoted rule` column; keep `AD` and `How it
143
+ lands here`. In the blockquote shape, drop the `> ` lines and the `Quoted verbatim from` sentence; keep
144
+ the `**AD-N title**` heading and the landing prose under it, each heading on its own line. An `AD-N`
145
+ cited here that is not in the spine is a finding.
146
+
147
+ **7 C4 L2.** Every PC listed in the table MUST have that container in its `containers:`. Then the
148
+ table becomes the pointer line.
149
+
150
+ **8 pointers at the moved pages.** Every `.md` that cites `.control/generated/brief.md`,
151
+ `blueprint.md`, or `prd-<slug>.md` **and that `cites-resolve` reads** is repointed to the new path — a
152
+ path substitution, nothing else in the sentence changes. That includes a product's own scratch and
153
+ issue notes. It excludes what the validator excludes: `.control/memlog/`, `.control/decisions/`,
154
+ `.control/reports/`, `questions/answered.md`, and `_bmad-output/` — those describe the past, and a
155
+ path rewritten there falsifies a record; the installer's probe skips them for the same reason.
156
+
157
+ ## Step 4 Render, then validate
158
+
159
+ ```bash
160
+ uv run .constitution/method/scripts/validate.py --generate
161
+ ```
162
+
163
+ This writes every reader's page into `.what-rendered/` and `.how-rendered/`, and clears the human pages
164
+ that used to sit in `.control/generated/`. Then `--check` MUST be green. Every finding at this point is
165
+ either a row that moved wrong in Step 2 or a pointer that points at nothing both are this skill's to
166
+ fix before it reports done.
167
+
168
+ ## Step 5 — Report, and commit once
169
+
170
+ What moved, file by file · what was landed into the registry, by id · what could not be placed and
171
+ needs the owner · the rendered pages now waiting to be read, one per gate · validators green. Then
172
+ **one** commit: `chore(method): upgrade <from> <to>`. Not one per document the upgrade is one
173
+ event.
174
+
175
+ ## Rules
176
+
177
+ - You MUST NOT change a sentence while moving it. Wording that reads wrong in its new home is a
178
+ finding for the owning skill, later.
179
+ - You MUST NOT invent a home. An `FR` no PRD cites, a Non-Goal neither boundary holds, an `AD-N` not
180
+ in the spine each is reported by id and left where it was.
181
+ - You MUST NOT write your findings into the corpus. A registry file carries rows and nothing about
182
+ the upgrade that produced them; a gap in this skill goes in the Step 5 report. The one exception is
183
+ the HTML comment the steps above name, placed where the owner will read the document.
184
+ - You MUST NOT re-cut `specs.yaml`. That is `wdi-build`'s, where a human can see it.
185
+ - You MUST NOT touch `.control/decisions/` or `.control/reports/`. A frozen `DEC-` that cites `V26` or
186
+ `W3` is history; the alias rule in `corpus-guide.md` covers it.
187
+ - Re-running on an upgraded repo MUST find nothing and say so. Every probe in Step 1 is idempotent.
188
+
189
+ ## Output
190
+
191
+ The Step 1 checklist with each item marked done · skipped (already new shape) · left for the owner, with
192
+ the id list for the last · the registry rows landed · **statements landed / FR blocks that had a
193
+ paragraph** · consequences moved · `questions/` rows added and rows found already present · proof-of-done
194
+ divergences, both texts · the path of every rendered page · the validator result · the commit.
@@ -25,10 +25,13 @@ The repo layout is governed by `corpus-guide.md` and mapped by
25
25
  | `.how/` | How it is built |
26
26
  | `.what-rendered/` · `.how-rendered/` | The two above, assembled for a human to read — one page per gate, at the mirror path. Regenerated by `validate.py`, never edited, never read by a skill |
27
27
  | `_bmad-output/` | Run workspace; MUST be in git, not curated |
28
+ | `.scratch/` | One directory per effort: a spec's `SPEC.md` and its ticket files, and ad hoc work that has no `FR` yet. MUST be in git — the corpus cites into it by path |
28
29
  | `.work/` | Scratch; MUST be in git, emptied when a task closes |
29
30
  | *(application roots)* | Application code — named and mapped in `.control/structure-codebase.md` |
30
31
 
31
- The method does not use a `docs/` layer for corpus or rules. A leftover `docs/`
32
+ **One exception, and it is not corpus.** `docs/agents/issue-tracker.md` and `docs/agents/domain.md` are the ENGINES' config, and their path belongs to the engines' author — `to-spec`, `to-tickets`, `implement` and `triage` read those two files and nowhere else. What they SAY is this method's, and `wdi-method` seeds both already answered. Neither is corpus, neither is a rule, and nothing else MAY be added beside them.
33
+
34
+ Otherwise the method does not use a `docs/` layer for corpus or rules. A leftover `docs/`
32
35
  folder is inventory to sort, not a second home.
33
36
 
34
37
  ## Article 4 — Lifecycle
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdi-method",
3
- "version": "0.6.7",
3
+ "version": "0.6.8",
4
4
  "description": "WDI Method — software delivery method that wraps BMad",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,43 +1,56 @@
1
- # Issue tracker
2
-
3
- Where issues live for this repo, and what `to-spec`, `to-tickets`, and `triage` read and write.
4
-
5
- This file is seeded by `wdi-method`. It is the product's from here on: change the tracker whenever you
6
- like, but keep the three invariants below, because `wdi-build` and the validators read them.
7
-
8
- ## Two places, and they are not the same place
9
-
10
- | | Owned by | Lives at |
11
- |---|---|---|
12
- | **A spec's tickets** — the work behind an `FR` | `wdi-build`, at G5 | `{spec_folder}/issues/<NN>-<slug>.md`, `spec_folder` from `.control/registry/specs.yaml` |
13
- | **Ad hoc work** — a quick bug report, a small idea, engineering-skill scratch | this file's convention | `.scratch/<slug>/` |
14
-
15
- `.scratch/` MUST NOT become a second place to plan a feature that already has an `FR`. The moment ad hoc
16
- work turns out to touch an `FR`, it stops and becomes a spec through `wdi-build` — the Fast Path rule in
17
- `delivery-flow-guide.md` owns that boundary.
18
-
19
- ## The three invariants
20
-
21
- Whatever tracker this repo uses — local markdown, GitHub, GitLab, Jira — these MUST hold:
22
-
23
- 1. **One parent per spec, one issue per ticket.** A ticket is an issue, never a sub-task: only an issue
24
- carries native blocking edges, and the frontier is read from them.
25
- 2. **Status lives on the ticket itself and nowhere else.** A `**Status:**` line near the top of the
26
- ticket file, or `status:` in its frontmatter. `ticket-status-one-home` reads it there, and copying it
27
- into `specs.yaml` is what that validator exists to refuse.
28
- 3. **Every ticket names what it `satisfies`** the `UC` or `FR` behind it. Without it the chain
29
- `FR UC ticket test` breaks and the RTM cannot say which promise went green.
30
-
31
- ## Conventions local markdown
32
-
33
- - One effort per directory: `.scratch/<slug>/`
34
- - One file per ticket at `.scratch/<slug>/issues/<NN>-<slug>.md`, numbered from `01`, never a single
35
- combined file
36
- - Blocking edges as a `Blocked by: NN, NN` line near the top
37
- - Comments append at the bottom under a `## Comments` heading
38
-
39
- ## Switching to a real tracker
40
-
41
- Re-run `/setup-matt-pocock-skills` and pick it, then keep the three invariants above. The mapping WDI
42
- Method expects is in `delivery-flow-guide.md` § *Mapping to a tracker*: parent issue is the spec, issue is
43
- the ticket, Fix Version is the release, and the `CAP`/`FR` travel as labels.
1
+ # Issue tracker
2
+
3
+ Where issues live for this repo, and what `to-spec`, `to-tickets`, and `triage` read and write.
4
+
5
+ This file is seeded by `wdi-method`. It is the product's from here on: change the tracker whenever you
6
+ like, but keep the three invariants below, because `wdi-build` and the validators read them.
7
+
8
+ ## One root, and the registry is what tells the two apart
9
+
10
+ Everything lives under `.scratch/`, one directory per effort:
11
+
12
+ | | Owned by | Lives at |
13
+ |---|---|---|
14
+ | **A spec** — the work behind an `FR` | `wdi-build`, at G5 | `.scratch/<spec-id>-<slug>/SPEC.md` and `.scratch/<spec-id>-<slug>/issues/<NN>-<slug>.md`, with `spec_folder` in `.control/registry/specs.yaml` naming that directory |
15
+ | **Ad hoc work** a quick bug report, a small idea, engineering-skill scratch | this file's convention | `.scratch/<slug>/` |
16
+
17
+ **The path no longer says which is which — the registry does.** An effort with a row in `specs.yaml`
18
+ is a spec and answers to G5; an effort with no row is ad hoc. That is deliberate: one root means the
19
+ engines need no case analysis and `to-tickets` publishes to the same place every time, and it puts the
20
+ distinction where something can actually check it.
21
+
22
+ `<spec-id>` is the id from `specs.yaml` — `.scratch/spec-3-checkout/`, never a bare slug. Left free,
23
+ that leaf gets written four different ways in four repos, and one repo managed all four inside itself:
24
+ a bare wave number, a `spec-` prefix with no number, a prefix with one, and a slug alone. Every one of
25
+ them was allowed, and none could be traced back to the row that owns it. The id in front is what makes
26
+ the folder answer to `specs.yaml`.
27
+
28
+ Ad hoc work that turns out to touch an `FR` **stops and becomes a spec** through `wdi-build` — the Fast
29
+ Path rule in `delivery-flow-guide.md` owns that boundary. It gains a row and a rename, not a second home.
30
+
31
+ ## The three invariants
32
+
33
+ Whatever tracker this repo uses — local markdown, GitHub, GitLab, Jira — these MUST hold:
34
+
35
+ 1. **One parent per spec, one issue per ticket.** A ticket is an issue, never a sub-task: only an issue
36
+ carries native blocking edges, and the frontier is read from them.
37
+ 2. **Status lives on the ticket itself and nowhere else.** A `**Status:**` line near the top of the
38
+ ticket file, or `status:` in its frontmatter. `ticket-status-one-home` reads it there, and copying it
39
+ into `specs.yaml` is what that validator exists to refuse.
40
+ 3. **Every ticket names what it `satisfies`** — the `UC` or `FR` behind it. Without it the chain
41
+ `FR UC ticket test` breaks and the RTM cannot say which promise went green.
42
+
43
+ ## Conventions local markdown
44
+
45
+ - One effort per directory: `.scratch/<spec-id>-<slug>/` for a spec, `.scratch/<slug>/` for ad hoc work
46
+ - The spec, where the size calls for one, is `SPEC.md` in that directory
47
+ - One file per ticket at `<effort>/issues/<NN>-<slug>.md`, numbered from `01`, never a single
48
+ combined file
49
+ - Blocking edges as a `Blocked by: NN, NN` line near the top
50
+ - Comments append at the bottom under a `## Comments` heading
51
+
52
+ ## Switching to a real tracker
53
+
54
+ Re-run `/setup-matt-pocock-skills` and pick it, then keep the three invariants above. The mapping WDI
55
+ Method expects is in `delivery-flow-guide.md` § *Mapping to a tracker*: parent issue is the spec, issue is
56
+ the ticket, Fix Version is the release, and the `CAP`/`FR` travel as labels.