Skip to content

Unify the task status system (2 enums, 4 color vocabularies, hardcoded hexes, fails contrast on light theme) #202

Description

@johannesjo

Problem

Task/agent status is expressed through four parallel color/label systems with hardcoded hex values scattered across files — and the colors fail contrast on the light theme because they bypass the token system entirely.

Fragmentation:

  • Two overlapping enums: TaskDotStatus ('busy'|'waiting'|'ready'|'review') and TaskAttentionState ('idle'|'active'|'needs_input'|'error'|'ready'|'review') — src/store/taskStatus.ts:110-111. StatusDot.tsx:6-15 merges them with attention overriding status; the result is that "agent working" renders as muted gray (busy) or accent (active) depending on which code path computed it.
  • Hardcoded status hexes outside the theme: #c084fc and #e5a800 in StatusDot.tsx:10,12,25; #c084fc duplicated again in Sidebar.tsx:68.
  • TaskStepsSection.tsx:11-15 defines five more phase colors (#fb923c, #60a5fa, #c084fc, #e5a800, #f87171).
  • SubTaskStrip.tsx invents its own tone system with #f87171 (:101) and #22c55e (:157,168) plus / glyphs instead of StatusDot.
  • TaskTitleBar.tsx:39-66 re-expresses the same landing states as text badges with different labels; PR/CI checks use a fourth dot+spinner vocabulary (TaskBranchInfoBar.tsx:125-181, TaskTitleBar.tsx:262-325).

Contrast & accessibility:

  • On the islands-light preset (white --bg-elevated, styles.css:445): #e5a800 = 2.11:1, #c084fc = 2.64:1 — both fail WCAG 1.4.11 (3:1 for non-text UI indicators). Status dots are the app's primary signal and are near-invisible on the light theme.
  • StatusDot is a bare <span> with only title= — not focusable, no role="img"/aria-label (StatusDot.tsx:51-63), and ready/review/waiting differ only by hue (indistinguishable under deuteranopia).

Proposed fix

  • One status module: a single ordered enum (error > needs_input > review > working > ready > idle; landing as a separate lifecycle dimension).
  • One --status-* theme token per state, with a light-preset override; delete the hardcoded hexes. This also makes status themable by the custom-theme feature, which currently can't reach these colors.
  • All surfaces (StatusDot, sidebar, SubTaskStrip, title-bar badges, desktop notifications) read from that module.
  • role="img" aria-label={getDotTooltip(…)} on StatusDot (one line), and a secondary non-color channel (dot shape or a short text badge) for ready/review/waiting.

From a full design/UX audit (2026-07-07); adversarially verified, contrast ratios recomputed. Line numbers as of b342bbd (v1.12.0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestuxUX / design improvements

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions