baldart 4.53.6 → 4.53.7

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,14 @@ 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.53.7] - 2026-06-19
9
+
10
+ **`setup-worktree.sh` no longer turns an empty `toolchain.commands.build` into a spurious `baseline: fail`.** Observed on a real `/new FEAT-0037` run in a consumer (`mayo`) whose `baldart.config.yml` declares `build: ''` (single-quoted empty scalar — the project's build is not a separate toolchain gate; per `toolchain-protocol.md` an empty command must fall back to the default `npm run build`). The deterministic SSOT worktree script (v4.53.0) read that value with a sed that stripped only DOUBLE quotes (`\"?([^\"#]*)\"?`), so `build: ''` came through as the **literal 2-char string `''`** — non-empty — so the `[ -n "$TC_BUILD" ]` fallback never fired and the script ran `bash -c "''"`, an empty *quoted* command → `bash: : command not found` (exit 127) → `baseline: fail`. tsc + biome had actually passed and the worktree was green on disk; the failure was entirely the unresolved empty scalar. Fix: (1) `_tc()` now resolves a YAML scalar to its true value — `build:`, `build: ''`, `build: ""`, `build: ~`, `build: null` all collapse to empty so the default fallback fires (strips one layer of matching single OR double quotes + YAML null markers + inline `# comment`); (2) the script now tracks build provenance and implements the protocol's **SKIP tier** — the *fallback* `npm run build` on a project with no `build` npm script is a no-build library → SKIP (baseline stays pass), never a spurious fail, while a *configured* (non-empty) build command is always run as a real gate. Verified by executing the resolver against every empty-scalar form + real values, the fallback/SKIP decision on a has-build vs no-build `package.json`, and reproducing the exact `bash: : command not found` exit-127 from the old sed. The prose inline fallbacks (`setup.md`, `worktree-manager/SKILL.md`, `new2.js`) are model-driven and never had the sed bug — no parallel fix needed. **PATCH** (deterministic-script bugfix; correctly-configured consumers see no behaviour change; no new agent/skill/command/config key, no install change).
11
+
12
+ ### Fixed
13
+
14
+ - **`framework/.claude/skills/worktree-manager/scripts/setup-worktree.sh`** — `_tc()` rewritten to dequote single/double quotes + treat `~`/`null` as empty (was stripping double quotes only, so `build: ''` resolved to the literal `''` and skipped the fallback → `bash -c "''"` → `bash: : command not found` → spurious `baseline: fail`). Build resolution now records `BUILD_FROM_CONFIG` and the baseline build step adds the toolchain-protocol SKIP tier: the fallback `npm run build` on a no-`build`-script project is SKIPPED (baseline pass), not failed; a configured command is always a real gate.
15
+
8
16
  ## [4.53.6] - 2026-06-18
9
17
 
10
18
  **`/new` now caps concurrency at 3 agents per wave — the API rate-limit guardrail, end to end.** Follow-up to the v4.53.5 root-cause finding (parallel coders killed by org-level rate-limiting): the org rate limit is SHARED across every terminal/session on the account, so a wide fan-out saturates the shared pool and the server throttles, killing agents mid-work and forcing full re-spawns (paying twice). Fix puts a hard ceiling of **3 concurrent agents** at every fan-out point in a `/new` epic: (1) `prd-card-writer` caps each `execution_strategy.groups[]` at ≤3 cards — a wider topological layer is split into sequential sub-groups of ≤3 (always safe: same-layer cards are independent by construction, so serializing them is correctness-neutral; the per-card `parallel_group` keeps its true logical layer, only the execution schedule is capped), so the **plan/cards reflect the rule**; (2) team-mode runtime never spawns more than 3 coders per wave and sub-batches a wider group sequentially (protects legacy epics + manual runs — the **guarantee**); (3) the per-wave and final review workflows cap their finder/verify fan-out at 3 via a rolling worker pool (not chunked barriers — those would block fast finders behind the slow background Codex poll). The cap is **3** (the user's choice — prefer never clogging over re-paying), a fixed operational guardrail like the existing retry caps (NOT a `baldart.config.yml` key). Honest limits: BALDART cannot see agents in OTHER terminals — the cap bounds one run; total cross-terminal parallelism is still the user's to manage. `new2` inherits the prd-card-writer group cap (same cards) and the final-review cap (shared workflow); its own per-card scheduling is not separately capped here (follow-up if it sees use). **PATCH** (operational guardrail on existing orchestration; no new agent/skill/command/config key, no install change).
package/VERSION CHANGED
@@ -1 +1 @@
1
- 4.53.6
1
+ 4.53.7
@@ -193,16 +193,36 @@ ENV_FILES=("${_clean[@]:-}")
193
193
  [ -n "$BACKLOG_DIR" ] || { BACKLOG_DIR="$(config_scalar paths backlog_dir)"; [ -n "$BACKLOG_DIR" ] || BACKLOG_DIR="backlog"; }
194
194
  [ -n "$INSTALL_CMD" ] || INSTALL_CMD="npm install"
195
195
  # toolchain.commands.* only when features.has_toolchain: true; else the defaults.
196
+ # Resolves a YAML scalar to its TRUE value: an empty scalar written any of the
197
+ # legal ways — `build:`, `build: ''`, `build: ""`, `build: ~`, `build: null` —
198
+ # MUST collapse to the empty string so the caller falls back to the default.
199
+ # (The old single-line sed stripped only DOUBLE quotes, so `build: ''` came
200
+ # through as the literal 2-char string `''` → non-empty → no fallback →
201
+ # `bash -c "''"` → `bash: : command not found` → spurious `baseline: fail`.)
196
202
  _tc() {
197
- local cfg="$MAIN/baldart.config.yml"
203
+ local cfg="$MAIN/baldart.config.yml" raw
198
204
  grep -E '^[[:space:]]*has_toolchain:[[:space:]]*true' "$cfg" >/dev/null 2>&1 || return 0
199
- grep -A20 '^toolchain:' "$cfg" 2>/dev/null | grep -A15 '^[[:space:]]*commands:' \
205
+ raw="$(grep -A20 '^toolchain:' "$cfg" 2>/dev/null | grep -A15 '^[[:space:]]*commands:' \
200
206
  | grep -E "^[[:space:]]+$1:" | head -1 \
201
- | sed -E "s/.*$1:[[:space:]]*\"?([^\"#]*)\"?.*/\1/" | sed -E 's/[[:space:]]+$//'
207
+ | sed -E "s/^[[:space:]]*$1:[[:space:]]*//" \
208
+ | sed -E 's/[[:space:]]+#.*$//; s/[[:space:]]+$//')" # drop YAML inline comment (space + #) + trailing ws
209
+ # strip ONE layer of matching surrounding quotes (single or double) → '' / "" become empty
210
+ case "$raw" in
211
+ \"*\") raw="${raw#\"}"; raw="${raw%\"}" ;;
212
+ \'*\') raw="${raw#\'}"; raw="${raw%\'}" ;;
213
+ esac
214
+ # explicit YAML null markers → empty
215
+ case "$raw" in '~'|null|Null|NULL) raw="" ;; esac
216
+ printf '%s' "$raw"
202
217
  }
203
218
  [ -n "$TC_TC" ] || TC_TC="$(_tc typecheck)"; [ -n "$TC_TC" ] || TC_TC="npx tsc --noEmit"
204
219
  [ -n "$TC_LINT" ] || TC_LINT="$(_tc lint)"; [ -n "$TC_LINT" ] || TC_LINT="npx eslint --max-warnings=0 src/"
205
- [ -n "$TC_BUILD" ] || TC_BUILD="$(_tc build)"; [ -n "$TC_BUILD" ] || TC_BUILD="npm run build"
220
+ # Build provenance matters for the SKIP tier (toolchain-protocol.md): a CONFIGURED
221
+ # build that fails is a real gate failure; the FALLBACK default `npm run build` on
222
+ # a project with no `build` script is a no-build library → SKIP, never fail.
223
+ BUILD_FROM_CONFIG=1
224
+ [ -n "$TC_BUILD" ] || TC_BUILD="$(_tc build)"
225
+ [ -n "$TC_BUILD" ] || { TC_BUILD="npm run build"; BUILD_FROM_CONFIG=0; }
206
226
 
207
227
  # --- log sink --------------------------------------------------------------
208
228
  [ -n "$LOG" ] || LOG="/tmp/wt-setup-${SLUG}.log"
@@ -427,23 +447,35 @@ TIMEOUT_BIN=""
427
447
  command -v timeout >/dev/null 2>&1 && TIMEOUT_BIN="timeout"
428
448
  [ -z "$TIMEOUT_BIN" ] && command -v gtimeout >/dev/null 2>&1 && TIMEOUT_BIN="gtimeout"
429
449
 
430
- err "… baseline build ($TC_BUILD, timeout ${BUILD_TIMEOUT}s)"
431
- if [ -n "$TIMEOUT_BIN" ]; then
432
- CI=1 "$TIMEOUT_BIN" "$BUILD_TIMEOUT" bash -c "$TC_BUILD" </dev/null >>"$LOG" 2>&1
433
- BUILD_RC=$?
434
- else
435
- err "WARN: no 'timeout'/'gtimeout' binary running build WITHOUT a hard timeout."
436
- CI=1 bash -c "$TC_BUILD" </dev/null >>"$LOG" 2>&1
437
- BUILD_RC=$?
450
+ # SKIP tier (toolchain-protocol.md): the FALLBACK default `npm run build` is only
451
+ # a real gate when the project actually defines a `build` script. A library with
452
+ # none no-build project SKIP (baseline stays pass), never a spurious fail. A
453
+ # CONFIGURED build command is always run as-is (its failure IS a real failure).
454
+ RUN_BUILD=1
455
+ if [ "$BUILD_FROM_CONFIG" = 0 ] && [ -f package.json ]; then
456
+ node -e 'const s=(require("./package.json").scripts)||{};process.exit(s.build?0:1)' 2>/dev/null \
457
+ || { RUN_BUILD=0; err "… baseline build SKIPPED (no toolchain build command + no 'build' npm script → no-build project, per toolchain-protocol tier 3)"; }
438
458
  fi
439
459
 
440
- if [ "$BUILD_RC" -eq 124 ] && [ -n "$TIMEOUT_BIN" ]; then
441
- M_BASELINE="timeout"; M_BLOG="$LOG"
442
- # leave buildVerified:false in the registry (already provisional)
443
- fail "baseline build TIMED OUT after ${BUILD_TIMEOUT}s partial log at $LOG" 7
444
- elif [ "$BUILD_RC" -ne 0 ]; then
445
- M_BASELINE="fail"; M_BLOG="$LOG"
446
- fail "baseline build FAILED (do NOT fix here the coder repairs it) see $LOG" 7
460
+ if [ "$RUN_BUILD" = 1 ]; then
461
+ err "… baseline build ($TC_BUILD, timeout ${BUILD_TIMEOUT}s)"
462
+ if [ -n "$TIMEOUT_BIN" ]; then
463
+ CI=1 "$TIMEOUT_BIN" "$BUILD_TIMEOUT" bash -c "$TC_BUILD" </dev/null >>"$LOG" 2>&1
464
+ BUILD_RC=$?
465
+ else
466
+ err "WARN: no 'timeout'/'gtimeout' binaryrunning build WITHOUT a hard timeout."
467
+ CI=1 bash -c "$TC_BUILD" </dev/null >>"$LOG" 2>&1
468
+ BUILD_RC=$?
469
+ fi
470
+
471
+ if [ "$BUILD_RC" -eq 124 ] && [ -n "$TIMEOUT_BIN" ]; then
472
+ M_BASELINE="timeout"; M_BLOG="$LOG"
473
+ # leave buildVerified:false in the registry (already provisional)
474
+ fail "baseline build TIMED OUT after ${BUILD_TIMEOUT}s — partial log at $LOG" 7
475
+ elif [ "$BUILD_RC" -ne 0 ]; then
476
+ M_BASELINE="fail"; M_BLOG="$LOG"
477
+ fail "baseline build FAILED (do NOT fix here — the coder repairs it) — see $LOG" 7
478
+ fi
447
479
  fi
448
480
 
449
481
  # 10. Build passed → flip buildVerified:true in the registry and finish clean.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baldart",
3
- "version": "4.53.6",
3
+ "version": "4.53.7",
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"