baldart 5.5.0 → 5.7.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 (65) hide show
  1. package/CHANGELOG.md +119 -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/capture/CHANGELOG.md +4 -0
  6. package/framework/.claude/skills/capture/SKILL.md +2 -1
  7. package/framework/.claude/skills/design-sync/CHANGELOG.md +4 -0
  8. package/framework/.claude/skills/design-sync/SKILL.md +2 -1
  9. package/framework/.claude/skills/ds-edit/CHANGELOG.md +5 -0
  10. package/framework/.claude/skills/ds-edit/SKILL.md +9 -10
  11. package/framework/.claude/skills/ds-handoff/CHANGELOG.md +5 -0
  12. package/framework/.claude/skills/ds-handoff/SKILL.md +3 -2
  13. package/framework/.claude/skills/ds-new/CHANGELOG.md +4 -0
  14. package/framework/.claude/skills/ds-new/SKILL.md +2 -1
  15. package/framework/.claude/skills/ds-render/CHANGELOG.md +4 -0
  16. package/framework/.claude/skills/ds-render/SKILL.md +2 -1
  17. package/framework/.claude/skills/e2e-review/CHANGELOG.md +4 -0
  18. package/framework/.claude/skills/e2e-review/SKILL.md +2 -1
  19. package/framework/.claude/skills/gamification-design/CHANGELOG.md +4 -0
  20. package/framework/.claude/skills/gamification-design/SKILL.md +2 -1
  21. package/framework/.claude/skills/graph-align/CHANGELOG.md +4 -0
  22. package/framework/.claude/skills/graph-align/SKILL.md +2 -1
  23. package/framework/.claude/skills/i18n/CHANGELOG.md +4 -0
  24. package/framework/.claude/skills/i18n/SKILL.md +2 -1
  25. package/framework/.claude/skills/motion-design/CHANGELOG.md +4 -0
  26. package/framework/.claude/skills/motion-design/SKILL.md +2 -1
  27. package/framework/.claude/skills/new/CHANGELOG.md +27 -0
  28. package/framework/.claude/skills/new/SKILL.md +2 -1
  29. package/framework/.claude/skills/new/references/commit.md +12 -8
  30. package/framework/.claude/skills/new/references/completeness.md +10 -0
  31. package/framework/.claude/skills/new/references/final-review.md +23 -0
  32. package/framework/.claude/skills/new/references/implement.md +14 -4
  33. package/framework/.claude/skills/new/references/merge-cleanup.md +35 -14
  34. package/framework/.claude/skills/new2/CHANGELOG.md +40 -0
  35. package/framework/.claude/skills/new2/SKILL.md +53 -12
  36. package/framework/.claude/skills/prd/CHANGELOG.md +40 -0
  37. package/framework/.claude/skills/prd/SKILL.md +18 -5
  38. package/framework/.claude/skills/prd/assets/state-template.md +8 -1
  39. package/framework/.claude/skills/prd/references/audit-phase.md +13 -1
  40. package/framework/.claude/skills/prd/references/backlog-phase.md +20 -0
  41. package/framework/.claude/skills/prd/references/discovery-phase.md +35 -0
  42. package/framework/.claude/skills/prd/references/ui-design-phase.md +28 -0
  43. package/framework/.claude/skills/prd/references/validation-phase.md +45 -1
  44. package/framework/.claude/skills/prd-add/CHANGELOG.md +4 -0
  45. package/framework/.claude/skills/prd-add/SKILL.md +2 -1
  46. package/framework/.claude/skills/skill-creator/references/skill-structure.md +31 -2
  47. package/framework/.claude/skills/skill-creator/scripts/quick_validate.py +25 -3
  48. package/framework/.claude/skills/ui-design/CHANGELOG.md +4 -0
  49. package/framework/.claude/skills/ui-design/SKILL.md +2 -1
  50. package/framework/.claude/skills/ui-implement/CHANGELOG.md +4 -0
  51. package/framework/.claude/skills/ui-implement/SKILL.md +2 -1
  52. package/framework/.claude/skills/worktree-manager/CHANGELOG.md +13 -0
  53. package/framework/.claude/skills/worktree-manager/SKILL.md +11 -1
  54. package/framework/.claude/skills/worktree-manager/scripts/merge-worktree.sh +82 -6
  55. package/framework/.claude/workflows/new-final-review.js +9 -7
  56. package/framework/.claude/workflows/new2-resolve.js +29 -1
  57. package/framework/.claude/workflows/new2.js +158 -18
  58. package/framework/agents/card-schema.md +18 -1
  59. package/framework/agents/research-protocol.md +6 -1
  60. package/framework/scripts/stamp-holistic-audit.js +53 -10
  61. package/package.json +1 -1
  62. package/src/commands/configure.js +9 -2
  63. package/src/commands/doctor.js +65 -0
  64. package/src/utils/skill-gate.js +139 -0
  65. package/src/utils/symlinks.js +72 -7
@@ -334,6 +334,16 @@ that is a **gate violation**: log it as
334
334
  - **Each domain specialist OWNS its lane end-to-end** — it runs its OWN false-positive check in the finding pass (doc-reviewer for doc, api-perf-cost-auditor for api/perf/data, and the Codex/`code-reviewer`-fallback engine for code), so its surviving findings are **already validated**. Do **NOT** cross-validate a doc or api finding by spawning `code-reviewer` (that is the WRONG specialist judging another domain), and do **NOT** re-run the same specialist over its own findings (self-judge — no model diversity). Codex findings are likewise already FP-validated (Step F.3 protocol includes it).
335
335
  - **Residual only:** a finding the originating specialist explicitly leaves UNRESOLVED (`confidence < 80`) is routed to the finding's **domain specialist** (by `domain`: doc→doc-reviewer, api/perf→api-perf-cost-auditor, security/migration→security-reviewer, test→qa-sentinel, else code-reviewer) over the cited file:line. If that domain specialist **is** the originating finder (it already had its pass), classify `NEEDS_MANUAL_CONFIRMATION` instead of re-spawning it — never self-judge, never silently drop.
