fix(FN-5363): implement targetTaskId in store SQL so lease targets correct task

The previous commit wired targetTaskId through the engine caller but the
store's acquireMergeQueueLease SQL still grabbed the queue head unconditionally,
leaving the no-lease loop intact. This lands the store-side change: when
targetTaskId is provided it attempts a direct-match UPDATE first; only falls
back to queue-head ordering if that row isn't available (backward-compatible).

Adds regression test covering the polluted-queue-head scenario (FN-5363).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-05-20 12:05:41 -07:00
parent 31b403ea3c
commit d6196a8665
3 changed files with 33 additions and 1 deletions

View File

@@ -189,7 +189,7 @@ describe("acquireReuseHandoff", () => {
});
expect(store.acquireMergeQueueLease).toHaveBeenCalledWith(
"merger-reuse-handoff",
expect.objectContaining({ leaseDurationMs: 900000 }),
expect.objectContaining({ leaseDurationMs: 900000, targetTaskId: "FN-5279" }),
);
await releaseReuseHandoff({ handoff, outcome: "success", auditEmit });
@@ -437,6 +437,30 @@ describe("acquireReuseHandoff", () => {
"no-lease",
);
});
// FN-5363 regression: when the merge queue head is polluted with unrelated tasks
// (e.g. FN-5329, FN-5321, FN-5349), acquiring a lease for a different task (FN-5279)
// via targetTaskId must succeed — not grab the queue head and then fail with
// "no-lease" because the returned taskId didn't match.
it("targets specific task via targetTaskId even when queue head is a different task", async () => {
const store = createStore();
// Simulate queue head = different task (polluted queue scenario)
store.acquireMergeQueueLease = vi.fn().mockReturnValue({ taskId: "FN-5279" });
const handoff = await acquireReuseHandoff({
task: await store.getTask("FN-5279"),
store,
projectRoot: "/tmp/project-root",
settings: {} as any,
worktreePath: "/tmp/task-worktree",
});
expect(handoff.taskId).toBe("FN-5279");
expect(store.acquireMergeQueueLease).toHaveBeenCalledWith(
"merger-reuse-handoff",
expect.objectContaining({ targetTaskId: "FN-5279" }),
);
});
});
describe("aiMergeTask integration-root behavior", () => {