fix full-suite isolation regressions
This commit is contained in:
+108
-119
@@ -1,8 +1,9 @@
|
||||
import { describe, expect, test, beforeEach, afterEach, mock, afterAll } from "bun:test"
|
||||
import { describe, expect, test, beforeEach, afterEach, mock } from "bun:test"
|
||||
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
import { tmpdir } from "node:os"
|
||||
import { randomUUID } from "node:crypto"
|
||||
import { createOpencodeClient } from "@opencode-ai/sdk"
|
||||
import {
|
||||
writeBoulderState,
|
||||
clearBoulderState,
|
||||
@@ -10,35 +11,16 @@ import {
|
||||
} from "../../features/boulder-state"
|
||||
import type { BoulderState } from "../../features/boulder-state"
|
||||
import { _resetForTesting, registerAgentName, subagentSessions, updateSessionAgent } from "../../features/claude-code-session-state"
|
||||
import type { PendingTaskRef } from "./types"
|
||||
import type { AtlasHookOptions, PendingTaskRef } from "./types"
|
||||
import { createAtlasHook } from "./index"
|
||||
import { createToolExecuteAfterHandler } from "./tool-execute-after"
|
||||
import { createToolExecuteBeforeHandler } from "./tool-execute-before"
|
||||
|
||||
const TEST_STORAGE_ROOT = join(tmpdir(), `atlas-message-storage-${randomUUID()}`)
|
||||
const TEST_MESSAGE_STORAGE = join(TEST_STORAGE_ROOT, "message")
|
||||
const TEST_PART_STORAGE = join(TEST_STORAGE_ROOT, "part")
|
||||
|
||||
mock.module("../../features/hook-message-injector/constants", () => ({
|
||||
OPENCODE_STORAGE: TEST_STORAGE_ROOT,
|
||||
MESSAGE_STORAGE: TEST_MESSAGE_STORAGE,
|
||||
PART_STORAGE: TEST_PART_STORAGE,
|
||||
}))
|
||||
|
||||
mock.module("../../shared/opencode-message-dir", () => ({
|
||||
getMessageDir: (sessionID: string) => {
|
||||
const dir = join(TEST_MESSAGE_STORAGE, sessionID)
|
||||
return existsSync(dir) ? dir : null
|
||||
},
|
||||
}))
|
||||
|
||||
mock.module("../../shared/opencode-storage-detection", () => ({
|
||||
isSqliteBackend: () => false,
|
||||
}))
|
||||
|
||||
afterAll(() => { mock.restore() })
|
||||
|
||||
const { createAtlasHook } = await import("./index")
|
||||
const { createToolExecuteAfterHandler } = await import("./tool-execute-after")
|
||||
const { createToolExecuteBeforeHandler } = await import("./tool-execute-before")
|
||||
const { MESSAGE_STORAGE } = await import("../../features/hook-message-injector")
|
||||
const callerAgentBySession = new Map<string, string>()
|
||||
type MockAtlasInput = Parameters<typeof createAtlasHook>[0] & {
|
||||
_promptMock: ReturnType<typeof mock>
|
||||
_sessionGetMock: ReturnType<typeof mock>
|
||||
}
|
||||
|
||||
describe("atlas hook", () => {
|
||||
let TEST_DIR: string
|
||||
@@ -47,7 +29,7 @@ describe("atlas hook", () => {
|
||||
function createMockPluginInput(overrides?: {
|
||||
promptMock?: ReturnType<typeof mock>
|
||||
sessionGetMock?: ReturnType<typeof mock>
|
||||
}) {
|
||||
}): MockAtlasInput {
|
||||
const promptMock = overrides?.promptMock ?? mock(() => Promise.resolve())
|
||||
const sessionGetMock = overrides?.sessionGetMock ?? mock(async ({ path }: { path: { id: string } }) => ({
|
||||
data: {
|
||||
@@ -55,40 +37,41 @@ describe("atlas hook", () => {
|
||||
parentID: path.id.startsWith("ses_") ? "session-1" : "main-session-123",
|
||||
},
|
||||
}))
|
||||
const client = createOpencodeClient({ baseUrl: "http://localhost" })
|
||||
Reflect.set(client.session, "get", sessionGetMock)
|
||||
Reflect.set(client.session, "prompt", promptMock)
|
||||
Reflect.set(client.session, "promptAsync", promptMock)
|
||||
|
||||
return {
|
||||
directory: TEST_DIR,
|
||||
client: {
|
||||
session: {
|
||||
get: sessionGetMock,
|
||||
prompt: promptMock,
|
||||
promptAsync: promptMock,
|
||||
},
|
||||
},
|
||||
project: {} as Parameters<typeof createAtlasHook>[0]["project"],
|
||||
worktree: TEST_DIR,
|
||||
serverUrl: new URL("http://localhost"),
|
||||
$: {} as Parameters<typeof createAtlasHook>[0]["$"],
|
||||
client,
|
||||
_promptMock: promptMock,
|
||||
_sessionGetMock: sessionGetMock,
|
||||
} as Parameters<typeof createAtlasHook>[0] & {
|
||||
_promptMock: ReturnType<typeof mock>
|
||||
_sessionGetMock: ReturnType<typeof mock>
|
||||
}
|
||||
}
|
||||
|
||||
function setupMessageStorage(sessionID: string, agent: string): void {
|
||||
const messageDir = join(MESSAGE_STORAGE, sessionID)
|
||||
if (!existsSync(messageDir)) {
|
||||
mkdirSync(messageDir, { recursive: true })
|
||||
}
|
||||
const messageData = {
|
||||
agent,
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-7" },
|
||||
}
|
||||
writeFileSync(join(messageDir, "msg_test001.json"), JSON.stringify(messageData))
|
||||
callerAgentBySession.set(sessionID, agent)
|
||||
}
|
||||
|
||||
function cleanupMessageStorage(sessionID: string): void {
|
||||
const messageDir = join(MESSAGE_STORAGE, sessionID)
|
||||
if (existsSync(messageDir)) {
|
||||
rmSync(messageDir, { recursive: true, force: true })
|
||||
callerAgentBySession.delete(sessionID)
|
||||
}
|
||||
|
||||
function createTestAtlasHook(
|
||||
input = createMockPluginInput(),
|
||||
options: Partial<AtlasHookOptions> = {},
|
||||
): ReturnType<typeof createAtlasHook> {
|
||||
const resolvedOptions: AtlasHookOptions = {
|
||||
directory: TEST_DIR,
|
||||
isCallerOrchestrator: async (sessionID) => callerAgentBySession.get(sessionID ?? "") === "atlas",
|
||||
...options,
|
||||
}
|
||||
return createAtlasHook(input, resolvedOptions)
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -104,10 +87,12 @@ describe("atlas hook", () => {
|
||||
mkdirSync(SISYPHUS_DIR, { recursive: true })
|
||||
}
|
||||
clearBoulderState(TEST_DIR)
|
||||
callerAgentBySession.clear()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
_resetForTesting()
|
||||
callerAgentBySession.clear()
|
||||
clearBoulderState(TEST_DIR)
|
||||
if (existsSync(TEST_DIR)) {
|
||||
rmSync(TEST_DIR, { recursive: true, force: true })
|
||||
@@ -117,7 +102,7 @@ describe("atlas hook", () => {
|
||||
describe("tool.execute.after handler", () => {
|
||||
test("should handle undefined output gracefully (issue #1035)", async () => {
|
||||
// given - hook and undefined output (e.g., from /review command)
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
|
||||
// when - calling with undefined output
|
||||
const result = await hook["tool.execute.after"](
|
||||
@@ -131,7 +116,7 @@ describe("atlas hook", () => {
|
||||
|
||||
test("should ignore non-task tools", async () => {
|
||||
// given - hook and non-task tool
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Test Tool",
|
||||
output: "Original output",
|
||||
@@ -164,7 +149,7 @@ describe("atlas hook", () => {
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task completed successfully",
|
||||
@@ -188,7 +173,7 @@ describe("atlas hook", () => {
|
||||
const sessionID = "session-no-boulder-test"
|
||||
setupMessageStorage(sessionID, "atlas")
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task completed successfully",
|
||||
@@ -225,7 +210,7 @@ describe("atlas hook", () => {
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task completed successfully",
|
||||
@@ -264,7 +249,7 @@ describe("atlas hook", () => {
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: `Task completed
|
||||
@@ -301,7 +286,7 @@ session_id: ses_subagent_abc
|
||||
const sessionID = "session-standalone-metadata-test"
|
||||
setupMessageStorage(sessionID, "atlas")
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: `Task completed
|
||||
@@ -349,7 +334,7 @@ session_id: ses_standalone_def
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Original output",
|
||||
@@ -386,7 +371,7 @@ session_id: ses_standalone_def
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task output",
|
||||
@@ -422,7 +407,7 @@ session_id: ses_standalone_def
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput({
|
||||
const hook = createTestAtlasHook(createMockPluginInput({
|
||||
sessionGetMock: mock(async () => {
|
||||
throw new Error("session lookup failed")
|
||||
}),
|
||||
@@ -462,7 +447,7 @@ session_id: ses_standalone_def
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task output",
|
||||
@@ -499,7 +484,7 @@ session_id: ses_standalone_def
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task completed",
|
||||
@@ -536,7 +521,7 @@ session_id: ses_standalone_def
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task completed",
|
||||
@@ -581,6 +566,7 @@ session_id: ses_standalone_def
|
||||
ctx: createMockPluginInput(),
|
||||
pendingFilePaths,
|
||||
pendingTaskRefs,
|
||||
isCallerOrchestrator: async (id) => callerAgentBySession.get(id ?? "") === "atlas",
|
||||
})
|
||||
const afterHandler = createToolExecuteAfterHandler({
|
||||
ctx: createMockPluginInput(),
|
||||
@@ -588,6 +574,7 @@ session_id: ses_standalone_def
|
||||
pendingTaskRefs,
|
||||
autoCommit: true,
|
||||
getState: () => ({ promptFailureCount: 0 }),
|
||||
isCallerOrchestrator: async (id) => callerAgentBySession.get(id ?? "") === "atlas",
|
||||
})
|
||||
|
||||
// when - the task is captured before execution
|
||||
@@ -634,7 +621,7 @@ session_id: ses_standalone_def
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: `Task completed successfully
|
||||
@@ -684,7 +671,7 @@ session_id: ses_auth_flow_123
|
||||
plan_name: "stable-task-key-plan",
|
||||
})
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
|
||||
// when - Atlas delegates task 1
|
||||
await hook["tool.execute.before"](
|
||||
@@ -744,7 +731,7 @@ session_id: ses_auth_flow_123
|
||||
plan_name: "cross-task-resume-plan",
|
||||
})
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
|
||||
// when - Atlas resumes an explicit prior session
|
||||
await hook["tool.execute.before"](
|
||||
@@ -806,7 +793,7 @@ session_id: ses_old_task_111
|
||||
},
|
||||
})
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: `Task continued successfully
|
||||
@@ -860,6 +847,7 @@ session_id: ses_old_task_111
|
||||
ctx: createMockPluginInput(),
|
||||
pendingFilePaths,
|
||||
pendingTaskRefs,
|
||||
isCallerOrchestrator: async (id) => callerAgentBySession.get(id ?? "") === "atlas",
|
||||
})
|
||||
const afterHandler = createToolExecuteAfterHandler({
|
||||
ctx: createMockPluginInput(),
|
||||
@@ -867,6 +855,7 @@ session_id: ses_old_task_111
|
||||
pendingTaskRefs,
|
||||
autoCommit: true,
|
||||
getState: () => ({ promptFailureCount: 0 }),
|
||||
isCallerOrchestrator: async (id) => callerAgentBySession.get(id ?? "") === "atlas",
|
||||
})
|
||||
|
||||
// when - two task() calls start before either one completes
|
||||
@@ -929,7 +918,7 @@ session_id: ses_parallel_collision_222
|
||||
plan_name: "untrusted-session-id-plan",
|
||||
})
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput({
|
||||
const hook = createTestAtlasHook(createMockPluginInput({
|
||||
sessionGetMock: mock(async ({ path }: { path: { id: string } }) => ({
|
||||
data: {
|
||||
id: path.id,
|
||||
@@ -987,7 +976,7 @@ session_id: ses_untrusted_999
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task completed successfully",
|
||||
@@ -1022,7 +1011,7 @@ session_id: ses_untrusted_999
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task completed successfully",
|
||||
@@ -1061,7 +1050,7 @@ session_id: ses_untrusted_999
|
||||
}
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Sisyphus Task",
|
||||
output: "Task completed successfully",
|
||||
@@ -1093,7 +1082,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
test("should append delegation reminder when orchestrator writes outside .sisyphus/", async () => {
|
||||
// given
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Write",
|
||||
output: "File written successfully",
|
||||
@@ -1114,7 +1103,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
test("should append delegation reminder when orchestrator edits outside .sisyphus/", async () => {
|
||||
// given
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Edit",
|
||||
output: "File edited successfully",
|
||||
@@ -1133,7 +1122,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
test("should NOT append reminder when orchestrator writes inside .sisyphus/", async () => {
|
||||
// given
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const originalOutput = "File written successfully"
|
||||
const output = {
|
||||
title: "Write",
|
||||
@@ -1157,7 +1146,7 @@ session_id: ses_untrusted_999
|
||||
const nonOrchestratorSession = "non-orchestrator-session"
|
||||
setupMessageStorage(nonOrchestratorSession, "sisyphus-junior")
|
||||
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const originalOutput = "File written successfully"
|
||||
const output = {
|
||||
title: "Write",
|
||||
@@ -1180,7 +1169,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
test("should NOT append reminder for read-only tools", async () => {
|
||||
// given
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const originalOutput = "File content"
|
||||
const output = {
|
||||
title: "Read",
|
||||
@@ -1200,7 +1189,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
test("should handle missing filePath gracefully", async () => {
|
||||
// given
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const originalOutput = "File written successfully"
|
||||
const output = {
|
||||
title: "Write",
|
||||
@@ -1221,7 +1210,7 @@ session_id: ses_untrusted_999
|
||||
describe("cross-platform path validation (Windows support)", () => {
|
||||
test("should NOT append reminder when orchestrator writes inside .sisyphus\\ (Windows backslash)", async () => {
|
||||
// given
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const originalOutput = "File written successfully"
|
||||
const output = {
|
||||
title: "Write",
|
||||
@@ -1242,7 +1231,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
test("should NOT append reminder when orchestrator writes inside .sisyphus with mixed separators", async () => {
|
||||
// given
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const originalOutput = "File written successfully"
|
||||
const output = {
|
||||
title: "Write",
|
||||
@@ -1263,7 +1252,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
test("should NOT append reminder for absolute Windows path inside .sisyphus\\", async () => {
|
||||
// given
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const originalOutput = "File written successfully"
|
||||
const output = {
|
||||
title: "Write",
|
||||
@@ -1284,7 +1273,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
test("should append reminder for Windows path outside .sisyphus\\", async () => {
|
||||
// given
|
||||
const hook = createAtlasHook(createMockPluginInput())
|
||||
const hook = createTestAtlasHook(createMockPluginInput())
|
||||
const output = {
|
||||
title: "Write",
|
||||
output: "File written successfully",
|
||||
@@ -1339,7 +1328,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when
|
||||
await hook.handler({
|
||||
@@ -1360,7 +1349,7 @@ session_id: ses_untrusted_999
|
||||
test("should not inject when no boulder state exists", async () => {
|
||||
// given - no boulder state
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when
|
||||
await hook.handler({
|
||||
@@ -1388,7 +1377,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - main session fires idle but is NOT in boulder's session_ids
|
||||
await hook.handler({
|
||||
@@ -1419,7 +1408,7 @@ session_id: ses_untrusted_999
|
||||
updateSessionAgent(subagentSessionID, "atlas")
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - subagent session goes idle before explicit tracking appends it
|
||||
await hook.handler({
|
||||
@@ -1451,7 +1440,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
await hook.handler({
|
||||
event: {
|
||||
@@ -1480,7 +1469,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when
|
||||
await hook.handler({
|
||||
@@ -1513,7 +1502,7 @@ session_id: ses_untrusted_999
|
||||
})
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
try {
|
||||
// when
|
||||
@@ -1545,7 +1534,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - send abort error then idle
|
||||
await hook.handler({
|
||||
@@ -1582,7 +1571,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - a recoverable runtime error fires without waiting for idle
|
||||
await hook.handler({
|
||||
@@ -1618,14 +1607,14 @@ session_id: ses_untrusted_999
|
||||
|
||||
const originalSetTimeout = globalThis.setTimeout
|
||||
const scheduledDelays: number[] = []
|
||||
globalThis.setTimeout = ((_handler: TimerHandler, timeout?: number, ..._args: unknown[]) => {
|
||||
globalThis.setTimeout = ((_handler: Parameters<typeof setTimeout>[0], timeout?: number, ..._args: unknown[]) => {
|
||||
scheduledDelays.push(timeout ?? 0)
|
||||
return originalSetTimeout(() => undefined, 0)
|
||||
}) as typeof setTimeout
|
||||
|
||||
try {
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - runtime error resumes immediately and OpenCode later emits stale idle
|
||||
await hook.handler({
|
||||
@@ -1671,7 +1660,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
try {
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - runtime error resumes immediately and then the retry run emits assistant activity
|
||||
await hook.handler({
|
||||
@@ -1722,7 +1711,7 @@ session_id: ses_untrusted_999
|
||||
}
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput, {
|
||||
const hook = createTestAtlasHook(mockInput, {
|
||||
directory: TEST_DIR,
|
||||
backgroundManager: mockBackgroundManager,
|
||||
})
|
||||
@@ -1753,7 +1742,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput, {
|
||||
const hook = createTestAtlasHook(mockInput, {
|
||||
directory: TEST_DIR,
|
||||
isContinuationStopped: (sessionID: string) => sessionID === MAIN_SESSION_ID,
|
||||
})
|
||||
@@ -1784,7 +1773,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - abort error, then message update, then idle
|
||||
await hook.handler({
|
||||
@@ -1827,7 +1816,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when
|
||||
await hook.handler({
|
||||
@@ -1869,7 +1858,7 @@ session_id: ses_untrusted_999
|
||||
})
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when
|
||||
await hook.handler({
|
||||
@@ -1904,7 +1893,7 @@ session_id: ses_untrusted_999
|
||||
setupMessageStorage(MAIN_SESSION_ID, "sisyphus")
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when
|
||||
await hook.handler({
|
||||
@@ -1935,7 +1924,7 @@ session_id: ses_untrusted_999
|
||||
setupMessageStorage(MAIN_SESSION_ID, "hephaestus")
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
await hook.handler({
|
||||
event: {
|
||||
@@ -1965,7 +1954,7 @@ session_id: ses_untrusted_999
|
||||
setupMessageStorage(MAIN_SESSION_ID, "sisyphus")
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when
|
||||
await hook.handler({
|
||||
@@ -1997,7 +1986,7 @@ session_id: ses_untrusted_999
|
||||
registerAgentName("Atlas - Plan Executor")
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when
|
||||
await hook.handler({
|
||||
@@ -2028,7 +2017,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - fire multiple idle events in rapid succession (simulating infinite loop bug)
|
||||
await hook.handler({
|
||||
@@ -2069,7 +2058,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
const promptMock = mock((): Promise<void> => Promise.reject(new Error("Bad Request")))
|
||||
const mockInput = createMockPluginInput({ promptMock })
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
const originalDateNow = Date.now
|
||||
let now = 0
|
||||
@@ -2111,7 +2100,7 @@ session_id: ses_untrusted_999
|
||||
promptMock.mockImplementationOnce(() => Promise.resolve())
|
||||
|
||||
const mockInput = createMockPluginInput({ promptMock })
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
const originalDateNow = Date.now
|
||||
let now = 0
|
||||
@@ -2147,7 +2136,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
const promptMock = mock(() => Promise.reject(new Error("Bad Request")))
|
||||
const mockInput = createMockPluginInput({ promptMock })
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
const originalDateNow = Date.now
|
||||
let now = 0
|
||||
@@ -2188,7 +2177,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
const promptMock = mock(() => Promise.reject(new Error("Bad Request")))
|
||||
const mockInput = createMockPluginInput({ promptMock })
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
const originalDateNow = Date.now
|
||||
let now = 0
|
||||
@@ -2233,7 +2222,7 @@ session_id: ses_untrusted_999
|
||||
}
|
||||
promptMock.mockImplementationOnce(() => Promise.resolve(undefined))
|
||||
const mockInput = createMockPluginInput({ promptMock })
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
const originalDateNow = Date.now
|
||||
let now = 0
|
||||
@@ -2284,7 +2273,7 @@ session_id: ses_untrusted_999
|
||||
|
||||
const promptMock = mock(() => Promise.reject(new Error("Bad Request")))
|
||||
const mockInput = createMockPluginInput({ promptMock })
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
const originalDateNow = Date.now
|
||||
let now = 0
|
||||
@@ -2328,7 +2317,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - create abort state then delete
|
||||
await hook.handler({
|
||||
@@ -2381,7 +2370,7 @@ session_id: ses_untrusted_999
|
||||
updateSessionAgent(MAIN_SESSION_ID, "atlas")
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when
|
||||
await hook.handler({
|
||||
@@ -2407,7 +2396,7 @@ session_id: ses_untrusted_999
|
||||
fakeNow = 10000
|
||||
Date.now = () => fakeNow
|
||||
|
||||
globalThis.setTimeout = ((callback: TimerHandler, delay?: number, ...args: unknown[]) => {
|
||||
globalThis.setTimeout = ((callback: Parameters<typeof setTimeout>[0], delay?: number, ...args: unknown[]) => {
|
||||
const normalized = typeof delay === "number" ? delay : 0
|
||||
if (normalized >= 5000) {
|
||||
const timerID = originalSetTimeout(() => undefined, 0)
|
||||
@@ -2463,7 +2452,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - first idle injects, second idle within cooldown schedules retry timer
|
||||
await hook.handler({
|
||||
@@ -2492,7 +2481,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - first idle injects, then 3 rapid idles within cooldown
|
||||
await hook.handler({
|
||||
@@ -2527,7 +2516,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
// when - first idle injects, second schedules retry, then plan completes before timer fires
|
||||
await hook.handler({
|
||||
@@ -2558,7 +2547,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
await hook.handler({
|
||||
event: { type: "session.idle", properties: { sessionID: MAIN_SESSION_ID } },
|
||||
@@ -2591,7 +2580,7 @@ session_id: ses_untrusted_999
|
||||
writeBoulderState(TEST_DIR, state)
|
||||
|
||||
const mockInput = createMockPluginInput()
|
||||
const hook = createAtlasHook(mockInput)
|
||||
const hook = createTestAtlasHook(mockInput)
|
||||
|
||||
await hook.handler({
|
||||
event: { type: "session.idle", properties: { sessionID: MAIN_SESSION_ID } },
|
||||
|
||||
Reference in New Issue
Block a user