baldart 5.4.0 → 5.4.1

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,31 @@ 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
+ ## [5.4.1] - 2026-07-03
9
+
10
+ **Minimal light lane — the roster for a simple card is now literally: grounding (inline),
11
+ coder, code review, doc review, commit, merge. Nothing else.** Completes v5.4.0 per the
12
+ maintainer's directive ("per cose così semplici voglio due passaggi in croce"): the compact
13
+ lane cut the CARD COUNT; this cuts the per-run AGENT COUNT. FEAT-0067-class run: ~33
14
+ agents → ~7.
15
+
16
+ - **Per-card doc review at light (single-card batch)**: the light review matrix adds the
17
+ scoped `doc-reviewer` per-card (review-cycle.md deferral-gate exception) because the
18
+ Final pass it used to defer to is now skippable.
19
+ - **Final Review skip gate (`final-review.md` § F.0 + `new2.js` `skipFinalLight`)**: ONE
20
+ light card + zero actionable per-card findings (→ zero fixes applied) → skip F.2–F.5
21
+ entirely. Honors the v4.56.1 refutation (per-card PRE-fix + final POST-fix are
22
+ non-redundant) by scoping the skip to runs where there IS no post-fix state; any
23
+ finding, fix, second card, or degraded reviewer → Final runs as always.
24
+ - **i18n fill spawn cut at light**: the owner briefing instructs the coder to fill every
25
+ target locale itself; the anti-hardcoded lint + locale-parity gates still enforce.
26
+ - **Production-readiness spawn cut for all-light batches**: no deployable surface exists
27
+ by Rule C (no migrations/indexes/cron/schema) — the agent only ever reported zero items.
28
+ - `check-new-parity.mjs` rule 18 locks the prose↔workflow lockstep for every cut.
29
+ - Skills: `new` 2.2.0 · `new2` 1.6.0.
30
+
31
+ Codex parity: portable (prose modules are the cross-tool SSOT; `new2.js` Claude-only by design).
32
+
8
33
  ## [5.4.0] - 2026-07-03
9
34
 
10
35
  **Elastic pipeline — `/prd`+`/new` compress to the minimum for trivial features and
package/VERSION CHANGED
@@ -1 +1 @@
1
- 5.4.0
1
+ 5.4.1
@@ -2,6 +2,17 @@
2
2
 
3
3
  Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
4
4
 
5
+ ## 2.2.0 — 2026-07-03 (framework v5.4.1)
6
+
7
+ - **Minimal light lane — roster cut to the core four.** A single light card now runs:
8
+ grounding-inline (step 2d) → owner → code review (Codex-light/code-reviewer) → scoped
9
+ doc-reviewer per-card (review-cycle deferral exception) → commit → merge. Cut for the
10
+ lane: i18n fill spawn (7c — owner fills locales inline, lint gate enforces), Final
11
+ Review when the per-card review is clean (final-review.md § F.0 Minimal-light skip
12
+ gate — POST-fix verification with zero fixes is vacuous; any finding/fix/second card →
13
+ Final runs), production-readiness spawn for all-light batches (no deployable surface
14
+ by Rule C). Guarded by check-new-parity rule 18.
15
+
5
16
  ## 2.1.0 — 2026-07-03 (framework v5.4.0)
6
17
 
7
18
  - **Light-lane inline grounding (implement.md step 2d).** A `review_profile: light` card
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: new
3
3
  effort: medium
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  description: >
6
6
  Orchestrate a team of specialized agents to implement one or more backlog cards
7
7
  end-to-end inside a dedicated worktree, with code review, doc review, QA, and
@@ -42,6 +42,19 @@ Once ALL cards are committed in the worktree:
42
42
  > A single card has no cross-card surface, so a finder's per-card pass and its final pass are genuinely
43
43
  > the same review.
44
44
 
