From 6b4b547a1bbbee703e5916c0068d61fa57775c4c Mon Sep 17 00:00:00 2001 From: Merge Sim Date: Wed, 9 Sep 2026 01:00:15 -0700 Subject: [PATCH] Name settled lifecycle rows by their terminal state An interrupted or unverifiable turn must not read as completed for any consumer that renders status text raw. One shared helper builds the text for both providers from the lifecycle state. --- src/main/claude/claude-turn-lifecycle-item.ts | 3 ++- ...journal-translation-turn-lifecycle.test.ts | 2 +- ...ex-structured-journal-translation-turns.ts | 8 ++++++-- src/shared/agent-turn-lifecycle-text.ts | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 src/shared/agent-turn-lifecycle-text.ts diff --git a/src/main/claude/claude-turn-lifecycle-item.ts b/src/main/claude/claude-turn-lifecycle-item.ts index 72c64c3c512..260958974b7 100644 --- a/src/main/claude/claude-turn-lifecycle-item.ts +++ b/src/main/claude/claude-turn-lifecycle-item.ts @@ -2,6 +2,7 @@ import type { AgentJournalItemIdentity, AgentJournalStatusItem } from '../../shared/agent-session-journal-types' +import { agentTurnLifecycleText } from '../../shared/agent-turn-lifecycle-text' import type { StructuredAgentSessionAppendOptions } from '../native-chat/agent-session-wire/structured-agent-session-event-sink' import { claudeText } from './claude-structured-item-translation' @@ -50,7 +51,7 @@ export function claudeTurnLifecycleItem( identity: claudeTurnLifecycleIdentity(sessionId, turnId), body: { kind: 'status', - text: end ? 'Claude turn completed' : 'Claude is working…', + text: agentTurnLifecycleText('Claude', end ? end.state : 'running'), turnLifecycle: end ? { turnId, state: end.state, startedAt, completedAt: end.completedAt } : { turnId, state: 'running', startedAt } diff --git a/src/main/codex/codex-structured-journal-translation-turn-lifecycle.test.ts b/src/main/codex/codex-structured-journal-translation-turn-lifecycle.test.ts index 150b3d54100..0e1b59c5970 100644 --- a/src/main/codex/codex-structured-journal-translation-turn-lifecycle.test.ts +++ b/src/main/codex/codex-structured-journal-translation-turn-lifecycle.test.ts @@ -286,7 +286,7 @@ describe('codex turn lifecycle rows', () => { key: 'legacy:codex:session-1:turn-lifecycle%3Aturn-cut', body: { kind: 'status', - text: 'Codex turn completed', + text: 'Codex turn interrupted', turnLifecycle: { turnId: 'turn-cut', state: 'interrupted', diff --git a/src/main/codex/codex-structured-journal-translation-turns.ts b/src/main/codex/codex-structured-journal-translation-turns.ts index 8e5311beaa7..c66d6a31d91 100644 --- a/src/main/codex/codex-structured-journal-translation-turns.ts +++ b/src/main/codex/codex-structured-journal-translation-turns.ts @@ -4,6 +4,7 @@ import type { AgentJournalTurnLifecycle, AgentJournalTurnLifecycleState } from '../../shared/agent-session-journal-types' +import { agentTurnLifecycleText } from '../../shared/agent-turn-lifecycle-text' import type { StructuredAgentSessionEventSink, StructuredAgentSessionSinkAdmission @@ -26,8 +27,11 @@ export function codexTurnLifecycleIdentity( export function codexTurnLifecycleBody( turnLifecycle: AgentJournalTurnLifecycle ): AgentJournalStatusItem { - const text = turnLifecycle.state === 'running' ? 'Codex is working…' : 'Codex turn completed' - return { kind: 'status', text, turnLifecycle } + return { + kind: 'status', + text: agentTurnLifecycleText('Codex', turnLifecycle.state), + turnLifecycle + } } /** `turn/completed` is Codex's only turn-end notification; a missing status is a clean finish. */ diff --git a/src/shared/agent-turn-lifecycle-text.ts b/src/shared/agent-turn-lifecycle-text.ts new file mode 100644 index 00000000000..f8bc2be568b --- /dev/null +++ b/src/shared/agent-turn-lifecycle-text.ts @@ -0,0 +1,19 @@ +import type { AgentJournalTurnLifecycleState } from './agent-session-journal-types' + +/** Fallback text on a lifecycle row for readers that render status text raw. + * Must never overstate what the host knows: an unobserved end is not "completed". */ +export function agentTurnLifecycleText( + agent: 'Claude' | 'Codex', + state: AgentJournalTurnLifecycleState +): string { + switch (state) { + case 'running': + return `${agent} is working…` + case 'completed': + return `${agent} turn completed` + case 'interrupted': + return `${agent} turn interrupted` + case 'unverifiable': + return `${agent} turn outcome unverifiable` + } +}