What happens
In a Claude chat, start a background workflow and let the chat's own turn finish. The chat goes idle. Then each progress update from the still-running workflow does two things:
- It flips the chat back to working, with a Stop button, even though the chat's own agent is not doing anything.
- It opens a new turn that stays running. The turn is still running after the workflow reports that it finished, and only closes when a later
result arrives.
The chat's last-activity time also moves forward on every progress update.
Expected
A background workflow's progress should update its own background-task row, and nothing else. The chat should stay idle. It should only start a turn when the agent is actually woken up, for example by the task-finished notification or by new assistant output.
Why it happens
- The Claude CLI (checked in 2.1.280) sends
system / task_progress frames while a background workflow is running, and for subagent progress too. The frames carry task_id and tool_use_id, but no parent_tool_use_id. So Orca treats them as coming from the chat's own agent.
claude-background-task-rows.ts folds each frame's token count into the background-task row. That changes the row, so it is written again, and because the row is still live, the translator opens an output turn for it.
claudeStreamTurnSource in claude-turn-opening.ts counts any frame that has a session_id and a uuid as assistant output. That opens a root turn named after the progress frame's uuid.
Reproduction
A unit probe on main (80e0bee) sends real frame shapes through the real Claude translator, the durable journal and the status feed:
- After the chat settled, it was idle at 20000.
- After the first
task_progress, the status became working, with the running turn sys-p1 (started 21000).
- After two more progress frames and the task's
task_notification, the turn was still running.
- Both
local_workflow and local_bash task types behave this way in that probe. The CLI only sends these progress frames for workflows and subagents; I found no sender for shell tasks.
This was not captured from a live Claude session. The frame shape comes from the CLI bundle and the translator's own fixtures.
Context
Found while reviewing #22520, which changes how a chat's status time is computed. This is on main today, and #22520 does not fix it; the fix belongs in the Claude translator's turn-opening rule.
What happens
In a Claude chat, start a background workflow and let the chat's own turn finish. The chat goes idle. Then each progress update from the still-running workflow does two things:
resultarrives.The chat's last-activity time also moves forward on every progress update.
Expected
A background workflow's progress should update its own background-task row, and nothing else. The chat should stay idle. It should only start a turn when the agent is actually woken up, for example by the task-finished notification or by new assistant output.
Why it happens
system/task_progressframes while a background workflow is running, and for subagent progress too. The frames carrytask_idandtool_use_id, but noparent_tool_use_id. So Orca treats them as coming from the chat's own agent.claude-background-task-rows.tsfolds each frame's token count into the background-task row. That changes the row, so it is written again, and because the row is still live, the translator opens an output turn for it.claudeStreamTurnSourceinclaude-turn-opening.tscounts any frame that has asession_idand auuidas assistant output. That opens a root turn named after the progress frame'suuid.Reproduction
A unit probe on
main(80e0bee) sends real frame shapes through the real Claude translator, the durable journal and the status feed:task_progress, the status becameworking, with the running turnsys-p1(started 21000).task_notification, the turn was stillrunning.local_workflowandlocal_bashtask types behave this way in that probe. The CLI only sends these progress frames for workflows and subagents; I found no sender for shell tasks.This was not captured from a live Claude session. The frame shape comes from the CLI bundle and the translator's own fixtures.
Context
Found while reviewing #22520, which changes how a chat's status time is computed. This is on
maintoday, and #22520 does not fix it; the fix belongs in the Claude translator's turn-opening rule.