Skip to content

warp viz redesign — design spec

Look it up. The build spec for the redesigned /warp page (bob warp viz). The committed reference design is warp-viz-mock.html — open it in a browser, switch the mock state bar (live / needs you / stale / no run), and resize to 390 wide for the phone layout. The exploration canvas it came from is the “Warp Viz Redesign” artifact (dark, filled cards); where the two differ, the mock and this spec win, because they follow the bob viz design checklist.

The page today opens on the phase graph, with the session facts in a tabbed pane beside it. The operator watches runs from across the room and from a phone, with 20/200 acuity. The questions he asks the page, in order:

  1. Does it need me?
  2. What is it doing right now, and is that normal?
  3. How far along is it?
  4. What just happened?
  5. Details: plan, commits, tree, CI, issues.

The redesign puts those answers top to bottom in that order, in large type, and moves the full state graph one click down.

  • Primary reader: the operator — 20/200 acuity. Body text is the large token scale (--text-base, 24px), never --text-dense-*. The current phase is --text-3xl. Nothing is smaller than --text-xs.
  • Text size control: A− / A+ in the header step a page-local multiplier --warp-scale from 0.75 to 1.5 in steps of 0.125 (default 1). Every size and space on the page is calc(var(--token) * var(--warp-scale)), so one control scales type, spacing, targets and bars together. No px literal in the stylesheet.
  • Targets: every control is at least --space-2xl (48px × scale) tall.
# Region Shown when Collapsible Cycles
0 Header always — —
1 Needs you at least one ask yes asks
2 Run (the “now” block) always yes sessions
3 Where it is (phase map) a run is active no —
4 Acceptance · Time by phase · Activity a run is active no —
5 Context tabs a run is active no —
6 Sources line always — —

Regions 1 and 2 are <details>/<summary> drawn by renderSection in scripts/dashboard/bob-controls.js (checklist: Page controls). Collapsed, the summary still says what the region holds (see each region below). Open/closed state persists per viewer under warp-viz-view/1, every storage call in try/catch.

The cycle control (‹ 1/3 › inside a summary) is new. Build it once in bob-controls.js next to renderSection, never inline in the page: two <button type="button"> with aria-labels, a position read-out in --font-mono, wrap-around, and clicks that do not toggle the <details> (stop propagation). Arrow keys on a focused cycle button step it.

<project> · live badge · updated Ns ago · spacer · A− A+ · Copy attach · Theme.

  • Live badge: ● live in --state-active; ● stale in --state-bad (st.stale); idle in --text-muted when no active session. Always a word, never the dot alone.
  • Copy attach copies st.host.attach; hidden when there is none.
  • Title: (!) prefix and favicon swap while st.attention.waiting — keep the #1586 behaviour unchanged.
  • Removed from the header: the session <select> (replaced by the Run cycle), the kind select, view: flat/iso (moves into the full-graph view), notify (keep the behaviour, move it to the Needs-you summary as a small Notify me toggle when the Notification API is available).

Summary (collapsed and open): N need you in --state-bad · the current ask’s kind and short line (ellipsis, full text in title) · cycle.

Open body: when line (muted) · the question as a heading (--text-xl) · the detail (muted, max ~38em) · actions.

Ask list, in this order:

  1. The run’s own pending decision: st.attention when waiting — kind from the attention reason (budget_exceeded, continue?, a decision), question from reason, link to attention.issue.
  2. The project’s open asks: GET /control/asks.json?project=<name> (bob-control-asks/1, already ordered by priority then age).

Actions — the page stays read-only:

  • Answer in Control → /control?ask=<owner/repo#N> (the existing ask screen, #3820), primary.
  • Copy attach for the run’s own decision.
  • No answer buttons on /warp itself. (The canvas showed option buttons; they are deferred until Control’s ask screen exposes an answer endpoint.)

If asks.json is available: false, the region still renders the run’s own ask and the Sources line names asks as not read. It never says “nothing needs you” while a source could not be read.

Summary: Run · state word (running / paused / stale, coloured active or bad) · phase label bold · session name · chunk i of n · cycle.

