From e188b6dbcf1c1ad48b35654d9c10eb7f1f5cba4d Mon Sep 17 00:00:00 2001 From: Val Alexander Date: Sun, 18 Oct 2026 04:10:17 -0500 Subject: [PATCH] Read a completed Codex web search as done, so it folds again Since #284, a tool whose outcome is unknown stays in view when its turn finishes. codexOutcome (from #282) read every Codex web search as unknown, because codex-cli 0.163.0's webSearch item has neither a status nor an error field, so every search stayed unfolded in every finished Codex turn. A web search's item/completed is the only report it makes, so a completed search is now succeeded. Unknown keeps meaning work that never reported. The contract doc's mapping table says so. Part of #277; follows #282 and #284. Coven-Harness: Claude Code / claude-opus-5-5 --- apps/desktop/src/main/engine/backends/codex.ts | 8 +++++--- apps/desktop/test/conversation-events.test.ts | 4 +++- docs/conversation-events.md | 2 +- docs/status.md | 4 ++++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/desktop/src/main/engine/backends/codex.ts b/apps/desktop/src/main/engine/backends/codex.ts index f3c9a3c9..7cdbeeba 100644 --- a/apps/desktop/src/main/engine/backends/codex.ts +++ b/apps/desktop/src/main/engine/backends/codex.ts @@ -675,8 +675,9 @@ export function codexPhase(phase: string | null | undefined): MessagePhase { * How a completed Codex tool item ended, from its own status (codex-cli 0.163.0): `declined` is a * denial, `failed` a failure, `completed` a success, except a command that completed with a non-zero * exit code (failed) or none at all (unknown). A command with no status is judged by its exit code. - * Any other item that reports no status (web search) is unknown unless it reports an error; so is a - * tool still `inProgress` when it completes. Exported for tests. + * A web search has neither a status nor an error field, so its `item/completed` is the only report it + * makes: it finished. Any other item without a status is unknown unless it reports an error, and so + * is a tool still `inProgress` when it completes. Exported for tests. */ export function codexOutcome(item: { type: string; status?: string; exitCode?: number | null; error?: unknown }): SettledOutcome { if (item.status === "declined") return "denied"; @@ -684,7 +685,8 @@ export function codexOutcome(item: { type: string; status?: string; exitCode?: n const exit = item.exitCode === 0 ? "succeeded" : typeof item.exitCode === "number" ? "failed" : "unknown"; if (item.status === "completed") return item.type === "commandExecution" ? exit : "succeeded"; if (item.status === undefined && item.type === "commandExecution" && exit !== "unknown") return exit; - return item.error ? "failed" : "unknown"; + if (item.error) return "failed"; + return item.status === undefined && item.type === "webSearch" ? "succeeded" : "unknown"; } function partIndex(value: unknown): number { diff --git a/apps/desktop/test/conversation-events.test.ts b/apps/desktop/test/conversation-events.test.ts index 95423dc3..107ea034 100644 --- a/apps/desktop/test/conversation-events.test.ts +++ b/apps/desktop/test/conversation-events.test.ts @@ -491,7 +491,9 @@ test("every Codex 0.163.0 phase and tool status has a mapping, and none but a cl assert.equal(codexOutcome({ type: "commandExecution", status: "completed", exitCode: null }), "unknown"); assert.equal(codexOutcome({ type: "commandExecution", exitCode: 0 }), "succeeded", "no status: the exit code decides"); assert.equal(codexOutcome({ type: "commandExecution", exitCode: 1 }), "failed"); - assert.equal(codexOutcome({ type: "webSearch" }), "unknown", "web search reports no status"); + // codex-cli 0.163.0's webSearch item has neither a status nor an error field, so item/completed is + // the only report a search makes: it finished. Unknown stays for work that never reported (#277). + assert.equal(codexOutcome({ type: "webSearch" }), "succeeded", "a web search that completed finished"); assert.equal(codexOutcome({ type: "mcpToolCall", error: { message: "boom" } }), "failed"); }); diff --git a/docs/conversation-events.md b/docs/conversation-events.md index 161659f3..c8afc5dd 100644 --- a/docs/conversation-events.md +++ b/docs/conversation-events.md @@ -198,7 +198,7 @@ id and the item id. | `completed`, any other tool | `succeeded` | | `inProgress` when the item completes | `unknown` | | no status, a command with an exit code | from the exit code | -| no status (web search), no error | `unknown` | +| no status (web search), no error | `succeeded`: codex-cli 0.163.0 gives a web search no status or error field, so its completion is its only report | | no status, an error | `failed` | `turn/completed` ends the turn: `completed`, `interrupted` and `failed` become the attempt's diff --git a/docs/status.md b/docs/status.md index 62d4142b..8d6e7cab 100644 --- a/docs/status.md +++ b/docs/status.md @@ -808,6 +808,10 @@ itself, shows 0.1.0 in About and kept its unsent drafts. knowledge base opens its file under the new name instead of failing on the old one. (#241) - **Large notes trees keep up with typing.** Typing in a page no longer redraws the Space sidebar's tree, and drawing a tree of about 2,000 items takes about 80 ms instead of 3 s (#241). +- **Codex web searches fold away again when a turn finishes.** Since #284, work whose result is + unknown stays in view, and every Codex web search read as unknown: codex-cli 0.163.0 gives a + search no status or error field. Its completion is its only report, so a completed search now + reads as done and folds like other finished work (#277). ## In flight