Dismiss a failed agent's red dot by reading it (#8831)

* fix(sidebar): clear the failed status once the error is read

Reading an errored agent already cleared its error attention, but the
state bucket also mapped lifecycle status "error" to failed. Lifecycle
only leaves "error" when the next turn starts, so the red dot and the
Failed group stuck until the agent was prompted again. The failed bucket
now follows unread error attention, the same way the green dot follows
unread finished attention; lifecycle status stays "error".

Because failed now depends on attention, a failure must replace unread
finished attention, otherwise a reload that fails on an unread agent
would show green.

* fix(sidebar): keep failed subagents red and let read failures be marked unread

The failed bucket now follows unread error attention, which broke three
places that relied on lifecycle "error" alone:

- Subagent track rows and provider-subagent tabs have no read state of
  their own, so failed children lost their red mark. They now map the
  child's lifecycle directly.
- A read errored workspace became "done" and offered Mark as unread, but
  the daemon only accepted idle or closed agents. Marking it unread now
  restores error attention.
- A reload that failed again while the lifecycle was already "error"
  raised no new attention. A failed reload now raises error attention
  directly instead of relying on a lifecycle transition.
This commit is contained in:
Mohamed Boudra
2026-11-05 18:49:12 +07:00
committed by GitHub
parent cdd7800fed
commit 59be8975a4
12 changed files with 267 additions and 39 deletions
+10 -3
View File
@@ -305,9 +305,9 @@ Workspace status is an aggregate activity signal computed **per `workspaceId`**.
Running provider-native subagents contribute `running` to the workspace owned by their parent agent. Their completed, failed, and canceled states stay in the parent's subagents track.
A finished workspace can be marked unread after it has been reviewed. The daemon restores
`finished` attention on its newest eligible workspace-root agent without sending a new completion
notification. Opening the workspace clears that attention through the normal focus flow.
A finished or failed workspace can be marked unread after it has been reviewed. The daemon restores
attention on its newest eligible workspace-root agent, `error` for an agent whose lifecycle is
`error` and `finished` otherwise, without sending a new notification. Opening the workspace clears that attention through the normal focus flow.
Attention is set by the agent finishing or failing and cleared by the client's
`workspace.clear_attention`, which fires when the user reads the chat. Loading an agent's runtime is
@@ -316,6 +316,13 @@ untouched. Forging either makes a background resume look like the user read a wo
agent worked in it just now, which rewrites the sidebar timestamp permanently — persisted
`updatedAt` is what workspace `statusEnteredAt` is re-derived from on the next daemon start.
The `failed` bucket follows unread `error` attention, not lifecycle status. An agent stays `error`
until its next turn starts, so reading the chat dismisses the red dot the same way it dismisses the
green one. For the same reason every new failure raises `error` attention, including a failed reload
that leaves the lifecycle at `error`, and replaces unread `finished` attention; otherwise the failed
agent would show the green dot or none. Subagents track marks are the exception: they follow the
child's lifecycle, because the track is where a failed child stays visible.
## The subagents track
The track is a pill at the foot of an agent's pane (`packages/app/src/subagents/track.tsx`): a count you can read at a glance, and a panel behind it — a popover on wide screens, a sheet on compact ones — holding the rows. It floats over the transcript rather than sitting in a band above the composer, so the timeline scrolls underneath it; `packages/app/src/panels/agent-tracks.tsx` owns that placement, and the pill frame is shared with the task list in `packages/app/src/composer/tracks.tsx`.