baldart 4.53.2 → 4.53.4

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 CHANGED
@@ -5,6 +5,23 @@ 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.53.4] - 2026-06-18
9
+
10
+ **Team-mode now has a MANDATORY empty-result / fabrication gate — a parallel coder that rests without doing the work no longer slips past on luck.** Observed on a real `/new FEAT-0035` L2 wave: of three coders spawned in parallel (03, 06, 07), **03 and 07 "came to rest" with NO completion report and zero file changes** (the empty-result failure pattern — same model-in-the-loop class as the v4.53.0 worktree-setup fabrication/stall), while 06 worked and reported normally. The orchestrator caught it only because it *improvised* a `git status` and noticed only 06's files had changed — the team-mode protocol (`team-mode.md` § Step C) merely said "read the completion report from the agent's output", assuming a report exists, and its failure branch only handled an agent that *reports* `status: failed`. So detection of a silent idle was model-discretion, not protocol: a less diligent run would have carried the empty work into the D pipeline and only hit it late/expensively at the D.3a AC-Closure or the Final build. Fix: Step C gains an explicit gate — for EACH agent, before logging it `done`, verify on disk that (a) it emitted the Step-7 completion report and (b) its `files_changed` actually changed in the worktree (`git status --porcelain` ∩ the card's File Ownership Map, using the v4.53.2 grep-verification discipline). No report on rest = empty-result; claimed-but-absent files = fabrication; both → the existing one-shot Step-B re-spawn (re-briefed to write + disk-confirm before reporting), second failure → `AskUserQuestion` skip/abandon. A legitimate zero-diff no-op (AC pre-satisfied) is the rare explicit exception, confirmed from the report's `evidence`. The coder brief (Step 7) is reinforced symmetrically: a `done` report is invalid with an empty diff. Cannot make coders not-idle (they do real work; the internal cause isn't recoverable from the trace — the agents left no report), but the DETECTION is now deterministic + mandatory instead of lucky. **PATCH** (protocol-hardening prose for team mode; no code/behaviour change in CLI or workflows, no `baldart.config.yml` key).
11
+
12
+ ### Fixed
13
+
14
+ - **`framework/.claude/skills/new/references/team-mode.md`** — Step C gains a MANDATORY "Empty-result / fabrication gate": a teammate resting without a completion report, or with `files_changed` not present on disk, is an empty-result/fabrication failure → one Step-B re-spawn (disk-verify re-brief) → `AskUserQuestion` on a second failure; never accept "came to rest" as "done" without on-disk evidence. Step-7 completion-report mandate reinforced (a `done` report is invalid with an empty diff).
15
+
16
+ ## [4.53.3] - 2026-06-18
17
+
18
+ **The per-wave/Final Codex review wrapper is now a thin relay on a cheaper model, not an Opus agent that re-investigates Codex's findings.** Observed on a real `/new FEAT-0035` run: the `codex` discovery agent burned ~127k tokens / 26 tool calls — it launched the Codex companion (correct) but then **re-grepped/sed'd the source to "mechanically confirm" Codex's findings** before returning, despite the design already trusting them (`preValidated`, FP-checked by Codex). Root cause: the wrapper consumed Codex's **freeform `task` output** (prose), which forced a smart+expensive model to parse 6 fields per finding out of prose — and it over-reached into self-investigation. Fix: instruct Codex to emit its findings as strict JSON between explicit `<<<FINDINGS_JSON>>>` / `<<<END_FINDINGS_JSON>>>` sentinels (verified on two real companion runs: output round-trips cleanly through `JSON.parse` with all our fields incl. `domain` + `requires_action`, and the sentinels make extraction deterministic despite the companion's `[codex]` trace lines + the truncated "Assistant message captured:" echo — the truncated copy lacks the closing sentinel so the last-complete-pair awk skips it). The wrapper is now a **pure relay**: write the task to a temp file (no shell-quote breakage — same discipline as v4.53.2), launch Codex in the background, poll for the END sentinel, extract via a fixed awk, `JSON.parse`, return — **no re-grep, no re-verify**. Model dropped from the inherited Opus to **`haiku` per-wave** (a poll misfire degrades safely to the `code-reviewer` fallback, and the Final re-runs Codex batch-wide) and **`sonnet` at the Final** (last cross-model gate before merge — no downstream Codex backstop). The review *mechanism* (Codex `task` + `--cwd` worktree + the changed-file list) is unchanged from production — only the output format, the wrapper's scope, and the model tier change. **PATCH** (cost/economy refinement of existing workflows; no new capability, no schema/config key, no install change).
19
+
20
+ ### Fixed
21
+
22
+ - **`framework/.claude/workflows/new-card-review.js`** — `codexPrompt` rewritten as a thin relay (write task → background launch → poll END sentinel → deterministic awk extract → `JSON.parse` → return; explicitly forbids self-investigation); Codex instructed to emit sentinel-delimited strict JSON findings; the `codex` discovery thunk runs on `model: 'haiku'`.
23
+ - **`framework/.claude/workflows/new-final-review.js`** — same relay rewrite + sentinel-JSON contract; the Final `codex` thunk runs on `model: 'sonnet'` (last cross-model gate, no downstream backstop).
24
+
8
25
  ## [4.53.2] - 2026-06-18
9
26
 
10
27
  **`/new` completeness/AC verification no longer treats a quote-broken grep as proof an AC is unimplemented.** Diagnosed from a real `/new FEAT-0035` team-mode L1 run: the orchestrator spot-checked AC-3 by grepping `data/products.ts` for the `mode:'catalog'|'picker'` token, the pattern's embedded single-quotes + pipe broke the shell/regex parse inside the `echo "=== … ===" && grep` block → **0 matches even though `mode` was fully implemented** (`ListProductsMode` type + `mode??'catalog'` + picker branch all present) → a false "AC-3 not implemented" alarm. It self-recovered (the orchestrator noticed the grep contradicted the coder's completion report and re-grepped correctly), but a false "AC absent" can otherwise trigger a needless gap-fix coder re-spawn — the same waste class as v4.53.1. Two compounding causes, both addressed: (1) grep-as-AC-evidence over **code-shaped tokens** is brittle (the verification phase is prose-mandated to "grep changed files for the implementation"), and (2) `0 matches` was conflated with "absent". Added a **Grep-verification discipline** to the completeness SSOT: search literals with `rg -F` (fixed-string, one fully-single-quoted pattern per call — never folded into an `echo "===…" && grep` composition), and a `0-match` that CONTRADICTS the coder's structured completion report is a likely broken grep → re-confirm by Reading the cited `file:line` BEFORE flagging or re-spawning (never re-spawn a coder on a 0-match alone). **PATCH** (verification-guidance hygiene to existing prose; no code/behaviour change in the workflows, no `baldart.config.yml` key).
