baldart 5.4.0 → 5.5.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 +47 -0
- package/VERSION +1 -1
- package/framework/.claude/skills/new/CHANGELOG.md +21 -0
- package/framework/.claude/skills/new/SKILL.md +11 -5
- package/framework/.claude/skills/new/references/final-review.md +13 -0
- package/framework/.claude/skills/new/references/implement.md +1 -1
- package/framework/.claude/skills/new/references/production-readiness.md +6 -0
- package/framework/.claude/skills/new/references/review-cycle.md +1 -1
- package/framework/.claude/skills/new/references/setup.md +1 -1
- package/framework/.claude/skills/new2/CHANGELOG.md +22 -0
- package/framework/.claude/skills/new2/SKILL.md +50 -6
- package/framework/.claude/workflows/new2.js +31 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,53 @@ 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.5.0] - 2026-07-03
|
|
9
|
+
|
|
10
|
+
**Migration deploy chain hardened (FEAT-0067 post-mortem — mayo).** The batch's DB
|
|
11
|
+
migration was fully declared in the cards (`db_migration` + `db_migrations_summary`,
|
|
12
|
+
per the consumer's prd-card-writer overlay) but the remote `db:push` was never
|
|
13
|
+
executed nor surfaced: new2's Migration Gate probed ONLY `migration_plan` (structural
|
|
14
|
+
vocabulary mismatch → silent no-op) and the end-of-batch `db-migration-deploy`
|
|
15
|
+
residual was lost by the mid-run DONE-flip, closing the epic against an unmet DoD.
|
|
16
|
+
|
|
17
|
+
- **Vocabulary aliases** (`/new` 2.2.1, `new2` 1.7.0): the `-auto` delegation gate,
|
|
18
|
+
`/new` Phase 0 1b and new2 Step 3.5 now detect a declared migration under
|
|
19
|
+
`migration_plan.required` (epic) OR `db_migrations_summary` (epic) OR
|
|
20
|
+
`db_migration.required: true` (per-card overlay convention).
|
|
21
|
+
- **new2 Step 5.1b Migration Sync Tail (NEW)**: after the autonomous workflow returns
|
|
22
|
+
(post-merge, on trunk), the SKILL runs the project's post-merge sync check
|
|
23
|
+
(overlay "branch B"); on red it asks Push now / Defer / Override interactively —
|
|
24
|
+
never pushes autonomously. Triggered by the Step-3.5 DECLARATION, not only by the
|
|
25
|
+
residual ledger (belt-and-braces vs a dropped residual). Telemetry
|
|
26
|
+
`migration_sync_tail`.
|
|
27
|
+
- Codex parity: portable (prose-only skill/reference edits; `new2` is Claude-only by
|
|
28
|
+
design — `/new` classic remains the Codex path and gains the same alias probe).
|
|
29
|
+
|
|
30
|
+
## [5.4.1] - 2026-07-03
|
|
31
|
+
|
|
32
|
+
**Minimal light lane — the roster for a simple card is now literally: grounding (inline),
|
|
33
|
+
coder, code review, doc review, commit, merge. Nothing else.** Completes v5.4.0 per the
|
|
34
|
+
maintainer's directive ("per cose così semplici voglio due passaggi in croce"): the compact
|
|
35
|
+
lane cut the CARD COUNT; this cuts the per-run AGENT COUNT. FEAT-0067-class run: ~33
|
|
36
|
+
agents → ~7.
|
|
37
|
+
|
|
38
|
+
- **Per-card doc review at light (single-card batch)**: the light review matrix adds the
|
|
39
|
+
scoped `doc-reviewer` per-card (review-cycle.md deferral-gate exception) because the
|
|
40
|
+
Final pass it used to defer to is now skippable.
|
|
41
|
+
- **Final Review skip gate (`final-review.md` § F.0 + `new2.js` `skipFinalLight`)**: ONE
|
|
42
|
+
light card + zero actionable per-card findings (→ zero fixes applied) → skip F.2–F.5
|
|
43
|
+
entirely. Honors the v4.56.1 refutation (per-card PRE-fix + final POST-fix are
|
|
44
|
+
non-redundant) by scoping the skip to runs where there IS no post-fix state; any
|
|
45
|
+
finding, fix, second card, or degraded reviewer → Final runs as always.
|
|
46
|
+
- **i18n fill spawn cut at light**: the owner briefing instructs the coder to fill every
|
|
47
|
+
target locale itself; the anti-hardcoded lint + locale-parity gates still enforce.
|
|
48
|
+
- **Production-readiness spawn cut for all-light batches**: no deployable surface exists
|
|
49
|
+
by Rule C (no migrations/indexes/cron/schema) — the agent only ever reported zero items.
|
|
50
|
+
- `check-new-parity.mjs` rule 18 locks the prose↔workflow lockstep for every cut.
|
|
51
|
+
- Skills: `new` 2.2.0 · `new2` 1.6.0.
|
|
52
|
+
|
|
53
|
+
Codex parity: portable (prose modules are the cross-tool SSOT; `new2.js` Claude-only by design).
|
|
54
|
+
|
|
8
55
|
## [5.4.0] - 2026-07-03
|
|
9
56
|
|
|
10
57
|
**Elastic pipeline — `/prd`+`/new` compress to the minimum for trivial features and
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.
|
|
1
|
+
5.5.0
|
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 2.2.1 — 2026-07-03 (FEAT-0067 post-mortem: migration vocabulary aliases)
|
|
6
|
+
|
|
7
|
+
- Il gate di delega `-auto` (condizione 4) e il Migration Gate Phase 0 1b (setup.md
|
|
8
|
+
step 2) ora rilevano una migrazione dichiarata sotto QUALSIASI vocabolario:
|
|
9
|
+
`migration_plan.required` (epic), `db_migrations_summary` (epic),
|
|
10
|
+
`db_migration.required: true` (per-card, convenzione overlay consumer). Una
|
|
11
|
+
migrazione dichiarata solo via alias con artifact non ancora su disco degrada come
|
|
12
|
+
oggi (missing-artifact) ma la dichiarazione viene SEMPRE registrata nel tracker —
|
|
13
|
+
il sync post-merge e il ledger dei follow-up devono conoscerla.
|
|
14
|
+
|
|
15
|
+
## 2.2.0 — 2026-07-03 (framework v5.4.1)
|
|
16
|
+
|
|
17
|
+
- **Minimal light lane — roster cut to the core four.** A single light card now runs:
|
|
18
|
+
grounding-inline (step 2d) → owner → code review (Codex-light/code-reviewer) → scoped
|
|
19
|
+
doc-reviewer per-card (review-cycle deferral exception) → commit → merge. Cut for the
|
|
20
|
+
lane: i18n fill spawn (7c — owner fills locales inline, lint gate enforces), Final
|
|
21
|
+
Review when the per-card review is clean (final-review.md § F.0 Minimal-light skip
|
|
22
|
+
gate — POST-fix verification with zero fixes is vacuous; any finding/fix/second card →
|
|
23
|
+
Final runs), production-readiness spawn for all-light batches (no deployable surface
|
|
24
|
+
by Rule C). Guarded by check-new-parity rule 18.
|
|
25
|
+
|
|
5
26
|
## 2.1.0 — 2026-07-03 (framework v5.4.0)
|
|
6
27
|
|
|
7
28
|
- **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
|
|
4
|
+
version: 2.2.1
|
|
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
|
|
@@ -66,10 +66,16 @@ kickoff, right after arg parsing):
|
|
|
66
66
|
2. `FORCE_INLINE == false` (the user did not pass `-inline`).
|
|
67
67
|
3. The `Workflow` tool is available in this session AND `.claude/workflows/new2.js`
|
|
68
68
|
is linked AND the `new2` skill is available.
|
|
69
|
-
4. No
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
4. No card in the batch declares a DB migration, under ANY of the recognized
|
|
70
|
+
vocabularies (cheap YAML probe): epic `migration_plan.required: true`, epic
|
|
71
|
+
`db_migrations_summary` (non-empty), or a batch card with
|
|
72
|
+
`db_migration.required: true` (the consumer-overlay convention — e.g. mayo's
|
|
73
|
+
prd-card-writer overlay). A declared migration keeps the classic path — its
|
|
74
|
+
Phase 0 step 1b owns the owner-gated apply under § "AUTONOMOUS RESOLUTION
|
|
75
|
+
RULE"; `new2`'s own migration gate is interactive. *Why the aliases are
|
|
76
|
+
load-bearing*: probing only `migration_plan` silently classified a
|
|
77
|
+
`db_migration`-declaring batch as migration-free (FEAT-0067 post-mortem — the
|
|
78
|
+
remote `db:push` was never surfaced).
|
|
73
79
|
|
|
74
80
|
**Action**: log ONE tracker line `[DELEGATED] -auto batch → new2 engine
|
|
75
81
|
(off-context): <residual args>` and invoke the `new2` skill with the SAME residual
|
|
@@ -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).**
|
|
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
|
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
1b. **Migration Gate (BLOCKING only when a migration is *declared* — else a silent no-op)** — resolve DB migrations interactively **before** the worktree exists, so the schema is live before any card builds against it. *Why this exists*: a migration applied to a shared/remote DB is owner-gated, so without this gate it is deferred to the END of the batch — and every downstream card in the batch is then built and verified against a schema that is not yet live (`validation_commands` / QA / E2E / DB-generated `tsc` types fail falsely → those cards cascade into deferral/blocked). Front-loading the migration removes that root cause. **The declaration lives in the EPIC card** (`migration_plan` block — project-specific, authored by the user, typically via the `.baldart/overlays/new.md` overlay). Steps:
|
|
23
23
|
|
|
24
24
|
1. **Find the batch's epic card(s).** Collect the distinct `group.parent` of the batch cards (or, for a `-full` invocation, the parent already known). For each, locate the epic YAML in `${paths.backlog_dir}` (filename `<PARENT>-*-epic.yml`, or the card whose `id == <PARENT>` / `group.is_epic: true`) and Read it.
|
|
25
|
-
2. **Look for `migration_plan` with `required: true
|
|
25
|
+
2. **Look for a declared migration — under ANY recognized vocabulary.** Primary: epic `migration_plan` with `required: true`. **Compat aliases (consumer-overlay conventions — same semantics, different field names)**: epic `db_migrations_summary` (non-empty), or any batch card carrying `db_migration.required: true` (map: `artifacts` ← each `db_migration.expected_file`; `summary` ← the slug; apply/push modalities ← `db_migration.remote_push` + the overlay's post-merge section; no `verify` unless declared). A migration declared ONLY via alias whose `expected_file` does not yet exist on disk (it will be authored mid-run by the coder) follows the step-3 missing-artifact degradation — but the declaration itself MUST still be recorded in the tracker (`## Migration\ndeclared (via db_migration) — deferred to post-merge sync`) so the post-merge Migration Sync step and the follow-up ledger know about it. If **nothing** declares a migration → write `## Migration\nnone (no migration declared)` to the tracker and **proceed to step 2** (behaviour is identical to today — zero extra prompts). This is the common case; do not surface anything.
|
|
26
26
|
3. **(declared) Verify the artifacts exist on disk.** For each path in `migration_plan.artifacts`, check it exists under `$MAIN`. If **any is missing** → do **NOT** apply or prompt; write `## Migration\ndeclared but artifact(s) missing: <paths> — degraded to deferred (author the migration first)` to the tracker and **proceed to step 2** (the migration falls back to the current end-of-batch owner-gated deferral — no regression). *(Auto-generating a missing artifact is out of scope; the migration must already be authored to be applied up-front.)*
|
|
27
27
|
4. **(declared + artifacts present) Assemble the apply modalities**, in this source order, de-duplicating by `id`: (a) `migration_plan.apply_modalities` from the epic block; (b) a `## Migration modalities` section in `.baldart/overlays/new.md` if present; (c) any project-memory note on how this project applies migrations; (d) the built-in tail `["Già applicata — prosegui", "Abort"]`. Each modality is `{ id, label, command? }`.
|
|
28
28
|
5. **`AskUserQuestion`** — `"La epic dichiara una migrazione DB (<summary>). Va applicata PRIMA del batch così le card downstream verificano contro lo schema reale. Come procedo?"` with up to 4 of the assembled modalities (always include "Già applicata — prosegui" and "Abort" as the last options). This is a legitimate Phase 0 question (Auto Mode does not override it).
|
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 1.7.0 — 2026-07-03 (FEAT-0067 post-mortem: migration mai deployata)
|
|
6
|
+
|
|
7
|
+
- **Step 3.5 vocabulary aliases**: il Migration Gate ora riconosce, oltre a
|
|
8
|
+
`migration_plan.required` (epic), anche `db_migrations_summary` (epic) e
|
|
9
|
+
`db_migration.required: true` (per-card — convenzione overlay consumer, es. mayo).
|
|
10
|
+
Root cause FEAT-0067: il probe solo-`migration_plan` classificava la batch come
|
|
11
|
+
migration-free → gate in silent no-op, `db:push` mai emerso.
|
|
12
|
+
- **Step 5.1b Migration Sync Tail (NEW)**: post-merge, il ramo B interattivo del sync
|
|
13
|
+
gate eseguito dalla SKILL (check-sync read-only → su rosso `AskUserQuestion`
|
|
14
|
+
Push now / Defer / Override; mai push in autonomo). Trigger belt-and-braces sulla
|
|
15
|
+
DICHIARAZIONE Step 3.5, non solo sul residual ledger (che il DONE-flip di FEAT-0067
|
|
16
|
+
aveva perso). Telemetria `migration_sync_tail`.
|
|
17
|
+
- Step 1.5: nota di delega aggiornata (il probe di `/new -auto` copre tutti i vocabolari).
|
|
18
|
+
|
|
19
|
+
## (workflow new2.js, framework v5.4.1) — 2026-07-03
|
|
20
|
+
|
|
21
|
+
- Minimal light lane mirror: single-card light adds per-card doc-reviewer to the review
|
|
22
|
+
matrix, skips the i18n fill spawn (owner briefing carries the fill instruction),
|
|
23
|
+
skips new-final-review when `lightLane && cleanReview` (zero actionable findings),
|
|
24
|
+
skips production-readiness for all-light batches. Result objects carry
|
|
25
|
+
`lightLane`/`cleanReview` for the Final gate.
|
|
26
|
+
|
|
5
27
|
## (workflow new2.js, framework v5.4.0) — 2026-07-03
|
|
6
28
|
|
|
7
29
|
- 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.
|
|
4
|
+
version: 1.7.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
|
|
@@ -85,8 +85,9 @@ everywhere this skill branches on it — Step 3.5 resolves deterministically (it
|
|
|
85
85
|
AUTONOMOUS branch) and **Step 3b's escape hatch is SKIPPED** (the user asked for
|
|
86
86
|
`-auto`; a post-batch question — and a possible `/new` re-invocation at full
|
|
87
87
|
inline cost — would break that promise even with a TTY present). `/new` only
|
|
88
|
-
delegates **migration-free** batches (it probes
|
|
89
|
-
itself
|
|
88
|
+
delegates **migration-free** batches (it probes ALL migration vocabularies
|
|
89
|
+
itself — `migration_plan.required`, epic `db_migrations_summary`, per-card
|
|
90
|
+
`db_migration.required`), so Step 3.5's one interactive question cannot fire on a delegated run —
|
|
90
91
|
if you nonetheless find a declared, unapplied migration in a delegated batch,
|
|
91
92
|
HALT and hand back to `/new` classic (`"batch con migrazione dichiarata — riesegui
|
|
92
93
|
/new <cards> -auto -inline"`) instead of asking. Everything else is identical to a
|
|
@@ -129,8 +130,16 @@ untouched), so the schema is live **before** the workflow starts. It mirrors `/n
|
|
|
129
130
|
1. **Find the batch's epic card(s)** — distinct `group.parent` of the resolved cards (or the `-full`
|
|
130
131
|
parent). Read each epic YAML in `${paths.backlog_dir}` (`<PARENT>-*-epic.yml`, or the card whose
|
|
131
132
|
`id == <PARENT>` / `group.is_epic: true`).
|
|
132
|
-
2. **Look for
|
|
133
|
-
|
|
133
|
+
2. **Look for a declared migration — under ANY recognized vocabulary.** Primary: epic
|
|
134
|
+
`migration_plan` with `required: true`. **Compat aliases (consumer-overlay conventions —
|
|
135
|
+
FEAT-0067 root cause: probing only `migration_plan` made this gate structurally blind to
|
|
136
|
+
`db_migration`-declaring cards)**: epic `db_migrations_summary` (non-empty), or any batch card
|
|
137
|
+
with `db_migration.required: true` (map: `artifacts` ← `db_migration.expected_file`; `summary`
|
|
138
|
+
← the slug; modalities ← `db_migration.remote_push` + overlay). Nothing declared → set
|
|
139
|
+
`migration = { status: 'none' }` and go to Step 4 (identical to today — zero extra prompts; do
|
|
140
|
+
not surface anything). Declared via ANY vocabulary → record `migrationDeclared: true` +
|
|
141
|
+
`declaredVia` in your own working state (Step 5.1b keys off it — it must NOT depend on the
|
|
142
|
+
workflow's residual ledger surviving) and continue below.
|
|
134
143
|
3. **(declared) Verify `migration_plan.artifacts` exist on disk under `$MAIN`.** Any missing → do NOT
|
|
135
144
|
apply or prompt; set `migration = { status: 'degraded', reason: 'artifact missing', artifacts }`
|
|
136
145
|
and go to Step 4 (the migration falls back to the current end-of-batch owner-gated deferral — no
|
|
@@ -245,6 +254,40 @@ returns when the batch is done. It returns:
|
|
|
245
254
|
step-1b HALT fields — the `/new` pre-flight back-fill (step 1b-ii) then normalizes its
|
|
246
255
|
`review_profile`/`owner_agent` on first ingestion, so even the crisis stub self-heals. This
|
|
247
256
|
main-repo, **disk-verified** write is the SSOT — nothing is dropped even on a non-merged batch.
|
|
257
|
+
1b. **Migration Sync Tail (post-merge "branch B" — the interactive owner-gated deploy the
|
|
258
|
+
autonomous batch could not run).** The workflow has returned and merged; you are the skill
|
|
259
|
+
main loop, in `$MAIN`, typically on `$TRUNK` — exactly the precondition of the project's
|
|
260
|
+
post-merge sync gate (e.g. the overlay's "on trunk, post-merge" branch). **Trigger — EITHER
|
|
261
|
+
condition, independently** (belt-and-braces: the FEAT-0067 failure dropped the residual
|
|
262
|
+
mid-run, so this tail keys on the Step-3.5 DECLARATION, never only on the ledger):
|
|
263
|
+
(a) `migrationDeclared` from Step 3.5 (any vocabulary) with `migration.status ≠ 'applied'`;
|
|
264
|
+
(b) any `residuals[]` entry whose kind/owner-gated action maps to `db-migration-deploy`.
|
|
265
|
+
Neither → skip silently. Steps:
|
|
266
|
+
- **Resolve the project's post-merge sync contract**, in source order: (i) the batch cards'
|
|
267
|
+
`db_migration.remote_push` / `migration_plan` (check command + push command); (ii) the
|
|
268
|
+
post-merge / trunk branch of the Migration Sync Gate section in `.baldart/overlays/new.md`;
|
|
269
|
+
(iii) `migration_plan.verify` alone (check-only). Nothing resolvable → skip the tail (the
|
|
270
|
+
step-1 follow-up card remains the ledger) and say so in the presentation.
|
|
271
|
+
- **Run the read-only sync CHECK first** (e.g. the overlay's check-sync command), from `$MAIN`
|
|
272
|
+
on `$TRUNK` (if `$MAIN` is not on `$TRUNK`, do not switch branches yourself — report and
|
|
273
|
+
leave the follow-up as ledger). **Green** → the migration is live: the `db-migration-deploy`
|
|
274
|
+
residual is SATISFIED (no follow-up needed — if step 1 already created one, delete it in the
|
|
275
|
+
same reconciliation commit and note why); record it and let step 2 DONE-flip the migration
|
|
276
|
+
card with its schema AC satisfied.
|
|
277
|
+
- **Red + INTERACTIVE** → ONE `AskUserQuestion` (post-batch skill-layer interaction, same
|
|
278
|
+
class as Step 3b — the zero-ask-during-batch invariant is untouched): *"La migration del
|
|
279
|
+
batch non risulta applicata al DB remoto (check-sync rosso). Come procedo?"* Options:
|
|
280
|
+
**[Push now]** (run the declared owner-gated push command from `$TRUNK` — honour
|
|
281
|
+
`stack.schema_deploy_from_trunk_only`; output to `/tmp/migration-push-<firstCard>.log`,
|
|
282
|
+
surface the exit code, then RE-RUN the check and require green) / **[Defer]** (keep the
|
|
283
|
+
step-1 follow-up card as the ledger; the card stays DONE-with-follow-up per its
|
|
284
|
+
`owner-gated` class) / **[Override]** (record the user's verbatim reason). Never push
|
|
285
|
+
without the user picking it.
|
|
286
|
+
- **Red + AUTONOMOUS** (env / delegated `/new -auto` origin — Step 1.5) → NEVER push
|
|
287
|
+
(outward, owner-gated). Ensure the step-1 follow-up exists, and surface the pending deploy
|
|
288
|
+
PROMINENTLY in the presentation (step 4) — a truthful "schema NOT live" line, not a footnote.
|
|
289
|
+
- Record `migration_sync_tail: { ran, trigger: 'declared'|'residual'|'both', check:
|
|
290
|
+
'green'|'red'|'unavailable', pushed: <bool>, outcome }` for telemetry (step 5).
|
|
248
291
|
2. **Mark deferred cards DONE — only after their follow-up exists AND every deferral class allows
|
|
249
292
|
it (F-040/H + A3).** Some committed cards were intentionally left **NON-DONE** because they carry
|
|
250
293
|
an open deferred AC: they are `perCardResults[]` entries with `deferred:true` plus a
|
|
@@ -358,7 +401,8 @@ returns when the batch is done. It returns:
|
|
|
358
401
|
(partial, output-only, excludes nested workflows). Keep `degraded`/`degradation_reasons` +
|
|
359
402
|
`cards_deferred_done_pending` in the record so
|
|
360
403
|
the A/B comparison stays honest. Also record `migration_gate: <migration.status>`
|
|
361
|
-
(`none`|`applied`|`skipped`|`degraded`)
|
|
404
|
+
(`none`|`applied`|`skipped`|`degraded`) and `migration_sync_tail` (Step 5.1b — whether the
|
|
405
|
+
post-merge check ran, its outcome, and whether an owner-gated push was user-approved) — the Step-3.5 gate is a pre-launch interaction, NOT a
|
|
362
406
|
mid-batch question, so it does not break the zero-ask-during-batch invariant; logging it keeps the
|
|
363
407
|
A/B honest about when a migration was front-loaded. Keep `deferral_breakdown` (per-class counts
|
|
364
408
|
of WHY residuals became follow-ups instead of in-batch fixes) in the record — a class dominating
|
|
@@ -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
|
-
|
|
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')
|
|
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
|
-
|
|
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
|