wdi-method 0.6.2 → 0.6.4
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 +44 -3
- package/bin/wdi-method.js +143 -0
- package/kit/skills/wdi-autopilot/SKILL.md +9 -0
- package/kit/skills/wdi-help/SKILL.md +8 -0
- package/kit/skills/wdi-upgrade/SKILL.md +8 -0
- package/kit-overlay/AGENTS.md +4 -0
- package/package.json +1 -1
- package/scaffold/docs/agents/domain.md +36 -0
- package/scaffold/docs/agents/issue-tracker.md +43 -0
package/README.md
CHANGED
|
@@ -25,7 +25,10 @@ page it is on.
|
|
|
25
25
|
## Install
|
|
26
26
|
|
|
27
27
|
Three steps, in this order. The first is required before step 3 will run; the second can wait until
|
|
28
|
-
|
|
28
|
+
**Both are required, and the installer refuses without either.** BMad has always been checked; the ticket
|
|
29
|
+
engines are checked too, because every repo that learned they were missing learned it inside `wdi-build`
|
|
30
|
+
with a spec already open. `--skip-engines-check` is the escape for the two cases that earn it: CI, and a
|
|
31
|
+
repo that will never reach G5.
|
|
29
32
|
|
|
30
33
|
**1. BMad Method** — in the product repo, picking the same agents you will give this installer:
|
|
31
34
|
|
|
@@ -44,8 +47,16 @@ claude plugins install mattpocock-skills # or, inside a session: /plugin i
|
|
|
44
47
|
npx skills@latest add mattpocock/skills
|
|
45
48
|
```
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
**You do not need to run `/setup-matt-pocock-skills` to get started.** Step 3 seeds `docs/agents/` with
|
|
51
|
+
the two answers WDI Method actually has a requirement on, so the engines are aligned from the first
|
|
52
|
+
install. Run the setup skill only to *change* something — to point at GitHub or Jira instead of local
|
|
53
|
+
markdown — and keep the three invariants the seeded `issue-tracker.md` names.
|
|
54
|
+
|
|
55
|
+
The seeding exists because the interview's own defaults are wrong here in one specific way: they send every
|
|
56
|
+
engineering skill looking for a root `CONTEXT.md` and `docs/adr/`, and Article 3 says this method has no
|
|
57
|
+
`docs/` layer for corpus or rules — `wdi-reconcile` reports both as findings. A repo that ran the setup
|
|
58
|
+
before installing this package keeps its own file, and the installer names the contradiction rather than
|
|
59
|
+
overwriting it.
|
|
49
60
|
|
|
50
61
|
**3. WDI Method:**
|
|
51
62
|
|
|
@@ -97,6 +108,36 @@ answers with the gate you are at, not with a menu.
|
|
|
97
108
|
|
|
98
109
|
---
|
|
99
110
|
|
|
111
|
+
## What to do right after install, and right after update
|
|
112
|
+
|
|
113
|
+
Two questions, and the honest answer to most of them is *nothing*. `wdi-help` answers them from the
|
|
114
|
+
registry at any time; this table is the same answer written down.
|
|
115
|
+
|
|
116
|
+
### After `install`
|
|
117
|
+
|
|
118
|
+
| | |
|
|
119
|
+
|---|---|
|
|
120
|
+
| Engines missing | You never get here — `install` refuses, and names both install paths. Install them, run it again |
|
|
121
|
+
| `/setup-matt-pocock-skills`? | **No.** The installer seeded `docs/agents/` already answered for this method. Run that interview only to *change* tracker |
|
|
122
|
+
| So what is first? | **`wdi-init` intent `setup`** — it sets the global `mode`, and nothing has started until it is |
|
|
123
|
+
| Then? | `wdi-problem` for G1. Or ask `wdi-help`, which reads the registry rather than this table |
|
|
124
|
+
|
|
125
|
+
### After `update`
|
|
126
|
+
|
|
127
|
+
| The summary said | Do |
|
|
128
|
+
|---|---|
|
|
129
|
+
| an **`upgrade`** line, naming content still in the old shape | **`wdi-upgrade`, before any other skill.** It moves every sentence into its new home, invents nothing, reports what it could not place, and ends in one commit. `wdi-help` and the validators read the new shape; a corpus half in the old one answers them wrongly |
|
|
130
|
+
| **no** `upgrade` line | Nothing. The update was mechanical and complete — carry on from wherever the gates say you are |
|
|
131
|
+
| `seeded docs/agents/` | Nothing. An older repo just received the engines' config, pre-answered. Read it if you like; do not run the setup interview to redo it |
|
|
132
|
+
| a warning that `domain.md` still points at a root `CONTEXT.md` | Add the correction that warning names to the top of that file. It was written by the setup interview before this package was installed, and it sends every engineering skill at two paths Article 3 forbids |
|
|
133
|
+
| a warning naming a **mandate** and `ad-n` | Only if you run `wdi-autopilot`. Decide whether that mandate should now park `AD-N` contradictions, and edit its `parked` list yourself — `update` never edits an authority you granted |
|
|
134
|
+
|
|
135
|
+
**`wdi-upgrade` is only ever about corpus content** — a brief, a PRD, an SRS, registry rows in the old
|
|
136
|
+
shape. It is not the answer to a missing engine, a missing tracker config, or anything under
|
|
137
|
+
`.control/memlog/`; each of those is handled by the installer itself or by the skill that owns it.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
100
141
|
## How to use it — the walk
|
|
101
142
|
|
|
102
143
|
A gate is a moment where a human reads **one page** and decides. Between gates the AI works in a
|
package/bin/wdi-method.js
CHANGED
|
@@ -123,6 +123,7 @@ function usage() {
|
|
|
123
123
|
--doc-language <text> prose of working documents; free text, default English
|
|
124
124
|
--doc-filename-language <text> slug part of document filenames; free text, default English
|
|
125
125
|
--skip-bmad-check
|
|
126
|
+
--skip-engines-check install without to-spec / to-tickets / implement
|
|
126
127
|
|
|
127
128
|
BMad first, then this package. ${WDI_REPO}
|
|
128
129
|
`);
|
|
@@ -166,6 +167,7 @@ function parseArgs(argv) {
|
|
|
166
167
|
while (rest.length) {
|
|
167
168
|
const t = rest.shift();
|
|
168
169
|
if (t === "--skip-bmad-check") args.skipBmad = true;
|
|
170
|
+
else if (t === "--skip-engines-check") args.skipEngines = true;
|
|
169
171
|
else if (t === "--rescue") args.rescue = true;
|
|
170
172
|
else if (t === "--yes" || t === "-y") args.yes = true;
|
|
171
173
|
else if (t === "--agents") {
|
|
@@ -318,6 +320,29 @@ function bmadMissingMessage() {
|
|
|
318
320
|
].join("\n");
|
|
319
321
|
}
|
|
320
322
|
|
|
323
|
+
// The engines used to WARN and let the install through, on the reasoning that G1-G4 run without them and
|
|
324
|
+
// a first install has no G5 yet. Both halves are still true, and the reasoning stopped being enough:
|
|
325
|
+
// `wdi-autopilot` needs all three from its first iteration, and a warning inside a forty-line summary is
|
|
326
|
+
// read exactly as often as it is skipped. The failure it was meant to prevent — learning they are missing
|
|
327
|
+
// inside `wdi-build`, with a spec already open — kept happening anyway.
|
|
328
|
+
//
|
|
329
|
+
// So it blocks, and `--skip-engines-check` is the escape, exactly as `--skip-bmad-check` is for BMad. The
|
|
330
|
+
// escape matters: CI installs into a bare checkout, and a repo that will never reach G5 is a real case.
|
|
331
|
+
function enginesMissingMessage() {
|
|
332
|
+
return [
|
|
333
|
+
"The ticket engines are not installed. G5 (wdi-build) and wdi-autopilot need all three.",
|
|
334
|
+
"",
|
|
335
|
+
` Claude Code: ${ENGINES_INSTALL}`,
|
|
336
|
+
` Other agents: ${ENGINES_INSTALL_ANY}`,
|
|
337
|
+
"",
|
|
338
|
+
"You do NOT need to run the setup skill after this — the installer seeds docs/agents/ already",
|
|
339
|
+
`answered for this method. Run ${ENGINES_SETUP} only to change tracker.`,
|
|
340
|
+
`Source: ${ENGINES_REPO}`,
|
|
341
|
+
"",
|
|
342
|
+
"G1-G4 run without them. To install anyway and add them later: --skip-engines-check",
|
|
343
|
+
].join("\n");
|
|
344
|
+
}
|
|
345
|
+
|
|
321
346
|
// The product's custom room. Three properties, and all three MUST hold together:
|
|
322
347
|
// install/update seeds its content ONLY when absent — never written again after that
|
|
323
348
|
// promote SKIPS it entirely, so a product's own rules can never reach the public repo
|
|
@@ -425,6 +450,117 @@ function splitProductConstitution(file) {
|
|
|
425
450
|
// Two refusals matter more than the move. It never writes over an existing `specs.yaml`, and it
|
|
426
451
|
// never deletes a `waves.yaml` whose content has nowhere to go: a half-finished hand migration
|
|
427
452
|
// leaves BOTH files present, and which one is real is not something an installer can know.
|
|
453
|
+
// `wdi-autopilot` named its ledger for the DAY before 0.6.2 — `autopilot-<YYYY-MM-DD>.md`. The mandate
|
|
454
|
+
// it belongs to is named for the MANDATE now — `autopilot-<DEC-id>.md` — because two mandates opened
|
|
455
|
+
// on the same day would otherwise append to one file and destroy both as a record, and because
|
|
456
|
+
// `mandate-accept` (the validator introduced alongside the rename) looks for the file at that path and
|
|
457
|
+
// nowhere else. This is a pure rename, like `waves.yaml` → `specs.yaml`: the ledger's own content is
|
|
458
|
+
// never touched, only found and moved. Renaming it is what a script can safely do; restructuring its
|
|
459
|
+
// CONTENT into the `## Resume` / `## Decisions` split is not — that has to read git and the registry to
|
|
460
|
+
// know where the run actually stands, so it is the skill's own job on the next iteration it runs, not
|
|
461
|
+
// this installer's.
|
|
462
|
+
// `/setup-matt-pocock-skills` interviews the owner and writes `docs/agents/`. Two of its answers are
|
|
463
|
+
// wrong for a WDI repo, and BOTH repos that ran it had to hand-correct the SAME file afterwards:
|
|
464
|
+
//
|
|
465
|
+
// - `domain.md` tells agents to read and lazily create a root `CONTEXT.md` and `docs/adr/`. Article 3
|
|
466
|
+
// says this method has no `docs/` layer for corpus or rules, and `wdi-reconcile` reports both as
|
|
467
|
+
// findings. The homes already exist: `.control/product-glossary.md`, `.what/`, `.how/`, `DEC-`.
|
|
468
|
+
// - `issue-tracker.md`'s local-markdown default puts every ticket under `.scratch/<feature>/`, while
|
|
469
|
+
// `wdi-build` owns tickets at `{spec_folder}/issues/`. Two homes for one ticket set.
|
|
470
|
+
//
|
|
471
|
+
// Seeding them removes the interview for the answers WDI Method actually has a requirement on. Seeded
|
|
472
|
+
// ONCE and never overwritten — after the first install they are the product's, like every other file
|
|
473
|
+
// under a path the product owns. An owner who wants a different tracker re-runs the setup skill; the
|
|
474
|
+
// seeded file says which three invariants have to survive that.
|
|
475
|
+
function seedAgentDocs(target) {
|
|
476
|
+
const dir = path.join(target, "docs", "agents");
|
|
477
|
+
let wrote = 0;
|
|
478
|
+
for (const name of ["domain.md", "issue-tracker.md"]) {
|
|
479
|
+
const to = path.join(dir, name);
|
|
480
|
+
if (fs.existsSync(to)) continue;
|
|
481
|
+
const seed = path.join(ROOT, "scaffold", "docs", "agents", name);
|
|
482
|
+
if (!fs.existsSync(seed)) continue;
|
|
483
|
+
copyFile(seed, to);
|
|
484
|
+
wrote += 1;
|
|
485
|
+
}
|
|
486
|
+
if (wrote) {
|
|
487
|
+
note(`seeded docs/agents/ (${wrote} file${wrote === 1 ? "" : "s"}) — the engines' config, pre-answered`);
|
|
488
|
+
note(" do NOT run /setup-matt-pocock-skills to redo these; re-run it only to change tracker");
|
|
489
|
+
}
|
|
490
|
+
return wrote > 0;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// A repo that ran the setup skill BEFORE installing this package still carries the default `domain.md`,
|
|
494
|
+
// and it is actively misleading: it sends every engineering skill looking for a root `CONTEXT.md` and
|
|
495
|
+
// `docs/adr/`, and tells them to create both lazily. Seeding cannot fix it, because the file already
|
|
496
|
+
// exists and a file under a product-owned path is never overwritten. So it is named instead.
|
|
497
|
+
function warnStaleAgentDocs(target) {
|
|
498
|
+
const file = path.join(target, "docs", "agents", "domain.md");
|
|
499
|
+
if (!fs.existsSync(file)) return;
|
|
500
|
+
const text = fs.readFileSync(file, "utf8");
|
|
501
|
+
if (!/CONTEXT\.md|docs\/adr/.test(text)) return;
|
|
502
|
+
// An override note is what both real repos added by hand. Recognising it is what stops this warning
|
|
503
|
+
// from firing forever on a file somebody already fixed.
|
|
504
|
+
if (/does not use|MUST NOT be created|no `docs\/` layer/i.test(text)) return;
|
|
505
|
+
note("docs/agents/domain.md still points agents at a root CONTEXT.md and docs/adr/");
|
|
506
|
+
note(" Article 3: this method has no `docs/` layer for corpus or rules, and wdi-reconcile");
|
|
507
|
+
note(" reports both as findings. Say so at the top of that file — the glossary is at");
|
|
508
|
+
note(" .control/product-glossary.md and a decision is a DEC-, never an ADR");
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function migrateAutopilotLedgers(target) {
|
|
512
|
+
const dir = path.join(target, ".control", "memlog");
|
|
513
|
+
if (!fs.existsSync(dir)) return;
|
|
514
|
+
const OLD = /^autopilot-(\d{4}-\d{2}-\d{2})\.md$/;
|
|
515
|
+
for (const name of fs.readdirSync(dir)) {
|
|
516
|
+
const m = OLD.exec(name);
|
|
517
|
+
if (!m) continue;
|
|
518
|
+
const from = path.join(dir, name);
|
|
519
|
+
const text = fs.readFileSync(from, "utf8");
|
|
520
|
+
const artifact = /^artifact:\s*(\S.*)$/m.exec(text)?.[1]?.trim();
|
|
521
|
+
const id = artifact && /(DEC-\d+)/.exec(artifact)?.[1];
|
|
522
|
+
if (!id) {
|
|
523
|
+
note(`.control/memlog/${name} looks like a pre-0.6.2 autopilot ledger, but its \`artifact:\` does`);
|
|
524
|
+
note(` not resolve to a DEC- id — rename it to autopilot-<the mandate's DEC- id>.md yourself`);
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
const to = path.join(dir, `autopilot-${id}.md`);
|
|
528
|
+
if (fs.existsSync(to)) {
|
|
529
|
+
note(`BOTH .control/memlog/${name} and autopilot-${id}.md exist — neither was touched`);
|
|
530
|
+
note(` the run's ledger is in one of them and I cannot tell which. Merge them, then delete the other`);
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
mv(from, to);
|
|
534
|
+
note(`renamed .control/memlog/${name} → autopilot-${id}.md (content unchanged)`);
|
|
535
|
+
note(` \`mandate-accept\` looks for a mandate's ledger at this exact path`);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// A mandate opened before 0.6.2 recorded `parked: []` under the OLD default — full authority, AD-N
|
|
540
|
+
// contradictions included. 0.6.2 changed the DEFAULT for a NEW mandate to park `ad-n`, because
|
|
541
|
+
// decision-guide.md says narrowing an invariant MUST NOT be softened further. A default only applies
|
|
542
|
+
// at the moment a mandate is written, so an EXISTING accepted mandate keeps whatever it already says —
|
|
543
|
+
// silently adding `ad-n` to it would be overwriting a value the owner already chose, which `update`
|
|
544
|
+
// MUST NOT do to anything in the product's own registry. So this only ever WARNS, naming the mandate
|
|
545
|
+
// and the one line that would close the gap, and leaves the decision to whoever reads the summary.
|
|
546
|
+
function warnStaleMandates(target) {
|
|
547
|
+
const file = path.join(target, ".control", "registry", "decisions.yaml");
|
|
548
|
+
if (!fs.existsSync(file)) return;
|
|
549
|
+
const text = fs.readFileSync(file, "utf8");
|
|
550
|
+
const blocks = text.split(/\n(?=\s*-\s*id:\s*DEC-)/);
|
|
551
|
+
for (const block of blocks) {
|
|
552
|
+
if (!/type:\s*mandate/.test(block)) continue;
|
|
553
|
+
if (!/status:\s*accepted/.test(block)) continue;
|
|
554
|
+
const id = /id:\s*(DEC-\d+)/.exec(block)?.[1];
|
|
555
|
+
const parkedLine = /parked:\s*(\[[^\]]*\]|.*)$/m.exec(block)?.[0] || "";
|
|
556
|
+
const parkedBlockList = /parked:\s*\n((?:\s+-\s*\S.*\n?)*)/.exec(block)?.[1] || "";
|
|
557
|
+
if (/ad-n/.test(parkedLine) || /ad-n/.test(parkedBlockList)) continue;
|
|
558
|
+
note(`${id || "a mandate"} predates the \`ad-n\`-parked-by-default protection (0.6.2) — its \`parked\``);
|
|
559
|
+
note(` list does not name it, so it still decides an AD-N contradiction on its own`);
|
|
560
|
+
note(` add \`ad-n\` to its \`parked\` list in decisions.yaml yourself if you want the new default`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
428
564
|
function migrateRegistryNames(target) {
|
|
429
565
|
const reg = path.join(target, ".control", "registry");
|
|
430
566
|
const from = path.join(reg, "waves.yaml");
|
|
@@ -1027,6 +1163,10 @@ function apply(target, agents,
|
|
|
1027
1163
|
// is about to occupy. Running it after would leave two copies of most guides.
|
|
1028
1164
|
const migrated = migrateToTwoFolders(target);
|
|
1029
1165
|
migrateRegistryNames(target);
|
|
1166
|
+
migrateAutopilotLedgers(target);
|
|
1167
|
+
warnStaleMandates(target);
|
|
1168
|
+
seedAgentDocs(target);
|
|
1169
|
+
warnStaleAgentDocs(target);
|
|
1030
1170
|
seedRequirementSplit(target);
|
|
1031
1171
|
// The split MUST also be reachable without a migration. 0.5.2 only ran it from inside
|
|
1032
1172
|
// migrateToTwoFolders, which returns early when the old layout is absent — so a repo that took
|
|
@@ -1436,6 +1576,9 @@ function runNonInteractive(args) {
|
|
|
1436
1576
|
if (!args.skipBmad && !bmadPresent(target)) {
|
|
1437
1577
|
die(bmadMissingMessage());
|
|
1438
1578
|
}
|
|
1579
|
+
if (!args.skipEngines && !enginesPresent(target)) {
|
|
1580
|
+
die(enginesMissingMessage());
|
|
1581
|
+
}
|
|
1439
1582
|
const existing = readIndexIdentity(target);
|
|
1440
1583
|
const product = args.product || existing.name;
|
|
1441
1584
|
const client = args.client ?? existing.client;
|
|
@@ -105,6 +105,14 @@ Open with three reads, in this order:
|
|
|
105
105
|
2. **Reconcile `## Resume` against git.** Compare the run branch HEAD with the commit Resume names. A
|
|
106
106
|
difference is work that landed before the last iteration died — rebuild Resume from what git shows
|
|
107
107
|
**before** starting anything new. Trusting a stale Resume is how a merged ticket gets implemented twice.
|
|
108
|
+
|
|
109
|
+
**A ledger with no `## Resume` heading at all is the same case, one step further back.** It is a
|
|
110
|
+
pre-0.6.2 ledger — a flat table with nothing else — and `update` only ever renames the file, never
|
|
111
|
+
restructures its content, because that restructuring needs exactly this read. Heal it once, here,
|
|
112
|
+
before touching anything else: wrap the existing table under a `## Decisions` heading if it is not
|
|
113
|
+
already, then **build a fresh `## Resume`** the same way as a stale one above — from the mandate row,
|
|
114
|
+
`.control/generated/status`, and the run branch's actual HEAD, never from the table's last row read as
|
|
115
|
+
prose. The table's own rows are untouched; only the missing head is added.
|
|
108
116
|
3. `.control/generated/status`, the mandate row, and **the ledger's `## Resume` only** — see § The ledger
|
|
109
117
|
for why that is a section and not a file.
|
|
110
118
|
|
|
@@ -330,6 +338,7 @@ When § The work table reaches § Finish:
|
|
|
330
338
|
- A mandate accepted by delegation, or with no `expires`
|
|
331
339
|
- Deciding something the mandate parks, or parking something the mandate did not
|
|
332
340
|
- A decision taken and not written to the ledger
|
|
341
|
+
- A pre-0.6.2 ledger left un-healed — no `## Resume` wrapped and rebuilt on first touch
|
|
333
342
|
- Reading the whole ledger when the run is alive — `## Resume` is what an iteration loads
|
|
334
343
|
- A `## Resume` that restates a decision, or repeats what the registry already answers
|
|
335
344
|
- A ledger cell longer than a line, instead of a pointer to a companion document
|
|
@@ -49,6 +49,10 @@ mis-route in this flow, because every other gate is the same for every component
|
|
|
49
49
|
| State | Next |
|
|
50
50
|
|---|---|
|
|
51
51
|
| `wdi-method update` just ran and its summary printed an `upgrade` line | `wdi-upgrade` — **before anything else**. Content is still in the old shape, and every skill below reads the new one |
|
|
52
|
+
| `wdi-method update` just ran and printed **no** `upgrade` line | Nothing. The update was mechanical and complete; carry on from wherever the gates say you are |
|
|
53
|
+
| `wdi-method install` just ran, first time in this repo | `wdi-init` intent `setup` — the global `mode`, and nothing has started until it is set |
|
|
54
|
+
| Someone asks whether to run `/setup-matt-pocock-skills` | **No**, unless they are changing tracker. `install` and `update` seed `docs/agents/` already answered for this method; re-running the interview restores defaults that contradict Article 3 |
|
|
55
|
+
| The installer refused, naming the ticket engines | Not a skill. Install them — `/plugin install mattpocock-skills`, or `npx skills@latest add mattpocock/skills` — then run the installer again |
|
|
52
56
|
| No registry, or no global `mode` set | `wdi-init` intent `setup` — nothing has started |
|
|
53
57
|
| No `.what/_product-brief/brief.md` | `wdi-problem` — G1 has not started |
|
|
54
58
|
| A brief exists, and no PRD covers the area in play | `wdi-product` intent `prd` |
|
|
@@ -87,6 +91,10 @@ it claims, or when one of its eight required sections is missing outright.
|
|
|
87
91
|
as blocking a design gate; `assumptions.md` holds nothing.
|
|
88
92
|
- You MUST NOT invent progress. If `.control/generated/status` is missing or stale, say so and name
|
|
89
93
|
`validate.py --generate`.
|
|
94
|
+
- You MUST NOT route anyone to `/setup-matt-pocock-skills` to *finish an install*. The installer seeds
|
|
95
|
+
`docs/agents/` pre-answered, and that interview's own defaults send every engineering skill looking for a
|
|
96
|
+
root `CONTEXT.md` and `docs/adr/` — which Article 3 forbids and `wdi-reconcile` reports. It is for
|
|
97
|
+
changing tracker, and nothing else.
|
|
90
98
|
- You MUST NOT run other skills on the user's behalf. Name the skill; let them invoke it. The one skill that
|
|
91
99
|
runs others is `wdi-autopilot`, and only under a mandate the owner accepted — that is what the mandate is.
|
|
92
100
|
- When the next step is blocked by a decision rather than by work, route to `wdi-question` or
|
|
@@ -10,6 +10,14 @@ content needs no judgment, seeds what is new, prunes what is retired. It stops e
|
|
|
10
10
|
about **content** begins — which PRD an `FR` belongs to, whether a sentence in the old brief was an
|
|
11
11
|
assumption or a constraint. Those are this skill's half.
|
|
12
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
|
+
|
|
13
21
|
**This is the one skill allowed to edit `brief.md`, `prd.md`, an SRS, an SDD, or a C4 file directly.**
|
|
14
22
|
Every other skill is forbidden, because a hand edit makes the memlog lie about how the document was
|
|
15
23
|
produced. An upgrade produces nothing: it moves sentences that already exist into the home the new
|
package/kit-overlay/AGENTS.md
CHANGED
|
@@ -154,6 +154,9 @@ verifies the result, and lands the memlog.
|
|
|
154
154
|
not diligence.
|
|
155
155
|
- `.claude/skills/bmad-*/customize.toml` MUST NOT be edited — it is overwritten on every BMad update;
|
|
156
156
|
customise through `_bmad/custom/`.
|
|
157
|
+
- `CONTEXT.md`, `CONTEXT-MAP.md`, and `docs/adr/` MUST NOT be created. `docs/agents/domain.md` is the
|
|
158
|
+
engines' config and says so too: the vocabulary is `.control/product-glossary.md`, domain knowledge is
|
|
159
|
+
`.what/`, design is `.how/`, and a decision is a `DEC-` — never an ADR. Article 3 owns the rule.
|
|
157
160
|
|
|
158
161
|
## Routing — load a guide when the task matches
|
|
159
162
|
|
|
@@ -184,6 +187,7 @@ verifies the result, and lands the memlog.
|
|
|
184
187
|
| Looking for where code lives, or placing new code | `.control/structure-codebase.md` |
|
|
185
188
|
| Looking for where a document lives | `.control/structure-document.md` |
|
|
186
189
|
| Writing or reviewing code | `.constitution/project/codebase-stack-guide.md` · `.constitution/project/codebase-conventions-guide.md` · `.constitution/project/codebase-brownfield-guide.md` |
|
|
190
|
+
| Running `to-spec`, `to-tickets`, `implement`, or `triage` | `docs/agents/issue-tracker.md` · `docs/agents/domain.md` — the engines' own config, seeded by `wdi-method` already answered for this method |
|
|
187
191
|
|
|
188
192
|
All three `.constitution/project/codebase-*-guide.md` start as `status: Draft`. While they are, their contents MAY be read
|
|
189
193
|
as guidance but MUST NOT be used to reject a change.
|
package/package.json
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Domain Docs
|
|
2
|
+
|
|
3
|
+
How the engineering skills should consume this repo's domain documentation when exploring the codebase.
|
|
4
|
+
|
|
5
|
+
**This repo does not use `CONTEXT.md`, `CONTEXT-MAP.md`, or `docs/adr/`, and none of them MUST be
|
|
6
|
+
created.** WDI Method already owns every home they would occupy, and a second home for the same fact is
|
|
7
|
+
drift rather than tidiness. `.constitution/method/constitution.md` Article 3 states it outright: this
|
|
8
|
+
method has no `docs/` layer for corpus or rules, and `wdi-reconcile` reports a root `CONTEXT.md` or a
|
|
9
|
+
`docs/adr/` as a finding against that article.
|
|
10
|
+
|
|
11
|
+
This file is seeded by `wdi-method` so the answer is right from the first install. `/setup-matt-pocock-skills`
|
|
12
|
+
would otherwise write its own default here — one that points at exactly the two paths above — and every
|
|
13
|
+
repo that ran it has had to hand-correct this file afterwards.
|
|
14
|
+
|
|
15
|
+
## Where each thing actually lives
|
|
16
|
+
|
|
17
|
+
| Looking for | Read |
|
|
18
|
+
|---|---|
|
|
19
|
+
| What a domain term means | `.control/product-glossary.md` |
|
|
20
|
+
| What is promised — a capability, an `FR`, a use case, a business rule | `.what/` |
|
|
21
|
+
| How it is built — the spine, C4, an inventory, an SDD, a contract | `.how/` |
|
|
22
|
+
| Why it is like this — a decision worth remembering | `.control/decisions/`, indexed by the generated decision table under `.control/generated/` |
|
|
23
|
+
| An architectural invariant | an `AD-N` in the architecture spine, under `.how/_platform/` |
|
|
24
|
+
| Which contexts exist and what each owns | `.control/registry/components.yaml` |
|
|
25
|
+
| Where code lives | `.control/structure-codebase.md` |
|
|
26
|
+
| Where documents live | `.control/structure-document.md` |
|
|
27
|
+
|
|
28
|
+
`AGENTS.md` § *The thing in your hand → its folder* is the short version of this table and is the
|
|
29
|
+
authority. Where this file and `AGENTS.md` disagree, `AGENTS.md` wins.
|
|
30
|
+
|
|
31
|
+
## A decision is a `DEC-`, never an ADR
|
|
32
|
+
|
|
33
|
+
`decision-guide.md` owns the shape, the one test that decides whether a decision is recorded at all, and
|
|
34
|
+
the `draft → accepted → applied` ladder. An ADR file under `docs/adr/` MUST NOT be written in its place:
|
|
35
|
+
the numbering is global and lives in `.control/registry/decisions.yaml`, and a decision recorded outside
|
|
36
|
+
it is invisible to `refs-resolve`, to the RTM, and to the generated decision table.
|
|
@@ -0,0 +1,43 @@
|
|
|
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.
|