baldart 5.4.1 → 5.6.0

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.
Files changed (32) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/VERSION +1 -1
  3. package/framework/.claude/agents/CHANGELOG.md +16 -0
  4. package/framework/.claude/agents/prd-card-writer.md +37 -3
  5. package/framework/.claude/skills/new/CHANGELOG.md +33 -0
  6. package/framework/.claude/skills/new/SKILL.md +11 -5
  7. package/framework/.claude/skills/new/references/commit.md +12 -8
  8. package/framework/.claude/skills/new/references/completeness.md +10 -0
  9. package/framework/.claude/skills/new/references/final-review.md +23 -0
  10. package/framework/.claude/skills/new/references/implement.md +14 -4
  11. package/framework/.claude/skills/new/references/merge-cleanup.md +35 -14
  12. package/framework/.claude/skills/new/references/setup.md +1 -1
  13. package/framework/.claude/skills/new2/CHANGELOG.md +50 -0
  14. package/framework/.claude/skills/new2/SKILL.md +101 -17
  15. package/framework/.claude/skills/prd/CHANGELOG.md +36 -0
  16. package/framework/.claude/skills/prd/SKILL.md +17 -5
  17. package/framework/.claude/skills/prd/assets/state-template.md +8 -1
  18. package/framework/.claude/skills/prd/references/audit-phase.md +13 -1
  19. package/framework/.claude/skills/prd/references/backlog-phase.md +20 -0
  20. package/framework/.claude/skills/prd/references/discovery-phase.md +35 -0
  21. package/framework/.claude/skills/prd/references/ui-design-phase.md +28 -0
  22. package/framework/.claude/skills/prd/references/validation-phase.md +45 -1
  23. package/framework/.claude/skills/worktree-manager/CHANGELOG.md +13 -0
  24. package/framework/.claude/skills/worktree-manager/SKILL.md +11 -1
  25. package/framework/.claude/skills/worktree-manager/scripts/merge-worktree.sh +82 -6
  26. package/framework/.claude/workflows/new-final-review.js +9 -7
  27. package/framework/.claude/workflows/new2-resolve.js +29 -1
  28. package/framework/.claude/workflows/new2.js +153 -17
  29. package/framework/agents/card-schema.md +18 -1
  30. package/framework/agents/research-protocol.md +6 -1
  31. package/framework/scripts/stamp-holistic-audit.js +53 -10
  32. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: new2
3
3
  effort: high
4
- version: 1.6.0
4
+ version: 1.8.0
5
5
  description: >
6
6
  Workflow-hosted batch engine for /new. Implements one or
7
7
  more backlog cards end-to-end by delegating the WHOLE batch to a background
@@ -85,8 +85,9 @@ everywhere this skill branches on it — Step 3.5 resolves deterministically (it
85
85
  AUTONOMOUS branch) and **Step 3b's escape hatch is SKIPPED** (the user asked for
86
86
  `-auto`; a post-batch question — and a possible `/new` re-invocation at full
87
87
  inline cost — would break that promise even with a TTY present). `/new` only
88
- delegates **migration-free** batches (it probes `migration_plan.required`
89
- itself), so Step 3.5's one interactive question cannot fire on a delegated run —
88
+ delegates **migration-free** batches (it probes ALL migration vocabularies
89
+ itself `migration_plan.required`, epic `db_migrations_summary`, per-card
90
+ `db_migration.required`), so Step 3.5's one interactive question cannot fire on a delegated run —
90
91
  if you nonetheless find a declared, unapplied migration in a delegated batch,
91
92
  HALT and hand back to `/new` classic (`"batch con migrazione dichiarata — riesegui
92
93
  /new <cards> -auto -inline"`) instead of asking. Everything else is identical to a
@@ -129,8 +130,16 @@ untouched), so the schema is live **before** the workflow starts. It mirrors `/n
129
130
  1. **Find the batch's epic card(s)** — distinct `group.parent` of the resolved cards (or the `-full`
130
131
  parent). Read each epic YAML in `${paths.backlog_dir}` (`<PARENT>-*-epic.yml`, or the card whose
131
132
  `id == <PARENT>` / `group.is_epic: true`).
132
- 2. **Look for `migration_plan` with `required: true`.** None set `migration = { status: 'none' }`
133
- and go to Step 4 (identical to today zero extra prompts; do not surface anything).
133
+ 2. **Look for a declared migration under ANY recognized vocabulary.** Primary: epic
134
+ `migration_plan` with `required: true`. **Compat aliases (consumer-overlay conventions
135
+ FEAT-0067 root cause: probing only `migration_plan` made this gate structurally blind to
136
+ `db_migration`-declaring cards)**: epic `db_migrations_summary` (non-empty), or any batch card
137
+ with `db_migration.required: true` (map: `artifacts` ← `db_migration.expected_file`; `summary`
138
+ ← the slug; modalities ← `db_migration.remote_push` + overlay). Nothing declared → set
139
+ `migration = { status: 'none' }` and go to Step 4 (identical to today — zero extra prompts; do
140
+ not surface anything). Declared via ANY vocabulary → record `migrationDeclared: true` +
141
+ `declaredVia` in your own working state (Step 5.1b keys off it — it must NOT depend on the
142
+ workflow's residual ledger surviving) and continue below.
134
143
  3. **(declared) Verify `migration_plan.artifacts` exist on disk under `$MAIN`.** Any missing → do NOT
135
144
  apply or prompt; set `migration = { status: 'degraded', reason: 'artifact missing', artifacts }`
136
145
  and go to Step 4 (the migration falls back to the current end-of-batch owner-gated deferral — no
@@ -193,7 +202,9 @@ Workflow({ name: 'new2', args: {
193
202
  ```
194
203
 
195
204
  Record the kickoff time (`ts`) before the call — Step 5 uses it to stamp the
196
- real wall-clock duration (the workflow cannot read a clock).
205
+ real wall-clock duration (the workflow cannot read a clock). Also record the
206
+ pre-batch trunk sha (`git -C $MAIN rev-parse ${trunk}`) — Step 5.4b audits every
207
+ non-card commit the batch introduced against it (v5.6.0).
197
208
 
198
209
  Capture `sessionId` the same way, in THIS skill's own context (not a subagent):
199
210
  `Bash(echo "${CLAUDE_CODE_SESSION_ID:-}")`. The workflow stamps it as