package/VERSION CHANGED
@@ -1 +1 @@
1
- 4.53.2
1
+ 4.53.4
@@ -109,7 +109,7 @@ Agent tool call:
109
109
  d) Self-heal up to 3 times if checks fail
110
110
  e) Verify completeness: for each requirement, confirm code exists (read it)
111
111
  f) If any requirement is missing after implementation, implement it now
112
- g) Output the completion report (MANDATORY format below)
112
+ g) Output the completion report (MANDATORY format below). A `status: done` report is INVALID unless your `files_changed` are actually written to disk — never rest/report done with an empty diff (the orchestrator disk-verifies and will treat a no-change rest as an empty-result failure and re-spawn you).
113
113
 
114
114
  ### 7. Completion Report (MANDATORY)
115
115
  ```completion-report
@@ -140,6 +140,12 @@ For each completed agent:
140
140
  2. Log to tracker: card ID, status, files changed, build/lint status.
141
141
  3. Do NOT read or store implementation details — only the verdict.
142
142
 
143
+ **Empty-result / fabrication gate (MANDATORY — since v4.53.4; do NOT accept "came to rest" as "done").** A background agent coming to rest is NOT proof it did the work. The observed failure mode (real, repeated): a teammate **idles and rests WITHOUT emitting the Step-7 completion report AND without changing any file** — a silent empty-result — while its peers in the same parallel wave completed normally. (Rarer twin: it reports `files_changed` it never wrote — fabrication.) Letting this slide is only caught later/expensively by the D.3a AC-Closure or the Final build; catch it HERE, deterministically, before running the rest of the D pipeline on empty work. For EACH agent, before logging it `done`, verify ON DISK:
144
+ - **A Step-7 completion report was emitted.** A teammate that rested with **no completion report = empty-result failure.** (Do not infer "done" from the rest event alone.)
145
+ - **Its `files_changed` actually changed in the worktree** — `git status --porcelain` intersected with that card's File Ownership Map is non-empty and covers the claimed paths (use the grep-verification discipline above — never a quote-broken check). **Zero changes in the card's ownership files = empty-result failure; report claims files that are not on disk = fabrication.**
146
+ - A genuinely legitimate no-op card (its AC turned out already satisfied) is the rare exception: confirm it from the report's per-requirement `evidence` pointing at PRE-EXISTING code, and log it explicitly as `no-op (AC pre-satisfied)` — never assume zero-diff means success.
147
+ On an empty-result / fabrication failure, take the one Step-B re-spawn below (same cap), re-briefing the coder with an explicit "write your ownership files and confirm them on disk before reporting done" mandate. A second empty result → `AskUserQuestion` (skip/abandon) — do not re-spawn a third time.
148
+
143
149
  **If an agent fails** (status: failed after 3 retries — the central repair cap):
144
150
  - Log failure in tracker `## Issues & Flags`.