Cycle: the sessions from /warp/sessions.json (the #1587 scanner). Stepping navigates ?root=<worktree> like today’s switcher. With one session the cycle shows 1/1 with both buttons disabled.

Open body, two columns that wrap:

  • Main — Now · phase label (--text-3xl, --state-active, or --state-bad when stale) · time in phase · usually a–b · stale line when stale · issue link + title (--text-lg) · chunk segments · facts row (Chunk i of n · Requirement j of m · Running <age>) · muted row (host · branch).
  • Vitals <dl>, 2×2: Commits · Tokens used (percent of budget, or raw count when no budget) · CI (✓ pass / ✗ fail with the word / not measured) · Retries.

Chunk segments: one per chunk; done = --text fill, current = --state-active, to come = hairline outline. role="img" with aria-label="chunk i of n". The words under it carry the same fact.

No run: the summary reads no active run; the body says when the last run ended with a link to its session report, and the command to start one. Regions 3–5 are hidden.

The happy path as three groups, left to right, wrapping:

  • Set up (once): preflight · discover · plan · chunk
  • Chunk loop (i of n): code · docs · test · commit · drift · report
  • Finish (per requirement): req done · qa · merge · promote

Each step: name + time spent this run (--font-mono, --text-sm). Done steps: ✓ name in ink. Current: ● name, --state-active, thick underline. To come: --text-dim, —.

Side trips (blocked, budget_exceeded, awaiting_continue, aborted, prerequisites) are not drawn unless current: then the current group gains that step after the step it left, in --state-bad, with its word.

Full state graph (section head button) opens today’s SVG graph — flat and iso views, tooltips (#1740), loop counts — in a full-width section below the tabs (or a <dialog>). The graph code moves, it does not change.

Group membership is derived from the engine phases, not hard-coded in the page: add a group field (setup / loop / finish / side) and a short label to PHASE_META and serve it on /warp/graph.json with the topology.

4. Acceptance · Time by phase · Activity

Section titled “4. Acceptance · Time by phase · Activity”

Two columns that wrap (left: Acceptance over Time by phase; right: Activity).

  • Acceptance — /warp/acs.json, unchanged source. Head carries done / total. ☑ rows in muted ink, ☐ rows in full ink. Hidden when no req or no checkboxes, as today.
  • Time by phase — from the session history (today’s durations table). The testing row is split by check (#4449): its longest four checks, from the engine’s check_durations.by_check (this run’s time per check), sit indented under it on the same scale, so a long testing phase shows which check took the time. Bars in --text; the current phase’s bar in --state-active. Top six phases by time, longest first.
  • Activity — one newest-first list merging phase transitions (st.history), commits (/warp/gitlog.json), chunk starts, reports filed and loop-backs. Each row: time (--font-mono, muted) · kind word · text. Kind words: phase, chunk, commit, report, retry, plus the current phase name for the live row. Only retry (--state-bad) and the live row (--state-active) are coloured. Show 8, fold the rest with the bob-controls fold (FOLD_FIRST / FOLD_STEP).

Plan #N (only when flightplan-scoped) · Commits · Tree · CI · Issues. These are the existing PANES rows — flightplan, gitlog, tree, ci, feed — with the same endpoints, polling and #1604 error handling. The warp pane is gone: its sections are regions 2–4 now. Selected tab persists in warp-viz-view/1. Real tablist semantics: role="tablist"/tab/tabpanel, aria-selected, arrow keys move between tabs.

The draggable/collapsible utility pane and the 75/25 split are retired; the page is one column that wraps.

Every source read. or Not read: <source> — <reason>. for each of asks, acs, ci, flightplan, gitlog, issues that failed (checklist: Honesty). Includes the #1968 “server can no longer run gh” notice.

On screen Source Exists today?
Live / stale / idle st.active, st.stale, st.stale_cause (SSE /warp/events) yes
Phase label st.display_phase ∥ st.phase, label from phase_meta label: new (PHASE_META.label)
Time in phase last st.history entry’s timestamp → now yes (derive)
usually a–b p25–p75 of this phase’s duration across this project’s recent sessions new — omit the phrase when fewer than 3 samples; never invent it
Issue + title workLabel(st), title via acs.json / issues yes
Chunk i of n st.chunk.index + 1, st.chunk.total yes
Requirement j of m flightplan items done/total (/warp/flightplan.json) or scope (st.scope) yes (derive); hide when neither
Running age first st.history timestamp → now yes (derive)
Host, attach st.host.label, st.host.kind, st.host.attach yes
Branch st.branch yes
Commits st.metrics.commits yes
Tokens st.token_usage (+ .budget.remaining_pct) yes
CI current branch’s newest run in /warp/ci.json yes
Retries count of loop-back edges traversed (today’s Loops section) yes
Phase groups /warp/graph.json + PHASE_META.group group: new
Per-phase time session history (today’s durations) yes
Asks st.attention + /control/asks.json?project= yes (cross-server fetch: see below)
Ask time-out decision-timeout policy for the pending decision new — omit the clause when not exposed
Sessions to cycle /warp/sessions.json yes
Working now (workflows, their phases and agents, background subagents) /warp/activity.json (bob-warp-activity/1: the project’s Claude Code session folders, #4394) yes
Building <items> in a workflow (N agents) /warp/activity.json building, shown in awaiting_continue / discovering yes
Idle between items since HH:MM /warp/activity.json idle (over 3 min in those phases with nothing running or just ended, counted from the latest of entering them, the newest workflow end and the newest background agent stop) yes

/control/asks.json is served by the Control server, not the per-project dashboard. Either proxy it through the project server as /warp/asks.json (preferred: one origin, ?root=-aware, same #1604 error path) or fetch it cross-origin from the fleet front door. Decide in the requirement.

Checklist rules, applied:

  • Only --state-active (in flight: live badge, current phase, current chunk, current bar, live activity row) and --state-bad (needs you, stale, retry, failed CI, a side-trip step) colour anything.
  • Done reads in plain ink with ✓; to come reads in --text-dim. Every coloured value is also a word or glyph.
  • No card fills, no borders around regions or rows. Hairline rules only under section heads, the tab list and activity rows. Controls have borders.
  • Both themes. Dark and light state pairs validated with the dataviz validator, as /bob is.

Same page, same order. Differences:

  • Phase label drops to --text-2xl.
  • Where it is: only the Chunk loop group; done steps fold to ✓ n done.
  • Vitals stay 2×2.
  • Tabs wrap. Heads wrap. 16px side gutter. No horizontal scroll.
  • <details>/<summary> regions; cycle buttons have aria-labels; disclosure state is native.
  • Visible focus ring (3px --state-active) on every control and link.
  • Links underlined; never colour alone.
  • Chunk segments and bars are role="img" with a label, or aria-hidden beside an equivalent text fact.
  • The (!) title prefix and favicon swap stay as the out-of-tab signal.
Today Redesign
Phase graph as the main surface (flat/iso) Behind Full state graph; unchanged code
warp utility tab (meta, burn, ACs, durations, loops) Regions 2–4
This project elsewhere fleet links Dropped from /warp — bob viz / BoB Control own the fleet
flightplan · feed · gitlog · tree · ci tabs Context tabs (feed renamed Issues)
Session <select> + all sessions link Run cycle; all sessions link moves into the Run summary
Attention banner Needs-you region (first ask)
Dispatch drawer, terminal drawer Unchanged, below the tabs — out of scope here
kind select (decompose / do machine screens) Unchanged behaviour; machine screens render in place of regions 3–5
Utility pane drag-resize / collapse Retired

Copy the bob viz design checklist into the requirement. One box does not hold as written and needs a decision issue linked from the requirement:

  • Type and spacing — “sizes come from --text-dense-*”. /warp uses the large scale (--text-*) times --warp-scale, for the operator’s acuity. Proposed rewording: a page uses one scale from design-tokens.js; /bob uses dense, /warp uses large; a page-local multiplier is allowed when it multiplies tokens and never introduces a px literal.
  • tests/test-warp-viz-*.sh assertions on the utility pane’s 75/25 layout, drag-resize and the warp tab go away or move; flightplan tab visibility (#1644) and the stale treatment (test-warp-viz-stale.sh) carry over.
  • New: regions render in the order above; asks cycle and wrap; the cycle does not toggle its <details>; open state and tab persist under warp-viz-view/1; --warp-scale clamps at 0.75 / 1.5; no px literal in the page stylesheet; the Sources line names each unread source; no “nothing needs you” while asks were not read.
  • Screenshots in both themes at 1440 and 390 via node scripts/dashboard/bob-viz-shots.js (add /warp to it).
  1. PHASE_META.group + .label on /warp/graph.json; cycle control in bob-controls.js with tests.
  2. Page shell: header, --warp-scale, Run region (sessions cycle), phase map, graph moved behind its button; retire the utility pane.
  3. Acceptance / Time / Activity columns; context tabs on the existing PANES.
  4. Needs-you region: /warp/asks.json proxy, ask cycle, Sources line.
  5. Phone layout, both themes, screenshots, checklist decision issue.