45
+ ### Step F.0 — Minimal-light skip gate (v5.4.1)
46
+
47
+ When the batch has exactly ONE committed card AND it is `review_profile: light` AND its
48
+ per-card review surfaced ZERO actionable findings (no blocks, no scope-expansion → no fix
49
+ pass was applied), **SKIP the entire Final Review** (F.2–F.5) and proceed to merge. The
50
+ Final pass exists for POST-fix verification and cross-card surface (v4.56.1 — per-card
51
+ PRE-fix + final POST-fix are non-redundant); with zero fixes and zero cross-card surface,
52
+ both reasons are absent — and doc coverage already ran per-card (the single-card light
53
+ review matrix includes the scoped doc-reviewer instead of deferring here, see
54
+ review-cycle.md § Deferral gate). Any finding on the card, any fix applied, any second
55
+ card, or any degraded reviewer → run the Final Review as written below. Log
56
+ `final-review: SKIPPED (single light card, clean per-card review — nothing post-fix to verify)`.
57
+
45
58
  ### Step F.1 — Resolve scope
46
59
 
47
60
  (All cards are committed; the batch now enters Final Review. No visibility emission — the internal tracker is the only state surface, see SKILL.md § "State surface — the tracker only". Record the Final-Review start/finish in the tracker only.)
@@ -500,7 +500,7 @@
500
500
  - **Grounding (cheap `grep`, like the Phase-1 plan-auditor grounding):** every cited source symbol/class MUST appear in `mockups/_src/` (`grep -rF "<symbol>" <prd_dir>/<slug>/mockups/_src/`), and every cited registry primitive MUST exist in the registry (`grep` `${paths.design_system}/INDEX.md` / `components/`). A symbol that is not in the source, or a primitive that is not in the registry, means a fabricated declaration → reject + re-spawn (do NOT pass it to the gates). Log `design-source: grounded` or `design-source: rejected (<reason>)` in the tracker.
501
501
  - This does NOT re-verify pixels — that stays with `visual-fidelity-verifier` (Phase 2.6). It only proves the source was read and the reuse-mapping targets are real. When the card has no design source, skip this step entirely.
502
502
 
