import { afterAll, describe, expect, it, mock } from "bun:test" mock.module("../../shared/system-directive", () => ({ createSystemDirective: (type: string) => `[DIRECTIVE:${type}]`, SystemDirectiveTypes: { TODO_CONTINUATION: "TODO CONTINUATION", RALPH_LOOP: "RALPH LOOP", BOULDER_CONTINUATION: "BOULDER CONTINUATION", DELEGATION_REQUIRED: "DELEGATION REQUIRED", SINGLE_TASK_ONLY: "SINGLE TASK ONLY", COMPACTION_CONTEXT: "COMPACTION CONTEXT", CONTEXT_WINDOW_MONITOR: "CONTEXT WINDOW MONITOR", PROMETHEUS_READ_ONLY: "PROMETHEUS READ-ONLY", }, })) afterAll(() => { mock.restore() }) import { createCompactionContextInjector } from "./index" import type { BackgroundManager } from "../../features/background-agent" import { TaskHistory } from "../../features/background-agent/task-history" import { setCompactionAgentConfigCheckpoint } from "../../shared/compaction-agent-config-checkpoint" function createMockContext( messageResponses: Array }>>, promptAsyncMock = mock(async () => ({})), ) { let callIndex = 0 return { client: { session: { messages: mock(async () => { const response = messageResponses[Math.min(callIndex, messageResponses.length - 1)] ?? [] callIndex += 1 return { data: response } }), promptAsync: promptAsyncMock, }, }, directory: "/tmp/test", } } function createMockBackgroundManager(): BackgroundManager { return { taskHistory: new TaskHistory() } as BackgroundManager } describe("createCompactionContextInjector", () => { describe("Agent Verification State preservation", () => { it("includes Agent Verification State section in compaction prompt", async () => { //#given const injector = createCompactionContextInjector() //#when const prompt = injector.inject() //#then expect(prompt).toContain("Agent Verification State") expect(prompt).toContain("Current Agent") expect(prompt).toContain("Verification Progress") }) it("includes reviewer-agent continuity fields", async () => { //#given const injector = createCompactionContextInjector() //#when const prompt = injector.inject() //#then expect(prompt).toContain("Previous Rejections") expect(prompt).toContain("Acceptance Status") expect(prompt).toContain("reviewer agents") }) it("preserves file verification progress fields", async () => { //#given const injector = createCompactionContextInjector() //#when const prompt = injector.inject() //#then expect(prompt).toContain("Pending Verifications") expect(prompt).toContain("Files already verified") }) }) it("restricts constraints to explicit verbatim statements", async () => { //#given const injector = createCompactionContextInjector() //#when const prompt = injector.inject() //#then expect(prompt).toContain("Explicit Constraints (Verbatim Only)") expect(prompt).toContain("Do NOT invent") expect(prompt).toContain("Quote constraints verbatim") }) describe("Delegated Agent Sessions", () => { it("includes delegated sessions section in compaction prompt", async () => { //#given const injector = createCompactionContextInjector() //#when const prompt = injector.inject() //#then expect(prompt).toContain("Delegated Agent Sessions") expect(prompt).toContain("RESUME, DON'T RESTART") expect(prompt).toContain("session_id") }) it("injects actual task history when backgroundManager and sessionID provided", async () => { //#given const mockManager = createMockBackgroundManager() mockManager.taskHistory.record("ses_parent", { id: "t1", sessionID: "ses_child", agent: "explore", description: "Find patterns", status: "completed", category: "quick" }) const injector = createCompactionContextInjector({ backgroundManager: mockManager }) //#when const prompt = injector.inject("ses_parent") //#then expect(prompt).toContain("Active/Recent Delegated Sessions") expect(prompt).toContain("**explore**") expect(prompt).toContain("[quick]") expect(prompt).toContain("`ses_child`") }) it("does not inject task history section when no entries exist", async () => { //#given const mockManager = createMockBackgroundManager() const injector = createCompactionContextInjector({ backgroundManager: mockManager }) //#when const prompt = injector.inject("ses_empty") //#then expect(prompt).not.toContain("Active/Recent Delegated Sessions") }) }) describe("agent checkpoint recovery", () => { it("re-injects checkpointed agent config after compaction when latest agent is lost", async () => { //#given const promptAsyncMock = mock(async () => ({})) const ctx = createMockContext( [ [ { info: { role: "user", agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, tools: { bash: "allow" }, }, }, ], [ { info: { role: "user", agent: "compaction", model: { providerID: "anthropic", modelID: "claude-opus-4-1" }, }, }, ], [ { info: { role: "user", agent: "compaction", model: { providerID: "anthropic", modelID: "claude-opus-4-1" }, }, }, ], [ { info: { role: "user", agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, tools: { bash: true }, }, }, ], ], promptAsyncMock, ) const injector = createCompactionContextInjector({ ctx }) //#when await injector.capture("ses_checkpoint") await injector.event({ event: { type: "session.compacted", properties: { sessionID: "ses_checkpoint" } }, }) //#then expect(promptAsyncMock).toHaveBeenCalledWith({ path: { id: "ses_checkpoint" }, body: { noReply: true, agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, tools: { bash: true }, parts: [ { type: "text", text: expect.stringContaining("restore checkpointed session agent configuration"), }, ], }, query: { directory: "/tmp/test" }, }) }) it("re-injects checkpointed agent config during autocontinue before synthetic continue", async () => { //#given const promptAsyncMock = mock(async () => ({})) const ctx = createMockContext( [ [ { info: { role: "user", agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, tools: { bash: "allow" }, }, }, ], [ { info: { role: "user", agent: "compaction", model: { providerID: "anthropic", modelID: "claude-opus-4-1" }, }, }, ], [ { info: { role: "user", agent: "compaction", model: { providerID: "anthropic", modelID: "claude-opus-4-1" }, }, }, ], [ { info: { role: "user", agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, tools: { bash: true }, }, }, ], ], promptAsyncMock, ) const injector = createCompactionContextInjector({ ctx }) //#when await injector.capture("ses_autocontinue_checkpoint") const restored = await injector.restore("ses_autocontinue_checkpoint") //#then expect(restored).toBe(true) expect(promptAsyncMock).toHaveBeenCalledWith({ path: { id: "ses_autocontinue_checkpoint" }, body: { noReply: true, agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, tools: { bash: true }, parts: [ { type: "text", text: expect.stringContaining("restore checkpointed session agent configuration"), }, ], }, query: { directory: "/tmp/test" }, }) }) it("clears stale checkpoint when the next compaction capture has no prompt config", async () => { //#given const promptAsyncMock = mock(async () => ({})) const sessionID = "ses_empty_checkpoint_capture" setCompactionAgentConfigCheckpoint(sessionID, { agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, tools: { bash: true }, }) const ctx = createMockContext([[], [], []], promptAsyncMock) const injector = createCompactionContextInjector({ ctx }) //#when await injector.capture(sessionID) const restored = await injector.restore(sessionID) //#then expect(restored).toBe(false) expect(promptAsyncMock).not.toHaveBeenCalled() }) it("recovers after five consecutive assistant messages with no text", async () => { //#given const promptAsyncMock = mock(async () => ({})) const ctx = createMockContext( [ [ { info: { role: "user", agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, }, }, ], [ { info: { role: "user", agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, }, }, ], [ { info: { role: "user", agent: "atlas", model: { providerID: "openai", modelID: "gpt-5" }, }, }, ], ], promptAsyncMock, ) const injector = createCompactionContextInjector({ ctx }) await injector.capture("ses_no_text_tail") await injector.event({ event: { type: "session.compacted", properties: { sessionID: "ses_no_text_tail" } }, }) //#when for (let index = 1; index <= 5; index++) { await injector.event({ event: { type: "message.updated", properties: { info: { id: `msg_${index}`, role: "assistant", sessionID: "ses_no_text_tail", }, }, }, }) } await injector.event({ event: { type: "session.idle", properties: { sessionID: "ses_no_text_tail" } }, }) //#then expect(promptAsyncMock).toHaveBeenCalledTimes(1) expect(promptAsyncMock).toHaveBeenCalledWith( expect.objectContaining({ path: { id: "ses_no_text_tail" }, body: expect.objectContaining({ noReply: true, agent: "atlas", }), }), ) }) }) })