fix(#2474): gate worktree dispatch on project-level USE_WORKTREES too (#2561)

* test(#2474): update dispatch gate test for dual-gate behavior

The #2772 test asserted the gate reads USE_WORKTREES_FOR_PLAN only.
Update to accept the dual-gate (USE_WORKTREES + USE_WORKTREES_FOR_PLAN).

* fix(#2474): gate worktree dispatch on project-level USE_WORKTREES too

The per-plan dispatch condition checked only USE_WORKTREES_FOR_PLAN
(submodule-derived), ignoring the project-level USE_WORKTREES flag.
Add USE_WORKTREES to the gate. Net-negative edit: compress two
nearby prose lines to offset the added shell condition (93353 bytes,
down from 93368).

Closes #2474

* docs(#2474): backfill changeset PR number (2561)

* fix: merge coverage gate into single-process check (#2474)

The test:coverage:unit script chained two c8 invocations with &&:
the first ran tests and wrote coverage data to .nyc_output/, the
second read that data for per-file branch checks. On fast CI runners
(ubuntu/24), the second process started before the filesystem flushed
the first process's writes — a classic TOCTOU race that caused
intermittent coverage gate failures.

Replace the two-process chain with a single c8 invocation that
generates both text and json-summary reports, followed by a Node
script (scripts/check-coverage-gate.cjs) that reads the JSON summary
once and checks both overall and per-file thresholds. No filesystem
race is possible because the JSON report is fully written before the
check script reads it.
This commit is contained in:
Tom Boucher
2026-07-23 09:14:02 -04:00
committed by GitHub
parent ae8526cd50
commit 7d298d6d4d
25 changed files with 83 additions and 27 deletions

View File

@@ -557,7 +557,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
Read and execute `gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md` for each plan. It extracts `PLAN_FILES` from the plan's JSON, intersects against `SUBMODULE_PATHS` (with normalization, bidirectional matching, and glob-prefix handling), and sets `USE_WORKTREES_FOR_PLAN` to `false` when the plan touches a submodule path. Append `plan_id` to a `WAVE_WORKTREE_PLANS` accumulator when `USE_WORKTREES_FOR_PLAN != false`.
The dispatch branches in step 3 below MUST gate on `USE_WORKTREES_FOR_PLAN` for the current plan, not on the project-level `USE_WORKTREES`.
The dispatch branches in step 3 gate on both `USE_WORKTREES` and `USE_WORKTREES_FOR_PLAN` (#2474).
2.75. **Execute:wave:pre capability dispatch:**
@@ -578,14 +578,14 @@ increases monotonically across waves. `{status}` is `complete` (success),
For 200k models, this keeps orchestrator context lean (~10-15%).
For 1M+ models (Opus 4.6, Sonnet 4.6), richer context can be passed directly.
**Worktree mode** (`USE_WORKTREES_FOR_PLAN` is not `false` — evaluated per-plan in step 2.5):
**Worktree mode** (`USE_WORKTREES` and `USE_WORKTREES_FOR_PLAN` not `false`):
Before spawning, capture the current HEAD:
```bash
EXPECTED_BASE=$(git rev-parse HEAD)
DISPATCH_TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
EXPECTED_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "${USE_WORKTREES_FOR_PLAN:-true}" != "false" ] && [ -z "${WAVE_WORKTREE_MANIFEST:-}" ]; then
if [ "${USE_WORKTREES:-true}" != "false" ] && [ "${USE_WORKTREES_FOR_PLAN:-true}" != "false" ] && [ -z "${WAVE_WORKTREE_MANIFEST:-}" ]; then
M=$(mktemp "${TMPDIR:-/tmp}/gsd-worktree-wave-XXXXXX") && mv "$M" "$M.json" && WAVE_WORKTREE_MANIFEST="$M.json" || exit 1 # XXXXXX must be path-final on BSD/macOS (#1520)
# Persist the dispatch-time orchestrator worktree root so wave-cleanup can pin back to the
# orchestrator's OWN worktree — NOT `git worktree list`'s first entry (always the main