baldart 4.12.0 → 4.13.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.
@@ -0,0 +1,267 @@
1
+ <!-- Modulo on-demand di /new — NON un file installato a sé. Caricato via Read dalla § "Routing" del SKILL.md core. -->
2
+
3
+ > **Modulo `/new`** — eseguilo, poi torna al core § "Routing" per la fase successiva. I `§ "..."` (Context economy, Context Tracking, Trivial-card fast-lane, Risk-signal detector, Fix Application Log) vivono nel **core SKILL.md**.
4
+
5
+ ## Final review (after all cards)
6
+
7
+ > **Primary code reviewer: Codex (a non-Anthropic frontier model, via `codex-companion.mjs`)** — cross-model validation with built-in FP filtering.
8
+ > Claude `code-reviewer` is the automatic fallback if Codex is unavailable.
9
+ > The `/codexreview` command remains available for standalone reviews on demand.
10
+
11
+ Once ALL cards are committed in the worktree:
12
+
13
+ > **Final-review FULL gate (since v3.37.0 — supersedes the v3.35.0 scope-reduction)** — because
14
+ > Phase 3.7 may now run a card at `light` depth, the per-card pass can NO LONGER be assumed to have
15
+ > full-reviewed every card. The final review is therefore the **unconditional safety gate that makes
16
+ > the Phase 3.7 `light` profile safe**: it ALWAYS runs a single FULL `/codexreview` (full agent set)
17
+ > over the **ENTIRE batch diff** before merge — **no N=1 skip, no cross-card scope reduction**. Every
18
+ > line of every card — including any reviewed at `light` in Phase 3.7 — receives a full-depth Codex
19
+ > review at least once before merge.
20
+ >
21
+ > - Run Steps F.1–F.5 for **EVERY batch, including N=1**. Nothing here is skipped.
22
+ > - `review_scope_files` = the **FULL union** of all touched files across all cards (F.1 step 4 —
23
+ > NEVER reduced to the cross-card subset).
24
+ > - F.3 invokes the full reviewer set (Codex + doc-reviewer + api-perf-cost-auditor + qa-sentinel)
25
+ > over that union; F.5 runs the final build.
26
+ >
27
+ > Rationale: this re-introduces the post-batch full pass that v3.35.0 de-duplicated away. That
28
+ > de-dup assumed Phase 3.7 had already full-reviewed every card — an assumption broken the moment
29
+ > `light` became selectable. The cost of one full batch-diff review is the deliberate price of the
30
+ > per-card `light` speed-up (explicit maintainer decision, v3.37.0).
31
+
32
+ ### Step F.1 — Resolve scope
33
+
34
+ **→ Visibility (batch transition)**: all cards are committed. TaskUpdate `Final review` → `in_progress` and emit a Progress Bar per § "Progress Visibility". Mark `Final review` → `completed` when F.5 finishes (fixes applied, build green).
35
+
36
+ 1. **Read the tracker file** to get the full picture: card IDs, files changed, commit hashes.
37
+ 2. Gather git evidence in the worktree:
38
+ ```bash
39
+ cd <worktree-path>
40
+ git diff --name-only <base-branch>...HEAD
41
+ ```
42
+ 3. Read each card's backlog YAML to collect `acceptance_criteria`, `files_likely_touched`.
43
+ 4. Build `review_scope_files` as the **FULL union** of card-indicated files + git-touched files
44
+ across ALL cards in the batch. **Since v3.37.0 this union is NEVER reduced** (the v3.35.0
45
+ cross-card scope-reduction is removed) — the final review is a full-depth pass over the entire
46
+ batch diff, so cards reviewed at `light` in Phase 3.7 still get a guaranteed full review before
47
+ merge. Record the union in the tracker; downstream F.3 reviews it in full.
48
+
49
+ ### Step F.2 — Architecture baseline
50
+
51
+ 5. **Reuse per-card baselines before re-spawning (dedup).** Phase 1 step 5b already persisted one
52
+ `/tmp/arch-baseline-<CARD-ID>.md` per card. Before spawning `codebase-architect` for the batch
53
+ scope, check whether every card in the batch already has a readable baseline file:
54
+ ```bash
55
+ MISSING=()
56
+ for c in <ALL-CARD-IDS>; do [ -s "/tmp/arch-baseline-$c.md" ] || MISSING+=("$c"); done
57
+ printf '%s\n' "${MISSING[@]}"
58
+ ```
59
+ - **All present** → do NOT re-spawn the architect for the full batch. Set `${ARCH_BASELINE_PATHS}`
60
+ to the newline-separated **list of `/tmp/arch-baseline-<CARD-ID>.md` paths** (they already cover
61
+ every touched file across the batch) — do NOT read or concatenate their contents inline (per
62
+ § "Context economy" → pass paths, not concatenations; Codex Reads them on demand). Proceed to F.3.
63
+ Log `f.2-arch: reused N per-card baselines (no re-spawn)` in the tracker. This avoids the N+1
64
+ architect invocations the per-card persistence was designed to prevent.
65
+ - **Any missing** (a card was added late, or a baseline was purged) → invoke **codebase-architect**
66
+ ONCE over the batch scope to map existing architecture, critical patterns, and high-risk code
67
+ paths for regression. Persist its output to `/tmp/arch-baseline-batch-<FIRST-CARD-ID>.md` and set
68
+ `${ARCH_BASELINE_PATHS}` to that single path. Log `f.2-arch: re-spawned (missing baselines: <list>)`. Do NOT spawn
69
+ the architect more than once for the batch — it is the single grounding context for all
70
+ downstream review agents.
71
+
72
+ ### Step F.3 — Codex deep code review (primary) + Claude agents (support)
73
+
74
+ > **Primary reviewer: Codex (a non-Anthropic frontier model, via `codex-companion.mjs`)** — cross-model validation. This is a SINGLE-MODEL Codex pass over the batch diff (scope + review + self-FP-check in one task) — it is NOT the full multi-agent `/codexreview` command pipeline (no sub-agent spawning, no Step 3.5 CoVe). The full per-card `/codexreview` already ran in Phase 3.7; this final pass is the cross-model batch-wide sweep. Claude agents (doc-reviewer, api-perf-cost-auditor) provide doc review and supplementary checks; qa-sentinel runs gates only.
75
+
76
+ 6. **Launch Codex code review** via `Bash` with `run_in_background: true` and `timeout: 600000` (10 min). **The companion script is invoked WITHOUT `--wait`** so the Bash call returns immediately and the orchestrator can fire the parallel Claude agents in step 7; poll `$REVIEW_FILE` for completion in F.4 (it is redirected to the file with `> "$REVIEW_FILE" 2>&1`, so it fills as Codex runs and is complete when the background task finishes — no inline `tee` copy, per § "Context economy"). Combining `run_in_background: true` with `--wait` would block the shell and defeat the parallelism — do NOT pass `--wait` here.
77
+
78
+ ```bash
79
+ REVIEW_FILE="/tmp/codexreview-batch-<FIRST-CARD-ID>-<SESSION-ID>.md" && \
80
+ CODEX_SCRIPT="$(ls -d ~/.claude/plugins/marketplaces/openai-codex/plugins/codex/scripts/codex-companion.mjs ~/.claude/plugins/cache/openai-codex/codex/*/scripts/codex-companion.mjs 2>/dev/null | sort -V | tail -1)" && \
81
+ [ -z "$CODEX_SCRIPT" ] && echo "CODEX_NOT_FOUND" > "$REVIEW_FILE" && exit 1; \
82
+ node "$CODEX_SCRIPT" task "
83
+ Run a deep multi-agent code review for these backlog cards. This is a post-implementation
84
+ review — the code is already written and committed. Your job is to find bugs, regressions,
85
+ security issues, and quality problems.
86
+
87
+ Cards to review (read each file):
88
+ ${CARD_PATHS}
89
+
90
+ Files changed (review ALL of these):
91
+ ${REVIEW_SCOPE_FILES}
92
+
93
+ Architecture baseline files (read each — they hold file paths, type signatures, patterns, high-risk paths):
94
+ ${ARCH_BASELINE_PATHS}
95
+
96
+ Follow the /codexreview protocol:
97
+ 1. For each card, read its backlog YAML for acceptance_criteria and entrypoints.
98
+ 2. Read every changed file in full.
99
+ 3. Check for: functional bugs, logic flaws, regressions, cross-card inconsistencies,
100
+ security issues (auth gaps, input validation, multi-tenant isolation),
101
+ performance issues (unbounded reads, N+1, missing pagination),
102
+ missing error handling on external boundaries.
103
+ 4. For each finding, return:
104
+ - finding_id: <CARD-ID>-F###
105
+ - title: short description
106
+ - severity: BLOCKER | HIGH | MEDIUM | LOW
107
+ - confidence: 0-100
108
+ - evidence: exact file:line + code quote
109
+ - minimal_fix_direction: what to change
110
+ 5. Run mandatory false-positive check: for each finding, ask 'What is the strongest
111
+ argument this is a false positive?' Suppress if the FP argument is convincing.
112
+ 6. Classify surviving findings as VERIFIED, FALSE_POSITIVE, or NEEDS_MANUAL_CONFIRMATION.
113
+
114
+ Return ONLY verified findings. If zero verified bugs: state 'No verified bugs found.'
115
+ " > "$REVIEW_FILE" 2>&1
116
+ ```
117
+
118
+ **Variable interpolation** (build the command string before execution):
119
+ - `${CARD_PATHS}`: newline-separated list of backlog YAML paths
120
+ - `${REVIEW_SCOPE_FILES}`: newline-separated list from Step F.1
121
+ - `${ARCH_BASELINE_PATHS}`: newline-separated list of per-card baseline file paths from Step F.2 (Codex Reads them on demand — do NOT inline their contents)
122
+
123
+ 7. **In parallel with Codex**, launch Claude support agents (single message):
124
+
125
+ | Agent | `subagent_type` | Focus | Output |
126
+ |-------|-----------------|-------|--------|
127
+ | **doc-reviewer** | `doc-reviewer` | Cross-card doc consistency, ssot-registry completeness, invariants | Findings: `finding_id`, `title`, `severity`, `confidence`, `evidence`, `minimal_fix_direction` |
128
+ | **api-perf-cost-auditor** | `api-perf-cost-auditor` | API/data/performance/cost defects (skip if no API/data files in scope) | Same findings schema |
129
+ | **qa-sentinel** | `qa-sentinel` | **Mechanical gates ONLY** over the batch scope (lint, tsc, full test suite, build, `npm audit`, markdownlint) | A PASS/FAIL gate table — NOT a findings list. qa-sentinel does not read source files, does not emit severities, and does not do edge-case/reproducibility analysis (its system prompt forbids it). A gate FAILURE feeds the fix-loop the same way a VERIFIED finding does. |
130
+
131
+ The two code-aware agents (doc-reviewer, api-perf-cost-auditor) receive: card IDs, YAML, `review_scope_files`, codebase-architect baseline, and a Budget Block per the `/codexreview` Step 2 contract (`framework/.claude/commands/codexreview.md`). qa-sentinel receives only the worktree path + the changed-file list and runs gates. Code-correctness/edge-case analysis is Codex's job (and the per-card `/codexreview` already ran) — do NOT ask qa-sentinel to produce code findings.
132
+
133
+ **Fan-out completion barrier (BLOCKING before F.4).** The three Claude agents write to a shared
134
+ findings pool that F.4 step 9 fans in. Before F.4 reads ANY finding, you MUST have collected the
135
+ return value of ALL THREE Task invocations from step 7 (doc-reviewer, api-perf-cost-auditor,
136
+ qa-sentinel) — never start the merge while a Task is still in flight. Because step 7 launches all
137
+ three in a single message, the harness returns when all three complete; do NOT proceed to step 9
138
+ on a partial set. (The Codex background task has its OWN barrier — step 8 below polls `$REVIEW_FILE`
139
+ for completion. The two barriers are independent: wait for BOTH the three Claude Tasks AND the
140
+ Codex background task before merging.)
141
+
142
+ ### Step F.4 — Collect & merge findings
143
+
144
+ 8. **Read Codex findings** from `$REVIEW_FILE` after the background command completes (the background
145
+ task was launched with `timeout: 600000` in step 6 — that 10-min window is the max wait).
146
+ - If file exists and contains findings → use as **primary code review source**.
147
+ - If file is empty, missing, or contains `CODEX_NOT_FOUND` → **fallback**: spawn `code-reviewer`
148
+ agent (subagent_type: `code-reviewer`) with the same scope and instructions. Log fallback
149
+ reason in tracker: `"Codex unavailable — fallback to Claude code-reviewer"`.
150
+ - **TIMED_OUT branch:** if the 10-min window elapses and `$REVIEW_FILE` still has no terminal
151
+ output (no findings block and no `CODEX_NOT_FOUND`), treat the Codex pass as **TIMED_OUT** — do
152
+ NOT block the merge gate waiting indefinitely and do NOT leave the task silently "in-progress".
153
+ Log `f.3-codex: TIMED_OUT` in `## Issues & Flags` and take the SAME `code-reviewer` fallback as
154
+ the unavailable case, so the final merge gate still gets a full code review.
155
+
156
+ 9. **Merge all findings** (Codex + Claude agents) into a consolidated list.
157
+ - Codex findings are already FP-validated (Step F.3 protocol includes it).
158
+ - Claude agent findings with `confidence < 80` → cross-validate by spawning **`code-reviewer`** as the static validator over the cited file:line; on disagreement between the originating agent and `code-reviewer`, classify the finding `NEEDS_MANUAL_CONFIRMATION` (do NOT silently drop it). (Naming the validator avoids the inconsistent "some second agent" interpretation.)
159
+ - Classify: `VERIFIED` | `FALSE_POSITIVE` | `NEEDS_MANUAL_CONFIRMATION`.
160
+ - `VERIFIED` findings proceed to fixes. **`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. Only `FALSE_POSITIVE` are dropped.
161
+
162
+ ### Step F.5 — Apply fixes and final build
163
+
164
+ 10. **Persist verified findings** to `/tmp/batch-final-review-<FIRST-CARD-ID>.md`.
165
+ 11. **Merge-blocking gate (mirrors the per-card Phase 3.7 gate this final pass backstops):** if any VERIFIED **BLOCKER or HIGH** finding exists, it MUST be resolved before Phase 6 merge. Apply fixes by **domain owner** (since v3.40.0 — same Domain-Override routing as the per-card phases), then re-verify; if a BLOCKER/HIGH cannot be resolved in a single apply + one retry, log it in `## Issues & Flags` and invoke `AskUserQuestion` (override with reason / escalate to a follow-up card / halt) — do NOT proceed to Phase 6 with an unresolved BLOCKER or HIGH. VERIFIED findings of severity MEDIUM are also applied (advisory below that). Partition the verified findings by the **Domain-Override match rules** ("Domain-Override Domains"):
166
+ - **`doc`-domain findings** (file path matching the `doc` match rule — `*.md` under `${paths.references_dir}`/`${paths.prd_dir}`, `CHANGELOG.md`, `ssot-registry.md`) → invoke the **doc-reviewer** agent once in write mode to apply them. NEVER route doc fixes to coder.
167
+ - **`security`-domain findings** (path in `paths.high_risk_modules`, or RLS-policy SQL) and **`migration`-domain findings** (SQL under the migrations dir) → route to **coder**, but apply the Sub-agent failure protocol's STOP-on-crash rule for these domains (never inline-fallback on a security/migration fix). These are NOT collapsed into a generic "everything else" bucket.
168
+ - **All remaining findings** (other code, perf, test) → invoke the **coder** agent once to apply them in a single pass.
169
+ Run in the order doc-reviewer → coder (or skip either if its partition is empty). Pass only the verified findings, not false positives.
170
+ 12. Run final build: `npm run lint && npx tsc --noEmit && npm run build` (redirect each to `/tmp/final-<gate>.txt` per § "Context economy"; surface only exit code + bounded extract on failure).
171
+ If any check fails, apply self-healing retry loop (up to 3 times).
172
+ 13. **Update tracker** with final review results:
173
+ - Review engine: Codex (a non-Anthropic frontier model, resolved at runtime by `codex-companion.mjs`) (primary) | Claude code-reviewer (fallback)
174
+ - Total findings raised / verified / false positives / needs-manual
175
+ - Fixes applied count
176
+ - Build status (pass/fail + retry count)
177
+ - Highest severity found
178
+ - **Phase-8 producer (named counters)** — ALSO write the structured line `review_findings: total=<R> verified=<V> blockers=<B>` to the tracker `## Final Review` section, where `R` = all findings raised (Codex + Claude agents, pre-FP), `V` = VERIFIED count, `B` = VERIFIED-BLOCKER count. These are the single named producers for Phase 8's batch-level `findings_total` / `findings_verified` / `blockers_count` — Phase 8 reads THESE keys, never re-parses prose. (Per-card Phase 3.7 codex counts stay in `## Pre-Merge Codex Review`; Phase 8 uses the batch-level `review_findings` line here as the canonical total so the QA-findings and codex-findings counts are not conflated.)
179
+
180
+ ### Step F.6 — Post-review wrap-up (SSOT summary, sync, hand-off to Phase 6)
181
+
182
+ > This is a distinct sub-section from F.1–F.5 (its own list); the numbering below restarts and does NOT continue the F.5 counter.
183
+
184
+ 1. **SSOT & Documentation Activity** (MANDATORY — run BEFORE merge):
185
+
186
+ Summarize all documentation and SSOT updates performed during the batch:
187
+
188
+ ```
189
+ ## Aggiornamenti SSOT & Documentazione
190
+
191
+ ### Documenti aggiornati
192
+ - `${paths.references_dir}/api/<module>.md` — N nuovi endpoint aggiunti
193
+ - `${paths.references_dir}/ui/<domain>.md` — N nuove route aggiunte
194
+ - `${paths.references_dir}/data-model.md` — N nuove collection
195
+ - `${paths.references_dir}/ssot-registry.md` — N entry aggiornate/create
196
+ - `${paths.references_dir}/project-status.md` — contesto aggiornato
197
+
198
+ ### ADR creati
199
+ - `${paths.adrs_dir}/ADR-YYYYMMDD-<slug>.md` — [titolo] (o "Nessun ADR creato")
200
+ ```
201
+
202
+ 2. **Knowledge Base Sync** (OPTIONAL — only if the project has an external knowledge corpus, e.g. an Obsidian vault, Confluence space, or Notion workspace):
203
+
204
+ If the project ships a `knowledge-sync` corpus agent (declared in `.baldart/overlays/new.md`), invoke it after doc updates so the external corpus stays aligned. If no such agent exists, skip this step with a one-line notice (do NOT dispatch a non-existent agent).
205
+
206
+ 3. **Proceed to Phase 6** (post-batch merge & cleanup).
207
+ 4. Present a **single summary report** to the user per card (and a batch summary at the end):
208
+ - **Files changed** (short list per card)
209
+ - **Test results** (new tests + existing tests count, pass rate at each iteration)
210
+ - **Build/lint status** (pass + retry count if any)
211
+ - **Fix cycles** (total number of self-healing retries across phases)
212
+ - **Final review** (findings: N raised / M verified / K false positives | fixes applied: N | highest severity)
213
+ - **UX testing** (PASS/FAIL/SKIP | test file path if written)
214
+ - **QA result** (profile: skip/light/balanced/deep | verdict: PASS/FAIL/SKIP | confidence % | failing gates: which of lint/tsc/test/build/markdownlint, or "none" | findings file path). E2E is reported separately (Phase 2.6 e2e-review), not by qa-sentinel.
215
+ - **Issues needing user attention** (anything unresolved, partially wired, or flagged)
216
+ - **Commit hashes** (from tracker)
217
+ - **Merge commit hash** (from Phase 6)
218
+ - **Card status reconciliation** (Phase 6b: N cards verified DONE, K force-updated)
219
+ - **Worktree cleanup status** (success/failed)
220
+ - **Knowledge-corpus sync status** (from Step F.6 item 2 "Knowledge Base Sync" — COMPLETED/FAILED/PARTIAL, or SKIPPED if no corpus-sync agent is configured)
221
+ - Overall implementation status
222
+
223
+ 4b. **Next Steps & Launch Command** (MANDATORY section — always present):
224
+
225
+ Check for remaining not-yet-DONE cards in the same epic group (match "not DONE",
226
+ not a hard-coded status value — see the `status enum` SSOT in REGISTRY.md):
227
+
228
+ ```bash
229
+ # Find parent epic's cards that are NOT yet DONE (TODO | READY | IN_PROGRESS | BLOCKED)
230
+ grep -l "parent: <EPIC-ID>" ${paths.backlog_dir}/*.yml \
231
+ | xargs grep -L "status: DONE"
232
+ ```
233
+
234
+ Present the section:
235
+
236
+ ```
237
+ ## Prossimi Passi
238
+
239
+ ### Lancio implementazione (copia e incolla)
240
+ ```
241
+ /new FEAT-XXXX-05 FEAT-XXXX-06 FEAT-XXXX-07
242
+ ```
243
+
244
+ ### Card rimanenti nell'epic
245
+ | Card | Titolo | Status | Gruppo parallelo |
246
+ |------|--------|--------|-----------------|
247
+ | FEAT-XXXX-05 | [title] | TODO | 2 |
248
+ | FEAT-XXXX-06 | [title] | TODO | 2 |
249
+
250
+ ### Card completate in questa sessione
251
+ | Card | Titolo | Commit |
252
+ |------|--------|--------|
253
+ | FEAT-XXXX-01 | [title] | abc1234 |
254
+ | FEAT-XXXX-02 | [title] | def5678 |
255
+ ```
256
+
257
+ If ALL cards in the epic are DONE:
258
+ ```
259
+ ## Prossimi Passi
260
+
261
+ Tutte le card dell'epic **FEAT-XXXX** sono state completate.
262
+ Pronto per il deploy: `/deploy` o `git push origin <trunk branch>` (il `git.trunk_branch` configurato)
263
+ ```
264
+
265
+ 5. **Proceed to Phase 7** (production readiness checklist).
266
+
267
+ ---
@@ -0,0 +1,353 @@
1
+ <!-- Modulo on-demand di /new — NON un file installato a sé. Caricato via Read dalla § "Routing" del SKILL.md core. -->
2
+
3
+ > **Modulo `/new`** — eseguilo, poi torna al core § "Routing" per la fase successiva. I `§ "..."` (Context economy, Context Tracking, Trivial-card fast-lane, Risk-signal detector, Fix Application Log) vivono nel **core SKILL.md**.
4
+
5
+ ### Phase 1 — Claim & Context
6
+ 1. **Update tracker**: set current card, phase = "1-claim".
7
+ 2. **`depends_on` gate (BEFORE claiming)** — read the card's `depends_on` field. For each listed card ID:
8
+ - Read that card's backlog YAML and check its `status` field.
9
+ - If NOT `DONE` → HALT: log in `## Issues & Flags` and ask the user: "Card <CARD-ID> depends on <DEP-ID> which is `<status>`. Proceed anyway, or wait?" Do not start implementation until the user responds explicitly. **The card status is NOT written until this gate passes** — so a HALT leaves the card untouched (no stale `IN_PROGRESS` for the next run to mis-read).
10
+ - If `DONE` (or the user chose "proceed anyway") → continue.
11
+ 2b. **Claim** — only now set the card status to `IN_PROGRESS` and assign yourself. **→ Visibility**: TaskUpdate this card's spine task → `in_progress`, and emit a Progress Bar (card change) per § "Progress Visibility".
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
+ 3. **(skip when provisionally trivial — see 2c)** 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`. The orchestrator does NOT propagate the 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.)
14
+ 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.
15
+ 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. Skip the plan-auditor when **BOTH** hold:
16
+ - **P1 — provenance present**: the card has `metadata.holistic_audit` with non-empty `audited_at`, `audited_commit`, `audited_set`.
17
+ - **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`):
18
+ ```bash
19
+ # empty AC, AC not in history, or any git error → treat as drift (do NOT skip)
20
+ DRIFT="$(git -C "$MAIN" log --oneline "$AC".."$TRUNK" -- $CARD_PATHS 2>/dev/null || echo "DRIFT")"
21
+ ```
22
+ P2 holds **iff** `$AC` is non-empty AND the command succeeds AND `$DRIFT` is empty.
23
+
24
+ (No S2/S3 cross-card conditions — grounding is per-card, and the holistic audit grounded each card individually.) If **P1 ∧ P2 → SKIP** the plan-auditor: log `plan-auditor grounding: SKIPPED (holistic_audit provenance, no drift on claimed paths since <AC short sha>)`, carry the card requirements unchanged into Phase 2, and proceed to step 5. **Fail-safe**: missing/partial provenance, any drift, or any git error → fall through to RUN the plan-auditor as written below (never a silent skip). Independent of the trivial fast-lane (a trivial card already skipped steps 3–4 at step 2c). Otherwise — invoke the **plan-auditor** agent in **QUICK mode** (pass `mode: QUICK`; its contract runs only the grounding checks, and because the codebase-architect findings are passed in below it does NOT re-spawn codebase-architect for this narrow check):
25
+ ```
26
+ mode: QUICK
27
+ Grounding check only (NOT a full audit — do not run the full AUDIT CHECKLIST A-H, and do not
28
+ re-invoke codebase-architect; the findings are pasted below). Verify this backlog card's
29
+ requirements are grounded in the actual codebase.
30
+
31
+ Check:
32
+ 1. Do all paths in files_likely_touched actually exist?
33
+ 2. Are all type/field references in requirements correct per the codebase findings below?
34
+ 3. Are any [ASSUMED] items answerable by reading the listed files (i.e., should be verified facts)?
35
+ 4. Do any requirements conflict with known anti-patterns from your memory?
36
+
37
+ Card YAML:
38
+ [paste full card YAML]
39
+
40
+ Codebase-architect findings:
41
+ [paste key findings from step 3]
42
+
43
+ Return: PASS | FIXES NEEDED (list exact corrections). No full audit report needed.
44
+ ```
45
+ - If **FIXES NEEDED**: apply corrections to the tracker notes for this card (do NOT modify the backlog YAML). Carry the corrected requirements into the Phase 2 briefing.
46
+ - If **PASS**: proceed.
47
+ 5. **Update tracker**: phase = "1-claim DONE", log codebase-architect key findings (1-2 lines) and plan-auditor result (PASS or corrections applied).
48
+ 5b. **Persist the architecture baseline for reuse (since v3.35.0)** — write the **untruncated codebase-architect task result verbatim** (the full Task-tool output: file paths, type signatures, patterns, high-risk paths) to `/tmp/arch-baseline-<CARD-ID>.md`. This is NOT the 1-2-line tracker summary from step 5 — serialize the agent's complete output to disk BEFORE you summarize it for the tracker, so Phase 3.7's per-card `/codexreview` (lean mode, reuses this file instead of re-spawning `codebase-architect`) gets enough detail to ground a reviewer. If you summarize first and write the summary, the lean contract is defeated.
49
+
50
+ ### Phase 2 — Implement (self-healing, up to 3 retries)
51
+ 6. **Update tracker**: phase = "2-implement".
52
+ 6b. **Agent dispatch (router)** — read `owner_agent` from the card YAML and resolve the spawn target per the table in § Agent Routing above:
53
+
54
+ ```
55
+ Let raw = card.owner_agent (string, may be missing).
56
+ # Epic guard FIRST — an epic is a tracker, not implementable work.
57
+ If card is an epic (id ends "-00" OR filename ends "-epic.yml" OR review_profile == "skip"
58
+ with no requirements): SKIP — do NOT dispatch to any agent. Log
59
+ "[ROUTER] card <ID> is an epic (tracker) — skipped, not implemented" and move to the next card.
60
+ Switch on raw:
61
+ - "coder" → spawn = "coder", briefing = "coder"
62
+ - "ui-expert" → spawn = "ui-expert", briefing = "ui-expert"
63
+ - "plan" → spawn = "coder", briefing = "coder"
64
+ + log: "[ROUTER] plan-only briefing not yet implemented — using coder"
65
+ - "visual-designer" → spawn = "coder", briefing = "coder"
66
+ + log: "[ROUTER] visual-designer briefing not yet implemented — using coder"
67
+ - "motion-expert" → spawn = "coder", briefing = "coder"
68
+ + log: "[ROUTER] motion-expert briefing not yet implemented — using coder"
69
+ - "" | missing | "claude"
70
+ → spawn = "coder", briefing = "coder"
71
+ + log: "[ROUTER] card <ID> has no valid owner_agent (got '<raw>'); defaulting to coder"
72
+ - anything else → HALT. Log: "[ROUTER] card <ID> has unknown owner_agent '<raw>' — not in {coder, ui-expert, plan, visual-designer, motion-expert}. Ask the user how to proceed."
73
+ ```
74
+
75
+ Log the resolved `spawn` and `briefing` in the tracker (1 line: `"router: owner_agent=<raw> → spawn=<agent>, briefing=<variant>"`). This is the audit trail for which specialist actually handled the card.
76
+
77
+ 7. Spawn the **resolved agent** (from step 6b) using this **standardized mission briefing** — fill in each section from the card YAML, tracker, and codebase-architect findings. When `briefing = "ui-expert"`, ALSO include the additional UI sections marked **[UI-ONLY]** below:
78
+
79
+ ```
80
+ ## MISSION BRIEFING — <CARD-ID>
81
+
82
+ ### Card Specification (verbatim — do not paraphrase)
83
+ Requirements:
84
+ [copy full requirements list from card YAML, including any corrections from the plan-auditor grounding check (step 4)]
85
+
86
+ Acceptance Criteria:
87
+ [copy full acceptance_criteria list from card YAML]
88
+
89
+ ### Unknowns & Conditional Requirements (MANDATORY — resolve before coding)
90
+ [If card has `unknowns` field: copy verbatim. If empty or absent: "None."]
91
+
92
+ Each unknown that says "verify X; if missing → do Y" is a BINARY-OUTCOME ITEM.
93
+ You MUST actively verify and produce one of the two outcomes (implementation OR TODO comment).
94
+ See `coder.md § Conditional Requirements — Binary-Outcome Items`.
95
+
96
+ ### Business Context (WHY this feature exists)
97
+ [paste business_rationale field from card YAML]
98
+ [if field is empty/missing, read PRD Section 1b from card's links.prd path]
99
+
100
+ ### Codebase Context
101
+ [paste codebase-architect key findings: file paths, exact line numbers, type signatures, existing patterns to follow]
102
+ [include any corrections or anti-patterns flagged by plan-auditor grounding check]
103
+
104
+ ### Design Reference (UI cards only — include if card has links.design)
105
+ Design file: [path from card's links.design field]
106
+ Read the design.html file and use it as the visual reference for your implementation.
107
+ The design was approved by the user — your implementation MUST match it.
108
+
109
+ ### [UI-ONLY] Registry-first BLOCKING pre-work (include ONLY when briefing = "ui-expert")
110
+ You are spawned as `ui-expert`. Before writing any UI code, you MUST complete
111
+ the registry-first cascade defined in
112
+ `framework/.claude/agents/ui-expert.md` § "Authoritative Style Reference —
113
+ Registry-First Protocol" (the SSOT lives in
114
+ `framework/agents/design-system-protocol.md`). Reproduce its 5 steps
115
+ verbatim, do NOT paraphrase or skip:
116
+
117
+ 1. Read `${paths.design_system}/INDEX.md` (component index + Canonical
118
+ Authority Matrix).
119
+ 2. Read `${paths.ui_guidelines}` (visual language, typography,
120
+ accessibility, brand voice).
121
+ 3. Read `${paths.design_system}/tokens-reference.md` (token contract —
122
+ SSOT for every color / spacing / shadow / radius / motion value).
123
+ 4. For EACH primitive in scope on this card, read
124
+ `${paths.design_system}/components/<Name>.md`. "In scope" = any
125
+ component named in the mockup, the requirements, or `files_likely_touched`.
126
+ 5. For EACH pattern in scope, read the relevant
127
+ `${paths.design_system}/patterns/<topic>.md`.
128
+
129
+ State, in your first response, which Authority Matrix rows govern this
130
+ card, which component specs you read (step 4), and which patterns you
131
+ read (step 5). Skipping this declaration = the orchestrator will reject
132
+ the implementation and re-spawn.
133
+
134
+ The `features.has_design_system: true` flag in `baldart.config.yml` is
135
+ the precondition for the full cascade. When `features.has_design_system:
136
+ false`, only step 2 applies — log the gap, recommend `/design-system-init`
137
+ if drift is visible, and proceed with coder-level diligence (no cascade
138
+ enforced).
139
+
140
+ ### [UI-ONLY] Implementation-only constraint (include ONLY when briefing = "ui-expert")
141
+ This `/new` invocation gives you the role of IMPLEMENTER, not designer:
142
+
143
+ - DO NOT redesign the mockup. The mockup at `links.design` is the
144
+ user-approved visual contract for this card.
145
+ - DO NOT silently adapt a mockup detail that conflicts with the registry
146
+ (e.g. a custom shadow not in `tokens-reference.md`, a font size off the
147
+ type scale, a color outside the palette). If you find such a conflict:
148
+ STOP, log it in the tracker as `[DS-DRIFT] mockup-vs-registry`, and ask
149
+ the user which side to honor.
150
+ - DO NOT extend scope into business logic, API calls, state management, or
151
+ validation rules. Those belong to a sibling `coder` card (see
152
+ `backlog-phase.md § Rule B`). If a requirement appears to need logic,
153
+ STOP and ask — do not implement it.
154
+
155
+ ### [UI-ONLY] Post-Intervention Coherence Check (include ONLY when briefing = "ui-expert")
156
+ Before declaring the card done, you MUST reconcile the three design-system
157
+ sources in the SAME commit as your UI change, per
158
+ `framework/agents/design-system-protocol.md § Post-Intervention Coherence Check`:
159
+
160
+ - `${paths.design_system}/INDEX.md` — add / update entries for any primitive
161
+ introduced or modified. Drift code: `DS_INDEX_DRIFT`.
162
+ - `${paths.design_system}/components/<Name>.md` — ship the per-component
163
+ spec for any new primitive; update the spec when a primitive's API or
164
+ visual changes. Drift code: `DS_COMPONENT_STALE`.
165
+ - `${paths.design_system}/tokens-reference.md` — add / update token entries
166
+ when introducing new semantic tokens. Drift code: `DS_TOKENS_DRIFT`.
167
+
168
+ The four conditions defined in `design-system-protocol.md` are the SSOT —
169
+ reproduce them in your completion report under a `design_system_coherence:`
170
+ block listing which conditions applied and which artifacts you updated.
171
+ Omitting the block = the orchestrator treats the card as not done.
172
+
173
+ ### File Permissions (ENFORCED — no exceptions)
174
+ MAY EDIT — your files for this card:
175
+ [list from ownership map for this card]
176
+
177
+ MUST READ ONLY — shared dependencies:
178
+ [list from ownership map: files owned by other cards that this card reads]
179
+
180
+ FORBIDDEN:
181
+ - Do NOT edit any file outside the MAY EDIT list above
182
+ - Do NOT refactor unrelated code
183
+ - Do NOT add unrequested features or extra error handling beyond what's specified
184
+ - Do NOT modify test files unless the card explicitly requires it
185
+
186
+ ### Database Indexes (if card has `db_indexes` — or legacy `firestore_indexes` — field)
187
+ This card requires the following indexes shipped in the SAME commit as the query
188
+ code. Missing indexes degrade performance or break production (variant per
189
+ `stack.database` — see `framework/.claude/agents/coder.md § Database Index Invariant`).
190
+
191
+ [paste db_indexes entries from card YAML, formatted as:]
192
+ | Entity | Dialect | Fields | Kind | Query Location | PRD Ref |
193
+ |--------|---------|--------|------|----------------|---------|
194
+ | [entity] | [stack.database] | [field1 ASC, field2 DESC] | [composite/covering/GIN/GSI] | [file path] | [IDX-N] |
195
+
196
+ **Where to ship the index — pick the artifact matching `stack.database`:**
197
+
198
+ - `firestore` → append to `firestore.indexes.json` under `indexes[]`:
199
+ ```json
200
+ {
201
+ "collectionGroup": "<entity>",
202
+ "queryScope": "COLLECTION",
203
+ "fields": [
204
+ { "fieldPath": "<field1>", "order": "ASCENDING" },
205
+ { "fieldPath": "<field2>", "order": "DESCENDING" }
206
+ ]
207
+ }
208
+ ```
209
+ Stage `firestore.indexes.json` together with the query code.
210
+ - `postgres` / `supabase` / `mysql` / `sqlite` → add a migration file under the
211
+ project's migrations dir (`migrations/`, `db/migrate/`, `supabase/migrations/`,
212
+ `prisma/migrations/` per project convention) with `CREATE INDEX ...` or the
213
+ Prisma `@@index([...])` directive. For Supabase, RLS policies live in the same
214
+ migration when relevant.
215
+ - `mongodb` → add `db.<entity>.createIndex(...)` to the project's index-bootstrap
216
+ script (path declared in `.baldart/overlays/new.md § Schema Bootstrap`), or run
217
+ it as part of the migration command.
218
+ - `dynamodb` → update the table definition in the project's IaC (CDK / Terraform /
219
+ SAM / SST) with the matching GSI/LSI.
220
+ - Stack `none` or unset → if you still see `db_indexes` on the card, ask the user
221
+ to confirm the persistence target before staging anything.
222
+
223
+ Stage the index artifact alongside the query code in the SAME commit. Verification
224
+ (post-deploy index propagation) is handled in the Production Readiness Checklist
225
+ section below, branched by `stack.deployment`.
226
+
227
+ ### Expected Output Locations
228
+ [pre-fill from codebase-architect: for each requirement, the file:line where the change should go]
229
+
230
+ ### Project Anti-Patterns & NFRs (ENFORCED)
231
+ Violating these is a BLOCKER in code review.
232
+
233
+ Deprecated patterns — the orchestrator MUST fill this from the project's own AGENTS.md / MEMORY.md / coding-standards.md before sending the briefing. If the project documents none, write "None documented." Do NOT pass placeholder example text to the coder (it wastes tokens and confuses the agent):
234
+ [resolved list of this project's deprecated/anti-patterns, or "None documented."]
235
+
236
+ Performance MUST rules (adapt to your stack):
237
+ - Bounded reads on every database query (`.limit()` / equivalent)
238
+ - Cursor-based pagination, not offset
239
+ - No per-row fetches in loops — batch instead
240
+ - Database indexes declared in schema config (same commit as the query that needs them)
241
+
242
+ Security MUST rules:
243
+ - No stack traces in HTTP responses — generic messages + error codes only
244
+ - No PII in console.log or error tracking
245
+ - No hardcoded secrets — env vars only
246
+ - ALL non-public routes MUST use the project's auth middleware
247
+
248
+ Coding standards (agents/coding-standards.md):
249
+ - Use the project's canonical terminology (document it in coding-standards.md)
250
+ - Honor the design-system theming contract (e.g. text/background pairing rules)
251
+ - Honor the project's image-format and asset-pipeline rules
252
+
253
+ Design System SSOT (MANDATORY for UI cards):
254
+ - Master reference: `${paths.design_system}/INDEX.md` (component index + Canonical Authority
255
+ Matrix + Quick rules MUST). Read this BEFORE touching any UI file.
256
+ - For each UI component you modify or create, read `${paths.design_system}/components/<Name>.md`.
257
+ - Merchant-themed surfaces MUST follow the pairing rule in
258
+ `the project's theming pattern doc (listed in `.baldart/overlays/ui-design.md`)`.
259
+ - Motion MUST follow `the project's motion pattern doc (listed in `.baldart/overlays/ui-design.md`)` (reduced-motion variants
260
+ required). The coder agent's own hardening (see `.claude/agents/coder.md`) already enforces
261
+ this — this briefing is an explicit reminder for UI-touching cards.
262
+ - No hardcoded hex/shadow/border values in component styling — canonical tokens only.
263
+
264
+ ### Batch Lessons (from prior cards in this batch)
265
+ [If tracker `## Lessons Learned` has entries, paste them here.
266
+ If empty or first card: "First card — no lessons yet."]
267
+
268
+ ### MANDATORY: Numbered Requirements Checklist (anti-skip measure)
269
+ Before you start coding, print this checklist to confirm you see ALL requirements:
270
+ ```
271
+ REQUIREMENTS TO IMPLEMENT:
272
+ [x] R1: [requirement text]
273
+ [x] R2: [requirement text]
274
+ ...
275
+ ACCEPTANCE CRITERIA TO SATISFY:
276
+ [x] AC1: [criterion text]
277
+ [x] AC2: [criterion text]
278
+ ...
279
+ CONDITIONAL / BINARY-OUTCOME ITEMS (from unknowns + requirements with "verify if / if missing"):
280
+ [ ] C1: [item text] → Branch to take: A (found+implement) | B (missing+TODO)
281
+ [ ] C2: [item text] → Branch to take: A (found+implement) | B (missing+TODO)
282
+ ...
283
+ Total: N requirements + M acceptance criteria + K conditional items = X items
284
+ ```
285
+ You MUST implement ALL items. Skipping even one is a failure.
286
+ For each conditional item: verify actively, then produce the correct branch artifact.
287
+
288
+ ### MANDATORY: Completion Report
289
+ When implementation is done, output this block in EXACTLY this format.
290
+ This report is NOT optional — if you omit it, the orchestrator will flag
291
+ your implementation as incomplete and spawn a fix agent.
292
+
293
+ ```completion-report
294
+ card: <CARD-ID>
295
+ requirements:
296
+ - id: 1
297
+ text: "[verbatim requirement text]"
298
+ status: done | not_implemented
299
+ evidence: "src/path/to/file.ts:LINE_NUMBER"
300
+ notes: "[if not_implemented: explain why]"
301
+ - id: 2
302
+ [repeat for each requirement]
303
+ acceptance_criteria:
304
+ - id: 1
305
+ text: "[verbatim criterion text]"
306
+ status: done | not_implemented
307
+ evidence: "src/path/to/file.ts:LINE_NUMBER"
308
+ items_total: [N]
309
+ items_done: [M]
310
+ items_skipped: [list of skipped item IDs, or "none"]
311
+ conditional_items:
312
+ - item: "[verbatim text of conditional requirement]"
313
+ branch_taken: "A-found" | "B-missing"
314
+ evidence: "src/path/to/file.ts:LINE_NUMBER"
315
+ notes: "[if B-missing: exact TODO location and text left; otherwise omit]"
316
+ ```
317
+
318
+ Per-requirement / per-AC `status` is BINARY: `done` or `not_implemented` (the legacy
319
+ `partial`/`blocked` values are removed — see `coder.md`). The orchestrator re-derives the
320
+ finer Done/Partial/Missing classification itself in Phase 2.5 by reading the code; the coder
321
+ report is a starting signal, not ground truth.
322
+ If `items_skipped` is not "none", you MUST explain why each was skipped.
323
+ The orchestrator treats any `not_implemented` or skipped item as a gap requiring a fix agent.
324
+ `conditional_items` MUST list every binary-outcome item from the card. If the card has no
325
+ conditional requirements, omit the field. `branch_taken: B-missing` MUST have a `notes`
326
+ field with the exact file path and line where the TODO comment was written.
327
+ ```
328
+
329
+ 8. **Run the verification gates and CAPTURE their output to disk** (so step 9 can pass it to a fix agent) — **redirect, never `tee`/stream inline** (per § "Context economy" → Gate-output discipline). Each is its own gate:
330
+ ```bash
331
+ cd <worktree-path>
332
+ npm run lint > /tmp/lint-<CARD-ID>.txt 2>&1; echo "lint:$?"
333
+ # tsc is its OWN blocking gate — run it ONLY when stack.language includes "typescript"
334
+ # (do NOT assume `npm run build` covers tsc — Next.js dev builds and many setups skip it):
335
+ npx tsc --noEmit > /tmp/tsc-<CARD-ID>.txt 2>&1; echo "tsc:$?" # guard: when stack.language includes "typescript"
336
+ npm test > /tmp/test-<CARD-ID>.txt 2>&1; echo "test:$?" # if tests exist
337
+ npm run build > /tmp/build-<CARD-ID>.txt 2>&1; echo "build:$?"
338
+ ```
339
+ The `echo "<gate>:$?"` lines surface only the **exit code** inline — the full log stays on disk. When `stack.language` does NOT include `typescript`, skip the `tsc` line (no equivalent gate). Capturing to `/tmp/*-<CARD-ID>.txt` guarantees the failing output is available for step 9. On a non-zero exit, read a **bounded** extract only (`tail -n 30 /tmp/<gate>-<CARD-ID>.txt`), never the whole log — do NOT run the gates without redirect-to-file capture.
340
+ 9. **If any check fails**: categorize the error (`lint | TypeScript | test | build`), log it in the tracker as `retry-cause: <category>`.
341
+ **Code-recovery check (MUST do before rewriting)**: before spawning a fix agent or rewriting code, check whether lint-staged or a pre-commit hook removed code that is actually needed (e.g. a field "unused" at commit time but consumed by later code). Inspect the captured diff and `git diff`/`git log -p` for the worktree branch and restore the needed code by an explicit file write. **Do NOT `git stash pop` inside the worktree** — `refs/stash` is globally shared across worktrees (`$GIT_COMMON_DIR`), so a stash created or popped in a worktree can corrupt another worktree's state (see Phase 4 WORKTREE COMMIT RULE). If you need to set work aside in a worktree, make a clearly-labelled WIP commit and record its hash in the tracker for later squash, never a stash.
342
+ When spawning a fix agent: scope it exclusively to this card's Edit-allowed files (from `## File Ownership Map`) — it MUST NOT touch files owned by other cards. Pass the fix agent: the **path** to the captured gate log (`/tmp/<gate>-<CARD-ID>.txt` — it Reads the log itself; do NOT inline-paste the full log into its prompt), the error category, and the explicit list of files it may edit. Do NOT ask the user — just fix and re-run. Fix the code, not the tests (unless the test itself is wrong). Repeat up to **3 times**. **Stuck-loop guard**: compare the failing error's fingerprint (file:line + message) between retries; if the SAME error reproduces on 2 consecutive retries, the fix is not converging (often a constraint outside the card's ownership map) — stop early, log `[STUCK-LOOP] <error>` in `## Issues & Flags`, and escalate to the user rather than burning the 3rd retry on an identical failure.
343
+ 10. If still failing after 3 retries (or on a stuck loop), log the failure in `## Issues & Flags` and ask the user before continuing.
344
+ 11. **Update tracker**: phase = "2-implement DONE", log files changed (short list), retry count, retry causes (e.g., `"2 retries: TypeScript x1, lint x1"`), and test results (new + existing test count, pass/fail).
345
+ 11b. **File diff gate** — verify the coder only touched its allowed files. The coder commits its work (per `coder.md`), so a bare `git diff --name-only HEAD` is vacuous (clean tree). Detect what the card's commits actually changed against the trunk, with an uncommitted-fallback:
346
+ ```bash
347
+ cd <worktree-path>
348
+ git diff --name-only "$TRUNK...HEAD" 2>/dev/null || git diff --name-only HEAD~1..HEAD
349
+ ```
350
+ (`$TRUNK` is the trunk branch resolved in Phase 0; if the worktree branched from a different base, the `HEAD~1..HEAD` fallback covers the last commit.)
351
+ Compare against this card's allowed files in `## File Ownership Map`.
352
+ - **All within allowed set** → proceed to Phase 2.5.
353
+ - **Any file outside allowed set** → log the violation in `## Issues & Flags` (`"unauthorized file: <path>"`), then spawn a **targeted revert coder agent** with instruction: "Revert ONLY these files to their pre-commit state. Do not touch any other file: [list unauthorized files]". Re-run build + lint to confirm clean state after revert. Update tracker with revert outcome, then proceed to Phase 2.5.