2026-03-06 22:00:21 +09:00
|
|
|
import { describe, expect, test } from "bun:test"
|
|
|
|
|
import { mkdirSync, rmSync } from "node:fs"
|
|
|
|
|
import { tmpdir } from "node:os"
|
|
|
|
|
import { join } from "node:path"
|
2026-03-06 22:37:41 +09:00
|
|
|
import { createToolExecuteAfterHandler } from "./tool-execute-after"
|
2026-03-06 22:00:21 +09:00
|
|
|
import { createToolExecuteBeforeHandler } from "./tool-execute-before"
|
|
|
|
|
import { ULTRAWORK_VERIFICATION_PROMISE } from "../hooks/ralph-loop/constants"
|
2026-03-06 22:37:41 +09:00
|
|
|
import { clearState, readState, writeState } from "../hooks/ralph-loop/storage"
|
2026-03-06 22:00:21 +09:00
|
|
|
|
|
|
|
|
describe("tool.execute.before ultrawork oracle verification", () => {
|
|
|
|
|
function createCtx(directory: string) {
|
|
|
|
|
return {
|
|
|
|
|
directory,
|
|
|
|
|
client: {
|
|
|
|
|
session: {
|
|
|
|
|
messages: async () => ({ data: [] }),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-17 16:20:27 +09:00
|
|
|
function createOracleTaskArgs(prompt: string): Record<string, unknown> {
|
|
|
|
|
return {
|
|
|
|
|
subagent_type: "oracle",
|
|
|
|
|
run_in_background: true,
|
|
|
|
|
prompt,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createSyncTaskMetadata(
|
|
|
|
|
args: Record<string, unknown>,
|
|
|
|
|
sessionId: string,
|
|
|
|
|
): Record<string, unknown> {
|
|
|
|
|
return {
|
|
|
|
|
prompt: args.prompt,
|
|
|
|
|
agent: "oracle",
|
|
|
|
|
run_in_background: args.run_in_background,
|
|
|
|
|
sessionId,
|
|
|
|
|
sync: true,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-06 22:00:21 +09:00
|
|
|
test("#given ulw loop is awaiting verification #when oracle task runs #then oracle prompt is enforced and sync", async () => {
|
|
|
|
|
const directory = join(tmpdir(), `tool-before-ulw-${Date.now()}`)
|
|
|
|
|
mkdirSync(directory, { recursive: true })
|
|
|
|
|
writeState(directory, {
|
|
|
|
|
active: true,
|
|
|
|
|
iteration: 3,
|
|
|
|
|
completion_promise: ULTRAWORK_VERIFICATION_PROMISE,
|
|
|
|
|
initial_completion_promise: "DONE",
|
|
|
|
|
started_at: new Date().toISOString(),
|
|
|
|
|
prompt: "Ship feature",
|
|
|
|
|
session_id: "ses-main",
|
|
|
|
|
ultrawork: true,
|
|
|
|
|
verification_pending: true,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const handler = createToolExecuteBeforeHandler({
|
|
|
|
|
ctx: createCtx(directory) as unknown as Parameters<typeof createToolExecuteBeforeHandler>[0]["ctx"],
|
|
|
|
|
hooks: {} as Parameters<typeof createToolExecuteBeforeHandler>[0]["hooks"],
|
|
|
|
|
})
|
2026-03-17 16:20:27 +09:00
|
|
|
const output = { args: createOracleTaskArgs("Check it") }
|
2026-03-06 22:00:21 +09:00
|
|
|
|
|
|
|
|
await handler({ tool: "task", sessionID: "ses-main", callID: "call-1" }, output)
|
|
|
|
|
|
2026-03-06 22:37:41 +09:00
|
|
|
expect(readState(directory)?.verification_attempt_id).toBeTruthy()
|
2026-03-06 22:00:21 +09:00
|
|
|
expect(output.args.run_in_background).toBe(false)
|
2026-03-18 17:45:59 +09:00
|
|
|
expect(output.args.prompt).toContain("Original task:")
|
2026-03-06 22:00:21 +09:00
|
|
|
expect(output.args.prompt).toContain("Ship feature")
|
2026-03-18 17:45:59 +09:00
|
|
|
expect(output.args.prompt).toContain("Review the work skeptically and critically")
|
2026-03-06 22:00:21 +09:00
|
|
|
expect(output.args.prompt).toContain(`<promise>${ULTRAWORK_VERIFICATION_PROMISE}</promise>`)
|
|
|
|
|
|
|
|
|
|
clearState(directory)
|
|
|
|
|
rmSync(directory, { recursive: true, force: true })
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test("#given ulw loop is not awaiting verification #when oracle task runs #then prompt is unchanged", async () => {
|
|
|
|
|
const directory = join(tmpdir(), `tool-before-ulw-${Date.now()}-plain`)
|
|
|
|
|
mkdirSync(directory, { recursive: true })
|
|
|
|
|
const handler = createToolExecuteBeforeHandler({
|
|
|
|
|
ctx: createCtx(directory) as unknown as Parameters<typeof createToolExecuteBeforeHandler>[0]["ctx"],
|
|
|
|
|
hooks: {} as Parameters<typeof createToolExecuteBeforeHandler>[0]["hooks"],
|
|
|
|
|
})
|
2026-03-17 16:20:27 +09:00
|
|
|
const output = { args: createOracleTaskArgs("Check it") }
|
2026-03-06 22:00:21 +09:00
|
|
|
|
|
|
|
|
await handler({ tool: "task", sessionID: "ses-main", callID: "call-1" }, output)
|
|
|
|
|
|
|
|
|
|
expect(output.args.run_in_background).toBe(true)
|
|
|
|
|
expect(output.args.prompt).toBe("Check it")
|
|
|
|
|
|
|
|
|
|
rmSync(directory, { recursive: true, force: true })
|
|
|
|
|
})
|
2026-03-06 22:37:41 +09:00
|
|
|
|
2026-04-01 17:19:45 -07:00
|
|
|
test("#given ulw-loop skill invocation carries user_message #when tool.execute.before runs #then the loop starts with that prompt", async () => {
|
|
|
|
|
const directory = join(tmpdir(), `tool-before-ulw-skill-${Date.now()}`)
|
|
|
|
|
mkdirSync(directory, { recursive: true })
|
|
|
|
|
const startLoopCalls: Array<{ sessionID: string; prompt: string; options: Record<string, unknown> }> = []
|
|
|
|
|
const handler = createToolExecuteBeforeHandler({
|
|
|
|
|
ctx: createCtx(directory) as unknown as Parameters<typeof createToolExecuteBeforeHandler>[0]["ctx"],
|
|
|
|
|
hooks: {
|
|
|
|
|
ralphLoop: {
|
|
|
|
|
startLoop: (sessionID: string, prompt: string, options?: Record<string, unknown>) => {
|
|
|
|
|
startLoopCalls.push({ sessionID, prompt, options: options ?? {} })
|
|
|
|
|
return true
|
|
|
|
|
},
|
|
|
|
|
cancelLoop: () => true,
|
|
|
|
|
getState: () => null,
|
|
|
|
|
},
|
|
|
|
|
} as unknown as Parameters<typeof createToolExecuteBeforeHandler>[0]["hooks"],
|
|
|
|
|
})
|
|
|
|
|
const output = {
|
|
|
|
|
args: {
|
|
|
|
|
name: "ulw-loop",
|
|
|
|
|
user_message: '"Ship feature" --strategy=continue',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await handler({ tool: "skill", sessionID: "ses-main", callID: "call-skill-ulw" }, output)
|
|
|
|
|
|
|
|
|
|
expect(startLoopCalls).toHaveLength(1)
|
|
|
|
|
expect(startLoopCalls[0]).toEqual({
|
|
|
|
|
sessionID: "ses-main",
|
|
|
|
|
prompt: "Ship feature",
|
|
|
|
|
options: {
|
|
|
|
|
ultrawork: true,
|
|
|
|
|
maxIterations: undefined,
|
|
|
|
|
completionPromise: undefined,
|
|
|
|
|
strategy: "continue",
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
rmSync(directory, { recursive: true, force: true })
|
|
|
|
|
})
|
|
|
|
|
|
2026-03-17 16:20:27 +09:00
|
|
|
test("#given ulw loop is awaiting verification #when oracle sync task metadata is persisted #then oracle session id is stored", async () => {
|
2026-03-06 22:37:41 +09:00
|
|
|
const directory = join(tmpdir(), `tool-after-ulw-${Date.now()}`)
|
|
|
|
|
mkdirSync(directory, { recursive: true })
|
|
|
|
|
writeState(directory, {
|
|
|
|
|
active: true,
|
|
|
|
|
iteration: 3,
|
|
|
|
|
completion_promise: ULTRAWORK_VERIFICATION_PROMISE,
|
|
|
|
|
initial_completion_promise: "DONE",
|
|
|
|
|
started_at: new Date().toISOString(),
|
|
|
|
|
prompt: "Ship feature",
|
|
|
|
|
session_id: "ses-main",
|
|
|
|
|
ultrawork: true,
|
|
|
|
|
verification_pending: true,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const beforeHandler = createToolExecuteBeforeHandler({
|
|
|
|
|
ctx: createCtx(directory) as unknown as Parameters<typeof createToolExecuteBeforeHandler>[0]["ctx"],
|
|
|
|
|
hooks: {} as Parameters<typeof createToolExecuteBeforeHandler>[0]["hooks"],
|
|
|
|
|
})
|
2026-03-17 16:20:27 +09:00
|
|
|
const beforeOutput = { args: createOracleTaskArgs("Check it") }
|
2026-03-06 22:37:41 +09:00
|
|
|
await beforeHandler({ tool: "task", sessionID: "ses-main", callID: "call-1" }, beforeOutput)
|
2026-03-17 16:20:27 +09:00
|
|
|
const metadataFromSyncTask = createSyncTaskMetadata(beforeOutput.args, "ses-oracle")
|
|
|
|
|
|
|
|
|
|
const handler = createToolExecuteAfterHandler({
|
|
|
|
|
ctx: createCtx(directory) as unknown as Parameters<typeof createToolExecuteAfterHandler>[0]["ctx"],
|
|
|
|
|
hooks: {} as Parameters<typeof createToolExecuteAfterHandler>[0]["hooks"],
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
await handler(
|
|
|
|
|
{ tool: "task", sessionID: "ses-main", callID: "call-1" },
|
|
|
|
|
{
|
|
|
|
|
title: "oracle task",
|
|
|
|
|
output: "done",
|
|
|
|
|
metadata: metadataFromSyncTask,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
expect(readState(directory)?.verification_session_id).toBe("ses-oracle")
|
|
|
|
|
|
|
|
|
|
clearState(directory)
|
|
|
|
|
rmSync(directory, { recursive: true, force: true })
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test("#given ulw loop is awaiting verification #when oracle metadata prompt is missing #then oracle session fallback is stored", async () => {
|
|
|
|
|
const directory = join(tmpdir(), `tool-after-ulw-fallback-${Date.now()}`)
|
|
|
|
|
mkdirSync(directory, { recursive: true })
|
|
|
|
|
writeState(directory, {
|
|
|
|
|
active: true,
|
|
|
|
|
iteration: 3,
|
|
|
|
|
completion_promise: ULTRAWORK_VERIFICATION_PROMISE,
|
|
|
|
|
initial_completion_promise: "DONE",
|
|
|
|
|
started_at: new Date().toISOString(),
|
|
|
|
|
prompt: "Ship feature",
|
|
|
|
|
session_id: "ses-main",
|
|
|
|
|
ultrawork: true,
|
|
|
|
|
verification_pending: true,
|
|
|
|
|
})
|
2026-03-06 22:37:41 +09:00
|
|
|
|
|
|
|
|
const handler = createToolExecuteAfterHandler({
|
|
|
|
|
ctx: createCtx(directory) as unknown as Parameters<typeof createToolExecuteAfterHandler>[0]["ctx"],
|
|
|
|
|
hooks: {} as Parameters<typeof createToolExecuteAfterHandler>[0]["hooks"],
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
await handler(
|
|
|
|
|
{ tool: "task", sessionID: "ses-main", callID: "call-1" },
|
|
|
|
|
{
|
|
|
|
|
title: "oracle task",
|
|
|
|
|
output: "done",
|
|
|
|
|
metadata: {
|
|
|
|
|
agent: "oracle",
|
2026-03-17 16:20:27 +09:00
|
|
|
sessionId: "ses-oracle-fallback",
|
|
|
|
|
sync: true,
|
2026-03-06 22:37:41 +09:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
2026-03-17 16:20:27 +09:00
|
|
|
expect(readState(directory)?.verification_session_id).toBe("ses-oracle-fallback")
|
2026-03-06 22:37:41 +09:00
|
|
|
|
|
|
|
|
clearState(directory)
|
|
|
|
|
rmSync(directory, { recursive: true, force: true })
|
|
|
|
|
})
|
|
|
|
|
|
2026-03-18 17:45:59 +09:00
|
|
|
test("#given ulw loop is awaiting verification #when oracle metadata uses sessionID #then oracle session id is stored", async () => {
|
|
|
|
|
const directory = join(tmpdir(), `tool-after-ulw-sessionid-${Date.now()}`)
|
|
|
|
|
mkdirSync(directory, { recursive: true })
|
|
|
|
|
writeState(directory, {
|
|
|
|
|
active: true,
|
|
|
|
|
iteration: 3,
|
|
|
|
|
completion_promise: ULTRAWORK_VERIFICATION_PROMISE,
|
|
|
|
|
initial_completion_promise: "DONE",
|
|
|
|
|
started_at: new Date().toISOString(),
|
|
|
|
|
prompt: "Ship feature",
|
|
|
|
|
session_id: "ses-main",
|
|
|
|
|
ultrawork: true,
|
|
|
|
|
verification_pending: true,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const handler = createToolExecuteAfterHandler({
|
|
|
|
|
ctx: createCtx(directory) as unknown as Parameters<typeof createToolExecuteAfterHandler>[0]["ctx"],
|
|
|
|
|
hooks: {} as Parameters<typeof createToolExecuteAfterHandler>[0]["hooks"],
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
await handler(
|
|
|
|
|
{ tool: "task", sessionID: "ses-main", callID: "call-1" },
|
|
|
|
|
{
|
|
|
|
|
title: "oracle task",
|
|
|
|
|
output: "done",
|
|
|
|
|
metadata: {
|
|
|
|
|
agent: "oracle",
|
|
|
|
|
sessionID: "ses-oracle-alt",
|
|
|
|
|
sync: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
expect(readState(directory)?.verification_session_id).toBe("ses-oracle-alt")
|
|
|
|
|
|
|
|
|
|
clearState(directory)
|
|
|
|
|
rmSync(directory, { recursive: true, force: true })
|
|
|
|
|
})
|
|
|
|
|
|
2026-03-06 22:37:41 +09:00
|
|
|
test("#given newer oracle attempt exists #when older oracle task finishes #then old session does not overwrite active verification", async () => {
|
|
|
|
|
const directory = join(tmpdir(), `tool-race-ulw-${Date.now()}`)
|
|
|
|
|
mkdirSync(directory, { recursive: true })
|
|
|
|
|
writeState(directory, {
|
|
|
|
|
active: true,
|
|
|
|
|
iteration: 3,
|
|
|
|
|
completion_promise: ULTRAWORK_VERIFICATION_PROMISE,
|
|
|
|
|
initial_completion_promise: "DONE",
|
|
|
|
|
started_at: new Date().toISOString(),
|
|
|
|
|
prompt: "Ship feature",
|
|
|
|
|
session_id: "ses-main",
|
|
|
|
|
ultrawork: true,
|
|
|
|
|
verification_pending: true,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const beforeHandler = createToolExecuteBeforeHandler({
|
|
|
|
|
ctx: createCtx(directory) as unknown as Parameters<typeof createToolExecuteBeforeHandler>[0]["ctx"],
|
|
|
|
|
hooks: {} as Parameters<typeof createToolExecuteBeforeHandler>[0]["hooks"],
|
|
|
|
|
})
|
|
|
|
|
const afterHandler = createToolExecuteAfterHandler({
|
|
|
|
|
ctx: createCtx(directory) as unknown as Parameters<typeof createToolExecuteAfterHandler>[0]["ctx"],
|
|
|
|
|
hooks: {} as Parameters<typeof createToolExecuteAfterHandler>[0]["hooks"],
|
|
|
|
|
})
|
|
|
|
|
|
2026-03-17 16:20:27 +09:00
|
|
|
const firstOutput = { args: createOracleTaskArgs("Check it") }
|
2026-03-06 22:37:41 +09:00
|
|
|
await beforeHandler({ tool: "task", sessionID: "ses-main", callID: "call-1" }, firstOutput)
|
|
|
|
|
const firstAttemptId = readState(directory)?.verification_attempt_id
|
|
|
|
|
|
2026-03-17 16:20:27 +09:00
|
|
|
const secondOutput = { args: createOracleTaskArgs("Check it again") }
|
2026-03-06 22:37:41 +09:00
|
|
|
await beforeHandler({ tool: "task", sessionID: "ses-main", callID: "call-2" }, secondOutput)
|
|
|
|
|
const secondAttemptId = readState(directory)?.verification_attempt_id
|
|
|
|
|
|
|
|
|
|
expect(firstAttemptId).toBeTruthy()
|
|
|
|
|
expect(secondAttemptId).toBeTruthy()
|
|
|
|
|
expect(secondAttemptId).not.toBe(firstAttemptId)
|
|
|
|
|
|
|
|
|
|
await afterHandler(
|
|
|
|
|
{ tool: "task", sessionID: "ses-main", callID: "call-1" },
|
|
|
|
|
{
|
|
|
|
|
title: "oracle task",
|
|
|
|
|
output: "done",
|
|
|
|
|
metadata: {
|
|
|
|
|
agent: "oracle",
|
|
|
|
|
prompt: String(firstOutput.args.prompt),
|
|
|
|
|
sessionId: "ses-oracle-old",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
expect(readState(directory)?.verification_session_id).toBeUndefined()
|
|
|
|
|
|
|
|
|
|
await afterHandler(
|
|
|
|
|
{ tool: "task", sessionID: "ses-main", callID: "call-2" },
|
|
|
|
|
{
|
|
|
|
|
title: "oracle task",
|
|
|
|
|
output: "done",
|
|
|
|
|
metadata: {
|
|
|
|
|
agent: "oracle",
|
|
|
|
|
prompt: String(secondOutput.args.prompt),
|
|
|
|
|
sessionId: "ses-oracle-new",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
expect(readState(directory)?.verification_session_id).toBe("ses-oracle-new")
|
|
|
|
|
|
|
|
|
|
clearState(directory)
|
|
|
|
|
rmSync(directory, { recursive: true, force: true })
|
|
|
|
|
})
|
2026-03-06 22:00:21 +09:00
|
|
|
})
|