feat(KB-150): kill active agent sessions on global pause

- Add settings:updated event to TaskStore with previous/new settings payload
- Kill all active executor agent sessions when globalPause transitions false→true
- Kill all active triage specification sessions on global pause with clean status reset
- Track and dispose active merger session on global pause via onSession callback
- Add JSDoc documenting global pause behavior on executor and triage constructors
This commit is contained in:
Dustin Byrne
2026-03-28 02:16:30 -04:00
parent 711b19740d
commit 0f2958df69
9 changed files with 443 additions and 5 deletions

View File

@@ -533,3 +533,50 @@ describe("aiMergeTask — usage limit detection", () => {
);
});
});
describe("aiMergeTask — onSession callback", () => {
beforeEach(() => {
vi.clearAllMocks();
mockedExistsSync.mockReturnValue(true);
setupHappyPathExecSync();
});
it("calls onSession with the session object after creation", async () => {
const mockSession = {
prompt: vi.fn().mockResolvedValue(undefined),
dispose: vi.fn(),
};
mockedCreateHaiAgent.mockResolvedValue({
session: mockSession,
} as any);
const onSession = vi.fn();
const store = createMockStore(
{ id: "KB-050", worktree: "/tmp/root/.worktrees/KB-050" },
[{ id: "KB-050", worktree: "/tmp/root/.worktrees/KB-050", column: "in-review" } as Task],
);
await aiMergeTask(store, "/tmp/root", "KB-050", { onSession });
expect(onSession).toHaveBeenCalledTimes(1);
expect(onSession).toHaveBeenCalledWith(mockSession);
});
it("works without onSession callback (backward compatible)", async () => {
mockedCreateHaiAgent.mockResolvedValue({
session: {
prompt: vi.fn().mockResolvedValue(undefined),
dispose: vi.fn(),
},
} as any);
const store = createMockStore(
{ id: "KB-050", worktree: "/tmp/root/.worktrees/KB-050" },
[{ id: "KB-050", worktree: "/tmp/root/.worktrees/KB-050", column: "in-review" } as Task],
);
// Should not crash without onSession
await expect(aiMergeTask(store, "/tmp/root", "KB-050")).resolves.toBeDefined();
});
});