baldart 4.11.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.
- package/CHANGELOG.md +43 -0
- package/VERSION +1 -1
- package/framework/.claude/agents/coder.md +3 -3
- package/framework/.claude/skills/new/SKILL.md +185 -2351
- package/framework/.claude/skills/new/references/codex-gate.md +129 -0
- package/framework/.claude/skills/new/references/commit.md +57 -0
- package/framework/.claude/skills/new/references/completeness.md +284 -0
- package/framework/.claude/skills/new/references/final-review.md +267 -0
- package/framework/.claude/skills/new/references/implement.md +353 -0
- package/framework/.claude/skills/new/references/merge-cleanup.md +175 -0
- package/framework/.claude/skills/new/references/metrics.md +72 -0
- package/framework/.claude/skills/new/references/production-readiness.md +232 -0
- package/framework/.claude/skills/new/references/review-cycle.md +247 -0
- package/framework/.claude/skills/new/references/setup.md +249 -0
- package/framework/.claude/skills/new/references/team-mode.md +253 -0
- package/framework/.claude/skills/worktree-manager/SKILL.md +16 -8
- package/framework/agents/coding-standards.md +5 -5
- package/package.json +1 -1
|
@@ -0,0 +1,129 @@
|
|
|
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 3.7 — Pre-Merge Codex Review Gate (MANDATORY — UNCONDITIONAL)
|
|
6
|
+
|
|
7
|
+
**This gate runs for EVERY card with code to review before the Phase 4 commit.** A per-card `/codexreview` MUST run BEFORE the Phase 4 commit, regardless of file paths or perceived risk. The historical conditional High-Risk Path detector is preserved below — but only as a **signal-logging step** to record *which* triggers matched in the tracker. It NEVER suppresses the `/codexreview` invocation. Even if zero triggers match, `/codexreview` runs.
|
|
8
|
+
|
|
9
|
+
> **Single carve-out — `IS_TRIVIAL` fast-lane (since v4.6.0)**: a card that is `IS_TRIVIAL` on its ACTUAL committed diff (`review_profile=skip` + non-source diff + 0 Step-A triggers — § "Trivial-card fast-lane") **skips this gate**, because there is no code for Codex to review. Its adversarial coverage is carried by the SAME unconditional **Final-review FULL gate** the `light` path already relies on (it runs Codex over the entire batch diff, including every trivial card's files, before merge). This is NOT a `time budget` skip — it is the deterministic `IS_TRIVIAL` gate reason, and the guard means a single source file in the diff flips the card back onto this gate. Log `codex-review: SKIPPED (trivial — non-source diff; covered by Final FULL gate)`.
|
|
10
|
+
|
|
11
|
+
**Rationale**: leaving the gate conditional caused it to be silently skipped on the majority of cards, defeating the AGENTS.md "MUST run BEFORE merge" requirement. The gate itself is unconditional — what varies is its DEPTH (`light` vs `full`). The protection against a missed blocker on a "low-risk" path (BUG-0530-class regressions) is carried by two mechanisms, not by an always-on per-card Codex pass: (1) the Step A detector escalates any risky diff to `full` per-card, and (2) the unconditional **Final-review FULL gate** runs Codex adversarial over the entire batch diff before merge. So `light` can safely run `code-reviewer` + FP-gate only (since v3.38.0) without weakening the merge gate.
|
|
12
|
+
|
|
13
|
+
#### Step A — Detect (signal-logging only, NEVER gates the next step)
|
|
14
|
+
|
|
15
|
+
Run the **§ "Risk-signal detector" del core SKILL.md** (rilocato lì perché anche la
|
|
16
|
+
§ "Trivial-card fast-lane" lo usa a Phase 1). È lo stesso identico detector bash
|
|
17
|
+
(trigger #1 high-risk module / #2 dead-code resurrection / #3 reference-aliasing):
|
|
18
|
+
produce la lista `TRIGGERS`. Logga quali trigger hanno fatto match; **non
|
|
19
|
+
short-circuita mai** lo Step B/C — `/codexreview` parte unconditional.
|
|
20
|
+
|
|
21
|
+
#### Step B — Log detector result (never skips)
|
|
22
|
+
|
|
23
|
+
Log the detector output in the tracker for traceability. **This step never short-circuits Step C — `/codexreview` runs unconditionally regardless of whether `TRIGGERS` is empty or populated.**
|
|
24
|
+
|
|
25
|
+
- If `TRIGGERS` is empty: log `## Pre-Merge Codex Review: no high-risk triggers matched (gate still runs unconditionally)` and proceed to Step C.
|
|
26
|
+
- If `TRIGGERS` is non-empty: log the matched triggers (see Step C step 1) and proceed to Step C.
|
|
27
|
+
|
|
28
|
+
#### Step C — Invoke per-card `/codexreview` (ALWAYS)
|
|
29
|
+
|
|
30
|
+
For EVERY card (no conditional skip — the gate ALWAYS runs; only its DEPTH varies):
|
|
31
|
+
|
|
32
|
+
0. **Select the Codex review profile (deterministic — Review Profile Selector)** by mapping the
|
|
33
|
+
card's review profile (read from the card's `review_profile` field per the QA Profile Selector
|
|
34
|
+
above — since v3.38.0; fallback-computed only for legacy cards) and the Step A detector:
|
|
35
|
+
- **`light`** ⟺ the card's profile ∈ {`skip`, `light`} **AND** Step A matched **zero**
|
|
36
|
+
high-risk triggers.
|
|
37
|
+
- **`full`** ⟺ otherwise — i.e. the card's profile ∈ {`balanced`, `deep`}, **OR** any Step A
|
|
38
|
+
trigger matched.
|
|
39
|
+
|
|
40
|
+
**Escalation-only invariant (since v3.38.0)**: the Step A detector runs on the ACTUAL diff and
|
|
41
|
+
can only ever **escalate** `light` → `full` (a high-risk path surfaced at implementation time
|
|
42
|
+
that the card's authored profile didn't anticipate). It can NEVER downgrade `full` → `light`.
|
|
43
|
+
The card's `review_profile` is the deterministic floor; the diff detector is the safety net on
|
|
44
|
+
top of it.
|
|
45
|
+
|
|
46
|
+
`light` is **NOT** a skip: `/codexreview` still runs `code-reviewer` + the Step 3 false-positive
|
|
47
|
+
gate. **Since v3.38.0 the per-card Codex adversarial pass is NO LONGER run at `light`** — it is the
|
|
48
|
+
prerogative of `full` and of the final cross-check. `light` drops the Codex adversarial pass AND the
|
|
49
|
+
breadth agents (qa-sentinel, api-perf-cost-auditor, doc-reviewer) AND Step 3.5 CoVe — leaving exactly
|
|
50
|
+
`code-reviewer` + FP-gate, the cheap per-card pass that yields the early feedback worth having on a
|
|
51
|
+
0-trigger, QA-light diff. `full` is unchanged (Codex adversarial + the full agent set, minus the
|
|
52
|
+
duplicate doc-reviewer).
|
|
53
|
+
**Where the BUG-0530 invariant now lives.** Pre-v3.38.0 the per-card Codex adversarial was the
|
|
54
|
+
"never miss a blocker on a low-risk path" guard. Two mechanisms now carry that guarantee instead,
|
|
55
|
+
so dropping it from `light` is safe:
|
|
56
|
+
1. **Escalation-only (Step A)** — any high-risk trigger on the ACTUAL diff promotes `light` → `full`,
|
|
57
|
+
so genuinely risky paths (auth/payment/permission/schema/…) STILL get per-card Codex adversarial.
|
|
58
|
+
Only a 0-trigger, authored-`light` card defers it.
|
|
59
|
+
2. **Final-review FULL gate (since v3.37.0)** — the **Final review ALWAYS runs a single FULL
|
|
60
|
+
`/codexreview` over the entire batch diff before merge** (no N=1 skip, no scope reduction — see
|
|
61
|
+
"Final review → Final-review FULL gate"), and FULL includes Codex adversarial. So every line of
|
|
62
|
+
every `light` card receives Codex adversarial at least once before merge.
|
|
63
|
+
Net effect: `light` per-card = early `code-reviewer` feedback; the Codex adversarial review is paid
|
|
64
|
+
once, at the final batch gate (or per-card the moment a risk trigger fires). To put per-card Codex
|
|
65
|
+
back on `light`, re-add agent #5 to the `light` branch of `/codexreview` Step -0.5.
|
|
66
|
+
|
|
67
|
+
Then dump the card diff (reviewer grounding) and write the lean contract `/codexreview` consumes:
|
|
68
|
+
```bash
|
|
69
|
+
cd <worktree-path>
|
|
70
|
+
# $TRUNK = the trunk branch resolved in Phase 0 (git.trunk_branch)
|
|
71
|
+
git diff "$TRUNK...HEAD" -- <card files from ownership map> > /tmp/diff-<CARD-ID>.txt 2>/dev/null \
|
|
72
|
+
|| git diff HEAD~1..HEAD > /tmp/diff-<CARD-ID>.txt
|
|
73
|
+
```
|
|
74
|
+
Write `/tmp/codexreview-lean-<CARD-ID>.json`:
|
|
75
|
+
```json
|
|
76
|
+
{ "profile": "light|full", "arch_baseline_path": "/tmp/arch-baseline-<CARD-ID>.md",
|
|
77
|
+
"diff_summary_path": "/tmp/diff-<CARD-ID>.txt", "skip_doc_reviewer": true,
|
|
78
|
+
"skip_api_perf_auditor": true }
|
|
79
|
+
```
|
|
80
|
+
`skip_doc_reviewer` is ALWAYS true: Phase 3 already ran `doc-reviewer` on this diff (with the
|
|
81
|
+
spec/docs-drift→bug lens since v3.35.0), so `/codexreview` agent #3 would be a duplicate.
|
|
82
|
+
`skip_api_perf_auditor` is ALWAYS true (since v4.7.0): the per-card api-perf/cost pass is deferred
|
|
83
|
+
to the **Final Review F.3 api-perf-cost-auditor** (batch-wide), so `/codexreview` agent #2 would be
|
|
84
|
+
a duplicate of the final sweep. (At `full` `/codexreview` would otherwise spawn it; at `light` it is
|
|
85
|
+
already dropped.)
|
|
86
|
+
|
|
87
|
+
1. **Log gate invocation** in the tracker under `## Pre-Merge Codex Review`:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
## Pre-Merge Codex Review
|
|
91
|
+
- Triggered: unconditional (mandatory pre-merge gate)
|
|
92
|
+
- Profile: light | full — reason: <review_profile=<skip|light|balanced|deep> (from card | computed); triggers=0 | trigger #N matched (escalated light→full)>
|
|
93
|
+
- Matched high-risk triggers: <list from detector, or "none">
|
|
94
|
+
- Action: invoking /codexreview <CARD-ID> (per-card, pre-merge gate; lean contract written)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
2. **Invoke `/codexreview`** for the single card via the Skill tool:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Skill: codexreview
|
|
101
|
+
args: <CARD-ID>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`/codexreview` Step -0.5 consumes `/tmp/codexreview-lean-<CARD-ID>.json`: reuses the Phase-1
|
|
105
|
+
architecture baseline (no re-spawn), drops the duplicate doc-reviewer, and for `profile: light`
|
|
106
|
+
also drops qa-sentinel + api-perf-cost-auditor + **the Codex adversarial pass** + Step 3.5 CoVe
|
|
107
|
+
(since v3.38.0). `code-reviewer` + Step 3 FP-gate + Step 4 report ALWAYS run. (`full` = standard
|
|
108
|
+
pipeline incl. Codex adversarial, minus the duplicate doc-reviewer.)
|
|
109
|
+
|
|
110
|
+
3. **Read the consolidated report**. `/codexreview` writes it to `/tmp/codexreview-report-<TIMESTAMP>.md` and RETURNS that exact path in its Skill-tool result — use the returned path, do NOT guess the timestamp. If the return value did not surface the path, locate the newest report whose body names this `<CARD-ID>` (`grep -l "<CARD-ID>" /tmp/codexreview-report-*.md | xargs ls -t | head -1`), never just the newest file by mtime (a parallel card's report could be newer). Extract:
|
|
111
|
+
- Verified BLOCKER count
|
|
112
|
+
- Verified HIGH count
|
|
113
|
+
- List of `[ripple-expanded]` findings (Step 3.5 widened scope). At `light` profile Step 3.5 CoVe does not run, so this list is structurally empty — log `ripple-expanded: 0 (CoVe not run at light)` rather than a bare `0`, so audits can tell "not attempted" apart from "attempted, none found".
|
|
114
|
+
|
|
115
|
+
4. **Apply fix sub-loop** (mirror of Phase 3.5 retry pattern):
|
|
116
|
+
- If 0 BLOCKER and 0 HIGH → log `verdict: PASS — proceeding to Phase 4` in tracker. Done. (MEDIUM/LOW findings are advisory at this per-card gate; they are not silently lost — the post-batch **Final-review FULL gate** applies every VERIFIED finding ≥ MEDIUM. Log the MEDIUM count in the tracker so it is visible.)
|
|
117
|
+
- If 1+ BLOCKER OR 1+ HIGH → spawn `coder` agent with the report path + list of VERIFIED bugs. **At `full` profile** the report contains Codex-suggested inline patches: pass them and have the coder **apply the suggested patches** with the right system prompt (project conventions, naming, testing patterns) — it does NOT re-do the analysis or re-grep (since v3.28.3), BUT it MUST first confirm each patch still applies against the current file state (prior fix-loop iterations may have shifted line offsets); if a patch no longer applies cleanly, the coder re-locates the target by content and applies the equivalent edit rather than a stale-offset verbatim paste. **At `light` profile** no Codex adversarial patches exist (the pass was dropped) — the findings come from `code-reviewer`; brief the coder accordingly (apply the `code-reviewer` fix direction; there are no Codex patches to paste). After coder fixes, **re-write the lean contract `/tmp/codexreview-lean-<CARD-ID>.json` (it is consumed-once and deleted by `/codexreview`)** and re-invoke `/codexreview` via the Skill tool with `args: <CARD-ID>` (NOT a bare prose mention — the card ID MUST be passed so the retry reviews THIS card, not an inferred one). Repeat **max 2 times**.
|
|
118
|
+
- If still BLOCKER/HIGH after 2 retries → log in `## Issues & Flags` and **ask the user** whether to proceed, escalate, or stop. The Phase 4 commit MUST NOT happen until the Pre-Merge Codex Review verdict is PASS or user explicitly overrides.
|
|
119
|
+
- **Telemetry** — for EVERY codex finding processed (verified BLOCKER, verified HIGH, or false-positive-filtered), append one row to `## Fix Application Log`: `3.7 | codex-<security|correctness|other> | est_lines=<n> | decision=<coder|skipped> | applied_by=<coder|-> | severity=<BLOCKER|HIGH|FALSE-POSITIVE> | retry=<n>`. Classify domain: `security` for findings touching RLS / auth / permissions / payments; `correctness` for logic / data integrity / race conditions; `other` for everything else.
|
|
120
|
+
|
|
121
|
+
5. **Update tracker**: phase = `3.7-codexgate DONE` (the gate runs unconditionally for every card — the legacy `3.7-highrisk` name implied it only fired on high-risk cards, which is no longer true), log final verdict, retry count, list of fixed findings, and the report path.
|
|
122
|
+
|
|
123
|
+
6. **E2E re-run obligation check (enforces the Phase 2.6 re-run trigger HERE)** — if this Phase 3.7 fix sub-loop modified any file under `${paths.app_dir}`, `${paths.components_primitives}`, or any `*.css` / `*.scss`, you MUST re-invoke `/e2e-review` (programmatic mode, same `.baldart/e2e-review/<CARD-ID>/` state dir) BEFORE the Phase 4 commit and resolve its verdict per the Phase 2.6 gating-logic table. Log `e2e-rerun: triggered` or `e2e-rerun: not-needed (no UI files touched in 3.7)` in the tracker so Phase 4 can assert it. Do NOT defer this to "it's documented in Phase 2.6" — the check fires here, where the fixes happen.
|
|
124
|
+
|
|
125
|
+
#### Why deterministic detector + agent pipeline
|
|
126
|
+
|
|
127
|
+
The detector (Step A) is bash + grep — guaranteed to run, no LLM skip. The downstream pipeline (Step C) is the existing `/codexreview` skill — fully tested, includes Codex adversarial review and Step 3.5 cross-agent CoVe. This combination ensures the AGENTS.md "MUST run BEFORE merge" rule is enforced reliably.
|
|
128
|
+
|
|
129
|
+
**Crash handling**: if `/codexreview` (or its fix-loop `coder`) crashes mid-phase, apply the "Sub-agent failure protocol" (below). Treat this gate as a **mandatory gate, NOT a non-domain-override fallback** — `/codexreview` covers the `security` domain (auth/payment/permission findings), so a crash that cannot be recovered by one retry STOPS the pipeline and routes to `AskUserQuestion`; do NOT rationalize it as "non-domain-override" and inline-bypass the merge gate.
|
|
@@ -0,0 +1,57 @@
|
|
|
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 4 — Commit (in worktree, NO merge yet)
|
|
6
|
+
|
|
7
|
+
> Sequential-mode global step numbering resumes here at 26 (Phase 3.5 ended at 25; Phase 3.7 used its own local C.0–C.6 counter). The tracker phase-string `4-commit` therefore maps to step 26, NOT a second step 25.
|
|
8
|
+
|
|
9
|
+
26. **Update tracker**: phase = "4-commit". **Entry assertion** — before committing, verify the Phase 3.7 e2e re-run obligation was honored: read the tracker for `e2e-rerun: triggered` / `e2e-rerun: not-needed`. If Phase 3.7 touched UI files but no `e2e-rerun` entry exists, do NOT commit yet — go run the re-run per Phase 3.7 step 6 first. Also confirm Phase 3.5/3.7 fixes did not leave lint/tsc broken: if the Phase 3.7 fix sub-loop applied any patch, run `npm run lint` + `npx tsc --noEmit` (when typescript) once before committing (redirect to disk per § "Context economy").
|
|
10
|
+
27. Stage and commit **all changes together** in the worktree using format `[CARD-ID] Brief description` (MUST per AGENTS.md). Include all relevant files — implementation, review fixes, QA-driven fixes, and doc updates in a single commit. Do NOT merge or push yet — that happens post-batch.
|
|
11
|
+
- **IMPORTANT — explicit staging**: NEVER use `git add -A` or `git add .`. Always stage files by explicit name:
|
|
12
|
+
```bash
|
|
13
|
+
cd <worktree-path>
|
|
14
|
+
# List changed files
|
|
15
|
+
git diff --name-only
|
|
16
|
+
git ls-files --others --exclude-standard
|
|
17
|
+
# Stage only the files this card touched (explicit names)
|
|
18
|
+
git add src/path/to/file1.ts src/path/to/file2.ts ...
|
|
19
|
+
# Commit directly — NO stash in worktrees
|
|
20
|
+
git commit -m "[CARD-ID] Brief description"
|
|
21
|
+
```
|
|
22
|
+
- **WORKTREE COMMIT RULE — NEVER use `git stash` in worktrees.** Stashes are globally shared across all worktrees (`refs/stash` via `git.commondir`). A stash created in one worktree can be popped by another, causing conflicts, data loss, and cascading merge failures. The file ownership map ensures no overlap between cards — explicit staging is sufficient isolation. The stash pattern in AGENTS.md applies ONLY to the main repo working tree.
|
|
23
|
+
- **If commit fails**:
|
|
24
|
+
0. **"Nothing to commit" is NOT a failure** — if the error is `nothing to commit, working tree clean`, all changes were already committed by a prior step (e.g. doc-reviewer committed its own docs, or a Phase 3.7 fix was already committed). Treat the card commit as already done, record the existing HEAD hash, and proceed to step 28 (Mark card DONE) — do NOT enter the COMMIT_LOCK / re-stage loop.
|
|
25
|
+
1. **Check for stale COMMIT_LOCK first** — parallel agents and crashed processes leave stale lock files. Always clear before retry:
|
|
26
|
+
```bash
|
|
27
|
+
rm -f <main-repo>/.git/worktrees/<worktree-name>/COMMIT_LOCK 2>/dev/null
|
|
28
|
+
```
|
|
29
|
+
2. Re-stage the same files explicitly and retry. Never run `git commit` alone after a failure — the staging area may have been altered by lint-staged auto-fixes. If lint-staged removed an "unused" variable that IS used by code in a later card, check `git diff` to see what changed, restore the needed code (explicit file write — **never `git stash pop` in a worktree**), re-stage, and retry.
|
|
30
|
+
3. **Retry cap + escalation** — retry the commit at most **2 times**. If it still fails (e.g. a pre-commit / doc-freshness rule that cannot be satisfied without human input), log the failure in `## Issues & Flags` as `[COMMIT-BLOCKED] <error>` and invoke `AskUserQuestion`: (a) fix the blocking condition manually and let me retry, (b) hand off the worktree intact, (c) abandon this card and continue the batch. Do NOT loop indefinitely and do NOT silently proceed to step 28 with an uncommitted card.
|
|
31
|
+
- The Claude Code pre-commit hook automatically skips for worktree commits (Husky handles checks natively in the worktree).
|
|
32
|
+
28. **Mark card DONE (MANDATORY — do NOT skip)**:
|
|
33
|
+
a. Edit the backlog YAML (`${paths.backlog_dir}/<CARD-ID>.yml`): set `status: DONE`, add `completed_date: <today>`.
|
|
34
|
+
b. Add implementation notes summarizing what was built.
|
|
35
|
+
c. **Update `${paths.references_dir}/ssot-registry.md`** — add/update the entry for this card's feature area. The pre-commit doc-freshness hook BLOCKS commits that touch `${paths.backlog_dir}/` without a corresponding ssot-registry update. Always include ssot-registry.md in the same commit as the backlog YAML.
|
|
36
|
+
d. **Verify the write**: re-read the YAML file and confirm `status: DONE` is present. If not, retry the edit.
|
|
37
|
+
e. Stage BOTH the updated YAML AND ssot-registry.md, then commit (or as an immediate follow-up commit if the Phase 4 implementation commit already happened). When this produces a SECOND commit for the card, record BOTH hashes in the tracker (`commit: <impl-hash> + <done-hash>`) so traceability/bisect is unambiguous.
|
|
38
|
+
29. **Update tracker**: move card to `## Completed Cards` with commit hash(es), summary, flags, **and `card_status: DONE (verified)`**. **→ Visibility**: TaskUpdate this card's spine task → `completed` (strip any live phase suffix) and emit a Progress Bar (card change) per § "Progress Visibility".
|
|
39
|
+
|
|
40
|
+
### Sub-agent failure protocol (since v3.28.3)
|
|
41
|
+
|
|
42
|
+
If any sub-agent **crashes or errors** during any phase, follow this 4-step protocol. The pre-v3.28.3 wording ("attempt the work yourself directly") was being used as a shortcut to bypass delegation rules even when no agent had crashed — that escape valve is closed.
|
|
43
|
+
|
|
44
|
+
1. **Log the failure** in the tracker with the full error trace (under `## Issues & Flags`, prefix `[AGENT-CRASH]`).
|
|
45
|
+
2. **Retry the same agent once**. Transient errors (network, rate-limit, race) are common; a single retry resolves most.
|
|
46
|
+
3. **If retry fails AND the fix is in a domain-override domain** (`doc`, `security`, `migration` — see "Domain-Override Domains" sub-section): **STOP the pipeline**, log in `## Issues & Flags`, and invoke `AskUserQuestion` with options (a) skip the finding, (b) hand off to user, (c) escalate to a different agent type. **NEVER** fall through to inline orchestrator apply for these domains. The whole point of delegation here is that the orchestrator does not have the right system prompt — bypassing on crash defeats the rule.
|
|
47
|
+
4. **If retry fails AND the fix is non-domain-override**: orchestrator MAY apply inline, but MUST log a Fix Application Log row with `applied_by=orchestrator-fallback` + `reason=<agent>-crash-retry-failed` so the telemetry surfaces frequency. If this happens often for the same agent, that agent's reliability is the problem, not the protocol.
|
|
48
|
+
|
|
49
|
+
Never block the pipeline indefinitely — recover and continue per the rules above. AskUserQuestion in step 3 is bounded by normal user response time.
|
|
50
|
+
|
|
51
|
+
### Phase 5 — Context Clean & Continue
|
|
52
|
+
30. Archive the card from Active Code Context in `${paths.references_dir}/project-status.md`.
|
|
53
|
+
31. **CONTEXT HYGIENE**: After updating the tracker, stop referencing this card's details. From this point forward do NOT pull this card's code, file contents, or review findings back into your messages — the tracker summary is the only carry-over; if you need a detail, Read the tracker (or the on-disk findings/gate file) at the point you need it. NOTE: this is a *reference-hygiene* instruction, not token reclamation — a prompt cannot make the model "forget" (see § "Context economy"). The real lever is upstream: because the § "Context economy" rules kept this card's bulk (gate logs, diffs, whole files, baselines) OUT of your inline context in the first place, there is little to carry over. If the harness auto-compacts at a card boundary, recover via the tracker per § "Context Tracking".
|
|
54
|
+
32. **Update tracker**: clear `## Current Card`, move to next pending card.
|
|
55
|
+
33. **Move to the next card** — restart the per-card pipeline at **Phase 1 (Claim & Context)** for the next pending card in `## Card Queue`. Do NOT re-run Phase 0 (workspace hygiene runs once per batch) and do NOT re-run Pre-flight worktree setup (the worktree already exists). When all cards in the queue are done, proceed to **Final review**.
|
|
56
|
+
|
|
57
|
+
---
|
|
@@ -0,0 +1,284 @@
|
|
|
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 2.5 — Implementation Completeness Check (MANDATORY)
|
|
6
|
+
|
|
7
|
+
Before triggering any review, you MUST verify that the coder agent implemented **every requirement and acceptance criterion** in the backlog card. This is a blocking gate — do NOT proceed to Phase 3 with unimplemented items.
|
|
8
|
+
|
|
9
|
+
**Step-by-step**:
|
|
10
|
+
|
|
11
|
+
0. **Conditional requirements pre-scan** (BLOCKING — before building the main checklist):
|
|
12
|
+
|
|
13
|
+
Scan the card's `requirements`, `acceptance_criteria`, `unknowns`, and `notes` fields for
|
|
14
|
+
conditional language patterns: "verify if / verify whether", "if missing / if not present /
|
|
15
|
+
if not found / if not already", "if already exists / if already included", "leave TODO /
|
|
16
|
+
add TODO / leave a note", "add if needed / create if missing", "add support if missing".
|
|
17
|
+
|
|
18
|
+
For each match, classify as a **binary-outcome item** and verify:
|
|
19
|
+
a. Positive branch: grep changed files for the implementation.
|
|
20
|
+
b. Negative branch (B-missing): grep codebase for `// TODO [CARD-ID]:` at the relevant location.
|
|
21
|
+
|
|
22
|
+
If NEITHER branch artifact exists → classify as `Missing` (not Partial) and trigger the
|
|
23
|
+
gap-resolution fix agent sub-loop immediately for these items (before continuing the checklist).
|
|
24
|
+
**Loop-counter scope**: the max-2 gap-resolution cap is tracked PER ITEM, not per phase. The
|
|
25
|
+
step-0 pre-scan and the step-5 main loop share the same per-item budget — an item that consumed
|
|
26
|
+
both retries here is NOT given two fresh retries at step 5; an item never touched here keeps its
|
|
27
|
+
full budget at step 5. This prevents both over-fixing (4 spawns) and starvation (0 retries left).
|
|
28
|
+
|
|
29
|
+
Also check: if the card has conditional requirements but the completion report has no
|
|
30
|
+
`conditional_items` section → flag as `Missing` (the coder must document the branch taken).
|
|
31
|
+
|
|
32
|
+
1. **Update tracker**: phase = "2.5-completeness".
|
|
33
|
+
2. Re-read the backlog card (`requirements`, `acceptance_criteria`, `unknowns`, and `definition_of_done` fields).
|
|
34
|
+
3. Build a checklist — one row per item:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
## Completeness Check — <CARD-ID>
|
|
38
|
+
| # | Requirement / Criterion | Status | Evidence |
|
|
39
|
+
|---|------------------------|--------|----------|
|
|
40
|
+
| 1 | [requirement text] | Done / Missing / Partial | [file:line or "not found"] |
|
|
41
|
+
| 2 | [acceptance criterion] | Done / Missing / Partial | [file:line or "not found"] |
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
4. For each item, verify by **reading the actual implementation code** — but read **narrowly** (per
|
|
45
|
+
§ "Context economy" → Targeted Reads): use the coder completion report's `evidence: file:line` as
|
|
46
|
+
the index, then `Grep` (or `Read` with a tight `offset`/`limit` around that line) for the specific
|
|
47
|
+
symbol/route/field — do NOT Read whole files into context to confirm one item. The report is your
|
|
48
|
+
index of WHERE to look; you still verify independently (do NOT trust its `status` alone), just
|
|
49
|
+
without pulling entire files inline.
|
|
50
|
+
|
|
51
|
+
**Verification depth per requirement type:**
|
|
52
|
+
- **"Create endpoint/route"** → verify: route file exists, handler has correct HTTP method,
|
|
53
|
+
request validation present, response shape matches requirement, auth middleware applied.
|
|
54
|
+
- **"Add UI component/page"** → verify: component file exists, renders the required elements,
|
|
55
|
+
handles loading/error/empty states if specified, is wired into the page/layout.
|
|
56
|
+
- **"Add field/collection"** → verify: type definition updated, field used in read AND write
|
|
57
|
+
paths, validation present if specified.
|
|
58
|
+
- **"Integrate with X"** → verify: import exists, function is called with correct parameters,
|
|
59
|
+
error handling present.
|
|
60
|
+
- **Data fields completeness** → if card has `data_fields` block:
|
|
61
|
+
- For each `status: existing` field: grep the changed files to confirm the field name is
|
|
62
|
+
referenced in the implementation. A declared-but-unused field is a red flag (wrong name
|
|
63
|
+
or dead code). Log in checklist as Partial if not found.
|
|
64
|
+
- For each `status: new` field: verify the field is BOTH written (setter/creator path)
|
|
65
|
+
AND read (getter/reader path) in the changed files.
|
|
66
|
+
- For each `status: modified` field: verify old-name references are removed and
|
|
67
|
+
new-name references exist.
|
|
68
|
+
- **DB compound query** → verify: if the card has a `db_indexes` (or legacy
|
|
69
|
+
`firestore_indexes`) field, check that EVERY listed index has been shipped to
|
|
70
|
+
the artifact matching `stack.database`:
|
|
71
|
+
- `firestore` → entries exist in `firestore.indexes.json` (match collection +
|
|
72
|
+
fields + order); also grep the query code to confirm `where()` + `orderBy()`
|
|
73
|
+
field names match the index definition exactly. Missing index = CRITICAL
|
|
74
|
+
(runtime 500 FAILED_PRECONDITION).
|
|
75
|
+
- `postgres`/`supabase`/`mysql`/`sqlite` → a migration file exists declaring
|
|
76
|
+
the index (or `prisma/schema.prisma` `@@index([...])`); grep the query to
|
|
77
|
+
confirm the column names match. Missing migration = CRITICAL (silent
|
|
78
|
+
Seq Scan in production on hot path).
|
|
79
|
+
- `mongodb` → `createIndex` call exists in the bootstrap script (or migration);
|
|
80
|
+
compound field order in the call matches equality → range → sort in the query.
|
|
81
|
+
Missing = HIGH (no immediate error, but slow aggregation under load).
|
|
82
|
+
- `dynamodb` → the GSI/LSI is declared in the IaC table definition AND the
|
|
83
|
+
query uses the GSI name via `IndexName`. Missing = CRITICAL (throttle on
|
|
84
|
+
hot partition).
|
|
85
|
+
|
|
86
|
+
If the completion report has `items_skipped` that is not "none", immediately flag those
|
|
87
|
+
items as Missing regardless of the agent's justification.
|
|
88
|
+
|
|
89
|
+
- **[UI-ONLY] Design-system conformance** → run ONLY when `briefing = "ui-expert"` from step 6b
|
|
90
|
+
AND `features.has_design_system: true` in `baldart.config.yml`:
|
|
91
|
+
- Grep the changed files for hardcoded design values that bypass the registry:
|
|
92
|
+
hex colors (`#[0-9a-fA-F]{3,8}`), `rgb(`/`rgba(`, `box-shadow:` with inline
|
|
93
|
+
offsets/blurs, `border-radius:` with px/rem literals, `font-size:` with raw
|
|
94
|
+
px/rem (outside the type scale), `padding`/`margin` with raw px (outside the
|
|
95
|
+
spacing scale). Each hit on a NEW or MODIFIED line = Partial — the value
|
|
96
|
+
should come from a token, not a literal.
|
|
97
|
+
- Verify the completion report includes the `design_system_coherence:` block
|
|
98
|
+
required by the UI-ONLY briefing. Missing block = Missing (orchestrator
|
|
99
|
+
cannot confirm Post-Intervention Coherence Check ran).
|
|
100
|
+
- For each new primitive declared by the report (or detected via Grep for new
|
|
101
|
+
components in `${paths.components_primitives}`), verify the matching
|
|
102
|
+
`${paths.design_system}/components/<Name>.md` spec was created in the same
|
|
103
|
+
commit. Missing spec = Partial — fix by re-spawning `ui-expert` with the
|
|
104
|
+
narrow instruction "ship the component spec for <Name> per
|
|
105
|
+
design-system-protocol.md".
|
|
106
|
+
- For each token change declared by the report, verify the entry exists in
|
|
107
|
+
`${paths.design_system}/tokens-reference.md`. Missing entry = Partial.
|
|
108
|
+
- If `features.has_design_system: false`, log "DS conformance skipped — flag is false" and continue.
|
|
109
|
+
|
|
110
|
+
5. Classify each item:
|
|
111
|
+
- **Done** — code exists AND satisfies the FULL scope of the requirement (not just partial).
|
|
112
|
+
- **Partial** — some code exists but the criterion is not fully satisfied (e.g., UI renders but no error state, endpoint exists but wrong response shape).
|
|
113
|
+
- **Missing** — no evidence found in the codebase, OR the coder agent explicitly skipped it.
|
|
114
|
+
|
|
115
|
+
**Gap resolution** (for Partial and Missing items):
|
|
116
|
+
|
|
117
|
+
- Spawn a **targeted fix coder agent** with:
|
|
118
|
+
- The exact list of unimplemented items (copy the checklist rows)
|
|
119
|
+
- The file-ownership restrictions from `## File Ownership Map`
|
|
120
|
+
- The instruction: "Implement ONLY these missing items. Do not refactor or expand scope."
|
|
121
|
+
- After the fix agent completes, re-run the static gates the fix could have broken — `npm run lint`, `npx tsc --noEmit` (when `stack.language` includes typescript), and `npm test` — not just build + lint (a gap-fix can introduce a type error or break a test that the earlier Phase 2 gate had passed). Redirect each to `/tmp/<gate>-<CARD-ID>.txt` per § "Context economy" (never inline).
|
|
122
|
+
- Re-verify each fixed item against the code — do NOT trust the agent's self-report.
|
|
123
|
+
- Repeat this sub-loop up to **2 times** (per-item budget, shared with step 0 — see "Loop-counter scope"). After 2 loops, if items remain Partial or Missing:
|
|
124
|
+
- Log in `## Issues & Flags`: list each unimplemented requirement.
|
|
125
|
+
- Ask the user whether to proceed to review despite the gap or stop.
|
|
126
|
+
- **Handoff to Phase 2.5b**: any AC that is still `Partial` or `Missing` at this point (whether the user said "proceed" or not) MUST be seeded into the Phase 2.5b AC Closure Ledger as a `deferred` row with `User-approved? pending` — the user's "proceed to review" answer here does NOT auto-approve the deferral; Phase 2.5b Step 4 still asks per-AC. Do NOT let "proceed" silently mark these ACs `implemented`.
|
|
127
|
+
|
|
128
|
+
5b. **API contract check**:
|
|
129
|
+
- From `git diff --name-only "$TRUNK...HEAD"`, identify `route.ts` files that existed before this card (MODIFIED) vs newly added (NEW).
|
|
130
|
+
- **NEW routes** are exempt from the breaking-change comparison (no prior contract to violate) BUT must still be checked for a **path collision**: read `${paths.references_dir}/api/index.md` and confirm the new route's URL path is not already documented under a different module. A collision → `[API-CONTRACT] PATH-COLLISION` in `## Issues & Flags` (BLOCKER — a second handler for a documented path).
|
|
131
|
+
- For each MODIFIED route:
|
|
132
|
+
a. Derive the API module from path (e.g., `src/app/api/v1/booking/[id]/route.ts` → `booking`).
|
|
133
|
+
b. Read `${paths.references_dir}/api/<module>.md` (or subdirectory match).
|
|
134
|
+
c. Read the modified route, extract response shape from `NextResponse.json()` calls.
|
|
135
|
+
d. Compare against documented schema.
|
|
136
|
+
e. Flag: removed fields or changed types → `[API-CONTRACT] BREAKING` in `## Issues & Flags` (BLOCKER).
|
|
137
|
+
Added fields only → `[API-CONTRACT] ADDITIVE` (informational).
|
|
138
|
+
No doc found → `[API-CONTRACT] NO-DOC` (informational).
|
|
139
|
+
|
|
140
|
+
5c. **Reference-aliasing mutation check** (MANDATORY — deterministic detector, reference-aliasing mutation prevention).
|
|
141
|
+
|
|
142
|
+
Detect call sites that pair a helper invocation with in-place mutation of an input array
|
|
143
|
+
without an identity guard. Anti-pattern (the reference-aliasing mutation family):
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
const result = filterHelper(input, ...);
|
|
147
|
+
input.length = 0; // ← wipes both input AND result when result === input
|
|
148
|
+
input.push(...result); // ← pushes zero elements (result was just emptied)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
This detector targets TypeScript/JavaScript array-mutation patterns. **Guard: run it only when `stack.language` includes `typescript` or `javascript`.** For other languages it does not apply — log `[ALIAS-MUTATION] skipped — stack.language not ts/js` and continue (do NOT report a non-TS diff as "clean", which would imply the check ran).
|
|
152
|
+
|
|
153
|
+
Run this exact bash block in the worktree (`$TRUNK` = the trunk branch resolved in Phase 0):
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
cd <worktree-path>
|
|
157
|
+
CHANGED_TS="$(git diff --name-only "$TRUNK...HEAD" -- '*.ts' '*.tsx' '*.js' '*.jsx' 2>/dev/null \
|
|
158
|
+
|| git diff --name-only HEAD~1..HEAD -- '*.ts' '*.tsx' '*.js' '*.jsx')"
|
|
159
|
+
|
|
160
|
+
ALIAS_HITS=()
|
|
161
|
+
for f in $CHANGED_TS; do
|
|
162
|
+
[ -f "$f" ] || continue
|
|
163
|
+
# Heuristic: find lines matching `arr.length = 0` followed within 3 lines by `arr.push(...result)`.
|
|
164
|
+
# Capture the variable name; flag for human/agent review.
|
|
165
|
+
python3 - "$f" <<'PY'
|
|
166
|
+
import re, sys
|
|
167
|
+
src = open(sys.argv[1]).read().splitlines()
|
|
168
|
+
for i, line in enumerate(src):
|
|
169
|
+
m = re.search(r'(\w+)\.length\s*=\s*0', line)
|
|
170
|
+
if not m: continue
|
|
171
|
+
var = m.group(1)
|
|
172
|
+
# Look back 5 lines for a const/let assignment from a function call returning to a different name,
|
|
173
|
+
# then forward 3 lines for `var.push(...other)`.
|
|
174
|
+
back = "\n".join(src[max(0,i-5):i])
|
|
175
|
+
fwd = "\n".join(src[i+1:i+4])
|
|
176
|
+
assign = re.search(rf'const\s+(\w+)\s*=\s*\w+\([^)]*\b{re.escape(var)}\b', back)
|
|
177
|
+
push = re.search(rf'{re.escape(var)}\.push\(\.\.\.(\w+)\)', fwd)
|
|
178
|
+
if assign and push and assign.group(1) == push.group(1):
|
|
179
|
+
print(f"{sys.argv[1]}:{i+1}: ALIAS-MUTATION candidate — '{var}.length = 0' followed by '{var}.push(...{push.group(1)})' where {push.group(1)} comes from a call that received {var}")
|
|
180
|
+
PY
|
|
181
|
+
done
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
For each hit, classify by reading 10 lines of context around the match:
|
|
185
|
+
|
|
186
|
+
- **Guarded** — an `if (<assignedName> !== <var>)` check wraps the reset+push block. SAFE. Log `[ALIAS-MUTATION] guarded` (informational, no action).
|
|
187
|
+
- **Defensively cloned** — the helper was called with `[...var]` or `var.slice()` instead of `var`. SAFE. Log `[ALIAS-MUTATION] cloned` (informational).
|
|
188
|
+
- **Helper always returns new array** — read every `return` in the helper. If ALL paths return `[...candidates]` / `candidates.filter(...)` / a new array literal, identity collision is impossible. SAFE. Log `[ALIAS-MUTATION] helper-immutable` (informational).
|
|
189
|
+
- **Un-guarded** — none of the above. Flag `[ALIAS-MUTATION] BLOCKER` in `## Issues & Flags` with file:line and the captured pattern.
|
|
190
|
+
|
|
191
|
+
For each `[ALIAS-MUTATION] BLOCKER`:
|
|
192
|
+
|
|
193
|
+
- Spawn a targeted fix `coder` agent with the exact file:line and instruction: "Add identity guard `if (result !== input) { ... }` around the in-place reset, OR clone the input with `[...input]` before passing it to the helper. Add a regression test on the caller pattern, co-located with the helper's existing tests following this project's test convention (e.g. a `*-reference` negative-control test next to the helper's test file). Read `agents/coding-standards.md § Reference-Aliasing Mutation Patterns` before implementing."
|
|
194
|
+
- Re-run the detector after the fix. The hit MUST classify as Guarded, Cloned, or helper-immutable. Repeat **max 2 times**.
|
|
195
|
+
- If still un-guarded after 2 loops → log in `## Issues & Flags` and ask the user.
|
|
196
|
+
|
|
197
|
+
Rationale (reference-aliasing incident class): a helper that returns its same input reference on some code paths, combined with a call site that did `arr.length = 0; arr.push(...result)` without an identity guard, silently wiped the result. The helper passed unit tests in isolation; the bug only manifested end-to-end. This detector closes that detection gap. Full policy: `agents/coding-standards.md § Reference-Aliasing Mutation Patterns`.
|
|
198
|
+
|
|
199
|
+
5d. **Caller-pattern test coverage check** (MANDATORY — when card introduces or modifies an exported helper consumed by 1+ caller with in-place mutation).
|
|
200
|
+
|
|
201
|
+
If the card's diff includes BOTH (a) an `export function` / `export const` declaration in a shared-library file (under `${paths.lib}` if defined, else the project's lib/util dir) AND (b) at least one call site in another file that mutates an input array in place (detected via the bash block in 5c), verify that a test file exists that exercises the **caller pattern** — not only the helper in isolation.
|
|
202
|
+
|
|
203
|
+
Required test characteristics:
|
|
204
|
+
|
|
205
|
+
- At least one case asserts the post-call state of the input array (e.g. `assert.strictEqual(arr.length, N)` after the helper invocation).
|
|
206
|
+
- At least one **negative-control case** documents the failure mode that would occur if the identity guard / defensive clone were removed.
|
|
207
|
+
|
|
208
|
+
If the test is missing:
|
|
209
|
+
|
|
210
|
+
- Spawn a targeted fix `coder` agent to write the test. The test MUST live in a file co-located with similar helpers, following this project's test convention (do NOT invent a directory — mirror where the helper's existing tests live).
|
|
211
|
+
- This is BLOCKING for Phase 4 commit when the helper is on a high-risk path (a path listed in `paths.high_risk_modules` in `baldart.config.yml`, e.g. auth / payments / a shared scoring-or-ranking primitive). On non-high-risk paths it's a HIGH-severity flag but the orchestrator may proceed and defer to `/codexreview`.
|
|
212
|
+
|
|
213
|
+
Rationale: in the originating incident, the helper's caller pattern was never tested (tests were deferred to a later E2E card); the helper passed in isolation while the caller-side aliasing bug shipped. A caller-pattern test at the helper-card level catches this class earlier.
|
|
214
|
+
|
|
215
|
+
6. **Update tracker**: phase = "2.5-completeness DONE", log result (PASS / GAPS REMAIN + count).
|
|
216
|
+
|
|
217
|
+
### Phase 2.5b — AC-Closure Gate (BLOCKING — Scope Closure Discipline)
|
|
218
|
+
|
|
219
|
+
This gate enforces `framework/agents/workflows.md § Scope Closure Discipline` at the per-card level. It runs after Phase 2.5's gap-resolution loops have settled and BEFORE Phase 2.55 (Simplify). It is non-skippable.
|
|
220
|
+
|
|
221
|
+
**Why this exists**: Phase 2.5's fix loops handle items an agent can implement autonomously. They do NOT handle the case where the implementer (or you, the orchestrator) decides — under context pressure or perceived complexity — that an AC is "good enough as is" or "already covered by an existing component". Burying that decision in the card YAML's `implementation_notes`, in a commit message, or in a final recap is a silent scope reduction. The decision belongs to the user.
|
|
222
|
+
|
|
223
|
+
**Step-by-step**:
|
|
224
|
+
|
|
225
|
+
1. **Update tracker**: phase = "2.5b-ac-closure".
|
|
226
|
+
|
|
227
|
+
2. **Build the AC Closure Ledger** — one row per `acceptance_criteria` entry from the card YAML (NOT requirements — only the AC list, because ACs are the user-facing contract):
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
## AC Closure Ledger — <CARD-ID>
|
|
231
|
+
| AC# | Text (verbatim) | Status | Evidence (file:line) | User-approved? |
|
|
232
|
+
|-----|-----------------|--------|----------------------|----------------|
|
|
233
|
+
| AC-1 | [text] | implemented | src/x.ts:42 | n/a |
|
|
234
|
+
| AC-2 | [text] | deferred | n/a | pending |
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Status enum: `implemented` | `deferred`. The Phase 2.5 categories map as follows: `Done` → `implemented`; `Partial` or `Missing` (after gap-resolution exhausted retries) → `deferred`. There is no third option — an AC is either in the diff or it is being deferred.
|
|
238
|
+
|
|
239
|
+
3. **Rationalization scan (BLOCKING for every `deferred` row)** — read the coder's completion report and the card's `implementation_notes`. If the justification for a `deferred` AC matches any of the patterns below, classify the row as `RATIONALIZATION_NEEDS_PROOF`:
|
|
240
|
+
|
|
241
|
+
- "covered by <X>" / "already covers" / "existing <X> handles" / "<X> already does"
|
|
242
|
+
- "implicit in <X>" / "no longer needed" / "redundant with <X>"
|
|
243
|
+
- "out of scope of this card" (when the AC is clearly listed in the card YAML)
|
|
244
|
+
|
|
245
|
+
For each `RATIONALIZATION_NEEDS_PROOF` row, the orchestrator MUST verify by reading `<X>` and producing a line-for-line scope mapping between the AC text and the alleged coverage. The mapping goes in the tracker under `## Rationalization Verification`. If the mapping does not hold (or cannot be produced confidently), the row stays `deferred` and proceeds to Step 4 — the rationalization does NOT auto-approve the deferral.
|
|
246
|
+
|
|
247
|
+
4. **User gate (BLOCKING `AskUserQuestion` — one per `deferred` AC that is not pre-approved)**:
|
|
248
|
+
|
|
249
|
+
For each `deferred` row whose `User-approved?` is `pending`, invoke `AskUserQuestion` with:
|
|
250
|
+
- Question: `"AC-<N> of <CARD-ID> non implementata. Testo verbatim: '<AC text>'. Motivazione dell'implementer: '<reason or 'nessuna — silent skip'>'. Come procedo?"`
|
|
251
|
+
- Options (max 4):
|
|
252
|
+
1. **"Implementa adesso"** — spawn a targeted fix `coder` agent scoped to this card's MAY EDIT files (from `## File Ownership Map`) with the instruction "Implement ONLY AC-<N>: '<AC text>'. Do not refactor or expand scope." Re-run Phase 2.5 verification on the resulting diff — **including the mandatory sub-steps 5b (API contract), 5c (alias-mutation), 5d (caller-pattern test)** if the fix touched a route, an exported helper, or a call site (a single-AC fix can still introduce these). **Hard cap: 2 attempts on the same AC.** On the 2nd failure, do NOT re-offer "Implementa adesso" — re-invoke `AskUserQuestion` with only options 2/3/4 (approve deferral / follow-up card / stop), so the loop cannot recur unbounded.
|
|
253
|
+
2. **"Approva il deferral"** — record `[USER-APPROVED DEFERRAL] <today>: <user-supplied reason>` on its own line in the card's `implementation_notes`. Mark the row `User-approved? yes`.
|
|
254
|
+
3. **"Sposta su follow-up card"** — create a backlog stub at `${paths.backlog_dir}/<CARD-ID>-followup-AC<N>.yml` with `status: TODO` AND the minimum fields the Pre-flight gate (step 1b) requires, so a future `/new` run can pick it up without halting: a non-empty `requirements` (≥1, derived from the AC), a non-empty `acceptance_criteria` (≥1, the verbatim AC text), and a non-empty `files_likely_touched` (≥1, carried from the parent card's ownership map for this AC). Mark the row `User-approved? yes (follow-up: <new-card-id>)`. Do NOT proceed to Phase 2.55 until the follow-up file exists on disk and passes the step-1b field check.
|
|
255
|
+
4. **"Ferma il batch"** — halt the orchestrator, leave the worktree intact, log the reason in `## Issues & Flags`. Do NOT commit.
|
|
256
|
+
|
|
257
|
+
Do NOT batch the question across multiple ACs — one `AskUserQuestion` per AC, so the user sees each AC's text in isolation. Issue the questions sequentially.
|
|
258
|
+
|
|
259
|
+
5. **`implementation_notes` deferral audit (cheap text grep — also BLOCKING)** — before exiting the phase, scan the card YAML's `implementation_notes` field (post-edits, including any text added during this phase) for any of these phrases:
|
|
260
|
+
|
|
261
|
+
- `deferred` / `deferral` / `defer to`
|
|
262
|
+
- `out of scope` / `scope cut`
|
|
263
|
+
- `covered by` / `already handles` / `redundant`
|
|
264
|
+
- `skipped` / `dropped`
|
|
265
|
+
|
|
266
|
+
When scanning a line, FIRST check for the `[USER-APPROVED DEFERRAL]` prefix; if present AND the corresponding AC row has `User-approved? yes`, the line is RESOLVED — do NOT re-match the rationalization keywords inside the user-supplied reason text (otherwise a freeform reason like "approve deferral: existing component already handles this" would re-flag an already-approved AC). Only lines WITHOUT the prefix (or whose AC row is not `yes`) are silent deferrals that escaped Step 4 — for those, trigger the Step 4 `AskUserQuestion` for the AC referenced (or for "the unspecified AC implied by this note" if no AC is named, asking the user to clarify which AC the note refers to). **If Step 5 triggers any new Step 4 question, fully resolve it (loop back into Step 4) BEFORE running Step 6** — do NOT write `2.5b-ac-closure DONE` while a triggered question is still open.
|
|
267
|
+
|
|
268
|
+
6. **Update tracker** (only after Steps 3–5 have fully settled, including any Step-5-triggered Step-4 question): phase = "2.5b-ac-closure DONE". Persist the AC Closure Ledger AND the Rationalization Verification (if any) in the tracker. Log counts on one line:
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
ac-closure: implemented=N | user-approved deferrals=M | follow-up cards created=K | rationalization-verifications passed=L
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The gate exits PASS only when every ledger row is either `implemented` or `deferred` with `User-approved? yes`. Phase 2.55 (Simplify) MUST NOT start until this gate exits PASS.
|
|
275
|
+
|
|
276
|
+
#### Context-pressure exception (still BLOCKING — no escape)
|
|
277
|
+
|
|
278
|
+
If at any point in Phases 2 / 2.5 / 2.5b you detect context-window pressure (your context is being summarized, you have ≥ 1 forced compaction, you are racing through verification, you are tempted to "just mark this AC as covered"), do NOT compensate by skipping ACs. The correct response is:
|
|
279
|
+
|
|
280
|
+
1. Stop the current card's pipeline.
|
|
281
|
+
2. Write the current state to the tracker under `## Issues & Flags` with the prefix `[CONTEXT-PRESSURE]` (which Phase 2 finished, which ACs are open, which files are dirty).
|
|
282
|
+
3. Invoke `AskUserQuestion` with options: (a) finish remaining ACs in a fresh `/new` session that resumes from the tracker, (b) commit the complete ACs and route the rest through this gate's Step 4, (c) hand off the worktree intact to the user.
|
|
283
|
+
|
|
284
|
+
Auto Mode does NOT override this rule. "Bias toward proceeding" applies to routine decisions ("should I rerun this check?", "should I confirm this safe rename?"), NEVER to scope reduction.
|