baldart 4.17.2 → 4.18.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 +14 -0
- package/README.md +8 -0
- package/VERSION +1 -1
- package/framework/.claude/agents/prd-card-writer.md +6 -4
- package/framework/.claude/commands/codexreview.md +28 -18
- package/framework/.claude/skills/new/SKILL.md +3 -3
- package/framework/.claude/skills/new/references/codex-gate.md +26 -22
- package/framework/.claude/skills/new/references/team-mode.md +13 -12
- package/framework/.claude/workflows/new2.js +45 -14
- package/framework/routines/code-review.routine.yml +25 -0
- package/package.json +1 -1
- package/src/utils/routine-adapters/claude-code-cloud.js +6 -0
- package/src/utils/routine-adapters/cron.js +40 -10
- package/src/utils/routine-adapters/github-actions.js +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ 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.18.0] - 2026-06-08
|
|
9
|
+
|
|
10
|
+
**Codex come finder a profilo `light` (`/new` + `new2`) + engine Codex opt-in nelle routine cron.** Sposta il carico di review da Claude alla licenza Codex dove la review è read-only e genera finding, mantenendo la diversità di modello (Codex trova, l'agent Claude verifica). **MINOR** (additivo/opt-in con fallback; nessuna rottura install, **nessuna chiave `baldart.config.yml`** → schema-propagation N/A — `review_engine` è schema routine-payload).
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **Profilo `light` → Codex è il finder per-card (inverte la scelta v3.38.0).** Prima `light` faceva `code-reviewer` (finder) + FP-gate e deferiva Codex al solo Final FULL gate. Ora `/codexreview` a `light` lancia **Codex come unico finder** + lo Step 3 FP-gate (`code-reviewer` + `codebase-architect` validano): la lettura full-diff esce da Claude, Claude conserva solo la validazione. `full` invariato (entrambi i finder). **Fallback obbligatorio**: Codex non disponibile → `light` degrada a `code-reviewer` finder (comportamento pre-v4.18.0), la review non salta mai. L'invariante BUG-0530 ne esce rafforzata (Codex per-card su ogni card non-triviale). File: `framework/.claude/commands/codexreview.md` (Step -0.5/Step 2/invariant/Method-log), `framework/.claude/skills/new/references/codex-gate.md` (razionale Phase 3.7).
|
|
15
|
+
- **Team-mode allineato: i `LIGHT_CARDS` non skippano più D.4b.** La partizione LIGHT/FULL esisteva per tenere Codex fuori da `light`; ora ogni card non-triviale gira `/codexreview` a D.4b (light → Codex-light, full → Codex-full). La D.2 group pass diventa **doc-reviewer only** (il code-reviewer di gruppo sui light cards è rimosso — la loro review si sposta a D.4b). Coverage-assertion e clausola "REVIEW DEPTH SCALES" aggiornate. File: `framework/.claude/skills/new/references/team-mode.md`, `framework/.claude/skills/new/SKILL.md`, `framework/.claude/agents/prd-card-writer.md` (Rule C — semantica Codex-`light`).
|
|
16
|
+
- **`new2.js`: mirror del Codex finder a `light`.** Il companion Codex è ora risolto in pre-flight per **ogni** batch (prima solo multi-card per il cross-card), con il path propagato in `sharedCtx`. A `light` il fan-out per-card usa un reviewer **`codex`** (un agent general-purpose che lancia `codex-companion.mjs --wait` sul diff) quando il companion è risolto, con fallback `code-reviewer`. Il FP-gate è preservato a valle dal judge avversariale di `new2-resolve` (F-015). Nuovo campo schema `codexScriptPath`; ledger `codex-companion`; telemetria `codex_resolved` ora probed per ogni batch.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **`review_engine: codex` opt-in nelle routine di review (solo backend cron).** `code-review.routine.yml` accetta `review_engine: claude|codex` (default `claude`) + un `prompt_codex:` per la review olistica single-pass. L'adapter `cron` risolve il companion Codex e lo invoca (`--wait`), con **guard `CODEX_NOT_FOUND` → fallback a `claude --agent`**; il check `ANTHROPIC_API_KEY` è ammorbidito a warning sul ramo Codex (Codex usa `~/.codex`). I backend `github-actions` e `claude-code-cloud` **non** supportano Codex (no plugin/auth in CI, schema RemoteTrigger ignoto) → emettono l'artefatto Claude + un warning esplicito. Codex non spawna specialist → la variante Codex perde la profondità security-reviewer/api-perf (documentato; usa `claude` per quella). File: `framework/routines/code-review.routine.yml`, `src/utils/routine-adapters/{cron,github-actions,claude-code-cloud}.js`, README.
|
|
21
|
+
|
|
8
22
|
## [4.17.2] - 2026-06-08
|
|
9
23
|
|
|
10
24
|
**`new2` hardening: 7 lacune latenti chiuse da una revisione adversariale dell'intero workflow.** Dopo i fix di v4.17.1 (nati da run reali), una revisione olistica di `new2` (orchestratore + resolve + final-review + skill) ha isolato 7 lacune non ancora emerse nei run ma reali alla lettura del codice — validate di persona scartando i falsi positivi (l'integrity gate di merge è corretto; lo skill "prose-only" è by-design). **PATCH** (hardening dei workflow `new2`/`new2-resolve` + skill/doc; nessuna nuova capability/layout, **nessuna chiave `baldart.config.yml`** → schema-propagation N/A).
|
package/README.md
CHANGED
|
@@ -310,6 +310,14 @@ Three backend adapters are bundled:
|
|
|
310
310
|
- **`github-actions`** — `.github/workflows/baldart-<name>.yml`
|
|
311
311
|
- **`cron`** — `scripts/routines/<name>.sh` + a crontab line
|
|
312
312
|
|
|
313
|
+
**Review engine (v4.18.0+)** — a review routine (e.g. `code-review`) may set `review_engine: codex`
|
|
314
|
+
in its `.routine.yml` to shift the finding pass onto the OpenAI Codex companion (spend a Codex
|
|
315
|
+
licence instead of Claude tokens). This is **cron-only** — it needs the Codex plugin + an
|
|
316
|
+
authenticated `~/.codex/` in the cron user's home; the `github-actions` and `claude-code-cloud`
|
|
317
|
+
backends fall back to the `claude` engine with a warning. Codex cannot spawn specialist subagents,
|
|
318
|
+
so the Codex engine runs a holistic single-pass review (no `security-reviewer` / `api-perf-cost-auditor`
|
|
319
|
+
split) — keep `review_engine: claude` (the default) when you need that depth.
|
|
320
|
+
|
|
313
321
|
During `npx baldart add` and `npx baldart update`, BALDART surfaces routines
|
|
314
322
|
the user has never reviewed and prompts to install them. Standalone command:
|
|
315
323
|
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.18.0
|
|
@@ -198,7 +198,9 @@ This field materializes the per-card review DEPTH **at authoring time**, so the
|
|
|
198
198
|
`/new` orchestrator READS it instead of re-deriving it heuristically at runtime.
|
|
199
199
|
The single field drives BOTH the QA depth (`/new` Phase 3.5) and the Codex review
|
|
200
200
|
profile (`/new` Phase 3.7 — `skip`/`light` → Codex `light`, `balanced`/`deep` →
|
|
201
|
-
Codex `full`).
|
|
201
|
+
Codex `full`). Note (since v4.18.0): Codex-`light` is no longer a "no-Codex" lane — it runs
|
|
202
|
+
**Codex as the per-card finder** with `code-reviewer` as the FP-gate verifier; `full` runs both
|
|
203
|
+
as finders. **This table is the Single Source of Truth for the decision
|
|
202
204
|
criteria** — how skip/light/balanced/deep is chosen lives ONLY here (Rule C).
|
|
203
205
|
`/new` does NOT re-derive the profile from a duplicate criteria table: it READS
|
|
204
206
|
the card's `review_profile` value and runs an **escalation-only** detector (it may
|
|
@@ -222,9 +224,9 @@ exception**: the LIGHT branch (b) above, a strictly UI-presentational card (`are
|
|
|
222
224
|
`paths.components_primitives` path). This narrow carve-out targets the `-ui` half of a
|
|
223
225
|
logic/ui split pair (e.g. a `…-submit-ui` card whose logic lives in its `…-submit-logic`
|
|
224
226
|
sibling): reviewing a pixels-only diff at Codex-`full` depth is waste, and the design-system
|
|
225
|
-
safety net still fires regardless of profile (a `light` card keeps its per-card
|
|
226
|
-
|
|
227
|
-
the
|
|
227
|
+
safety net still fires regardless of profile (a `light` card keeps its per-card code-review —
|
|
228
|
+
since v4.18.0 a per-card Codex finder + `code-reviewer` FP-gate — plus `code-reviewer` rule 8 /
|
|
229
|
+
the registry-first DS cascade, and is covered by the batch-wide Final FULL gate). Any
|
|
228
230
|
doubt — a hint of logic, state, data binding, a new/modified primitive, or `areas` beyond
|
|
229
231
|
`[ui]` — disqualifies branch (b): the card stays `balanced`. When in doubt between `balanced`
|
|
230
232
|
and `deep`, choose `deep`. `files_likely_touched` counts are advisory only — never downgrade a
|
|
@@ -65,21 +65,28 @@ For the (single) card in scope, check for `/tmp/codexreview-lean-<CARD-ID>.json`
|
|
|
65
65
|
api-perf-cost-auditor**, which runs batch-wide before merge — so a per-card run here would be a
|
|
66
66
|
duplicate. It is an independent breadth agent (NOT a Step 3 FP-gate validator), so omitting it is
|
|
67
67
|
safe (unlike `code-reviewer`, which the FP-gate depends on). *(A3)*
|
|
68
|
-
- `profile: "light"` →
|
|
69
|
-
|
|
70
|
-
(`
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
- `profile: "light"` → **Codex (agent #4) is the SOLE finder** (since v4.18.0 — inverts the
|
|
69
|
+
v3.38.0 "light drops Codex" choice). Omit agent #1 (`code-reviewer`) **as a Step-2 finder**, omit
|
|
70
|
+
agent #2 (`api-perf-cost-auditor`) and agent #3 (`doc-reviewer`), and **skip Step 3.5 (CoVe)**.
|
|
71
|
+
The **Step 3 false-positive gate STILL runs** (`code-reviewer` + `codebase-architect` validate the
|
|
72
|
+
Codex findings) — so `code-reviewer` is present at `light`, just as a *verifier*, not a finder.
|
|
73
|
+
This is the cost-shift lane: the diff sweep runs on Codex, Claude only validates the findings.
|
|
74
|
+
**Codex-unavailable fallback (MANDATORY)**: if the companion glob resolves empty, or Codex exits
|
|
75
|
+
non-zero / `CODEX_UNAVAILABLE`, **spawn agent #1 (`code-reviewer`) as the finder** (the pre-v4.18.0
|
|
76
|
+
`light` behavior) so the per-card review never silently vanishes; the Step 3 FP-gate then validates
|
|
77
|
+
its own findings as before. Any high-risk diff trigger escalates the card to `full` (both finders)
|
|
78
|
+
per the Review Profile Selector; the Final-review FULL gate re-runs Codex batch-wide regardless. *(B1)*
|
|
75
79
|
- `profile: "full"` (or missing) → full agent set incl. Codex adversarial, minus #3 if `skip_doc_reviewer`.
|
|
76
80
|
|
|
77
|
-
**Invariant**: lean mode NEVER suppresses the run itself — at minimum
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
**Invariant**: lean mode NEVER suppresses the run itself — at minimum a **finder + the Step 3 FP-gate**
|
|
82
|
+
execute on every card. At `light` the finder is **Codex** (or `code-reviewer` on the Codex-unavailable
|
|
83
|
+
fallback); at `full` both `code-reviewer` and Codex run as finders. If the contract file is
|
|
84
|
+
malformed/unreadable, fall back to **full mode** and note it. **Consume-once**: delete
|
|
85
|
+
`/tmp/codexreview-lean-<CARD-ID>.json` immediately after parsing it, so a later standalone
|
|
86
|
+
`/codexreview <CARD-ID>` on the same card never inherits a stale lean contract from a prior `/new` run.
|
|
87
|
+
Record the resolved mode in the Step 4 report `Method` section, e.g.
|
|
88
|
+
`lean: profile=light, architect=reused, doc-reviewer=skipped(Phase 3), codex=finder(light), code-reviewer=fp-gate, cove=skipped`
|
|
89
|
+
(or `codex=unavailable→code-reviewer finder(light)` when the fallback fired).
|
|
83
90
|
|
|
84
91
|
---
|
|
85
92
|
|
|
@@ -162,11 +169,14 @@ Launch these agents in parallel for each card:
|
|
|
162
169
|
> **Lean agent set (Step -0.5)**: when a contract file is active, launch only the agents the resolved
|
|
163
170
|
> mode permits — `skip_doc_reviewer` omits #3 (`doc-reviewer`); `skip_api_perf_auditor` omits #2
|
|
164
171
|
> (`api-perf-cost-auditor`) **even at `full`** (since v4.7.0 — deferred to the Final F.3 batch-wide
|
|
165
|
-
> auditor); `profile: light`
|
|
166
|
-
>
|
|
167
|
-
> `
|
|
168
|
-
>
|
|
169
|
-
>
|
|
172
|
+
> auditor); `profile: light` (since v4.18.0) launches **only agent #4 (Codex) as the finder** — agent
|
|
173
|
+
> #1 (`code-reviewer`) does NOT run as a Step-2 finder, #2 and #3 are omitted, and Step 3.5 CoVe is
|
|
174
|
+
> skipped; `code-reviewer` then runs in the **Step 3 FP-gate** as a verifier. **Codex-unavailable
|
|
175
|
+
> fallback at `light`**: if the companion is missing or errors, launch agent #1 (`code-reviewer`) as
|
|
176
|
+
> the finder instead (the Step 3 FP-gate validates its findings). At `full` with `skip_api_perf_auditor`,
|
|
177
|
+
> launch #1 + #4 (Codex) (+ #3 unless `skip_doc_reviewer`). At `full` with no skips (and in full mode
|
|
178
|
+
> with no contract file), launch all four. The standalone `/codexreview <CARD-ID>` invocation (no
|
|
179
|
+
> contract) is always full with the complete set.
|
|
170
180
|
|
|
171
181
|
**Codex invocation rules (agent #4):**
|
|
172
182
|
|
|
@@ -15,7 +15,7 @@ description: >
|
|
|
15
15
|
|
|
16
16
|
> **NO PHASE SKIP FOR PERCEIVED TIME, EVER (BLOCKING)**: MANDATORY phases are non-negotiable in BOTH sequential mode and team mode. The phrases `time budget`, `context budget`, `context pressure as override`, `for time`, `to save tokens`, `to save iterations`, or any model-invented constraint are NOT valid skip reasons. The only valid skip reasons are those explicitly enumerated in each phase's Gate table (e.g. `features.has_e2e_review: false`, backend-only diff, card type `docs`/`chore`/`config`, **the card's `review_profile`-driven review depth — see next paragraph — the `IS_TRIVIAL` fast-lane (`review_profile=skip` + non-source diff + 0 high-risk triggers), defined once in § "Trivial-card fast-lane", and the v4.7.0 Final-deferred reviews: plan-auditor grounding skipped on `/prd` holistic-audit provenance + no drift; per-card doc-review / qa-sentinel / api-perf-cost-auditor deferred to the unconditional Final FULL gate when their `review_profile`/provenance condition holds**). Documenting skipped phases at the end of a batch as `"saltati per time budget"` is a protocol violation per the FEAT-0006 incident — treat any such phrase in your own output as a self-correction trigger: stop, surface the situation via `AskUserQuestion`, and resume only after explicit user direction. Auto Mode does NOT override this. Team-mode orchestrators (L0/L1) propagate every MANDATORY phase per-card and never aggregate, reduce, or pre-filter the per-card pipeline **for any model-invented reason**.
|
|
17
17
|
|
|
18
|
-
> **REVIEW DEPTH SCALES WITH `review_profile` (deterministic — NOT a time/token skip)**: the review *depth* of a card MAY scale with its `review_profile` (the PRD-authored field, escalation-only via the Step-A detector — `light`→`full` never the reverse), exactly as the QA tier (D.4) and Codex `light`/`full` depth (D.4b / Phase 3.7 Step C) already do. This is an **enumerated, deterministic gate reason**, the polar opposite of a `time budget` skip: it is driven by a field a human authored at PRD time, not by the model's perception of how long the batch is taking. In **team mode**
|
|
18
|
+
> **REVIEW DEPTH SCALES WITH `review_profile` (deterministic — NOT a time/token skip)**: the review *depth* of a card MAY scale with its `review_profile` (the PRD-authored field, escalation-only via the Step-A detector — `light`→`full` never the reverse), exactly as the QA tier (D.4) and Codex `light`/`full` depth (D.4b / Phase 3.7 Step C) already do. This is an **enumerated, deterministic gate reason**, the polar opposite of a `time budget` skip: it is driven by a field a human authored at PRD time, not by the model's perception of how long the batch is taking. In **team mode** (since v4.18.0) every non-trivial card receives its per-card code review at the **D.4b `/codexreview`** pass: a `light` (0-trigger) card runs `/codexreview` at `profile: light` (**Codex finder + `code-reviewer` FP-gate**), a `full` card at `profile: full` (both finders). The D.2 group pass is now **doc-reviewer only** (the old D.2 group code-reviewer over light cards is removed — their code review moved to D.4b). `TRIVIAL_CARDS` (non-source diff) skip D.4b and rely on the doc-reviewer pass + the Final FULL gate. Every card still gets ≥1 per-card code review **plus** the cross-batch Final FULL gate. The **sequential** per-card pipeline is analogous (its Phase 3.7 `/codexreview` runs at `light`/`full` per the card profile). Skipping a gate WITHOUT an enumerated `review_profile`/Gate-table reason remains a protocol violation.
|
|
19
19
|
|
|
20
20
|
## Project Context
|
|
21
21
|
|
|
@@ -421,8 +421,8 @@ skip: it is gated entirely on deterministic, PRD-authored signals.
|
|
|
421
421
|
|
|
422
422
|
**Fail-safe guard (degrade toward MORE review, never less)**: if ANY condition fails — a single
|
|
423
423
|
source file in the diff, one Step-A trigger, or a non-`skip` profile — `IS_TRIVIAL=false` and the
|
|
424
|
-
card follows its normal path (in team mode that is `LIGHT_CARDS`: D.
|
|
425
|
-
sequential, the full per-card pipeline). A mis-authored `skip` on a code card, or a `skip` card
|
|
424
|
+
card follows its normal path (in team mode that is `LIGHT_CARDS`: D.4b `/codexreview` at `light` —
|
|
425
|
+
Codex finder + FP-gate — plus the Final FULL gate; in sequential, the full per-card pipeline). A mis-authored `skip` on a code card, or a `skip` card
|
|
426
426
|
whose text mentions `auth`/`payment`/etc., is therefore always caught. The classifier can only ever
|
|
427
427
|
*remove* review from a card that demonstrably has no code to review.
|
|
428
428
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
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
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`).
|
|
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`). Since v4.18.0 **both depths run Codex per-card**: at `light` Codex is the SOLE finder and `code-reviewer` validates in the FP-gate; at `full` both run as finders. So the BUG-0530-class "missed blocker on a low-risk path" guard is now carried directly (Codex sweeps every non-trivial card), reinforced by (1) the Step A detector escalating any risky diff to `full`, and (2) the unconditional **Final-review FULL gate** running Codex over the entire batch diff before merge. The Codex-unavailable fallback (`light` degrades to `code-reviewer` finder) keeps the merge gate intact when the companion is absent.
|
|
12
12
|
|
|
13
13
|
#### Step A — Detect (signal-logging only, NEVER gates the next step)
|
|
14
14
|
|
|
@@ -43,26 +43,28 @@ For EVERY card (no conditional skip — the gate ALWAYS runs; only its DEPTH var
|
|
|
43
43
|
The card's `review_profile` is the deterministic floor; the diff detector is the safety net on
|
|
44
44
|
top of it.
|
|
45
45
|
|
|
46
|
-
`light` is **NOT** a skip
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
`light` is **NOT** a skip. **Since v4.18.0 the per-card Codex pass runs at `light` as the SOLE
|
|
47
|
+
finder** (inverting the v3.38.0 choice that deferred Codex to the final cross-check). At `light`
|
|
48
|
+
`/codexreview` launches **Codex (finder)** + the **Step 3 false-positive gate** (`code-reviewer` +
|
|
49
|
+
`codebase-architect` validate the Codex findings) — dropping the breadth agents (qa-sentinel,
|
|
50
|
+
api-perf-cost-auditor, doc-reviewer) AND Step 3.5 CoVe. So `code-reviewer` is still present at
|
|
51
|
+
`light`, but as the *verifier*, not the finder: the diff sweep moves off Claude onto Codex (the
|
|
52
|
+
cost-shift), Claude only validates. `full` is unchanged (Codex adversarial + `code-reviewer` both as
|
|
53
|
+
finders + the full agent set, minus the duplicate doc-reviewer).
|
|
54
|
+
**Codex-unavailable fallback (MANDATORY).** If the companion glob resolves empty or Codex errors,
|
|
55
|
+
`light` degrades to **`code-reviewer` as the finder** (the pre-v4.18.0 behavior) + the FP-gate — the
|
|
56
|
+
per-card review never silently vanishes.
|
|
57
|
+
**Where the BUG-0530 invariant now lives.** The "never miss a blocker on a low-risk path" guard is
|
|
58
|
+
now carried **directly** — Codex sweeps every non-trivial card per-card — reinforced by two nets:
|
|
56
59
|
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/…)
|
|
58
|
-
Only a 0-trigger, authored-`light` card defers it.
|
|
60
|
+
so genuinely risky paths (auth/payment/permission/schema/…) get BOTH finders per-card.
|
|
59
61
|
2. **Final-review FULL gate (since v3.37.0)** — the **Final review ALWAYS runs a single FULL
|
|
60
62
|
`/codexreview` over the entire batch diff before merge** (no N=1 skip, no scope reduction — see
|
|
61
|
-
"Final review → Final-review FULL gate")
|
|
62
|
-
|
|
63
|
-
Net effect: `light` per-card =
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
"Final review → Final-review FULL gate"). So every line of every card is re-swept by Codex
|
|
64
|
+
batch-wide before merge.
|
|
65
|
+
Net effect: `light` per-card = Codex finder + `code-reviewer` FP-gate (or `code-reviewer` finder on
|
|
66
|
+
the Codex-unavailable fallback). To revert per-card Codex off `light`, restore the v3.38.0 `light`
|
|
67
|
+
branch of `/codexreview` Step -0.5 (`code-reviewer` finder only).
|
|
66
68
|
|
|
67
69
|
Then dump the card diff (reviewer grounding) and write the lean contract `/codexreview` consumes:
|
|
68
70
|
```bash
|
|
@@ -103,9 +105,11 @@ For EVERY card (no conditional skip — the gate ALWAYS runs; only its DEPTH var
|
|
|
103
105
|
|
|
104
106
|
`/codexreview` Step -0.5 consumes `/tmp/codexreview-lean-<CARD-ID>.json`: reuses the Phase-1
|
|
105
107
|
architecture baseline (no re-spawn), drops the duplicate doc-reviewer, and for `profile: light`
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
runs **Codex as the sole finder** (since v4.18.0) + the Step 3 FP-gate (`code-reviewer` +
|
|
109
|
+
`codebase-architect` validate), dropping qa-sentinel + api-perf-cost-auditor + Step 3.5 CoVe. On
|
|
110
|
+
Codex-unavailable, `light` degrades to `code-reviewer` finder. Step 3 FP-gate + Step 4 report ALWAYS
|
|
111
|
+
run. (`full` = standard pipeline incl. Codex adversarial + `code-reviewer` finder, minus the
|
|
112
|
+
duplicate doc-reviewer.)
|
|
109
113
|
|
|
110
114
|
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
115
|
- Verified BLOCKER count
|
|
@@ -114,7 +118,7 @@ For EVERY card (no conditional skip — the gate ALWAYS runs; only its DEPTH var
|
|
|
114
118
|
|
|
115
119
|
4. **Apply fix sub-loop** (mirror of Phase 3.5 retry pattern):
|
|
116
120
|
- 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**
|
|
121
|
+
- 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** (since v4.18.0) the findings come from **Codex** (the sole finder) — the report carries Codex's `minimal_fix_direction`; brief the coder to apply it (treat it like the `full`-profile Codex fix direction). **On the Codex-unavailable fallback** the `light` findings come from `code-reviewer` instead — brief the coder to apply the `code-reviewer` fix direction (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
122
|
- 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
123
|
- **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
124
|
|
|
@@ -161,12 +161,12 @@ After ALL agents in the group complete successfully:
|
|
|
161
161
|
- `FULL_CARDS` = all others (effective profile `balanced`/`deep`, OR any Step-A trigger).
|
|
162
162
|
- **Sub-classify `TRIVIAL_CARDS` ⊆ `LIGHT_CARDS`** = cards that are `IS_TRIVIAL` on the committed diff (§ "Trivial-card fast-lane": `review_profile == skip` AND 0 Step-A triggers AND **non-source diff**). These are the LIGHT cards that have nothing for `code-reviewer` to review. (A `skip` card whose diff DID touch a source file is in `LIGHT_CARDS` but NOT `TRIVIAL_CARDS` — the guard keeps it on the code-review path.)
|
|
163
163
|
- **Sub-classify `DOC_DEFER_CARDS`** (since v4.7.0, for #2 doc deferral) = cards with `review_profile == light` whose committed diff touches **NO documentation file** (no `.md`, no path under `${paths.references_dir}`, no data-model/ssot/api doc). Their per-card doc-review is deferred to the Final F.3 doc-reviewer. (Trivial cards, and any card whose diff touches a doc file, are NOT in this set — doc-review stays relevant for them.)
|
|
164
|
-
- Log: `## D.1.5 Effective Profiles\n<CARD-ID>: profile=<floor> triggers=<n> diff=<source|non-source> → effective=<light|full> (<LIGHT_CARDS|FULL_CARDS>)<, TRIVIAL / DOC_DEFER if applicable>` per card. This single computation is the SSOT for D.2 (
|
|
164
|
+
- Log: `## D.1.5 Effective Profiles\n<CARD-ID>: profile=<floor> triggers=<n> diff=<source|non-source> → effective=<light|full> (<LIGHT_CARDS|FULL_CARDS>)<, TRIVIAL / DOC_DEFER if applicable>` per card. This single computation is the SSOT for D.2 (doc-reviewer scoping), D.3b/D.3c (already skipped for trivial), and D.4b (inclusion + per-card Codex profile: `light` cards → `/codexreview` `light`, `full` cards → `full`) — do NOT recompute it downstream.
|
|
165
165
|
|
|
166
|
-
2. **D.2 — Combined static review (group)** —
|
|
167
|
-
- **doc-reviewer — over the group MINUS `DOC_DEFER_CARDS`** (since v4.7.0). It runs **read-only here
|
|
168
|
-
- **code-reviewer
|
|
169
|
-
- **Tradeoff (documented, accepted — see top-of-file `REVIEW DEPTH SCALES` clause)**:
|
|
166
|
+
2. **D.2 — Combined static review (group)** — **doc-reviewer only** (since v4.18.0 — the code-reviewer pass moved to D.4b; see below):
|
|
167
|
+
- **doc-reviewer — over the group MINUS `DOC_DEFER_CARDS`** (since v4.7.0). It runs **read-only here**, MUST **attribute every doc finding to a specific card** (by file → ownership map), and applies the full Phase 3 mandate INCLUDING the spec/docs-drift→bug lens (since v3.35.0). The `DOC_DEFER_CARDS` (light, no-doc diff per D.1.5) are excluded — their doc-review is deferred to the Final F.3 doc-reviewer (batch-wide). **If the group is entirely `DOC_DEFER_CARDS` → skip the D.2 doc-reviewer** and log `D.2 doc-reviewer: DEFERRED to Final FULL gate (all cards light + no-doc diff)`. D.4a consumes the per-card findings (for the non-deferred cards) and dispatches the doc-reviewer (in write mode) to apply them — no second AUDIT spawn, but the FIXES are still owned by doc-reviewer.
|
|
168
|
+
- **No D.2 code-reviewer (since v4.18.0).** Previously `code-reviewer` ran here over `LIGHT_CARDS \ TRIVIAL_CARDS` as their single per-card code review (to keep Codex off light). Now that `light` runs Codex per-card (Codex finder + FP-gate at D.4b — `code-reviewer` validates there), the light cards' code review lives at **D.4b** alongside the full cards. D.2 no longer spawns a code-reviewer; log `D.2 code-reviewer: N/A (light cards code-reviewed at D.4b via Codex-light since v4.18.0)`.
|
|
169
|
+
- **Tradeoff (documented, accepted — see top-of-file `REVIEW DEPTH SCALES` clause)**: every non-trivial card now reaches a per-card Codex pass at D.4b (light → Codex-light, full → Codex-full). `TRIVIAL_CARDS` (non-source diff) are still covered only by the doc-reviewer group pass + the Final FULL gate. The batch-wide **Final-review FULL gate** remains the cross-card safety net (Codex over the entire batch diff, plus code-reviewer fallback).
|
|
170
170
|
|
|
171
171
|
3. **D.3 — Apply fixes (group)** — If D.2 findings exist, spawn ONE fix-coder to apply all fixes in a single pass. Run build + lint after.
|
|
172
172
|
|
|
@@ -183,10 +183,11 @@ After ALL agents in the group complete successfully:
|
|
|
183
183
|
|
|
184
184
|
4a. **D.4a — Per-card doc gate (consumes D.2, since v3.35.0; doc-reviewer-applied since v3.40.0)** — Do NOT re-run the doc AUDIT (D.2 already produced per-card-attributed findings). If any card in the group has doc findings, invoke the **doc-reviewer once in write mode** over the group, passing the per-card-attributed findings from D.2, to APPLY all doc fixes in a single pass (it is now alone — code-reviewer is done — so the D.2 parallel-safety constraint no longer applies). Do **NOT** spawn a fix-coder for doc findings: `doc` is owned by `doc-reviewer` (see "Domain-Override Domains"); a code-oriented coder lacks the doc-invariant contract. The only exception is a doc-drift→bug finding rooted in CODE — that follows the D.4b code fix path. (Previously D.4a spawned a fix-coder per card; the audit was already collapsed to a single attributed D.2 pass. D.4b's per-card `/codexreview` also skips its doc-reviewer via the lean contract, so the doc AUDIT runs once per group while the doc FIXES run once per group via doc-reviewer.) **Telemetry** — append one row per applied doc finding to `## Fix Application Log`: `D.4a | doc | est_lines=<n> | decision=doc-reviewer | applied_by=doc-reviewer | card=<ID> | finding=<1-line>`. **Phase-8 producer (named counter)** — ALSO record per card the `doc_gaps: found=<N> fixed=<M>` line in that card's `## Completed Cards` entry (same named counter as sequential Phase 3 step 15), so Phase 8 reads `doc_gaps_found`/`doc_gaps_fixed` from a structured field, not a free-form row.
|
|
185
185
|
|
|
186
|
-
4b. **D.4b — Pre-Merge Codex Review Gate (per-card, profile-gated via D.1.5)** — Invoke `/codexreview` for **
|
|
187
|
-
- **`LIGHT_CARDS` →
|
|
188
|
-
- **`
|
|
189
|
-
|
|
186
|
+
4b. **D.4b — Pre-Merge Codex Review Gate (per-card, profile-gated via D.1.5)** — Invoke `/codexreview` for **EVERY non-trivial card** (i.e. all of `LIGHT_CARDS \ TRIVIAL_CARDS` plus all `FULL_CARDS`), one at a time, BEFORE any commit. This mirrors Phase 3.7 of the sequential path. (Since v4.18.0 `LIGHT_CARDS` are NO LONGER skipped here — `light` runs a per-card Codex pass.)
|
|
187
|
+
- **`LIGHT_CARDS \ TRIVIAL_CARDS` → run `/codexreview` at `profile: light`** (since v4.18.0): **Codex is the sole finder** + the Step 3 FP-gate (`code-reviewer` + `codebase-architect` validate); no api-perf/doc/CoVe. This is where these cards' per-card code review now lives (D.2 no longer code-reviews them). On Codex-unavailable, `light` degrades to `code-reviewer` finder. Log `codex-review: <verdict> (light — Codex finder + FP-gate)`.
|
|
188
|
+
- **`TRIVIAL_CARDS` → SKIP D.4b** (non-source diff — nothing for Codex to review; covered by the doc-reviewer group pass + the Final FULL gate). Log `codex-review: SKIPPED (trivial — non-source diff; covered by Final FULL gate)`.
|
|
189
|
+
- **`FULL_CARDS` → run `/codexreview` at `profile: full`** (Codex adversarial + `code-reviewer` finder + CoVe + FP-gate). Keep the sequential one-at-a-time loop (avoid N concurrent `/codexreview`, each of which fans out multiple sub-agents → rate-limit risk). ⚠️ Since light cards now also run here, the D.4b loop is longer per group — accepted cost of moving the diff sweep onto Codex.
|
|
190
|
+
Apply the same fix sub-loop as sequential Phase 3.7 Step C.4: if the consolidated report shows verified BLOCKER/HIGH findings, spawn a fix-coder and — **re-writing the consumed-once lean contract first** — re-invoke `/codexreview` via the Skill tool with `args: <CARD-ID>` (max 2 retries per card; a bare prose mention or a missing card-ID would let the retry review the wrong card). If still BLOCKER/HIGH after retries, ask the user before proceeding to D.5. The D.5 commits MUST NOT happen until every card in the group has a PASS verdict (or explicit user override via `AskUserQuestion`). Log results in the tracker under `## Pre-Merge Codex Review` per card. **Lean + profile (since v3.35.0)**: before each card's `/codexreview`, apply the same Review Profile Selector and write the same `/tmp/codexreview-lean-<CARD-ID>.json` contract as sequential Phase 3.7 Step C — `arch_baseline_path` pointing at `/tmp/arch-baseline-group-<FIRST-CARD-ID>.md`, `skip_doc_reviewer: true`, `skip_api_perf_auditor: true` (since v4.7.0 — api-perf deferred to the Final F.3 batch-wide auditor), and `profile` resolved from D.1.5 (`light` cards → `light`, `full` cards → `full`; do NOT recompute). The post-batch **Final-review FULL gate** (a single FULL `/codexreview` over the entire batch diff, which team mode reaches via "Post-batch — same as sequential mode") remains the cross-card safety net for every card including the trivial ones.
|
|
190
191
|
|
|
191
192
|
5. **D.5 — Commit** — One commit per card using explicit staging from the ownership map. **NO stash in worktrees** (stashes are globally shared via `refs/stash` — see Phase 4 WORKTREE COMMIT RULE):
|
|
192
193
|
```bash
|
|
@@ -220,10 +221,10 @@ Before moving to Step E, the orchestrator MUST verify the tracker contains, for
|
|
|
220
221
|
- `doc-review: <status | DEFERRED to Final FULL gate (DOC_DEFER_CARDS: light + no-doc diff)>` (from D.4a — runs for trivial cards too; the DEFERRED form is valid ONLY for `DOC_DEFER_CARDS` per D.1.5)
|
|
221
222
|
- `qa: <profile=... | verdict=... | mechanical-only (trivial) | DEFERRED to Final FULL gate (group max=balanced, no risk escalation)>` (group-level from D.4; the DEFERRED form is valid when the group max profile ≤ balanced with no Step-A escalation)
|
|
222
223
|
- `api-perf: <covered at D.4b | DEFERRED to Final FULL gate (skip_api_perf_auditor)>` (per-card — `skip_api_perf_auditor` defers it to F.3 batch-wide; DEFERRED is the normal v4.7.0 value)
|
|
223
|
-
- `code-review: <covered at D.
|
|
224
|
-
- `codex-review: <verdict
|
|
224
|
+
- `code-review: <covered at D.4b (Codex-light FP-gate or Codex-full) | SKIPPED (trivial — non-source diff)>` (per-card — since v4.18.0 light cards are code-reviewed at D.4b, not D.2; the trivial SKIP is valid ONLY for `TRIVIAL_CARDS` per the D.1.5 partition)
|
|
225
|
+
- `codex-review: <verdict (light — Codex finder + FP-gate) | verdict (full) | SKIPPED (trivial — non-source diff; covered by Final FULL gate)>` (per-card from D.4b — since v4.18.0 `LIGHT_CARDS` produce a Codex verdict, NOT a skip; the SKIPPED form is valid ONLY for `TRIVIAL_CARDS`)
|
|
225
226
|
|
|
226
|
-
A missing entry means a sub-step was skipped. An entry whose value is a **`review_profile`-driven SKIP/DEFER**, an **`IS_TRIVIAL` SKIP**, or a **`/prd`-provenance SKIP** with a documented enumerated reason above (D.3b `skip` profile; D.4b
|
|
227
|
+
A missing entry means a sub-step was skipped. An entry whose value is a **`review_profile`-driven SKIP/DEFER**, an **`IS_TRIVIAL` SKIP**, or a **`/prd`-provenance SKIP** with a documented enumerated reason above (D.3b `skip` profile; D.4b/code/codex `TRIVIAL_CARDS`; doc-review `DOC_DEFER_CARDS`; QA `group max=balanced, no escalation`; api-perf `skip_api_perf_auditor`; plan-auditor `holistic_audit provenance`) is a VALID, present entry — not a violation; all defer to the unconditional Final FULL gate. What remains forbidden: a missing entry, or a skip whose reason is `time budget` / `to save tokens` / any model-invented constraint. If any entry is genuinely missing, do NOT proceed to Step E — return to the missing sub-step and execute it. Documenting "skipped per time budget" or similar is a protocol violation per the top-of-file rigidity clause.
|
|
227
228
|
|
|
228
229
|
#### Step E: Context purge + next group
|
|
229
230
|
|
|
@@ -147,6 +147,9 @@ const PREFLIGHT_SCHEMA = {
|
|
|
147
147
|
// G2 — deterministic Codex availability (glob-resolved, NOT a self-reported judgement),
|
|
148
148
|
// so a false negative on the cross-card check is visible in telemetry. true=companion found.
|
|
149
149
|
codexResolved: { type: 'boolean' },
|
|
150
|
+
// v4.18.0 — the resolved companion path (absolute), threaded into per-card review so a
|
|
151
|
+
// `light` card can run Codex as its finder. Empty string when codexResolved is false.
|
|
152
|
+
codexScriptPath: { type: 'string' },
|
|
150
153
|
workspaceNote: { type: 'string' },
|
|
151
154
|
archBaselinePaths: { type: 'array', items: { type: 'string' } },
|
|
152
155
|
},
|
|
@@ -181,9 +184,13 @@ const projectBrief = [
|
|
|
181
184
|
// companion glob FIRST (existence taken out of the agent's judgement), run it in the
|
|
182
185
|
// BACKGROUND with a file poll, and forbid a premature CODEX_NOT_FOUND — same discipline as
|
|
183
186
|
// new-final-review.js, fixing the parallel false-negative the v4.17.1 fix #3 left here.
|
|
187
|
+
// v4.18.0 — resolve the Codex companion for EVERY batch (single + multi), because `light` cards now
|
|
188
|
+
// run a per-card Codex finder (not just the multi-card cross-card check). The glob decides existence,
|
|
189
|
+
// not the agent's judgement; the resolved PATH is threaded to runCard via sharedCtx.
|
|
190
|
+
const codexResolveBullet = `• Codex companion resolution (ALWAYS — single AND multi-card; needed for the per-card Codex-light review since v4.18.0): run \`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\`. Set codexResolved:true AND codexScriptPath:<the printed absolute path> IFF it prints a path (existence is glob-decided, NOT your judgement); else codexResolved:false AND codexScriptPath:''. ALWAYS return BOTH fields.\n`
|
|
184
191
|
const g3Bullet = cardIds.length < 2
|
|
185
|
-
? `• G3 cross-card grounding: SKIPPED — only one runnable card, nothing cross-card exists. Set crossCard='N/A-single-card'
|
|
186
|
-
: `• G3 cross-card grounding (setup.md 3d), MULTI-card:
|
|
192
|
+
? `• G3 cross-card grounding: SKIPPED — only one runnable card, nothing cross-card exists. Set crossCard='N/A-single-card'. (The Codex companion is still resolved per the bullet above, for the per-card Codex-light review.)\n`
|
|
193
|
+
: `• G3 cross-card grounding (setup.md 3d), MULTI-card: using the codexScriptPath resolved above, IF codexResolved run the cross-card conflict check by launching \`node "$codexScriptPath" task "<cross-card conflict questions: FILE_CONFLICT/IMPLICIT_DEP/ORDER_RISK/STATE_MUTATION>" > "$FILE" 2>&1\` in the BACKGROUND (run_in_background:true) and POLL "$FILE" to completion (full window). Read the audit ONLY via the [codex]-stripping filter; return DISTILLED findings. Set crossCard='CAPABILITY_UNAVAILABLE' ONLY when codexResolved is false, or it resolved but "$FILE" held CODEX_NOT_FOUND / stayed empty after the FULL window — NEVER because a single synchronous Bash call returned slowly. Provenance-skip still applies (same-provenance cards → nothing cross-card). If conflicts FOUND you MUST APPLY them: FILE_CONFLICT/ORDER_RISK → force the cards SEQUENTIAL and encode it in dependsOn (the conflicting later card dependsOn the earlier).\n`
|
|
187
194
|
phase('Pre-flight')
|
|
188
195
|
let preflight = null
|
|
189
196
|
try {
|
|
@@ -194,6 +201,7 @@ try {
|
|
|
194
201
|
`DETERMINISTIC GATE POLICIES (NO user prompts):\n` +
|
|
195
202
|
`• G1 dirty-tree (main repo ${MAIN}): partition framework-managed noise exactly as setup.md step 3 ($METRICS=${METRICS}, .baldart/generated|state.json|skill-conflicts.json — NOT overlays/). Genuine user work → auto-stash 'baldart-new2-${firstCard}' (main checkout) and record the label. Never commit/abort/prompt.\n` +
|
|
196
203
|
`• Worktree (setup.md step 4): create ONE code worktree off ${TRUNK}; install deps; assign a port; run the baseline (tsc+lint+build). Copy ONLY the artifacts needed (env/.env.local/.env.example/supabase/.temp) — do NOT bulk-copy untracked files from the main repo (avoids stray backlog cards in the worktree). Use the git-authoritative idempotency pre-check. E2: baseline FAILS → fix once; still failing → baseline:'fail' + baselineLog (batch-fatal).\n` +
|
|
204
|
+
codexResolveBullet +
|
|
197
205
|
g3Bullet +
|
|
198
206
|
`• G4 card-field validation (setup.md 1b/1c): card missing requirements/acceptance_criteria/files_likely_touched → EXCLUDE (excluded[] + reason). Never HALT for one bad card.\n` +
|
|
199
207
|
`• G5 depends-on: a card whose depends_on names a non-DONE card NOT in this batch → EXCLUDE it AND every in-batch card that transitively depends on it.\n` +
|
|
@@ -217,8 +225,9 @@ if (!preflight || preflight.ok === false || preflight.baseline === 'fail') {
|
|
|
217
225
|
for (const ex of preflight.excluded || []) ledger(ex.card, 'preflight-exclude', 'EXCLUDED', ex.reason)
|
|
218
226
|
if (preflight.workspaceNote) ledger(firstCard, 'G1/G2-workspace', 'AUTO', preflight.workspaceNote)
|
|
219
227
|
if (preflight.crossCard) ledger(firstCard, 'G3-cross-card', 'INFO', preflight.crossCard)
|
|
220
|
-
// G2 — surface the deterministic Codex availability (
|
|
221
|
-
|
|
228
|
+
// G2/v4.18.0 — surface the deterministic Codex availability (now probed for every batch; drives
|
|
229
|
+
// both the multi-card cross-card check AND the per-card Codex-light finder).
|
|
230
|
+
ledger(firstCard, 'codex-companion', preflight.codexResolved ? 'RESOLVED' : 'FALLBACK', preflight.codexResolved ? `glob-resolved → per-card Codex-light enabled (${preflight.codexScriptPath || '?'})` : 'companion not found → code-reviewer finder fallback')
|
|
222
231
|
|
|
223
232
|
const runnableCards = preflight.cards || []
|
|
224
233
|
const cardGraph = preflight.cardGraph || []
|
|
@@ -229,6 +238,9 @@ const sharedCtx = {
|
|
|
229
238
|
branch: preflight.branch,
|
|
230
239
|
ownershipMapPath: preflight.ownershipMapPath,
|
|
231
240
|
archBaselinePaths: preflight.archBaselinePaths || [],
|
|
241
|
+
// v4.18.0 — per-card Codex-light finder needs the resolved companion path in runCard scope.
|
|
242
|
+
codexResolved: !!preflight.codexResolved,
|
|
243
|
+
codexScriptPath: preflight.codexScriptPath || '',
|
|
232
244
|
}
|
|
233
245
|
|
|
234
246
|
// F-016/F-010 — materialise ONE follow-up per policy-deferred AC up front; never resolve.
|
|
@@ -383,20 +395,39 @@ async function runCard(cardId, cardPath, lessons) {
|
|
|
383
395
|
const securityRelevant = highRisk.length
|
|
384
396
|
|| ownerAgent === 'security-reviewer'
|
|
385
397
|
|| /auth|security|secret|migration|rls/i.test(`${scopeFiles.join(' ')} ${cardBrief}`)
|
|
398
|
+
// v4.18.0 — at `light`, Codex is the SOLE finder (cost-shift off Claude); `code-reviewer` is the
|
|
399
|
+
// fallback when the companion is unavailable. The FP-gate equivalent is preserved downstream: any
|
|
400
|
+
// block routes through resolve(), whose mandatory adversarial judge (new2-resolve F-015, code domain
|
|
401
|
+
// → code-reviewer) cross-checks the Codex finding before a fix/followup. `balanced`/`deep` unchanged.
|
|
402
|
+
const codexAvail = !!sharedCtx.codexResolved && !!sharedCtx.codexScriptPath
|
|
386
403
|
const reviewers = reviewProfile === 'skip' ? []
|
|
387
|
-
: reviewProfile === 'light' ? ['code-reviewer']
|
|
404
|
+
: reviewProfile === 'light' ? (codexAvail ? ['codex'] : ['code-reviewer'])
|
|
388
405
|
: ['code-reviewer', 'doc-reviewer', 'qa-sentinel', 'api-perf-cost-auditor'].concat(
|
|
389
406
|
securityRelevant ? ['security-reviewer'] : [])
|
|
407
|
+
const reviewSchema = { type: 'object', required: ['blocks', 'scopeExpansion'], additionalProperties: true,
|
|
408
|
+
properties: { blocks: { type: 'array', items: { type: 'object', additionalProperties: true } }, scopeExpansion: { type: 'array', items: { type: 'object', additionalProperties: true } }, note: { type: 'string' } } }
|
|
390
409
|
let reviewResults = []
|
|
391
410
|
try {
|
|
392
|
-
reviewResults = (await parallel(reviewers.map((ra) => () =>
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
411
|
+
reviewResults = (await parallel(reviewers.map((ra) => () => {
|
|
412
|
+
const onErr = (e) => { if (e && e.transientExhausted) noteDegraded('outage'); return null }
|
|
413
|
+
if (ra === 'codex') {
|
|
414
|
+
// Codex-light finder: a general-purpose agent drives the resolved companion (Bash, --wait).
|
|
415
|
+
return agentSafe(
|
|
416
|
+
`You are the Codex review driver for card ${cardId} (review_profile=light — Codex is the SOLE finder since v4.18.0; you are NOT code-reviewer). Run the OpenAI Codex companion as a REVIEW-ONLY adversarial pass over this card's diff, then return its material findings in the schema below.\n\n${cardBrief}\nDiff: /tmp/diff-${cardId}.txt\nMAY-EDIT: ${JSON.stringify(mayEdit)}\n\n` +
|
|
417
|
+
`Run it in the FOREGROUND (it blocks; do NOT pass run_in_background):\n node "${sharedCtx.codexScriptPath}" task "Review-only — DO NOT make edits, no --write flag. Adversarial review of card ${cardId} using the diff at /tmp/diff-${cardId}.txt. Focus: auth/permission boundaries, data-loss paths, race conditions, rollback safety, schema drift, invariant violations. Report ONLY material findings with file+line evidence." --wait\n` +
|
|
418
|
+
`Read the Codex output ONLY through a [codex]-trace-stripping filter. **Fallback**: if it exits non-zero / prints CODEX_NOT_FOUND / stays empty, set note='codex-unavailable' and perform the review yourself with the code-reviewer lens (your domain).\n\n` +
|
|
419
|
+
`Map Codex BLOCKER/HIGH findings to blocks:[{gate:'codex-light',domain,evidence}] (each non-empty gate AND evidence — F-014). Map legitimate findings BEYOND this card's AC to scopeExpansion:[{evidence,domain,withinOwnership,newAC}].\n\n` +
|
|
420
|
+
`Return: { blocks:[...], scopeExpansion:[...], note }`,
|
|
421
|
+
{ label: `review:${cardId}:codex`, phase: 'Implement', agentType: 'general-purpose', schema: reviewSchema }
|
|
422
|
+
).catch(onErr)
|
|
423
|
+
}
|
|
424
|
+
return agentSafe(
|
|
425
|
+
`You are ${ra}. Review card ${cardId} per ${REF}/review-cycle.md + ${REF}/codex-gate.md (your domain only). Run your gates on the COMMITTED-or-working state.\n\n${cardBrief}\nDiff: /tmp/diff-${cardId}.txt\n\n` +
|
|
426
|
+
`Report ONLY blocking failures that survive your retry cap as blocks:[{gate,domain,evidence}] (each MUST have non-empty gate AND evidence — F-014). Report legitimate findings BEYOND this card's AC as scopeExpansion:[{evidence,domain,withinOwnership,newAC}].\n\n` +
|
|
427
|
+
`Return: { blocks:[...], scopeExpansion:[...], note }`,
|
|
428
|
+
{ label: `review:${cardId}:${ra}`, phase: 'Implement', agentType: ra, schema: reviewSchema }
|
|
429
|
+
).catch(onErr)
|
|
430
|
+
}))).filter(Boolean)
|
|
400
431
|
} catch (_) { /* parallel never rejects; nulls filtered */ }
|
|
401
432
|
|
|
402
433
|
// F-014 — only route well-formed blocks (non-empty gate+evidence).
|
|
@@ -665,7 +696,7 @@ function buildTelemetry() {
|
|
|
665
696
|
degraded,
|
|
666
697
|
degradation_reasons: degradationReasons,
|
|
667
698
|
execution_mode: preflight ? preflight.executionMode : 'sequential',
|
|
668
|
-
codex_resolved:
|
|
699
|
+
codex_resolved: preflight ? !!preflight.codexResolved : null, // v4.18.0 — probed for EVERY batch (drives per-card Codex-light + multi-card cross-card)
|
|
669
700
|
// cost — total_tokens via budget.spent() delta; agent_count via counter; wall_clock_s stamped by the SKILL.
|
|
670
701
|
total_tokens: totalTokens,
|
|
671
702
|
agent_count: agentCount,
|
|
@@ -10,6 +10,15 @@ schedule:
|
|
|
10
10
|
|
|
11
11
|
agent: code-reviewer
|
|
12
12
|
|
|
13
|
+
# Review engine (since v4.18.0 — opt-in, additive, default claude). `codex` shifts the finding
|
|
14
|
+
# pass onto the OpenAI Codex companion to spend on a Codex licence instead of Claude tokens.
|
|
15
|
+
# IMPORTANT: only the `cron` backend supports `codex` — it needs the Codex plugin + `~/.codex/`
|
|
16
|
+
# authenticated in the cron user's home. The `github-actions` and `claude-code-cloud` backends
|
|
17
|
+
# fall back to `claude` with a warning (no Codex plugin / unknown remote schema). With `codex`,
|
|
18
|
+
# specialist auto-spawn is NOT available (Codex cannot spawn subagents) — use `claude` when you
|
|
19
|
+
# need the security-reviewer / api-perf-cost-auditor depth. See framework/docs/WORKFLOWS.md.
|
|
20
|
+
review_engine: claude
|
|
21
|
+
|
|
13
22
|
prompt: |
|
|
14
23
|
Run the nightly code review:
|
|
15
24
|
|
|
@@ -30,6 +39,22 @@ prompt: |
|
|
|
30
39
|
Scope is changed files only. Pre-existing code is not in scope unless
|
|
31
40
|
a change introduces a regression there.
|
|
32
41
|
|
|
42
|
+
# Used ONLY when review_engine: codex (cron backend). Single-pass adversarial review — Codex
|
|
43
|
+
# cannot spawn specialist subagents, so this is holistic (no security-reviewer / api-perf split).
|
|
44
|
+
prompt_codex: |
|
|
45
|
+
Review-only adversarial pass — DO NOT make edits, no --write flag.
|
|
46
|
+
|
|
47
|
+
1. Compute the diff for commits from the last 24h on the main / develop branch
|
|
48
|
+
(changed files only; pre-existing code in scope only if a change regresses it).
|
|
49
|
+
2. Holistic single-pass review (NO specialist subagents available): bugs, regressions,
|
|
50
|
+
logic flaws, AND — since there is no specialist split — also cover auth/permission
|
|
51
|
+
boundaries, data-loss paths, race conditions, and obvious API/perf/cost defects yourself.
|
|
52
|
+
3. Report only material findings with file+line evidence, ordered by severity.
|
|
53
|
+
4. Write the consolidated report to `docs/reports/{{YYYYMMDD}}-code-review.md`.
|
|
54
|
+
|
|
55
|
+
NOTE: this engine trades specialist depth for cost-shift onto the Codex licence. For full
|
|
56
|
+
security-reviewer / api-perf-cost-auditor coverage, set review_engine: claude.
|
|
57
|
+
|
|
33
58
|
output:
|
|
34
59
|
path: docs/reports/{{YYYYMMDD}}-code-review.md
|
|
35
60
|
commit:
|
package/package.json
CHANGED
|
@@ -53,10 +53,16 @@ class ClaudeCodeCloudAdapter {
|
|
|
53
53
|
installed_at: new Date().toISOString()
|
|
54
54
|
};
|
|
55
55
|
fs.writeFileSync(this.configPath(spec.name), JSON.stringify(config, null, 2) + '\n');
|
|
56
|
+
// review_engine: codex is cron-only — the RemoteTrigger config schema does not carry it and the
|
|
57
|
+
// cloud runner is not guaranteed to have the Codex plugin/auth — so this backend always uses claude.
|
|
58
|
+
const codexWarn = String(spec.review_engine || '').toLowerCase() === 'codex'
|
|
59
|
+
? [`⚠ review_engine: codex is NOT supported on claude-code-cloud — this routine runs on the claude engine.`]
|
|
60
|
+
: [];
|
|
56
61
|
return {
|
|
57
62
|
backend: this.name,
|
|
58
63
|
artifacts: [path.relative(this.cwd, this.configPath(spec.name))],
|
|
59
64
|
followup: [
|
|
65
|
+
...codexWarn,
|
|
60
66
|
`Open Claude Code in this repo and run:`,
|
|
61
67
|
` /schedule create --config .claude/routines/${spec.name}.json`,
|
|
62
68
|
`(or invoke the agent once with /loop ${spec.schedule.cron} <command> to test the cadence)`
|
|
@@ -76,6 +76,10 @@ class CronAdapter {
|
|
|
76
76
|
const commitEnabled = spec.output && spec.output.commit && spec.output.commit.enabled;
|
|
77
77
|
const commitPrefix = (spec.output && spec.output.commit && spec.output.commit.prefix) || `[${spec.name.toUpperCase()}]`;
|
|
78
78
|
const promptHeredoc = spec.prompt;
|
|
79
|
+
// review_engine (since v4.18.0): cron is the ONLY backend that supports `codex`. When set, the
|
|
80
|
+
// wrapper drives the OpenAI Codex companion and falls back to `claude --agent` if it is absent.
|
|
81
|
+
const engine = String(spec.review_engine || 'claude').toLowerCase();
|
|
82
|
+
const promptCodex = spec.prompt_codex || spec.prompt;
|
|
79
83
|
const repoRoot = '"$(cd "$(dirname "$0")/../.." && pwd)"';
|
|
80
84
|
|
|
81
85
|
return `#!/usr/bin/env bash
|
|
@@ -99,7 +103,13 @@ if ! command -v claude >/dev/null 2>&1; then
|
|
|
99
103
|
echo "ERROR: claude CLI not found on PATH" >&2
|
|
100
104
|
exit 1
|
|
101
105
|
fi
|
|
102
|
-
|
|
106
|
+
${engine === 'codex'
|
|
107
|
+
? `# review_engine: codex — Codex authenticates via the plugin + ~/.codex (NOT ANTHROPIC_API_KEY).
|
|
108
|
+
# The key is only needed if the run falls back to claude, so this is a soft warning, not a hard stop.
|
|
109
|
+
if [ -z "\${ANTHROPIC_API_KEY:-}" ]; then
|
|
110
|
+
echo "NOTE: ANTHROPIC_API_KEY unset — fine for the Codex engine, but the claude fallback would fail." >&2
|
|
111
|
+
fi`
|
|
112
|
+
: `: "\${ANTHROPIC_API_KEY:?ANTHROPIC_API_KEY must be set (export it from the cron env or your shell profile)}"`}
|
|
103
113
|
|
|
104
114
|
# Marks this as an unattended (no-human) run. The /baldart-update skill (and
|
|
105
115
|
# any other autonomy-aware skill) auto-detects this and switches to
|
|
@@ -113,17 +123,37 @@ OUT_PATH="${outputPath}"
|
|
|
113
123
|
OUT_PATH="\${OUT_PATH//\\{\\{YYYYMMDD\\}\\}/$DATE}"
|
|
114
124
|
mkdir -p "$(dirname "$OUT_PATH")"
|
|
115
125
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
126
|
+
# Claude engine (also the fallback for the Codex engine).
|
|
127
|
+
run_claude() {
|
|
128
|
+
claude --print --output-format json --mode bypassPermissions \\
|
|
129
|
+
--agent ${spec.agent} \\
|
|
130
|
+
> /tmp/baldart-${spec.name}.json <<'PROMPT'
|
|
119
131
|
${promptHeredoc}
|
|
120
132
|
PROMPT
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
# Persist the output if the agent did not already write to disk
|
|
134
|
+
if [ ! -s "$OUT_PATH" ]; then
|
|
135
|
+
jq -r '.result // .' /tmp/baldart-${spec.name}.json > "$OUT_PATH" 2>/dev/null \\
|
|
136
|
+
|| cp /tmp/baldart-${spec.name}.json "$OUT_PATH"
|
|
137
|
+
fi
|
|
138
|
+
}
|
|
139
|
+
${engine === 'codex'
|
|
140
|
+
? `# review_engine: codex — resolve the OpenAI Codex companion (glob decides existence, not us).
|
|
141
|
+
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)"
|
|
142
|
+
if [ -n "$CODEX_SCRIPT" ] && command -v node >/dev/null 2>&1; then
|
|
143
|
+
echo "Codex engine: $CODEX_SCRIPT"
|
|
144
|
+
node "$CODEX_SCRIPT" task "$(cat <<'CODEXPROMPT'
|
|
145
|
+
${promptCodex}
|
|
146
|
+
CODEXPROMPT
|
|
147
|
+
)" --wait > "$OUT_PATH" 2>/tmp/baldart-${spec.name}-codex.err || true
|
|
148
|
+
if [ ! -s "$OUT_PATH" ]; then
|
|
149
|
+
echo "WARN: Codex produced no output (see /tmp/baldart-${spec.name}-codex.err) — falling back to claude" >&2
|
|
150
|
+
run_claude
|
|
151
|
+
fi
|
|
152
|
+
else
|
|
153
|
+
echo "WARN: CODEX_NOT_FOUND — codex plugin / ~/.codex not present for this user, or node missing — falling back to claude" >&2
|
|
154
|
+
run_claude
|
|
155
|
+
fi`
|
|
156
|
+
: `run_claude`}
|
|
127
157
|
${commitEnabled ? `
|
|
128
158
|
# Auto-commit the report and any inline fixes
|
|
129
159
|
if git diff --quiet && git diff --staged --quiet; then
|
|
@@ -36,10 +36,15 @@ class GitHubActionsAdapter {
|
|
|
36
36
|
}
|
|
37
37
|
const yml = this._renderWorkflow(spec);
|
|
38
38
|
fs.writeFileSync(this.workflowPath(spec.name), yml);
|
|
39
|
+
// review_engine: codex is cron-only (no Codex plugin/auth in CI) — this backend always uses claude.
|
|
40
|
+
const codexWarn = String(spec.review_engine || '').toLowerCase() === 'codex'
|
|
41
|
+
? [`⚠ review_engine: codex is NOT supported on github-actions (no Codex plugin/auth in CI) — this routine runs on the claude engine.`]
|
|
42
|
+
: [];
|
|
39
43
|
return {
|
|
40
44
|
backend: this.name,
|
|
41
45
|
artifacts: [path.relative(this.cwd, this.workflowPath(spec.name))],
|
|
42
46
|
followup: [
|
|
47
|
+
...codexWarn,
|
|
43
48
|
`Set the repository secret ANTHROPIC_API_KEY in GitHub.`,
|
|
44
49
|
`Commit and push .github/workflows/baldart-${spec.name}.yml to enable the schedule.`,
|
|
45
50
|
`Manual test: gh workflow run baldart-${spec.name}.yml`
|