fix(tray): align status and controls with the composer

Merged
TE
5d ago
+641-130

Fixes #27908. Fixes #28875.

The running tray above the composer keeps its duration, status, Stop and disclosure on shared fixed tracks, including an empty Stop slot for ended rows. Its controls align with the default composer's Stop and microphone, using equal gaps and matching insets. Workflow progress stays beside the title so every status word starts at the same x.

Leo, 2026-10-31:

WHY WAS THIS NOT FIXED IN THE 4:01 NIGHTLY
BULLSHIT ALIGNMENT
BULLSHIT SPACING

Earlier: “align this right side's chevrons”, “IT'S SO MISALIGNED”.

Carries the needed work from #28587, #29030, #27930 and #29250, preserving commit authorship. #27930's folding is superseded by #29030's per-chat memory, and its Stop-before-chevron layout already landed through #29264. The newer one-glyph rows remain. The tray starts folded, retains the person's per-chat choice, and constructs no hidden rows after its fold completes.

Takes back #29276: this latest request explicitly calls for aligned status words, so the tray shows its status in a fixed column; other row consumers retain their current presentation.

Design: running tray, updated in leo-workspace #2038.

MetricBeforeAfterDeltaHarness
Hidden row constructions in a fully folded 300-agent tray300 per render0-300subagent-tray.test.tsx observable name-read regression carried from #29250

Validation: fleet browser geometry and web compilation pending. The geometry test compares Running, Done and Cancelled rows against the composer with a 0.5px tolerance. Required webview shards must complete before merge.

Risk: contained tray layout and folding. Existing fold focus, per-chat memory and hidden-row behavior retain regression coverage. The fold animation owns its existing cleanup; no new timers or observers.

No capture: geometry is checked in Chromium; screenshots are not a landing gate.

Agent session: agent session

🤖 Generated with Claude Code