fix(FN-5279): apply reuse-mode squash to local main and guard executor-lease race
In reuse-task-worktree mode the merger detaches HEAD in the task worktree so the squash commit lands on detached HEAD; nothing previously advanced the project root's local integration branch, so changes never appeared on main. Step 5c now applies the squash to projectRootDir via git merge --ff-only, falling back to a regular merge with AI conflict resolution if main has diverged. pushAfterMerge (when enabled) now runs from projectRootDir where the branch was just advanced, so parsePushRemoteTarget can resolve a branch instead of failing on the worktree's detached HEAD. Also tightens acquireReuseHandoff: the executor-lease check above the queue-lease acquisition was non-atomic, letting a local executor grab the task between checks. Re-check after acquisition and release the queue lease with a precise diagnostic instead of proceeding into a generic failure later. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,7 +22,7 @@ import { git, hasGit, makeReliabilityFixture } from "./_helpers.js";
|
||||
const mockedCreateFnAgent = vi.mocked(createFnAgent);
|
||||
|
||||
describe("FN-5279 reliability interactions: merge reuse task worktree", () => {
|
||||
it.skipIf(!hasGit)("happy path merges from a reused task worktree without mutating the project root", async () => {
|
||||
it.skipIf(!hasGit)("happy path merges from a reused task worktree and applies the squash to the project root's integration branch", async () => {
|
||||
const fixture = await makeReliabilityFixture({
|
||||
taskId: "FN-5279-RI-HAPPY",
|
||||
settings: {
|
||||
@@ -71,7 +71,14 @@ describe("FN-5279 reliability interactions: merge reuse task worktree", () => {
|
||||
const acquired = audits.find((event) => event.mutationType === "merge:reuse-handoff-acquired");
|
||||
expect(acquired?.metadata).toMatchObject({ integrationRemote: "origin", integrationBranch: "master" });
|
||||
|
||||
expect(git(rootDir, "git rev-parse HEAD")).toBe(rootHeadBefore);
|
||||
// Step 5c (FN-5279 reuse mode) advances the project root's integration
|
||||
// branch to the new squash commit so changes actually land on master.
|
||||
expect(auditTypes).toContain("merge:reuse-integration-branch-advanced");
|
||||
const advanced = audits.find(
|
||||
(event) => event.mutationType === "merge:reuse-integration-branch-advanced",
|
||||
);
|
||||
expect(advanced?.metadata).toMatchObject({ via: "ff-merge" });
|
||||
expect(git(rootDir, "git rev-parse HEAD")).not.toBe(rootHeadBefore);
|
||||
expect(git(rootDir, "git status --porcelain --untracked-files=no")).toBe(rootTrackedStatusBefore);
|
||||
} finally {
|
||||
await fixture.cleanup();
|
||||
|
||||
Reference in New Issue
Block a user