Skip to content

Latest commit

 

History

History
181 lines (150 loc) · 10.5 KB

File metadata and controls

181 lines (150 loc) · 10.5 KB

Design System — Agent Orchestrator

This document supersedes the previous "Warm Terminal" system. AO's design language is Mission Control: a calm, high-signal control room for supervising a fleet of autonomous agents. The earlier warm-neutral direction (Geist Sans, amber/orange orchestrator CTA, brown-tinted surfaces) is retired. This file is the single source of truth — there is no second package-level DESIGN.md. Origin: the dashboard design-language exploration in docs/design/dashboard-language.md and its canonical mockups (kanban.html, session.html).

Product Context

  • What this is: A web dashboard for supervising fleets of parallel AI coding agents. Each agent gets its own git worktree, branch, and PR. The dashboard is the operator's single pane of glass.
  • Who it's for: Developers running 10–30+ agents in parallel. It must stay calm and glanceable with 20+ agents running.
  • Project type: Next.js 15 (App Router) + React 19 + Tailwind v4. A kanban fleet board (home) and a per-session detail view.

Concept & Identity

A calm, high-signal control room. Linear-grade restraint, dense but humane. State is glanceable, not noisy.

The blue/orange split. The mascot is the Claude Code character recolored blue — the conductor. This drives a deliberate two-color semantic split:

  • Blue = the orchestrator (AO itself / "you"). Brand, the single solid-fill primary CTA (the Orchestrator button), active selection, focus, links.
  • Orange = the agents being conducted. The per-agent identity and the working status — the one "an agent is alive right now" signal (a gently breathing dot, the terminal cursor).

Blue does not replace orange; they mean different things. The board reads as a blue conductor surrounded by orange agents.

Color discipline

Color = meaning. Most states get none. The UI is grayscale by default; color is rationed so it always signals something.

Token Hex Use
Blue #4d8dff orchestrator / you — primary action, selection, focus, links (the only solid-fill button)
Orange #f59f4c a working agent (status dot + terminal cursor)
Amber #e8c14a needs-your-input / attention (incl. unresolved review comments, changes requested)
Red #ef6b6b failing / stuck (CI failed, crashed, conflicts)
Green #74b98a mergeable / passed / resolved
Neutral grays everything healthy & passive: in-review, idle, done, metadata

Diff add/remove green & red are permitted in their literal context (the Changes view).

Surfaces & lines (dark, cool neutral)

The product is dark-only mission control. The dark theme is authoritative.

Token (literal) Value Maps to semantic token
--bg #0a0b0d --color-bg-base (app base)
--bg-side #08090b --color-bg-sidebar
--card #15171b --color-bg-surface / --color-bg-cardthe only bordered surface
--card-hover #191b20 --color-bg-elevated / -elevated-hover
--col #0e0f12 --color-column-bg (kanban trough)
--term #0c0d10 xterm background (terminal-themes.ts)
--line rgba(255,255,255,0.06) --color-border-subtle / -default
--line-2 rgba(255,255,255,0.10) --color-border-strong
--t1 … --t4 #f4f5f7 #9ba1aa #646a73 #444951 --color-text-primary/secondary/tertiary/muted

These literals live at the top of the .dark block in packages/web/src/app/globals.css; the existing --color-* semantic tokens alias them, so all consuming CSS keeps working. Don't rename the semantic tokens — add/alias and migrate.

Typography

Self-hosted via next/font/local (packages/web/src/fonts/). No external font CDN.

  • UI = Schibsted Grotesk (--font-sans). The product voice. Used for all chrome: titles, labels, buttons, body. A distinctive grotesk — not Inter/system.
  • Machine = JetBrains Mono (--font-mono). Branches, IDs, PR numbers, costs, timestamps, terminal — anything the machine emits.
  • Numerals: tabular-nums wherever numbers appear (counts, costs, tokens).
  • Never render chrome in mono. The sans/mono split is itself a design device: product voice vs. machine voice.

(Geist Sans is removed. JetBrains Mono is no longer used for display headlines.)

Status as one system

A single semantic spectrum maps the canonical lifecycle to a {tone, label} pair and is used everywhere — kanban card badge, sidebar dot, session topbar pill. It lives in lib/status-spec.ts (getStatusSpec) and renders through StatusBadge.

Tone Color Meaning
working orange (breathing) an agent is alive right now
input amber needs your input
changes amber changes requested
fail red CI failed / stuck / crashed / conflicts
review neutral in review / waiting on a reviewer
ready / merged green mergeable / landed
neutral gray idle / done / terminated

Tone is refined from the (tested) attention-level bucket so a card's badge never disagrees with the column it sits in.

Layout patterns

