baldart 4.11.0 → 4.12.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 +18 -0
- package/VERSION +1 -1
- package/framework/.claude/skills/new/SKILL.md +73 -34
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ All notable changes to BALDART will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [4.12.0] - 2026-06-04
|
|
9
|
+
|
|
10
|
+
**`/new` non gonfia più il context dell'orchestrator su long-run — il bulk content (log dei gate, `git diff`, file interi, baseline) non scorre più nel canale inline dell'orchestrator: vive su disco e viaggia per *path*.** Sintomo riportato dall'utente: su batch lunghi il consumo si impennava per il context bloat. Una prima ipotesi (i *finding* delle review che tornano inline + un card-runner sub-agent isolato + un "context purge" da rinforzare) è stata **sottoposta a review avversariale e refutata**: (1) l'orchestrator DEVE leggere il contenuto dei finding ai punti-decisione (domain-override partition, AC-Closure, `NEEDS_MANUAL_CONFIRMATION`, merge/dedup del Final gate) → un contratto "verdict-only" che li nasconde romperebbe la skill e i consumer condivisi (`/prd`, `/codexreview`); (2) un card-runner sub-agent non può ospitare i gate utente né garantire il nested-spawn dei reviewer; (3) un "compaction-lossless checkpoint" non regge (`/tmp` è single-point-of-failure, l'auto-compact non è controllabile da una skill). La verifica sul codice ha trovato che **il vero driver del bloat è il bulk content reso inline nei tool-result dell'orchestrator stesso**, non i finding: output dei gate `lint`/`tsc`/`test`/`build` (resi inline da `| tee`, ~40-50%), `git diff` completo passato inline ai simplify agent (~25-30%), Read di file interi nel completeness check, e baseline concatenati nel Final F.3. **MINOR** (cambia il comportamento di esecuzione di `/new`; nessuna nuova capability, nessun nuovo agente, nessuna chiave `baldart.config.yml`, nessun contratto di return degli agent toccato — la schema-propagation rule non si applica).
|
|
11
|
+
|
|
12
|
+
> **Why.** L'orchestrator di `/new` è un unico contesto long-lived su tutto il batch: ogni byte che rende inline (Bash tool-result, prompt che compone, file che Read-a) resta in finestra per l'intero run, e nessun "purge" via prompt recupera token. La fix attacca la radice — **tenere il bulk fuori dal canale inline** — senza toccare ciò che l'orchestrator può leggere ai punti-decisione (i finding restano file-resident e leggibili on-demand). Onestà sui limiti: questo riduce il *rate di accumulo* (stima ~40-50% sul footprint dominante), non azzera la crescita del context; il bound vero richiederebbe isolamento per-card a livello di harness, fuori dalla portata di una skill.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **`framework/.claude/skills/new/SKILL.md`** — nuova sezione SSOT **`## Context economy (MANDATORY)`** (HARD RULE in 5 punti: gate-output discipline, diff-to-disk, findings file-resident, pass-paths-not-concatenations, targeted Reads). Applicata ai siti che la violavano:
|
|
17
|
+
- **Gate bash (Phase 2 step 8)** — `cmd 2>&1 | tee /tmp/x.txt` → `cmd > /tmp/x.txt 2>&1; echo "<gate>:$?"`: l'output completo resta su disco, inline solo l'exit code; su fallimento si legge un estratto *bounded* (`tail -n 30`), mai il log intero. Step 9 passa al fix agent il **path** del log, non il blob.
|
|
18
|
+
- **Tutti i re-run di gate foreground** (gap-fix Phase 2.5, Phase 2.55 step 5, Phase 3 step 16, pre-commit Phase 4, Final F.5, team D.1/D.3b) — pointer alla disciplina (redirect a disco, mai inline).
|
|
19
|
+
- **`git diff` (Phase 2.55 step 2-3)** — `git diff > /tmp/diff-<CARD>.txt`; i 3 simplify agent ricevono il **path** e leggono il diff da soli, niente «full diff» nei prompt. Team D.3b allineato.
|
|
20
|
+
- **Blocchi Codex (Phase 0 cross-card audit, Final F.3)** — `2>&1 | tee "$FILE"` → `> "$FILE" 2>&1` (niente copia inline; il file si riempie comunque in streaming per il polling F.4, commento aggiornato).
|
|
21
|
+
- **Final F.3 baseline** — `${ARCH_BASELINE}` (contenuti concatenati) → `${ARCH_BASELINE_PATHS}` (lista di path che Codex Read-a on-demand); F.2 non concatena più i per-card baseline.
|
|
22
|
+
- **Completeness check (Phase 2.5 step 4)** — Read *mirati* (grep con `offset`/`limit` stretti attorno al `file:line` del completion report) invece di Read di file interi.
|
|
23
|
+
- **Progress Bar** — blocco markdown completo solo alle boundary pesanti (card/wave/gate-decision/STOP); il movimento di fase intra-card si mostra via Task spine sub-state, non ri-emettendo la tabella a ogni fase.
|
|
24
|
+
- **Phase 5 step 31** — il "CONTEXT PURGE" è ri-etichettato come *reference-hygiene* (non token-reclamation, che un prompt non può ottenere); il leverage reale è upstream (la § Context economy tiene il bulk fuori dal context fin dall'inizio).
|
|
25
|
+
|
|
8
26
|
## [4.11.0] - 2026-06-04
|
|
9
27
|
|
|
10
28
|
**Gli overlay non costringono più a riconciliare a ogni `baldart update` — la VERSION non è più incisa nell'identità dei file generati né usata come segnale di drift quando il base file non è cambiato.** Sintomo riportato dall'utente: ogni update richiedeva una riconciliazione. La verifica del sorgente ha trovato **due trigger indipendenti con la stessa radice** — la VERSION del framework veniva trattata come parte dell'identità di overlay/file-generati, ma viene bumpata a *ogni* release a prescindere dal fatto che lo specifico base file sia cambiato. **(A) churn dei file agent/command generati:** `buildMarker()` stampava `base_version=<VERSION>` nel commento `<!-- baldart-generated -->`; a ogni update la VERSION cambiava → la riga del marker cambiava anche su contenuto byte-identico → git vedeva un diff → scattava il commit `post-update reconcile` *a ogni update*. Il campo era puramente informativo (`readMarker` lo leggeva ma nessuno gate-ava la rigenerazione su di esso). **(B) falso-drift degli skill overlay:** `doctor` e `status` confrontavano il pin `base_skill_version` *direttamente* con la VERSION installata (ignorando `base_file_sha`), così ogni bump faceva apparire ogni overlay come "drifted" anche con base SKILL.md identico — mentre `overlay drift` lo faceva già correttamente SHA-first. **MINOR** (cambia il formato del marker generato; nessuna chiave `baldart.config.yml` — la fix riusa `base_file_sha` già presente).
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.12.0
|
|
@@ -167,7 +167,7 @@ In team mode the cards of a wave run in parallel: set ALL of a wave's card tasks
|
|
|
167
167
|
|
|
168
168
|
### B. Progress Bar — markdown, at transition boundaries
|
|
169
169
|
|
|
170
|
-
Append this block to your message **at
|
|
170
|
+
Append this block to your message **at the heavy transition boundaries only** (NOT on every message, and NOT on every intra-card phase change — that accumulates markdown across long autonomous runs; per § "Context economy"). A **heavy transition boundary** is any of: a **card change**, a **wave change**, **any gate decision** (resolved or skipped), and every `AskUserQuestion` / STOP. **Intra-card phase movement** (e.g. Phase 2 → 2.5 → 2.55 within the same card, with no gate decision) is shown via the **Task spine live sub-state** (TaskUpdate, § A above) — NOT by re-emitting this full markdown block each phase.
|
|
171
171
|
|
|
172
172
|
```
|
|
173
173
|
---
|
|
@@ -204,6 +204,39 @@ In **team mode** the same gates map to the per-card team sub-steps (D.3a AC-Clos
|
|
|
204
204
|
|
|
205
205
|
---
|
|
206
206
|
|
|
207
|
+
## Context economy (MANDATORY)
|
|
208
|
+
|
|
209
|
+
`/new` runs as a single long-lived orchestrator across a whole batch. Every byte the orchestrator
|
|
210
|
+
renders inline (Bash tool-results, agent prompts it composes, files it Reads) stays in its context
|
|
211
|
+
window for the **entire** run — there is no real "purge" (the soft "forget" instruction does not
|
|
212
|
+
reclaim tokens). On long batches the dominant token cost is **bulk content the orchestrator pipes
|
|
213
|
+
through its own inline channel**: gate logs, full `git diff`s, whole-file Reads, concatenated
|
|
214
|
+
baselines. Keep that bulk on disk and pass **paths**, not bodies.
|
|
215
|
+
|
|
216
|
+
> **HARD RULE — bulk content never streams inline.**
|
|
217
|
+
> 1. **Gate-output discipline.** Never run a verification gate (`lint` / `tsc` / `test` / `build`)
|
|
218
|
+
> with its output streaming inline — **never `| tee`, never a bare `npm run …`**. Always
|
|
219
|
+
> `cmd > /tmp/<gate>-<CARD-ID>.txt 2>&1` and surface only the exit code inline (`echo "<gate>:$?"`).
|
|
220
|
+
> On failure, surface a **bounded** extract only (`tail -n 30` or `grep -Ei 'error|fail' … | head -n 30`),
|
|
221
|
+
> never the whole log. Pass any fix agent the **file path**, not the inline blob.
|
|
222
|
+
> 2. **Diffs to disk.** Capture `git diff` to `/tmp/diff-<CARD-ID>.txt` and pass agents that path —
|
|
223
|
+
> never paste a full diff into a prompt or render it inline. (`git diff --name-only` file *lists*
|
|
224
|
+
> are fine — they are small.)
|
|
225
|
+
> 3. **Findings stay file-resident.** Reviewer findings already live in their report files
|
|
226
|
+
> (`/qa/*.md`, `/tmp/codexreview-*.md`). Read a findings file only at the decision point that needs
|
|
227
|
+
> it (merge / domain-route / severity tally) — do not echo finding bodies back into your messages.
|
|
228
|
+
> 4. **Pass baseline/report paths, not concatenations.** When briefing a downstream reviewer
|
|
229
|
+
> (e.g. Codex), give it the **list of baseline/report paths** to read on demand rather than
|
|
230
|
+
> inlining their concatenated contents.
|
|
231
|
+
> 5. **Targeted Reads.** When verifying code (Phase 2.5), Read only the evidence lines (grep with
|
|
232
|
+
> tight context around the `file:line` the completion report names) — not whole files.
|
|
233
|
+
>
|
|
234
|
+
> This rule is purely about the **inline channel**. It does NOT change any agent's return contract,
|
|
235
|
+
> nor what the orchestrator is allowed to read at a decision point — only that bulk arrives via a
|
|
236
|
+
> path the consumer opens itself, not via the orchestrator's own context.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
207
240
|
## Phase 0 — Workspace Hygiene Pre-flight (BLOCKING — non-skippable)
|
|
208
241
|
|
|
209
242
|
**Why this exists**: FEAT-0006 incident left the main repo with an unpushed orphan commit (`c9d41f9`) and `develop` diverged from `origin/develop` because `/new` started work on a dirty/diverged repo without surfacing the situation. This phase reconciles the main repo state BEFORE any worktree is created, and snapshots any in-progress user work so Phase 6c can restore it after the batch.
|
|
@@ -376,7 +409,7 @@ In **team mode** the same gates map to the per-card team sub-steps (D.3a AC-Clos
|
|
|
376
409
|
```bash
|
|
377
410
|
AUDIT_FILE="/tmp/codex-crosscard-<FIRST-CARD-ID>-<SESSION-ID>.md" && \
|
|
378
411
|
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)" && \
|
|
379
|
-
[ -z "$CODEX_SCRIPT" ] && echo "CODEX_NOT_FOUND"
|
|
412
|
+
[ -z "$CODEX_SCRIPT" ] && echo "CODEX_NOT_FOUND" > "$AUDIT_FILE" && exit 1; \
|
|
380
413
|
node "$CODEX_SCRIPT" task --wait "
|
|
381
414
|
Cross-card grounding check for a batch of backlog cards about to be implemented together.
|
|
382
415
|
Your job is to find conflicts BETWEEN cards that per-card reviewers would miss.
|
|
@@ -405,7 +438,7 @@ In **team mode** the same gates map to the per-card team sub-steps (D.3a AC-Clos
|
|
|
405
438
|
- **Fix**: concrete recommendation (add depends_on, force sequential, etc.)
|
|
406
439
|
|
|
407
440
|
If no cross-card conflicts: return PASS.
|
|
408
|
-
"
|
|
441
|
+
" > "$AUDIT_FILE" 2>&1
|
|
409
442
|
```
|
|
410
443
|
|
|
411
444
|
**Variable interpolation**:
|
|
@@ -885,20 +918,20 @@ For each card, execute these phases in order:
|
|
|
885
918
|
field with the exact file path and line where the TODO comment was written.
|
|
886
919
|
```
|
|
887
920
|
|
|
888
|
-
8. **Run the verification gates and CAPTURE their output** (so step 9 can pass it to a fix agent). Each is its own gate:
|
|
921
|
+
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:
|
|
889
922
|
```bash
|
|
890
923
|
cd <worktree-path>
|
|
891
|
-
npm run lint
|
|
924
|
+
npm run lint > /tmp/lint-<CARD-ID>.txt 2>&1; echo "lint:$?"
|
|
892
925
|
# tsc is its OWN blocking gate — run it ONLY when stack.language includes "typescript"
|
|
893
926
|
# (do NOT assume `npm run build` covers tsc — Next.js dev builds and many setups skip it):
|
|
894
|
-
npx tsc --noEmit
|
|
895
|
-
npm test
|
|
896
|
-
npm run build
|
|
927
|
+
npx tsc --noEmit > /tmp/tsc-<CARD-ID>.txt 2>&1; echo "tsc:$?" # guard: when stack.language includes "typescript"
|
|
928
|
+
npm test > /tmp/test-<CARD-ID>.txt 2>&1; echo "test:$?" # if tests exist
|
|
929
|
+
npm run build > /tmp/build-<CARD-ID>.txt 2>&1; echo "build:$?"
|
|
897
930
|
```
|
|
898
|
-
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 — do NOT run the gates without capture.
|
|
931
|
+
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.
|
|
899
932
|
9. **If any check fails**: categorize the error (`lint | TypeScript | test | build`), log it in the tracker as `retry-cause: <category>`.
|
|
900
933
|
**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.
|
|
901
|
-
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
|
|
934
|
+
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.
|
|
902
935
|
10. If still failing after 3 retries (or on a stuck loop), log the failure in `## Issues & Flags` and ask the user before continuing.
|
|
903
936
|
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).
|
|
904
937
|
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:
|
|
@@ -950,8 +983,12 @@ Before triggering any review, you MUST verify that the coder agent implemented *
|
|
|
950
983
|
| 2 | [acceptance criterion] | Done / Missing / Partial | [file:line or "not found"] |
|
|
951
984
|
```
|
|
952
985
|
|
|
953
|
-
4. For each item, verify by **reading the actual implementation code** (
|
|
954
|
-
|
|
986
|
+
4. For each item, verify by **reading the actual implementation code** — but read **narrowly** (per
|
|
987
|
+
§ "Context economy" → Targeted Reads): use the coder completion report's `evidence: file:line` as
|
|
988
|
+
the index, then `Grep` (or `Read` with a tight `offset`/`limit` around that line) for the specific
|
|
989
|
+
symbol/route/field — do NOT Read whole files into context to confirm one item. The report is your
|
|
990
|
+
index of WHERE to look; you still verify independently (do NOT trust its `status` alone), just
|
|
991
|
+
without pulling entire files inline.
|
|
955
992
|
|
|
956
993
|
**Verification depth per requirement type:**
|
|
957
994
|
- **"Create endpoint/route"** → verify: route file exists, handler has correct HTTP method,
|
|
@@ -1023,7 +1060,7 @@ Before triggering any review, you MUST verify that the coder agent implemented *
|
|
|
1023
1060
|
- The exact list of unimplemented items (copy the checklist rows)
|
|
1024
1061
|
- The file-ownership restrictions from `## File Ownership Map`
|
|
1025
1062
|
- The instruction: "Implement ONLY these missing items. Do not refactor or expand scope."
|
|
1026
|
-
- 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).
|
|
1063
|
+
- 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).
|
|
1027
1064
|
- Re-verify each fixed item against the code — do NOT trust the agent's self-report.
|
|
1028
1065
|
- 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:
|
|
1029
1066
|
- Log in `## Issues & Flags`: list each unimplemented requirement.
|
|
@@ -1238,8 +1275,8 @@ After completeness is verified, clean up the implementation before it reaches re
|
|
|
1238
1275
|
**Step-by-step**:
|
|
1239
1276
|
|
|
1240
1277
|
1. **Update tracker**: phase = "2.55-simplify".
|
|
1241
|
-
2.
|
|
1242
|
-
3. Launch **three agents in parallel** (single message
|
|
1278
|
+
2. Capture the current card's changes to disk — `git diff > /tmp/diff-<CARD-ID>.txt` in the worktree (**redirect, not inline** — per § "Context economy" → Diffs to disk).
|
|
1279
|
+
3. Launch **three agents in parallel** (single message). Each receives the **path** `/tmp/diff-<CARD-ID>.txt` and Reads the diff itself — do NOT paste the full diff into the prompts:
|
|
1243
1280
|
|
|
1244
1281
|
- **Reuse agent** — search the codebase for existing utilities/helpers that could replace newly written code. Flag duplicated functionality, inline logic that could use existing utils.
|
|
1245
1282
|
- **Quality agent** — flag redundant state, parameter sprawl, copy-paste with slight variation, leaky abstractions, stringly-typed code where constants/enums exist, unnecessary JSX nesting, unnecessary comments (WHAT comments, narration, task references).
|
|
@@ -1252,7 +1289,7 @@ After completeness is verified, clean up the implementation before it reaches re
|
|
|
1252
1289
|
|
|
1253
1290
|
**Telemetry (Fix Application Log)** — for EVERY finding (valid OR skipped) append one row to the tracker's `## Fix Application Log` section per the schema above. Use `domain=simplify-{reuse|quality|efficiency}` matching the originating agent. Include the `severity` trailing key. Inline: `decision=inline | applied_by=orchestrator | est_lines=<n> | severity=<HIGH|MEDIUM> | finding=<1-line>`. Delegated (domain-override): `decision=<coder|doc-reviewer> | applied_by=<coder|doc-reviewer> | est_lines=<n> | severity=<...> | finding=<1-line>`. Skipped: `decision=skipped | applied_by=- | est_lines=0 | reason=<false-positive|not-worth-addressing>`.
|
|
1254
1291
|
|
|
1255
|
-
5. After all fixes, run `npm run lint` and `npx tsc --noEmit` to confirm nothing broke.
|
|
1292
|
+
5. After all fixes, run `npm run lint` and `npx tsc --noEmit` to confirm nothing broke (redirect to disk per § "Context economy"; surface only exit code + a bounded extract on failure).
|
|
1256
1293
|
If either fails, fix the regression (up to **2 retries**). **If it still fails after 2 retries**: do NOT silently continue to Phase 2.6 with a broken tree — log the failure in `## Issues & Flags` as `[SIMPLIFY-REGRESSION]` and invoke `AskUserQuestion` (revert the simplify fixes / keep and have me fix manually / stop the card), mirroring the Phase 3.5 escalation.
|
|
1257
1294
|
|
|
1258
1295
|
6. **Update tracker**: phase = "2.55-simplify DONE", log count of fixes applied (or "clean — 0 fixes").
|
|
@@ -1423,7 +1460,7 @@ skill's Phase 1 falls back to deriving Gherkin scenarios from
|
|
|
1423
1460
|
Doc-reviewer applies all doc-domain fixes itself. The orchestrator does NOT spawn a coder for doc fixes (since v3.40.0 — `doc` is owned by `doc-reviewer`, see "Domain-Override Domains"). The only doc-reviewer output that leaves this phase unfixed is a **doc-drift→bug finding rooted in CODE** (the implementation contradicts a documented contract). Route it explicitly: if the conflicting code file matches the `security` Domain-Override match rule (`paths.high_risk_modules`) → spawn `coder` with the finding now, in this phase (a security-class code fix is not deferrable to a `light` Phase 3.7); otherwise carry the finding into the Phase 3.7 `/codexreview` input as a known code-drift bug and let the Phase 3.7 fix sub-loop apply it. Either way, append a Fix Application Log row with `domain=codex-correctness` (NOT `doc`) so telemetry attributes it as a code fix. Do NOT leave it accumulating in the tracker with no fix owner.
|
|
1424
1461
|
14. **Knowledge-corpus sync (OPTIONAL — only if the project ships a corpus-sync agent)**: There is NO shipped `obsidian-sync` agent — do NOT dispatch one (a hard dispatch to a non-existent subagent fails silently). Only when the project provides its own knowledge-corpus sync agent (declared in `.baldart/overlays/new.md`) AND doc-reviewer's findings indicate a corpus impact, invoke that agent with the listed paths after the doc fixes are applied. Otherwise skip with a one-line notice (`knowledge-corpus sync: skipped (no corpus-sync agent configured)`). Non-blocking either way.
|
|
1425
1462
|
15. **Telemetry** — after doc-reviewer returns, append one row per doc finding to `## Fix Application Log`: `3 | doc | est_lines=<n> | decision=doc-reviewer | applied_by=doc-reviewer | finding=<1-line>`. If 0 findings, append one row: `3 | doc | est_lines=0 | decision=skipped | applied_by=- | reason=no-findings`. **Phase-8 producer (named counter)** — ALSO record the per-card doc-gap counts as a structured line in `## Current Card` (carried into `## Completed Cards` at Phase 5): `doc_gaps: found=<N> fixed=<M>` where `N` = total doc findings doc-reviewer raised and `M` = those it applied. This is the single named producer for Phase 8's `doc_gaps_found` / `doc_gaps_fixed` fields — without it those fields have no upstream write and Phase 8 would hard-code zeros. (D.4a is the team-mode producer of the same counter — see Phase 7 § D.4a.)
|
|
1426
|
-
16. Run `npm run lint` and `npx tsc --noEmit` (when `stack.language` includes typescript) to verify nothing broke. If doc-reviewer touched any source-adjacent file (a `.ts`/`.tsx` helper, a co-located doc export), also run `npm run build`. If any check fails, apply the self-healing retry loop (up to 3 times, no user prompt). **If still failing after 3 retries**: do NOT fall through silently to Phase 3.5 — log `[DOC-PHASE-REGRESSION]` in `## Issues & Flags` and invoke `AskUserQuestion` (revert the doc-phase edits that broke the build / keep and fix manually / stop the card).
|
|
1463
|
+
16. Run `npm run lint` and `npx tsc --noEmit` (when `stack.language` includes typescript) to verify nothing broke (redirect to disk per § "Context economy"). If doc-reviewer touched any source-adjacent file (a `.ts`/`.tsx` helper, a co-located doc export), also run `npm run build`. If any check fails, apply the self-healing retry loop (up to 3 times, no user prompt). **If still failing after 3 retries**: do NOT fall through silently to Phase 3.5 — log `[DOC-PHASE-REGRESSION]` in `## Issues & Flags` and invoke `AskUserQuestion` (revert the doc-phase edits that broke the build / keep and fix manually / stop the card).
|
|
1427
1464
|
17. **Telemetry for the step-16 self-heal** — if the retry loop spawned any fix (a code edit to recover from a doc-phase regression), append a Fix Application Log row for it AFTER the loop settles (the step-15 doc telemetry row was written before this loop ran, so it does not capture step-16 fixes). Then update tracker: phase = "3-doc-review DONE", log doc findings count, fixes applied.
|
|
1428
1465
|
If doc-reviewer found a recurring gap, append 1-line to `## Lessons Learned`:
|
|
1429
1466
|
`DOC: <pattern>`
|
|
@@ -1645,7 +1682,7 @@ The detector (Step A) is bash + grep — guaranteed to run, no LLM skip. The dow
|
|
|
1645
1682
|
|
|
1646
1683
|
> 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.
|
|
1647
1684
|
|
|
1648
|
-
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.
|
|
1685
|
+
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").
|
|
1649
1686
|
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.
|
|
1650
1687
|
- **IMPORTANT — explicit staging**: NEVER use `git add -A` or `git add .`. Always stage files by explicit name:
|
|
1651
1688
|
```bash
|
|
@@ -1689,7 +1726,7 @@ Never block the pipeline indefinitely — recover and continue per the rules abo
|
|
|
1689
1726
|
|
|
1690
1727
|
### Phase 5 — Context Clean & Continue
|
|
1691
1728
|
30. Archive the card from Active Code Context in `${paths.references_dir}/project-status.md`.
|
|
1692
|
-
31. **CONTEXT
|
|
1729
|
+
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".
|
|
1693
1730
|
32. **Update tracker**: clear `## Current Card`, move to next pending card.
|
|
1694
1731
|
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**.
|
|
1695
1732
|
|
|
@@ -1749,14 +1786,16 @@ Once ALL cards are committed in the worktree:
|
|
|
1749
1786
|
for c in <ALL-CARD-IDS>; do [ -s "/tmp/arch-baseline-$c.md" ] || MISSING+=("$c"); done
|
|
1750
1787
|
printf '%s\n' "${MISSING[@]}"
|
|
1751
1788
|
```
|
|
1752
|
-
- **All present** → do NOT re-spawn the architect for the full batch.
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1789
|
+
- **All present** → do NOT re-spawn the architect for the full batch. Set `${ARCH_BASELINE_PATHS}`
|
|
1790
|
+
to the newline-separated **list of `/tmp/arch-baseline-<CARD-ID>.md` paths** (they already cover
|
|
1791
|
+
every touched file across the batch) — do NOT read or concatenate their contents inline (per
|
|
1792
|
+
§ "Context economy" → pass paths, not concatenations; Codex Reads them on demand). Proceed to F.3.
|
|
1793
|
+
Log `f.2-arch: reused N per-card baselines (no re-spawn)` in the tracker. This avoids the N+1
|
|
1794
|
+
architect invocations the per-card persistence was designed to prevent.
|
|
1756
1795
|
- **Any missing** (a card was added late, or a baseline was purged) → invoke **codebase-architect**
|
|
1757
1796
|
ONCE over the batch scope to map existing architecture, critical patterns, and high-risk code
|
|
1758
|
-
paths for regression. Persist its output to `/tmp/arch-baseline-batch-<FIRST-CARD-ID>.md` and
|
|
1759
|
-
|
|
1797
|
+
paths for regression. Persist its output to `/tmp/arch-baseline-batch-<FIRST-CARD-ID>.md` and set
|
|
1798
|
+
`${ARCH_BASELINE_PATHS}` to that single path. Log `f.2-arch: re-spawned (missing baselines: <list>)`. Do NOT spawn
|
|
1760
1799
|
the architect more than once for the batch — it is the single grounding context for all
|
|
1761
1800
|
downstream review agents.
|
|
1762
1801
|
|
|
@@ -1764,12 +1803,12 @@ Once ALL cards are committed in the worktree:
|
|
|
1764
1803
|
|
|
1765
1804
|
> **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.
|
|
1766
1805
|
|
|
1767
|
-
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
|
|
1806
|
+
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.
|
|
1768
1807
|
|
|
1769
1808
|
```bash
|
|
1770
1809
|
REVIEW_FILE="/tmp/codexreview-batch-<FIRST-CARD-ID>-<SESSION-ID>.md" && \
|
|
1771
1810
|
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)" && \
|
|
1772
|
-
[ -z "$CODEX_SCRIPT" ] && echo "CODEX_NOT_FOUND"
|
|
1811
|
+
[ -z "$CODEX_SCRIPT" ] && echo "CODEX_NOT_FOUND" > "$REVIEW_FILE" && exit 1; \
|
|
1773
1812
|
node "$CODEX_SCRIPT" task "
|
|
1774
1813
|
Run a deep multi-agent code review for these backlog cards. This is a post-implementation
|
|
1775
1814
|
review — the code is already written and committed. Your job is to find bugs, regressions,
|
|
@@ -1781,8 +1820,8 @@ Once ALL cards are committed in the worktree:
|
|
|
1781
1820
|
Files changed (review ALL of these):
|
|
1782
1821
|
${REVIEW_SCOPE_FILES}
|
|
1783
1822
|
|
|
1784
|
-
Architecture baseline (
|
|
1785
|
-
${
|
|
1823
|
+
Architecture baseline files (read each — they hold file paths, type signatures, patterns, high-risk paths):
|
|
1824
|
+
${ARCH_BASELINE_PATHS}
|
|
1786
1825
|
|
|
1787
1826
|
Follow the /codexreview protocol:
|
|
1788
1827
|
1. For each card, read its backlog YAML for acceptance_criteria and entrypoints.
|
|
@@ -1803,13 +1842,13 @@ Once ALL cards are committed in the worktree:
|
|
|
1803
1842
|
6. Classify surviving findings as VERIFIED, FALSE_POSITIVE, or NEEDS_MANUAL_CONFIRMATION.
|
|
1804
1843
|
|
|
1805
1844
|
Return ONLY verified findings. If zero verified bugs: state 'No verified bugs found.'
|
|
1806
|
-
"
|
|
1845
|
+
" > "$REVIEW_FILE" 2>&1
|
|
1807
1846
|
```
|
|
1808
1847
|
|
|
1809
1848
|
**Variable interpolation** (build the command string before execution):
|
|
1810
1849
|
- `${CARD_PATHS}`: newline-separated list of backlog YAML paths
|
|
1811
1850
|
- `${REVIEW_SCOPE_FILES}`: newline-separated list from Step F.1
|
|
1812
|
-
- `${
|
|
1851
|
+
- `${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)
|
|
1813
1852
|
|
|
1814
1853
|
7. **In parallel with Codex**, launch Claude support agents (single message):
|
|
1815
1854
|
|
|
@@ -1858,7 +1897,7 @@ Once ALL cards are committed in the worktree:
|
|
|
1858
1897
|
- **`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.
|
|
1859
1898
|
- **All remaining findings** (other code, perf, test) → invoke the **coder** agent once to apply them in a single pass.
|
|
1860
1899
|
Run in the order doc-reviewer → coder (or skip either if its partition is empty). Pass only the verified findings, not false positives.
|
|
1861
|
-
12. Run final build: `npm run lint && npx tsc --noEmit && npm run build
|
|
1900
|
+
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).
|
|
1862
1901
|
If any check fails, apply self-healing retry loop (up to 3 times).
|
|
1863
1902
|
13. **Update tracker** with final review results:
|
|
1864
1903
|
- Review engine: Codex (a non-Anthropic frontier model, resolved at runtime by `codex-companion.mjs`) (primary) | Claude code-reviewer (fallback)
|
|
@@ -2538,7 +2577,7 @@ For each completed agent:
|
|
|
2538
2577
|
|
|
2539
2578
|
After ALL agents in the group complete successfully:
|
|
2540
2579
|
|
|
2541
|
-
1. **D.1 — Build verification (group)** — Run `npm run build` in the worktree to verify combined changes compile. If build fails, identify which card's changes broke it (from `git diff` per card), spawn a targeted fix-coder for those files only.
|
|
2580
|
+
1. **D.1 — Build verification (group)** — Run `npm run build` in the worktree to verify combined changes compile (redirect to `/tmp/build-group.txt` per § "Context economy"; surface only exit code + bounded extract on failure). If build fails, identify which card's changes broke it (from `git diff --name-only` per card), spawn a targeted fix-coder for those files only.
|
|
2542
2581
|
|
|
2543
2582
|
1.5. **D.1.5 — Effective per-card review profile (compute ONCE; drives D.2 + D.4b)** — For EACH card in the group, compute its **effective codex profile** with the SAME deterministic rule the sequential Phase 3.7 Step C uses, so the two paths never disagree:
|
|
2544
2583
|
- **Floor**: read the card's `review_profile` field (`skip`/`light`/`balanced`/`deep`) per the QA Profile Selector (fallback-computed only for legacy cards lacking the field).
|
|
@@ -2559,7 +2598,7 @@ After ALL agents in the group complete successfully:
|
|
|
2559
2598
|
|
|
2560
2599
|
3a. **D.3a — Phase 2.5b AC-Closure Gate (per-card, BLOCKING — non-skippable)** — For EACH card in the group, **sequentially**, invoke the full Phase 2.5b gate as documented in `### Phase 2.5b — AC-Closure Gate (BLOCKING — Scope Closure Discipline)`. This includes: build the AC Closure Ledger from the card YAML, run the rationalization scan, invoke `AskUserQuestion` one-per-deferred-AC, run the `implementation_notes` deferral audit, and persist the ledger in the tracker. Until EVERY card in the group exits PASS, do NOT proceed to D.3b. Cards exiting with `not_implemented` ACs that the user routes to "Implementa adesso" must finish their fix-coder loop and re-pass the gate before D.3b starts for the next card. Log under `## AC Closure Ledger — <CARD-ID>` per card.
|
|
2561
2600
|
|
|
2562
|
-
3b. **D.3b — Phase 2.55 Simplify (per-card, FANNED OUT across the group)** — The Simplify agents are **read-only analysis on file-disjoint per-card diffs** (the orchestrator applies the fixes afterward), so there is NO reason to run them one card at a time. **Spawn the per-card Simplify analysis for ALL eligible cards in PARALLEL** — in a SINGLE message, fire each card's Phase 2.55 trio (Reuse / Quality / Efficiency)
|
|
2601
|
+
3b. **D.3b — Phase 2.55 Simplify (per-card, FANNED OUT across the group)** — The Simplify agents are **read-only analysis on file-disjoint per-card diffs** (the orchestrator applies the fixes afterward), so there is NO reason to run them one card at a time. **Spawn the per-card Simplify analysis for ALL eligible cards in PARALLEL** — in a SINGLE message, fire each card's Phase 2.55 trio (Reuse / Quality / Efficiency) against that card's diff captured to `/tmp/diff-<CARD-ID>.txt` (per Phase 2.55 step 2 — pass each trio the **path**, scoped to the card's File Ownership Map; never inline the diff). Per-card (not group-aggregate) so findings stay attributable. When all analyses return, **apply fixes per card** (file-disjoint → no write conflict), then re-run `npm run lint` and `npx tsc --noEmit` on the worktree ONCE for the whole group (redirect to disk per § "Context economy"). (Concurrency is capped by the platform; passing N cards is safe — excess agents queue.)
|
|
2563
2602
|
- **Gate (enumerated, `review_profile`-driven)**: SKIP D.3b for a card whose `review_profile == skip` (trivial / non-implementable card — Simplify is quality-only, so there is no merge-gate coverage to lose, and there is no substantive diff to simplify). Log `simplify: SKIPPED (review_profile=skip)`. For `light`/`balanced`/`deep` cards D.3b runs unchanged. This is the ONLY enumerated skip — never skip D.3b "for time" on a `light`+ card. (Skipped cards are simply omitted from the parallel fan-out.)
|
|
2564
2603
|
|
|
2565
2604
|
3c. **D.3c — Phase 2.6 E2E-Review (per-card)** — First, evaluate the existing Gate table for EVERY card at once (skip when `features.has_e2e_review: false`, backend-only diff per the diff predicate documented in Phase 2.6, or card type in the Phase 2.6 skip set — `backend`/`api`/`db`/`infra`/`docs`/`chore`/`config`). In practice most cards in a group skip this gate (backend/db/api), so the eligible set is usually 0–1. For the cards that PASS the gate, invoke `/e2e-review` in programmatic mode with that card's payload. Each `/e2e-review` keeps its own isolated state dir (`.baldart/e2e-review/<CARD-ID>/`), so multiple runs do not clobber each other's artifacts.
|