fix: recover completed tasks stuck in progress

This commit is contained in:
gsxdsm
2026-04-05 15:24:32 -07:00
parent cb941df102
commit f4012fc5f2
10 changed files with 500 additions and 36 deletions

View File

@@ -4,12 +4,16 @@ import { EventEmitter } from "node:events";
// ── Capture instances & arguments ───────────────────────────────────
let capturedExecutorOpts: Record<string, unknown> | undefined;
let capturedSelfHealingOpts: Record<string, unknown> | undefined;
const {
mockAuthStorage,
mockModelRegistry,
mockDiscoverAndLoadExtensions,
mockCreateExtensionRuntime,
mockSelfHealingStart,
mockSelfHealingStop,
mockCheckStuckBudget,
} = vi.hoisted(() => ({
mockAuthStorage: { getAuth: vi.fn(), setAuth: vi.fn() },
mockModelRegistry: {
@@ -21,6 +25,9 @@ const {
errors: [],
}),
mockCreateExtensionRuntime: vi.fn(),
mockSelfHealingStart: vi.fn(),
mockSelfHealingStop: vi.fn(),
mockCheckStuckBudget: vi.fn().mockResolvedValue(true),
}));
// Minimal mock store backed by EventEmitter so `store.on` works
@@ -195,6 +202,14 @@ vi.mock("@fusion/engine", async (importOriginal) => {
start: vi.fn(),
stop: vi.fn(),
})),
SelfHealingManager: vi.fn().mockImplementation((_store: unknown, opts: unknown) => {
capturedSelfHealingOpts = opts as Record<string, unknown>;
return {
start: mockSelfHealingStart,
stop: mockSelfHealingStop,
checkStuckBudget: mockCheckStuckBudget,
};
}),
scanIdleWorktrees: vi.fn().mockResolvedValue([]),
cleanupOrphanedWorktrees: vi.fn().mockResolvedValue(0),
};
@@ -574,6 +589,7 @@ describe("runDashboard — auto-merge pause exclusion", () => {
beforeEach(async () => {
capturedExecutorOpts = undefined;
capturedSelfHealingOpts = undefined;
vi.clearAllMocks();
resetGitHubMocks();
mockStore = makeMockStore();
@@ -759,6 +775,17 @@ describe("runDashboard — immediate resume on unpause", () => {
expect(resumeOrphaned).toHaveBeenCalled();
});
it("passes executor recovery callbacks into SelfHealingManager", async () => {
await runDashboard(0, { open: false });
expect(capturedSelfHealingOpts).toMatchObject({
rootDir: process.cwd(),
recoverCompletedTask: expect.any(Function),
getExecutingTaskIds: expect.any(Function),
});
expect(mockSelfHealingStart).toHaveBeenCalled();
});
it("sweeps merge queue on unpause when autoMerge is enabled", async () => {
// Set up settings to return autoMerge: true for the drain queue check
mockStore.getSettings.mockResolvedValue({