diff --git a/plugins/codex/scripts/lib/job-control.mjs b/plugins/codex/scripts/lib/job-control.mjs index ad152c157..f213e01be 100644 --- a/plugins/codex/scripts/lib/job-control.mjs +++ b/plugins/codex/scripts/lib/job-control.mjs @@ -256,6 +256,15 @@ export function buildSingleJobSnapshot(cwd, reference, options = {}) { export function resolveResultJob(cwd, reference) { const workspaceRoot = resolveWorkspaceRoot(cwd); const jobs = sortJobsNewestFirst(reference ? listJobs(workspaceRoot) : filterJobsForCurrentSession(listJobs(workspaceRoot))); + + if (reference) { + const selected = matchJobReference(jobs, reference); + if (selected.status === "queued" || selected.status === "running") { + throw new Error(`Job ${selected.id} is still ${selected.status}. Check /codex:status and try again once it finishes.`); + } + return { workspaceRoot, job: selected }; + } + const selected = matchJobReference( jobs, reference, @@ -271,10 +280,6 @@ export function resolveResultJob(cwd, reference) { throw new Error(`Job ${active.id} is still ${active.status}. Check /codex:status and try again once it finishes.`); } - if (reference) { - throw new Error(`No finished job found for "${reference}". Run /codex:status to inspect active jobs.`); - } - throw new Error("No finished Codex jobs found for this repository yet."); } diff --git a/tests/runtime.test.mjs b/tests/runtime.test.mjs index 8f276835b..7b4d02ae5 100644 --- a/tests/runtime.test.mjs +++ b/tests/runtime.test.mjs @@ -1415,6 +1415,43 @@ test("result returns the stored output for the latest finished job by default", ); }); +test("result reports the status of an explicitly referenced active job", () => { + const workspace = makeTempDir(); + const stateDir = resolveStateDir(workspace); + fs.mkdirSync(stateDir, { recursive: true }); + + 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", + createdAt: "2026-03-18T15:00:00.000Z", + updatedAt: "2026-03-18T15:01:00.000Z" + } + ] + }, + null, + 2 + )}\n`, + "utf8" + ); + + const result = run("node", [SCRIPT, "result", "task-live"], { + cwd: workspace + }); + + assert.notEqual(result.status, 0); + assert.match(result.stderr, /Job task-live is still running/i); + assert.doesNotMatch(result.stderr, /No job found/i); +}); + test("result without a job id prefers the latest finished job from the current Claude session", () => { const workspace = makeTempDir(); const stateDir = resolveStateDir(workspace);