baldart 4.27.2 → 4.28.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 +17 -0
- package/VERSION +1 -1
- package/framework/.claude/skills/new2/SKILL.md +5 -1
- package/framework/.claude/skills/prd/assets/epic-template.yml +28 -0
- package/framework/.claude/workflows/new2.js +21 -1
- package/framework/templates/overlays/README.md +1 -0
- package/framework/templates/overlays/new.migration-example.md +60 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,23 @@ 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.28.1] - 2026-06-11
|
|
9
|
+
|
|
10
|
+
**Doc: list the `new.migration-example.md` overlay example in the overlays README.** Completes the v4.28.0 Migration Gate docs — the example overlay file shipped in v4.28.0 was not yet listed in the `framework/templates/overlays/README.md` example table. **PATCH** (doc-only).
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **`framework/templates/overlays/README.md`** — added the `new.migration-example.md` row (Migration-Gate apply modalities for `/new` Phase 0 step 1b · `new2` Step 3.5).
|
|
15
|
+
|
|
16
|
+
## [4.28.0] - 2026-06-11
|
|
17
|
+
|
|
18
|
+
**`new2`: front-loaded Migration Gate — declared DB migrations are applied BEFORE the batch, so downstream cards verify against a live schema.** The workflow runs autonomously and cannot apply an owner-gated DB migration mid-run, so a declared migration was deferred to end-of-batch — and every downstream card was built/verified against a schema not yet live (`validation_commands` / QA / E2E / DB-generated `tsc` types fail falsely → those cards cascade into deferral). The new gate runs in the **skill** (the main loop, which can interact — the workflow's zero-ask contract is untouched), mirroring `/new` Phase 0 step 1b: it finds the batch epic's `migration_plan` (`required: true`), verifies artifacts on disk, assembles apply modalities (epic `apply_modalities` + `.baldart/overlays/new.md` `## Migration modalities` + project memory + built-in `Già applicata`/`Abort`), asks ONE pre-launch question, executes the chosen modality in `$MAIN`, and passes a `migration` manifest into the workflow. **MINOR** (additive capability on the EXPERIMENTAL `new2` surface; the gate is a silent no-op when no migration is declared and degrades to today's end-of-batch deferral when artifacts are missing — no regression; the `migration` arg is the skill→workflow contract only, NOT a `baldart.config.yml` key, so the schema-change propagation rule does not apply).
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **`framework/.claude/skills/new2/SKILL.md` Step 3.5 — Migration Gate.** BLOCKING only when a migration is declared; otherwise a silent no-op. Emits the `migration = { status: 'none'|'applied'|'skipped'|'degraded', modality?, summary?, artifacts?, affects_cards? }` manifest passed to the workflow (Step 4 args block). The final-record step also logs `migration_gate: <status>` so the A/B comparison stays honest about when a migration was front-loaded (a pre-launch interaction, NOT a mid-batch question — the zero-ask-during-batch invariant holds).
|
|
23
|
+
- **`framework/.claude/workflows/new2.js` — migration manifest consumption.** Reads `a.migration` (args contract documented), and when `status === 'applied'` injects an EXCEPTION to the F-016 owner-gated rule in the preflight (the schema-apply / db-push AC of the affected cards must NOT be classified as a policy-deferred AC — it is satisfied) and a `MIGRATION LIVE` note into each affected card's brief (run REAL validation against the live schema, do not defer or build against an absent schema). A migration NOT covered by the manifest still follows the existing end-of-batch owner-gated deferral.
|
|
24
|
+
|
|
8
25
|
## [4.27.2] - 2026-06-11
|
|
9
26
|
|
|
10
27
|
**`new2` resolve: kill the second self-judging adversarial pass for `security` too.** v4.27.1 removed the wasteful adversarial doc review (doc-reviewer judging doc-reviewer). An audit of every fixer→judge pair in the resolution pass found `security` is the exact same structural case: the fixer is `security-reviewer` (protected domain) and so is the judge, so the mandatory cross-check was `security-reviewer` judging `security-reviewer` — no cross-model diversity, the same waste. The skip is now driven by a structural guard, `selfJudges = (fixerAgent === judgeAgent)`, instead of a per-domain allowlist, so it covers doc + security today and can't silently regress if the fixer/judge map changes. Every domain where fixer ≠ judge (ui/perf/test/code/migration) keeps the mandatory adversarial cross-check unchanged. **PATCH** (cost/latency optimization on the EXPERIMENTAL `new2` surface; no config key, no change to `/new`).
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.28.1
|
|
@@ -223,4 +223,8 @@ returns when the batch is done. It returns:
|
|
|
223
223
|
`residualFollowups.length` — which double-counts). `total_tokens`/`agent_count` come from the
|
|
224
224
|
workflow; if `total_tokens` is null, run the `/new` Phase-8 `-stats` script to backfill real
|
|
225
225
|
`usage`. Keep `degraded`/`degradation_reasons` + `cards_deferred_done_pending` in the record so
|
|
226
|
-
the A/B comparison stays honest.
|
|
226
|
+
the A/B comparison stays honest. Also record `migration_gate: <migration.status>`
|
|
227
|
+
(`none`|`applied`|`skipped`|`degraded`) — the Step-3.5 gate is a pre-launch interaction, NOT a
|
|
228
|
+
mid-batch question, so it does not break the zero-ask-during-batch invariant; logging it keeps the
|
|
229
|
+
A/B honest about when a migration was front-loaded. Do NOT re-summarise the cards — the workflow
|
|
230
|
+
already did.
|
|
@@ -143,6 +143,34 @@ execution_strategy:
|
|
|
143
143
|
- "{{FEAT-XXXX-N}} e {{FEAT-XXXX-M}} entrambi modificano {{file}} — forzato sequenziale"
|
|
144
144
|
# omit if no conflicts
|
|
145
145
|
|
|
146
|
+
# =============================================================================
|
|
147
|
+
# Migration Plan (OPTIONAL — declare ONLY when the epic needs a DB schema change
|
|
148
|
+
# applied BEFORE its cards run). Read by /new (Phase 0 step 1b) and new2 (Step 3.5):
|
|
149
|
+
# the skill front-loads the migration interactively so downstream cards verify
|
|
150
|
+
# against the LIVE schema instead of a deferred one. Project-specific — the shape of
|
|
151
|
+
# `apply_modalities` (db:push, local apply, …) belongs in the consumer's
|
|
152
|
+
# `.baldart/overlays/new.md`; see framework/templates/overlays/new.migration-example.md.
|
|
153
|
+
# OMIT this block entirely when the epic introduces no schema change (the common case;
|
|
154
|
+
# the gate then stays a silent no-op). The migration `artifacts` must already exist on
|
|
155
|
+
# disk to be applied up-front — if absent, the gate degrades to the current
|
|
156
|
+
# end-of-batch owner-gated deferral.
|
|
157
|
+
# =============================================================================
|
|
158
|
+
|
|
159
|
+
# migration_plan:
|
|
160
|
+
# required: true
|
|
161
|
+
# summary: "{{Add bookings.status enum column + composite index}}"
|
|
162
|
+
# artifacts:
|
|
163
|
+
# - {{supabase/migrations/20260611_add_status.sql}}
|
|
164
|
+
# apply_modalities: # de-duped by id; merged with overlays/new.md + project memory
|
|
165
|
+
# - id: remote-push
|
|
166
|
+
# label: "db:push al DB remoto (eseguito dalla skill su tua approvazione)"
|
|
167
|
+
# command: "{{npx supabase db push}}"
|
|
168
|
+
# - id: local
|
|
169
|
+
# label: "Applica in locale"
|
|
170
|
+
# command: "{{npx supabase db reset --local}}"
|
|
171
|
+
# affects_cards: [{{FEAT-XXXX-02}}, {{FEAT-XXXX-03}}] # downstream che richiedono lo schema live
|
|
172
|
+
# verify: "{{npx supabase gen types typescript --local | head}}" # opzionale — probe post-apply
|
|
173
|
+
|
|
146
174
|
# =============================================================================
|
|
147
175
|
# Canonical Docs (epic-level — children inherit subset)
|
|
148
176
|
# =============================================================================
|
|
@@ -20,6 +20,10 @@ export const meta = {
|
|
|
20
20
|
// metricsDir string paths.metrics (telemetry dir)
|
|
21
21
|
// refModulesBase string dir holding /new reference modules (semantic SSOT)
|
|
22
22
|
// config object parsed baldart.config.yml (paths.*/stack.*/features.*/git.*)
|
|
23
|
+
// migration object Migration Gate manifest (skill Step 3.5): { status:'none'|'applied'|
|
|
24
|
+
// 'skipped'|'degraded', modality?, summary?, artifacts?, affects_cards? }.
|
|
25
|
+
// status:'applied' → the declared schema is LIVE before the batch, so the
|
|
26
|
+
// affected cards' apply-AC is NOT owner-gated-deferred (F-016 exception).
|
|
23
27
|
// flags { stats, effort, full }
|
|
24
28
|
// ts string ISO timestamp injected by the skill (Date.now() is unavailable here)
|
|
25
29
|
//
|
|
@@ -45,6 +49,12 @@ const METRICS = a.metricsDir || 'docs/metrics'
|
|
|
45
49
|
const REF = (a.refModulesBase || '.claude/skills/new/references').replace(/\/$/, '')
|
|
46
50
|
const FLAGS = a.flags || {}
|
|
47
51
|
const TS = a.ts || ''
|
|
52
|
+
// Migration Gate manifest (skill Step 3.5 — front-loaded BEFORE this workflow ran). When
|
|
53
|
+
// status:'applied', the declared schema is LIVE on the active DB, so its apply-AC must NOT be
|
|
54
|
+
// re-classified as an owner-gated policy-deferred AC (F-016) — the downstream cards verify for real.
|
|
55
|
+
const migration = a.migration || { status: 'none' }
|
|
56
|
+
const migrationApplied = migration && migration.status === 'applied'
|
|
57
|
+
const migrationAffects = Array.isArray(migration.affects_cards) ? migration.affects_cards : []
|
|
48
58
|
const features = cfg.features || {}
|
|
49
59
|
const paths = cfg.paths || {}
|
|
50
60
|
const gitCfg = cfg.git || {}
|
|
@@ -230,6 +240,9 @@ try {
|
|
|
230
240
|
`• cardGraph (REQUIRED, F-021): for every runnable card return { id, dependsOn:[IN-BATCH deps only], ownerAgent (the card's owner_agent; G25 unknown→'coder'), reviewProfile (the card's review_profile; default 'balanced'), policyDeferredACs, alreadyCommitted, alreadyCommittedSha, isEpic (implement.md §6b epic guard: id ends '-00' OR filename ends '-epic.yml' OR group.is_epic:true OR review_profile 'skip' with no requirements), filesLikelyTouched (verbatim from the YAML) }.\n` +
|
|
231
241
|
`• B1/F-026 idempotency (per card, AFTER the worktree exists): set alreadyCommitted:true (+ alreadyCommittedSha) IFF ALL hold: (a) a commit referencing the card id exists in ${TRUNK}..HEAD of the worktree; (b) the card's validation_commands re-run GREEN right now; (c) NO open follow-up card for it exists in ${paths.backlog_dir || 'backlog'}. On a FRESH worktree ${TRUNK}..HEAD is empty → all false, zero extra work.\n` +
|
|
232
242
|
`• F-016 AC↔ownership consistency: for each acceptance_criterion, derive the file(s) it requires editing. If those files are NOT a subset of the card's MAY-EDIT/files_likely_touched → add the AC to policyDeferredACs:[{n,text,owningCard|owningFile,reason}] (it will become ONE follow-up, never a resolve). Do the same for any AC whose remedy is an owner-gated infra action (remote db push / deploy / secret / DNS).\n` +
|
|
243
|
+
(migrationApplied
|
|
244
|
+
? `• MIGRATION ALREADY APPLIED (skill Migration Gate, Step 3.5): the DB migration "${migration.summary || '(declared)'}" was applied to the active DB BEFORE this batch — the schema is LIVE. EXCEPTION to the F-016 owner-gated rule above: do NOT classify the schema-apply / "run migration" / db-push AC of card(s) [${migrationAffects.join(', ') || '(affects_cards from the epic)'}] as policyDeferredAC — it is SATISFIED. Those cards must run REAL validation against the live schema (validation_commands, queries, DB-generated types), not defer it. (A migration NOT covered by this manifest still follows the owner-gated deferral above.)\n`
|
|
245
|
+
: '') +
|
|
233
246
|
`• Ownership (setup.md 3c): build the file-ownership map → /tmp; return ownershipMapPath. F-040: each card's MAY-EDIT = files_likely_touched ∪ every path NAMED EXPLICITLY in that card's acceptance_criteria/definition_of_done (an ADR the DoD says to update, the data-model / ER doc for a schema-change, etc.) — so editing a DoD-mandated doc is NOT a file-diff violation. Do NOT add another card's files this way.\n` +
|
|
234
247
|
`• Do NOT write architecture baselines — the per-card codebase-architect specialist does that during the card pipeline (B7).\n\n` +
|
|
235
248
|
`Return the structured PREFLIGHT object. ok:false ONLY if the workspace is unworkable.`,
|
|
@@ -429,7 +442,10 @@ async function runCard(cardId, cardPath) {
|
|
|
429
442
|
return { card: cardId, status: 'committed', commit: node.alreadyCommittedSha || '-', filesChanged: [], scopeFiles: [], archBaselinePath: `/tmp/arch-baseline-${cardId}.md`, gates }
|
|
430
443
|
}
|
|
431
444
|
|
|
432
|
-
const
|
|
445
|
+
const migrationNote = (migrationApplied && migrationAffects.includes(cardId))
|
|
446
|
+
? `\nMIGRATION LIVE: the DB migration "${migration.summary || '(declared)'}" was applied to the active DB BEFORE this batch (skill Migration Gate). The schema is REAL — run actual validation against it (validation_commands, queries, DB-generated types); do NOT defer the schema-apply AC or build against an absent schema.`
|
|
447
|
+
: ''
|
|
448
|
+
const cardBrief = `${projectBrief}\n\nCard: ${cardId}\nCard YAML: ${cardPath}\nOwner agent: ${ownerAgent} · Review profile: ${reviewProfile}\nWorktree: ${sharedCtx.worktreePath} (cd into it)\nFile-ownership map: ${sharedCtx.ownershipMapPath}\nNOTE: ACs already pre-classified as policy-deferred MUST NOT be implemented or routed — they are tracked as follow-ups.${migrationNote}`
|
|
433
449
|
|
|
434
450
|
// --- Phase 1 (B7, v4.26.0) — SPECIALIST decomposition: each Phase-1 duty runs as its own
|
|
435
451
|
// agent ("ognuno fa una cosa"), with handoff via /tmp files so the owner's context stays
|
|
@@ -966,6 +982,10 @@ function buildTelemetry() {
|
|
|
966
982
|
cards_followup: perCardResults.filter((r) => r.status === 'followup').length,
|
|
967
983
|
cards_blocked: runnableCards.filter((id) => state[id] === 'blocked').length,
|
|
968
984
|
cards_deferred: residuals.filter((x) => x.kind === 'policy-deferred-ac').length,
|
|
985
|
+
// Migration Gate (skill Step 3.5, pre-launch — NOT a mid-batch question, so the zero-ask-during
|
|
986
|
+
// -batch invariant is intact). 'applied' = schema front-loaded; the affected cards' apply-AC was
|
|
987
|
+
// satisfied up-front instead of deferred owner-gated.
|
|
988
|
+
migration_gate: (migration && migration.status) || 'none',
|
|
969
989
|
residuals_total: residuals.length,
|
|
970
990
|
// followups_on_disk is filled by the SKILL after it materialises pending residuals.
|
|
971
991
|
followups_materialized_in_workflow: residuals.filter((x) => x.materialized).length,
|
|
@@ -50,6 +50,7 @@ Full protocol: [`framework/agents/project-context.md`](../../agents/project-cont
|
|
|
50
50
|
|------|------|
|
|
51
51
|
| `ui-design.fidelity-example.md` | Neo-Brutalism, Recharts/nivo charting stack, merchant theming pairing, Safari open command, evaluation thresholds |
|
|
52
52
|
| `copywriting.fidelity-example.md` | 4-pillar brand voice, Italian-only rule, segment register matrix (customer/merchant/staff/admin), forbidden vocabulary |
|
|
53
|
+
| `new.migration-example.md` | Migration-Gate apply modalities (`/new` Phase 0 step 1b · `new2` Step 3.5) — how this project front-loads a declared DB migration (db:push / local apply / Prisma deploy) before the batch |
|
|
53
54
|
|
|
54
55
|
Other overlay examples may be added over time. Skills that did not have
|
|
55
56
|
heavy hard-coded opinions (e.g. `find-skills`, `simplify`) don't need
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
base_skill: new
|
|
3
|
+
base_skill_version: 4.28.0
|
|
4
|
+
mode: extend
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# new — migration-gate overlay (example)
|
|
8
|
+
|
|
9
|
+
> Drop this into your repo at `.baldart/overlays/new.md` (it is shared by `/new`
|
|
10
|
+
> **and** `new2`) to teach the **Migration Gate** how *your* project applies a DB
|
|
11
|
+
> schema change. The gate runs **before** the batch (/new Phase 0 step 1b · new2
|
|
12
|
+
> Step 3.5): when an epic card declares a `migration_plan`, the skill front-loads
|
|
13
|
+
> the migration interactively so downstream cards verify against the **live**
|
|
14
|
+
> schema instead of one deferred to the end of the batch.
|
|
15
|
+
>
|
|
16
|
+
> Two layers cooperate:
|
|
17
|
+
> 1. **The epic card** declares *that* a migration is needed + the artifacts
|
|
18
|
+
> (`migration_plan` block — see `epic-template.yml`).
|
|
19
|
+
> 2. **This overlay** declares *how* this project applies migrations (the
|
|
20
|
+
> `## Migration modalities` section below). The gate merges the epic's
|
|
21
|
+
> `apply_modalities` with these, de-duped by `id`, and adds the built-in
|
|
22
|
+
> `["Già applicata — prosegui", "Abort"]` tail.
|
|
23
|
+
>
|
|
24
|
+
> Adapt the commands to your stack (Supabase / Prisma / Drizzle / raw SQL / …).
|
|
25
|
+
|
|
26
|
+
## Migration modalities
|
|
27
|
+
|
|
28
|
+
These are offered (via `AskUserQuestion`) whenever an epic declares
|
|
29
|
+
`migration_plan.required: true` and its `artifacts` exist on disk. The skill runs
|
|
30
|
+
the chosen `command` in the main repo (`$MAIN`), captures output to
|
|
31
|
+
`/tmp/migration-<first-card>.log`, surfaces only the exit code, and — when the
|
|
32
|
+
`migration_plan.verify` probe is present — requires it green too. A command is
|
|
33
|
+
**never** run without the user selecting it.
|
|
34
|
+
|
|
35
|
+
- **id: `remote-push`** — applica al DB remoto/condiviso (owner-gated; eseguito
|
|
36
|
+
dalla skill SOLO su tua approvazione esplicita).
|
|
37
|
+
- command: `npx supabase db push`
|
|
38
|
+
- When to pick: dev DB condiviso o staging dove le card verificano contro il
|
|
39
|
+
DB reale.
|
|
40
|
+
- **id: `local`** — applica a un DB locale/shadow; la prod resta un deploy
|
|
41
|
+
manuale post-merge (Phase 7 lo riporta come item manuale).
|
|
42
|
+
- command: `npx supabase db reset --local` *(oppure `npx prisma migrate dev`)*
|
|
43
|
+
- When to pick: il batch verifica contro un DB locale effimero.
|
|
44
|
+
- **id: `prisma-deploy`** — esempio Prisma per uno stack diverso.
|
|
45
|
+
- command: `npx prisma migrate deploy`
|
|
46
|
+
|
|
47
|
+
> Verifica post-apply consigliata (referenziata da `migration_plan.verify`
|
|
48
|
+
> nell'epic): rigenera i tipi dal DB così `tsc` downstream è onesto, es.
|
|
49
|
+
> `npx supabase gen types typescript --local > src/types/db.ts` oppure
|
|
50
|
+
> `npx prisma generate`.
|
|
51
|
+
|
|
52
|
+
## Notes
|
|
53
|
+
|
|
54
|
+
- Se l'epic NON dichiara `migration_plan` (o `required: false`), il gate è un
|
|
55
|
+
**no-op silenzioso** — nessun prompt aggiuntivo, comportamento identico a oggi.
|
|
56
|
+
- Se gli `artifacts` non esistono ancora su disco, il gate **degrada**: non
|
|
57
|
+
applica nulla e la migrazione segue il path owner-gated di fine batch (nessuna
|
|
58
|
+
regressione). La migrazione va autorata prima per essere front-loaddata.
|
|
59
|
+
- Le modalità possono anche arrivare dalla **memoria di progetto** (oltre che da
|
|
60
|
+
questo overlay e dal blocco epic): la skill le unisce tutte.
|