baldart 5.4.1 → 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 CHANGED
@@ -5,6 +5,28 @@ 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
+
8
30
  ## [5.4.1] - 2026-07-03
9
31
 
10
32
  **Minimal light lane — the roster for a simple card is now literally: grounding (inline),
package/VERSION CHANGED
@@ -1 +1 @@
1
- 5.4.1
1
+ 5.5.0
@@ -2,6 +2,16 @@
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
+
5
15
  ## 2.2.0 — 2026-07-03 (framework v5.4.1)
6
16
 
7
17
  - **Minimal light lane — roster cut to the core four.** A single light card now runs:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: new
3
3
  effort: medium
4
- version: 2.2.0
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 epic card in the batch declares `migration_plan.required: true` (cheap YAML
70
- probe on the batch's `group.parent` epics). A declared migration keeps the
71
- classic path its Phase 0 step 1b owns the owner-gated apply under
72
- § "AUTONOMOUS RESOLUTION RULE"; `new2`'s own migration gate is interactive.
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
@@ -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`.** If **no** epic in the batch declares one → write `## Migration\nnone (no migration_plan 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.
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,20 @@
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
+
5
19
  ## (workflow new2.js, framework v5.4.1) — 2026-07-03
6
20
 
7
21
  - Minimal light lane mirror: single-card light adds per-card doc-reviewer to the review
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: new2
3
3
  effort: high
4
- version: 1.6.0
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 `migration_plan.required`
89
- itself), so Step 3.5's one interactive question cannot fire on a delegated run —
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 `migration_plan` with `required: true`.** None set `migration = { status: 'none' }`
133
- and go to Step 4 (identical to today zero extra prompts; do not surface anything).
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`) the Step-3.5 gate is a pre-launch interaction, NOT a
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baldart",
3
- "version": "5.4.1",
3
+ "version": "5.5.0",
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"