feat(desktop,host-service): surface agent failures as a "failed" status
Problem
Terminal-agent status was derived from a Start / Stop / PermissionRequest vocabulary with no failure category, so a failed agent turn was silent — the pane stayed on "working".
What this does
Adds a first-class Failed lifecycle event and a red failed PaneStatus, driven purely by CLI-reported failures: Claude Code emits a StopFailure hook on API errors (rate_limit, overloaded, authentication_failed, billing_error, server_error, …). We register that hook and map StopFailure → Failed.
Because StopFailure fires while the session stays alive, the binding just flips to Failed and surfaces through the normal live read — no session-status or liveness plumbing. It self-clears when the agent retries (next Start). The failed status is a red pulsing dot (like permission) and counts toward the unread / dock-badge attention totals.
Scope
Deliberately limited to failures a CLI actually reports via a hook — no exit-code/crash inference (that path had false-positive risk on ordinary non-zero shell exits and is not worth the complexity). Non-Claude CLIs that don't emit a failure hook simply won't show failed; that's fine.
Tests
mapEventType (StopFailure→Failed), deriveTerminalAgentStatus, the store recording Failed without dropping the binding, and the full StopFailure→Failed notifications-router path (asserting agent identity survives). Typecheck + lint clean.
Verified end-to-end (CDP)
Drove the running dev desktop: POSTing a StopFailure hook for a live terminal agent flipped the binding Start→Failed and turned the Terminal tab, pane header, and sidebar workspace badge from amber "working" to red "failed".
Summary by cubic
Surfaces agent failures as a first-class failed status across apps/desktop and packages/host-service. Claude Code API errors now show a red “failed” state instead of staying “working”.
-
New Features
- Added
Failedlifecycle event andfailedPaneStatus(red, pulsing). Shown in status indicators and attention/unread counts; priority just belowpermission. - Register Claude Code
StopFailurehook and map toFailedwhile the session stays alive; clears on nextStart. Detection is hook-reported only (no exit-code heuristics). - Keep
failedbindings in live reads so panes show failure; never use them as attach targets.
- Added
-
Bug Fixes
- Preserve agent identity on
Failedbroadcasts and keep the binding in the store.
- Preserve agent identity on
Summary by CodeRabbit
-
New Features
- Added clear failure status tracking for terminal agents.
- Failure events now remain visible and display a red, pulsing “Agent failed” indicator.
- Workspaces with failed agents are marked as requiring attention and included in attention counts.
- Claude integrations now report stop-failure events.
-
Bug Fixes
- Distinguished failed agent runs from normally stopped runs, ensuring failure notifications and statuses are surfaced correctly.