Fleet board (home) — kanban.html

  • Lead with the fleet, not the terminal. Answers "what are all my agents doing?" at a glance.
  • Frameless columns: lifecycle columns Working → Needs you → In review → Ready to merge are borderless tinted troughs with a faint per-column semantic top-glow. The card is the only bordered surface — no box-in-box.
  • Compact cards: status badge + id, task title (2-line clamp), branch, a thin footer. Done/Terminated collapses at the bottom.
  • The sidebar always shows all projects' sessions; the board filters client-side. The SSE refresh interval is 5s (unchanged — C-14).

Session detail — session.html

  • Framed terminal as a real surface (header + viewport), flush to sidebar/topbar. It is a live xterm.js/PTY — we do not style its content; we only set the frame and the xterm.js theme object (background --term, orange cursor, blue selection, a 16-color ANSI palette tied to the tokens — see terminal-themes.ts). Claude Code's own input lives inside the terminal; there is no separate composer.
  • Pluggable inspector rail (a registered-view slot): SessionInspector with views Summary · Changes · Browser; adding more (Logs, Cost…) is just another entry.
    • Summary is ordered by supervision value: Pull request → Review comments → Activity → Overview (the PR card bundles PR + review comments).
    • Review comments surface a soft-blue Address action (askAgentToFix) that hands the comment — with its file:line — to the agent session to fix.
    • Browser is reserved for a web-preview / Playwright plugin.
  • Topbar: ‹ Kanban (back) · title + inline branch · status pill · notifications · Kill (trash) · Orchestrator (blue primary, org-chart icon).

Iconography & motion

  • Line icons only (Lucide-style, ~1.6px stroke, currentColor, inline SVG). No emoji.
  • Motion is minimal & purposeful: a slow CSS-only "breathe" pulse on the working dot / terminal cursor (@keyframes breathe, 2.4s). No animation libraries (C-07). All motion respects prefers-reduced-motion: reduce.

Web Implementation Rules

  • Tokens over raw values. Use the --color-* semantic tokens (or the literal --bg/--card/--t1… palette) from globals.css. No hardcoded hex/rgba in components.
  • No inline style= for theme values (C-02). Tailwind utilities with var(--token), or a named class in globals.css.
  • No external UI kits (Radix, shadcn, Headless UI, …) (C-01).
  • Tailwind vs CSS classes: Tailwind for one-off layout/spacing; add a class in globals.css when a pattern is theme-sensitive, uses pseudo-elements/gradients, or repeats 3+ times.
  • App Router only (C-06). Component files ≤ 400 lines (C-04). Test files for new/changed components (C-12).
  • Dark theme is always preserved (C-05). Light-mode tokens still exist for the theme toggle but mission control is designed and tuned for dark.

Accessibility

  • Focus indicators: outline: 2px solid var(--color-accent); outline-offset: 2px on :focus-visible. Never outline: none without a visible replacement.
  • Reduced motion: @media (prefers-reduced-motion: reduce) disables animations/transitions. Non-negotiable.
  • Color independence: never encode meaning with color alone. Status badges always pair a colored dot with a text label.
  • Contrast: body text ≥ 4.5:1; UI/borders/icons ≥ 3:1. The text ramp --t1…--t3 is for primary→labels on the --bg/--card surfaces; --t4 is for faint/disabled only.
  • Keyboard nav: all interactive elements reachable via Tab; Escape closes popovers; logical order.
  • ARIA labels on all icon-only buttons.

Constraints

  • C-01: No new UI component libraries
  • C-02: No inline styles in new/modified code
  • C-04: Component files max 400 lines
  • C-05: Dark theme preserved
  • C-06: Next.js App Router only
  • C-07: No animation libraries (CSS-only motion)
  • C-12: Test files for new/changed components
  • C-14: SSE 5s interval unchanged

Decisions Log

Date Decision Rationale
2026-05-27 Mission Control supersedes Warm Terminal A single source of truth. The product is a calm control room for a fleet of agents; cool restraint + rationed color reads better at 20+ agents than warm decoration.
2026-05-27 Blue = orchestrator/you, orange = working agent The mascot is the blue conductor; orange is the Claude Code lineage. Two colors, two meanings — the product metaphor, visualized.
2026-05-27 Schibsted Grotesk (UI) + JetBrains Mono (machine), self-hosted A distinctive grotesk for the product voice; mono reserved for machine data. Self-hosted via next/font/local — no external font CDN.
2026-05-27 One status system (getStatusSpec + StatusBadge) Kanban badge, sidebar dot, and topbar pill all render from one spectrum so status never disagrees with itself.
2026-05-27 The card is the only bordered surface Frameless tinted columns with per-column glow; cards are flat --card with a hairline ring. No box-in-box nesting.