336
336
  - Classify: `VERIFIED` | `FALSE_POSITIVE` | `NEEDS_MANUAL_CONFIRMATION`.
337
+ - **Closure-invalidating findings (v5.6.0 — FEAT-0068 post-mortem).** A VERIFIED finding (any
338
+ severity) asserting that an **epic goal or epic AC is NOT met** while state says otherwise —
339
+ overclaim in the SSOT/registry, "DONE but unmet", "goal not achieved" — is a **STATE defect,
340
+ not a prose defect**. Tag it `closure_invalidating: true`. Its fix has TWO mandatory parts:
341
+ (1) the text correction (the doc fixer's job as usual), AND (2) the **state reversal** — the
342
+ named epic must NOT be closed in Phase 6b, or, if already `DONE` on disk, must be REOPENED to
343
+ `IN_PROGRESS` in the same repair commit (`merge-cleanup.md` 5e step a). Accepting the text
344
+ fix alone as resolution merges a registry that says "goal not achieved" alongside an epic
345
+ YAML that says DONE — the exact FEAT-0068 contradiction. The batch verdict becomes PARTIAL
346
+ (§ Report verdict below) whenever one of these stands.
337
347
  - `VERIFIED` findings proceed to fixes — **EXCEPT no-action ones** (`requires_action:false`, or a "no fix required" / "acceptable as-is" / "verified non-issue" direction; MEDIUM/LOW only). A no-action finding is TRUE but needs no change: record it (`decision=skipped | reason=no-action`) and do NOT route it to a writer. (The delegated `new-final-review` workflow returns these separately as `noActionFindings` + `summary.noAction`; the inline path classifies them here.) **`NEEDS_MANUAL_CONFIRMATION` findings are NOT discarded** — list them in `## Issues & Flags` and surface them to the user via `AskUserQuestion` (treat as VERIFIED, treat as FALSE_POSITIVE, or hand off) before merge. **When AUTONOMOUS, apply § "AUTONOMOUS RESOLUTION RULE" (SKILL.md): category=blocker; recommended=treat NEEDS_MANUAL_CONFIRMATION as VERIFIED (never as a false positive), else materialize a follow-up card.** Only `FALSE_POSITIVE` are dropped.
338
348
 
339
349
  ### Step F.5 — Apply fixes and final build
@@ -403,6 +413,19 @@ that is a **gate violation**: log it as
403
413
  4. Emit the **minimal end-of-batch result block** (per § "orchestrator is near-silent" in the core SKILL.md — this is NOT a per-phase report). ONE line per card and nothing more of the process telemetry:
404
414
  - `<CARD-ID>: merged @<sha> | failed: <one clause> | deferred → <followup-id>`
405
415
 
416
+ **Report verdict (v5.6.0 — HARD headline rule, FEAT-0068 post-mortem).** The FIRST line of the
417
+ result block is a verdict, and it is computed, not felt:
418
+ - `⚠️ PARTIAL — obiettivo epic NON raggiunto: <one clause naming the gap>` whenever ANY of:
419
+ a HIGH/BLOCKER residual or follow-up carrying substantive scope work exists; the parent epic
420
+ was left open (or reopened) by Phase 6b 5e; a closure-invalidating finding stands; any epic
421
+ AC is still `[ ]`. Name the gap and its follow-up card in the first three lines.
422
+ - `✅ COMPLETO` is RESERVED for: every card merged, no HIGH+ residual, epic (when present)
423
+ closed with ACs verified.
424
+ A run that ships 6/6 cards but leaves the epic goal on 10% of its surface is PARTIAL — the
425
+ FEAT-0068 report headlined "✅ batch completo" over a disclosed-but-buried HIGH gap, and the
426
+ user discovered it only by asking. "Nulla perso" (tracking) is never a substitute for "non
427
+ finito" (truth): a follow-up that holds the epic's remaining work is REMAINING WORK.
428
+
406
429
  Then, **only if non-empty**, the **actionable residue**: issues needing user attention (anything unresolved, partially wired, or flagged — terse, with `path:line` / `CARD-ID` exact). All process telemetry — files changed, test/build/lint status, fix cycles, review-finding counts, UX/QA verdicts, commit + merge hashes, card-status reconciliation, worktree cleanup, knowledge-corpus sync — is **NOT rendered**: it lives in the tracker and `$METRICS/skill-runs.jsonl`. (The Next Steps & Launch Command in 4b below and any Production Readiness manual steps ARE part of the actionable residue — keep them.)
407
430
 
408
431
  4b. **Next Steps & Launch Command** (MANDATORY section — always present):
@@ -11,10 +11,10 @@
11
11
  2b. **Claim** — only now set the card status to `IN_PROGRESS` (in the backlog YAML / tracker) and assign yourself. This is a state write, not a visibility emission — do not also spend a TaskUpdate / Progress-Bar turn (§ "State surface — the tracker only").
12
12
  2c. **Trivial-card classification (BLOCKING gate for steps 3–4)** — evaluate `IS_TRIVIAL(card)` per § "Trivial-card fast-lane". Note: condition 3 (non-source diff) cannot be fully evaluated until the coder has produced the diff, so at this point compute the **provisional** trivial flag from conditions 1+2 only (`review_profile == skip` AND no Step-A trigger sourced from the card YAML text + `files_likely_touched` extensions — if EVERY path in `files_likely_touched` is non-source, condition 3 is provisionally satisfied). If provisionally trivial → **SKIP steps 3, 3a, and 4** (architecture grounding); log `trivial: architecture grounding skipped (review_profile=skip + non-source files_likely_touched + 0 triggers)` and jump to Phase 2. Re-confirm `IS_TRIVIAL` on the ACTUAL committed diff at the review gates (Phase 2.55/3.5/3.7); if the coder unexpectedly touched a source file, the guard flips the card back onto the normal review path there. If NOT provisionally trivial → run steps 3, 3a, 4 as normal.
13
13
  2d. **Light-lane inline grounding (since v5.4.0 — BLOCKING gate for steps 3–4, after 2c)** — when the card is NOT provisionally trivial AND `review_profile == light`: **SKIP step 3 (the dedicated codebase-architect spawn) and step 4** — the OWNER agent grounds INLINE instead, per **AGENTS.md § Change Tiers, orchestrated-pipeline exception** (a light card is ≤3 files with no logic-risk signal by Rule C; a dedicated retriever at that scale costs more than the exploration it isolates). The understanding obligation is UNCHANGED — only the delegation is waived: the owner briefing (step 6/7) MUST carry the line "Ground INLINE before coding: read the files in scope + their immediate integration points; scoped exploration only". Step 3a still runs (write Active Code Context from the card YAML, noting `grounding: inline-light`). Log `phase1: INLINE-LIGHT (review_profile=light — no retriever spawn, owner grounds inline)`. `balanced`/`deep` cards run steps 3, 3a, 4 as written — this lane never applies to them.
14
- 3. **(skip when provisionally trivial — see 2c — or on the light lane — see 2d)** Invoke the **codebase-architect** agent (MUST per AGENTS.md) to understand the relevant codebase area, existing patterns, and architecture before any implementation. When `features.has_lsp_layer: true`, the architect uses LSP find-references for identifier-shaped lookups — this needs NO handoff from the orchestrator: the architect reads `features.has_lsp_layer` from `baldart.config.yml` directly (the flag is ambient) per `agents/code-search-protocol.md`. Likewise, when `features.has_code_graph: true`, the architect uses the Graphify code graph for structural/relational lookups (ambient flag) per `agents/code-graph-protocol.md`. The orchestrator does NOT propagate either flag. (Earlier doc versions numbered this step 4; the step that read project-status BEFORE the architect was removed because it persisted pre-analysis context — see step 3a.) **Pass `OUTPUT=terse` in the architect prompt (since v4.49.0)** — this is grounding for the coder/reviewer, not an explanation, so the architect returns its structured contract (reuse table + canonical evidence + `path:line — symbol` rows + `totals:`) without narrative prose. **Pass the analysis profile too (since v4.94.0)**: `PROFILE=ui` when the card has a non-empty `links.design` OR `links.design_src` (the same mockup bit that drives step 6a), else `PROFILE=feature` — contract and per-profile scoping in `agents/analysis-profiles.md` (its § 3 caller routing table is normative). The profile is deterministic from the card YAML; never leave the architect to infer it. The verbatim baseline persisted at step 5b keeps all the substance a lean `/codexreview` needs (paths, signatures, patterns, high-risk paths) while staying small in the orchestrator's context and on disk. **Baseline content contract (MANDATORY — since v4.56.0):** the architect prompt is grounding INPUT only — pass the card scope, `files_likely_touched`, and the question to map. NEVER put line-level fix directives ("remove lines 90-91", "Fix: use X"), the words "implement/fix/apply", or acceptance-criteria framed as a task into the architect prompt. The architect produces a read-only MAP (file/symbol locations, patterns, type signatures, integration points, high-risk paths); it does NOT implement and has no `Task`/Agent tool to delegate (see `codebase-architect.md` § Role boundary). The coder is a separate spawn the orchestrator owns.
14
+ 3. **(skip when provisionally trivial — see 2c — or on the light lane — see 2d)** Invoke the **codebase-architect** agent (MUST per AGENTS.md) to understand the relevant codebase area, existing patterns, and architecture before any implementation. When `features.has_lsp_layer: true`, the architect uses LSP find-references for identifier-shaped lookups — this needs NO handoff from the orchestrator: the architect reads `features.has_lsp_layer` from `baldart.config.yml` directly (the flag is ambient) per `agents/code-search-protocol.md`. Likewise, when `features.has_code_graph: true`, the architect uses the Graphify code graph for structural/relational lookups (ambient flag) per `agents/code-graph-protocol.md`. The orchestrator does NOT propagate either flag. (Earlier doc versions numbered this step 4; the step that read project-status BEFORE the architect was removed because it persisted pre-analysis context — see step 3a.) **Pass `OUTPUT=terse` in the architect prompt (since v4.49.0)** — this is grounding for the coder/reviewer, not an explanation, so the architect returns its structured contract (reuse table + canonical evidence + `path:line — symbol` rows + `totals:`) without narrative prose. **Pass the analysis profile too (since v4.94.0)**: `PROFILE=ui` when the card's `HAS_MOCKUP` bit is true (the same semantic mockup test that drives step 6a — v5.6.0: a bare `links.design` pointer on a docs/meta card does NOT make it a UI card), else `PROFILE=feature` — contract and per-profile scoping in `agents/analysis-profiles.md` (its § 3 caller routing table is normative). The profile is deterministic from the card YAML; never leave the architect to infer it. The verbatim baseline persisted at step 5b keeps all the substance a lean `/codexreview` needs (paths, signatures, patterns, high-risk paths) while staying small in the orchestrator's context and on disk. **Baseline content contract (MANDATORY — since v4.56.0):** the architect prompt is grounding INPUT only — pass the card scope, `files_likely_touched`, and the question to map. NEVER put line-level fix directives ("remove lines 90-91", "Fix: use X"), the words "implement/fix/apply", or acceptance-criteria framed as a task into the architect prompt. The architect produces a read-only MAP (file/symbol locations, patterns, type signatures, integration points, high-risk paths); it does NOT implement and has no `Task`/Agent tool to delegate (see `codebase-architect.md` § Role boundary). The coder is a separate spawn the orchestrator owns.
15
15
  3a. Update `${paths.references_dir}/project-status.md` Active Code Context (skip when the file does not exist in the project) — do this AFTER the codebase-architect run (step 3) so the "Active Code Context" reflects the architect's findings (which files are actually in scope), not just the card YAML's `files_likely_touched`. Writing it before the architect run would persist pre-analysis claims that downstream agents (e.g. a parallel card) would then read as truth.
16
16
  4. **Plan-auditor grounding check** — but first, a **provenance skip (since v4.7.0 — mirror of Step 3d)**: the `/prd` Step 6.6 holistic audit already ran a per-card grounding pass when the card was authored. Re-grounding here is only worth a plan-auditor spawn if something changed since. **This skip is the NORMAL path for a card implemented right after `/prd`, not an occasional optimization** — `/prd` now guarantees the `metadata.holistic_audit` stamp lands on every audited card (deterministic backstop at `validation-phase.md` Step 7 item 5b, since the v4.88.2 provenance-reliability fix), so P1 below holds whenever the batch is freshly authored. Skip the plan-auditor when **BOTH** hold:
17
- - **P1 — provenance present**: the card has `metadata.holistic_audit` with non-empty `audited_at`, `audited_commit`, `audited_set`.
17
+ - **P1 — provenance present AND evidence-backed (v5.6.0)**: the card has `metadata.holistic_audit` with non-empty `audited_at`, `audited_commit`, `audited_set`, **and a non-empty `agents_run` list** (the v5.6.0 evidence field the stamper writes only when it received a real audit report). A stamp with `status: skipped` or WITHOUT `agents_run` is treated as **ABSENT** — the FEAT-0068 `/prd` session stamped all 6 cards while the Step 6.2–6.6 audit team never spawned (phantom stamp), and P1∧P2 would have suppressed the plan-auditor on a false premise. Pre-v5.6.0 stamps (no `agents_run` field at all) therefore fall through to RUN the plan-auditor — deliberate fail-safe, not a bug.
18
18
  - **P2 — no drift on this card's claimed paths** since the audit baseline. With `$AC` = `metadata.holistic_audit.audited_commit`, `$MAIN`/`$TRUNK` from the tracker, and this card's `files_likely_touched`/claimed paths (`$CARD_PATHS`):
19
19
  ```bash
20
20
  # empty AC, AC not in history, or any git error → treat as drift (do NOT skip)
@@ -57,7 +57,17 @@
57
57
  If card is an epic (id ends "-00" OR filename ends "-epic.yml" OR review_profile == "skip"
58
58
  with no requirements): SKIP — log "[ROUTER] card <ID> is an epic (tracker) — skipped,
59
59
  not implemented" and move to the next card.
60
- If card has links.design OR links.design_src (a mockup exists):
60
+ # v5.6.0 (FEAT-0068): "has a mockup" is SEMANTIC, not a bare-field test. The /prd epic
61
+ # explainer html stamped on 5/6 cards clamped a docs+ADR card to ui-expert (6.55M, the
62
+ # run's costliest agent) and put a meta-only card through the fidelity lane.
63
+ HAS_MOCKUP := links.design_src is non-empty
64
+ OR ( links.design is non-empty
65
+ AND ( component_bindings is non-empty
66
+ OR files_likely_touched intersects component/style/UI source paths ) )
67
+ # A bare links.design on a docs/test/meta-only card is a POINTER to the epic's design
68
+ # explainer, not a build target → route by owner_agent (step 6b). Log the demotion:
69
+ # "[ROUTER] card <ID> carries links.design but builds no mocked UI → owner_agent router".
70
+ If HAS_MOCKUP:
61
71
  IF the /ui-implement skill is available:
62
72
  DELEGATE this card's mockup→code implement + fidelity verify to /ui-implement
63
73
  in programmatic mode (contract: ui-implement/references/integration.md).
@@ -82,7 +92,7 @@
82
92
  ```
83
93
 
84
94
  `owner_agent` is still honored for **review/ownership semantics** (AC-closure ownership, `security-reviewer` relevance, the mixed-card review cluster) — it simply no longer decides the BUILD agent when a mockup is present.
85
- 6b. **Agent dispatch (router — cards WITHOUT a mockup only).** Reached only when step 6a did not fire (the card has no `links.design`/`links.design_src`). Read `owner_agent` from the card YAML and resolve the spawn target per the table in § Agent Routing above:
95
+ 6b. **Agent dispatch (router — cards WITHOUT a mockup only).** Reached only when step 6a did not fire (`HAS_MOCKUP` false no mockup, or a bare `links.design` pointer on a card that builds no mocked UI). Read `owner_agent` from the card YAML and resolve the spawn target per the table in § Agent Routing above:
86
96
 
87
97
  ```
88
98
  Let raw = card.owner_agent (string, may be missing).
@@ -93,24 +93,45 @@ The most common failure mode is leaving cards IN_PROGRESS after merge. This crea
93
93
 
94
94
  For each **distinct parent epic** referenced by the batch — the set of `group.parent`
95
95
  values across the batch cards, PLUS any card in the batch that is itself an epic
96
- (`group.is_epic: true`) — do:
97
- a. Read the epic parent card `${paths.backlog_dir}/<EPIC-ID>.yml`. If `status: DONE`
98
- already skip (idempotent).
99
- b. Check that **every** child is DONE (not just the batch's subset children
100
- implemented in earlier sessions count too):
96
+ (`group.is_epic: true`) — close ONLY when the FULL predicate (a)–(d) holds
97
+ (v5.6.0, FEAT-0068 post-mortem: the old children-count-only predicate closed an epic whose
98
+ goal was unmet on ~90% of screens — the count was true and the DoD was false):
99
+ a. Read the epic parent card `${paths.backlog_dir}/<EPIC-ID>.yml`.
100
+ - `status: DONE` already **and** the checks below still hold → skip (idempotent).
101
+ - `status: DONE` already **but** (b)/(c)/(d) now FAIL (an open follow-up child appeared, a
102
+ closure-invalidating finding stands) → **REOPEN** it: set `status: IN_PROGRESS`, annotate
103
+ `completed_date`, add note `"REOPENED — closed against open scope (v5.6.0 guard)"`, fold
104
+ into the reconciliation commit. The ratchet is two-way: a false DONE never survives a
105
+ reconciliation pass.
106
+ b. Check that **every** child is DONE (not just the batch's subset — children implemented in
107
+ earlier sessions count too, and **follow-up cards count as children**: a
108
+ `<card>-followup-*.yml` carrying `parent: <EPIC-ID>` is an OPEN child until implemented):
101
109
  ```bash
102
110
  # Lists children of <EPIC-ID> that are NOT yet DONE. Empty output ⇒ all DONE.
111
+ # No ^ anchor — the schema nests `parent:` indented under `group:` (the v4.99.0
112
+ # commit-time gate anchored it and was a silent no-op; do not re-introduce that).
103
113
  grep -l "parent: <EPIC-ID>" ${paths.backlog_dir}/*.yml | xargs grep -L "status: DONE"
104
114
  ```
105
- c. **Only if** that command prints nothing (all children DONE) force-update the epic
106
- parent: set `status: DONE`, add `completed_date: <today>`, add note
107
- `"Marked DONE by epic-closure gate (Phase 6b) all children DONE"`. Stage it and
108
- **fold into the SAME reconciliation commit** as step 5 (or, if step 5 didn't run
109
- because all children were already DONE, make a dedicated
110
- `[BATCH] Close epic <EPIC-ID> all children DONE` commit, honoring the same
111
- COMMIT_LOCK / doc-freshness precautions as step 5a–5d).
112
- d. **If any child is still open** leave the epic untouched: it is genuinely still in
113
- progress, and step-4b's "Card rimanenti nell'epic" table already reports the gap.
115
+ c. **No blocking open work attached to the epic**: scan the tracker's `## Issues & Flags` +
116
+ residual/follow-up ledger for this batch — any open `scope-expansion` / `unresolved` /
117
+ `ac-unmet` item on a child of this epic, or any **closure-invalidating** final-review
118
+ finding (`final-review.md` § Closure-invalidating findings) naming this epic's goal
119
+ leave the epic OPEN (a text fix to the overclaiming doc does NOT clear this).
120
+ d. **Epic ACs verified**: read the epic YAML's own `acceptance_criteria`. For each `[ ]`
121
+ item, verify it with concrete evidence — run its `ac_verification` oracle when present,
122
+ else a targeted check and flip to `[x]` ONLY with evidence recorded in the tracker. An
123
+ AC you cannot verify stays `[ ]` and the epic stays OPEN (report which AC and why).
124
+ Never close an epic whose own checklist still has `[ ]` items.
125
+ e. **Only if (b)+(c)+(d) all pass** → update the epic parent: set `status: DONE`, add
126
+ `completed_date: <today>`, add note `"Marked DONE by epic-closure gate (Phase 6b) —
127
+ children+follow-ups DONE, ACs verified"`. Stage it and **fold into the SAME reconciliation
128
+ commit** as step 5 (or, if step 5 didn't run because all children were already DONE, make a
129
+ dedicated `[BATCH] Close epic <EPIC-ID>` commit, honoring the same COMMIT_LOCK /
130
+ doc-freshness precautions as step 5a–5d).
131
+ f. **If any check fails** → leave the epic untouched (or REOPEN per step a) and report the
132
+ concrete reason: step-4b's "Card rimanenti nell'epic" table + the final report's epic-goal
133
+ line must show it — the batch verdict is **PARTIAL**, never ✅, while the epic is open
134
+ (`final-review.md` § Report verdict).
114
135
  6. **Update tracker** with reconciliation results:
115
136
  ```
116
137
  ## Phase 6b — Status Reconciliation
@@ -2,6 +2,46 @@
2
2
 
3
3
  Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
4
4
 
5
+ ## 1.8.1 — 2026-07-06
6
+
7
+ - **Feature-gate**: added `requires_feature: has_backlog` frontmatter — this skill is now linked into a consumer only when `features.has_backlog` is enabled (it already refused at runtime otherwise). Trims Codex's ~2% skill-description budget on projects without the feature. Install-time gate, portable across Claude + Codex.
8
+
9
+ ## 1.8.0 — 2026-07-04 (FEAT-0068 post-mortem: integrità dell'esito + igiene git)
10
+
11
+ - **`new2.js`**: step 4b (chiusura epic) RIMOSSO dal commit agent — la chiusura vive
12
+ SOLO nella merge phase 5e col predicato v5.6.0 (blocklist JS `closureBlockedEpics`
13
+ da residual/follow-up/finding closure-invalidating + figli/follow-up DONE + AC epic
14
+ verificati, `epicsLeftOpen` con motivi); **guardia post-merge** gemella di F-029
15
+ (`epic-closure-guard` VIOLATION + residual `false-epic-closure` HIGH → la skill
16
+ riapre); detection **closure-invalidating** sui finding della final review.
17
+ - **`buildReport`**: verdetto calcolato `⚠️ PARTIAL`/`✅ COMPLETO` come PRIMA sezione,
18
+ sezione `## Epic goal` per-epic, `severity` sui residui (`residualSeverity`),
19
+ "nulla perso" consentito solo senza HIGH.
20
+ - **Commit agent**: clausola WORKTREE ISOLATION estesa ai TOOL (Read/Edit/Write path
21
+ assoluti — il cwd HARD RULE v5.3.0 copriva solo Bash), path del card YAML del
22
+ worktree passato esplicito, sibling/epic READ-ONLY, evidenza porcelain
23
+ before/after sul main + **isolation-guard JS** (main sporcato = VIOLATION +
24
+ residual HIGH). Era: 79 turni/4.30M di detour + stash dangling.
25
+ - **Merge**: `merge-worktree.sh --safety-sweep allowlist:` (solo bookkeeping del
26
+ batch; codice non gated mai spazzato nel trunk — F-030 per costruzione); divieto
27
+ esplicito di `git stash` ovunque (ff-pull bloccato = leave+report).
28
+ - **`new2-resolve.js`**: esito **`refuted`** ratificato avversarialmente (premessa
29
+ falsa = zero edit — era: 4.73M per "fixare" un blocker falso disattivando la suite
30
+ visual-regression) + `terminalReason: verification-posture-change` (un fix che
31
+ skippa/flag-gata una verifica mandata da un AC è FORBIDDEN).
32
+ - **`new-final-review.js`**: relay Codex in **foreground `--wait`** (una sola Bash,
33
+ timeout 600000) — l'enforcement structured-output forzava un TIMEOUT a 83s/600s e
34
+ il processo moriva col relay → fallback freddo da 3.68M; reap dell'orfano scoped
35
+ al worktree su timeout reale.
36
+ - **Routing**: `hasMockup` semantico nel cardGraph (BUILDS the mocked UI) +
37
+ `parentEpic` per blocklist/report.
38
+ - **SKILL.md**: Step 2 predicato di chiusura completo + **ramo REOPEN** (ratchet
39
+ bidirezionale); Step 4 presenta il verdetto verbatim (mai ri-headline un PARTIAL);
40
+ **Step 4b audit igiene git** (commit non-card ispezionati con `git show --stat` —
41
+ mai attribuire provenienza senza check; stash del batch riconciliati, mai "non
42
+ miei"; residual `main-repo-contamination` ripristinati); pre-sha del trunk
43
+ registrato al kickoff.
44
+
5
45
  ## 1.7.0 — 2026-07-03 (FEAT-0067 post-mortem: migration mai deployata)
6
46
 
7
47
  - **Step 3.5 vocabulary aliases**: il Migration Gate ora riconosce, oltre a
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  name: new2
3
3
  effort: high
4
- version: 1.7.0
4
+ version: 1.8.1
5
+ requires_feature: has_backlog
5
6
  description: >
6
7
  Workflow-hosted batch engine for /new. Implements one or
7
8
  more backlog cards end-to-end by delegating the WHOLE batch to a background
@@ -202,7 +203,9 @@ Workflow({ name: 'new2', args: {
202
203
  ```
203
204
 
204
205
  Record the kickoff time (`ts`) before the call — Step 5 uses it to stamp the
205
- real wall-clock duration (the workflow cannot read a clock).
206
+ real wall-clock duration (the workflow cannot read a clock). Also record the
207
+ pre-batch trunk sha (`git -C $MAIN rev-parse ${trunk}`) — Step 5.4b audits every
208
+ non-card commit the batch introduced against it (v5.6.0).
206
209
 
207
210
  Capture `sessionId` the same way, in THIS skill's own context (not a subagent):
208
211
  `Bash(echo "${CLAUDE_CODE_SESSION_ID:-}")`. The workflow stamps it as
@@ -254,6 +257,10 @@ returns when the batch is done. It returns:
254
257
  step-1b HALT fields — the `/new` pre-flight back-fill (step 1b-ii) then normalizes its
255
258
  `review_profile`/`owner_agent` on first ingestion, so even the crisis stub self-heals. This
256
259
  main-repo, **disk-verified** write is the SSOT — nothing is dropped even on a non-merged batch.
260
+ **Exception (v5.6.0):** residuals of kind `false-epic-closure` and `main-repo-contamination` are
261
+ **reconciliation ACTIONS, not backlog work** — do NOT mint follow-up cards for them. The former
262
+ is handled by step 2's REOPEN branch; the latter by step 4b's hygiene audit (inspect + restore
263
+ the named main-repo paths).
257
264
  1b. **Migration Sync Tail (post-merge "branch B" — the interactive owner-gated deploy the
258
265
  autonomous batch could not run).** The workflow has returned and merged; you are the skill
259
266
  main loop, in `$MAIN`, typically on `$TRUNK` — exactly the precondition of the project's
@@ -310,11 +317,25 @@ returns when the batch is done. It returns:
310
317
  **Then re-run the epic-closure check for the cards just marked DONE.** The merge agent's
311
318
  epic-closure (Phase 6b step 5e) ran BEFORE this step, when the deferred cards were still
312
319
  NON-DONE — so an epic whose last open child was a deferred card is still TODO and nothing
313
- else will ever close it. For each distinct `group.parent` of the cards marked DONE here: if
314
- `grep -l "parent: <EPIC-ID>" ${paths.backlog_dir}/*.yml | xargs grep -L "status: DONE"`
315
- prints nothing, set the epic card `status: DONE` + `completed_date` + note
316
- `"epic-closure gate all children DONE (post-run, new2 skill)"`, folded into the SAME
317
- reconciliation commit. If any child is still open, leave the epic untouched.
320
+ else will ever close it. For each distinct `group.parent` of the cards marked DONE here,
321
+ close ONLY when the FULL v5.6.0 predicate holds (the same one the merge agent runs —
322
+ `merge-cleanup.md` § epic closure): (a) `grep -l "parent: <EPIC-ID>" ${paths.backlog_dir}/*.yml
323
+ | xargs grep -L "status: DONE"` prints nothing — **follow-up cards count as children** (step 1
324
+ just materialised them here in the main repo, so this grep now sees them); (b) no `residuals[]`
325
+ entry of a blocking class (`scope-expansion`/`unresolved`/`ac-unmet`/`out-of-ownership`) maps to
326
+ a child of this epic; (c) the epic YAML's own `acceptance_criteria` are all `[x]` — verify any
327
+ still-`[ ]` item with its `ac_verification` oracle (or a targeted check) and flip it ONLY with
328
+ evidence; an unverifiable AC leaves the epic OPEN. When all three hold, set the epic
329
+ `status: DONE` + `completed_date` + note `"epic-closure gate — children DONE + epic ACs
330
+ verified (post-run, new2 skill)"`, folded into the SAME reconciliation commit. Otherwise leave
331
+ the epic untouched and say why in the presentation.
332
+ **REOPEN branch (v5.6.0 — the ratchet is two-way now).** For every `false-epic-closure`
333
+ residual, AND for any epic found `status: DONE` on disk while the grep above still prints an
334
+ open child (follow-ups included) or a closure-invalidating finding stands: flip the epic back
335
+ to `status: IN_PROGRESS`, remove/annotate its `completed_date`, add note `"REOPENED — closed
336
+ against open scope (false DONE, v5.6.0 guard)"`, and fold into the same reconciliation commit.
337
+ An epic whose registry/ADR text says "goal not achieved" while its YAML says DONE is exactly
338
+ the FEAT-0068 contradiction this branch exists to prevent — the STATE wins, not the prose.
318
339
  3. **Resume if degraded — HARD-BOUNDED (v4.92.0).** If `degraded` is true, re-invoke
319
340
  the workflow with `Workflow({ scriptPath, resumeFromRunId })` (same `args` + the
320
341
  new `ts`). The per-card **skip-completed** guard makes the resume idempotent —
@@ -377,11 +398,31 @@ returns when the batch is done. It returns:
377
398
  (out of scope by design — the workflow is autonomous).
378
399
  - Record `escape_hatch: { eligible: N, offered: <bool>, ran_new: <bool>, followups: [...] }`
379
400
  in telemetry (step 5 below) so the A/B stays honest about when the hatch was used.
380
- 4. **Present.** Print `report` verbatim. Surface `residuals` prominently
381
- ("questi residui sono tracciati come follow-up: …") the post-run review that
382
- replaced the ~25 mid-run questions. If `degraded`, say so plainly (the run was
383
- incomplete and resumed). If the escape hatch ran `/new` (step 3b), fold its outcome
384
- into the presentation (which follow-ups were closed by `/new`).
401
+ 4. **Present.** Print `report` verbatim **including its verdict headline** (`⚠️ PARTIAL` /
402
+ `✅ COMPLETO`, v5.6.0): NEVER re-headline a PARTIAL run as a success in your own framing, and
403
+ never bury an epic-goal gap under a completion table (the FEAT-0068 report said "✅ 6/6 DONE"
404
+ over a disclosed-but-buried HIGH gap — the user discovered it only by asking). Surface
405
+ `residuals` prominently ("questi residui sono tracciati come follow-up: …") the post-run
406
+ review that replaced the ~25 mid-run questions; a HIGH residual is REMAINING WORK, present it
407
+ as such. If `degraded`, say so plainly (the run was incomplete and resumed). If the escape
408
+ hatch ran `/new` (step 3b), fold its outcome into the presentation (which follow-ups were
409
+ closed by `/new`).
410
+ 4b. **Batch git hygiene audit (v5.6.0 — never assert provenance without checking).** From the
411
+ kickoff you know the trunk's pre-batch sha (record `git -C $MAIN rev-parse ${trunk}` at Step 4
412
+ BEFORE launching the workflow). Now:
413
+ - `git -C $MAIN log --oneline <pre-sha>..HEAD` — for every commit whose subject does NOT
414
+ reference a batch card id (e.g. `[safety]`, unexpected chores), run `git show --stat <sha>`
415
+ and LIST it in the presentation with its files. Never attribute a commit to "a previous run"
416
+ without this check (the FEAT-0068 orchestrator asserted exactly that, and it was false).
417
+ A safety/sweep commit whose files are outside the batch's bookkeeping is a finding to
418
+ surface, not to normalize.
419
+ - `git -C $MAIN stash list` — any stash created during this batch (grep the batch/card ids and
420
+ the `baldart-new2-` label) MUST be reconciled NOW: inspect (`git stash show -p`), then apply
421
+ or drop with the user's standing policy — in AUTONOMOUS mode leave it but list it as a
422
+ PROMINENT pending item, never as a footnote and never "not mine to drop" (if this batch's
423
+ machinery created it, it IS yours to reconcile).
424
+ - Every `main-repo-contamination` residual: inspect the named paths in `$MAIN` and restore
425
+ them (they are the commit-agent detour's droppings), reporting what was restored.
385
426
  5. **Record truthful telemetry — reconciled against disk (F-040).** Before appending `telemetry`
386
427
  to `${metricsDir}/skill-runs.jsonl`, fill the fields the workflow could not compute and
387
428
  **reconcile the report against the real disk state** (agent `reason` strings can over-claim — a
@@ -2,6 +2,46 @@
2
2
 
3
3
  Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
4
4
 
5
+ ## 1.6.1 — 2026-07-06
6
+
7
+ - **Feature-gate**: added `requires_feature: has_prd_workflow` frontmatter — this skill is now linked into a consumer only when `features.has_prd_workflow` is enabled (it already refused at runtime otherwise). Trims Codex's ~2% skill-description budget on projects without the feature. Install-time gate, portable across Claude + Codex.
8
+
9
+ ## 1.6.0 — 2026-07-04 (FEAT-0068 post-mortem: il root cause era qui)
10
+
11
+ - **ISA "UI ROLE FAMILY (registry-first)"** (`discovery-phase.md` Dimension 9, gated su
12
+ `features.has_design_system`): per feature chrome/primitive enumera i PROPRIETARI della
13
+ superficie del goal dal registry (role families / Selection Policy), non solo i consumer
14
+ esistenti del meccanismo; **flag BLOCK su `@deprecated`** nel fix-path (i successori
15
+ documentati diventano il target). Era: DrilldownHeader/SectionHeader (~90% degli screen)
16
+ in NESSUNA card, ricetta ancorata su un Header deprecato da 5 pagine.
17
+ - **§0 LOAD CONTRACT** in testa a `discovery-phase.md`: il modulo supera il cap del Read —
18
+ vista PARTIAL ⇒ offset-Read obbligatori fino alla fine (la coda persa conteneva Exit
19
+ condition + Codex completeness cross-check + Research Trigger, mai eseguiti sul run reale).
20
+ - **`module_read` stamps** (SKILL.md): la lettura dei moduli di fase è ESEGUITA non recitata
21
+ — stamp nello state file, verificato dal validator (3 moduli mai letti sul run reale).
22
+ - **`step_3_mode` enum CHIUSO + contratto `skipped`** (`ui-design-phase.md`): `skipped` =
23
+ NESSUN artefatto di design, `links.design` vuoto, ogni explainer passa da `/ui-design`
24
+ (era: modalità fabbricata `design-spec` + design.html hand-authored su 5/6 card);
25
+ **Reconciliation-lite** (no mockup ≠ no reconciliation: role family dal registry ⇒
26
+ `component_bindings`); **trigger di ri-enumerazione ISA** quando la ricetta cambia target.
27
+ - **Gate quantificatore-universale sugli AC epic** (`validation-phase.md` item e):
28
+ "ogni schermata" ⇒ owner della superficie (census fresco) ⊆ unione scope figli, else
29
+ BLOCKER; `invariant_owners:` persistiti nell'epic.
30
+ - **Item 0-ii Phase-evidence audit** (`validation-phase.md`): stamp module_read + gate con
31
+ evidenza (API Perf Gate stampato `N/A` senza spawn sul run reale) + enum step_3_mode.
32
+ - **Stamp holistic evidence-gated** (`stamp-holistic-audit.js --audit-report` →
33
+ `agents_run`/`findings_count`; senza artefatto → `status: skipped` che `/new` tratta come
34
+ ASSENTE). Era: stamp su 6/6 card con zero spawn di audit (phantom stamp).
35
+ - **Card-writer self-validation** (`backlog-phase.md` + agente): il validator gira
36
+ nell'output del writer PRIMA del return (era: round-trip completo su EARS in italiano);
37
+ **Rule A ramo deterministico** (files docs/test-only ⇒ owner coder, mai `links.design`);
38
+ epic con `ac_verification` obbligatoria + mai count hardcodato; invariante lifecycle
39
+ baseline per suite snapshot.
40
+ - **Step 7.9 HARD RULE mw-docs** (`validation-phase.md`): mai `/mw` generico su worktree
41
+ `kind: docs` (+ guardia lato worktree-manager); era ~4M di BUILD_FAIL falso + unblock umano.
42
+ - **EDIT CONTRACT dello state file** (template + HARD RULE 2): anchor sul bare `key:` con
43
+ literal appena letto (5 retry ciechi da ~250k sul run reale).
44
+
5
45
  ## 1.5.0 — 2026-07-03 (framework v5.4.0)
6
46
 
7
47
  - **Step 2.1 Tier Gate (elastic pipeline).** At Discovery exit the feature is classified
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  name: prd
3
3
  effort: high
4
- version: 1.5.0
4
+ version: 1.6.1
5
+ requires_feature: has_prd_workflow
5
6
  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
7
  ---
7
8
 
@@ -54,9 +55,17 @@ message. You ask questions, wait for answers, and iterate.
54
55
  | 7 | Resolution, Commit & Merge | [validation-phase.md](references/validation-phase.md) |
55
56
  | 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
57
 
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
58
+ **Before starting each phase, read the corresponding reference file — EXECUTED, not
59
+ recited (v5.6.0).** After reading a phase module, record `module_read: <file> (full)` in the
60
+ state file's section for that phase; if the Read reported a PARTIAL view (the module exceeds
61
+ the token cap — `discovery-phase.md` does), issue offset Reads until the END of the file
62
+ before proceeding and stamp `(full, N reads)`. The Step 6 validator (`validation-phase.md`
63
+ item 0-ii) checks these stamps deterministically. This exists because a real session ran
64
+ Steps 2.5/4/4.5/5 with `research-phase.md`, `prd-writing-phase.md` and `backlog-phase.md`
65
+ NEVER read (6 Reads total in 73 turns): the improvised Step 5 contract produced a full
66
+ validator-rework round, and the truncated discovery tail silently dropped the mandatory Codex
67
+ completeness cross-check. ONE exception class: **agent-facing specs are passed BY PATH to the
68
+ agent that consumes them and MUST NOT be loaded into the orchestrator context.** Today these are
60
69
  `references/api-perf-gate.md` (read by `api-perf-cost-auditor` at Step 4.5 and at the
61
70
  Step 6 audit) and `references/audit-teammate-prompt.md` (read by each Step 6.6 audit
62
71
  teammate). Rationale: a spec loaded by a subagent costs one cheap Read in a disposable
@@ -70,7 +79,11 @@ for the rest of the run.
70
79
  > **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
80
 
72
81
  1. Follow steps in order. NEVER skip a step or jump ahead.
73
- 2. Every step MUST update the state file before proceeding.
82
+ 2. Every step MUST update the state file before proceeding. **State-file Edit hygiene
83
+ (v5.6.0):** anchor every Edit on the bare `key:` prefix with a literal you just Read —
84
+ never a recalled literal with trailing comments/alignment/blank lines (the template's
85
+ EDIT CONTRACT header; 5 blind retries at ~250k each on a real session). A failed match →
86
+ Read the exact lines, retry ONCE with the fresh literal.
74
87
  3. Every gate MUST be satisfied before moving to the next step.
75
88
  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
89
  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