baldart 5.2.0 → 5.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,44 @@ 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.2.1] - 2026-07-03
9
+
10
+ **`/mw` local-trunk sync robustness.** The worktree merge's local-trunk sync
11
+ (step 4c "Common", both `pr` and `local-push` strategies) failed to
12
+ fast-forward on the majority of real checkouts, needlessly leaving
13
+ `SYNC-DEFERRED` / `SYNC-NEEDS-DECISION`. Two targeted fixes, kept single-sourced
14
+ across the executed SSOT (`framework/.claude/skills/worktree-manager/scripts/merge-worktree.sh`)
15
+ and the prose (`worktree-manager/SKILL.md` step 4c) — **without `git stash`**,
16
+ which stays forbidden here because `refs/stash` is shared across all worktrees
17
+ via `git.commondir` (the FEAT-0522 incident): a stash from the main checkout can
18
+ pop into the wrong worktree, and two parallel `/mw` runs race on the shared
19
+ stash list.
20
+
21
+ - **Fix 1 — safe ref-advance when main is on another branch.** Previously, if
22
+ the main repo's HEAD was not on `$TRUNK`, sync did a fetch-only and always
23
+ emitted `SYNC-DEFERRED`, never advancing the local `$TRUNK` ref. Now it
24
+ fast-forwards `refs/heads/$TRUNK` via a ref-only, ff-only fetch
25
+ (`git fetch origin $TRUNK:$TRUNK`) that **never touches any working tree** and
26
+ never checks out — turning a large class of deferrals into a clean sync
27
+ (`sync_marker: none`). If `$TRUNK` is checked out in another worktree, git
28
+ refuses and it falls back to fetch-only + defer.
29
+ - **Fix 2 — accurate ff-fail disambiguation.** When the ff failed with a
30
+ tracked-clean tree and no owned/foreign dirt, the code fell to a misleading
31
+ "clean (diverged?)" marker (the dirty scan uses `--untracked-files=no`, so an
32
+ untracked-file collision was invisible to it). Now it disambiguates via
33
+ `merge-base --is-ancestor` between a **genuine branch divergence** (needs a
34
+ rebase/merge decision) and an **untracked-file collision** (the blocking files
35
+ are enumerated), emitting the correct actionable marker.
36
+
37
+ Behaviour is strictly safer: cases #2 (foreign uncommitted work) and #3 (real
38
+ divergence) still defer to ONE explicit user gate — never auto-committed, never
39
+ stashed — which is the correct behaviour on a shared checkout.
40
+
41
+ **Codex parity: portable.** The change is pure git plumbing inside the
42
+ dual-runtime `merge-worktree.sh` (executed identically under Claude and Codex)
43
+ plus its prose twin; no runtime-specific mechanic, no config key. The
44
+ schema-change propagation rule does not apply (no `baldart.config.yml` key).
45
+
8
46
  ## [5.2.0] - 2026-07-03
9
47
 
10
48
  **The local design studio.** `/ui-design` is refounded from the root as the
package/VERSION CHANGED
@@ -1 +1 @@
1
- 5.2.0
1
+ 5.2.1
@@ -2,6 +2,25 @@
2
2
 
3
3
  Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
4
4
 
5
+ ## 1.1.0 — 2026-07-03
6
+
7
+ ### Fixed — local-trunk sync robustness (step 4c "Common", both strategies)
8
+
9
+ Il sync del trunk locale falliva l'ff nella maggior parte dei checkout reali,
10
+ lasciando `SYNC-DEFERRED` / `SYNC-NEEDS-DECISION` inutilmente. Due fix mirati,
11
+ **senza `git stash`** (vietato — `refs/stash` è condiviso tra worktree, incidente
12
+ FEAT-0522). SSOT script `scripts/merge-worktree.sh` + prose SKILL.md tenuti in sync.
13
+
14
+ - **Fix 1** — quando il main è su un branch ≠ `$TRUNK`, avanza il *ref* locale
15
+ `refs/heads/$TRUNK` con un fetch ref-only ff-only (`git fetch origin $TRUNK:$TRUNK`),
16
+ **senza toccare il working tree** e senza checkout. Converte una grossa fetta di
17
+ `SYNC-DEFERRED` in sync pulito (`sync_marker: none`). Se `$TRUNK` è checked out in
18
+ un altro worktree git rifiuta → fallback al fetch-only + defer.
19
+ - **Fix 2** — quando l'ff fallisce con tree tracked-clean e nessun file owned/foreign,
20
+ disambigua via `merge-base --is-ancestor` tra **divergenza reale** del branch (serve
21
+ rebase/merge) e **collisione con file untracked** (elencati) — prima riportava sempre
22
+ il fuorviante "clean (diverged?)" (lo scan usa `--untracked-files=no`).
23
+
5
24
  ## 1.0.0 — 2026-07-01
