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.
This commit is contained in:
Merge Sim
2026-09-09 01:00:15 -07:00
parent 5060f54584
commit 6b4b547a1b
4 changed files with 28 additions and 4 deletions
@@ -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 }
@@ -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',
@@ -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. */
+19
View File
@@ -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`
}
}