FN-5743: cut over merge dequeue authority to merge-request queue
Shift merge dequeue enforcement to merge-request queue/marker authority with reliability coverage updates. - Enforce merge eligibility and dequeue ownership via merge-request queue/marker checks in engine and scheduler paths. - Add hard-cancel behavior coverage to ensure queued merge requests are canceled when tasks are user-canceled. - Extend core merge-request record/store tests and reliability interaction suites for dual-observe and cancel-on-hard-cancel seams. - Document the FN-5741/FN-5743 reliability backstop updates in AGENTS.md and architecture docs. Files changed: AGENTS.md | 2 + docs/architecture.md | 2 + packages/core/src/__tests__/merge-request-record.test.ts | 18 ++++ packages/core/src/store.ts | 13 +++ packages/engine/src/__tests__/reliability-interactions/dual-observe-merge-seam.test.ts | 57 +++++++++++++ packages/engine/src/__tests__/reliability-interactions/merge-request-cancel-on-hard-cancel.test.ts | 87 +++++++++++++++++++ packages/engine/src/project-engine.ts | 98 +++++++++++++++++++++- packages/engine/src/scheduler.ts | 12 ++- 8 files changed, 284 insertions(+), 5 deletions(-) Fusion-Task-Id: FN-5743 Fusion-Task-Lineage: b9a49aeb-ed73-42fe-924d-25c7097d1bb9
This commit is contained in:
@@ -94,4 +94,22 @@ describe("TaskStore merge request record + completion handoff marker", () => {
|
||||
store.clearCompletionHandoffAcceptedMarker(taskId);
|
||||
expect(store.getCompletionHandoffAcceptedMarker(taskId)).toBeNull();
|
||||
});
|
||||
|
||||
it("cancels merge request and clears handoff marker on user hard-cancel from in-review to todo", async () => {
|
||||
const taskId = await createTask();
|
||||
await store.moveTask(taskId, "todo");
|
||||
await store.moveTask(taskId, "in-progress");
|
||||
await store.handoffToReview(taskId, {
|
||||
ownerAgentId: "agent-test",
|
||||
evidence: { reason: "fn_task_done", runId: "run-1", agentId: "agent-test" },
|
||||
});
|
||||
|
||||
store.upsertMergeRequestRecord(taskId, { state: "queued", attemptCount: 1, lastError: "pending" });
|
||||
store.setCompletionHandoffAcceptedMarker(taskId, { source: "executor:fn_task_done" });
|
||||
|
||||
await store.moveTask(taskId, "todo", { moveSource: "user" });
|
||||
|
||||
expect(store.getMergeRequestRecord(taskId)?.state).toBe("cancelled");
|
||||
expect(store.getCompletionHandoffAcceptedMarker(taskId)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5544,6 +5544,19 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
||||
}
|
||||
|
||||
await this.writeTaskJsonFile(dir, task);
|
||||
if (fromColumn === "in-review" && toColumn === "todo" && moveSource === "user") {
|
||||
const handoffAccepted = this.getCompletionHandoffAcceptedMarker(id);
|
||||
const mergeRequest = this.getMergeRequestRecord(id);
|
||||
if (handoffAccepted && mergeRequest && mergeRequest.state !== "succeeded" && mergeRequest.state !== "cancelled") {
|
||||
if (mergeRequest.state === "queued" || mergeRequest.state === "running" || mergeRequest.state === "retrying" || mergeRequest.state === "manual-required") {
|
||||
this.transitionMergeRequestState(id, "cancelled", {
|
||||
attemptCount: mergeRequest.attemptCount,
|
||||
lastError: mergeRequest.lastError ?? "cancelled-by-user-hard-cancel",
|
||||
});
|
||||
}
|
||||
}
|
||||
this.clearCompletionHandoffAcceptedMarker(id);
|
||||
}
|
||||
if (toColumn === "done") {
|
||||
this.clearLinkedAgentTaskIds(id, task.updatedAt);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user