503
- 7c. **i18n fill pass (explicit, deterministic — v5.0.0, promoted from the step-9 sub-bullet).** When `features.has_i18n: true` AND this card's diff added new source-locale keys — detect deterministically, never by intuition:
503
+ 7c. **i18n fill pass (explicit, deterministic — v5.0.0, promoted from the step-9 sub-bullet).** **Light lane (v5.4.1): SKIP this spawn** — on the light lane (step 2d) the owner briefing already instructed the coder to fill EVERY target locale itself (context-aware from the registry); the anti-hardcoded lint + locale-parity gates at step 8 enforce it. Log `i18n-fill: SKIP (light lane — owner fills inline)`. Otherwise: when `features.has_i18n: true` AND this card's diff added new source-locale keys — detect deterministically, never by intuition:
504
504
  ```bash
505
505
  cd <worktree-path>
506
506
  # $SRC_LOCALE = the source-language locale file path (from i18n config / the project's locales root)
@@ -6,6 +6,12 @@
6
6
 
7
7
  After Phase 6 completes (or after the final summary report if Phase 6 is deferred), present a **Production Readiness Checklist** — a clear list of all manual or infrastructure actions required to launch the implemented changes in production.
8
8
 
9
+ > **Minimal light lane (v5.4.1): SKIP the spawn for an all-`light` batch** — a light card
10
+ > carries no deployable surface by Rule C (no migrations, indexes, cron, schema, env); the
11
+ > checklist agent would only report zero items. Log
12
+ > `phase7-production: SKIPPED (all-light batch — no deployable surface)`. Any
13
+ > `balanced`/`deep` card in the batch → run as written.
14
+
9
15
  ### How to detect items
10
16
 
11
17
  Scan ALL files changed across the batch (use the tracker's completed cards + `git diff` against the base branch) and check for the items below.
@@ -305,7 +305,7 @@ skill's Phase 1 falls back to deriving Gherkin scenarios from
305
305
 
306
306
  > **Note**: Code review is NOT performed in this phase — it is handled by the **mandatory unconditional `/codexreview` gate in Phase 3.7**, which runs per-card BEFORE the Phase 4 commit. The post-batch `/codexreview` in the Final review remains as a final FULL-diff sweep over the entire batch (since v3.37.0 — the guaranteed full-depth merge gate). This Phase 3 focuses exclusively on documentation sync, which must happen per-card (tied to the specific commit).
307
307
 
308
- > **Deferral gate (since v4.7.0 — enumerated, `review_profile`-driven)**: SKIP per-card doc-review and defer it to the **Final Review F.3 doc-reviewer** (which runs over the entire batch) when the card is **`review_profile == light` AND its committed diff touches NO documentation file** (no `.md`, no path under `${paths.references_dir}`, no data-model/ssot/api doc). These are small code changes with no doc surface of their own; their only doc concern is drift, which the batch-wide Final doc-reviewer catches. Log `doc-review: DEFERRED to Final FULL gate (light, no doc files in diff)` and proceed to Phase 3.5. **KEEP per-card doc-review** for: `deep` cards, `balanced` cards (they may still PASS-fast via the deterministic gate below — that gate, not this deferral, is their only skip lane), ANY card whose diff touches a doc file (the change IS doc-relevant), and trivial cards (doc-review is their primary gate — § "Trivial-card fast-lane", unchanged). Never defer "for time" — the only enumerated reasons are `light + non-doc diff` and the deterministic PASS-fast below.
308
+ > **Deferral gate (since v4.7.0 — enumerated, `review_profile`-driven)**: SKIP per-card doc-review and defer it to the **Final Review F.3 doc-reviewer** (which runs over the entire batch) when the card is **`review_profile == light` AND its committed diff touches NO documentation file** (no `.md`, no path under `${paths.references_dir}`, no data-model/ssot/api doc). These are small code changes with no doc surface of their own; their only doc concern is drift, which the batch-wide Final doc-reviewer catches. Log `doc-review: DEFERRED to Final FULL gate (light, no doc files in diff)` and proceed to Phase 3.5. **KEEP per-card doc-review** for: `deep` cards, `balanced` cards (they may still PASS-fast via the deterministic gate below — that gate, not this deferral, is their only skip lane), ANY card whose diff touches a doc file (the change IS doc-relevant), and trivial cards (doc-review is their primary gate — § "Trivial-card fast-lane", unchanged). Never defer "for time" — the only enumerated reasons are `light + non-doc diff` and the deterministic PASS-fast below. **Single-card light batch exception (v5.4.1 minimal light lane): do NOT defer** — when the batch has exactly ONE card and it is `light`, the Final Review is itself SKIPPED if the per-card review is clean (see final-review.md § Minimal-light skip gate), so the deferral target would never run: run the scoped per-card doc-reviewer here instead.
309
309
  >
310
310
  > **Deterministic PASS-fast (v5.0.0 — measured: 84/127 per-card doc reviews returned PASS)**: when implement.md step 11c produced `/tmp/docinv-<CARD-ID>.json` AND it says `pass_fast_eligible: true` (zero non-advisory invariant rows triggered + no doc file in the diff + the card declares no `documentation_impact`/`canonical_docs`) AND the card is NOT `deep` → log `doc-review: PASS-fast (doc-invariants: 0 blocking rows) — Final doc-reviewer backstop stands` and **skip the per-card spawn** (proceed to Phase 3.5). No gate is removed: the batch-Final F.3 doc-reviewer still sees this card's diff. Own-Doc Closure: NEW-file obligations are definitionally empty (no invariant row fired, no docs declared); obligations on MODIFIED primitives/routes are covered by the automatic spec resync (`DS_COMPONENT_STALE` serializer gate, v4.70.0) plus the Final F.3 backstop — the invariant table's R1/R3 fire on new files only, by design. `deep` cards always spawn. Missing docinv JSON → no PASS-fast (fall through to the normal path).
311
311
 
@@ -2,6 +2,14 @@
2
2
 
3
3
  Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
4
4
 
5
+ ## (workflow new2.js, framework v5.4.1) — 2026-07-03
6
+
7
+ - Minimal light lane mirror: single-card light adds per-card doc-reviewer to the review
8
+ matrix, skips the i18n fill spawn (owner briefing carries the fill instruction),
9
+ skips new-final-review when `lightLane && cleanReview` (zero actionable findings),
10
+ skips production-readiness for all-light batches. Result objects carry
11
+ `lightLane`/`cleanReview` for the Final gate.
12
+
5
13
  ## (workflow new2.js, framework v5.4.0) — 2026-07-03
6
14
 
7
15
  - Light lane: `review_profile: light|skip` cards no longer spawn the Phase-1 retriever —
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: new2
3
3
  effort: high
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  description: >
6
6
  Workflow-hosted batch engine for /new. Implements one or
7
7
  more backlog cards end-to-end by delegating the WHOLE batch to a background
@@ -617,7 +617,7 @@ async function runCard(cardId, cardPath) {
617
617
  const phase1Brief = architectOk
618
618
  ? `Phase 1 already ran as specialist agents. READ the architecture baseline at ${baselinePath} BEFORE writing any code — it is your codebase context; do NOT redo the exploration.${auditCorrections.length ? `\nPlan-audit corrections (apply them as amendments to this briefing — do NOT modify the backlog YAML):\n${auditCorrections.map((c, i) => ` ${i + 1}. ${c}`).join('\n')}` : ''}`
619
619
  : phase1.architect === 'inline-light'
620
- ? `Phase 1 light lane (v5.4.0): this card is review_profile '${reviewProfile}' (≤3-file scale) — no dedicated retriever ran. Ground INLINE per AGENTS.md § Change Tiers (orchestrated-pipeline exception): BEFORE writing code, read the files in scope + their immediate integration points (imports/consumers). Scoped exploration of the touched area only — not a repo sweep; the understanding obligation is unchanged, only the delegation was waived.`
620
+ ? `Phase 1 light lane (v5.4.0): this card is review_profile '${reviewProfile}' (≤3-file scale) — no dedicated retriever ran. Ground INLINE per AGENTS.md § Change Tiers (orchestrated-pipeline exception): BEFORE writing code, read the files in scope + their immediate integration points (imports/consumers). Scoped exploration of the touched area only — not a repo sweep; the understanding obligation is unchanged, only the delegation was waived.${features.has_i18n ? ' I18N (light lane): NO separate fill pass runs for this card — fill EVERY target locale yourself for any new key (context-aware from the registry); the anti-hardcoded lint gate must pass.' : ''}`
621
621
  : `Phase 1 fallback: the architect specialist was unavailable — do the Phase 1 claim+architect exploration yourself per ${REF}/implement.md and persist the baseline to ${baselinePath} before coding.`
622
622
  // T1.A (v4.90.0) — mockup cards: binding-compliance is verified deterministically by the
623
623
  // check-bindings.mjs script (ui-implement Step 5b is the SSOT; this is the new2 parallel).
@@ -670,7 +670,10 @@ async function runCard(cardId, cardPath) {
670
670
  // v5.0.0 — explicit i18n fill pass (implement.md step 7c mirror; closes the measured leakage
671
671
  // where locale fills were spawned as general-purpose). The translator is named BY TYPE; it
672
672
  // self-detects new source-locale keys from the diff and no-ops cheaply when there are none.
673
- if (features.has_i18n) {
673
+ // v5.4.1 minimal light lane — no separate fill pass: the owner filled every locale itself
674
+ // (its briefing carries the instruction) and the Phase-2 anti-hardcoded lint gate enforces it.
675
+ if (features.has_i18n && lightLane) g('i18n-fill', 'SKIP', 'light lane — owner fills locales inline; lint gate enforces')
676
+ else if (features.has_i18n) {
674
677
  try {
675
678
  const fill = await agentSafe(
676
679
  `You are i18n-translator (fill pass for card ${cardId} — agents/i18n-protocol.md per-card cascade). cd into the card worktree. FIRST detect deterministically whether this card's diff (/tmp/diff-${cardId}.txt) added NEW source-locale keys; if none → return { ran:false, keys:0 } immediately (no-op). If keys exist: fill the missing TARGET locales for exactly those keys, context-aware from the registry at ${paths.i18n_registry || 'the i18n registry'} — the source locale stays untouched (the coder is source-only by design). Then re-run the project's locale-parity check if one exists. Return: { ran, keys, note }`,
@@ -834,7 +837,14 @@ async function runCard(cardId, cardPath) {
834
837
  }
835
838
  let reviewers
836
839
  if (reviewProfile === 'skip') reviewers = []
837
- else if (reviewProfile === 'light') reviewers = codexAvail ? ['codex'] : ['code-reviewer']
840
+ else if (reviewProfile === 'light') {
841
+ reviewers = codexAvail ? ['codex'] : ['code-reviewer']
842
+ // v5.4.1 minimal light lane — a single-card light batch skips the Final workflow when its
843
+ // per-card review is clean (nothing post-fix to verify), so doc coverage cannot defer
844
+ // there: run the scoped doc-reviewer per-card instead. Multi-card light keeps the
845
+ // deferral (the Final batch pass still runs and covers it).
846
+ if (cardIds.length === 1) reviewers.push('doc-reviewer')
847
+ }
838
848
  else if (noEvidence) reviewers = FULL_FANOUT // balanced/deep, no surface evidence → conservative full
839
849
  else reviewers = relevanceGated() // balanced AND deep — surface-gated breadth
840
850
  if (reviewProfile !== 'skip') g('review-matrix', 'PLANNED', `[${reviewProfile}${noEvidence ? '→conservative-full (no surface evidence)' : ''}] ${reviewers.join('+') || '(none)'} · docs:${touchesDocs} code:${touchesCode} api/data:${touchesApiData} sec:${securityRelevant}`)
@@ -974,8 +984,13 @@ async function runCard(cardId, cardPath) {
974
984
  // B6 — which reviewers ACTUALLY ran (the gated matrix); Phase Final keys its slim/skip
975
985
  // decision on this, and per_card telemetry records it for the A/B spawn accounting.
976
986
  reviewersRun: reviewers,
977
- // B7 — Phase-1 specialist record (architect: done|inline-fallback; audit: pass|fixes|skipped-*).
987
+ // B7 — Phase-1 specialist record (architect: done|inline-fallback|inline-light; audit: pass|fixes|skipped-*).
978
988
  phase1,
989
+ // v5.4.1 minimal light lane — Phase Final keys its skip on these: a single light card whose
990
+ // per-card review surfaced NOTHING actionable has no post-fix state for the Final pass to
991
+ // verify (the Final review's purpose — v4.56.1 — is POST-fix verification, not re-review).
992
+ lightLane,
993
+ cleanReview: blocks.length === 0 && scopeExp.length === 0,
979
994
  scopeFiles, archBaselinePath: `/tmp/arch-baseline-${cardId}.md`, gates,
980
995
  }
981
996
  }
@@ -1151,7 +1166,13 @@ const committed = perCardResults.filter((r) => r.status === 'committed')
1151
1166
  phase('Final')
1152
1167
  let finalSummary = null
1153
1168
  let mergeBlocked = degraded
1154
- if (committed.length && !degraded) {
1169
+ // v5.4.1 minimal light lane — ONE light card, clean per-card review (zero actionable
1170
+ // findings → zero fixes applied): the Final pass has nothing post-fix to verify and its
1171
+ // doc coverage already ran per-card (the light single-card matrix includes doc-reviewer).
1172
+ // Any finding/fix on the card, any second card, or any degradation → Final runs as always.
1173
+ const skipFinalLight = committed.length === 1 && committed[0].lightLane && committed[0].cleanReview && !degraded
1174
+ if (skipFinalLight) ledger(firstCard, 'final-review', 'SKIPPED', 'single light card, clean per-card review — nothing post-fix to verify (doc ran per-card)')
1175
+ if (committed.length && !degraded && !skipFinalLight) {
1155
1176
  const reviewScopeFiles = dedupe(committed.flatMap((r) => r.scopeFiles || []))
1156
1177
  const archPaths = committed.map((r) => r.archBaselinePath).filter(Boolean)
1157
1178
  const allArch = archPaths.length === committed.length ? archPaths : null
@@ -1295,7 +1316,11 @@ if (!committed.length) {
1295
1316
  // Phase Production (Phase 7) — non-blocking; report-not-execute (F-011 infra-deferred).
1296
1317
  // ───────────────────────────────────────────────────────────────────────────
1297
1318
  phase('Production')
1298
- if (mergeResult && mergeResult.merged) {
1319
+ if (mergeResult && mergeResult.merged && committed.length && committed.every((r) => r.lightLane)) {
1320
+ // v5.4.1 minimal light lane — light cards carry no deployable surface by Rule C (no
1321
+ // migrations/indexes/cron/schema); the checklist would only burn a spawn to report zero items.
1322
+ ledger(firstCard, 'phase7-production', 'SKIPPED', 'all-light batch — no deployable surface (Rule C)')
1323
+ } else if (mergeResult && mergeResult.merged) {
1299
1324
  try {
1300
1325
  // Schema-deploy-from-trunk-only invariant (v4.33.0): a remote schema/RLS/index/
1301
1326
  // migration deploy desyncs a shared remote datastore when run off-trunk. When the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baldart",
3
- "version": "5.4.0",
3
+ "version": "5.4.1",
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"