fix(ralph-loop): harden oracle verification flow

Capture oracle verification sessions more reliably and accept parent-session VERIFIED evidence so ULW loops do not retry after successful review.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-03-18 17:45:59 +09:00
parent 23c0ff60f2
commit ce8957e1e1
6 changed files with 95 additions and 14 deletions
+14 -3
View File
@@ -6,6 +6,17 @@ import { readState, writeState } from "../hooks/ralph-loop/storage"
const VERIFICATION_ATTEMPT_PATTERN = /<ulw_verification_attempt_id>(.*?)<\/ulw_verification_attempt_id>/i
function getMetadataString(metadata: Record<string, unknown> | undefined, keys: string[]): string | undefined {
for (const key of keys) {
const value = metadata?.[key]
if (typeof value === "string") {
return value
}
}
return undefined
}
function getPluginDirectory(ctx: PluginContext): string | null {
if (typeof ctx === "object" && ctx !== null && "directory" in ctx && typeof ctx.directory === "string") {
return ctx.directory
@@ -43,9 +54,9 @@ export function createToolExecuteAfterHandler(args: {
if (input.tool === "task") {
const directory = getPluginDirectory(ctx)
const sessionId = typeof output.metadata?.sessionId === "string" ? output.metadata.sessionId : undefined
const agent = typeof output.metadata?.agent === "string" ? output.metadata.agent : undefined
const prompt = typeof output.metadata?.prompt === "string" ? output.metadata.prompt : undefined
const sessionId = getMetadataString(output.metadata, ["sessionId", "sessionID", "session_id"])
const agent = getMetadataString(output.metadata, ["agent"])
const prompt = getMetadataString(output.metadata, ["prompt"])
const verificationAttemptId = prompt?.match(VERIFICATION_ATTEMPT_PATTERN)?.[1]?.trim()
const loopState = directory ? readState(directory) : null
const isVerificationContext =
+25 -1
View File
@@ -20,6 +20,26 @@ export function createToolExecuteBeforeHandler(args: {
) => Promise<void> {
const { ctx, hooks } = args
function buildUltraworkOracleVerificationPrompt(prompt: string, originalTask: string, verificationAttemptId: string): string {
const verificationPrompt = [
"You are verifying the active ULTRAWORK loop result for this session.",
"",
"Original task:",
originalTask,
"",
"Review the work skeptically and critically.",
"Assume it may be incomplete, misleading, or subtly broken until the evidence proves otherwise.",
"Look for missing scope, weak verification, process violations, hidden regressions, and any reason the task should NOT be considered complete.",
"",
`If the work is fully complete, end your response with <promise>${ULTRAWORK_VERIFICATION_PROMISE}</promise>.`,
"If the work is not complete, explain the blocking issues clearly and DO NOT emit that promise.",
"",
`<ulw_verification_attempt_id>${verificationAttemptId}</ulw_verification_attempt_id>`,
].join("\n")
return `${prompt ? `${prompt}\n\n` : ""}${verificationPrompt}`
}
return async (input, output): Promise<void> => {
await hooks.writeExistingFileGuard?.["tool.execute.before"]?.(input, output)
await hooks.questionLabelTruncator?.["tool.execute.before"]?.(input, output)
@@ -91,7 +111,11 @@ export function createToolExecuteBeforeHandler(args: {
verification_session_id: undefined,
})
argsObject.run_in_background = false
argsObject.prompt = `${prompt ? `${prompt}\n\n` : ""}You are verifying the active ULTRAWORK loop result for this session. Review whether the original task is truly complete: ${loopState.prompt}\n\nIf the work is fully complete, end your response with <promise>${ULTRAWORK_VERIFICATION_PROMISE}</promise>. If the work is not complete, explain the blocking issues clearly and DO NOT emit that promise.\n\n<ulw_verification_attempt_id>${verificationAttemptId}</ulw_verification_attempt_id>`
argsObject.prompt = buildUltraworkOracleVerificationPrompt(
prompt,
loopState.prompt,
verificationAttemptId,
)
}
}
@@ -65,7 +65,9 @@ describe("tool.execute.before ultrawork oracle verification", () => {
expect(readState(directory)?.verification_attempt_id).toBeTruthy()
expect(output.args.run_in_background).toBe(false)
expect(output.args.prompt).toContain("Original task:")
expect(output.args.prompt).toContain("Ship feature")
expect(output.args.prompt).toContain("Review the work skeptically and critically")
expect(output.args.prompt).toContain(`<promise>${ULTRAWORK_VERIFICATION_PROMISE}</promise>`)
clearState(directory)
@@ -171,6 +173,45 @@ describe("tool.execute.before ultrawork oracle verification", () => {
rmSync(directory, { recursive: true, force: true })
})
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 })
})
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 })