cmux NEXT: the working spinner is a faint ring with a turning sweep, not the 3/4 arc or spokes

Merged
TE
6d ago
+313-49

Leo:

  • 2026-10-31: "who even decided to put that 3/4 circle"
  • 2026-11-01, about the macOS segmented spokes: "why the f***ing did you make the spinner into this????"

So the agent working-state mark is neither the 3/4 arc (#31409 restored it) nor the spokes (#29903 swapped them in). It is now a faint full ring (22%) with a short bright sweep (80°, round caps) turning smoothly, as in Claude and ChatGPT, in native and web, so the sidebar, tabs and transcript match.

What changed

  • Native (CmuxNextDesign): a new StatusIndicatorPlan.Glyph.sweep. workingGlyph is .sweep, with sweepLength = 0.22. StatusIndicatorLayer draws a track CAShapeLayer at trackOpacity plus the sweep CAShapeLayer, and the existing .spin animation turns the sweep on the shared clock. StatusGlyphArt draws its still mask. The StatusWorkingLook restyle guard and the Codex still-ring swap follow workingGlyph, so they are unchanged.
  • Web: Spinner draws cv-spinner__track + cv-spinner__sweep for agent work. loading keeps cv-spinner__arc. The breathe/shimmer looks hide the track and sweep.
  • Unchanged: the shared-clock phase, Reduce Motion and the static look (a still mark, plus the Codex still ring), stop and cleanup (no loop when not working or hidden), the "macOS Spinner" loading style (spokes), loading's thin arc, tint, the Chief typing dots, and the unread, presence and progress marks.

Gallery

New entry agent-pane.working-spinner ("Working spinner: looks"). It shows light and dark side by side at 12, 14 and 16 px. Variants:

  • compare: all four
  • ring-sweep: (b), shipped
  • conic: (c), a conic-gradient sweep with a fading tail
  • rejected: the 3/4 arc and the spokes, for reference

Picked (b). At sidebar size (12-14 px) the conic tail fades into a grey smudge with no clear head, while the sweep's head stays crisp. The sweep also maps one-to-one onto the native CAShapeLayer mark.

Tests

  • StatusWorkingLookTests.theWorkingSpinnerIsARingWithASweepNeverTheArcOrSpokes: for every icon set, the working mark is .sweep + .spin, never .arc and never .native/.step.
  • theWorkingSweepDrawsATrackAndAShortTurningArc: the layer draws a track at about 22% plus a short sweep with round caps that turns.
  • Updated: CodexStatusIconSetTests, NoBreathingDotTests, SpinnerClockTests (working spinners across a sleep share one phase).
  • Web: spinnerTurns.test.tsx asserts the track plus sweep markup. spinner-phase and static-status-loops mount the new markup.

Risk: small and view-only. It is one new glyph case in the status indicator layer; it adds no logic or state.

🤖 Generated with Claude Code

Agent session: agent session


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Replaces the agent working-state spinner (3/4 arc and macOS spokes) with a faint full ring (22% opacity) and a short 80° bright sweep with round caps, turning smoothly on the shared clock, in both native macOS and web.

  • Adds a sweep glyph case to the native status indicator; workingGlyph now resolves to .sweep with sweepLength = 0.22, drawing a faint track plus a short turning arc.
  • Updates the web Spinner to draw cv-spinner__track + cv-spinner__sweep for agent work; loading keeps the thin arc and "macOS Spinner" keeps the spokes.
  • Breathe/shimmer looks now hide the track and sweep instead of the arc.
  • Adds a gallery board (agent-pane.working-spinner) comparing the shipped ring+sweep, a conic runner-up, and the rejected arc and spokes at 12/14/16 px in light and dark; Spinner leaves the gallery coverage allowlist.
  • Tests pin the working mark as .sweep + .spin for every icon set, verify the track opacity and sweep length, and assert the web markup.

Risk is view-only: no state or logic changes, and Reduce Motion, the shared clock, and the still look are unchanged.