baldart 4.14.0 → 4.15.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,34 @@ 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.15.0] - 2026-06-04
|
|
9
|
+
|
|
10
|
+
**Il pre-flight di `/new` smette di gonfiare il contesto dell'orchestrator: il setup worktree + baseline build e il check Codex cross-card girano in background fuori dal prefisso cached, e le scritture del tracker di pre-flight si fondono in un singolo flush.** Forensics su una run reale (`/new FEAT-0020 -full`, 8 card, team mode) — estrazione del campo `usage` per turno dal transcript — ha mostrato **~150k token di occupazione al solo pre-flight, prima di toccare una card**, con un `cache_read` cumulativo di ~10M token (il prefisso ri-letto a ogni turno × ~70 turni). La diagnosi ovvia («è il bloat della prosa della skill») è stata **refutata dai numeri**: dopo lo split di v4.14.0, la prosa skill-controllata in quei 150k è solo ~18%; il floor statico ambiente (schemi tool MCP + CLAUDE.md + memoria) è ~42% e non è toccabile da `/new`; il vero driver residuo è il **numero di turni dell'orchestrator nel pre-flight** (~70) — ognuno ri-bolla il prefisso — alimentato da tre sprechi concreti. **MINOR** (cambio di orchestrazione capability-preserving di `/new`: stessi gate, stessi output, stesso install-contract; nessuna chiave `baldart.config.yml`, nessuna modifica CLI).
|
|
11
|
+
|
|
12
|
+
> **Why.** L'orchestrator di `/new` è long-lived: tutto ciò che entra nel suo contesto ci resta per l'intera run e viene ri-letto (a tariffa cache-read) a ogni turno. Tre cose lo gonfiavano al pre-flight senza alcun bisogno di restare nell'orchestrator: (1) l'invocazione inline di `/nw` caricava il corpo da **~1200 righe** di `worktree-manager` nel prefisso cached + camminava `npm install`/`tsc`/`lint`/`build` per ~15-20 turni foreground; (2) il trace `[codex]` del check cross-card rientrava nell'orchestrator perché il result-handling faceva `tail`/`cat` del file grezzo (pieno di righe di comando-trace) invece del solo verdict; (3) il tracker veniva creato e poi editato ~5 volte in modo incrementale durante un pre-flight che è idempotente e non ha bisogno di persistenza mid-flight. La cura sposta (1) e (2) in **contesti usa-e-getta** (subagente background + Bash background) di cui l'orchestrator trattiene solo il verdict strutturato, e collassa (3) in **un solo flush**. Il pattern è additivo agli invarianti già presenti (§ "Context economy" del core, regola sul canale inline) e non tocca nessun gate BLOCKING né il contratto di recovery per-fase dell'esecuzione card. Lezione metodologica confermata: dopo ogni fix il driver dominante può spostarsi d'asse — qui da "prosa nel prefisso" (v4.13/4.14) a "turni di pre-flight × prefisso crescente".
|
|
13
|
+
|
|
14
|
+
> **Onestà sulla magnitudine (post code-review + DUE giri di adversarial review).** Il risparmio vero è il **sollievo del prefisso dell'orchestrator** (corpo di worktree-manager fuori dal prefisso cached + ~15-30 turni foreground collassati in background ops): i token del build NON spariscono — vengono spesi nel subagente, sullo stesso pool di sessione — ma smettono di moltiplicarsi contro il prefisso crescente dell'orchestrator a ogni turno. La review avversariale ha **refutato** quattro punti rivelatisi difetti reali (poi fixati): (1) l'assunzione "un subagente può invocare una Skill" era **non provata e senza fallback** → **fallback inline a `/nw`** se il subagente non ritorna il blocco; (2) la barriera a due op poteva **risvegliarsi sul primo completamento** e leggere un `$AUDIT_FILE` a metà → **wait-for-ALL esplicito**; (3) la delega worktree apriva un **recovery-gap** (un worktree di codice NON è ri-creabile — `/nw` fa fail-loud su collisione). Il primo rimedio (pre-check su `registry.json`) è stato **a sua volta refutato dal secondo giro**: worktree-manager scrive l'entry registry SOLO a fine `/nw`, *dopo* il build, quindi per tutta la finestra di barriera il worktree esiste su disco ma NON è in registry → il check era cieco proprio nello scenario da coprire. Fix corretto: **rilevamento git-autoritativo** (`git worktree list` sul branch deterministico) con resume-se-completo / reset-e-ricrea-se-orfano (a pre-flight non c'è lavoro card da perdere); (4) il flush proponeva un `Write`-da-memoria che dopo una compaction avrebbe **droppato i campi Phase-0** (`$MAIN`/`$TRUNK`) → ora solo `Edit` chirurgici, mai overwrite; più una clausola nel **Context recovery protocol** del core che codifica il rientro in Pre-flight step 4. Per contro l'adversarial è stata essa stessa **refutata dai dati** sul filtro `[codex]`: lo static-grep del `.mjs` diceva "prefisso mai emesso", ma il file audit reale ha **63 righe `[codex]` su 73** (il wrapper Codex di Claude Code le emette nel redirect) → il filtro è corretto e tenuto.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **`framework/.claude/skills/new/references/setup.md`** — Pre-flight (once) step 4-6 riscritti:
|
|
19
|
+
- **Step 4 (Lever #1)**: il setup worktree non è più invocato inline; l'orchestrator spawna **un subagente background** (`general-purpose`, **`mode: bypassPermissions`**, `run_in_background`, `name: worktree-setup-<FIRST-CARD-ID>`) che invoca `/nw` programmatic e ritorna SOLO un blocco strutturato (`worktree_path`/`branch`/`port`/`created_at`/`baseline`/`baseline_log`). Il corpo da ~1200 righe di `worktree-manager` + i log install/build vivono e muoiono nel contesto del subagente. **Guardie (post-review, 2 giri)**: step **4a2** pre-check **git-autoritativo** (`git worktree list` sul branch deterministico — NON il registry, che è scritto solo a fine `/nw` ed è cieco durante il build) → worktree completo: resume; orfano mid-build: reset (`worktree remove --force` + `branch -D`) e ricrea; step **4d** fallback inline a `/nw` se il subagente non ritorna il blocco (capability Skill-da-subagente non assunta, mai strandare la barriera); campo `created_at` nel blocco (e letto dal registry sul path di resume) per non rompere `cycle_time_mins`; flush con soli `Edit` chirurgici (mai `Write`-da-memoria, che dopo compaction droppa i campi Phase-0).
|
|
20
|
+
- **Step 5 (barrier)**: l'orchestrator lancia 3d (Codex) + 4 (worktree subagent) insieme e **chiude il turno** su una barriera **wait-for-ALL** (attende OGNI op lanciata, non la prima — altrimenti leggerebbe un `$AUDIT_FILE` a metà; compaction mid-barrier rientra in pre-flight, resa sicura dal 4a2) — niente più ~30 turni foreground di walk-through (no `sleep`/`echo`, ri-invocazione automatica a completamento).
|
|
21
|
+
- **Step 6 (Lever #3)**: al resume, gate sul `baseline: fail` (STOP), verdict Codex distillato, e **un singolo Edit** che scrive l'intero blocco di pre-flight (`## File Ownership Map` + `## Execution Mode` + `## Worktree` + `## Cross-Card Conflicts (Codex)`) — niente Edit incrementali per sub-step (pre-flight idempotente; la persistenza incrementale resta per l'esecuzione card).
|
|
22
|
+
- **Step 3d "Result handling" (Lever #2)**: aggiunta la **verdict-extraction discipline** — il file `$AUDIT_FILE` contiene il trace `[codex]` davanti al verdict; vietato `cat`/`tail`/`head` grezzo, si legge solo via filtro `grep -vE '^\[codex\]' "$AUDIT_FILE" | tail -n 60` e si logga il finding distillato, mai il trace.
|
|
23
|
+
- **`framework/.claude/skills/new/references/team-mode.md`** — Team Mode Pre-flight: le sezioni `## Team Mode` + `## Parallel Groups` confluiscono nel **flush unico** di setup.md step 6c (niente Edit separato); il wave layout è risolto prima del lancio dei background ops, così è in-context per il flush.
|
|
24
|
+
- **`framework/.claude/skills/new/SKILL.md`** — § "Context economy": nuovo **punto 6** (delega il setup body-heavy a un contesto usa-e-getta — background subagent/Bash, l'orchestrator tiene solo il verdict; batch delle scritture tracker di pre-flight) + chiusura della regola estesa a «what the orchestrator chooses to retain».
|
|
25
|
+
|
|
26
|
+
## [4.14.1] - 2026-06-04
|
|
27
|
+
|
|
28
|
+
**Il gate Simplify del Team Mode di `/new` (D.3b) ora skippa solo le card davvero trivial (`TRIVIAL_CARDS`), non tutte quelle con `review_profile == skip` — chiude una divergenza col path sequential (Phase 2.55 `IS_TRIVIAL`) e con la stessa D.1.5 di team-mode.** La pipeline per-card di `/new` vive in due modalità (sequential e team) che ri-enunciano alcuni gate; due predicati gemelli erano davvero divergenti. **Drift 1 (bug, fixato)**: il sequential Phase 2.55 ri-conferma `IS_TRIVIAL` sul diff ACTUAL committato (tutte e 3 le condizioni, incl. il check non-source) → una card `review_profile=skip` con un file SORGENTE nel diff reale NON è trivial → ESEGUE Simplify; il team D.3b invece skippava sul solo `review_profile == skip`, ignorando il diff reale → la saltava. Aggravante: team-mode era incoerente con sé stesso — a D.1.5 calcola GIÀ `TRIVIAL_CARDS` col check non-source completo (e la sua nota SSOT dichiara «D.3b already skipped for trivial»), ma il gate D.3b gateava sul set più lasco. Blast radius: solo qualità (la card prendeva comunque D.2 code-review + il Final FULL gate), ma in team mode si perdeva la difesa contro la deviazione del coder che il sequential ha. **Drift 2 (intenzionale, documentato)**: lo scope per-GRUPPO della QA gate (D.4) vs per-CARD del sequential (21b) — stesso predicato (`deep`/risk → FULL, altrimenti defer al Final), granularità per necessità del modello a wave (qa-sentinel gira una volta sul diff combinato del gruppo); è il lato deliberatamente più conservativo (una card rischiosa → tutto il gruppo FULL), nessun gap di correttezza → comportamento invariato, aggiunta solo una frase di chiarimento. **PATCH** (bugfix di un falso-skip in team mode; nessuna capability, nessuna chiave `baldart.config.yml`).
|
|
29
|
+
|
|
30
|
+
> **Why.** I gate ri-enunciati nei due path di `/new` devono restare predicato-identici, o le due modalità divergono silenziosamente. Qui il fix è un puro allineamento: D.3b passa dal set lasco (`review_profile == skip`) al set già calcolato a monte a D.1.5 (`TRIVIAL_CARDS` = `review_profile==skip` AND 0 Step-A triggers AND non-source diff), che è esattamente l'`IS_TRIVIAL` del sequential 2.55. Nessuna nuova logica, nessun ricalcolo: si consuma il set che D.1.5 dichiarava già di pilotare. Il Drift 2 si lascia perché la granularità per-gruppo è una necessità del modello a wave (un solo qa-sentinel sul diff combinato), non una svista, ed è il lato più sicuro — ma ora è documentato come intenzionale per non farlo rifixare in futuro.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- **`framework/.claude/skills/new/references/team-mode.md`** — gate D.3b (Simplify) riscritto da «SKIP per `review_profile == skip`» a «SKIP per card in `TRIVIAL_CARDS`» (il set già computato a D.1.5), con log-line allineata al sequential (`simplify: SKIPPED (trivial — non-source diff)`); una card `skip` con file sorgente nel diff ora esegue Simplify come nel sequential 2.55. D.4 (QA gate) — aggiunta una frase che documenta lo scope per-gruppo come INTENZIONALE (stesso predicato del sequential 21b, valutato a livello di gruppo perché qa-sentinel gira una volta sul diff combinato; lato deliberatamente più conservativo). Nessun cambio di logica su D.4.
|
|
35
|
+
|
|
8
36
|
## [4.14.0] - 2026-06-04
|
|
9
37
|
|
|
10
38
|
**Nuovo tipo di payload `.claude/workflows/` (dynamic workflow di Claude Code) + il primo workflow `new-final-review`: la Final Review F.2–F.4 di `/new` può girare come script di orchestrazione deterministico, opt-in e con fallback inline.** I dynamic workflow (research-preview di Claude Code) spostano l'orchestrazione fan-out fuori dal context-window dell'orchestrator, nel codice. Una review avversariale ha **refutato** l'idea di farne il motore *per-card* di `/new` (rompe la portabilità Codex — sono Claude-only; dipende da una preview come breaking change; duplica la logica di gate col team-mode; introduce attrito-permessi e regressione di recovery proprio dove `/new` è più intrecciata con worktree/git/stato). Il bersaglio scelto è invece la parte dove i rischi spariscono e il valore resta: la **Final Review F.1–F.6** è **read-only** (gli agenti leggono solo il diff committato), ha **definizione SSOT unica** condivisa da sequential e team mode (→ nessun twin), e ha l'**adversarial-verify già nativo** (FP-check di Codex in F.3, cross-validation `code-reviewer` a confidence<80 in F.4). **MINOR** (nuova capability additiva: nuovo payload type + un workflow; nessun breaking change, nessuna chiave `baldart.config.yml` — il gating è runtime via presenza del tool `Workflow`; i consumer senza workflow o Codex-only eseguono la Final Review inline come prima).
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.15.0
|
|
@@ -80,7 +80,7 @@ Branch: [feat/FEAT-XXXX-slug]
|
|
|
80
80
|
Slug: [the slug used to derive Branch/Path — see Pre-flight step 4]
|
|
81
81
|
Path: [.worktrees/feat-FEAT-XXXX-slug]
|
|
82
82
|
Port: [from registry]
|
|
83
|
-
Created: [ISO-8601 timestamp the worktree was created — Pre-flight step
|
|
83
|
+
Created: [ISO-8601 timestamp the worktree was created — Pre-flight step 6c backfills from the worktree-setup subagent's created_at; Phase 8 cycle_time_mins start anchor]
|
|
84
84
|
Group parent: [FEAT-XXXX or "standalone"]
|
|
85
85
|
Main repo: [/absolute/path/to/main/repo]
|
|
86
86
|
Trunk branch: [resolved git.trunk_branch — Phase 0 step 0 populates]
|
|
@@ -230,8 +230,14 @@ baselines. Keep that bulk on disk and pass **paths**, not bodies.
|
|
|
230
230
|
> inlining their concatenated contents.
|
|
231
231
|
> 5. **Targeted Reads.** When verifying code (Phase 2.5), Read only the evidence lines (grep with
|
|
232
232
|
> tight context around the `file:line` the completion report names) — not whole files.
|
|
233
|
+
> 6. **Delegate body-heavy setup to a discarded context.** Work whose *output* the orchestrator does
|
|
234
|
+
> not retain — worktree creation + baseline build (invoking `/nw` loads the ~1200-line
|
|
235
|
+
> worktree-manager skill into the cached prefix), external grounding checks — runs in a **background
|
|
236
|
+
> subagent / background Bash**; the orchestrator keeps only the structured verdict (a handful of
|
|
237
|
+
> fields), never the skill body, logs, or trace. And **batch the pre-flight tracker writes into one
|
|
238
|
+
> flush** — pre-flight is idempotent, so per-sub-step Edits are churn the cached prefix re-reads.
|
|
233
239
|
>
|
|
234
|
-
> This rule is
|
|
240
|
+
> This rule is about the **inline channel** and what the orchestrator chooses to retain. It does NOT change any agent's return contract,
|
|
235
241
|
> nor what the orchestrator is allowed to read at a decision point — only that bulk arrives via a
|
|
236
242
|
> path the consumer opens itself, not via the orchestrator's own context.
|
|
237
243
|
|
|
@@ -311,6 +317,7 @@ per-card nei sub-step D.x (mai aggregate). Caricalo quando Pre-flight seleziona
|
|
|
311
317
|
If at ANY point you are unsure where you are in the batch:
|
|
312
318
|
1. Read your tracker file (`/tmp/batch-tracker-<FIRST-CARD-ID>.md`)
|
|
313
319
|
2. Check `## Current Card` — if populated, resume that card at the listed phase.
|
|
320
|
+
2b. **Pre-flight not finished?** If `## Current Card` is empty / `(none — starting pre-flight)` AND `## Worktree` still shows skeleton placeholders (no real `Path:`/`Port:`), then a compaction hit mid-pre-flight (most likely during the step-5 background barrier). Re-enter **Pre-flight at step 4** (Read the `setup.md` module first per § "Routing"): its step-4a2 git pre-check re-detects an already-created worktree via `git worktree list` and resumes-or-resets it safely — so re-entry never double-creates or fails-loud.
|
|
314
321
|
3. **Re-Read the phase module** named in `## Current Card`'s `phase_module_loaded:` field (a compaction may have evacuated it from context — see § "Routing" HARD RULE). If the field is absent, map the listed phase to its module via the § "Routing" table and Read that.
|
|
315
322
|
4. Check `## Card Queue` — find the next unchecked card.
|
|
316
323
|
5. Check `## Completed Cards` — know what's already done (don't redo).
|
|
@@ -157,9 +157,9 @@
|
|
|
157
157
|
|
|
158
158
|
When `mode == sequential`, the per-card pipeline below runs exactly as documented. The `execution_strategy.groups` levels are simply ignored. When `mode == team`, skip the per-card pipeline and follow the **Team Mode** section at the end of this document.
|
|
159
159
|
|
|
160
|
-
**→ Create the Task spine now.** The execution mode and (in team mode) the wave layout are resolved — create the native Task spine per § "Progress Visibility" A: `Pre-flight` (→ `in_progress`) + one task per card (wave-labelled in team mode) + `Final review` + `Merge & cleanup`. Emit the first Progress Bar with this batch's table. Mark `Pre-flight` → `completed`
|
|
160
|
+
**→ Create the Task spine now.** The execution mode and (in team mode) the wave layout are resolved — create the native Task spine per § "Progress Visibility" A: `Pre-flight` (→ `in_progress`) + one task per card (wave-labelled in team mode) + `Final review` + `Merge & cleanup`. Emit the first Progress Bar with this batch's table. Mark `Pre-flight` → `completed` at the pre-flight resume (step 6d), once both background ops have returned and the consolidated tracker flush is written.
|
|
161
161
|
|
|
162
|
-
3d. **Codex batch cross-card grounding check** (
|
|
162
|
+
3d. **Codex batch cross-card grounding check** (background — launched together with the worktree-setup subagent in step 4, then a single barrier in step 5)
|
|
163
163
|
|
|
164
164
|
> **Why**: a non-Anthropic frontier model (Codex, via `codex-companion.mjs`) reviews the full card batch for cross-card conflicts that per-card plan-auditor checks cannot detect (each plan-auditor sees only one card).
|
|
165
165
|
|
|
@@ -228,7 +228,12 @@
|
|
|
228
228
|
**Result handling** (read before Phase 1 of first card):
|
|
229
229
|
- **Background completion barrier (BLOCKING):** record the background task id when you launch it; do NOT read `$AUDIT_FILE` until that task has completed. Because this gate's verdict steers Phase-1 card ordering, the first card MUST NOT start while the check is in flight.
|
|
230
230
|
- **TIMED_OUT branch:** the launch sets `timeout: 300000` (5 min). If the background task hits the timeout without producing a terminal result (the tail of `$AUDIT_FILE` shows no `PASS` / conflict block / `CODEX_NOT_FOUND`), treat it as **TIMED_OUT** — do NOT leave the task "in-progress" and silently proceed. Log `cross-card-check: TIMED_OUT` in `## Cross-Card Conflicts (Codex)` and take the SAME fallback as `CODEX_NOT_FOUND`: spawn `code-reviewer` over the batch with the four conflict questions. Never start the batch with cross-card review in an unresolved/in-flight state.
|
|
231
|
-
-
|
|
231
|
+
- **Verdict-extraction discipline (Context economy — the trace MUST NOT re-enter the orchestrator).** `$AUDIT_FILE` holds the full `[codex]` command trace (every `sed`/`grep`/`cat` Codex ran while investigating) *ahead of* the verdict — that trace is pure noise and must never land in the orchestrator's context. **NEVER `cat`/`tail`/`head` the raw file.** Read it only through a filter that strips the trace and keeps the terminal verdict:
|
|
232
|
+
```bash
|
|
233
|
+
grep -vE '^\[codex\]' "$AUDIT_FILE" | tail -n 60
|
|
234
|
+
```
|
|
235
|
+
Parse PASS / `CODEX_NOT_FOUND` / conflict-findings from that filtered output only. When logging to the tracker, write the **distilled findings** (one line per conflict: cards + type + one-line fix) — never paste the raw block, and never the trace.
|
|
236
|
+
- Read the exact `$AUDIT_FILE` path recorded in the tracker after the background command completes (always via the trace-stripping filter above).
|
|
232
237
|
- If the file contains **`CODEX_NOT_FOUND`** (Codex unavailable): do NOT silently proceed — **fallback**: spawn the `code-reviewer` agent over the full batch's card YAMLs + file-ownership map with the same cross-card conflict questions (FILE_CONFLICT / IMPLICIT_DEP / ORDER_RISK / STATE_MUTATION). If `code-reviewer` is also unavailable, surface `CAPABILITY_UNAVAILABLE: cross-card-review` to the user and ask whether to proceed without cross-card detection or halt. Never run a multi-card batch with cross-card review silently skipped.
|
|
233
238
|
- If **PASS** or file empty: proceed normally.
|
|
234
239
|
- If **conflicts found**: log in tracker under `## Cross-Card Conflicts (Codex)` and present to user. For each conflict:
|
|
@@ -236,14 +241,51 @@
|
|
|
236
241
|
- `IMPLICIT_DEP` → add `depends_on` entry to tracker notes (do NOT modify backlog YAML).
|
|
237
242
|
- `STATE_MUTATION` → add warning to both cards' Phase 2 briefings.
|
|
238
243
|
|
|
239
|
-
4. **Worktree setup
|
|
240
|
-
a. **Resolve the `slug`** (
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
4. **Worktree setup — delegate to a BACKGROUND subagent (Context economy: the worktree-manager skill body + the install/build walk-through must NOT enter the orchestrator context).** Do **NOT** invoke `/nw` inline from the orchestrator. Invoking the skill here loads the ~1200-line `worktree-manager` body into the orchestrator's **cached prefix** (re-read every later turn) and then steps through `npm install` → `tsc` → `lint` → `build` across ~15-20 foreground turns, each re-reading the whole growing prefix. Both costs are pure waste in the orchestrator — they belong in a context that is discarded. Instead:
|
|
245
|
+
a. **Resolve the `slug`** (in-context, cheap — the only part the orchestrator keeps). Derive it deterministically: if the parent card (or the lead card) has `git_strategy.branch` set, parse the slug from it (`feat/<PARENT-ID>-<slug>` → `<slug>`); otherwise slugify the parent/lead card `title` (lowercase, non-alphanumerics → `-`, collapse repeats, trim, cap ~40 chars). Do NOT let `/nw` invent its own slug — pass it explicitly.
|
|
246
|
+
a2. **Recovery/idempotency pre-check (BLOCKING — before any spawn; detect via GIT, not the registry).** A **code** worktree is NOT re-creatable: `/nw` **fails loudly on a slug/branch collision** (it does not resume like docs mode — see worktree-manager step 2 "code worktree collision → fail loudly"). And the registry is a **lagging** witness — worktree-manager writes its entry only at the END of `/nw`, *after* the full build (worktree-manager step 6), so for the whole barrier window a worktree can exist on disk while `.worktrees/registry.json` has NO entry for it. Detecting by registry presence would therefore be blind exactly during the compaction window this guard exists for. Use the **git-authoritative** check instead:
|
|
247
|
+
```bash
|
|
248
|
+
# WT_BRANCH MUST be resolved EXACTLY as /nw will derive it (or detection misses a custom branch
|
|
249
|
+
# and the re-spawn hits the fail-loud collision this guard exists to prevent):
|
|
250
|
+
# use the parent/lead card's git_strategy.branch verbatim if set, else the fallback feat/<PARENT-ID>-<slug>.
|
|
251
|
+
WT_BRANCH="<git_strategy.branch — or — feat/<PARENT-ID>-<slug>>"
|
|
252
|
+
WT_PATH="$(git -C "$MAIN" worktree list --porcelain \
|
|
253
|
+
| awk -v b="refs/heads/$WT_BRANCH" '$1=="worktree"{p=$2} $1=="branch"&&$2==b{print p}')"
|
|
254
|
+
```
|
|
255
|
+
- **`WT_PATH` empty** (no worktree) → proceed to 4b (spawn fresh).
|
|
256
|
+
- **`WT_PATH` set AND `registry.json` has a complete code entry for this slug** (a finished prior run — `buildVerified` recorded) → **resume**: read `path`/`branch`/`port`/`createdAt`/`buildVerified` from that entry, skip to step 6; re-run the baseline as a single background `Bash` (output to `/tmp`) **only if** `buildVerified` is not `true`.
|
|
257
|
+
- **`WT_PATH` set but NO complete registry entry** (a prior attempt interrupted mid-setup — the normal compaction-mid-barrier state: worktree created, build unfinished, entry never written) → it is a half-built orphan with **no card work** (we are still in pre-flight, zero commits). **Reset clean and recreate**: `git -C "$MAIN" worktree remove --force "$WT_PATH"` then `git -C "$MAIN" branch -D "$WT_BRANCH"` (both ignore-if-absent), then proceed to 4b. A pre-flight worktree has nothing to lose, so a clean recreate is always safe — and it sidesteps the fail-loud collision a naive re-spawn would hit.
|
|
258
|
+
This — detection by `git worktree list`, not the lagging registry — is what makes the deferred-flush pre-flight genuinely idempotent across compaction.
|
|
259
|
+
b. **Spawn ONE background subagent** (Agent tool, **`mode: "bypassPermissions"`** — mandatory per the SKILL.md meta-rules; a background agent that hit a permission prompt with no human present would stall the barrier forever — `run_in_background: true`, `name: "worktree-setup-<FIRST-CARD-ID>"`, a subagent type that can use the Skill tool — `general-purpose`) whose ENTIRE mission is to run `/nw` and return the block below. Briefing:
|
|
260
|
+
```
|
|
261
|
+
Invoke the worktree-manager skill in `/nw` programmatic mode with:
|
|
262
|
+
{ cards: [<all card IDs>], groupParent: <PARENT-ID|null>, slug: "<slug>" }
|
|
263
|
+
Let it: group cards, derive the branch from git_strategy.branch (fallback
|
|
264
|
+
feat/<PARENT-ID>-<slug>), create the worktree in .worktrees/, install deps,
|
|
265
|
+
copy env files, assign a free port, update .worktrees/registry.json (all card
|
|
266
|
+
IDs in the `cards` field), and run the baseline (tsc + lint + build).
|
|
267
|
+
Redirect ALL install/build/git output to files under /tmp — never inline it.
|
|
268
|
+
Return ONLY this block, nothing else (no logs, no narration, no skill recap):
|
|
269
|
+
worktree_path: <absolute path>
|
|
270
|
+
branch: <branch>
|
|
271
|
+
port: <n>
|
|
272
|
+
created_at: <ISO-8601, stamped WHEN you create the worktree — before install/build>
|
|
273
|
+
baseline: pass | fail
|
|
274
|
+
baseline_log: <path on failure, else "-">
|
|
275
|
+
If the build fails, return `baseline: fail` with the log path and STOP — do not continue.
|
|
276
|
+
```
|
|
277
|
+
c. The subagent's context (the worktree-manager skill body, install/build logs, git output) **lives and dies inside it** — the orchestrator receives only the structured block. Combined with the Codex check (3d, also background), this replaces the old ~30-turn foreground pre-flight tail with background ops and a single resume.
|
|
278
|
+
d. **Fallback if the subagent cannot run `/nw` (the Skill-from-subagent capability is NOT assumed).** If the subagent returns empty, or without the structured block — e.g. it cannot invoke the Skill tool in this consumer, or it returns the known "0 tool uses · Done" empty-result failure — do **NOT** strand the barrier: the orchestrator **falls back to invoking `/nw` inline itself** (the pre-v4.15.0 path — slug from 4a, then record `worktree_path`/`branch`/`port` and stamp `created_at` from the inline return). You lose the prefix saving for this one run, but pre-flight completes. This is the same opt-in-with-fallback discipline the Codex check (3d) and the dynamic-workflow gate use — never leave the worktree uncreated on a missing capability.
|
|
279
|
+
5. **End the turn — barrier on ALL launched background ops (wait for every one, not the first).** Having launched the Codex cross-card check (3d) and the worktree-setup subagent (4), the orchestrator has nothing to do until they return. **End the turn** — do NOT poll with `sleep`/`echo "waiting"` loops (§ "Context economy"; same rule as team-mode Step C). Background agents and background `Bash` re-invoke the orchestrator automatically on completion. **Wait for EVERY launched op before step 6**: each completion wakes you separately, so on each wake check whether *all* launched ops have returned — if one is still in flight, **end the turn again** and wait. Do NOT proceed to step 6 on the first completion, or you would read a half-written `$AUDIT_FILE` (and 3d's "If PASS or file empty: proceed normally" would silently swallow real conflicts) or a missing worktree block. (If 3d was SKIPPED by the provenance gate, the only op is the worktree subagent — or none, if step 4a2 resumed an existing worktree.) **Recovery**: a compaction mid-barrier re-enters pre-flight from step 4; the 4a2 git pre-check makes that safe (the worktree is detected via `git worktree list` and resumed-or-reset, never blindly re-created into a fail-loud collision).
|
|
280
|
+
6. **On resume — flush the pre-flight tracker sections in one pass (no incremental per-sub-step churn).** When all launched ops have returned:
|
|
281
|
+
a. **Baseline gate**: if the worktree subagent returned `baseline: fail` → STOP and report (point the user at `baseline_log`). Do NOT continue to Phase 1.
|
|
282
|
+
b. **Codex verdict**: handle it via the verdict-extraction discipline in 3d (read `$AUDIT_FILE` through the `[codex]`-stripping filter; keep distilled findings only).
|
|
283
|
+
c. **One-pass tracker flush (no round-trips).** Assemble the pre-flight sections **in-context** (they are all small) and fill them with **back-to-back `Edit`s and no intervening reads**. The win is killing the old read-modify-read-modify churn (~5 incremental edits), **not** the literal tool-call count. **Do NOT `Write`-overwrite the whole file from in-context memory**: Phase 0 already wrote `Main repo:` / `Trunk branch:` / `Metrics dir:` into `## Worktree` and the `Status`/divergence lines into `## Phase 0`, and after a barrier compaction you may no longer hold those in-context (`$MAIN` "does not survive context compaction" — § Phase 0 step 1) — an overwrite-from-memory would silently drop them and HALT later with "`$MAIN` absent from tracker". Surgical `Edit`s on the placeholder sections leave Phase 0's content intact. Sections filled here:
|
|
284
|
+
- `## File Ownership Map` (3b).
|
|
285
|
+
- `## Worktree` — path / branch / slug / port, plus `Created:` = **the subagent block's `created_at`** (worktree-creation time, NOT resume time, so Phase 8's `cycle_time_mins` still spans the build window). On the **4a2 resume** path, `Created:` = the registry entry's `createdAt`; on the **4d inline fallback**, stamp `date -u +%Y-%m-%dT%H:%M:%SZ` at creation. (Never leave `Created:` empty — `cycle_time_mins` anchors on it.)
|
|
286
|
+
- `## Cross-Card Conflicts (Codex)` — distilled findings (the 3d skip-decision already wrote the `SKIPPED`/`RUN — reason` line; append the distilled findings on the RUN path, nothing to add on SKIP).
|
|
287
|
+
- In team mode: `## Team Mode` + `## Parallel Groups` (per team-mode.md).
|
|
288
|
+
`## Execution Mode` was already written at step 3c (it must exist before the Task spine) — do NOT rewrite it here. **Rationale**: pre-flight is idempotent and cheap to redo (step 4a2's git pre-check guards worktree re-creation), so the data sections do not need mid-flight persistence; per-phase incremental writes resume for card execution, where mid-phase recovery actually matters. The file already exists (the skeleton was created at batch start per § Context Tracking; Phase 0 wrote `## Phase 0`) — backfill, do NOT re-create.
|
|
289
|
+
d. **→ Visibility**: mark the `Pre-flight` Task spine entry → `completed` and emit the first wave's Progress Bar.
|
|
248
290
|
|
|
249
291
|
---
|
|
@@ -15,10 +15,10 @@ It does NOT accumulate implementation details, codebase-architect findings, or r
|
|
|
15
15
|
|
|
16
16
|
### Team Mode Pre-flight
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
The standard pre-flight (setup.md Phase 0 + steps 1-6) runs unchanged; add:
|
|
19
19
|
|
|
20
|
-
1. Read the `execution_strategy.groups` (each with `level` + `cards`) and sort into execution layers by `level`. For legacy cards lacking the block, fall back to the on-the-fly topological-layer computation from step 3c.
|
|
21
|
-
2.
|
|
20
|
+
1. Read the `execution_strategy.groups` (each with `level` + `cards`) and sort into execution layers by `level`. For legacy cards lacking the block, fall back to the on-the-fly topological-layer computation from step 3c. This is resolved **before** launching the background ops (setup.md step 4), so the wave layout is in-context for the consolidated flush.
|
|
21
|
+
2. **Fold the team-mode sections into the single consolidated pre-flight write** (setup.md step 6c — do NOT add a separate Edit). The same one-shot flush that writes the ownership map / mode / worktree / cross-card sections also writes:
|
|
22
22
|
```
|
|
23
23
|
## Team Mode
|
|
24
24
|
Status: active
|
|
@@ -173,13 +173,13 @@ After ALL agents in the group complete successfully:
|
|
|
173
173
|
3a. **D.3a — Phase 2.5b AC-Closure Gate (per-card, BLOCKING — non-skippable)** — For EACH card in the group, **sequentially**, invoke the full Phase 2.5b gate as documented in `### Phase 2.5b — AC-Closure Gate (BLOCKING — Scope Closure Discipline)`. This includes: build the AC Closure Ledger from the card YAML, run the rationalization scan, invoke `AskUserQuestion` one-per-deferred-AC, run the `implementation_notes` deferral audit, and persist the ledger in the tracker. Until EVERY card in the group exits PASS, do NOT proceed to D.3b. Cards exiting with `not_implemented` ACs that the user routes to "Implementa adesso" must finish their fix-coder loop and re-pass the gate before D.3b starts for the next card. Log under `## AC Closure Ledger — <CARD-ID>` per card.
|
|
174
174
|
|
|
175
175
|
3b. **D.3b — Phase 2.55 Simplify (per-card, FANNED OUT across the group)** — The Simplify agents are **read-only analysis on file-disjoint per-card diffs** (the orchestrator applies the fixes afterward), so there is NO reason to run them one card at a time. **Spawn the per-card Simplify analysis for ALL eligible cards in PARALLEL** — in a SINGLE message, fire each card's Phase 2.55 trio (Reuse / Quality / Efficiency) against that card's diff captured to `/tmp/diff-<CARD-ID>.txt` (per Phase 2.55 step 2 — pass each trio the **path**, scoped to the card's File Ownership Map; never inline the diff). Per-card (not group-aggregate) so findings stay attributable. When all analyses return, **apply fixes per card** (file-disjoint → no write conflict), then re-run `npm run lint` and `npx tsc --noEmit` on the worktree ONCE for the whole group (redirect to disk per § "Context economy"). (Concurrency is capped by the platform; passing N cards is safe — excess agents queue.)
|
|
176
|
-
- **Gate (enumerated, `
|
|
176
|
+
- **Gate (enumerated, `TRIVIAL_CARDS`-driven)**: SKIP D.3b for a card in **`TRIVIAL_CARDS`** (the set already computed at D.1.5 — `review_profile == skip` AND 0 Step-A triggers AND **non-source diff**), aligning team mode with sequential Phase 2.55's `IS_TRIVIAL` re-confirmation on the ACTUAL diff and with team-mode's own D.1.5 SSOT. A trivial card has no substantive diff to simplify, and Simplify is quality-only (no merge-gate coverage to lose). Log `simplify: SKIPPED (trivial — non-source diff)`. **A card with `review_profile == skip` whose committed diff DID touch a source file is NOT in `TRIVIAL_CARDS` → run D.3b for it** (exactly as sequential 2.55 does — `skip` is the floor, the real diff is the deciding check). For `light`/`balanced`/`deep` cards D.3b runs unchanged. This is the ONLY enumerated skip — never skip D.3b "for time" on a non-trivial card. (Skipped cards are simply omitted from the parallel fan-out.)
|
|
177
177
|
|
|
178
178
|
3c. **D.3c — Phase 2.6 E2E-Review (per-card)** — First, evaluate the existing Gate table for EVERY card at once (skip when `features.has_e2e_review: false`, backend-only diff per the diff predicate documented in Phase 2.6, or card type in the Phase 2.6 skip set — `backend`/`api`/`db`/`infra`/`docs`/`chore`/`config`). In practice most cards in a group skip this gate (backend/db/api), so the eligible set is usually 0–1. For the cards that PASS the gate, invoke `/e2e-review` in programmatic mode with that card's payload. Each `/e2e-review` keeps its own isolated state dir (`.baldart/e2e-review/<CARD-ID>/`), so multiple runs do not clobber each other's artifacts.
|
|
179
179
|
- **Parallel-when-safe**: if **two or more** cards pass the gate, you MAY fan them out in parallel ONLY when they hit **disjoint routes/pages** — the genuinely shared resource is the worktree's single dev-server port, and concurrent Playwright sessions against one server are fine for disjoint routes. If the eligible cards touch overlapping routes (or `/e2e-review` spins its own server and a port clash is possible), run those **sequentially** to avoid a flaky cross-test. Default to parallel for the common disjoint case; fall back to sequential on any contention.
|
|
180
180
|
- BLOCKING per-card: if `/e2e-review` returns `"blocked"` or `"error"`, surface to the user via the same `AskUserQuestion` documented in Phase 2.6 — do NOT proceed to D.4 with an unresolved card. Skips are logged with the documented gate reason, never with `"time budget"` or similar.
|
|
181
181
|
|
|
182
|
-
4. **D.4 — QA gate (group; since v4.7.0 — runs only for `deep` / risk-escalation, else deferred to Final)** — Read each card's `review_profile` field and the D.1.5 Step-A trigger result. **Run the group qa-sentinel (once, at FULL) iff** the group's MAX profile is `deep` **OR** any card in the group had a Step-A risk escalation. **Otherwise (max profile ≤ `balanced`, no escalation) → DEFER the group QA to the Final Review F.3 qa-sentinel** (FULL suite + build + audit over the entire batch — the unconditional merge gate); log `D.4 QA: DEFERRED to Final FULL gate (group max=balanced, no risk escalation)`. This mirrors sequential step 21b. When it DOES run, invoke qa-sentinel at FULL (the combined group diff must be validated together) using the same prompt contract as Phase 3.5 step 22. ⚠️ A balanced-only group runs its first suite at the Final gate; merge safety is preserved because Final is FULL over the whole batch.
|
|
182
|
+
4. **D.4 — QA gate (group; since v4.7.0 — runs only for `deep` / risk-escalation, else deferred to Final)** — Read each card's `review_profile` field and the D.1.5 Step-A trigger result. **Run the group qa-sentinel (once, at FULL) iff** the group's MAX profile is `deep` **OR** any card in the group had a Step-A risk escalation. **Otherwise (max profile ≤ `balanced`, no escalation) → DEFER the group QA to the Final Review F.3 qa-sentinel** (FULL suite + build + audit over the entire batch — the unconditional merge gate); log `D.4 QA: DEFERRED to Final FULL gate (group max=balanced, no risk escalation)`. This mirrors sequential step 21b. When it DOES run, invoke qa-sentinel at FULL (the combined group diff must be validated together) using the same prompt contract as Phase 3.5 step 22. **Granularity (INTENTIONAL — not a drift)**: the predicate is identical to sequential 21b (`deep`/risk-escalation → FULL, else defer to the Final FULL gate), but it is evaluated **per-GROUP** here whereas sequential evaluates it per-CARD. This is by design — qa-sentinel runs once over the group's combined diff (the wave-batched model gives it no per-card granularity), so the gate is deliberately the more conservative side: a single `deep`/risk card escalates the WHOLE group to FULL rather than just itself. No correctness gap — every card still reaches a FULL suite no later than the unconditional Final gate. ⚠️ A balanced-only group runs its first suite at the Final gate; merge safety is preserved because Final is FULL over the whole batch.
|
|
183
183
|
|
|
184
184
|
4a. **D.4a — Per-card doc gate (consumes D.2, since v3.35.0; doc-reviewer-applied since v3.40.0)** — Do NOT re-run the doc AUDIT (D.2 already produced per-card-attributed findings). If any card in the group has doc findings, invoke the **doc-reviewer once in write mode** over the group, passing the per-card-attributed findings from D.2, to APPLY all doc fixes in a single pass (it is now alone — code-reviewer is done — so the D.2 parallel-safety constraint no longer applies). Do **NOT** spawn a fix-coder for doc findings: `doc` is owned by `doc-reviewer` (see "Domain-Override Domains"); a code-oriented coder lacks the doc-invariant contract. The only exception is a doc-drift→bug finding rooted in CODE — that follows the D.4b code fix path. (Previously D.4a spawned a fix-coder per card; the audit was already collapsed to a single attributed D.2 pass. D.4b's per-card `/codexreview` also skips its doc-reviewer via the lean contract, so the doc AUDIT runs once per group while the doc FIXES run once per group via doc-reviewer.) **Telemetry** — append one row per applied doc finding to `## Fix Application Log`: `D.4a | doc | est_lines=<n> | decision=doc-reviewer | applied_by=doc-reviewer | card=<ID> | finding=<1-line>`. **Phase-8 producer (named counter)** — ALSO record per card the `doc_gaps: found=<N> fixed=<M>` line in that card's `## Completed Cards` entry (same named counter as sequential Phase 3 step 15), so Phase 8 reads `doc_gaps_found`/`doc_gaps_fixed` from a structured field, not a free-form row.
|
|
185
185
|
|