2026-03-31 00:28:15 +08:00
import fs from "node:fs" ;
import path from "node:path" ;
import test from "node:test" ;
import assert from "node:assert/strict" ;
import { spawn } from "node:child_process" ;
2026-04-01 03:33:32 +08:00
import { fileURLToPath } from "node:url" ;
2026-03-31 00:28:15 +08:00
import { buildEnv , installFakeCodex } from "./fake-codex-fixture.mjs" ;
import { initGitRepo , makeTempDir , run } from "./helpers.mjs" ;
import { loadBrokerSession } from "../plugins/codex/scripts/lib/broker-lifecycle.mjs" ;
import { resolveStateDir } from "../plugins/codex/scripts/lib/state.mjs" ;
2026-04-01 03:40:08 +08:00
const ROOT = path . resolve ( path . dirname ( fileURLToPath ( import . meta . url ) ) , ".." ) ;
2026-03-31 00:28:15 +08:00
const PLUGIN _ROOT = path . join ( ROOT , "plugins" , "codex" ) ;
const SCRIPT = path . join ( PLUGIN _ROOT , "scripts" , "codex-companion.mjs" ) ;
const STOP _HOOK = path . join ( PLUGIN _ROOT , "scripts" , "stop-review-gate-hook.mjs" ) ;
const SESSION _HOOK = path . join ( PLUGIN _ROOT , "scripts" , "session-lifecycle-hook.mjs" ) ;
async function waitFor ( predicate , { timeoutMs = 5000 , intervalMs = 50 } = { } ) {
const start = Date . now ( ) ;
while ( Date . now ( ) - start < timeoutMs ) {
const value = await predicate ( ) ;
if ( value ) {
return value ;
}
await new Promise ( ( resolve ) => setTimeout ( resolve , intervalMs ) ) ;
}
throw new Error ( "Timed out waiting for condition." ) ;
}
test ( "setup reports ready when fake codex is installed and authenticated" , ( ) => {
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
const result = run ( "node" , [ SCRIPT , "setup" , "--json" ] , {
cwd : ROOT ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 ) ;
const payload = JSON . parse ( result . stdout ) ;
assert . equal ( payload . ready , true ) ;
assert . match ( payload . codex . detail , /advanced runtime available/ ) ;
assert . equal ( payload . sessionRuntime . mode , "direct" ) ;
} ) ;
test ( "setup is ready without npm when Codex is already installed and authenticated" , ( ) => {
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
fs . symlinkSync ( process . execPath , path . join ( binDir , "node" ) ) ;
const result = run ( "node" , [ SCRIPT , "setup" , "--json" ] , {
cwd : ROOT ,
env : {
... process . env ,
PATH : binDir
}
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
const payload = JSON . parse ( result . stdout ) ;
assert . equal ( payload . ready , true ) ;
assert . equal ( payload . npm . available , false ) ;
assert . equal ( payload . codex . available , true ) ;
assert . equal ( payload . auth . loggedIn , true ) ;
} ) ;
test ( "review renders a no-findings result from app-server review/start" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . mkdirSync ( path . join ( repo , "src" ) ) ;
fs . writeFileSync ( path . join ( repo , "src" , "app.js" ) , "export const value = 1;\n" ) ;
run ( "git" , [ "add" , "src/app.js" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "src" , "app.js" ) , "export const value = 2;\n" ) ;
const result = run ( "node" , [ SCRIPT , "review" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 ) ;
assert . match ( result . stdout , /Reviewed uncommitted changes/ ) ;
assert . match ( result . stdout , /No material issues found/ ) ;
} ) ;
test ( "review accepts the quoted raw argument style for built-in base-branch review" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . mkdirSync ( path . join ( repo , "src" ) ) ;
fs . writeFileSync ( path . join ( repo , "src" , "app.js" ) , "export const value = 1;\n" ) ;
run ( "git" , [ "add" , "src/app.js" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "src" , "app.js" ) , "export const value = 2;\n" ) ;
const result = run ( "node" , [ SCRIPT , "review" , "--base main" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 ) ;
assert . match ( result . stdout , /Reviewed changes against main/ ) ;
assert . match ( result . stdout , /No material issues found/ ) ;
} ) ;
test ( "adversarial review renders structured findings over app-server turn/start" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . mkdirSync ( path . join ( repo , "src" ) ) ;
fs . writeFileSync ( path . join ( repo , "src" , "app.js" ) , "export const value = items[0];\n" ) ;
run ( "git" , [ "add" , "src/app.js" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "src" , "app.js" ) , "export const value = items[0].id;\n" ) ;
const result = run ( "node" , [ SCRIPT , "adversarial-review" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 ) ;
assert . match ( result . stdout , /Missing empty-state guard/ ) ;
} ) ;
test ( "adversarial review accepts the same base-branch targeting as review" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . mkdirSync ( path . join ( repo , "src" ) ) ;
fs . writeFileSync ( path . join ( repo , "src" , "app.js" ) , "export const value = items[0];\n" ) ;
run ( "git" , [ "add" , "src/app.js" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "src" , "app.js" ) , "export const value = items[0].id;\n" ) ;
const result = run ( "node" , [ SCRIPT , "adversarial-review" , "--base" , "main" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . match ( result . stdout , /Branch review against main|against main/i ) ;
assert . match ( result . stdout , /Missing empty-state guard/ ) ;
} ) ;
test ( "review includes reasoning output when the app server returns it" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "with-reasoning" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello again\n" ) ;
const result = run ( "node" , [ SCRIPT , "review" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . match ( result . stdout , /Reasoning:/ ) ;
assert . match ( result . stdout , /Reviewed the changed files and checked the likely regression paths first|Reviewed the changed files and checked the likely regression paths/i ) ;
} ) ;
test ( "review logs reasoning summaries and review output to the job log" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "with-reasoning" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello again\n" ) ;
const result = run ( "node" , [ SCRIPT , "review" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
const stateDir = resolveStateDir ( repo ) ;
const state = JSON . parse ( fs . readFileSync ( path . join ( stateDir , "state.json" ) , "utf8" ) ) ;
const log = fs . readFileSync ( state . jobs [ 0 ] . logFile , "utf8" ) ;
assert . match ( log , /Reasoning summary/ ) ;
assert . match ( log , /Reviewed the changed files and checked the likely regression paths/ ) ;
assert . match ( log , /Review output/ ) ;
assert . match ( log , /Reviewed uncommitted changes\./ ) ;
} ) ;
test ( "task --resume-last resumes the latest persisted task thread" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const firstRun = run ( "node" , [ SCRIPT , "task" , "initial task" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( firstRun . status , 0 , firstRun . stderr ) ;
const result = run ( "node" , [ SCRIPT , "task" , "--resume-last" , "follow up" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal ( result . stdout , "Resumed the prior run.\nFollow-up prompt accepted.\n" ) ;
} ) ;
test ( "task-resume-candidate returns the latest rescue thread from the current session" , ( ) => {
const workspace = makeTempDir ( ) ;
const stateDir = resolveStateDir ( workspace ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : { stopReviewGate : false } ,
jobs : [
{
id : "task-current" ,
status : "completed" ,
title : "Codex Task" ,
jobClass : "task" ,
sessionId : "sess-current" ,
threadId : "thr_current" ,
summary : "Investigate the flaky test" ,
updatedAt : "2026-03-24T20:00:00.000Z"
} ,
{
id : "task-other-session" ,
status : "completed" ,
title : "Codex Task" ,
jobClass : "task" ,
sessionId : "sess-other" ,
threadId : "thr_other" ,
summary : "Old rescue run" ,
updatedAt : "2026-03-24T20:05:00.000Z"
} ,
{
id : "review-current" ,
status : "completed" ,
title : "Codex Review" ,
jobClass : "review" ,
sessionId : "sess-current" ,
threadId : "thr_review" ,
summary : "Review main...HEAD" ,
updatedAt : "2026-03-24T20:10:00.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const result = run ( "node" , [ SCRIPT , "task-resume-candidate" , "--json" ] , {
cwd : workspace ,
env : {
... process . env ,
CODEX _COMPANION _SESSION _ID : "sess-current"
}
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
const payload = JSON . parse ( result . stdout ) ;
assert . equal ( payload . available , true ) ;
assert . equal ( payload . sessionId , "sess-current" ) ;
assert . equal ( payload . candidate . id , "task-current" ) ;
assert . equal ( payload . candidate . threadId , "thr_current" ) ;
} ) ;
test ( "session start hook exports the Claude session id and plugin data dir for later commands" , ( ) => {
const repo = makeTempDir ( ) ;
const envFile = path . join ( makeTempDir ( ) , "claude-env.sh" ) ;
fs . writeFileSync ( envFile , "" , "utf8" ) ;
const pluginDataDir = makeTempDir ( ) ;
const result = run ( "node" , [ SESSION _HOOK , "SessionStart" ] , {
cwd : repo ,
env : {
... process . env ,
CLAUDE _ENV _FILE : envFile ,
CLAUDE _PLUGIN _DATA : pluginDataDir
} ,
input : JSON . stringify ( {
hook _event _name : "SessionStart" ,
session _id : "sess-current" ,
cwd : repo
} )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal (
fs . readFileSync ( envFile , "utf8" ) ,
` export CODEX_COMPANION_SESSION_ID='sess-current' \n export CLAUDE_PLUGIN_DATA=' ${ pluginDataDir } ' \n `
) ;
} ) ;
test ( "write task output focuses on the Codex result without generic follow-up hints" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "task" , "--write" , "fix the failing test" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal ( result . stdout , "Handled the requested task.\nTask prompt accepted.\n" ) ;
} ) ;
test ( "task --resume acts like --resume-last without leaking the flag into the prompt" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
const statePath = path . join ( binDir , "fake-codex-state.json" ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const firstRun = run ( "node" , [ SCRIPT , "task" , "initial task" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( firstRun . status , 0 , firstRun . stderr ) ;
const result = run ( "node" , [ SCRIPT , "task" , "--resume" , "follow up" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
const fakeState = JSON . parse ( fs . readFileSync ( statePath , "utf8" ) ) ;
assert . equal ( fakeState . lastTurnStart . threadId , "thr_1" ) ;
assert . equal ( fakeState . lastTurnStart . prompt , "follow up" ) ;
} ) ;
test ( "task --fresh is treated as routing control and does not leak into the prompt" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
const statePath = path . join ( binDir , "fake-codex-state.json" ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "task" , "--fresh" , "diagnose the flaky test" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
const fakeState = JSON . parse ( fs . readFileSync ( statePath , "utf8" ) ) ;
assert . equal ( fakeState . lastTurnStart . prompt , "diagnose the flaky test" ) ;
} ) ;
test ( "task forwards model selection and reasoning effort to app-server turn/start" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
const statePath = path . join ( binDir , "fake-codex-state.json" ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "task" , "--model" , "spark" , "--effort" , "low" , "diagnose the failing test" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
const fakeState = JSON . parse ( fs . readFileSync ( statePath , "utf8" ) ) ;
assert . equal ( fakeState . lastTurnStart . model , "gpt-5.3-codex-spark" ) ;
assert . equal ( fakeState . lastTurnStart . effort , "low" ) ;
} ) ;
test ( "task logs reasoning summaries and assistant messages to the job log" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "with-reasoning" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "task" , "investigate the failing test" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
const stateDir = resolveStateDir ( repo ) ;
const state = JSON . parse ( fs . readFileSync ( path . join ( stateDir , "state.json" ) , "utf8" ) ) ;
const log = fs . readFileSync ( state . jobs [ 0 ] . logFile , "utf8" ) ;
assert . match ( log , /Reasoning summary/ ) ;
assert . match ( log , /Inspected the prompt, gathered evidence, and checked the highest-risk paths first/ ) ;
assert . match ( log , /Assistant message/ ) ;
assert . match ( log , /Handled the requested task/ ) ;
} ) ;
test ( "task logs subagent reasoning and messages with a subagent prefix" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "with-subagent" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "task" , "challenge the current design" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
const stateDir = resolveStateDir ( repo ) ;
const state = JSON . parse ( fs . readFileSync ( path . join ( stateDir , "state.json" ) , "utf8" ) ) ;
const log = fs . readFileSync ( state . jobs [ 0 ] . logFile , "utf8" ) ;
assert . match ( log , /Starting subagent design-challenger via collaboration tool: wait\./ ) ;
assert . match ( log , /Subagent design-challenger reasoning:/ ) ;
assert . match ( log , /Questioned the retry strategy and the cache invalidation boundaries\./ ) ;
assert . match ( log , /Subagent design-challenger:/ ) ;
assert . match (
log ,
/The design assumes retries are harmless, but they can duplicate side effects without stronger idempotency guarantees\./
) ;
} ) ;
test ( "task waits for the main thread to complete before returning the final result" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "with-subagent" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "task" , "challenge the current design" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal ( result . stdout , "Handled the requested task.\nTask prompt accepted.\n" ) ;
} ) ;
test ( "task ignores later subagent messages when choosing the final returned output" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "with-late-subagent-message" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "task" , "challenge the current design" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal ( result . stdout , "Handled the requested task.\nTask prompt accepted.\n" ) ;
} ) ;
test ( "task can finish after subagent work even if the parent turn/completed event is missing" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "with-subagent-no-main-turn-completed" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "task" , "challenge the current design" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal ( result . stdout , "Handled the requested task.\nTask prompt accepted.\n" ) ;
} ) ;
test ( "task using the shared broker still completes when Codex spawns subagents" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "with-subagent" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello again\n" ) ;
const env = buildEnv ( binDir ) ;
const review = run ( "node" , [ SCRIPT , "review" ] , {
cwd : repo ,
env
} ) ;
assert . equal ( review . status , 0 , review . stderr ) ;
if ( ! loadBrokerSession ( repo ) ) {
return ;
}
const result = run ( "node" , [ SCRIPT , "task" , "challenge the current design" ] , {
cwd : repo ,
env
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal ( result . stdout , "Handled the requested task.\nTask prompt accepted.\n" ) ;
} ) ;
test ( "task --background enqueues a detached worker and exposes per-job status" , async ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "slow-task" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const launched = run ( "node" , [ SCRIPT , "task" , "--background" , "--json" , "investigate the failing test" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( launched . status , 0 , launched . stderr ) ;
const launchPayload = JSON . parse ( launched . stdout ) ;
assert . equal ( launchPayload . status , "queued" ) ;
assert . match ( launchPayload . jobId , /^task-/ ) ;
const waitedStatus = run (
"node" ,
2026-04-01 04:04:24 +08:00
[ SCRIPT , "status" , launchPayload . jobId , "--wait" , "--timeout-ms" , "15000" , "--json" ] ,
2026-03-31 00:28:15 +08:00
{
cwd : repo ,
env : buildEnv ( binDir )
}
) ;
assert . equal ( waitedStatus . status , 0 , waitedStatus . stderr ) ;
const waitedPayload = JSON . parse ( waitedStatus . stdout ) ;
assert . equal ( waitedPayload . job . id , launchPayload . jobId ) ;
assert . equal ( waitedPayload . job . status , "completed" ) ;
const resultPayload = await waitFor ( ( ) => {
const result = run ( "node" , [ SCRIPT , "result" , launchPayload . jobId , "--json" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
if ( result . status !== 0 ) {
return null ;
}
return JSON . parse ( result . stdout ) ;
} ) ;
assert . equal ( resultPayload . job . id , launchPayload . jobId ) ;
assert . equal ( resultPayload . job . status , "completed" ) ;
assert . match ( resultPayload . storedJob . rendered , /Handled the requested task/ ) ;
} ) ;
test ( "review rejects focus text because it is native-review only" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello again\n" ) ;
const result = run ( "node" , [ SCRIPT , "review" , "--scope working-tree focus on auth" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status > 0 , true ) ;
assert . match ( result . stderr , /does not support custom focus text/i ) ;
assert . match ( result . stderr , /\/codex:adversarial-review focus on auth/i ) ;
} ) ;
test ( "review rejects staged-only scope because it is native-review only" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello again\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "review" , "--scope" , "staged" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status > 0 , true ) ;
assert . match ( result . stderr , /Unsupported review scope "staged"/i ) ;
assert . match ( result . stderr , /Use one of: auto, working-tree, branch, or pass --base <ref>/i ) ;
} ) ;
test ( "adversarial review rejects staged-only scope to match review target selection" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello again\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
const result = run ( "node" , [ SCRIPT , "adversarial-review" , "--scope" , "staged" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status > 0 , true ) ;
assert . match ( result . stderr , /Unsupported review scope "staged"/i ) ;
assert . match ( result . stderr , /Use one of: auto, working-tree, branch, or pass --base <ref>/i ) ;
} ) ;
test ( "review accepts --background while still running as a tracked review job" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello again\n" ) ;
const launched = run ( "node" , [ SCRIPT , "review" , "--background" , "--json" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( launched . status , 0 , launched . stderr ) ;
const launchPayload = JSON . parse ( launched . stdout ) ;
assert . equal ( launchPayload . review , "Review" ) ;
assert . match ( launchPayload . codex . stdout , /No material issues found/ ) ;
const status = run ( "node" , [ SCRIPT , "status" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( status . status , 0 , status . stderr ) ;
assert . match ( status . stdout , /# Codex Status/ ) ;
assert . match ( status . stdout , /Codex Review/ ) ;
assert . match ( status . stdout , /completed/ ) ;
} ) ;
test ( "status shows phases, hints, and the latest finished job" , ( ) => {
const workspace = makeTempDir ( ) ;
const stateDir = resolveStateDir ( workspace ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
const logFile = path . join ( jobsDir , "review-live.log" ) ;
fs . writeFileSync (
logFile ,
[
"[2026-03-18T15:30:00.000Z] Starting Codex Review." ,
"[2026-03-18T15:30:01.000Z] Thread ready (thr_1)." ,
"[2026-03-18T15:30:02.000Z] Turn started (turn_1)." ,
"[2026-03-18T15:30:03.000Z] Reviewer started: current changes"
] . join ( "\n" ) ,
"utf8"
) ;
const finishedJobFile = path . join ( jobsDir , "review-done.json" ) ;
fs . writeFileSync (
finishedJobFile ,
JSON . stringify (
{
id : "review-done" ,
status : "completed" ,
title : "Codex Review" ,
rendered : "# Codex Review\n\nReviewed uncommitted changes.\nNo material issues found.\n"
} ,
null ,
2
) ,
"utf8"
) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : { stopReviewGate : false } ,
jobs : [
{
id : "review-live" ,
kind : "review" ,
kindLabel : "review" ,
status : "running" ,
title : "Codex Review" ,
jobClass : "review" ,
phase : "reviewing" ,
threadId : "thr_1" ,
summary : "Review working tree diff" ,
logFile ,
createdAt : "2026-03-18T15:30:00.000Z" ,
updatedAt : "2026-03-18T15:30:03.000Z"
} ,
{
id : "review-done" ,
status : "completed" ,
title : "Codex Review" ,
jobClass : "review" ,
threadId : "thr_done" ,
summary : "Review main...HEAD" ,
createdAt : "2026-03-18T15:10:00.000Z" ,
startedAt : "2026-03-18T15:10:05.000Z" ,
completedAt : "2026-03-18T15:11:10.000Z" ,
updatedAt : "2026-03-18T15:11:10.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const result = run ( "node" , [ SCRIPT , "status" ] , {
cwd : workspace
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . match ( result . stdout , /Active jobs:/ ) ;
assert . match ( result . stdout , /\| Job \| Kind \| Status \| Phase \| Elapsed \| Codex Session ID \| Summary \| Actions \|/ ) ;
assert . match ( result . stdout , /\| review-live \| review \| running \| reviewing \| .* \| thr_1 \| Review working tree diff \|/ ) ;
assert . match ( result . stdout , /`\/codex:status review-live`<br>`\/codex:cancel review-live`/ ) ;
assert . match ( result . stdout , /Live details:/ ) ;
assert . match ( result . stdout , /Latest finished:/ ) ;
assert . match ( result . stdout , /Progress:/ ) ;
assert . match ( result . stdout , /Session runtime: direct startup/ ) ;
assert . match ( result . stdout , /Phase: reviewing/ ) ;
assert . match ( result . stdout , /Codex session ID: thr_1/ ) ;
assert . match ( result . stdout , /Resume in Codex: codex resume thr_1/ ) ;
assert . match ( result . stdout , /Thread ready \(thr_1\)\./ ) ;
assert . match ( result . stdout , /Reviewer started: current changes/ ) ;
assert . match ( result . stdout , /Duration: 1m 5s/ ) ;
assert . match ( result . stdout , /Codex session ID: thr_done/ ) ;
assert . match ( result . stdout , /Resume in Codex: codex resume thr_done/ ) ;
} ) ;
test ( "status without a job id only shows jobs from the current Claude session" , ( ) => {
const workspace = makeTempDir ( ) ;
const stateDir = resolveStateDir ( workspace ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
const currentLog = path . join ( jobsDir , "review-current.log" ) ;
const otherLog = path . join ( jobsDir , "review-other.log" ) ;
fs . writeFileSync ( currentLog , "[2026-03-18T15:30:00.000Z] Reviewer started: current changes\n" , "utf8" ) ;
fs . writeFileSync ( otherLog , "[2026-03-18T15:31:00.000Z] Reviewer started: old changes\n" , "utf8" ) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : { stopReviewGate : false } ,
jobs : [
{
id : "review-current" ,
kind : "review" ,
kindLabel : "review" ,
status : "running" ,
title : "Codex Review" ,
jobClass : "review" ,
phase : "reviewing" ,
sessionId : "sess-current" ,
threadId : "thr_current" ,
summary : "Current session review" ,
logFile : currentLog ,
createdAt : "2026-03-18T15:30:00.000Z" ,
updatedAt : "2026-03-18T15:30:00.000Z"
} ,
{
id : "review-other" ,
kind : "review" ,
kindLabel : "review" ,
status : "completed" ,
title : "Codex Review" ,
jobClass : "review" ,
sessionId : "sess-other" ,
threadId : "thr_other" ,
summary : "Previous session review" ,
createdAt : "2026-03-18T15:20:00.000Z" ,
startedAt : "2026-03-18T15:20:05.000Z" ,
completedAt : "2026-03-18T15:21:00.000Z" ,
updatedAt : "2026-03-18T15:21:00.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const result = run ( "node" , [ SCRIPT , "status" ] , {
cwd : workspace ,
env : {
... process . env ,
CODEX _COMPANION _SESSION _ID : "sess-current"
}
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . deepEqual (
[ ... new Set ( result . stdout . match ( /review-(?:current|other)/g ) ? ? [ ] ) ] ,
[ "review-current" ]
) ;
} ) ;
test ( "status preserves adversarial review kind labels" , ( ) => {
const workspace = makeTempDir ( ) ;
const stateDir = resolveStateDir ( workspace ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
const logFile = path . join ( jobsDir , "review-adv.log" ) ;
fs . writeFileSync ( logFile , "[2026-03-18T15:30:00.000Z] Reviewer started: adversarial review\n" , "utf8" ) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : { stopReviewGate : false } ,
jobs : [
{
id : "review-adv-live" ,
kind : "adversarial-review" ,
status : "running" ,
title : "Codex Adversarial Review" ,
jobClass : "review" ,
phase : "reviewing" ,
threadId : "thr_adv_live" ,
summary : "Adversarial review current changes" ,
logFile ,
createdAt : "2026-03-18T15:30:00.000Z" ,
updatedAt : "2026-03-18T15:30:00.000Z"
} ,
{
id : "review-adv" ,
kind : "adversarial-review" ,
status : "completed" ,
title : "Codex Adversarial Review" ,
jobClass : "review" ,
threadId : "thr_adv_done" ,
summary : "Adversarial review working tree diff" ,
createdAt : "2026-03-18T15:10:00.000Z" ,
startedAt : "2026-03-18T15:10:05.000Z" ,
completedAt : "2026-03-18T15:11:10.000Z" ,
updatedAt : "2026-03-18T15:11:10.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const result = run ( "node" , [ SCRIPT , "status" ] , {
cwd : workspace
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . match ( result . stdout , /\| review-adv-live \| adversarial-review \| running \| reviewing \|/ ) ;
assert . match ( result . stdout , /- review-adv \| completed \| adversarial-review \| Codex Adversarial Review/ ) ;
assert . match ( result . stdout , /Codex session ID: thr_adv_live/ ) ;
assert . match ( result . stdout , /Codex session ID: thr_adv_done/ ) ;
} ) ;
test ( "status --wait times out cleanly when a job is still active" , ( ) => {
const workspace = makeTempDir ( ) ;
const stateDir = resolveStateDir ( workspace ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
const logFile = path . join ( jobsDir , "task-live.log" ) ;
fs . writeFileSync ( logFile , "[2026-03-18T15:30:00.000Z] Starting Codex Task.\n" , "utf8" ) ;
fs . writeFileSync (
path . join ( jobsDir , "task-live.json" ) ,
JSON . stringify (
{
id : "task-live" ,
status : "running" ,
title : "Codex Task" ,
logFile
} ,
null ,
2
) ,
"utf8"
) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : { stopReviewGate : false } ,
jobs : [
{
id : "task-live" ,
status : "running" ,
title : "Codex Task" ,
jobClass : "task" ,
summary : "Investigate flaky test" ,
logFile ,
createdAt : "2026-03-18T15:30:00.000Z" ,
startedAt : "2026-03-18T15:30:01.000Z" ,
updatedAt : "2026-03-18T15:30:02.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const result = run ( "node" , [ SCRIPT , "status" , "task-live" , "--wait" , "--timeout-ms" , "25" , "--json" ] , {
cwd : workspace
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
const payload = JSON . parse ( result . stdout ) ;
assert . equal ( payload . job . id , "task-live" ) ;
assert . equal ( payload . job . status , "running" ) ;
assert . equal ( payload . waitTimedOut , true ) ;
} ) ;
test ( "result returns the stored output for the latest finished job by default" , ( ) => {
const workspace = makeTempDir ( ) ;
const stateDir = resolveStateDir ( workspace ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
fs . writeFileSync (
path . join ( jobsDir , "review-finished.json" ) ,
JSON . stringify (
{
id : "review-finished" ,
status : "completed" ,
title : "Codex Review" ,
rendered : "# Codex Review\n\nReviewed uncommitted changes.\nNo material issues found.\n" ,
result : {
codex : {
stdout : "Reviewed uncommitted changes.\nNo material issues found."
}
} ,
threadId : "thr_review_finished"
} ,
null ,
2
) ,
"utf8"
) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : { stopReviewGate : false } ,
jobs : [
{
id : "review-finished" ,
status : "completed" ,
title : "Codex Review" ,
jobClass : "review" ,
threadId : "thr_review_finished" ,
summary : "Review working tree diff" ,
createdAt : "2026-03-18T15:00:00.000Z" ,
updatedAt : "2026-03-18T15:01:00.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const result = run ( "node" , [ SCRIPT , "result" ] , {
cwd : workspace
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal (
result . stdout ,
"Reviewed uncommitted changes.\nNo material issues found.\n\nCodex session ID: thr_review_finished\nResume in Codex: codex resume thr_review_finished\n"
) ;
} ) ;
test ( "result without a job id prefers the latest finished job from the current Claude session" , ( ) => {
const workspace = makeTempDir ( ) ;
const stateDir = resolveStateDir ( workspace ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
fs . writeFileSync (
path . join ( jobsDir , "review-current.json" ) ,
JSON . stringify (
{
id : "review-current" ,
status : "completed" ,
title : "Codex Review" ,
threadId : "thr_current" ,
result : {
codex : {
stdout : "Current session output."
}
}
} ,
null ,
2
) ,
"utf8"
) ;
fs . writeFileSync (
path . join ( jobsDir , "review-other.json" ) ,
JSON . stringify (
{
id : "review-other" ,
status : "completed" ,
title : "Codex Review" ,
threadId : "thr_other" ,
result : {
codex : {
stdout : "Old session output."
}
}
} ,
null ,
2
) ,
"utf8"
) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : { stopReviewGate : false } ,
jobs : [
{
id : "review-current" ,
status : "completed" ,
title : "Codex Review" ,
jobClass : "review" ,
sessionId : "sess-current" ,
threadId : "thr_current" ,
summary : "Current session review" ,
createdAt : "2026-03-18T15:10:00.000Z" ,
updatedAt : "2026-03-18T15:11:00.000Z"
} ,
{
id : "review-other" ,
status : "completed" ,
title : "Codex Review" ,
jobClass : "review" ,
sessionId : "sess-other" ,
threadId : "thr_other" ,
summary : "Old session review" ,
createdAt : "2026-03-18T15:20:00.000Z" ,
updatedAt : "2026-03-18T15:21:00.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const result = run ( "node" , [ SCRIPT , "result" ] , {
cwd : workspace ,
env : {
... process . env ,
CODEX _COMPANION _SESSION _ID : "sess-current"
}
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal (
result . stdout ,
"Current session output.\n\nCodex session ID: thr_current\nResume in Codex: codex resume thr_current\n"
) ;
} ) ;
test ( "result for a finished write-capable task returns the raw Codex final response" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const taskRun = run ( "node" , [ SCRIPT , "task" , "--write" , "fix the flaky integration test" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( taskRun . status , 0 , taskRun . stderr ) ;
const result = run ( "node" , [ SCRIPT , "result" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . match ( result . stdout , /^Handled the requested task\.\nTask prompt accepted\.\n/ ) ;
assert . match ( result . stdout , /Codex session ID: thr_[a-z0-9]+/i ) ;
assert . match ( result . stdout , /Resume in Codex: codex resume thr_[a-z0-9]+/i ) ;
} ) ;
test ( "cancel stops an active background job and marks it cancelled" , async ( t ) => {
const workspace = makeTempDir ( ) ;
const stateDir = resolveStateDir ( workspace ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
const sleeper = spawn ( process . execPath , [ "-e" , "setInterval(() => {}, 1000)" ] , {
cwd : workspace ,
detached : true ,
stdio : "ignore"
} ) ;
sleeper . unref ( ) ;
t . after ( ( ) => {
try {
process . kill ( - sleeper . pid , "SIGTERM" ) ;
} catch {
try {
process . kill ( sleeper . pid , "SIGTERM" ) ;
} catch {
// Ignore missing process.
}
}
} ) ;
const logFile = path . join ( jobsDir , "task-live.log" ) ;
const jobFile = path . join ( jobsDir , "task-live.json" ) ;
fs . writeFileSync ( logFile , "[2026-03-18T15:30:00.000Z] Starting Codex Task.\n" , "utf8" ) ;
fs . writeFileSync (
jobFile ,
JSON . stringify (
{
id : "task-live" ,
status : "running" ,
title : "Codex Task" ,
logFile
} ,
null ,
2
) ,
"utf8"
) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : { stopReviewGate : false } ,
jobs : [
{
id : "task-live" ,
status : "running" ,
title : "Codex Task" ,
jobClass : "task" ,
summary : "Investigate flaky test" ,
pid : sleeper . pid ,
logFile ,
createdAt : "2026-03-18T15:30:00.000Z" ,
startedAt : "2026-03-18T15:30:01.000Z" ,
updatedAt : "2026-03-18T15:30:02.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const cancelResult = run ( "node" , [ SCRIPT , "cancel" , "task-live" , "--json" ] , {
cwd : workspace
} ) ;
assert . equal ( cancelResult . status , 0 , cancelResult . stderr ) ;
assert . equal ( JSON . parse ( cancelResult . stdout ) . status , "cancelled" ) ;
await waitFor ( ( ) => {
try {
process . kill ( sleeper . pid , 0 ) ;
return false ;
} catch ( error ) {
return error ? . code === "ESRCH" ;
}
} ) ;
const state = JSON . parse ( fs . readFileSync ( path . join ( stateDir , "state.json" ) , "utf8" ) ) ;
const cancelled = state . jobs . find ( ( job ) => job . id === "task-live" ) ;
assert . equal ( cancelled . status , "cancelled" ) ;
assert . equal ( cancelled . pid , null ) ;
const stored = JSON . parse ( fs . readFileSync ( jobFile , "utf8" ) ) ;
assert . equal ( stored . status , "cancelled" ) ;
assert . match ( fs . readFileSync ( logFile , "utf8" ) , /Cancelled by user/ ) ;
} ) ;
test ( "cancel sends turn interrupt to the shared app-server before killing a brokered task" , async ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
const fakeStatePath = path . join ( binDir , "fake-codex-state.json" ) ;
installFakeCodex ( binDir , "interruptible-slow-task" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const env = buildEnv ( binDir ) ;
const launched = run ( "node" , [ SCRIPT , "task" , "--background" , "--json" , "investigate the flaky worker timeout" ] , {
cwd : repo ,
env
} ) ;
assert . equal ( launched . status , 0 , launched . stderr ) ;
const launchPayload = JSON . parse ( launched . stdout ) ;
const jobId = launchPayload . jobId ;
assert . ok ( jobId ) ;
const stateDir = resolveStateDir ( repo ) ;
const runningJob = await waitFor ( ( ) => {
const state = JSON . parse ( fs . readFileSync ( path . join ( stateDir , "state.json" ) , "utf8" ) ) ;
const job = state . jobs . find ( ( candidate ) => candidate . id === jobId ) ;
if ( job ? . status === "running" && job . threadId && job . turnId ) {
return job ;
}
return null ;
2026-04-01 04:04:24 +08:00
} , { timeoutMs : 15000 } ) ;
2026-03-31 00:28:15 +08:00
const cancelResult = run ( "node" , [ SCRIPT , "cancel" , jobId , "--json" ] , {
cwd : repo ,
env
} ) ;
assert . equal ( cancelResult . status , 0 , cancelResult . stderr ) ;
const cancelPayload = JSON . parse ( cancelResult . stdout ) ;
assert . equal ( cancelPayload . status , "cancelled" ) ;
assert . equal ( cancelPayload . turnInterruptAttempted , true ) ;
assert . equal ( cancelPayload . turnInterrupted , true ) ;
await waitFor ( ( ) => {
const fakeState = JSON . parse ( fs . readFileSync ( fakeStatePath , "utf8" ) ) ;
return fakeState . lastInterrupt ? ? null ;
} ) ;
const fakeState = JSON . parse ( fs . readFileSync ( fakeStatePath , "utf8" ) ) ;
assert . deepEqual ( fakeState . lastInterrupt , {
threadId : runningJob . threadId ,
turnId : runningJob . turnId
} ) ;
const cleanup = run ( "node" , [ SESSION _HOOK , "SessionEnd" ] , {
cwd : repo ,
env ,
input : JSON . stringify ( {
hook _event _name : "SessionEnd" ,
cwd : repo
} )
} ) ;
assert . equal ( cleanup . status , 0 , cleanup . stderr ) ;
} ) ;
test ( "session end fully cleans up jobs for the ending session" , async ( t ) => {
const repo = makeTempDir ( ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const stateDir = resolveStateDir ( repo ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
const completedLog = path . join ( jobsDir , "completed.log" ) ;
const runningLog = path . join ( jobsDir , "running.log" ) ;
const otherSessionLog = path . join ( jobsDir , "other.log" ) ;
const completedJobFile = path . join ( jobsDir , "review-completed.json" ) ;
const runningJobFile = path . join ( jobsDir , "review-running.json" ) ;
const otherJobFile = path . join ( jobsDir , "review-other.json" ) ;
fs . writeFileSync ( completedLog , "completed\n" , "utf8" ) ;
fs . writeFileSync ( runningLog , "running\n" , "utf8" ) ;
fs . writeFileSync ( otherSessionLog , "other\n" , "utf8" ) ;
fs . writeFileSync ( completedJobFile , JSON . stringify ( { id : "review-completed" } , null , 2 ) , "utf8" ) ;
fs . writeFileSync ( otherJobFile , JSON . stringify ( { id : "review-other" } , null , 2 ) , "utf8" ) ;
const sleeper = spawn ( process . execPath , [ "-e" , "setInterval(() => {}, 1000)" ] , {
cwd : repo ,
detached : true ,
stdio : "ignore"
} ) ;
sleeper . unref ( ) ;
fs . writeFileSync ( runningJobFile , JSON . stringify ( { id : "review-running" } , null , 2 ) , "utf8" ) ;
t . after ( ( ) => {
try {
process . kill ( - sleeper . pid , "SIGTERM" ) ;
} catch {
try {
process . kill ( sleeper . pid , "SIGTERM" ) ;
} catch {
// Ignore missing process.
}
}
} ) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : { stopReviewGate : false } ,
jobs : [
{
id : "review-completed" ,
status : "completed" ,
title : "Codex Review" ,
sessionId : "sess-current" ,
logFile : completedLog ,
createdAt : "2026-03-18T15:30:00.000Z" ,
updatedAt : "2026-03-18T15:31:00.000Z"
} ,
{
id : "review-running" ,
status : "running" ,
title : "Codex Review" ,
sessionId : "sess-current" ,
pid : sleeper . pid ,
logFile : runningLog ,
createdAt : "2026-03-18T15:32:00.000Z" ,
updatedAt : "2026-03-18T15:33:00.000Z"
} ,
{
id : "review-other" ,
status : "completed" ,
title : "Codex Review" ,
sessionId : "sess-other" ,
logFile : otherSessionLog ,
createdAt : "2026-03-18T15:34:00.000Z" ,
updatedAt : "2026-03-18T15:35:00.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const result = run ( "node" , [ SESSION _HOOK , "SessionEnd" ] , {
cwd : repo ,
env : {
... process . env ,
CODEX _COMPANION _SESSION _ID : "sess-current"
} ,
input : JSON . stringify ( {
hook _event _name : "SessionEnd" ,
session _id : "sess-current" ,
cwd : repo
} )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . equal ( fs . existsSync ( otherSessionLog ) , true ) ;
assert . equal ( fs . existsSync ( otherJobFile ) , true ) ;
assert . deepEqual (
fs . readdirSync ( path . dirname ( otherJobFile ) ) . sort ( ) ,
[ path . basename ( otherJobFile ) , path . basename ( otherSessionLog ) ] . sort ( )
) ;
await waitFor ( ( ) => {
try {
process . kill ( sleeper . pid , 0 ) ;
return false ;
} catch ( error ) {
return error ? . code === "ESRCH" ;
}
} ) ;
const state = JSON . parse ( fs . readFileSync ( path . join ( stateDir , "state.json" ) , "utf8" ) ) ;
assert . deepEqual ( state . jobs . map ( ( job ) => job . id ) , [ "review-other" ] ) ;
const otherJob = state . jobs [ 0 ] ;
assert . equal ( otherJob . logFile , otherSessionLog ) ;
} ) ;
test ( "stop hook runs a stop-time review task and blocks on findings when the review gate is enabled" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
const fakeStatePath = path . join ( binDir , "fake-codex-state.json" ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const setup = run ( "node" , [ SCRIPT , "setup" , "--enable-review-gate" , "--json" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( setup . status , 0 , setup . stderr ) ;
const setupPayload = JSON . parse ( setup . stdout ) ;
assert . equal ( setupPayload . reviewGateEnabled , true ) ;
const taskResult = run ( "node" , [ SCRIPT , "task" , "--write" , "fix the issue" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( taskResult . status , 0 , taskResult . stderr ) ;
const blocked = run ( "node" , [ STOP _HOOK ] , {
cwd : repo ,
env : buildEnv ( binDir ) ,
input : JSON . stringify ( {
cwd : repo ,
session _id : "sess-stop-review" ,
last _assistant _message : "I completed the refactor and updated the retry logic."
} )
} ) ;
assert . equal ( blocked . status , 0 , blocked . stderr ) ;
const blockedPayload = JSON . parse ( blocked . stdout ) ;
assert . equal ( blockedPayload . decision , "block" ) ;
assert . match ( blockedPayload . reason , /Codex stop-time review found issues that still need fixes/i ) ;
assert . match ( blockedPayload . reason , /Missing empty-state guard/i ) ;
const fakeState = JSON . parse ( fs . readFileSync ( fakeStatePath , "utf8" ) ) ;
assert . match ( fakeState . lastTurnStart . prompt , /<task>/i ) ;
assert . match ( fakeState . lastTurnStart . prompt , /<compact_output_contract>/i ) ;
assert . match ( fakeState . lastTurnStart . prompt , /Only review the work from the previous Claude turn/i ) ;
assert . match ( fakeState . lastTurnStart . prompt , /I completed the refactor and updated the retry logic\./ ) ;
const status = run ( "node" , [ SCRIPT , "status" ] , {
cwd : repo ,
env : {
... buildEnv ( binDir ) ,
CODEX _COMPANION _SESSION _ID : "sess-stop-review"
}
} ) ;
assert . equal ( status . status , 0 , status . stderr ) ;
assert . match ( status . stdout , /Codex Stop Gate Review/ ) ;
} ) ;
test ( "stop hook logs running tasks to stderr without blocking when the review gate is disabled" , ( ) => {
const repo = makeTempDir ( ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const stateDir = resolveStateDir ( repo ) ;
const jobsDir = path . join ( stateDir , "jobs" ) ;
fs . mkdirSync ( jobsDir , { recursive : true } ) ;
const runningLog = path . join ( jobsDir , "task-running.log" ) ;
fs . writeFileSync ( runningLog , "running\n" , "utf8" ) ;
fs . writeFileSync (
path . join ( stateDir , "state.json" ) ,
` ${ JSON . stringify (
{
version : 1 ,
config : {
stopReviewGate : false
} ,
jobs : [
{
id : "task-live" ,
status : "running" ,
title : "Codex Task" ,
jobClass : "task" ,
sessionId : "sess-current" ,
logFile : runningLog ,
createdAt : "2026-03-18T15:32:00.000Z" ,
updatedAt : "2026-03-18T15:33:00.000Z"
}
]
} ,
null ,
2
) } \ n ` ,
"utf8"
) ;
const blocked = run ( "node" , [ STOP _HOOK ] , {
cwd : repo ,
env : {
... process . env ,
CODEX _COMPANION _SESSION _ID : "sess-current"
} ,
input : JSON . stringify ( { cwd : repo } )
} ) ;
assert . equal ( blocked . status , 0 , blocked . stderr ) ;
assert . equal ( blocked . stdout . trim ( ) , "" ) ;
assert . match ( blocked . stderr , /Codex task task-live is still running/i ) ;
assert . match ( blocked . stderr , /\/codex:status/i ) ;
assert . match ( blocked . stderr , /\/codex:cancel task-live/i ) ;
} ) ;
test ( "stop hook allows the stop when the review gate is enabled and the stop-time review task is clean" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "adversarial-clean" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const setup = run ( "node" , [ SCRIPT , "setup" , "--enable-review-gate" , "--json" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( setup . status , 0 , setup . stderr ) ;
const allowed = run ( "node" , [ STOP _HOOK ] , {
cwd : repo ,
env : buildEnv ( binDir ) ,
input : JSON . stringify ( { cwd : repo , session _id : "sess-stop-clean" } )
} ) ;
assert . equal ( allowed . status , 0 , allowed . stderr ) ;
assert . equal ( allowed . stdout . trim ( ) , "" ) ;
} ) ;
test ( "stop hook does not block when Codex is unavailable even if the review gate is enabled" , ( ) => {
const repo = makeTempDir ( ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const setup = run ( process . execPath , [ SCRIPT , "setup" , "--enable-review-gate" , "--json" ] , {
cwd : repo
} ) ;
assert . equal ( setup . status , 0 , setup . stderr ) ;
const allowed = run ( process . execPath , [ STOP _HOOK ] , {
cwd : repo ,
env : {
... process . env ,
PATH : ""
} ,
input : JSON . stringify ( { cwd : repo } )
} ) ;
assert . equal ( allowed . status , 0 , allowed . stderr ) ;
assert . equal ( allowed . stdout . trim ( ) , "" ) ;
assert . match ( allowed . stderr , /Codex is not set up for the review gate/i ) ;
assert . match ( allowed . stderr , /Run \/codex:setup/i ) ;
} ) ;
test ( "stop hook does not block when Codex is not authenticated even if the review gate is enabled" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir , "logged-out" ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
const setup = run ( "node" , [ SCRIPT , "setup" , "--enable-review-gate" , "--json" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( setup . status , 0 , setup . stderr ) ;
const allowed = run ( "node" , [ STOP _HOOK ] , {
cwd : repo ,
env : buildEnv ( binDir ) ,
input : JSON . stringify ( { cwd : repo } )
} ) ;
assert . equal ( allowed . status , 0 , allowed . stderr ) ;
assert . equal ( allowed . stdout . trim ( ) , "" ) ;
assert . match ( allowed . stderr , /Codex is not set up for the review gate/i ) ;
assert . match ( allowed . stderr , /not authenticated/i ) ;
assert . match ( allowed . stderr , /!codex login/i ) ;
} ) ;
test ( "commands lazily start and reuse one shared app-server after first use" , async ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
const fakeStatePath = path . join ( binDir , "fake-codex-state.json" ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello again\n" ) ;
const env = buildEnv ( binDir ) ;
const review = run ( "node" , [ SCRIPT , "review" ] , {
cwd : repo ,
env
} ) ;
assert . equal ( review . status , 0 , review . stderr ) ;
const brokerSession = loadBrokerSession ( repo ) ;
if ( ! brokerSession ) {
return ;
}
const adversarial = run ( "node" , [ SCRIPT , "adversarial-review" ] , {
cwd : repo ,
env
} ) ;
assert . equal ( adversarial . status , 0 , adversarial . stderr ) ;
const fakeState = JSON . parse ( fs . readFileSync ( fakeStatePath , "utf8" ) ) ;
assert . equal ( fakeState . appServerStarts , 1 ) ;
const cleanup = run ( "node" , [ SESSION _HOOK , "SessionEnd" ] , {
cwd : repo ,
env ,
input : JSON . stringify ( {
hook _event _name : "SessionEnd" ,
cwd : repo
} )
} ) ;
assert . equal ( cleanup . status , 0 , cleanup . stderr ) ;
} ) ;
test ( "status reports shared session runtime when a lazy broker is active" , ( ) => {
const repo = makeTempDir ( ) ;
const binDir = makeTempDir ( ) ;
installFakeCodex ( binDir ) ;
initGitRepo ( repo ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello\n" ) ;
run ( "git" , [ "add" , "README.md" ] , { cwd : repo } ) ;
run ( "git" , [ "commit" , "-m" , "init" ] , { cwd : repo } ) ;
fs . writeFileSync ( path . join ( repo , "README.md" ) , "hello again\n" ) ;
const review = run ( "node" , [ SCRIPT , "review" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( review . status , 0 , review . stderr ) ;
if ( ! loadBrokerSession ( repo ) ) {
return ;
}
const result = run ( "node" , [ SCRIPT , "status" ] , {
cwd : repo ,
env : buildEnv ( binDir )
} ) ;
assert . equal ( result . status , 0 , result . stderr ) ;
assert . match ( result . stdout , /Session runtime: shared session/ ) ;
} ) ;