#6471·gsd-2

fix(auto-resume): creation-failed swallowed in resume path — emits confusing 'Unhandled phase' guard-block when project root is on milestone branch

Author: Lazydayz137Created Jun 9, 2026Updated Jun 22, 2026

Problem

When a prior auto-mode session exits without merging (project root stays checked out on milestone/<MID>), the next /gsd auto invocation fails silently in the resume path and then emits a confusing non-actionable guard-block: "Unhandled phase 'executing' — run /gsd doctor to diagnose." instead of surfacing the real cause.

Root Cause

Two bugs compound:

Bug 1 — auto-start.js resume path silently ignores creation-failed

In the resume path (s.paused = true), enterMilestone failure handling only stops auto-mode for lease-conflict. All other failures (including creation-failed) are silently swallowed and execution continues with dispatchBasePath = project root:

javascript
// auto-start.js ~line 2035 (resume path)
if (!enterResult.ok && enterResult.reason === "lease-conflict") {
    ctx.ui.notify(`Cannot resume milestone...`);
    await stopAuto(ctx, pi, "lease-conflict during resume");
    return;
}
// ALL OTHER FAILURES fall through — rebuildScope still runs, orchestrator starts
rebuildScope(s.basePath, s.currentMilestoneId);

Compare the fresh-start path (auto-start.js ~line 932) which handles all non-ok reasons and calls releaseLockAndReturn().

Bug 2 — worktree-lifecycle.js error message mentions "another worktree" but the real conflict is the project root's main worktree

When milestone/M001 is checked out in the project root, git reports:

Branch "milestone/M001" is already in use by another worktree.

The "another worktree" is the main working tree itself — not a registered .gsd/worktrees/ entry. The error is accurate but lacks an actionable recovery hint. The user needs git checkout main (or their integration branch), not /worktree remove M001.

Expected Behavior

The resume path should mirror the fresh-start path's exhaustive error handling. When enterResult.reason === "creation-failed" and the error message contains "already in use", the engine should:

  1. Detect whether the project root's current branch matches milestone/<MID>
  2. Stop auto-mode with a clear message: "Project root is checked out on milestone/M001. Run git checkout main to recover, then re-run /gsd auto."

Minimal fix — in auto-start.js resume path, add parity with fresh-start path:

javascript
if (!enterResult.ok) {
    const isBranchInUse = enterResult.reason === "creation-failed"
        && String(enterResult.cause?.message ?? "").includes("already in use");
    if (isBranchInUse) {
        ctx.ui.notify(
            `Cannot resume: project root is checked out on milestone/${s.currentMilestoneId}. ` +
            `Run "git checkout main" then re-run /gsd auto.`,
            "error"
        );
    } else if (enterResult.reason === "lease-conflict") {
        ctx.ui.notify(`Cannot resume milestone ${s.currentMilestoneId}: lease held by another worker.`, "error");
    } else {
        ctx.ui.notify(`Cannot resume: worktree entry failed (${enterResult.reason}).`, "error");
    }
    await stopAuto(ctx, pi, `resume-worktree-failed: ${enterResult.reason}`);
    return;
}

Environment

  • GSD version: 3.0.0
  • Isolation mode: worktree
  • Active milestone: M001 / active slice: S05
  • Project root branch at failure: milestone/M001 (31 commits ahead of main, unmerged)

Reproduction Context

  1. Auto-mode runs tasks on milestone/M001 branch inside .gsd/worktrees/M001/
  2. Session exits without merge (e.g. OS sleep, SIGKILL, manual stop)
  3. Worktree directory is cleaned up but the project root remains on milestone/M001
  4. User runs /gsd auto — bootstrap enters resume path
  5. enterMilestone fails: Branch "milestone/M001" is already in use by another worktree
  6. Resume path swallows the error, orchestrator starts, dispatch fires resolveDispatch
  7. Guard-block emitted: "Unhandled phase 'executing' — run /gsd doctor to diagnose."
  8. Auto-mode stalls; user cannot restart without knowing to run git checkout main

Forensic Evidence

2026-06-09T08:22:23Z [worktree-create-failed] flow=d9232403
  error: "Branch \"milestone/M001\" is already in use by another worktree."
  fallback: "project-root"

2026-06-09T08:22:25Z [guard-block] flow=auto-orc
  reason: "Unhandled phase \"executing\" — run /gsd doctor to diagnose."

2026-06-09T08:23:23Z [worktree-orphaned] flow=73a43fce
  milestoneId: "M001", reason: "in-progress-unmerged"
  commitsAhead: 31, worktreeDirExists: false

Anomalies from forensics: 8 unmerged worktree exits, 1 worktree create failure, 2 guard-block events.


Auto-generated by /gsd forensics