Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
3.8 KiB
id, title, status, wave, depends_on, plan, spec
| id | title | status | wave | depends_on | plan | spec |
|---|---|---|---|---|---|---|
| 01-header-status-ui | Keep Working + spinner on every active header | done | 1 | plan.md | ../../specs/ui/subagent-observability.md |
Task 01: Keep Working + spinner on every active header
Intent
Make a live subagent card glanceable without expanding it: Working copy and spinner stay on the header even when the card has children, and a failed or cancelled finish gets a red mark. Successful completion gets a muted check.
Acceptance
SubagentHeaderrenderst("task:working")andGridSpinnerwheneverisActiveis true, including whenhasExpandableContentis true. TheshowInlineWorkinggate is gone.- When
isActiveis false andnormalizeToolCallStatus(metadata.status)iserrororcancelled, the header shows a redIconX(h-3.5 w-3.5 text-red-500) witharia-labeltask:failedortask:cancelled. A successful complete header shows a mutedIconCheckwitharia-labeltask:statusCompleted. Pending-settled headers show neither spinner, Working, nor X. - Terminal nested payload statuses take precedence over running metadata in
isSubagentEffectivelyActive.SubagentMetaRowand!isActivechip timing stay unchanged. No new locale keys.
Regression tests (write first — must fail before the production change)
In apps/web/components/task/chat/messages/tool-subagent-message.test.tsx:
- Active + children:
metadataStatus: "running"with twochildToolmessages. AssertgetByText("Working...")andgetByRole("status", { name: "Loading" }). Current code hides Working when children exist, so this fails first. - Complete + children:
metadataStatus: "complete"with children. Assert onegetByLabelText("Completed"), no Working, and no Loading status. - Failed:
metadataStatus: "failed"(or"error"). AssertgetByLabelText("Failed")and no Loading status. - Cancelled:
metadataStatus: "cancelled". AssertgetByLabelText("Cancelled")and no Loading status. - Terminal nested payloads:
payloadStatus: "errored"overrides running metadata andpayloadStatus: "failed"or"cancelled"overrides complete metadata.
Reuse subagentMessage / renderSubagent / childTool. Do not invent a Done chip assertion.
Files likely touched
apps/web/components/task/chat/messages/tool-subagent-message.tsxapps/web/components/task/chat/messages/tool-subagent-message.test.tsx
Dependencies
None.
Parallelism
Sequential. Component and unit tests share the same files.
Inputs
- Spec:
### Header statusand the three new header-status scenarios. - Plan: Frontend and Tests.
- Pattern:
ExecuteStatusIconintool-execute-message.tsx(spinner / red X / no check for this card). ImportnormalizeToolCallStatusfrom./tool-statusor@/lib/utils/tool-call-status.
Verification
cd apps && pnpm install --frozen-lockfile && pnpm --filter @kandev/web test -- components/task/chat/messages/tool-subagent-message.test.tsx && cd web && NODE_OPTIONS="--max-old-space-size=6144" pnpm run typecheck && pnpm exec eslint components/task/chat/messages/tool-subagent-message.tsx components/task/chat/messages/tool-subagent-message.test.tsx && pnpm exec prettier --check components/task/chat/messages/tool-subagent-message.tsx components/task/chat/messages/tool-subagent-message.test.tsx
Output contract
Summary, files changed, tests run, blockers, risks, and this task plus plan.md status/results updated in the same conversation.
Results
Done. Removed showInlineWorking. Active headers always show task:working + GridSpinner. Terminal nested failures and cancellations now override stale metadata. Failed/cancelled headers show a labelled red IconX. Complete headers show a labelled muted check.
- Unit tests: 52 passed (
tool-subagent-message.test.tsx). The regression run failed 4 cases before the status precedence fix. - Typecheck / eslint / prettier: pass.