diff --git a/src/main/claude/claude-background-task-tracker.test.ts b/src/main/claude/claude-background-task-tracker.test.ts index 040fbce29d2..4e1fae6ff8a 100644 --- a/src/main/claude/claude-background-task-tracker.test.ts +++ b/src/main/claude/claude-background-task-tracker.test.ts @@ -114,6 +114,25 @@ describe('ClaudeBackgroundTaskTracker', () => { }) }) + it('retires a phantom foreground row when the next turn starts', () => { + // A foreground `task_started` with no turn open has no `result` coming to + // retire it, so it would sit in the strip — with no stop of its own — and + // refuse a conversation command. Turn start is the same evidence `result` + // is, and settling on it is cleanup only: nothing gates visibility on it. + const tracker = new ClaudeBackgroundTaskTracker() + tracker.observe( + system('task_started', { + task_id: 'phantom', + task_type: 'local_agent', + is_backgrounded: false + }) + ) + expect(tracker.state?.tasks).toEqual([{ id: 'phantom', kind: 'agent', stoppable: false }]) + + tracker.observe({ type: 'user' }, true) + expect(tracker.state).toBeNull() + }) + it('publishes bounded display details when a running task description changes', () => { const tracker = new ClaudeBackgroundTaskTracker() expect( diff --git a/src/main/claude/claude-background-task-tracker.ts b/src/main/claude/claude-background-task-tracker.ts index 3105f0e97f3..64c285b447b 100644 --- a/src/main/claude/claude-background-task-tracker.ts +++ b/src/main/claude/claude-background-task-tracker.ts @@ -89,6 +89,15 @@ export class ClaudeBackgroundTaskTracker { } observe(message: Record, startsTurn = false): boolean { + // A new turn is the same evidence `result` is: nothing the previous turn + // left foreground is still that turn's work. This is CLEANUP ONLY — a row's + // visibility never depends on `startsTurn`, which is Orca's own + // dispatch-correlation bookkeeping and is false by design for undispatched + // turns, so a missed one degrades to the old behaviour and can never hide + // live work. + if (startsTurn) { + this.settleForegroundTasks() + } if (message.type === 'result') { this.settleForegroundTasks() } else if (message.type === 'system') {