0a15785c98
Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
3.9 KiB
3.9 KiB
spec, created, status
| spec | created | status |
|---|---|---|
| docs/specs/ui/subagent-observability.md | 2026-08-25 | done |
Implementation Plan: Subagent active header status
Overview
The collapsed subagent header already has a GridSpinner while isSubagentEffectivelyActive is true, but task:working is gated on isActive && !hasExpandableContent. A live wave with nested children therefore looks like a settled type + description row. This plan keeps Working + spinner on every active header, adds a red IconX after failed or cancelled finishes, and shows a muted completion check after success. Identity chips stay settled-card metadata. Unit tests cover the new states; existing /e2e:subagent specs assert the settled header. No backend or mock-agent change.
Frontend
apps/web/components/task/chat/messages/tool-subagent-message.tsx
- Delete
showInlineWorking. Rendert("task:working")wheneverisActive, next to the existingGridSpinner, including whenhasExpandableContentis true. - Pass
metadata?.statusintoSubagentHeader. When not active, ifnormalizeToolCallStatus(status)iserrororcancelled, render a shrink-0 redIconX(h-3.5 w-3.5 text-red-500) witharia-labeltask:failedortask:cancelled. Pattern:ExecuteStatusIconintool-execute-message.tsx, but reusetask:failed/task:cancelledinstead of command keys, and never renderIconCheck. - Keep
SubagentMetaRowand the UUID/model/duration chip timing (!isActive). Preserve terminal nested payload precedence inisSubagentEffectivelyActive.
Mobile design contract
- Desktop and mobile share the same header. No overlay, drawer, or navigation change.
- Nearest exemplar:
ExecuteStatusIconplus the existing subagent header (min-h-11expandable hit target belowsm). - Status glyph stays
shrink-0so type, description, and Working truncate first. - Parity proof:
mobile-subagent.spec.tsasserts the settled header at phone width.
Tests
- What: active card with children still shows Working + Loading spinner; complete card shows one Completed check; failed/cancelled show the labelled red mark.
File:
apps/web/components/task/chat/messages/tool-subagent-message.test.tsx. How: extendToolSubagentMessage/ expansion cases. Active +childMessagesmust showtask:workingandrole=statusnameLoading. Complete + children must not. Failed/cancelled fixtures assertgetByLabelTextfor Failed / Cancelled and no spinner.
E2E Tests
- Scenario: GIVEN
/e2e:subagentcompletes, WHEN the card is visible, THEN there is no Loading status, no Working copy, one Completed check, and the metadata row is visible. Files:apps/web/e2e/tests/chat/subagent.spec.tsandapps/web/e2e/tests/chat/mobile-subagent.spec.ts. - Do not add a mock-agent scenario. The existing
scenarioSubagentwindow is ~150ms; active-with-children and failed/cancelled are unit-tested.
Verification Results
pnpm --filter @kandev/web test -- components/task/chat/messages/tool-subagent-message.test.tsx— 52 passed.pnpm exec eslint+pnpm run typecheckon the two unit files — pass.pnpm e2e:run --host --project chromium -- tests/chat/subagent.spec.ts— 1 passed.pnpm e2e:run --host --project mobile-chrome -- tests/chat/mobile-subagent.spec.ts— 1 passed.
Implementation Waves And Parallel Candidates
Wave 1:
Wave 2:
Sequential. E2E asserts the settled header produced by task 01.
Risks
- Fresh worktrees need
cd apps && pnpm install --frozen-lockfilebefore any pnpm command. - E2E runs the production Vite build. Rebuild after the UI change (
pnpm e2e:rundoes this; a staleapps/web/distwill miss the header). - Do not invent
task:subagentFailedkeys. Reusetask:working,task:failed,task:cancelled, andcommon:loadingIndicatorLabel.
Open Questions
None.