diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-set.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-set.ts index 2c429c75239..e6154c705f4 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-set.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-set.ts @@ -84,12 +84,6 @@ export function structuredAgentSessionResumableSet( if (turn.state !== 'interrupted' && turn.state !== 'unverifiable') { continue } - // Read off the MARKER, never re-derived. Teardown cancels the pending prompt a few phases after - // it writes the marker, so by now the live journal no longer reports `attention` for exactly the - // sessions this refuses — which is what made the re-derived version inert. - if (marker.awaitsUser) { - continue - } candidates.push({ sessionId: marker.sessionId, workspaceId: record.location.workspaceId, diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume.test.ts index c46aae64019..b7ff7dfc2ee 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume.test.ts @@ -136,7 +136,6 @@ function marker(overrides: Partial = {}): AgentSession recordedAt: NOW, trigger: 'quit', providerHandleRoot: HANDLE_ROOT, - awaitsUser: false, ...overrides } } @@ -175,7 +174,6 @@ describe('deriving what was working at teardown', () => { turnId: 'turn-1', recordedAt: NOW, trigger: 'quit', - awaitsUser: false, providerHandleRoot: HANDLE_ROOT } ]) @@ -367,13 +365,6 @@ describe('the resumable set', () => { ) }) - // The flag is CAPTURED at teardown because teardown then cancels the prompt: by the time this - // predicate runs, the live journal no longer reports `attention`, so only the recorded value can - // still refuse. Re-deriving it here was inert for exactly the sessions it was written for. - it('refuses a marker recorded while the chat was blocked on the user', () => { - expect(resumableSet({ markers: [marker({ awaitsUser: true })] })).toEqual([]) - }) - it('offers a turn whose end the host could not verify', () => { expect( resumableSet({ markers: [marker()], items: [turnItem('turn-1', 'unverifiable')] }) @@ -539,7 +530,6 @@ describe('the restart-resume surface', () => { turnId: 'turn-2', recordedAt: NOW, trigger: 'update', - awaitsUser: false, providerHandleRoot: HANDLE_ROOT } ]) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-working-at-teardown.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-working-at-teardown.ts index 4996ec90143..e7f8f981eba 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-working-at-teardown.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-working-at-teardown.ts @@ -44,12 +44,16 @@ export function structuredAgentSessionsWorkingAtTeardown(input: { } const snapshot = session.journal.snapshot() const status = projectStructuredAgentSessionStatus(snapshot.items, snapshot.submissions) - // Captured HERE, while it is still true. A later teardown phase cancels the pending prompt, so - // nothing downstream can re-derive this fact — the marker has to carry it. - const awaitsUser = status === 'attention' // The product's own classification, so the marker rule cannot disagree with what the UI calls // working. A turn blocked on an approval or a question projects as `attention`: the agent is // waiting on the USER, and that is not interrupted work to hand back. + // + // This is the SINGLE gate for those sessions, and deliberately has no mirror in the launch-side + // predicate. Teardown is the only writer of markers and `attention` exits here, so no marker for + // such a session is ever minted and a predicate-side clause would be unreachable. It could not + // even re-derive the fact — a later teardown phase cancels the pending prompt — so it would have + // to be a captured flag, and a field that is structurally always false reads as a safeguard + // while guarding nothing. Do not re-add one. if (status !== 'working') { continue } @@ -68,7 +72,6 @@ export function structuredAgentSessionsWorkingAtTeardown(input: { turnId, recordedAt: input.now, trigger: input.trigger, - awaitsUser, // Root, not key: the close path advances Claude's leaf moments after this runs, and a key // comparison would then refuse the session forever. providerHandleRoot: agentSessionProviderHandleRoot(head.handle) diff --git a/src/main/runtime/agent-session-resume-marker-store.test.ts b/src/main/runtime/agent-session-resume-marker-store.test.ts index 5d77292745e..3142fdd09e3 100644 --- a/src/main/runtime/agent-session-resume-marker-store.test.ts +++ b/src/main/runtime/agent-session-resume-marker-store.test.ts @@ -22,7 +22,6 @@ function marker(overrides: Partial = {}): AgentSession recordedAt: NOW, trigger: 'quit', providerHandleRoot: 'codex:"thread-1"', - awaitsUser: false, ...overrides } } diff --git a/src/shared/agent-session-resume-marker.ts b/src/shared/agent-session-resume-marker.ts index 79172fe0b26..66639b44d7d 100644 --- a/src/shared/agent-session-resume-marker.ts +++ b/src/shared/agent-session-resume-marker.ts @@ -34,14 +34,6 @@ export type AgentSessionResumeMarker = { * preserve — a resume that changes it forked — which is exactly what this guard is for. */ providerHandleRoot: string - /** - * Whether the chat was blocked on the USER — a pending approval or question — at teardown. - * - * CAPTURED, never re-derived, because teardown itself destroys the evidence: a later phase - * cancels the pending prompt, so by the next launch the projection no longer reports `attention` - * for precisely the sessions this exists to refuse. Re-reading it was inert. - */ - awaitsUser: boolean } const MAX_FIELD_LENGTH = 512 @@ -59,7 +51,6 @@ export function isAgentSessionResumeMarker(value: unknown): value is AgentSessio isMarkerField(marker.sessionId) && isMarkerField(marker.turnId) && isMarkerField(marker.providerHandleRoot) && - typeof marker.awaitsUser === 'boolean' && Number.isSafeInteger(marker.recordedAt) && (marker.recordedAt as number) >= 0 && (marker.trigger === 'quit' || marker.trigger === 'update')