fix: realign cwd before dispatch + clean stale merge state on failure (#1389) (#1400)

In worktree isolation, process.cwd() drifts when async_bash or background
jobs change directory, causing commits to land on the wrong branch.
Realign cwd to basePath before every dispatch and hook dispatch.

Also clean stale .git/SQUASH_MSG, MERGE_HEAD, MERGE_MSG after failed
squash-merges to prevent subsequent git operations from seeing phantom
merge state.

Adapted to post-M001 architecture: cwd fix in auto-loop.ts runUnit(),
hook cwd fix in auto.ts dispatchHookUnit(), merge cleanup in
worktree-resolver.ts _mergeWorktreeMode().

Co-authored-by: Lex Christopherson <lex@glittercowboy.com>
This commit is contained in:
Tom Boucher 2026-03-19 18:55:18 -04:00 committed by GitHub
parent c58bf42333
commit bc9cfb1992
3 changed files with 23 additions and 0 deletions

View file

@ -221,6 +221,15 @@ export async function runUnit(
s.pendingResolve = resolve;
});
// Ensure cwd matches basePath before dispatch (#1389).
// async_bash and background jobs can drift cwd away from the worktree.
// Realigning here prevents commits from landing on the wrong branch.
try {
if (process.cwd() !== s.basePath) {
process.chdir(s.basePath);
}
} catch { /* non-fatal — chdir may fail if dir was removed */ }
// ── Send the prompt ──
debugLog("runUnit", { phase: "send-message", unitType, unitId });

View file

@ -1145,6 +1145,9 @@ export async function dispatchHookUnit(
ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
ctx.ui.notify(`Running post-unit hook: ${hookName}`, "info");
// Ensure cwd matches basePath before hook dispatch (#1389)
try { if (process.cwd() !== s.basePath) process.chdir(s.basePath); } catch {}
debugLog("dispatchHookUnit", {
phase: "send-message",
promptLength: hookPrompt.length,

View file

@ -13,6 +13,8 @@
* `process.chdir()` internally this class MUST NOT double-chdir.
*/
import { existsSync, unlinkSync } from "node:fs";
import { join } from "node:path";
import type { AutoSession } from "./auto/session.js";
import { debugLog } from "./debug-logger.js";
@ -372,6 +374,15 @@ export class WorktreeResolver {
});
ctx.notify(`Milestone merge failed: ${msg}`, "warning");
// Clean up stale merge state left by failed squash-merge (#1389)
try {
const gitDir = join(originalBase || this.s.basePath, ".git");
for (const f of ["SQUASH_MSG", "MERGE_HEAD", "MERGE_MSG"]) {
const p = join(gitDir, f);
if (existsSync(p)) unlinkSync(p);
}
} catch { /* best-effort */ }
// Error recovery: always restore to project root
if (originalBase) {
try {