6
25
 
7
26
  - Baseline: versioning per-skill introdotto al framework v4.82.0.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: worktree-manager
3
3
  effort: medium
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  description: >
6
6
  Manage fully independent git worktrees for parallel coding agents.
7
7
  Commands: /nw (new worktree) creates an isolated workspace with its own
@@ -1168,16 +1168,37 @@ if [ "$CURRENT_BRANCH" = "$TRUNK" ]; then
1168
1168
  echo "[SYNC-NEEDS-DECISION] framework-managed reconcile rebase conflict on $TRUNK — orchestrator MUST raise ONE explicit user gate."
1169
1169
  fi
1170
1170
  else
1171
- echo "[SYNC-NEEDS-DECISION] main repo $TRUNK cannot fast-forward and the working tree is clean (diverged?) orchestrator MUST raise ONE explicit user gate."
1171
+ # Fix 2 tracked tree clean, nothing owned/foreign dirty, yet ff failed.
1172
+ # Disambiguate a genuine branch divergence from an untracked-file collision the
1173
+ # incoming ff would overwrite (origin/$TRUNK is current — the pull fetched it).
1174
+ # NEVER stash to clear it (refs/stash is shared across worktrees — FEAT-0522).
1175
+ if git -C "$MAIN" merge-base --is-ancestor "$TRUNK" "origin/$TRUNK" 2>/dev/null; then
1176
+ COLLIDE=""
1177
+ for f in $(git -C "$MAIN" ls-files --others --exclude-standard); do
1178
+ git -C "$MAIN" cat-file -e "origin/$TRUNK:$f" 2>/dev/null && COLLIDE="$COLLIDE $f"
1179
+ done
1180
+ echo "[SYNC-NEEDS-DECISION] main repo $TRUNK is fast-forwardable but untracked file(s) block the merge:${COLLIDE:- (unknown)} — orchestrator MUST raise ONE explicit user gate."
1181
+ else
1182
+ echo "[SYNC-NEEDS-DECISION] main repo $TRUNK has diverged from origin/$TRUNK (local commits not on origin) — needs a rebase/merge decision; orchestrator MUST raise ONE explicit user gate."
1183
+ fi
1172
1184
  fi
1173
1185
  fi
1174
1186
  else
1175
- echo "ℹ️ Main repo HEAD is '$CURRENT_BRANCH' not switching. Next manual \`git pull\` on $TRUNK will sync."
1176
- git -C "$MAIN" fetch origin "$TRUNK" --quiet
1177
- # Structured marker for upstream orchestrators (e.g. /new Phase 6c).
1178
- # `/mw` standalone keeps fetch-only behavior (terminal isolation); orchestrators
1179
- # parse this marker and route reconciliation through an explicit user gate.
1180
- echo "[SYNC-DEFERRED] main repo HEAD=${CURRENT_BRANCH}, local $TRUNK not fast-forwarded — orchestrator workspace-hygiene phase must reconcile."
1187
+ # Fix 1 main is on another branch: do NOT checkout $TRUNK. Fast-forward the local
1188
+ # $TRUNK *ref* without touching any working tree via a ref-only, ff-only fetch.
1189
+ # `git fetch origin $TRUNK:$TRUNK` advances refs/heads/$TRUNK only on a fast-forward
1190
+ # and fails cleanly otherwise (never a checkout, never a stash). If $TRUNK is checked
1191
+ # out in another worktree git refuses we fall back to fetch-only + defer.
1192
+ if git -C "$MAIN" fetch origin "$TRUNK:$TRUNK" --quiet 2>/dev/null; then
1193
+ echo "✅ Local $TRUNK ref fast-forwarded to origin/$TRUNK (main HEAD='$CURRENT_BRANCH' untouched)."
1194
+ else
1195
+ echo "ℹ️ Main repo HEAD is '$CURRENT_BRANCH' — not switching. Next manual \`git pull\` on $TRUNK will sync."
1196
+ git -C "$MAIN" fetch origin "$TRUNK" --quiet
1197
+ # Structured marker for upstream orchestrators (e.g. /new Phase 6c).
1198
+ # `/mw` standalone keeps fetch-only behavior (terminal isolation); orchestrators
1199
+ # parse this marker and route reconciliation through an explicit user gate.
1200
+ echo "[SYNC-DEFERRED] main repo HEAD=${CURRENT_BRANCH}, local $TRUNK not fast-forwarded (diverged or checked out elsewhere) — orchestrator workspace-hygiene phase must reconcile."
1201
+ fi
1181
1202
  fi