145
151
  - Other agents in the group continue unaffected.
@@ -191,18 +191,36 @@ log(codexResolved
191
191
  ? `Codex companion resolved deterministically: ${codexScriptPath}`
192
192
  : 'Codex companion NOT found (deterministic pre-flight) — primary code review via code-reviewer fallback.')
193
193
 
194
- const codexPrompt =
195
- `Run a deep, cross-model code review over this wave's diff, following the review protocol summarized in ${protocolRef} (Phase 3.7). The code is already written and committed — find bugs, regressions, security issues, and quality problems.\n\n` +
196
- `The Codex companion script is ALREADY CONFIRMED PRESENT at:\n ${codexScriptPath}\n` +
197
- `Launch it in the BACKGROUND and poll for completion do NOT run it synchronously (a sync run would hit the Bash tool timeout):\n` +
198
- ` • REVIEW_FILE=a unique /tmp file (e.g. /tmp/codexreview-wave-${cards[0].cardId}-$$.md)\n` +
199
- ` • node "${codexScriptPath}" task "<your review instructions>" > "$REVIEW_FILE" 2>&1 — run this with run_in_background:true (the launching call returns immediately).\n` +
200
- ` • Then POLL $REVIEW_FILE (BashOutput / repeated reads) until it holds a terminal result, up to a full 10-minute window.\n` +
201
- `Return codexAvailable:false ONLY if $REVIEW_FILE ends up containing "CODEX_NOT_FOUND" or stays empty after the FULL 10-minute windowNEVER because a single Bash call returned slowly.\n\n` +
194
+ // Codex companion review. The WRAPPER is a thin relay (model: haiku — see the thunk): it launches
195
+ // Codex, waits, and extracts Codex's JSON findings with a deterministic awk. It does NOT review or
196
+ // re-verify code itself (Codex's findings are authoritative + FP-validated) the old wrapper burned
197
+ // ~100k+ tokens re-grepping to "confirm" findings the design already trusts. Codex emits its findings
198
+ // between explicit sentinels so the extraction is unambiguous despite the companion's `[codex]` trace
199
+ // lines and the truncated "Assistant message captured:" echo (verified on real companion runs).
200
+ const codexReviewTask =
201
+ `Run a deep code review over this wave's committed diff. The code is already written and committedfind bugs, regressions, security issues, and quality problems, per the protocol in ${protocolRef} (Phase 3.7).\n\n` +
202
202
  `${waveBrief}\n\n${baselineBrief}\n\n` +
