wdi-method 0.5.4 → 0.5.9
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/bin/wdi-method.js +17 -0
- package/kit/.constitution/method/README.md +5 -3
- package/kit/.constitution/method/document/architecture-guide.md +209 -209
- package/kit/.constitution/method/document/corpus-guide.md +2 -2
- package/kit/.constitution/method/document/sdd-guide.md +3 -2
- package/kit/.constitution/method/document/templates/architecture-spine.md +100 -100
- package/kit/.constitution/method/document/templates/inventory.md +2 -2
- package/kit/.constitution/method/document/templates/sdd.md +1 -1
- package/kit/.constitution/method/document/templates/srs.md +149 -149
- package/kit/.constitution/method/document/templates/uc.md +69 -69
- package/kit/.constitution/method/scripts/inventory.py +99 -293
- package/kit/.constitution/method/scripts/validate.py +1676 -1648
- package/kit/.constitution/method/why/portability.md +7 -0
- package/kit/.constitution/project/README.md +8 -0
- package/kit/.constitution/project/inventory-readers.py +85 -0
- package/kit/skills/wdi-blueprint/SKILL.md +203 -203
- package/kit/skills/wdi-build/SKILL.md +4 -2
- package/kit/skills/wdi-init/SKILL.md +38 -4
- package/kit/skills/wdi-log/SKILL.md +107 -107
- package/kit/skills/wdi-report/SKILL.md +6 -6
- package/kit-overlay/README.md +5 -3
- package/kit-overlay/portability.md +7 -0
- package/package.json +1 -1
- package/scaffold/.control/registry/decisions.yaml +3 -3
|
@@ -31,6 +31,12 @@ them only an *example* does — not a rule.
|
|
|
31
31
|
Everything else — the five gates, the two fields, the fifteen skills, the templates, `validate.py`,
|
|
32
32
|
`inventory.py`, `../method-glossary.md`, and the three files beside this one — carries without edit.
|
|
33
33
|
|
|
34
|
+
One half-exception, and it is by design: `inventory.py` is the generic engine and carries whole, but
|
|
35
|
+
it reads no code itself. The three readers live in `../../project/inventory-readers.py`, which ships
|
|
36
|
+
as a skeleton and belongs to the product. A new project runs `wdi-init` intent `readers` once and
|
|
37
|
+
rewrites that file, nothing else. No example ships, deliberately — an example is a guess about a
|
|
38
|
+
stack nobody here has seen.
|
|
39
|
+
|
|
34
40
|
## What does NOT travel
|
|
35
41
|
|
|
36
42
|
| Stays behind | Why |
|
|
@@ -38,6 +44,7 @@ Everything else — the five gates, the two fields, the fifteen skills, the temp
|
|
|
38
44
|
| `.control/` | This product's state. A new project scaffolds its own through `wdi-init` intent `setup`, or receives empty stubs on first `install` |
|
|
39
45
|
| `.what/` · `.how/` | This product's promises and build |
|
|
40
46
|
| `.constitution/project/codebase-*-guide.md` | Written by the **project**, not the method. They ship as empty `Draft` stubs |
|
|
47
|
+
| `.constitution/project/inventory-readers.py` | How THIS product's code is read. Seeded as a SKELETON — no patterns and no stack. `wdi-init` intent `readers` writes it against the repo in front of it |
|
|
41
48
|
| `_bmad-output/` | Run workspace |
|
|
42
49
|
| The `bmad-*` skills themselves | BMad's, installed by BMad. Only `_bmad/custom/*.toml` is ours |
|
|
43
50
|
|
|
@@ -22,6 +22,14 @@ Normative rules that hold **only in this product**, and are not code conventions
|
|
|
22
22
|
- a naming or language policy that differs from the method default
|
|
23
23
|
- a prohibition or obligation specific to this domain
|
|
24
24
|
|
|
25
|
+
## Not a rule, but it lives here anyway
|
|
26
|
+
|
|
27
|
+
`inventory-readers.py` — how this product's code is read, for the three inventories. It sits in the
|
|
28
|
+
room for the same reason the rules do: the method's engine is generic, reading a stack is not, and
|
|
29
|
+
`update` MUST NOT overwrite what a product wrote about its own code. What ships is a **skeleton** —
|
|
30
|
+
no patterns, no stack — and `wdi-init` intent `readers` fills it in against this repo. `V27` does not
|
|
31
|
+
look at it: only `.md` is a rule.
|
|
32
|
+
|
|
25
33
|
## What does not
|
|
26
34
|
|
|
27
35
|
| The thing | Its home |
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""inventory readers — how THIS product's code is read. Owned by the product, not the method.
|
|
2
|
+
|
|
3
|
+
THIS FILE IS A SKELETON. It reads nothing yet, and it says so rather than reporting an empty
|
|
4
|
+
product: `SKELETON = True` below makes the engine refuse to run until the readers are written.
|
|
5
|
+
Delete that line when they are.
|
|
6
|
+
|
|
7
|
+
Write them with the skill rather than by hand:
|
|
8
|
+
|
|
9
|
+
wdi-init intent `readers`
|
|
10
|
+
|
|
11
|
+
That skill reads this repo — its migrations, its routes, its screens, whatever shape they take —
|
|
12
|
+
and fills the three functions in for the stack actually in front of it. It is the right way round:
|
|
13
|
+
the package ships no stack, and no example to be mistaken for one.
|
|
14
|
+
|
|
15
|
+
The whole file is yours. `wdi-method update` never writes over it and `promote` never publishes it,
|
|
16
|
+
so there is nothing here marked off-limits and nothing to merge. The engine —
|
|
17
|
+
`.constitution/method/scripts/inventory.py` — is the method's and is replaced on every update.
|
|
18
|
+
That is the seam: a folder, not a marked region inside a shared file.
|
|
19
|
+
|
|
20
|
+
WHAT THE ENGINE EXPECTS. Three functions, each taking the repo root and returning a `Derived`:
|
|
21
|
+
|
|
22
|
+
derive_db(root) -> Derived the tables this product stores
|
|
23
|
+
derive_api(root) -> Derived the endpoints it serves
|
|
24
|
+
derive_screen(root) -> Derived the screens it renders
|
|
25
|
+
|
|
26
|
+
Three names are INJECTED before this module executes, so import nothing for them:
|
|
27
|
+
|
|
28
|
+
Row(key, cells, source) one row. `key` is its stable identity, used for comparison; `cells`
|
|
29
|
+
are in the column order the engine renders; `source` is the file it
|
|
30
|
+
was read from
|
|
31
|
+
Derived(rows, unread) what a reader returns
|
|
32
|
+
decisions(path) an inventory's own `states:` and `platform_rows:`, read from its
|
|
33
|
+
frontmatter — a judgement no pattern can derive, so it is declared in
|
|
34
|
+
the artifact it governs
|
|
35
|
+
|
|
36
|
+
Nothing else is offered. Needing more of the engine means the seam is in the wrong place, and that
|
|
37
|
+
is a change to make in the method — not to reach around here.
|
|
38
|
+
|
|
39
|
+
THE COLUMN ORDER `cells` MUST FOLLOW:
|
|
40
|
+
|
|
41
|
+
db Table · Owning component · What it holds · Key columns · Status
|
|
42
|
+
api Host · Method · Path · Owning component · Description · Status
|
|
43
|
+
screen Screen · Route · States · Owning component · UC served
|
|
44
|
+
|
|
45
|
+
(The leading `No` is the engine's; it keeps the numbering stable and a reader MUST NOT supply it.)
|
|
46
|
+
|
|
47
|
+
THE RULE THAT NO STACK CHANGES: whatever a pattern cannot read is appended to `unread` and
|
|
48
|
+
reported. It MUST NOT be guessed, and it MUST NOT be silently dropped. An inventory assembled from
|
|
49
|
+
a README, or from a route name that merely looks plausible, is worth less than none — it reads as
|
|
50
|
+
derived while being invented.
|
|
51
|
+
|
|
52
|
+
A kind this product genuinely does not have MAY return `Derived()`. That is a real answer, and it
|
|
53
|
+
is not the same as this file still being a skeleton.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
from __future__ import annotations
|
|
57
|
+
|
|
58
|
+
from pathlib import Path
|
|
59
|
+
|
|
60
|
+
# Delete this line once the three functions below actually read something. While it is here the
|
|
61
|
+
# engine refuses to run, because a skeleton returning nothing and a product owning nothing look
|
|
62
|
+
# identical in the output — and only one of them is true.
|
|
63
|
+
SKELETON = True
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def read(path: Path) -> str:
|
|
67
|
+
try:
|
|
68
|
+
return path.read_text(encoding="utf-8", errors="replace")
|
|
69
|
+
except OSError:
|
|
70
|
+
return ""
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def derive_db(root: Path) -> "Derived": # noqa: F821 — injected by the engine
|
|
74
|
+
"""Every table this product stores, from wherever its schema actually lives."""
|
|
75
|
+
return Derived(unread=["derive_db has not been written for this product yet"])
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def derive_api(root: Path) -> "Derived": # noqa: F821 — injected by the engine
|
|
79
|
+
"""Every endpoint this product serves, from wherever its routes are registered."""
|
|
80
|
+
return Derived(unread=["derive_api has not been written for this product yet"])
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def derive_screen(root: Path) -> "Derived": # noqa: F821 — injected by the engine
|
|
84
|
+
"""Every screen this product renders, from wherever its routes are declared."""
|
|
85
|
+
return Derived(unread=["derive_screen has not been written for this product yet"])
|
|
@@ -1,203 +1,203 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wdi-blueprint
|
|
3
|
-
description: Use at G3 Blueprint — the one whole-product portrait, written once. Two intents, catalog and platform. Owns the use case catalogue, actors, domain model, cross-component business rules, the glossary, the spine, C4, cross-cutting, and the three inventories. Never writes a single component's depth.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# WDI Blueprint
|
|
7
|
-
|
|
8
|
-
G3 decides **the whole portrait of the system**: which use cases exist, their entities, their tables, their
|
|
9
|
-
endpoints, their screens, and the invariants that bind everything built from them. Once per product.
|
|
10
|
-
|
|
11
|
-
Two intents, run in this order:
|
|
12
|
-
|
|
13
|
-
| Intent | Writes | Wraps |
|
|
14
|
-
|---|---|---|
|
|
15
|
-
| `catalog` | Per `<pc>`: § Actor Register · § UC Catalogue · `03-domain/domain-model.md`. Product level: `.what/business-rules.md` · `.control/product-glossary.md` · `usecases.yaml` | — |
|
|
16
|
-
| `platform` | `.how/_platform/`: the spine · C4 L1/L2/L3 · `cross-cutting.md` · the three inventories. Registry: `containers` | `bmad-architecture` |
|
|
17
|
-
|
|
18
|
-
**Blueprint content is untouched by `mode` and by `risk_accepted`.** Everything above exists at every mode,
|
|
19
|
-
including `catalog`. That is what keeps the order non-circular: `mode` is first needed at G4.
|
|
20
|
-
|
|
21
|
-
You MUST NOT write a single component's depth — full UC flows, local rules, failure behaviour, contracts. All
|
|
22
|
-
of that is `wdi-component` at G4. You MUST NOT write a promise; when the blueprint proves a PRD wrong, that is
|
|
23
|
-
`wdi-product`, not a quiet edit here.
|
|
24
|
-
|
|
25
|
-
## Inputs
|
|
26
|
-
|
|
27
|
-
| Source | What it answers |
|
|
28
|
-
|---|---|
|
|
29
|
-
| `.what/_product-brief/brief.md` | The problem, the primary user, the boundary the portrait MUST respect |
|
|
30
|
-
| `.what/_prd/*/prd.md` — **every one** | Every promise made: the `FR`/`NFR` the portrait has to cover |
|
|
31
|
-
| `.control/registry/components.yaml` | Which components exist, and their `owns:` |
|
|
32
|
-
| `.control/product-glossary.md` | Terms already fixed |
|
|
33
|
-
| `.control/decisions/` | `accepted` and `applied` decisions an `AD-N` usually sits behind |
|
|
34
|
-
| `src/` · `web/` | What actually runs, when this is not a new project |
|
|
35
|
-
| `.constitution/method/document/srs-guide.md` · `architecture-guide.md` | The rules the result is checked against |
|
|
36
|
-
|
|
37
|
-
## Step 1 — Position
|
|
38
|
-
|
|
39
|
-
- The components MUST already exist. If `components.yaml` holds no `product_components`, route to `wdi-init`
|
|
40
|
-
intent `component` — the slicing is born at the tail of G2, from the brief plus every PRD.
|
|
41
|
-
- `catalog` runs before `platform`. The spine is written against a portrait that exists.
|
|
42
|
-
- If the spine and C4 set already exist, `platform` is an **amendment**, never a create. A second create
|
|
43
|
-
overwrites what three waves of annotation put there.
|
|
44
|
-
- If the ask is one component's mechanism or its full flows, route to `wdi-component`.
|
|
45
|
-
- If the ask is what the product promises, route to `wdi-product` — an invariant is not a promise.
|
|
46
|
-
|
|
47
|
-
## Step 2 — Intent `catalog`, in order
|
|
48
|
-
|
|
49
|
-
The order is binding, and each step is the input to the next. Writing them out of order produces use cases
|
|
50
|
-
whose nouns nobody defined.
|
|
51
|
-
|
|
52
|
-
1. **Glossary.** Every domain noun, into `.control/product-glossary.md`, alphabetically, each citing the
|
|
53
|
-
document and section its definition came from. You MUST NOT invent a definition — cite a source, or route
|
|
54
|
-
the term to `wdi-question`. Two words meaning one thing is **drift**, and it MUST be resolved to one word
|
|
55
|
-
in the same pass, with the losing synonym corrected in the documents that use it.
|
|
56
|
-
2. **UC Catalogue**, per component. One line per use case: `UC-N` · title · actor · the `FR` it satisfies ·
|
|
57
|
-
`critical` yes/no. A title MUST be a sentence a user would say, not a system term.
|
|
58
|
-
3. **Actor Register**, per component. It stays in the SRS kernel; it is the SSOT the SDD mirrors.
|
|
59
|
-
4. **Domain model** — entities, relations, columns — into `.what/<pc>/03-domain/domain-model.md`. Conceptual;
|
|
60
|
-
database column types belong to `.how/`.
|
|
61
|
-
5. **Cross-component business rules** into `.what/business-rules.md`. A rule binding only one component is
|
|
62
|
-
G4 work and MUST NOT be written here.
|
|
63
|
-
|
|
64
|
-
`critical` means the use case touches **money, personal data, or an irreversible action**. Nothing else. If
|
|
65
|
-
the count passes a third of a component's use cases, derive it again — `delivery-flow-guide.md` owns the rule
|
|
66
|
-
and it MUST NOT be negotiated.
|
|
67
|
-
|
|
68
|
-
**A method term MUST NOT be written into `.constitution/method/method-glossary.md`.** A product term binds one
|
|
69
|
-
project; a method term binds every project the method is installed in. Raise it as a proposal, state where it
|
|
70
|
-
appeared and why the existing vocabulary does not cover it, and hand it to the owner.
|
|
71
|
-
|
|
72
|
-
## Step 3 — Parallel where there is a key, serial where there is not
|
|
73
|
-
|
|
74
|
-
This is not theory. In the previous run, 41 cross-component business rules from seven parallel agents had to
|
|
75
|
-
be merged and de-duplicated **serially**, because the target file had no key — and that merge was the most
|
|
76
|
-
expensive part of the pass.
|
|
77
|
-
|
|
78
|
-
> Parallel fan-out is only for output with a natural key. Output that is a shared list with no key MUST be
|
|
79
|
-
> written by one agent that reads the whole input.
|
|
80
|
-
|
|
81
|
-
| Work | Parallel? | Key |
|
|
82
|
-
|---|---|---|
|
|
83
|
-
| UC catalogue, actors, entities per component | yes | Product Component |
|
|
84
|
-
| Glossary, cross-component business rules, the spine | **no** | there is none |
|
|
85
|
-
| The three inventories | yes, one agent per source | table · endpoint · screen |
|
|
86
|
-
|
|
87
|
-
Three guards when running parallel: each agent writes only its own keyed file; shared files are written in one
|
|
88
|
-
serial pass afterwards; the owner reviews the merged result, not N agent reports. Open questions from N agents
|
|
89
|
-
arrive as **one** ranked batch.
|
|
90
|
-
|
|
91
|
-
## Step 4 — Intent `platform`
|
|
92
|
-
|
|
93
|
-
Dispatch `bmad-architecture` at **initiative** altitude for the spine. Do not restate the rules to it — they
|
|
94
|
-
arrive through `persistent_facts` in `_bmad/custom/bmad-architecture.toml`, which installs
|
|
95
|
-
`architecture-guide.md` there rather than as `doc_standards` deliberately.
|
|
96
|
-
|
|
97
|
-
Then verify and land:
|
|
98
|
-
|
|
99
|
-
| # | Check | Fails when |
|
|
100
|
-
|---|---|---|
|
|
101
|
-
| 1 | Home | The spine landed anywhere but `.how/_platform/ARCHITECTURE-SPINE.md` |
|
|
102
|
-
| 2 | Every `AD-N` carries Binds, Prevents, and Rule | One is blank — an `AD-N` with no Prevents is a preference |
|
|
103
|
-
| 3 | Every `AD-N` is an invariant | Breaking it in one component would not break another. It is a seed, and MUST be marked as one |
|
|
104
|
-
| 4 | Stack, tree, and data shapes marked as seeds | Written as contracts, which makes the spine wrong at the first upgrade |
|
|
105
|
-
| 5 | No alternatives or cost in the spine | Those live in the `DEC-` behind it; a second copy drifts |
|
|
106
|
-
| 6 | Nothing but invariants | A statement affecting one component only — that is its SDD |
|
|
107
|
-
| 7 | Memlog at `.control/memlog/spine.md` | A `.memlog.md` appeared inside `.how/` — `--workspace` was used |
|
|
108
|
-
|
|
109
|
-
Check 7 MUST be fixed immediately. V16 rejects a memlog inside the corpus.
|
|
110
|
-
|
|
111
|
-
**Land the C4 set by amending, never overwriting.** The files are living and already carry annotations,
|
|
112
|
-
including a pre-method provenance note that MUST survive. When the incoming set contradicts an annotation
|
|
113
|
-
already there, you MUST stop and report it, and MUST NOT resolve it by preferring the newer drawing. Where a
|
|
114
|
-
C4 file and the spine disagree, the spine wins and the disagreement MUST be reported. One
|
|
115
|
-
`c4-l3-<container>.md` per `built: true` container **holding more than one Product Component**. A
|
|
116
|
-
`built: false` container gets no L3 at all, and a one-PC container needs none because the L2 matrix already
|
|
117
|
-
places it. **Not one of the three waits for a wave** — `architecture-guide.md` owns that.
|
|
118
|
-
|
|
119
|
-
**Register the containers** in `containers:` in `components.yaml`, in the same act as landing the L2. It is
|
|
120
|
-
not a follow-up, and it unblocks everyone else: an `LC` MUST name its container.
|
|
121
|
-
|
|
122
|
-
Each container MUST carry `built:` — `true` when we write what is inside it, `false` when we deploy
|
|
123
|
-
someone else's implementation. It decides whether the container gets an L3, an `LC`, and a heading in the
|
|
124
|
-
codebase map (V25). Something whose **runtime we do not deploy** is an external system: it belongs at L1,
|
|
125
|
-
and registering it here promises a codebase-map section that will never exist.
|
|
126
|
-
|
|
127
|
-
**Fill each PC's `containers:` in the same act, and land the matrix at L2** — the registry is the SSOT and
|
|
128
|
-
the L2 table renders it. A PC MUST list every `built: true` container it lives in; listing only the main
|
|
129
|
-
one is the error the matrix exists to catch. Complete for every PC at G3, untouched by `mode`.
|
|
130
|
-
|
|
131
|
-
You MUST NOT register a
|
|
132
|
-
`product_component` or a `logical_component`.
|
|
133
|
-
|
|
134
|
-
**Register what `_platform` owns** in the same pass — a domain entity through `platform_owns`, an inventory
|
|
135
|
-
row through that inventory's `platform_rows:`, an `LC` through its `component:`. The test is in
|
|
136
|
-
`corpus-guide.md` and both halves MUST hold. Each one MUST then be described under `## Platform-owned` in
|
|
137
|
-
`cross-cutting.md`, in the same act: V21 checks that second half, because owning something without
|
|
138
|
-
documenting it is taking ownership without taking responsibility.
|
|
139
|
-
|
|
140
|
-
A judgement the pattern cannot derive MUST live in the artifact it governs, not in a script and not in a
|
|
141
|
-
skill: an inventory's `platform_rows:` and `states:` are declared in that inventory's own frontmatter, so
|
|
142
|
-
re-derivation preserves them. Anywhere else, the next run deletes the owner's decision.
|
|
143
|
-
|
|
144
|
-
`_platform` is **not** a Product Component. You MUST NOT give it a `mode`, a `risk_accepted`, an SRS, or a
|
|
145
|
-
G4, and you MUST NOT move an entity there because its owner is hard to decide.
|
|
146
|
-
|
|
147
|
-
## Step 5 — The three inventories
|
|
148
|
-
|
|
149
|
-
They land in `.how/_platform/` with **one owner: this skill.** No negotiation with `wdi-ux`, and no second
|
|
150
|
-
copy inside any SDD.
|
|
151
|
-
|
|
152
|
-
| State | How each is born |
|
|
153
|
-
|---|---|
|
|
154
|
-
| No code yet | Written as a **plan** — the tables, endpoints, and screens intended. Nothing can be derived, because there is no source |
|
|
155
|
-
| Code exists | **Derived first** by `.constitution/method/scripts/inventory.py
|
|
156
|
-
|
|
157
|
-
An inventory MUST NOT be assembled from a README or from route names that look plausible. Numbers are stable:
|
|
158
|
-
a new row takes the next number, never a renumber.
|
|
159
|
-
|
|
160
|
-
## Step 6 — The roll-up, and what the owner actually reads
|
|
161
|
-
|
|
162
|
-
Regenerate `.control/generated/blueprint.md` with `validate.py --generate`. It assembles the UC catalogue, the
|
|
163
|
-
actor lists, the domain model, and the three inventories into **one page**.
|
|
164
|
-
|
|
165
|
-
**That page is what G3 reviews** — not seven files. The catalogue and actors stay in their component kernels as
|
|
166
|
-
their permanent home; the roll-up is a view. One fact, one home, one view.
|
|
167
|
-
|
|
168
|
-
You MUST NOT hand-write anything under `.control/generated/`.
|
|
169
|
-
|
|
170
|
-
## Step 7 — Review and questions
|
|
171
|
-
|
|
172
|
-
- No `doc_standards` fires for an SRS or for the spine. Dispatch `wdi-review`, which reads the lens set from
|
|
173
|
-
each component's `risk_accepted`.
|
|
174
|
-
- You MUST NOT open G3 on a portrait that has not been through it.
|
|
175
|
-
- Every unresolved to-be-confirmed MUST be filed through `wdi-question`, in **one** ranked batch — into
|
|
176
|
-
`assumptions.md` by default, `blocking.md` only through its three tests.
|
|
177
|
-
- A decision surfacing while writing goes to `wdi-decision`, never into the document as a parenthetical.
|
|
178
|
-
- An `AD-N` that reverses or narrows an earlier one MUST go through `wdi-decision` first. Editing an `AD-N` in
|
|
179
|
-
place is how a reversal happens with nobody deciding it.
|
|
180
|
-
|
|
181
|
-
## Step 8 — A PRD that arrives after G3
|
|
182
|
-
|
|
183
|
-
The blueprint is **living and amended**, not repeated. `wdi-init` intent `component` births the new
|
|
184
|
-
components, this skill adds their rows to the catalogue and the three inventories, and **G3 reopens over the
|
|
185
|
-
delta only**. The 45-minute session does not run again for one additional initiative.
|
|
186
|
-
|
|
187
|
-
## Rules
|
|
188
|
-
|
|
189
|
-
- You MUST NOT write into `.how/<pc>/`, and `design-system.md` in `_platform/` belongs to `wdi-ux`.
|
|
190
|
-
- You MUST NOT regenerate the C4 set from scratch. The loss of annotations is invisible in a diff that reads
|
|
191
|
-
as a rewrite.
|
|
192
|
-
- You MUST NOT raise `status:`. Status is a stage; the `reviewed:` block is an event.
|
|
193
|
-
- You MUST NOT write a definition into `.constitution/` at all — not the method glossary, not a guide.
|
|
194
|
-
- When the portrait cannot be drawn because a PRD has not settled what it must cover, say so and stop.
|
|
195
|
-
- Memlog: one per Product Component at `.control/memlog/<pc>.md`, plus `.control/memlog/spine.md` for
|
|
196
|
-
`platform`, through `memlog.py --path`. `--workspace` MUST NOT be used.
|
|
197
|
-
|
|
198
|
-
## Output
|
|
199
|
-
|
|
200
|
-
Intents run · the catalogue and inventories as counts, per component · glossary terms written, proposed, and
|
|
201
|
-
rejected with the rule that rejected each · the `AD-N` that are new or changed · what was amended in the C4
|
|
202
|
-
set and what contradicted it · containers registered · plan-versus-code differences reported · whether the
|
|
203
|
-
roll-up regenerated and `wdi-review` ran · the one ranked batch of questions.
|
|
1
|
+
---
|
|
2
|
+
name: wdi-blueprint
|
|
3
|
+
description: Use at G3 Blueprint — the one whole-product portrait, written once. Two intents, catalog and platform. Owns the use case catalogue, actors, domain model, cross-component business rules, the glossary, the spine, C4, cross-cutting, and the three inventories. Never writes a single component's depth.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# WDI Blueprint
|
|
7
|
+
|
|
8
|
+
G3 decides **the whole portrait of the system**: which use cases exist, their entities, their tables, their
|
|
9
|
+
endpoints, their screens, and the invariants that bind everything built from them. Once per product.
|
|
10
|
+
|
|
11
|
+
Two intents, run in this order:
|
|
12
|
+
|
|
13
|
+
| Intent | Writes | Wraps |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `catalog` | Per `<pc>`: § Actor Register · § UC Catalogue · `03-domain/domain-model.md`. Product level: `.what/business-rules.md` · `.control/product-glossary.md` · `usecases.yaml` | — |
|
|
16
|
+
| `platform` | `.how/_platform/`: the spine · C4 L1/L2/L3 · `cross-cutting.md` · the three inventories. Registry: `containers` | `bmad-architecture` |
|
|
17
|
+
|
|
18
|
+
**Blueprint content is untouched by `mode` and by `risk_accepted`.** Everything above exists at every mode,
|
|
19
|
+
including `catalog`. That is what keeps the order non-circular: `mode` is first needed at G4.
|
|
20
|
+
|
|
21
|
+
You MUST NOT write a single component's depth — full UC flows, local rules, failure behaviour, contracts. All
|
|
22
|
+
of that is `wdi-component` at G4. You MUST NOT write a promise; when the blueprint proves a PRD wrong, that is
|
|
23
|
+
`wdi-product`, not a quiet edit here.
|
|
24
|
+
|
|
25
|
+
## Inputs
|
|
26
|
+
|
|
27
|
+
| Source | What it answers |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `.what/_product-brief/brief.md` | The problem, the primary user, the boundary the portrait MUST respect |
|
|
30
|
+
| `.what/_prd/*/prd.md` — **every one** | Every promise made: the `FR`/`NFR` the portrait has to cover |
|
|
31
|
+
| `.control/registry/components.yaml` | Which components exist, and their `owns:` |
|
|
32
|
+
| `.control/product-glossary.md` | Terms already fixed |
|
|
33
|
+
| `.control/decisions/` | `accepted` and `applied` decisions an `AD-N` usually sits behind |
|
|
34
|
+
| `src/` · `web/` | What actually runs, when this is not a new project |
|
|
35
|
+
| `.constitution/method/document/srs-guide.md` · `architecture-guide.md` | The rules the result is checked against |
|
|
36
|
+
|
|
37
|
+
## Step 1 — Position
|
|
38
|
+
|
|
39
|
+
- The components MUST already exist. If `components.yaml` holds no `product_components`, route to `wdi-init`
|
|
40
|
+
intent `component` — the slicing is born at the tail of G2, from the brief plus every PRD.
|
|
41
|
+
- `catalog` runs before `platform`. The spine is written against a portrait that exists.
|
|
42
|
+
- If the spine and C4 set already exist, `platform` is an **amendment**, never a create. A second create
|
|
43
|
+
overwrites what three waves of annotation put there.
|
|
44
|
+
- If the ask is one component's mechanism or its full flows, route to `wdi-component`.
|
|
45
|
+
- If the ask is what the product promises, route to `wdi-product` — an invariant is not a promise.
|
|
46
|
+
|
|
47
|
+
## Step 2 — Intent `catalog`, in order
|
|
48
|
+
|
|
49
|
+
The order is binding, and each step is the input to the next. Writing them out of order produces use cases
|
|
50
|
+
whose nouns nobody defined.
|
|
51
|
+
|
|
52
|
+
1. **Glossary.** Every domain noun, into `.control/product-glossary.md`, alphabetically, each citing the
|
|
53
|
+
document and section its definition came from. You MUST NOT invent a definition — cite a source, or route
|
|
54
|
+
the term to `wdi-question`. Two words meaning one thing is **drift**, and it MUST be resolved to one word
|
|
55
|
+
in the same pass, with the losing synonym corrected in the documents that use it.
|
|
56
|
+
2. **UC Catalogue**, per component. One line per use case: `UC-N` · title · actor · the `FR` it satisfies ·
|
|
57
|
+
`critical` yes/no. A title MUST be a sentence a user would say, not a system term.
|
|
58
|
+
3. **Actor Register**, per component. It stays in the SRS kernel; it is the SSOT the SDD mirrors.
|
|
59
|
+
4. **Domain model** — entities, relations, columns — into `.what/<pc>/03-domain/domain-model.md`. Conceptual;
|
|
60
|
+
database column types belong to `.how/`.
|
|
61
|
+
5. **Cross-component business rules** into `.what/business-rules.md`. A rule binding only one component is
|
|
62
|
+
G4 work and MUST NOT be written here.
|
|
63
|
+
|
|
64
|
+
`critical` means the use case touches **money, personal data, or an irreversible action**. Nothing else. If
|
|
65
|
+
the count passes a third of a component's use cases, derive it again — `delivery-flow-guide.md` owns the rule
|
|
66
|
+
and it MUST NOT be negotiated.
|
|
67
|
+
|
|
68
|
+
**A method term MUST NOT be written into `.constitution/method/method-glossary.md`.** A product term binds one
|
|
69
|
+
project; a method term binds every project the method is installed in. Raise it as a proposal, state where it
|
|
70
|
+
appeared and why the existing vocabulary does not cover it, and hand it to the owner.
|
|
71
|
+
|
|
72
|
+
## Step 3 — Parallel where there is a key, serial where there is not
|
|
73
|
+
|
|
74
|
+
This is not theory. In the previous run, 41 cross-component business rules from seven parallel agents had to
|
|
75
|
+
be merged and de-duplicated **serially**, because the target file had no key — and that merge was the most
|
|
76
|
+
expensive part of the pass.
|
|
77
|
+
|
|
78
|
+
> Parallel fan-out is only for output with a natural key. Output that is a shared list with no key MUST be
|
|
79
|
+
> written by one agent that reads the whole input.
|
|
80
|
+
|
|
81
|
+
| Work | Parallel? | Key |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| UC catalogue, actors, entities per component | yes | Product Component |
|
|
84
|
+
| Glossary, cross-component business rules, the spine | **no** | there is none |
|
|
85
|
+
| The three inventories | yes, one agent per source | table · endpoint · screen |
|
|
86
|
+
|
|
87
|
+
Three guards when running parallel: each agent writes only its own keyed file; shared files are written in one
|
|
88
|
+
serial pass afterwards; the owner reviews the merged result, not N agent reports. Open questions from N agents
|
|
89
|
+
arrive as **one** ranked batch.
|
|
90
|
+
|
|
91
|
+
## Step 4 — Intent `platform`
|
|
92
|
+
|
|
93
|
+
Dispatch `bmad-architecture` at **initiative** altitude for the spine. Do not restate the rules to it — they
|
|
94
|
+
arrive through `persistent_facts` in `_bmad/custom/bmad-architecture.toml`, which installs
|
|
95
|
+
`architecture-guide.md` there rather than as `doc_standards` deliberately.
|
|
96
|
+
|
|
97
|
+
Then verify and land:
|
|
98
|
+
|
|
99
|
+
| # | Check | Fails when |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| 1 | Home | The spine landed anywhere but `.how/_platform/ARCHITECTURE-SPINE.md` |
|
|
102
|
+
| 2 | Every `AD-N` carries Binds, Prevents, and Rule | One is blank — an `AD-N` with no Prevents is a preference |
|
|
103
|
+
| 3 | Every `AD-N` is an invariant | Breaking it in one component would not break another. It is a seed, and MUST be marked as one |
|
|
104
|
+
| 4 | Stack, tree, and data shapes marked as seeds | Written as contracts, which makes the spine wrong at the first upgrade |
|
|
105
|
+
| 5 | No alternatives or cost in the spine | Those live in the `DEC-` behind it; a second copy drifts |
|
|
106
|
+
| 6 | Nothing but invariants | A statement affecting one component only — that is its SDD |
|
|
107
|
+
| 7 | Memlog at `.control/memlog/spine.md` | A `.memlog.md` appeared inside `.how/` — `--workspace` was used |
|
|
108
|
+
|
|
109
|
+
Check 7 MUST be fixed immediately. V16 rejects a memlog inside the corpus.
|
|
110
|
+
|
|
111
|
+
**Land the C4 set by amending, never overwriting.** The files are living and already carry annotations,
|
|
112
|
+
including a pre-method provenance note that MUST survive. When the incoming set contradicts an annotation
|
|
113
|
+
already there, you MUST stop and report it, and MUST NOT resolve it by preferring the newer drawing. Where a
|
|
114
|
+
C4 file and the spine disagree, the spine wins and the disagreement MUST be reported. One
|
|
115
|
+
`c4-l3-<container>.md` per `built: true` container **holding more than one Product Component**. A
|
|
116
|
+
`built: false` container gets no L3 at all, and a one-PC container needs none because the L2 matrix already
|
|
117
|
+
places it. **Not one of the three waits for a wave** — `architecture-guide.md` owns that.
|
|
118
|
+
|
|
119
|
+
**Register the containers** in `containers:` in `components.yaml`, in the same act as landing the L2. It is
|
|
120
|
+
not a follow-up, and it unblocks everyone else: an `LC` MUST name its container.
|
|
121
|
+
|
|
122
|
+
Each container MUST carry `built:` — `true` when we write what is inside it, `false` when we deploy
|
|
123
|
+
someone else's implementation. It decides whether the container gets an L3, an `LC`, and a heading in the
|
|
124
|
+
codebase map (V25). Something whose **runtime we do not deploy** is an external system: it belongs at L1,
|
|
125
|
+
and registering it here promises a codebase-map section that will never exist.
|
|
126
|
+
|
|
127
|
+
**Fill each PC's `containers:` in the same act, and land the matrix at L2** — the registry is the SSOT and
|
|
128
|
+
the L2 table renders it. A PC MUST list every `built: true` container it lives in; listing only the main
|
|
129
|
+
one is the error the matrix exists to catch. Complete for every PC at G3, untouched by `mode`.
|
|
130
|
+
|
|
131
|
+
You MUST NOT register a
|
|
132
|
+
`product_component` or a `logical_component`.
|
|
133
|
+
|
|
134
|
+
**Register what `_platform` owns** in the same pass — a domain entity through `platform_owns`, an inventory
|
|
135
|
+
row through that inventory's `platform_rows:`, an `LC` through its `component:`. The test is in
|
|
136
|
+
`corpus-guide.md` and both halves MUST hold. Each one MUST then be described under `## Platform-owned` in
|
|
137
|
+
`cross-cutting.md`, in the same act: V21 checks that second half, because owning something without
|
|
138
|
+
documenting it is taking ownership without taking responsibility.
|
|
139
|
+
|
|
140
|
+
A judgement the pattern cannot derive MUST live in the artifact it governs, not in a script and not in a
|
|
141
|
+
skill: an inventory's `platform_rows:` and `states:` are declared in that inventory's own frontmatter, so
|
|
142
|
+
re-derivation preserves them. Anywhere else, the next run deletes the owner's decision.
|
|
143
|
+
|
|
144
|
+
`_platform` is **not** a Product Component. You MUST NOT give it a `mode`, a `risk_accepted`, an SRS, or a
|
|
145
|
+
G4, and you MUST NOT move an entity there because its owner is hard to decide.
|
|
146
|
+
|
|
147
|
+
## Step 5 — The three inventories
|
|
148
|
+
|
|
149
|
+
They land in `.how/_platform/` with **one owner: this skill.** No negotiation with `wdi-ux`, and no second
|
|
150
|
+
copy inside any SDD.
|
|
151
|
+
|
|
152
|
+
| State | How each is born |
|
|
153
|
+
|---|---|
|
|
154
|
+
| No code yet | Written as a **plan** — the tables, endpoints, and screens intended. Nothing can be derived, because there is no source |
|
|
155
|
+
| Code exists | **Derived first** by `.constitution/method/scripts/inventory.py`, which reads this product's patterns from `.constitution/project/inventory-readers.py`, then compares with the plan. The difference is a **finding**, not hand work. A product with no reader file is told so and nothing is derived — it is never guessed |
|
|
156
|
+
|
|
157
|
+
An inventory MUST NOT be assembled from a README or from route names that look plausible. Numbers are stable:
|
|
158
|
+
a new row takes the next number, never a renumber.
|
|
159
|
+
|
|
160
|
+
## Step 6 — The roll-up, and what the owner actually reads
|
|
161
|
+
|
|
162
|
+
Regenerate `.control/generated/blueprint.md` with `validate.py --generate`. It assembles the UC catalogue, the
|
|
163
|
+
actor lists, the domain model, and the three inventories into **one page**.
|
|
164
|
+
|
|
165
|
+
**That page is what G3 reviews** — not seven files. The catalogue and actors stay in their component kernels as
|
|
166
|
+
their permanent home; the roll-up is a view. One fact, one home, one view.
|
|
167
|
+
|
|
168
|
+
You MUST NOT hand-write anything under `.control/generated/`.
|
|
169
|
+
|
|
170
|
+
## Step 7 — Review and questions
|
|
171
|
+
|
|
172
|
+
- No `doc_standards` fires for an SRS or for the spine. Dispatch `wdi-review`, which reads the lens set from
|
|
173
|
+
each component's `risk_accepted`.
|
|
174
|
+
- You MUST NOT open G3 on a portrait that has not been through it.
|
|
175
|
+
- Every unresolved to-be-confirmed MUST be filed through `wdi-question`, in **one** ranked batch — into
|
|
176
|
+
`assumptions.md` by default, `blocking.md` only through its three tests.
|
|
177
|
+
- A decision surfacing while writing goes to `wdi-decision`, never into the document as a parenthetical.
|
|
178
|
+
- An `AD-N` that reverses or narrows an earlier one MUST go through `wdi-decision` first. Editing an `AD-N` in
|
|
179
|
+
place is how a reversal happens with nobody deciding it.
|
|
180
|
+
|
|
181
|
+
## Step 8 — A PRD that arrives after G3
|
|
182
|
+
|
|
183
|
+
The blueprint is **living and amended**, not repeated. `wdi-init` intent `component` births the new
|
|
184
|
+
components, this skill adds their rows to the catalogue and the three inventories, and **G3 reopens over the
|
|
185
|
+
delta only**. The 45-minute session does not run again for one additional initiative.
|
|
186
|
+
|
|
187
|
+
## Rules
|
|
188
|
+
|
|
189
|
+
- You MUST NOT write into `.how/<pc>/`, and `design-system.md` in `_platform/` belongs to `wdi-ux`.
|
|
190
|
+
- You MUST NOT regenerate the C4 set from scratch. The loss of annotations is invisible in a diff that reads
|
|
191
|
+
as a rewrite.
|
|
192
|
+
- You MUST NOT raise `status:`. Status is a stage; the `reviewed:` block is an event.
|
|
193
|
+
- You MUST NOT write a definition into `.constitution/` at all — not the method glossary, not a guide.
|
|
194
|
+
- When the portrait cannot be drawn because a PRD has not settled what it must cover, say so and stop.
|
|
195
|
+
- Memlog: one per Product Component at `.control/memlog/<pc>.md`, plus `.control/memlog/spine.md` for
|
|
196
|
+
`platform`, through `memlog.py --path`. `--workspace` MUST NOT be used.
|
|
197
|
+
|
|
198
|
+
## Output
|
|
199
|
+
|
|
200
|
+
Intents run · the catalogue and inventories as counts, per component · glossary terms written, proposed, and
|
|
201
|
+
rejected with the rule that rejected each · the `AD-N` that are new or changed · what was amended in the C4
|
|
202
|
+
set and what contradicted it · containers registered · plan-versus-code differences reported · whether the
|
|
203
|
+
roll-up regenerated and `wdi-review` ran · the one ranked batch of questions.
|
|
@@ -96,8 +96,10 @@ Three rules this corpus adds. All three MUST be stated in the dispatch of any st
|
|
|
96
96
|
- **The corpus is not the worker's to change.** A worker MUST NOT edit `.what/`, `.how/`, or an `applied`
|
|
97
97
|
`DEC-`. A deviation from the SDD or an `AD-N` is **reported**, and it becomes a `DEC-` through
|
|
98
98
|
`wdi-decision` — never absorbed as a code patch.
|
|
99
|
-
- **Verification is run, not assumed.**
|
|
100
|
-
`
|
|
99
|
+
- **Verification is run, not assumed.** The commands are this product's, and they live in
|
|
100
|
+
`.constitution/project/codebase-stack-guide.md` — build, test, and whatever the front end needs, each with
|
|
101
|
+
the directory it runs from. A skill MUST NOT carry one product's build line. A green registry workflow
|
|
102
|
+
MUST NOT be reported as proof the code compiles; they answer different questions.
|
|
101
103
|
|
|
102
104
|
### Step 1 — plan
|
|
103
105
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wdi-init
|
|
3
|
-
description: Use for anything that must exist before work can start or continue — scaffolding the registries at install, birthing Product Components after G2, setting or changing a component's mode, setting or reviewing its risk_accepted,
|
|
3
|
+
description: Use for anything that must exist before work can start or continue — scaffolding the registries at install, birthing Product Components after G2, setting or changing a component's mode, setting or reviewing its risk_accepted, refreshing the two structure maps, and writing this product's inventory readers. Six intents. Never writes .what/ or .how/ content beyond a skeleton.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# WDI Init
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Six intents, one skill, because all six answer the same question: **what has to exist before the
|
|
9
9
|
next piece of work makes sense?** A registry row, a folder pair, a depth setting, a risk note, a map
|
|
10
|
-
of where things are.
|
|
10
|
+
of where things are, a reader that can see this product's code.
|
|
11
11
|
|
|
12
12
|
| Intent | Does | Precondition | How often |
|
|
13
13
|
|---|---|---|---|
|
|
@@ -16,6 +16,7 @@ of where things are.
|
|
|
16
16
|
| `mode` | Change `mode` — global in `index.yaml`, or one component in `components.yaml`. Guided | — | any time |
|
|
17
17
|
| `risk` | Set or review one component's `risk_accepted`, with disclosure of what it touches | the component exists | any time, usually before G4 |
|
|
18
18
|
| `structure` | Re-derive `.control/structure-codebase.md` and `structure-document.md` from the tree on disk | — | when folders change, and at wave close |
|
|
19
|
+
| `readers` | Write `.constitution/project/inventory-readers.py` for **this** repo's stack, then prove it by running the engine | code exists | once, and again when the code's shape moves |
|
|
19
20
|
|
|
20
21
|
## Two boundaries
|
|
21
22
|
|
|
@@ -131,11 +132,44 @@ caller is unsure: a map is cheap to check and expensive to get wrong.
|
|
|
131
132
|
A hand-edited map MUST be treated as drift: re-derive, then say what the hand edit claimed that the tree
|
|
132
133
|
does not support.
|
|
133
134
|
|
|
135
|
+
## Intent `readers`
|
|
136
|
+
|
|
137
|
+
`inventory.py` is two halves. Comparing what was derived against the plan, reporting the gap, keeping
|
|
138
|
+
the numbers stable — that is the same in every stack and belongs to the method. **Reading the code is
|
|
139
|
+
not**, so the package ships a skeleton and no example: an example is a guess about somebody else's
|
|
140
|
+
stack, and the whole point of deriving rather than assembling is that nothing is guessed.
|
|
141
|
+
|
|
142
|
+
The file is `.constitution/project/inventory-readers.py`. All of it is the product's — `update` never
|
|
143
|
+
writes over it and `promote` never publishes it — so there is no protected region inside it and
|
|
144
|
+
nothing to merge.
|
|
145
|
+
|
|
146
|
+
1. **Read the repo before writing a line.** Where does the schema live, how are routes registered,
|
|
147
|
+
how are screens declared. A stack you have not confirmed on disk MUST NOT be assumed from a
|
|
148
|
+
filename or a dependency list.
|
|
149
|
+
2. Fill `derive_db`, `derive_api`, and `derive_screen`. The contract, the injected names, and the
|
|
150
|
+
column order per kind are in the skeleton's own docstring and MUST NOT be restated here.
|
|
151
|
+
3. **Delete the `SKELETON = True` line.** While it stands the engine refuses to run, and that is
|
|
152
|
+
deliberate: a skeleton returning nothing and a product owning nothing read identically.
|
|
153
|
+
4. **Prove it, and this step is not optional.** Run `uv run .constitution/method/scripts/inventory.py`,
|
|
154
|
+
then open at least one file each reader claims to have read and confirm the rows match what is
|
|
155
|
+
actually written there. A regex that returns plausible rows from the wrong place is the failure
|
|
156
|
+
mode this intent invites, and running the engine is the only thing that catches it.
|
|
157
|
+
5. Whatever a pattern cannot read goes to `unread`. You MUST NOT widen a pattern until it stops
|
|
158
|
+
reporting; an honest `unread` is worth more than a row nobody checked.
|
|
159
|
+
6. Report what each reader reads, in one line per kind, and what it deliberately does not.
|
|
160
|
+
|
|
161
|
+
A kind this product genuinely does not have returns `Derived()` — a real answer. You MUST NOT return
|
|
162
|
+
it to make the output quiet.
|
|
163
|
+
|
|
164
|
+
The rows themselves are **not** yours to land. This intent produces the reader; `wdi-blueprint` intent
|
|
165
|
+
`platform` owns the three inventories, and a plan-versus-code gap is its finding to route.
|
|
166
|
+
|
|
134
167
|
## Rules
|
|
135
168
|
|
|
136
169
|
- You MUST NOT write `.what/` or `.how/` content beyond a skeleton and its frontmatter. Behaviour is
|
|
137
170
|
`wdi-blueprint` and `wdi-component`; mechanism is `wdi-component`.
|
|
138
|
-
- You MUST NOT write into `.constitution/`.
|
|
171
|
+
- You MUST NOT write into `.constitution/method/`. Intent `readers` writes exactly one file in
|
|
172
|
+
`.constitution/project/`, and nothing else there.
|
|
139
173
|
- You MUST NOT fill `mode` or `risk_accepted` with a value the owner has not confirmed. Both are the
|
|
140
174
|
owner's, and a proposal recorded as a decision is the one failure disclosure cannot survive.
|
|
141
175
|
- You MUST NOT create a Product Component because a folder would look tidy. A PC no `FR` points at is a
|