fix(FN-4917): harden session-start recovery assertions and cap coverage
Fusion-Task-Id: FN-4917 Fusion-Task-Lineage: 1422a545-f4b5-4e1f-a347-8be2a4202f45
This commit is contained in:
committed by
gsxdsm
parent
56f8fc3cdf
commit
1dffcb492e
@@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import "../executor-test-helpers.js";
|
||||
import { TaskExecutor } from "../../executor.js";
|
||||
import { createFnAgent } from "../../pi.js";
|
||||
import { createMockStore, resetExecutorMocks } from "../executor-test-helpers.js";
|
||||
import { createMockStore, mockedExecSync, resetExecutorMocks } from "../executor-test-helpers.js";
|
||||
|
||||
const mockedCreateFnAgent = vi.mocked(createFnAgent);
|
||||
|
||||
@@ -25,6 +25,7 @@ function makeTask(overrides: Record<string, unknown> = {}) {
|
||||
describe("reliability interactions: FN-4917 worktree incomplete session-start", () => {
|
||||
beforeEach(() => {
|
||||
resetExecutorMocks();
|
||||
mockedExecSync.mockReturnValue("");
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -57,13 +58,15 @@ describe("reliability interactions: FN-4917 worktree incomplete session-start",
|
||||
expect(task.worktree).toBeNull();
|
||||
expect(task.branch).toBeNull();
|
||||
expect(task.sessionFile).toBeNull();
|
||||
expect(events.map((e) => e.mutationType)).toEqual(expect.arrayContaining([
|
||||
"worktree:incomplete-detected",
|
||||
"worktree:auto-recovered",
|
||||
]));
|
||||
const mutationTypes = events.map((e) => e.mutationType);
|
||||
const firstDetectedIndex = mutationTypes.indexOf("worktree:incomplete-detected");
|
||||
const firstRecoveredIndex = mutationTypes.indexOf("worktree:auto-recovered");
|
||||
expect(firstDetectedIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(firstRecoveredIndex).toBeGreaterThan(firstDetectedIndex);
|
||||
const sessionStartEvent = events.find((e) => e.mutationType === "worktree:incomplete-detected" && e.metadata?.source === "session-start");
|
||||
expect(sessionStartEvent?.metadata?.classification).toBe(classification);
|
||||
expect(store.logEntry).not.toHaveBeenCalledWith("FN-4917-T", expect.stringMatching(/Refusing to start coding agent/), expect.anything(), expect.anything());
|
||||
expect(events.some((e) => e.mutationType === "worktree:incomplete-detected" && e.metadata?.source === "resume")).toBe(true);
|
||||
expect(store.logEntry.mock.calls.some((call: unknown[]) => String(call[1] ?? "").includes("Refusing to start coding agent"))).toBe(false);
|
||||
});
|
||||
|
||||
it("preserves progress when steps already completed", async () => {
|
||||
@@ -91,6 +94,28 @@ describe("reliability interactions: FN-4917 worktree incomplete session-start",
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4917-T", "todo", { preserveProgress: true });
|
||||
});
|
||||
|
||||
it("escalates when session-start auto-recovery reaches retry cap", async () => {
|
||||
const store = createMockStore();
|
||||
const events: any[] = [];
|
||||
let task = makeTask({ worktree: "/tmp/wt", branch: "fusion/fn-4917-t", worktreeSessionRetryCount: 3 });
|
||||
store.recordRunAuditEvent = vi.fn(async (event: any) => events.push(event));
|
||||
store.getTask.mockImplementation(async () => task);
|
||||
store.updateTask.mockImplementation(async (_id: string, updates: any) => {
|
||||
task = { ...task, ...updates };
|
||||
return task;
|
||||
});
|
||||
|
||||
mockedCreateFnAgent.mockRejectedValueOnce(new Error("Refusing to start coding agent in incomplete worktree: /tmp/wt"));
|
||||
|
||||
const executor = new TaskExecutor(store, process.cwd());
|
||||
await executor.execute(task);
|
||||
|
||||
expect(store.moveTask).not.toHaveBeenCalledWith("FN-4917-T", "todo", expect.anything());
|
||||
expect(events).toEqual(expect.arrayContaining([
|
||||
expect.objectContaining({ domain: "git", mutationType: "worktree:auto-recovered", metadata: expect.objectContaining({ action: "escalate-exhausted" }) }),
|
||||
]));
|
||||
});
|
||||
|
||||
it("does not intercept unrelated session-start failures", async () => {
|
||||
const store = createMockStore();
|
||||
let task = makeTask({ worktree: "/tmp/wt", branch: "fusion/fn-4917-t" });
|
||||
|
||||
Reference in New Issue
Block a user