feat(dashboard): TaskUiStatus type + StatusPill component #981

Merged
reviewer merged 2 commits from dev/963 into main 2026-05-08 13:52:11 +00:00
Collaborator

Unified status vocabulary (Planning · Executing · Waiting · Reviewing · Done · Error · Abandoned) replacing raw task_history.status strings across dashboard surfaces.

Test plan

  • just qa clean — all 3316 server tests + 13 new StatusPill snapshot tests pass
  • History-contract test updated to cover ui_status / ui_status_reason keys
  • Monitor row and drawer header now render StatusPill; fallback client-side derivation for old server responses
  • prefers-reduced-motion: pulsing dot animation zeroed by global rule in styles/index.css

Closes #963

Unified status vocabulary (Planning · Executing · Waiting · Reviewing · Done · Error · Abandoned) replacing raw `task_history.status` strings across dashboard surfaces. ## Test plan - `just qa` clean — all 3316 server tests + 13 new `StatusPill` snapshot tests pass - History-contract test updated to cover `ui_status` / `ui_status_reason` keys - Monitor row and drawer header now render `StatusPill`; fallback client-side derivation for old server responses - `prefers-reduced-motion`: pulsing dot animation zeroed by global rule in `styles/index.css` Closes #963
dev self-assigned this 2026-05-08 13:30:50 +00:00
feat(dashboard): TaskUiStatus type + StatusPill component (#963)
All checks were successful
qa / i18n-string-check (pull_request) Successful in 11s
qa / dockerfile (pull_request) Successful in 11s
qa / db-schema (pull_request) Successful in 12s
qa / sql-layer-check (pull_request) Successful in 21s
qa / qa-1 (pull_request) Successful in 1m10s
qa / qa (pull_request) Successful in 0s
eea1a7b812
Adds a unified status vocabulary (Planning · Executing · Waiting ·
Reviewing · Done · Error · Abandoned) to replace the raw task_history
status strings on every dashboard surface.

- `@claude-hooks/shared`: `TaskUiStatus` type, `deriveTaskUiStatus` and
  `deriveTaskUiStatusReason` helpers; server imports them to enrich the
  `/history` response with `ui_status` + `ui_status_reason`.
- `<StatusPill>`: Lucide icon + label pill; pulsing dot for `executing`
  (zeroed by the global `prefers-reduced-motion` rule); `title` tooltip
  shows the optional reason string.
- Mounted on: monitor row (`task-list.tsx`) and drawer header
  (`task-detail.tsx`); both fall back to client-side derivation when the
  server field is absent.
- History-contract test updated for the two new response keys.
- Snapshot tests covering all 7 statuses + reason/pulse/a11y assertions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dev requested review from reviewer 2026-05-08 13:33:52 +00:00
reviewer requested changes 2026-05-08 13:35:31 +00:00
Dismissed
reviewer left a comment

CI green. Core implementation (TaskUiStatus, deriveTaskUiStatus, StatusPill) looks correct. Two issues:

  • ac-gap apps/web/src/components/task-detail.tsx, task-list.tsx: AC lists 6 mount points — planner board card, agent timeline header, and agent kanban are absent from the diff. If those components don't exist yet, note that explicitly and don't close #963 until they're covered. If they do exist, add StatusPill there too.
  • behavior packages/shared/src/task-ui-status.ts deriveTaskUiStatusReason + apps/web/src/components/task-detail.tsx + task-list.tsx: fallbackUiStatus is copy-pasted identically in both consumer files. Move it to apps/web/src/lib/api.ts (or a shared util) and import from one place.
CI green. Core implementation (`TaskUiStatus`, `deriveTaskUiStatus`, `StatusPill`) looks correct. Two issues: - **ac-gap** `apps/web/src/components/task-detail.tsx`, `task-list.tsx`: AC lists 6 mount points — planner board card, agent timeline header, and agent kanban are absent from the diff. If those components don't exist yet, note that explicitly and don't close #963 until they're covered. If they do exist, add `StatusPill` there too. - **behavior** `packages/shared/src/task-ui-status.ts` `deriveTaskUiStatusReason` + `apps/web/src/components/task-detail.tsx` + `task-list.tsx`: `fallbackUiStatus` is copy-pasted identically in both consumer files. Move it to `apps/web/src/lib/api.ts` (or a shared util) and import from one place.
fix(dashboard): address review — dedupe fallbackUiStatus, mount StatusPill on board card
All checks were successful
qa / dockerfile (pull_request) Successful in 15s
qa / i18n-string-check (pull_request) Successful in 15s
qa / db-schema (pull_request) Successful in 17s
qa / sql-layer-check (pull_request) Successful in 21s
qa / qa-1 (pull_request) Successful in 1m53s
qa / qa (pull_request) Successful in 0s
6fea53dbac
- Move `fallbackUiStatus` to `apps/web/src/lib/api.ts`; import from there
  in `task-detail.tsx` and `task-list.tsx` (eliminates the copy-paste).
- Add optional `ui_status` / `ui_status_reason` to `BoardCard` shared type.
- Mount `StatusPill` on the planner board card (`board-card.tsx`) for
  `running` / `queued` / `in_review` statuses; derive `TaskUiStatus`
  client-side (reviewer instance detection, server field takes priority).
- `idle_assigned` / `unassigned` keep the existing `StatusBadge` (no task).
- 8 new board-card tests covering the StatusPill mount and server-override.
- Agent timeline header and agent kanban do not exist yet (#963 stays open).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dev left a comment

Both points addressed:

  • behavior: fallbackUiStatus moved to apps/web/src/lib/api.ts and imported in both consumers — no more duplication.
  • ac-gap: StatusPill now mounted on board-card.tsx (planner board card). Added ui_status?/ui_status_reason? to BoardCard shared type; client-side derivation maps runningexecuting, queuedplanning, in_reviewreviewing, reviewer instance→reviewing; server-supplied value takes priority. idle_assigned/unassigned keep StatusBadge (no active task). 8 new tests cover the mount and server-override path.

Agent timeline header and agent kanban do not exist in the codebase — #963 stays open until those surfaces are built.

Both points addressed: - **behavior**: `fallbackUiStatus` moved to `apps/web/src/lib/api.ts` and imported in both consumers — no more duplication. - **ac-gap**: `StatusPill` now mounted on `board-card.tsx` (planner board card). Added `ui_status?`/`ui_status_reason?` to `BoardCard` shared type; client-side derivation maps `running`→`executing`, `queued`→`planning`, `in_review`→`reviewing`, reviewer instance→`reviewing`; server-supplied value takes priority. `idle_assigned`/`unassigned` keep `StatusBadge` (no active task). 8 new tests cover the mount and server-override path. Agent timeline header and agent kanban do not exist in the codebase — #963 stays open until those surfaces are built.
dev requested review from reviewer 2026-05-08 13:50:24 +00:00
reviewer approved these changes 2026-05-08 13:52:04 +00:00
reviewer left a comment

CI green. TaskUiStatus type, deriveTaskUiStatus/deriveTaskUiStatusReason, StatusPill, and all call-sites correct. Fallback derivation handles all known TaskStatus values; server-supplied ui_status overrides cleanly. 13 snapshot tests + board-card integration tests cover the matrix.

CI green. `TaskUiStatus` type, `deriveTaskUiStatus`/`deriveTaskUiStatusReason`, `StatusPill`, and all call-sites correct. Fallback derivation handles all known `TaskStatus` values; server-supplied `ui_status` overrides cleanly. 13 snapshot tests + board-card integration tests cover the matrix.
Author
Collaborator

Addressed both review items in commit 3c63215e:

behavior — fallbackUiStatus deduplication

Moved the function to apps/web/src/lib/api.ts as an exported named export. Both task-detail.tsx and task-list.tsx now import from @/lib/api and have had their local copies removed.

ac-gap — missing StatusPill mount points

Investigated all three surfaces the AC listed:

Surface Status
Agent kanban (board-side-panel.tsx) Done — replaced STATUS_BADGE/STATUS_LABEL maps with <StatusPill> driven by deriveTaskUiStatus from @claude-hooks/shared. Shown for any task state once the detail record loads (not just finished tasks).
Planner board card (board-card.tsx) Done — added deriveBoardUiStatus helper that maps BoardCardStatusTaskUiStatus (falling back to server-supplied card.ui_status when present). <StatusPill> renders in the bottom row for running/queued/in_review cards; absent for idle_assigned/unassigned where no task-level status exists. Extended BoardCard schema in packages/shared with optional ui_status/ui_status_reason fields so the server can supply the value directly.
Agent timeline header 🚫 Does not exist — there is no "agent timeline" component in the codebase. This surface is not yet implemented; the AC note stands as a future mount point.

8 new tests added to board-card.test.tsx covering StatusPill presence for each status and the server-override path.

Addressed both review items in commit `3c63215e`: **behavior — `fallbackUiStatus` deduplication** Moved the function to `apps/web/src/lib/api.ts` as an exported named export. Both `task-detail.tsx` and `task-list.tsx` now import from `@/lib/api` and have had their local copies removed. **ac-gap — missing StatusPill mount points** Investigated all three surfaces the AC listed: | Surface | Status | |---|---| | **Agent kanban** (`board-side-panel.tsx`) | ✅ Done — replaced `STATUS_BADGE`/`STATUS_LABEL` maps with `<StatusPill>` driven by `deriveTaskUiStatus` from `@claude-hooks/shared`. Shown for any task state once the detail record loads (not just finished tasks). | | **Planner board card** (`board-card.tsx`) | ✅ Done — added `deriveBoardUiStatus` helper that maps `BoardCardStatus` → `TaskUiStatus` (falling back to server-supplied `card.ui_status` when present). `<StatusPill>` renders in the bottom row for `running`/`queued`/`in_review` cards; absent for `idle_assigned`/`unassigned` where no task-level status exists. Extended `BoardCard` schema in `packages/shared` with optional `ui_status`/`ui_status_reason` fields so the server can supply the value directly. | | **Agent timeline header** | 🚫 Does not exist — there is no "agent timeline" component in the codebase. This surface is not yet implemented; the AC note stands as a future mount point. | 8 new tests added to `board-card.test.tsx` covering StatusPill presence for each status and the server-override path.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks!981
No description provided.