baldart 4.56.0 → 4.56.2
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,32 @@ 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.56.2] - 2026-06-19
|
|
9
|
+
|
|
10
|
+
**`/new` per-card Codex relay bumped haiku → sonnet — stops a real run from discarding a valid Codex review (incl. a BLOCKER) and falling back to a cold, weaker `code-reviewer`.** A user reported the symptom directly: in the per-wave Discovery phase Codex emitted a perfect sentinel-wrapped JSON array (3 findings, one a BLOCKER race condition on the idempotency key), yet the workflow still ran the cold `code-reviewer (fallback)` — which re-reviewed from scratch (~101k tok) and **missed the BLOCKER**.
|
|
11
|
+
|
|
12
|
+
Root cause: the per-wave Codex relay in `new-card-review.js` ran on `model: 'haiku'`. The relay is "thin" but is still a model in the loop that must follow a multi-branch decision tree AND faithfully pass a large JSON array through the structured schema. Haiku proved too weak on a real run — it went off-script (re-grepped source to "confirm" findings, explicitly forbidden by the prompt) and then failed the pass-through, returning `codexAvailable:false` with empty `codexProse`. The fan-in (`item.r.codexAvailable && Array.isArray(findings)`) therefore discarded every Codex finding and triggered the **plain** cold fallback (not even the codex-seeded one). The "a misfire degrades safely to the fallback" assumption baked into the old comment is false: the cold fallback is a *different model hunting from scratch*, not a backstop — it lost the BLOCKER.
|
|
13
|
+
|
|
14
|
+
`new-final-review.js` already learned this exact lesson (its relay is `model: 'sonnet'` "not haiku because this is the last cross-model gate before merge"); the per-wave relay was simply left behind. This brings it to parity. The relay prompt is low-volume plumbing, so the haiku→sonnet delta is negligible against a dropped BLOCKER plus a ~100k-token cold re-review. Matches the recorded lessons that a weak *model in the loop for pure plumbing* fabricates/abandons, and that the cheap-model-via-structured-output bet only holds if the model can actually emit the structure.
|
|
15
|
+
|
|
16
|
+
**PATCH** — single-line model change (+ rationale comment) in `framework/.claude/workflows/new-card-review.js`; no schema/prose/install/layout change, no new config key. The Codex prompt, awk extraction, sentinel contract, and prose-salvage path are all unchanged.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **`framework/.claude/workflows/new-card-review.js`** — per-wave Codex relay `model: 'haiku'` → `model: 'sonnet'`, with an expanded rationale comment explaining why the misfire-degrades-safely assumption is false (parity with `new-final-review.js`).
|
|
21
|
+
|
|
22
|
+
## [4.56.1] - 2026-06-19
|
|
23
|
+
|
|
24
|
+
**`/new` per-card review-cluster — corrected a prose-vs-implementation drift about Codex depth (doc-only, no behaviour change).** Triggered by a user question — "why does `/new` run a per-card review *and* a final review for a single card, when some agents overlap?". A full read of `new-card-review.js` + `new-final-review.js` + the orchestrating modules, followed by an adversarial refutation pass, established that the apparent double-review is **not** redundant: the per-card Codex/qa-sentinel run in the **Discovery phase (PRE-fix, PRE-E2E)**, while the final Codex/qa-sentinel run on the **post-fix, post-E2E** tree — the same temporal argument the framework already uses to keep `slimDoc:false` on the delegated path (`final-review.md`). A proposed `slimCodex` (drop the final Codex on N=1 when per-card Codex ran) was **refuted and NOT implemented**: it would review materially different code and reopen the v3.35.0 scope-reduction hole that v3.37.0 closed (Codex + qa-sentinel are the explicit never-slim exceptions to F-041).
|
|
25
|
+
|
|
26
|
+
The one genuine defect the review surfaced: `references/review-cycle.md` (Phase 2.5x delegation gate) claimed the Step-A detector "also tells the workflow's Codex pass the depth." It does not — `qaTier` is binary (`light|full`, gating `qa-sentinel` only), the workflow's Codex prompt is unconditionally a "deep code review" and never reads `qaTier`, and that is correct (per `codex-gate.md`, at `light` Codex stays the SOLE deep finder — only the breadth agents qa/api/doc are dropped). Fix: the prose now states Step-A drives `qaTier` only, the per-card Codex review is always full-depth regardless of profile, and the Codex stage takes no depth input.
|
|
27
|
+
|
|
28
|
+
**PATCH** — single-file prose correction in `framework/.claude/skills/new/references/review-cycle.md`; no workflow/agent/skill behaviour change, no install/layout change, no new config key.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- **`framework/.claude/skills/new/references/review-cycle.md`** — Phase 2.5x `qaTier` bullet: removed the false "Step-A tells the Codex pass the depth" claim; clarified that Step-A drives `qaTier` (qa-sentinel inclusion) only and the per-card Codex pass is always a full deep review.
|
|
33
|
+
|
|
8
34
|
## [4.56.0] - 2026-06-19
|
|
9
35
|
|
|
10
36
|
**Hardening from a real `/new` session post-mortem (mayo, FEAT-0035-followup batch): three protocol-violation classes the framework *allowed*, a recurring Codex waste, and a context-economy win.** The orchestrator recovered and merged all 5 cards, but only by improvising around failures the framework should have prevented. Root cause across the board: the framework trusted **prose discipline** where it needed **enforced constraints**.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.56.
|
|
1
|
+
4.56.2
|
|
@@ -36,7 +36,12 @@ so it surfaces in telemetry.
|
|
|
36
36
|
- `qaTier` ← the **Phase 3.5 profile selection** (step 19-21b below: `review_profile` floor →
|
|
37
37
|
`skip`/`light` ⇒ `qaTier:"light"` (qa-sentinel deferred to Final), `deep` **or any Phase 3.7 Step-A
|
|
38
38
|
high-risk trigger on this card's diff** ⇒ `qaTier:"full"`). Compute the **Step-A detector**
|
|
39
|
-
(`references/codex-gate.md` Step A) once here — it
|
|
39
|
+
(`references/codex-gate.md` Step A) once here — it drives **`qaTier` only** (whether `qa-sentinel`
|
|
40
|
+
runs per-card or is deferred to the Final). It does **NOT** modulate the workflow's Codex pass:
|
|
41
|
+
the per-card Codex review is **always a full deep review** regardless of profile (per
|
|
42
|
+
`codex-gate.md` — at `light` Codex is still the SOLE deep finder; only the breadth agents
|
|
43
|
+
qa/api/doc are dropped), so the workflow's Codex stage takes no depth input and `qaTier` does
|
|
44
|
+
not reach it.
|
|
40
45
|
- `scopeFiles` ← this card's committed diff (`git diff --name-only "$TRUNK...HEAD"`, fallback `HEAD~1..HEAD`). **Diffs to disk (context economy, v4.43.0):** write the card's full diff to `/tmp/diff-<CARD-ID>.txt` once and derive BOTH the Step-A grep (above) and this `--name-only` list from it — never read the raw diff inline (mirrors the team-mode D.1.5 batching discipline, so the two paths stay symmetric).
|
|
41
46
|
- `editableFiles` ← this card's **File Ownership Map** entries (the coder's write scope; `setup.md` step 3b).
|
|
42
47
|
- `archBaselinePath` ← `/tmp/arch-baseline-<CARD-ID>.md` (persisted at `implement.md` step 5b).
|
|
@@ -302,9 +302,16 @@ for (const c of cards) {
|
|
|
302
302
|
}
|
|
303
303
|
}
|
|
304
304
|
if (codexResolved) {
|
|
305
|
-
// model: haiku —
|
|
306
|
-
//
|
|
307
|
-
|
|
305
|
+
// model: sonnet (NOT haiku) — parity with new-final-review.js. The wrapper is a thin relay (launch +
|
|
306
|
+
// poll + awk-extract + faithfully pass Codex's JSON array through the schema), but it is STILL a model
|
|
307
|
+
// in the loop, and haiku proved too weak for it on a real run: it went off-script (re-grepped source to
|
|
308
|
+
// "confirm" findings, explicitly forbidden) and then failed the pass-through — Codex emitted a valid
|
|
309
|
+
// array (incl. a BLOCKER) yet the relay returned codexAvailable:false, so the workflow discarded all of
|
|
310
|
+
// Codex's findings and ran the COLD code-reviewer fallback, which missed the BLOCKER. The "misfire
|
|
311
|
+
// degrades safely to the fallback" assumption is false: the cold fallback is a different model hunting
|
|
312
|
+
// from scratch, not a backstop. Pass-through fidelity on a low-volume plumbing prompt costs little, and
|
|
313
|
+
// a dropped BLOCKER + a 100k-token cold fallback dwarf the haiku→sonnet delta.
|
|
314
|
+
findThunks.push(() => agent(codexPrompt, { label: 'codex', phase: 'Discovery', model: 'sonnet', schema: CODEX_SCHEMA }).then((r) => ({ kind: 'codex', card: null, r })))
|
|
308
315
|
}
|
|
309
316
|
if (maxQaTier === 'full') {
|
|
310
317
|
findThunks.push(() => agent(qaPrompt, { label: 'qa-sentinel', phase: 'Discovery', agentType: 'qa-sentinel', schema: GATES_SCHEMA }).then((r) => ({ kind: 'qa', card: null, r })))
|