Files
msd-core/gsd-core/references/execute-phase-between-wave-reset.md
Tom Boucher f5276b36b3 fix(#1369): refresh wave manifest and re-check base before each wave in execute-phase (#1492)
* fix(#1369): refresh wave manifest and re-check base before each wave in execute-phase

Two compounding issues caused wave N+1 worktrees to fork from the stale
pre-wave-N commit, immediately tripping the worktree_branch_check FATAL
guard in every executor:

1. worktree.base-check auto-degrade only ran once at initialize time.
   After wave N merges advanced orchestrator HEAD past origin/HEAD, new
   worktrees were still forked from origin/HEAD (Claude Code "fresh" base).

2. WAVE_WORKTREE_MANIFEST was never unset between waves, so wave N+1
   reused the consumed wave-N manifest file, which would have blocked the
   step 5.5 manifest guard (#3384) on subsequent waves.

Fix: add two safeguards in execute-phase.md —
- Step 0.5 (start of each wave): re-runs worktree.base-check; auto-degrades
  USE_WORKTREES=false for that wave when HEAD has diverged from origin/HEAD.
- Step 7c (end of each wave): unsets WAVE_WORKTREE_MANIFEST so wave N+1
  creates a fresh per-wave manifest; re-asserts worktree.set-baseref
  (idempotent) and re-evaluates base degradation after wave merges land.

17 regression tests added in tests/bug-1369-wave-stale-base.test.cjs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(#1369): rename test to fix-NNN convention; update workflow size baseline

Rename tests/bug-1369-wave-stale-base.test.cjs → tests/fix-1369-wave-stale-base.test.cjs
to satisfy the lint-regression-test-names gate (new files cannot use bug-NNN prefix).

Update tests/workflow-size-baseline.json for execute-phase.md: 93157 → 97393
(LF-normalized byte count after adding step 0.5 inter-wave base re-check and
step 7c between-wave manifest reset).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(#1369): add issue reference to allow-test-rule comment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(#1369): extract new execute-phase steps to references; satisfy ADR-857 cap

Step 0.5 (inter-wave worktree base re-check) and steps 7b–7c (pre-wave
dependency check + between-wave manifest reset/base refresh) added by this
PR grew execute-phase.md to 97393 bytes, violating the ADR-857 phase-6
architectural mandate that host-loop bodies remain strictly below the
pre-phase-6 baseline of 93166 bytes.

Extract both new blocks into dedicated reference files:
- gsd-core/references/execute-phase-wave-guard.md (step 0.5)
- gsd-core/references/execute-phase-between-wave-reset.md (steps 7b + 7c)

Replace inline prose with @-reference pointers. File now measures 92851
bytes (LF-normalized), satisfying the ADR-857 capstone conformance gate.

Also update tests/workflow-size-baseline.json to 92851 and add both new
reference files to docs/INVENTORY-MANIFEST.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(#1369): update regression tests to read from extracted reference files

Steps 0.5 and 7b+7c were moved to reference files to satisfy the ADR-857
size cap on execute-phase.md. Tests now check @-reference pointers in the
workflow for ordering and read content assertions from the reference files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 14:22:59 -04:00

2.6 KiB

7b. Pre-wave dependency check (waves 2+ only): Before wave N+1, run gsd-tools.cjs query verify.key-links {phase_dir}/{plan}-PLAN.md for each upcoming plan. If any PRIOR-wave artifact link fails, present: - ## Cross-Plan Wiring Gap with plan/link/from/pattern rows - Options: investigate+fix before continue, or continue with cascade risk Skip key-links that reference files in the CURRENT (upcoming) wave.

7c. Between-wave manifest reset and worktree base refresh (waves 2+ only — #1369):

REQUIRED before each wave transition when USE_WORKTREES != "false" and RUNTIME = "claude".

Wave N's WAVE_WORKTREE_MANIFEST was consumed by worktree.cleanup-wave in step 5.5. It must be unset so wave N+1's step 3 creates a fresh manifest for the new wave's worktrees. Without this, the wave N+1 manifest guard (step 5.5, #3384) blocks on the stale/empty consumed file.

After wave N merges and tracking commits, the orchestrator HEAD has advanced past the commit the Claude Code harness may have cached as the worktree fork base at session start. New worktrees spawned for wave N+1 could fork from the stale pre-wave-N HEAD, causing every executor to trip the worktree_branch_check FATAL guard immediately (symptom: HEAD is <old-sha>, expected <new-sha>).

# Unset per-wave manifest so wave N+1 creates a fresh one (#3384, #1369).
unset WAVE_WORKTREE_MANIFEST

# Between-wave base refresh (#1369): after wave N merges and tracking commits, HEAD has
# advanced. Re-assert worktree.baseRef:"head" (idempotent — no-op if already set) so the
# Claude Code harness re-reads the live HEAD on the next Agent(isolation="worktree") call
# rather than using a cached session-start commit as the fork base.
if [ "$RUNTIME" = "claude" ] && [ "$USE_WORKTREES" != "false" ]; then
  gsd_run query worktree.set-baseref 2>/dev/null || true

  # Safety re-check: evaluate degradation AFTER the wave N commits. If HEAD has diverged
  # from origin/HEAD and baseRef is NOT "head", degrade remaining waves to sequential to
  # avoid the base-mismatch FATAL in executor agents.
  _BETWEEN_DEGRADE=$(gsd_run query worktree.base-check --pick shouldDegrade 2>/dev/null || echo "false")
  if [ "$_BETWEEN_DEGRADE" = "true" ]; then
    _DEGRADE_MSG=$(gsd_run query worktree.base-check --pick message 2>/dev/null || true)
    [ -n "$_DEGRADE_MSG" ] && printf '%s\n' "$_DEGRADE_MSG" >&2
    printf 'Degrading to sequential mode for remaining waves: HEAD advanced past worktree fork base after wave %s merge (#1369).\n' "${N}" >&2
    USE_WORKTREES=false
  fi
fi