fix(FN-5353): reacquire fresh worktree on reuse-handoff refusal

After merge:reuse-handoff-refused with no usable task worktree:
- Acquire a fresh worktree and restore the fusion/<task-id> branch
  from baseCommitSha before continuing merge
- Hard-fail only if fresh acquisition itself fails (not cwd-main fallback)
- Emit merge:reuse-worktree-fresh-acquire / merge:reuse-worktree-fresh-acquired
  audit events around the acquisition lifecycle

Replaces the incorrect cwd-main fallback (499784581) with correct
reacquire path. Updates regression test in merge-reuse-task-worktree.test.ts
to assert fresh-acquire audit trail instead of cwd-main fallback.

Refs: FN-5353
This commit is contained in:
gsxdsm
2026-05-20 10:47:35 -07:00
parent a03a5de235
commit 6d66559eb3
3 changed files with 64 additions and 108 deletions

View File

@@ -349,7 +349,7 @@ describe("FN-5279 reliability interactions: merge reuse task worktree", () => {
}
}, 30_000);
it.skipIf(!hasGit)("falls back to cwd-main when reuse is requested without a task worktree", async () => {
it.skipIf(!hasGit)("reacquires a fresh task worktree when reuse is requested without a task worktree", async () => {
const fixture = await makeReliabilityFixture({
taskId: "FN-5353-RI-MISSING-WORKTREE",
settings: {
@@ -382,12 +382,13 @@ describe("FN-5279 reliability interactions: merge reuse task worktree", () => {
expect((await store.getTask(task.id))?.column).toBe("done");
const audits = store.getRunAuditEvents({ taskId: task.id });
const auditTypes = audits.map((event) => event.mutationType);
expect(auditTypes).toContain("merge:reuse-fallback-cwd-main");
expect(auditTypes).not.toContain("merge:reuse-handoff-acquired");
const fallback = audits.find((event) => event.mutationType === "merge:reuse-fallback-cwd-main");
expect(auditTypes).toContain("merge:reuse-fallback-new-worktree");
expect(auditTypes).toContain("merge:reuse-handoff-acquired");
expect(auditTypes).not.toContain("merge:reuse-fallback-cwd-main");
const fallback = audits.find((event) => event.mutationType === "merge:reuse-fallback-new-worktree");
expect(fallback?.metadata).toMatchObject({
reason: "missing-task-worktree",
worktreePath: null,
source: "fresh",
integrationBranch: "master",
});
} finally {