203
- `For each finding return: finding_id, title, severity (BLOCKER|HIGH|MEDIUM|LOW), confidence (0-100), evidence (exact file:line + code quote), minimal_fix_direction, and domain (doc|security|migration|code|perf|test). ` +
204
- `Run the mandatory false-positive check on every finding and suppress the unconvincing ones (your findings are treated as already FP-validated). ` +
205
- `Then the actionability check: an observation you have VERIFIED needs NO change anywhere (the fix direction would be "no fix required" / "acceptable as-is" / "verified non-issue") is not work — set requires_action:false on it (it is recorded but never sent to a fixer), or simply do not emit it. Emit requires_action true/omitted ONLY when a concrete edit is needed. Set codexAvailable:true when the review ran.`
203
+ `Run the mandatory false-positive check on every finding and suppress the unconvincing ones. Actionability: set requires_action:false on a VERIFIED observation that needs NO change (a cleared concern MED/LOW only; a BLOCKER/HIGH is always requires_action:true).\n\n` +
204
+ `Emit your findings as your FINAL message, between these EXACT sentinels and nothing else after the opening sentinel:\n` +
205
+ `<<<FINDINGS_JSON>>>\n` +
206
+ `[{"finding_id":"<CARD-ID>-F###","title":"...","severity":"BLOCKER|HIGH|MEDIUM|LOW","confidence":<0-100>,"evidence":"exact file:line + code quote","minimal_fix_direction":"...","domain":"doc|security|migration|code|perf|test","requires_action":true}]\n` +
207
+ `<<<END_FINDINGS_JSON>>>\n` +
208
+ `Use an empty array [] between the sentinels if there are no real bugs.`
209
+ const codexTaskFile = `/tmp/codextask-${cards[0].cardId}-$$.txt`
210
+ const codexReviewFile = `/tmp/codexreview-wave-${cards[0].cardId}-$$.md`
211
+ const codexPrompt =
212
+ `You are a THIN RELAY around the Codex companion — do NOT review or investigate code yourself, do NOT grep/sed/Read source to "confirm" findings (Codex's findings are authoritative and already FP-validated; re-verifying them is wasted work). Your ONLY job: launch Codex, wait, extract its JSON, return it.\n\n` +
213
+ `The companion script is ALREADY CONFIRMED PRESENT at:\n ${codexScriptPath}\n\n` +
214
+ `Run EXACTLY these steps and nothing else:\n` +
215
+ ` 1. Write the task text (everything after "TASK PROMPT:" at the end of this message) to ${codexTaskFile} using the Write tool — do NOT inline it into the shell command (avoids quote breakage).\n` +
216
+ ` 2. Launch Codex in the BACKGROUND (run_in_background:true — a sync run hits the Bash timeout):\n` +
217
+ ` node "${codexScriptPath}" task "$(cat ${codexTaskFile})" --cwd "${a.worktreePath || '.'}" > ${codexReviewFile} 2>&1\n` +
218
+ ` 3. POLL ${codexReviewFile} (BashOutput / repeated reads) until it contains "<<<END_FINDINGS_JSON>>>" (terminal) OR "CODEX_NOT_FOUND" OR the full 10-minute window has elapsed.\n` +
219
+ ` 4. Extract the findings with this EXACT command (deterministic — skips the [codex] trace + truncated echo, takes the LAST complete sentinel pair):\n` +
220
+ ` awk '/<<<FINDINGS_JSON>>>/{c=1;b="";next}/<<<END_FINDINGS_JSON>>>/{c=0;last=b;next}c{b=b $0 ORS}END{printf "%s",last}' ${codexReviewFile}\n` +
221
+ ` Parse that output as JSON and return it verbatim as \`findings\` (its keys already match the schema). Do NOT re-verify, re-grep, or Read any source file.\n\n` +
222
+ `Set codexAvailable:false ONLY if ${codexReviewFile} contains "CODEX_NOT_FOUND" or has no "<<<END_FINDINGS_JSON>>>" after the FULL 10-minute window — NEVER because a single poll returned slowly. Otherwise codexAvailable:true.\n\n` +
223
+ `TASK PROMPT:\n${codexReviewTask}`
206
224
 
207
225
  const tcGateLines = [
208
226
  ['lint', tcCmds.lint], ['typecheck', tcCmds.typecheck], ['test', tcCmds.test],
@@ -242,7 +260,9 @@ for (const c of cards) {
242
260
  }
243
261
  }
244
262
  if (codexResolved) {
245
- findThunks.push(() => agent(codexPrompt, { label: 'codex', phase: 'Discovery', schema: CODEX_SCHEMA }).then((r) => ({ kind: 'codex', card: null, r })))
263
+ // model: haiku the wrapper is a deterministic relay (launch + poll + awk-extract); a poll misfire
264
+ // degrades safely to the code-reviewer fallback below, and the Final review re-runs Codex batch-wide.
265
+ findThunks.push(() => agent(codexPrompt, { label: 'codex', phase: 'Discovery', model: 'haiku', schema: CODEX_SCHEMA }).then((r) => ({ kind: 'codex', card: null, r })))
246
266
  }
