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` + } +}