fix: derive initial state from worktree when one exists (#654)

When auto-mode restarts after being stopped, the initial deriveState()
reads from the project root which has stale .gsd/ metadata. Completed
units appear incomplete, causing re-dispatch of finished work.

The auto-worktree (if it exists from the previous run) has the current
state. After the initial deriveState(base), check if an auto-worktree
exists for the active milestone and re-derive from there.

This is safe because:
- Only triggers when worktree isolation is enabled
- Only when not already inside a worktree
- Only when an auto-worktree actually exists for the milestone
- The worktree setup at lines 976+ still runs normally after

Fixes #654

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
deseltrus 2026-03-16 20:13:16 +01:00
parent 25eab8f368
commit 35f63f050a

View file

@ -824,6 +824,23 @@ export async function startAuto(
let state = await deriveState(base);
// ── Stale worktree state recovery (#654) ─────────────────────────────────
// When auto-mode was previously stopped and restarted, the project root's
// .gsd/ directory may have stale metadata (completed units showing as
// incomplete). If an auto-worktree exists for the active milestone, it has
// the current state — re-derive from there to avoid re-dispatching
// finished work.
if (
state.activeMilestone &&
shouldUseWorktreeIsolation() &&
!detectWorktreeName(base)
) {
const wtPath = getAutoWorktreePath(base, state.activeMilestone.id);
if (wtPath) {
state = await deriveState(wtPath);
}
}
// ── Milestone branch recovery (#601) ─────────────────────────────────────
// When auto-mode was previously stopped, the milestone branch is preserved
// but the worktree is removed. The project root (integration branch) may