247
267
  if (maxQaTier === 'full') {
248
268
  findThunks.push(() => agent(qaPrompt, { label: 'qa-sentinel', phase: 'Discovery', agentType: 'qa-sentinel', schema: GATES_SCHEMA }).then((r) => ({ kind: 'qa', card: null, r })))
@@ -148,18 +148,36 @@ log(codexResolved
148
148
  ? `Codex companion resolved deterministically: ${codexScriptPath}`
149
149
  : 'Codex companion NOT found (deterministic pre-flight) — primary review via code-reviewer fallback.')
150
150
 
151
- const codexPrompt =
152
- `Run a deep, cross-model code review over this batch diff, following the /codexreview protocol summarized in ${protocolRef} (Step F.3). The code is already written and committed — find bugs, regressions, security issues, and quality problems.\n\n` +
153
- `The Codex companion script is ALREADY CONFIRMED PRESENT at:\n ${codexScriptPath}\n` +
154
- `Launch it in the BACKGROUND and poll for completion — do NOT run it synchronously (a sync run would hit the Bash tool timeout and is the exact bug this design fixes):\n` +
155
- ` • REVIEW_FILE=a unique /tmp file (e.g. /tmp/codexreview-batch-${a.firstCardId || 'batch'}-$$.md)\n` +
156
- ` • node "${codexScriptPath}" task "<your review instructions>" > "$REVIEW_FILE" 2>&1 run this with run_in_background:true (the launching call returns immediately).\n` +
157
- ` • Then POLL $REVIEW_FILE (BashOutput / repeated reads) until it holds a terminal result, up to a full 10-minute window.\n` +
158
- `Return codexAvailable:false ONLY if $REVIEW_FILE ends up containing "CODEX_NOT_FOUND" or stays empty after the FULL 10-minute window NEVER because a single Bash call returned slowly. The script's existence is already verified, so a premature false here is a bug, not a capability gap.\n\n` +
151
+ // Codex companion review. The WRAPPER is a thin relay (model: sonnet — see the thunk): it launches
152
+ // Codex, waits, and extracts Codex's JSON findings with a deterministic awk; it does NOT review or
153
+ // re-verify code itself (Codex's findings are authoritative + FP-validated). Codex emits findings
154
+ // between explicit sentinels so the extraction is unambiguous despite the companion's `[codex]` trace
155
+ // and the truncated "Assistant message captured:" echo. Sonnet (not haiku) here because the Final is
156
+ // the last cross-model gate before mergeno downstream Codex pass backstops a wrapper misfire.
157
+ const codexReviewTask =
158
+ `Run a deep code review over this batch diff, per the /codexreview protocol in ${protocolRef} (Step F.3). The code is already written and committed find bugs, regressions, security issues, and quality problems.\n\n` +
159
159
  `${scopeBrief}\n\n${baselineBrief}\n\n` +
160
- `For each finding return: finding_id, title, severity (BLOCKER|HIGH|MEDIUM|LOW), confidence (0-100), evidence (exact file:line + code quote), minimal_fix_direction, and domain (doc|security|migration|code|perf|test). ` +
161
- `Run the mandatory false-positive check on every finding and suppress the unconvincing ones (your findings are treated as already FP-validated). ` +
162
- `Then the actionability check: an observation you have VERIFIED needs NO change anywhere (the fix direction would be "no fix required" / "acceptable as-is" / "verified non-issue") is not work — set requires_action:false on it (it is recorded but never sent to a fixer), or simply do not emit it. Emit requires_action true/omitted ONLY when a concrete edit is needed. Set codexAvailable:true when the review ran.`
160
+ `Run the mandatory false-positive check on every finding and suppress the unconvincing ones. Actionability: set requires_action:false on a VERIFIED observation that needs NO change (a cleared concern MED/LOW only; a BLOCKER/HIGH is always requires_action:true).\n\n` +
161
+ `Emit your findings as your FINAL message, between these EXACT sentinels and nothing else after the opening sentinel:\n` +
162
+ `<<<FINDINGS_JSON>>>\n` +
163
+ `[{"finding_id":"<CARD-ID>-F###","title":"...","severity":"BLOCKER|HIGH|MEDIUM|LOW","confidence":<0-100>,"evidence":"exact file:line + code quote","minimal_fix_direction":"...","domain":"doc|security|migration|code|perf|test","requires_action":true}]\n` +
164
+ `<<<END_FINDINGS_JSON>>>\n` +
165
+ `Use an empty array [] between the sentinels if there are no real bugs.`
166
+ const codexTaskFile = `/tmp/codextask-batch-${a.firstCardId || 'batch'}-$$.txt`
167
+ const codexReviewFile = `/tmp/codexreview-batch-${a.firstCardId || 'batch'}-$$.md`
168
+ const codexPrompt =
169
+ `You are a THIN RELAY around the Codex companion — do NOT review or investigate code yourself, do NOT grep/sed/Read source to "confirm" findings (Codex's findings are authoritative and already FP-validated). Your ONLY job: launch Codex, wait, extract its JSON, return it.\n\n` +
170
+ `The companion script is ALREADY CONFIRMED PRESENT at:\n ${codexScriptPath}\n\n` +
171
+ `Run EXACTLY these steps and nothing else:\n` +
172
+ ` 1. Write the task text (everything after "TASK PROMPT:" at the end of this message) to ${codexTaskFile} using the Write tool — do NOT inline it into the shell command (avoids quote breakage).\n` +
173
+ ` 2. Launch Codex in the BACKGROUND (run_in_background:true — a sync run hits the Bash timeout):\n` +
174
+ ` node "${codexScriptPath}" task "$(cat ${codexTaskFile})" --cwd "${a.worktreePath || '.'}" > ${codexReviewFile} 2>&1\n` +
175
+ ` 3. POLL ${codexReviewFile} (BashOutput / repeated reads) until it contains "<<<END_FINDINGS_JSON>>>" (terminal) OR "CODEX_NOT_FOUND" OR the full 10-minute window has elapsed.\n` +
176
+ ` 4. Extract the findings with this EXACT command (deterministic — skips the [codex] trace + truncated echo, takes the LAST complete sentinel pair):\n` +
177
+ ` awk '/<<<FINDINGS_JSON>>>/{c=1;b="";next}/<<<END_FINDINGS_JSON>>>/{c=0;last=b;next}c{b=b $0 ORS}END{printf "%s",last}' ${codexReviewFile}\n` +
178
+ ` Parse that output as JSON and return it verbatim as \`findings\` (its keys already match the schema). Do NOT re-verify, re-grep, or Read any source file.\n\n` +
179
+ `Set codexAvailable:false ONLY if ${codexReviewFile} contains "CODEX_NOT_FOUND" or has no "<<<END_FINDINGS_JSON>>>" after the FULL 10-minute window — NEVER because a single poll returned slowly. Otherwise codexAvailable:true.\n\n` +
180
+ `TASK PROMPT:\n${codexReviewTask}`
163
181
 
164
182
  const docPrompt =
165
183
  `Cross-card documentation + SSOT-registry review over the batch diff, per ${protocolRef} Step F.3 (doc-reviewer row). Check doc consistency, ssot-registry completeness, and invariants across the changed files.\n\n${scopeBrief}\n\n${baselineBrief}\n\n` +
@@ -201,7 +219,9 @@ if (!slimDoc) {
201
219
  }
202
220
  // Codex thunk runs ONLY when the pre-flight resolved the companion (else: no wasted agent).
203
221
  if (codexResolved) {
204
- reviewThunks.unshift(() => agent(codexPrompt, { label: 'codex', phase: 'Review', schema: CODEX_SCHEMA }).then((r) => ({ kind: 'codex', r })))
222
+ // model: sonnet thin relay (launch + poll + awk-extract), no self-investigation; sonnet (not haiku)
223
+ // because this is the last cross-model gate before merge (no downstream Codex pass backstops a misfire).
224
+ reviewThunks.unshift(() => agent(codexPrompt, { label: 'codex', phase: 'Review', model: 'sonnet', schema: CODEX_SCHEMA }).then((r) => ({ kind: 'codex', r })))
205
225
  }
206
226
  // api-perf-cost-auditor: skipped when no API/data files OR when it already ran per-card (slimApi).
207
227
  if (!slimApi && a.hasApiDataFiles !== false) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baldart",
3
- "version": "4.53.2",
3
+ "version": "4.53.4",
4
4
  "description": "Claude Agent Framework - Reusable framework for coordinating AI agents and humans in software projects",
5
5
  "bin": {
6
6
  "baldart": "./bin/baldart.js"