1182
1203
  ```
1183
1204
 
@@ -492,12 +492,34 @@ if [ "$CURRENT_BRANCH" = "$TRUNK" ]; then
492
492
  M_SYNCMARK="SYNC-NEEDS-DECISION"; M_SYNCDETAIL="framework-managed reconcile rebase conflict on $TRUNK"
493
493
  fi
494
494
  else
495
- M_SYNCMARK="SYNC-NEEDS-DECISION"; M_SYNCDETAIL="main repo $TRUNK cannot fast-forward and the working tree is clean (diverged?)"
495
+ # Fix 2 tracked tree clean, nothing owned/foreign dirty, yet ff failed.
496
+ # Disambiguate a genuine branch divergence from an untracked-file collision
497
+ # the incoming ff would overwrite (origin/$TRUNK is current — pull fetched it).
498
+ # NEVER stash to clear it (refs/stash is shared across worktrees — FEAT-0522).
499
+ if git -C "$MAIN" merge-base --is-ancestor "$TRUNK" "origin/$TRUNK" 2>/dev/null; then
500
+ COLLIDE=""
501
+ for f in $(git -C "$MAIN" ls-files --others --exclude-standard 2>/dev/null); do
502
+ git -C "$MAIN" cat-file -e "origin/$TRUNK:$f" 2>/dev/null && COLLIDE="$COLLIDE $f"
503
+ done
504
+ M_SYNCMARK="SYNC-NEEDS-DECISION"; M_SYNCDETAIL="main repo $TRUNK is fast-forwardable but untracked file(s) block the merge:${COLLIDE:- (unknown)} — orchestrator MUST raise ONE explicit user gate"
505
+ else
506
+ M_SYNCMARK="SYNC-NEEDS-DECISION"; M_SYNCDETAIL="main repo $TRUNK has diverged from origin/$TRUNK (local commits not on origin) — needs a rebase/merge decision, orchestrator MUST raise ONE explicit user gate"
507
+ fi
496
508
  fi
497
509
  fi
498
510
  else
499
- git -C "$MAIN" fetch origin "$TRUNK" --quiet 2>>"$LOG" || true
500
- M_SYNCMARK="SYNC-DEFERRED"; M_SYNCDETAIL="main repo HEAD=${CURRENT_BRANCH}, local $TRUNK not fast-forwarded"
511
+ # Fix 1 main is on another branch: do NOT checkout $TRUNK. Fast-forward the local
512
+ # $TRUNK *ref* (refs/heads/$TRUNK) WITHOUT touching any working tree via a ref-only,
513
+ # ff-only fetch. `git fetch origin $TRUNK:$TRUNK` advances the local branch ref only
514
+ # on a fast-forward and fails cleanly (non-destructive) otherwise — never a checkout,
515
+ # never a stash. If $TRUNK is checked out in another worktree git refuses and we fall
516
+ # back to the deferred fetch below.
517
+ if git -C "$MAIN" fetch origin "$TRUNK:$TRUNK" --quiet 2>>"$LOG"; then
518
+ M_SYNCMARK="none"; M_SYNCDETAIL="local $TRUNK ref fast-forwarded to origin (main HEAD=${CURRENT_BRANCH}, working tree untouched)"
519
+ else
520
+ git -C "$MAIN" fetch origin "$TRUNK" --quiet 2>>"$LOG" || true
521
+ M_SYNCMARK="SYNC-DEFERRED"; M_SYNCDETAIL="main repo HEAD=${CURRENT_BRANCH}, local $TRUNK not fast-forwarded (diverged or checked out elsewhere)"
522
+ fi
501
523
  fi
502
524
 
503
525
  # 7. Cleanup worktree + registry (only after a verified land). Individual cmds.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baldart",
3
- "version": "5.2.0",
3
+ "version": "5.2.1",
4
4
  "description": "Claude Agent Framework - Reusable framework for coordinating AI agents and humans in software projects",
5
5
  "bin": {
6
6
  "baldart": "./bin/baldart.js"