@@ -245,6 +256,44 @@ returns when the batch is done. It returns:
245
256
  step-1b HALT fields — the `/new` pre-flight back-fill (step 1b-ii) then normalizes its
246
257
  `review_profile`/`owner_agent` on first ingestion, so even the crisis stub self-heals. This
247
258
  main-repo, **disk-verified** write is the SSOT — nothing is dropped even on a non-merged batch.
259
+ **Exception (v5.6.0):** residuals of kind `false-epic-closure` and `main-repo-contamination` are
260
+ **reconciliation ACTIONS, not backlog work** — do NOT mint follow-up cards for them. The former
261
+ is handled by step 2's REOPEN branch; the latter by step 4b's hygiene audit (inspect + restore
262
+ the named main-repo paths).
263
+ 1b. **Migration Sync Tail (post-merge "branch B" — the interactive owner-gated deploy the
264
+ autonomous batch could not run).** The workflow has returned and merged; you are the skill
265
+ main loop, in `$MAIN`, typically on `$TRUNK` — exactly the precondition of the project's
266
+ post-merge sync gate (e.g. the overlay's "on trunk, post-merge" branch). **Trigger — EITHER
267
+ condition, independently** (belt-and-braces: the FEAT-0067 failure dropped the residual
268
+ mid-run, so this tail keys on the Step-3.5 DECLARATION, never only on the ledger):
269
+ (a) `migrationDeclared` from Step 3.5 (any vocabulary) with `migration.status ≠ 'applied'`;
270
+ (b) any `residuals[]` entry whose kind/owner-gated action maps to `db-migration-deploy`.
271
+ Neither → skip silently. Steps:
272
+ - **Resolve the project's post-merge sync contract**, in source order: (i) the batch cards'
273
+ `db_migration.remote_push` / `migration_plan` (check command + push command); (ii) the
274
+ post-merge / trunk branch of the Migration Sync Gate section in `.baldart/overlays/new.md`;
275
+ (iii) `migration_plan.verify` alone (check-only). Nothing resolvable → skip the tail (the
276
+ step-1 follow-up card remains the ledger) and say so in the presentation.
277
+ - **Run the read-only sync CHECK first** (e.g. the overlay's check-sync command), from `$MAIN`
278
+ on `$TRUNK` (if `$MAIN` is not on `$TRUNK`, do not switch branches yourself — report and
279
+ leave the follow-up as ledger). **Green** → the migration is live: the `db-migration-deploy`
280
+ residual is SATISFIED (no follow-up needed — if step 1 already created one, delete it in the
281
+ same reconciliation commit and note why); record it and let step 2 DONE-flip the migration
282
+ card with its schema AC satisfied.
283
+ - **Red + INTERACTIVE** → ONE `AskUserQuestion` (post-batch skill-layer interaction, same
284
+ class as Step 3b — the zero-ask-during-batch invariant is untouched): *"La migration del
285
+ batch non risulta applicata al DB remoto (check-sync rosso). Come procedo?"* Options:
286
+ **[Push now]** (run the declared owner-gated push command from `$TRUNK` — honour
287
+ `stack.schema_deploy_from_trunk_only`; output to `/tmp/migration-push-<firstCard>.log`,
288
+ surface the exit code, then RE-RUN the check and require green) / **[Defer]** (keep the
289
+ step-1 follow-up card as the ledger; the card stays DONE-with-follow-up per its
290
+ `owner-gated` class) / **[Override]** (record the user's verbatim reason). Never push
291
+ without the user picking it.
292
+ - **Red + AUTONOMOUS** (env / delegated `/new -auto` origin — Step 1.5) → NEVER push
293
+ (outward, owner-gated). Ensure the step-1 follow-up exists, and surface the pending deploy
294
+ PROMINENTLY in the presentation (step 4) — a truthful "schema NOT live" line, not a footnote.
295
+ - Record `migration_sync_tail: { ran, trigger: 'declared'|'residual'|'both', check:
296
+ 'green'|'red'|'unavailable', pushed: <bool>, outcome }` for telemetry (step 5).
248
297
  2. **Mark deferred cards DONE — only after their follow-up exists AND every deferral class allows
249
298
  it (F-040/H + A3).** Some committed cards were intentionally left **NON-DONE** because they carry
250
299
  an open deferred AC: they are `perCardResults[]` entries with `deferred:true` plus a
@@ -267,11 +316,25 @@ returns when the batch is done. It returns:
267
316
  **Then re-run the epic-closure check for the cards just marked DONE.** The merge agent's
268
317
  epic-closure (Phase 6b step 5e) ran BEFORE this step, when the deferred cards were still
269
318
  NON-DONE — so an epic whose last open child was a deferred card is still TODO and nothing
270
- else will ever close it. For each distinct `group.parent` of the cards marked DONE here: if
271
- `grep -l "parent: <EPIC-ID>" ${paths.backlog_dir}/*.yml | xargs grep -L "status: DONE"`
272
- prints nothing, set the epic card `status: DONE` + `completed_date` + note
273
- `"epic-closure gate all children DONE (post-run, new2 skill)"`, folded into the SAME
274
- reconciliation commit. If any child is still open, leave the epic untouched.
319
+ else will ever close it. For each distinct `group.parent` of the cards marked DONE here,
320
+ close ONLY when the FULL v5.6.0 predicate holds (the same one the merge agent runs —
321
+ `merge-cleanup.md` § epic closure): (a) `grep -l "parent: <EPIC-ID>" ${paths.backlog_dir}/*.yml
322
+ | xargs grep -L "status: DONE"` prints nothing — **follow-up cards count as children** (step 1
323
+ just materialised them here in the main repo, so this grep now sees them); (b) no `residuals[]`
324
+ entry of a blocking class (`scope-expansion`/`unresolved`/`ac-unmet`/`out-of-ownership`) maps to
325
+ a child of this epic; (c) the epic YAML's own `acceptance_criteria` are all `[x]` — verify any
326
+ still-`[ ]` item with its `ac_verification` oracle (or a targeted check) and flip it ONLY with
327
+ evidence; an unverifiable AC leaves the epic OPEN. When all three hold, set the epic
328
+ `status: DONE` + `completed_date` + note `"epic-closure gate — children DONE + epic ACs
329
+ verified (post-run, new2 skill)"`, folded into the SAME reconciliation commit. Otherwise leave
330
+ the epic untouched and say why in the presentation.
331
+ **REOPEN branch (v5.6.0 — the ratchet is two-way now).** For every `false-epic-closure`
332
+ residual, AND for any epic found `status: DONE` on disk while the grep above still prints an
333
+ open child (follow-ups included) or a closure-invalidating finding stands: flip the epic back
334
+ to `status: IN_PROGRESS`, remove/annotate its `completed_date`, add note `"REOPENED — closed
335
+ against open scope (false DONE, v5.6.0 guard)"`, and fold into the same reconciliation commit.
336
+ An epic whose registry/ADR text says "goal not achieved" while its YAML says DONE is exactly
337
+ the FEAT-0068 contradiction this branch exists to prevent — the STATE wins, not the prose.
275
338
  3. **Resume if degraded — HARD-BOUNDED (v4.92.0).** If `degraded` is true, re-invoke
276
339
  the workflow with `Workflow({ scriptPath, resumeFromRunId })` (same `args` + the
277
340
  new `ts`). The per-card **skip-completed** guard makes the resume idempotent —
@@ -334,11 +397,31 @@ returns when the batch is done. It returns:
334
397
  (out of scope by design — the workflow is autonomous).
335
398
  - Record `escape_hatch: { eligible: N, offered: <bool>, ran_new: <bool>, followups: [...] }`
336
399
  in telemetry (step 5 below) so the A/B stays honest about when the hatch was used.
337
- 4. **Present.** Print `report` verbatim. Surface `residuals` prominently
338
- ("questi residui sono tracciati come follow-up: …") the post-run review that
339
- replaced the ~25 mid-run questions. If `degraded`, say so plainly (the run was
340
- incomplete and resumed). If the escape hatch ran `/new` (step 3b), fold its outcome
341
- into the presentation (which follow-ups were closed by `/new`).
400
+ 4. **Present.** Print `report` verbatim **including its verdict headline** (`⚠️ PARTIAL` /
401
+ `✅ COMPLETO`, v5.6.0): NEVER re-headline a PARTIAL run as a success in your own framing, and
402
+ never bury an epic-goal gap under a completion table (the FEAT-0068 report said "✅ 6/6 DONE"
403
+ over a disclosed-but-buried HIGH gap — the user discovered it only by asking). Surface
404
+ `residuals` prominently ("questi residui sono tracciati come follow-up: …") the post-run
405
+ review that replaced the ~25 mid-run questions; a HIGH residual is REMAINING WORK, present it
406
+ as such. If `degraded`, say so plainly (the run was incomplete and resumed). If the escape
407
+ hatch ran `/new` (step 3b), fold its outcome into the presentation (which follow-ups were
408
+ closed by `/new`).
409
+ 4b. **Batch git hygiene audit (v5.6.0 — never assert provenance without checking).** From the
410
+ kickoff you know the trunk's pre-batch sha (record `git -C $MAIN rev-parse ${trunk}` at Step 4
411
+ BEFORE launching the workflow). Now:
412
+ - `git -C $MAIN log --oneline <pre-sha>..HEAD` — for every commit whose subject does NOT
413
+ reference a batch card id (e.g. `[safety]`, unexpected chores), run `git show --stat <sha>`
414
+ and LIST it in the presentation with its files. Never attribute a commit to "a previous run"
415
+ without this check (the FEAT-0068 orchestrator asserted exactly that, and it was false).
416
+ A safety/sweep commit whose files are outside the batch's bookkeeping is a finding to
417
+ surface, not to normalize.
418
+ - `git -C $MAIN stash list` — any stash created during this batch (grep the batch/card ids and
419
+ the `baldart-new2-` label) MUST be reconciled NOW: inspect (`git stash show -p`), then apply
420
+ or drop with the user's standing policy — in AUTONOMOUS mode leave it but list it as a
421
+ PROMINENT pending item, never as a footnote and never "not mine to drop" (if this batch's
422
+ machinery created it, it IS yours to reconcile).
423
+ - Every `main-repo-contamination` residual: inspect the named paths in `$MAIN` and restore
424
+ them (they are the commit-agent detour's droppings), reporting what was restored.
342
425
  5. **Record truthful telemetry — reconciled against disk (F-040).** Before appending `telemetry`
343
426
  to `${metricsDir}/skill-runs.jsonl`, fill the fields the workflow could not compute and
344
427
  **reconcile the report against the real disk state** (agent `reason` strings can over-claim — a
@@ -358,7 +441,8 @@ returns when the batch is done. It returns:
358
441
  (partial, output-only, excludes nested workflows). Keep `degraded`/`degradation_reasons` +
359
442
  `cards_deferred_done_pending` in the record so
360
443
  the A/B comparison stays honest. Also record `migration_gate: <migration.status>`
361
- (`none`|`applied`|`skipped`|`degraded`) the Step-3.5 gate is a pre-launch interaction, NOT a
444
+ (`none`|`applied`|`skipped`|`degraded`) and `migration_sync_tail` (Step 5.1b whether the
445
+ post-merge check ran, its outcome, and whether an owner-gated push was user-approved) — the Step-3.5 gate is a pre-launch interaction, NOT a
362
446
  mid-batch question, so it does not break the zero-ask-during-batch invariant; logging it keeps the
363
447
  A/B honest about when a migration was front-loaded. Keep `deferral_breakdown` (per-class counts
364
448
  of WHY residuals became follow-ups instead of in-batch fixes) in the record — a class dominating
@@ -2,6 +2,42 @@
2
2
 
3
3
  Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
4
4
 
5
+ ## 1.6.0 — 2026-07-04 (FEAT-0068 post-mortem: il root cause era qui)
6
+
7
+ - **ISA "UI ROLE FAMILY (registry-first)"** (`discovery-phase.md` Dimension 9, gated su
8
+ `features.has_design_system`): per feature chrome/primitive enumera i PROPRIETARI della
9
+ superficie del goal dal registry (role families / Selection Policy), non solo i consumer
10
+ esistenti del meccanismo; **flag BLOCK su `@deprecated`** nel fix-path (i successori
11
+ documentati diventano il target). Era: DrilldownHeader/SectionHeader (~90% degli screen)
12
+ in NESSUNA card, ricetta ancorata su un Header deprecato da 5 pagine.
13
+ - **§0 LOAD CONTRACT** in testa a `discovery-phase.md`: il modulo supera il cap del Read —
14
+ vista PARTIAL ⇒ offset-Read obbligatori fino alla fine (la coda persa conteneva Exit
15
+ condition + Codex completeness cross-check + Research Trigger, mai eseguiti sul run reale).
16
+ - **`module_read` stamps** (SKILL.md): la lettura dei moduli di fase è ESEGUITA non recitata
17
+ — stamp nello state file, verificato dal validator (3 moduli mai letti sul run reale).
18
+ - **`step_3_mode` enum CHIUSO + contratto `skipped`** (`ui-design-phase.md`): `skipped` =
19
+ NESSUN artefatto di design, `links.design` vuoto, ogni explainer passa da `/ui-design`
20
+ (era: modalità fabbricata `design-spec` + design.html hand-authored su 5/6 card);
21
+ **Reconciliation-lite** (no mockup ≠ no reconciliation: role family dal registry ⇒
22
+ `component_bindings`); **trigger di ri-enumerazione ISA** quando la ricetta cambia target.
23
+ - **Gate quantificatore-universale sugli AC epic** (`validation-phase.md` item e):
24
+ "ogni schermata" ⇒ owner della superficie (census fresco) ⊆ unione scope figli, else
25
+ BLOCKER; `invariant_owners:` persistiti nell'epic.
26
+ - **Item 0-ii Phase-evidence audit** (`validation-phase.md`): stamp module_read + gate con
27
+ evidenza (API Perf Gate stampato `N/A` senza spawn sul run reale) + enum step_3_mode.
28
+ - **Stamp holistic evidence-gated** (`stamp-holistic-audit.js --audit-report` →
29
+ `agents_run`/`findings_count`; senza artefatto → `status: skipped` che `/new` tratta come
30
+ ASSENTE). Era: stamp su 6/6 card con zero spawn di audit (phantom stamp).
31
+ - **Card-writer self-validation** (`backlog-phase.md` + agente): il validator gira
32
+ nell'output del writer PRIMA del return (era: round-trip completo su EARS in italiano);
33
+ **Rule A ramo deterministico** (files docs/test-only ⇒ owner coder, mai `links.design`);
34
+ epic con `ac_verification` obbligatoria + mai count hardcodato; invariante lifecycle
35
+ baseline per suite snapshot.
36
+ - **Step 7.9 HARD RULE mw-docs** (`validation-phase.md`): mai `/mw` generico su worktree
37
+ `kind: docs` (+ guardia lato worktree-manager); era ~4M di BUILD_FAIL falso + unblock umano.
38
+ - **EDIT CONTRACT dello state file** (template + HARD RULE 2): anchor sul bare `key:` con
39
+ literal appena letto (5 retry ciechi da ~250k sul run reale).
40
+
5
41
  ## 1.5.0 — 2026-07-03 (framework v5.4.0)
6
42
 
7
43
  - **Step 2.1 Tier Gate (elastic pipeline).** At Discovery exit the feature is classified
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: prd
3
3
  effort: high
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  description: "Structured PRD creation skill. Use when the user says /prd, 'crea un prd', 'nuova funzionalita', 'pianifica feature', or wants to plan a new feature end-to-end. Also handles /prd-add, 'aggiungi requisito', 'serve anche', 'manca un endpoint' for change requests on active PRD sessions — runs ICIAS impact analysis to determine which phases need SKIP/PATCH/REDO. Produces PRD + UI design + backlog cards, all validated and committed. Multi-turn conversation: asks questions, waits for answers, iterates through discovery, design, spec writing, card creation, and validation phases."
6
6
  ---
7
7
 
@@ -54,9 +54,17 @@ message. You ask questions, wait for answers, and iterate.
54
54
  | 7 | Resolution, Commit & Merge | [validation-phase.md](references/validation-phase.md) |
55
55
  | 7.6 | Obsidian back-reference — FINAL (upgrades the 1.2 provisional block; only if a spec note was given) | [validation-phase.md](references/validation-phase.md) + [obsidian-backref.md](references/obsidian-backref.md) |
56
56
 
57
- **Before starting each phase, read the corresponding reference file**with ONE
58
- exception class: **agent-facing specs are passed BY PATH to the agent that consumes
59
- them and MUST NOT be loaded into the orchestrator context.** Today these are
57
+ **Before starting each phase, read the corresponding reference file — EXECUTED, not
58
+ recited (v5.6.0).** After reading a phase module, record `module_read: <file> (full)` in the
59
+ state file's section for that phase; if the Read reported a PARTIAL view (the module exceeds
60
+ the token cap — `discovery-phase.md` does), issue offset Reads until the END of the file
61
+ before proceeding and stamp `(full, N reads)`. The Step 6 validator (`validation-phase.md`
62
+ item 0-ii) checks these stamps deterministically. This exists because a real session ran
63
+ Steps 2.5/4/4.5/5 with `research-phase.md`, `prd-writing-phase.md` and `backlog-phase.md`
64
+ NEVER read (6 Reads total in 73 turns): the improvised Step 5 contract produced a full
65
+ validator-rework round, and the truncated discovery tail silently dropped the mandatory Codex
66
+ completeness cross-check. ONE exception class: **agent-facing specs are passed BY PATH to the
67
+ agent that consumes them and MUST NOT be loaded into the orchestrator context.** Today these are
60
68
  `references/api-perf-gate.md` (read by `api-perf-cost-auditor` at Step 4.5 and at the
61
69
  Step 6 audit) and `references/audit-teammate-prompt.md` (read by each Step 6.6 audit
62
70
  teammate). Rationale: a spec loaded by a subagent costs one cheap Read in a disposable
@@ -70,7 +78,11 @@ for the rest of the run.
70
78
  > **Runtime portability.** On **Codex**, bind this skill's mechanics per `framework/agents/runtime-portability-protocol.md` (named-agent spawn, decision gates, file-backed state; never probe `Workflow`/`AskUserQuestion`/the task spine). Rules below are Claude-first with explicit **Codex:** branches (RULES 4, 11) — additive, Claude imperatives unchanged.
71
79
 
72
80
  1. Follow steps in order. NEVER skip a step or jump ahead.
73
- 2. Every step MUST update the state file before proceeding.
81
+ 2. Every step MUST update the state file before proceeding. **State-file Edit hygiene
82
+ (v5.6.0):** anchor every Edit on the bare `key:` prefix with a literal you just Read —
83
+ never a recalled literal with trailing comments/alignment/blank lines (the template's
84
+ EDIT CONTRACT header; 5 blind retries at ~250k each on a real session). A failed match →
85
+ Read the exact lines, retry ONCE with the fresh literal.
74
86
  3. Every gate MUST be satisfied before moving to the next step.
75
87
  4. **Progress tracking.** Claude Code: use TaskCreate/TaskUpdate for ALL progress tracking. **Codex** (no task spine): use a file-backed queue at `$WORKTREE_PATH/${paths.prd_dir}/sessions/<slug>-tasks.jsonl` — one record per task (`status` / `claimed_by` / `findings_path`) — and the session **state file** stays the recovery SSOT either way. (Binding: `framework/agents/runtime-portability-protocol.md` § state-spine.)
76
88
  5. When context is compressed or session resumes: run Step 0 first.
@@ -1,4 +1,11 @@
1
1
  # PRD Session: {{slug}}
2
+
3
+ <!-- EDIT CONTRACT (v5.6.0 — N8, 5 failed Edits at ~250k context each on a real session):
4
+ when updating a `key: value` line in this file, ANCHOR ON THE BARE KEY PREFIX ONLY
5
+ (`old_string` = from start-of-line through the current value you just Read — never a
6
+ recalled-from-memory literal that includes trailing `# comments`, column alignment, or
7
+ surrounding blank lines; those drift). If an Edit fails to match, Read the exact lines
8
+ FIRST and retry once with the fresh literal — never loop blind retries. -->
2
9
  Created: {{YYYY-MM-DD HH:MM}}
3
10
  Status: discovery # discovery | mockups-pending-input | research-in-progress | pending-external-handoff | ui-design | writing | specs-confirmed | backlog | audit | validation | committing | completed | done
4
11
  stats_enabled: {{true if invoked with -stats/--stats, else false}}
@@ -121,7 +128,7 @@ mockup_analysis.design_system_alignment:
121
128
  status: pending # aligned | violations | not-applicable
122
129
  violations: []
123
130
 
124
- step_3_mode: pending # full | hybrid | skipped | mockup-only
131
+ step_3_mode: pending # CLOSED ENUM: full | hybrid | skipped | mockup-only | pending_external_handoff — any other value is a Step 6 BLOCKER (v5.6.0)
125
132
  design.html_path: pending # path | n/a (mockup-only)
126
133
 
127
134
  screens_in_scope: [] # [{ name, slot_id, screen_id, canvas_ref, covered_by_mockups: bool, generated_in_step_3b: bool }]
@@ -398,8 +398,19 @@ metadata:
398
398
  audited_at: "<HOLISTIC_AUDITED_AT>"
399
399
  audited_commit: "<HOLISTIC_AUDITED_COMMIT>" # "" if git unavailable → /new treats as drift (runs Step 3d)
400
400
  audited_set: ["FEAT-XXXX-01", "FEAT-XXXX-02", ...] # sorted; the joint cross-card scope
401
+ agents_run: ["plan-auditor", "codebase-architect", ...] # v5.6.0 EVIDENCE — written by the
402
+ # stamper from the audit report artifact (--audit-report). A stamp WITHOUT a non-empty
403
+ # agents_run is treated as ABSENT by /new P1 (the plan-auditor runs): on FEAT-0068 the
404
+ # stamp landed on all 6 cards while the audit team never spawned (phantom stamp).
405
+ findings_count: 3 # optional, from the report
401
406
  ```
402
407
 
408
+ **Write the audit report artifact FIRST (v5.6.0 — the stamp's evidence).** Before running the
409
+ stamper, persist the Step 6.6 audit outcome to `/tmp/prd-audit-<slug>.md` with at minimum a
410
+ literal `agents_run: <comma-separated agent types actually spawned>` line and a
411
+ `findings_count: <N>` line. No spawns happened → do NOT fabricate the file: run the stamper
412
+ without `--audit-report` and it stamps `status: "skipped"` honestly.
413
+
403
414
  > **Fail-safe contract**: the block is an OPTIMIZATION hint for `/new`, never a *correctness* gate — if `audited_commit` is empty or the block is absent, `/new` Step 3d **and** the `implement.md` Phase-1 plan-auditor grounding (step 4, P1) simply RUN as before (redundant, never wrong). **But writing the block is MANDATORY whenever the audit ran.** It is the single most-omitted step under context pressure, and its absence is exactly what makes `/new` / `new2` spawn the plan-auditor on **every** freshly-authored card even when the batch is implemented immediately after this audit (nothing changed since). Do NOT skip it "to save a write". If git is genuinely unavailable, write `audited_commit: ""` **explicitly** — never omit the block. `validation-phase.md` Step 7 item 5b is the **deterministic backstop** that guarantees this lands before the PRD commit even if this per-card write is missed — but write it here too; the backstop is a safety net, not a license to skip.
404
415
 
405
416
  **Deterministic writer — EXECUTE, don't hand-edit.** `framework/scripts/stamp-holistic-audit.js` mechanizes this write (idempotent, additive, epic-skipping, self-verifying). Run it ONCE for the whole card set after the per-card field edits:
@@ -407,7 +418,8 @@ metadata:
407
418
  ```bash
408
419
  node .framework/framework/scripts/stamp-holistic-audit.js \
409
420
  --at "$HOLISTIC_AUDITED_AT" --commit "$HOLISTIC_AUDITED_COMMIT" \
410
- --set "<sorted child IDs, comma-separated>" ${CARD_PATHS}
421
+ --set "<sorted child IDs, comma-separated>" \
422
+ --audit-report "/tmp/prd-audit-<slug>.md" ${CARD_PATHS}
411
423
  ```
412
424
 
413
425
  Hand-edit the YAML only when the script is genuinely unreachable in this install — and say so in the audit log.
@@ -22,6 +22,19 @@ and BLOCK the commit. The `/new` orchestrator dispatches implementation
22
22
  agent by this field (see `framework/.claude/skills/new/SKILL.md` § Agent
23
23
  Routing), so a wrong value silently routes the card to the wrong specialist.
24
24
 
25
+ **Rule A deterministic branch (v5.6.0 — FEAT-0068):** when a card's
26
+ `files_likely_touched` are ALL docs/test/config/meta paths (zero `src/` UI or
27
+ component/style files), `owner_agent` MUST be `coder` regardless of the
28
+ feature's topic — a docs+ADR+test card for a UI epic is still a coder card
29
+ (`owner_agent: ui-expert` with zero UI paths is a Step 6 BLOCKER). Also do NOT
30
+ stamp `links.design` on such a card: `links.design` goes ONLY on cards whose
31
+ scope implements mocked regions (`component_bindings` present or
32
+ `files_likely_touched` intersecting the mocked components); on anything else it
33
+ is a stray pointer that clamps the build to ui-expert downstream (`/new`
34
+ mockup-first router) — the FEAT-0068 docs card cost 6.55M for exactly this.
35
+ This separates HETEROGENEOUS domains; it does not contradict the v5.4.0
36
+ proportionality floor (which discourages splitting a small HOMOGENEOUS change).
37
+
25
38
  ### Rule B — UI cards have UI-only scope (no mixed scope)
26
39
 
27
40
  A card with `owner_agent: ui-expert` MUST be scoped EXCLUSIVELY to graphical
@@ -263,6 +276,13 @@ The `prd-card-writer` agent owns the entire card writing pipeline:
263
276
  - State file update with card list and matrices
264
277
  - `env_vars` field: for every card that introduces/modifies/removes env vars (detectable from PRD Section 6 or requirements that mention `process.env`, secrets, API keys, feature flags), populate the field with `action: new|modified|removed`, `scope`, `required`, `note`. If the card does not touch env vars, write `env_vars: []`.
265
278
  - `review_profile` field: deterministic per-card review depth (`skip|light|balanced|deep`). The decision criteria (how each profile is chosen) live ONLY in `prd-card-writer.md § Rule C` — see that file for the criteria. The `/new` orchestrator reads this value from the card and runs an escalation-only detector; it does NOT re-derive from a duplicate criteria table. Epics always get `review_profile: skip`. Honor any explicit author override already present in the YAML.
279
+ - **Self-validation BEFORE returning (v5.6.0 — reviewer-owns-its-domain, FEAT-0068 N6):** the
280
+ card-writer brief MUST require the agent to RUN the deterministic validator on its own output
281
+ (`node .framework/framework/scripts/validate-card-baseline.js --prd <card files>`) and return
282
+ only on exit 0, fixing its own deterministic defects (enums, EARS token language, forbidden
283
+ patterns) in-context. Step 6 re-runs the same validator as the independent gate — but a
284
+ deterministic failure discovered only at Step 6 costs a full orchestrator→agent round-trip
285
+ (~1.5M + a resume on the real session, where all 6 children bounced on Italian EARS tokens).
266
286
 
267
287
  ### What stays in the main context
268
288
 
@@ -1,5 +1,21 @@
1
1
  # Discovery Phase (Steps 0-2)
2
2
 
3
+ > **§0 — LOAD CONTRACT (v5.6.0 — read this first; it exists because of a real truncation).**
4
+ > This module is LARGER than the Read tool's default token cap. A plain `Read` returns a
5
+ > **PARTIAL view** (the banner says so) and silently drops the TAIL — which contains the
6
+ > **Exit condition**, the **mandatory Codex Discovery Completeness Cross-Check**, the
7
+ > **Research Trigger**, and the `mockup_analysis` schema. On the FEAT-0068 session exactly
8
+ > that happened: lines 953+ were never loaded, the cross-check never ran, and the coverage
9
+ > blind spot it exists to catch (integration owners no dimension modelled) shipped into the
10
+ > cards. HARD RULE: **if your Read of this file reports a partial view, you MUST issue
11
+ > follow-up Read calls with `offset` until you have seen the end of the file — BEFORE
12
+ > closing any discovery dimension.** Record `module_read: discovery-phase.md (full, N reads)`
13
+ > in the state file's phase section (the Step 6 validator checks the stamp). The
14
+ > tail-critical gates, so you know what you are looking for: (1) Exit condition — all
15
+ > dimensions covered + user validation; (2) Codex Discovery Completeness Cross-Check —
16
+ > MANDATORY sweep for the questioner's own blind spots before closing; (3) Research
17
+ > Trigger — background launch at 6+ dimensions; (4) `mockup_analysis` schema.
18
+
3
19
  ## Step 0 — Context Recovery
4
20
 
5
21
  Run BEFORE any other step.
@@ -815,6 +831,25 @@ Instead, run the ISA scan and present findings for validation.
815
831
  the picker-mode call, while the live catalog-mode consumer page was never
816
832
  enumerated → it surfaced as a HIGH only at the final review.) Grep the function
817
833
  name across the codebase and list each distinct caller file:line.
834
+ - UI ROLE FAMILY — registry-first surface OWNERSHIP (v5.6.0; only when
835
+ features.has_design_system is true AND the feature's recipe targets a chrome/
836
+ primitive ROLE: "the header/top edge of every screen", bottom bars, anchored
837
+ overlays/toasts, page shells). Every other category above enumerates EXISTING
838
+ code that references the feature's mechanism — but a component that LACKS the
839
+ mechanism is structurally invisible to that grep. This category enumerates the
840
+ OWNERS of the goal surface instead: read the design-system registry
841
+ (${paths.design_system}/INDEX.md role families / Selection Policy +
842
+ components/<Name>.md) for the family that renders that role, list EVERY member
843
+ as its OWN touchpoint (with its consumer count: `grep -rl <Component> | wc -l`),
844
+ and mark each HIGH (the goal is invisible wherever an unlisted member renders).
845
+ **@deprecated flag (BLOCKING):** if a family member the recipe anchors on carries
846
+ a `@deprecated` docblock, the touchpoint MUST name the documented successors and
847
+ the recipe MUST target them — anchoring a surface-wide goal on a deprecated
848
+ member is a scope error, not a style choice. (FEAT-0068: the ISA enumerated the
849
+ 44 existing consumers of env(safe-area-*) and anchored "the header" on a
850
+ @deprecated Header.tsx serving 5 pages, while the successors DrilldownHeader/
851
+ SectionHeader — 63 files, ~90% of screens — appeared in NO card; the coverage
852
+ gate then passed 44/44 vacuously against the wrong inventory.)
818
853
 
819
854
  For each touchpoint found, report:
820
855
  - Category (from above)
@@ -114,6 +114,34 @@ dimension from the discovery checklist. Pick exactly one branch:
114
114
  | `mockups.status: none` AND `mockups.source: internal` | **Full** | Run the standard pipeline 3a → 3b → 3c → 3d → 3e as below. `step_3_mode: full`. |
115
115
  | `mockups.status` ∈ {`provided`, `partial`} AND UI impact ≠ N/A | **Hybrid** | Per-screen routing (see § Hybrid mode below). `step_3_mode: hybrid` (or `mockup-only` if every screen is covered AND no `mockup_analysis.design_system_alignment.violations` — distinct from `skipped`, which means no UI at all). |
116
116
 
117
+ **`step_3_mode` is a CLOSED ENUM (v5.6.0): `full | hybrid | mockup-only | skipped |
118
+ pending_external_handoff`.** Writing any other value is a protocol violation the Step 6
119
+ validator now rejects deterministically. The FEAT-0068 session invented `design-spec` when the
120
+ user declined mockups on a UI feature — an unscoped gap the model filled by fabrication — and
121
+ the hand-authored inline "visual explainer" it produced became `links.design` on 5/6 cards,
122
+ routing a docs card to ui-expert downstream. The rules that close that gap:
123
+ - **`skipped` means NO design artifact.** No inline design.html, no "visual spec" Write, and
124
+ `links.design` stays EMPTY on every card. Any visual explainer the user asks for goes through
125
+ `Skill(ui-design)` (which runs its craft gates) — the orchestrator NEVER hand-authors design
126
+ HTML.
127
+ - **UI feature + user declines mockups is still `skipped`** (or Full if the user accepts
128
+ internal generation) — there is no third "spec-only" lane. What the cards need instead is
129
+ § Reconciliation-lite below.
130
+ - **Reconciliation-lite (v5.6.0 — "no mockup" must NOT mean "no reconciliation").** When
131
+ `step_3_mode: skipped` (or `mockup-only`) AND the feature touches design-system primitives
132
+ (`features.has_design_system: true`), STILL run the registry half of Component
133
+ Reconciliation: resolve the affected ROLE FAMILIES from `${paths.design_system}/INDEX.md`
134
+ (Selection Policy + role families — same lens as the ISA "UI ROLE FAMILY" category, which by
135
+ now has enumerated the owners), and emit `component_bindings` for the cards from the registry
136
+ alone. The FEAT-0068 chain — mockups skipped → reconciliation never ran → the registry that
137
+ named DrilldownHeader/SectionHeader as the canonical headers was never consulted → the recipe
138
+ anchored on a @deprecated component — is exactly what this closes.
139
+ - **Re-enumeration trigger (v5.6.0).** If a design/recipe decision taken IN THIS PHASE changes
140
+ WHAT the feature applies to (a different component family, a broader/narrower surface than
141
+ discovery assumed), the ISA surface inventory is STALE: re-run the affected ISA category
142
+ (Dimension 9 — at minimum UI ROLE FAMILY) before PRD writing. Locking a recipe after the scan
143
+ without re-enumerating is how a correct inventory goes wrong silently.
144
+
117
145
  Mark task 2 as `in_progress` for the Full and Hybrid branches.
118
146
 
119
147
  ## Delegation to `ui-design` Skill
@@ -52,6 +52,19 @@ Mark task 5 as `in_progress`.
52
52
  surface / ISA file owned by NO card is a BLOCKER (this is the gap that otherwise surfaces only
53
53
  at `/new`'s expensive final review). Message: `"ISA touchpoint <path> (<category>) is owned by
54
54
  no card — assign it to a card's files_likely_touched."`
55
+ - **Universal-quantifier epic AC gate (v5.6.0 — FEAT-0068):** for every EPIC acceptance
56
+ criterion carrying a universal quantifier over a UI/route surface ("ogni schermata",
57
+ "tutte le route", "every screen", "all pages", "nessun <difetto> su <superficie>"),
58
+ derive the surface's OWNER components from the **fresh registry/ISA census** (the
59
+ UI ROLE FAMILY touchpoints of discovery Dimension 9 — NOT the raw mechanism-consumer
60
+ touchpoints, or you inherit an incomplete inventory) and verify each owner appears in
61
+ the union of the child cards' `files_likely_touched`/scope. An owner covered by NO
62
+ child is a BLOCKER: `"Epic AC-<n> quantifies over <surface> but owner <component>
63
+ (<N> files) belongs to no card."` Persist the resolved owner list as
64
+ `invariant_owners:` in the epic YAML so the `/new` epic-closure gate can re-verify
65
+ it. (FEAT-0068: the epic promised "no seam on every screen" while DrilldownHeader/
66
+ SectionHeader — ~90% of screens — belonged to no card; the ISA→card gate passed
67
+ 44/44 vacuously because the inventory itself was wrong.)
55
68
  Both are SEMANTIC (path extraction from prose / ISA needs interpretation) — bias toward flagging.
56
69
 
57
70
  **Gate**: the 0-i validator exits 0 on every card (enums, conditional `requirements`, zero
@@ -59,6 +72,22 @@ Mark task 5 as `in_progress`.
59
72
  checks (b)/(c) are noted in the audit log; user may accept them after review. The 0-i and (e)
60
73
  BLOCKERs must be fixed before commit.
61
74
 
75
+ 0-ii. **Phase-evidence audit (v5.6.0 — executed, not recited; FEAT-0068 shipped TWO phantom
76
+ gates).** Deterministic checks on the STATE FILE before the audit protocol runs:
77
+ - **`module_read` stamps**: each executed phase section must carry its `module_read:
78
+ <reference file> (full)` stamp (SKILL.md § phase-module loading). A phase that ran with
79
+ its module unread is a protocol violation to surface — on FEAT-0068, `research-phase.md`,
80
+ `prd-writing-phase.md` and `backlog-phase.md` were never read and the improvised Step 5
81
+ contract produced the EARS rework round.
82
+ - **Gate stamps carry evidence**: any gate recorded as run/passed/`N/A` (API Performance
83
+ Gate, holistic audit, Codex Discovery Cross-Check) must name its evidence — an agent
84
+ spawn/report path for agent gates, the concrete reason for an `N/A`. A gate stamp with no
85
+ evidence is treated as NOT RUN (the FEAT-0068 session stamped `pass # N/A` on the API
86
+ gate without ever spawning the auditor, and the holistic stamp landed with zero audit
87
+ spawns).
88
+ - **`step_3_mode` ∈ {full, hybrid, mockup-only, skipped, pending_external_handoff}**: any
89
+ other value (the session fabricated `design-spec`) is a BLOCKER — fix the state file and
90
+ re-run the branch it should have taken.
62
91
  1. **Field Name Audit (runs after item 0 — only when item 0 passes for a given card; skipped for cards blocked in item 0)** — for each generated card:
63
92
 
64
93
  a. Verify every `data_fields` entry has `ts_verified: true` OR `status: new` with `schema_ref`.
@@ -142,9 +171,15 @@ created by Step 1 (HARD RULE 17). `$WORKTREE_PATH` is set in the state file.
142
171
  HOLISTIC_AUDITED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
143
172
  HOLISTIC_AUDITED_COMMIT="$(git -C "$WORKTREE_PATH" merge-base HEAD "${git.trunk_branch}" 2>/dev/null || git -C "$WORKTREE_PATH" rev-parse "${git.trunk_branch}" 2>/dev/null || echo "")"
144
173
  # --set = the sorted Step-5 child card IDs (the joint cross-card scope), comma-separated.
174
+ # --audit-report (v5.6.0, REQUIRED for a full stamp) = the audit-phase report artifact
175
+ # (e.g. /tmp/prd-audit-<slug>.md, written by audit-phase Step 6.9 with its `agents_run:`
176
+ # line). NO artifact on disk = the audit team never ran (the FEAT-0068 phantom stamp) →
177
+ # run WITHOUT the flag and the script writes `status: skipped` + NO agents_run, which
178
+ # /new's P1 treats as ABSENT (plan-auditor runs — fail-safe, exactly right).
145
179
  node .framework/framework/scripts/stamp-holistic-audit.js \
146
180
  --at "$HOLISTIC_AUDITED_AT" --commit "$HOLISTIC_AUDITED_COMMIT" \
147
- --set "<ID1,ID2,...>" "$WORKTREE_PATH/${paths.backlog_dir}"/FEAT-XXXX-*.yml
181
+ --set "<ID1,ID2,...>" --audit-report "/tmp/prd-audit-<slug>.md" \
182
+ "$WORKTREE_PATH/${paths.backlog_dir}"/FEAT-XXXX-*.yml
148
183
  ```
149
184
  The script is **idempotent** (a card already stamped by Step 6.9.4 is untouched),
150
185
  **additive** (never overwrites other `metadata` keys), skips EPIC cards (they carry
@@ -223,6 +258,15 @@ created by Step 1 (HARD RULE 17). `$WORKTREE_PATH` is set in the state file.
223
258
  Input: { "worktreePath": "$WORKTREE_PATH" }
224
259
  ```
225
260
 
261
+ **HARD RULE (v5.6.0 — FEAT-0068 N1): `mw-docs`, NEVER generic `/mw`, for a docs worktree.**
262
+ The registry entry for this worktree says `kind: "docs"` — a generic `/mw` on it runs the
263
+ forbidden unbounded `npm run build` (a docs worktree has no node_modules → guaranteed false
264
+ BUILD_FAIL, manual recovery, classifier-blocked push; ~4M wasted on the real session). If
265
+ you find yourself about to call `/mw`, or to invent invocation args (`checksAlreadyPassed`
266
+ is NOT an input of this contract), STOP — the invocation above is the whole contract.
267
+ `/mw` itself refuses a `kind: "docs"` worktree since v5.6.0 (worktree-manager pre-flight),
268
+ but do not rely on the belt: use the right mode.
269
+
226
270
  The skill executes:
227
271
  - Safety commit (idempotent — likely no-op after step 8; if any file was
228
272
  missed by item 6's explicit list, the safety commit picks it up, but the
@@ -2,6 +2,19 @@
2
2
 
3
3
  Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
4
4
 
5
+ ## 1.2.0 — 2026-07-04 (FEAT-0068 post-mortem)
6
+
7
+ - **`merge-worktree.sh --safety-sweep <all|allowlist:globs>`**: in modalità allowlist il
8
+ safety commit pre-rebase stagia SOLO i file che matchano (bookkeeping del batch), con
9
+ messaggio onesto che li enumera; le modifiche TRACKED fuori allowlist vengono messe in
10
+ quarantena byte-per-byte (`quarantined:` nel manifest) e ripristinate a HEAD, gli
11
+ untracked restano su disco (`uncommitted_left:`). Default `all` invariato per `/mw`
12
+ interattivo. Chiude lo split-brain col F-030 del chiamante ("[safety] Auto-commit" da
13
+ 751 righe opaco su develop, ricorrente FEAT-0067/FEAT-0068).
14
+ - **Guardia docs-worktree in `/mw`** (BLOCKING, step 1): registry `kind: "docs"` ⇒ rifiuto
15
+ con puntatore a `mw-docs` (un `/mw` generico su un docs worktree = build unbounded senza
16
+ node_modules ⇒ BUILD_FAIL falso garantito, ~4M su un run `/prd` reale).
17
+
5
18
  ## 1.1.0 — 2026-07-03
6
19
 
7
20
  ### Fixed — local-trunk sync robustness (step 4c "Common", both strategies)
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: worktree-manager
3
3
  effort: medium
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  description: >
6
6
  Manage fully independent git worktrees for parallel coding agents.
7
7
  Commands: /nw (new worktree) creates an isolated workspace with its own
@@ -685,6 +685,16 @@ Supports two modes:
685
685
 
686
686
  Read `.worktrees/registry.json`. If multiple entries exist or user didn't specify, list them and ask which to merge.
687
687
 
688
+ **Docs-worktree guard (v5.6.0 — BLOCKING, before anything else).** If the resolved registry
689
+ entry carries `kind: "docs"`, this is the WRONG mode: REFUSE and route to `mw-docs`
690
+ (programmatic: `Mode: programmatic, mw-docs`). A generic `/mw` on a docs worktree runs the
691
+ build/check pipeline against a tree with no node_modules → a guaranteed false BUILD_FAIL,
692
+ manual recovery, and a blocked push (observed on a real `/prd` session: ~4M tokens + a human
693
+ unblock). Message: `"WRONG MODE: worktree '<slug>' is kind:docs — use mw-docs (docs merge:
694
+ no build, additive-registry resolution). Refusing generic /mw."` Also ignore any invented
695
+ invocation args (`checksAlreadyPassed` is a `/new`-orchestrator flag, not a user contract) —
696
+ the registry entry is the SSOT for what kind of merge this is.
697
+
688
698
  Fallback: `git worktree list` if registry is missing.
689
699
 
690
700
  Determine, reading them from the worktree's registry entry (R6):