Skip to content

cmux NEXT: unread ring appears steady, stays until its pane is clicked, then blinks out (classic parity, GUI agents too) - #22678

Merged
austinywang merged 8 commits into
feat-cmux-nextfrom
feat-cmux-next-unread-ring-classic
Oct 21, 2026
Merged

austinywang merged 8 commits into
feat-cmux-nextfrom
feat-cmux-next-unread-ring-classic

Conversation

@austinywang

@austinywang austinywang commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This makes cmux NEXT's blue unread pane ring behave the way Austin asked on 2026-10-20, matching cmux classic's ring.

  • Arrival: when an agent finishes, a steady blue ring appears. notifications.attention.style now defaults to steady; blink and pulse stay available.
  • Dismiss: the ring stays until you go into that pane, by clicking or typing in it or opening its notification. notifications.dismissal now defaults to click; focus stays a choice. Then the ring blinks blinkCount times and goes away, as classic's dismiss flash does. A ring cleared any other way (Mark Read, a timeout, a mute, Dismiss Highlight, another device) fades without the blink.
  • Clicks read only the clicked pane: a click reads the pane under the pointer, found with a layout hit test. A click on the sidebar, the titlebar or another pane no longer clears the focused pane's ring.
  • Finishes in a pane you can see: a turn or an OSC 7501 done that finishes in a visible pane keeps its ring under click. It posts no banner (cx-kxa2, cx-slk1h), the feed is told it didn't alert, and the timeout dismissal still gets its deadline.
  • GUI agent chats: these now ring when their turn ends. acpmux reads a turn that ends in a shown chat at once (cx-n8ou), so nothing marked the pane. AgentTurnStateStore.onTurnEnded feeds NotificationCenterService.agentFinished. Mark Workspace Read, Mark All Read and Clear All clear those rings too.

Takes back 78680d5 (pushed directly on 2026-10-19, no PR), which set the focus dismissal default. Why: Austin dogfooded it and rings cleared before he clicked the pane. Lawrence's u2414 words were also "you click and it gets dismissed".

Changelog

  • Changed: In cmux NEXT, a pane's blue unread ring appears steady when an agent finishes, including agent chats, and stays until you click or type in that pane; it then blinks out.

Testing

Command: cmux-ci run --class light --script scripts/ci/package-test-lane.sh --arg=suite --arg=Packages/macOS/CmuxNext --arg=<suites>

  • Red 22646d3 (step 7ae3e9d2): UnreadRingClickReadTests fails. A click in the other pane read the focused pane (ack surface:1), and a click outside the panes read one too. The default tests fail on focus.
  • Red fa5f7fd (step f7e502f3): no dismiss flash, and the style default was still blink.
  • Head 65aae85 (step 454e5af5): 12 suites pass: AgentTurnRingTests, AttentionDismissFlashTests, AttentionDefaultTests, PaneAttentionDismissFlashTests, AttentionSteadyTests, StaticStatusIndicatorTests, BlinkRateCapTests, UnreadRingClickReadTests, UnreadDismissDefaultsTests, UnreadRingDismissTests, WatchedDoneReadTests and AgentChatDoneDotTests.
  • scripts/cmux-next/prepush-gate.py: no new violations.

Observed / Not run

  • Observed: Austin dogfooded tags 22678-unread-ring-click-only and 22678-unread-ring-steady-flash, which led to these changes. Tag 22678-unread-ring-gui-agents (1549a2a) is with him now.
  • Not run: the generated docs/mdm/* still list the old defaults until the autofix regenerates them. The agentTurnEnded tab lookup and the observeAttention entry-read collection have no direct test. Nothing was run on the full CmuxNext suite.

🤖 Generated with Claude Code

@austinywang

Copy link
Copy Markdown
Contributor Author

Correctness review (subagent), head 8c42df8

Round 1 on the first version: FIX

  1. The shown set read state that isn't observed (focus topology, window occlusion). A tab switch in a pane without focus ran no pass, so that tab could be read later at an unrelated pass. Fixed: shownTabs(in:) reads TabSelectionMemory and LayoutModel.visiblePanes (both observed) and no longer filters on occlusion. Classic counted a rendered pane whatever covered the window.
  2. Columns scrolled off screen in a strip or canvas counted as on screen. Fixed: only visiblePanes count.
  3. An on-screen read retires the pane's approval banner. Kept on purpose: classic dismissed a visible pane's notification the same way.
  4. Test gaps (the trivial log.count assertion, no unfocused tab-switch case). Fixed: the test counts ack lines and covers a background tab selected in the pane without focus.

Round 2: PASS. Workspace switches re-run the pass through viewedRevision (SettleKey includes the topology's workspace). visiblePanes is reported in a window that is never ordered in. PaneModel.id is the TabSelectionMemory key. Optional note applied: when the stored selection names a tab that just closed, fall back to the pane's default tab.

My own check: the branch diff is 4 files (two notification service files, ProgramStatusSeen.swift and the new test). Fleet: red 6905d76 fails the two new tests (step a567469d); the fix head passes UnreadRingClassicReadTests, UnreadRingDismissTests and WatchedDoneReadTests (step 641089e8). No tagged-build dogfood was run.

@austinywang austinywang added the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Oct 21, 2026
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 1549a2a: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr22678 -f ref=feat-cmux-next-unread-ring-classic -f platform=macos -f backend_mode=local

Not verified: macOS jobs did not run: compile and app tests were skipped on 1549a2ad2a; ci-status is green without them.

CI passes on 1549a2ad2a (run 39550917171 attempt 1).
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped (the macos job needs both to succeed). Re-run CI once they pass, before merging.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

web and size checks: green

@blacksmith-sh

This comment has been minimized.

@teamleaderleo

Copy link
Copy Markdown
Collaborator

Bead cx-zo71h created for this PR by the cmux coordinator.

@austinywang austinywang removed the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Oct 21, 2026
austinywang and others added 2 commits October 20, 2026 21:57
…ped in (red)

Austin (2026-10-20): the ring must persist until he clicks into that
specific pane. The default dismissal, focus, read a pane when it merely took
focus, and a mouse-down read the window's focused tab whatever lay under the
pointer. noteMouseDown now takes the click location (still unused here), so
these tests fail until the fix: the default is still focus, and a click in
the other pane or outside the panes reads the focused pane.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed in

Austin (2026-10-20), on the dev build of the previous approach: the ring
cleared without a click; it must persist until he goes in and clicks on that
specific pane. Lawrence's u2414 words (2026-10-19) were the same: "you click
and it gets dismissed".

- notifications.dismissal defaults to click: a click in the pane, a key
  typed in it, or opening the notification reads it. Focus alone (a
  workspace switch, a keyboard move, Cmd+1-9, the palette) keeps the ring.
  focus stays a choice in Settings.
- A mouse-down reads the pane under the pointer (layout hit test over the
  visible panes), not the window's focused tab: a click on the sidebar, the
  titlebar or another pane no longer clears the focused pane's ring. A page's
  own window or a top page keeps the focused-tab read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austinywang
austinywang force-pushed the feat-cmux-next-unread-ring-classic branch from 8c42df8 to 4dc3b8f Compare October 21, 2026 05:01
@austinywang austinywang changed the title cmux NEXT: the unread ring clears like cmux classic (focused pane wherever the keyboard is, panes that come on screen) cmux NEXT: the unread ring stays until its own pane is clicked or typed in Oct 21, 2026
…age window hit-test its pane

Review findings on the click default:
- A turn that finished, or an OSC 7501 done, in a pane on screen was read at
  arrival whatever the dismissal mode, so its ring never showed. That read
  on sight is now the focus mode's; under click it posts no banner
  (cx-kxa2, cx-slk1h) and keeps the ring until the pane is clicked or typed
  in. WatchedDoneReadTests pin both modes.
- A click in a child window (a Chromium page's) hit-tests the pane in the
  workspace window it belongs to, instead of reading the focused tab.
- Overlapping panes where the click moved no focus read nothing rather than
  an arbitrary pane.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo

Copy link
Copy Markdown
Collaborator

cmux-next guards / defaults-snapshot is red on 23 of 23 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

austinywang and others added 5 commits October 20, 2026 22:10
… gets its timeout

Re-review of fc67117: the early return for a finish seen in a visible
pane skipped the feed driver's not-alerted note (the item could then be
mirrored to the iPhone though the person watched it) and the timeout
dismissal's deadline. One helper, keepSeenUnread, does both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… pane is read (red)

Austin (2026-10-20): in cmux classic a blue ring just appears when the agent
is done, and the blink plays when he goes into the pane and it dismisses;
cmux NEXT had the order switched (blink on arrival, a plain fade on read).
The overlay now hears whether its pane is focused, and a dismiss animation
seam exists that returns nothing yet, so these tests fail until the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pane is read

Austin (2026-10-20), on the click-only dev build: cmux NEXT had classic's
order switched. The ring blinked when the agent finished and simply vanished
when he went into the pane. In cmux classic a blue ring just appears, and
the flash plays as the notification is dismissed.

- notifications.attention.style defaults to steady (blink and pulse stay
  choices): the ring appears clearly visible with no blink.
- MotionGate.attentionDismissAnimation: blinkCount blinks at the peak,
  ending with no ring (one fade under Reduce Motion, none with animations
  off or no ring style).
- PaneOverlayView plays it when the mark goes away while its pane is focused
  (the person clicked or typed into it); a ring read elsewhere (Mark Read in
  the sidebar, a mute) just fades. ScreenContentView passes the pane's focus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of f47f16e: the flash keyed on the pane having focus, so a ring on
the focused pane also blinked when Mark Read, a timeout, a mute, Dismiss
Highlight or another device cleared it. NotificationCenterService now
records tabs read by a click, a key or an open (entryReads), and
WorkspaceContentController hands the layout the panes whose mark that read
removed (LayoutModel.attentionReadByEntry) just before it removes them; only
those blink. Static status indicators (cx-sya4n) get one fade instead of
blinks. BlinkRateCapTests covers the dismiss flash; stale "blink is the
default" comments updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Austin (2026-10-20): the blue attention ring should also mark a GUI agent
chat pane when the agent finishes, as it does a terminal agent's. acpmux
reads a turn that ends in a shown chat at once (cx-n8ou) and posts no
notification for it, so nothing marked the pane.

- AgentTurnStateStore.onTurnEnded: a session's turn went from working to
  anything else (the watch closing is not an end).
- NotificationCenterService.agentFinished: the chat tabs of that session,
  by ring generation; attentionMarks rings their panes. Going into the pane
  under the dismissal policy (click, key, open by default) clears it with
  the dismiss blink; Mark Read and Dismiss Highlight clear it quietly; a
  muted workspace draws no ring.

New behavior rather than a regression, so AgentTurnRingTests land with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austinywang
austinywang merged commit 3c73ce6 into feat-cmux-next Oct 21, 2026
@austinywang
austinywang deleted the feat-cmux-next-unread-ring-classic branch October 21, 2026 05:47
@austinywang austinywang changed the title cmux NEXT: the unread ring stays until its own pane is clicked or typed in cmux NEXT: unread ring appears steady, stays until its pane is clicked, then blinks out (classic parity, GUI agents too) Oct 21, 2026
@austinywang

Copy link
Copy Markdown
Contributor Author

Correctness reviews (subagents) since the first review comment. Head 65aae85.

  1. Click default (4dc3b8f), FIX:
    • Visible finishes were read at arrival → kept unread under click, with no banner (fc67117).
    • Child windows fell back to the focused tab → hit-test in the host window (fc67117).
    • Overlapping hits were picked arbitrarily → no read unless one is focused (fc67117).
    • Feed note and timeout skipped on the early return → keepSeenUnread (d031e3b).
    • Re-review: PASS.
  2. Steady ring and dismiss flash (f47f16e), FIX:
    • The flash keyed on focus, so Mark Read, a timeout or a mute on the focused pane blinked → only entry reads blink (entryReads → LayoutModel.attentionReadByEntry) (9dac6eb).
    • Static indicators → one fade (9dac6eb).
    • The flash is now in BlinkRateCapTests (9dac6eb).
  3. Entry reads and GUI agent ring (9dac6eb, 1549a2a), FIX:
    • A stale entry read could blink a later Mark Read → taken on every change (65aae85).
    • Workspace, all-read and clear-all paths left chat rings → readAgentTurns (65aae85).
    • A chat ring now needs a local or mirrored host, and focus mode skips a viewed chat (65aae85).
    • Not re-reviewed after 65aae85.

Fleet run on 65aae85: 12 suites green (step 454e5af5). Not labeled ready-to-land: waiting on Austin's dogfood and the docs/mdm autofix.

teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…made it stale (defaults-snapshot base red) (#23056)

* test: check-stamp fails a pull request only for the settings sources it changed

Red: defaults-snapshot fails every pull request and base push while the base
autofix catches up (base 6143f81: stale for Localizable.xcstrings,
NotificationModes.swift, NotificationPreferences.swift and
SettingsSchema+Appearance.swift, none of them changed by those PRs), and the
message points at a REPAIR.md row this repository does not have.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue

* cmux-next guards: a stale settings export fails only the event that changed its source

defaults-snapshot ran check-stamp on the whole tree, so once a merge landed a
settings source without its exports (d986b17, #22678, #23028; none
changed a default), every pull request and every base push was red until the
base autofix caught up, which merges minutes apart kept from happening for
hours. check-stamp --base now fails only for sources changed since the base
(the merge commit's base tip, or a push's parent) and prints the inherited
ones as a warning. The stale message names the PR autofix and
regenerate-settings-exports.sh instead of a REPAIR.md row this repository
does not have.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue

* cmux-next generated files: inherited stale settings exports warn here too; #22275 follow-ups

The generated-files job's check-stamp failed every pull request on the base's
stale exports the same way; it now passes --base HEAD^1 as defaults-snapshot
does. #22275's review follow-ups: autofix-areas.sh, regenerate-settings-
exports.sh and the generated-files comments still described check-fresh and
the snapshot, and the fork hint's `git commit -am` left files the patch adds
unstaged (now `git apply --index`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue

* test: check-stamp --base fails a head's own stamp edit and passes past 20 inherited sources

Red (review of #23056): a head that takes an old stamp passes as stale on the
base, and with over 20 stale sources the "and N more" line fails every head.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue

* defaults guard: check-stamp --base judges each stale source before the list is cut

The inherited split ran on the printed lines: a head whose own stamp entry
differs from the base's passed as stale on the base, and past 20 sources the
"and N more" line failed every head. stamp_freshness now splits the full list
and needs both the source bytes and the stamp entry to be the base's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
lawrencecchen added a commit that referenced this pull request Oct 21, 2026
…unread tab

The pane attention ring (notification blue) drew around any pane with an
unread tab, so a Markdown file shown in front of a background agent tab got
a blue ring it never asked for. Classic's ring lived on the notifying
terminal; now the ring marks a pane only while the tab the window shows in
it is unread, or is an agent chat whose turn ended (#22678). The
background tab keeps its own dot.

Co-Authored-By: Claude <noreply@anthropic.com>
lawrencecchen added a commit that referenced this pull request Oct 21, 2026
Fleet export (run-swift-testing-suites.sh export-settings) at e29cfed,
then defaults_guard.py snapshot; check-fresh passes. The export also
catches up source changes already on feat-cmux-next that were never
exported: the notification defaults of #22678 (dismissal click,
attention style steady, moveToTop off), sidebar.sessionTree (#21814),
agents.trust.*, and the inactive tab style help text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lawrencecchen added a commit that referenced this pull request Oct 21, 2026
#22678 made the ring appear steady and blink out when the person goes into
its pane. Classic also had: the dismiss flash as a double blink at full
strength (0, 1, 0, 1, 0, ease-out rises, ease-in falls), a glow on the ring
and a stronger one on the flash, settings that turn the flash off
(notifications.paneFlash) and keep typing from flashing (paneFlashOnTyping).
Reduce Motion must show a static ring with no flash. These tests fail until
the next commit.
lawrencecchen added a commit that referenced this pull request Oct 21, 2026
…low, flash settings, static under Reduce Motion

#22678 made the ring appear steady and blink out when the person goes into
its pane. This brings over what classic's ring still had:

- The dismiss flash is classic's FocusFlashPattern.doubleBlink: opacity 0,
  1, 0, 1, 0 at even key times, ease-out rises, ease-in falls, full strength.
  Classic took 0.9 s; the 2 Hz cap holds it at one flash period (1 s).
- The ring glows in its color as classic's did (0.35 opacity, 3 pt at rest;
  0.6, 6 pt while it flashes out), with a precomputed shadow path.
- notifications.attention.flash and notifications.attention.flashOnTyping
  (Settings > Notifications > Attention Ring, cmux.json); classic's
  notifications.paneFlash and paneFlashOnTyping migrate to them.
- Reduce Motion: the ring shows static at its rest and goes with no flash.

The color is notifications.attention.color, default Palette.notificationBlue
(the unread dot's token).
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…23754)

Leo (2026-10-21): "the model response does a double blue ring pulse", which
was agreed not to be the default. #22678 made an agent chat's pane ring in
the notification blue when its turn ends, even in the chat being watched,
and blink twice as the person clicks or types into it.

- The agent turn ring is opt-in: Debug Settings
  notifications.attention.agentTurnRing (AgentTurnRing.tunable), off by
  default. Off, a turn that ends in a shown chat rings nothing, as before
  #22678 (acpmux reads it at once). Terminal notification rings are
  unchanged.
- On, the ring is a hairline (one device pixel) in the pane border color
  with no glow, never the notification blue, through its dismiss flash too
  (AttentionMark.hairline).
- AgentTurnRingTests: a finished turn rings nothing by default; the opt-in
  ring is a neutral hairline and a later notification's ring is blue again.


Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 23, 2026
…chats stay calm (#23968)

* cmux NEXT: a finished reply no longer rings its chat pane by default

Leo (2026-10-21): "the model response does a double blue ring pulse", which
was agreed not to be the default. #22678 made an agent chat's pane ring in
the notification blue when its turn ends, even in the chat being watched,
and blink twice as the person clicks or types into it.

- The agent turn ring is opt-in: Debug Settings
  notifications.attention.agentTurnRing (AgentTurnRing.tunable), off by
  default. Off, a turn that ends in a shown chat rings nothing, as before
  #22678 (acpmux reads it at once). Terminal notification rings are
  unchanged.
- On, the ring is a hairline (one device pixel) in the pane border color
  with no glow, never the notification blue, through its dismiss flash too
  (AttentionMark.hairline).
- AgentTurnRingTests: a finished turn rings nothing by default; the opt-in
  ring is a neutral hairline and a later notification's ring is blue again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* cmux NEXT: the attention ring is themed and set per pane kind; agent chats stay calm

Leo (2026-10-21): "I don't think we should have blinky on turn end for GUI...
and if we have any kind of blinky, it should be themed/customizable."

- Color: the ring and its dismiss flash default to the theme accent
  (Palette.accentFill), never the fixed notification blue; a picked
  notifications.attention.color or source color still wins. The sidebar
  unread dot keeps the notification blue.
- notifications.attention.ringStyle: glow (classic's, default), ring (the
  stroke alone, no glow at rest or in the flash) or none (no ring layer).
- notifications.attention.terminals (on) and agentChats (off): which panes
  ring. agentChats replaces #23754's Debug agentTurnRing toggle and its
  hairline look, so there is one switch; off, a turn end in an agent chat
  rings and flashes nothing, and turning it off clears a ring showing.
- blinkCount keeps setting the flashes; Reduce Motion stays static.
- Settings rows, cmux.json parser, agent-settable keys and strings in 21
  languages; AttentionThemedFlashTests covers the defaults, the accent,
  ring style none and ring, the count and Reduce Motion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* cmux NEXT showcase: seeded notifications never land on the Home dock tab

live-qa (nightly 3a63d6d): the Home/Chief dock pane showed the attention ring
and its tab the unread dot with an empty chat, in scene-composer,
scene-settings and steps captures. DebugShowcase.seed posted its three
sample notifications to the focused pane's first tab, which on a showcase
launch is the home-dock page tab. They now go to the first non-page tab, or
to the ledger alone when there is none; the panel still lists them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* cmux NEXT: each pane kind has its own ring look and count; agent chats ring as cmuxterm-hq#2959 says

The debate verdict (cmuxterm-hq#2959): agent chat off by default (none);
on, a ring, not a glow, one short pulse then steady until clicked or typed
in, only on panes not being looked at; accent color, count 1, bursts
coalesced; Reduce Motion static.

- notifications.attention.terminals and agentChats are now looks (glow,
  ring, none): terminals glow, agent chats none. They replace the single
  ringStyle and the two toggles, so each kind has one setting.
  notifications.attention.agentChatBlinkCount (1) is the chat's flash
  count; blinkCount (2) stays the terminal's.
- AttentionMark.agentChat picks the pane's look in the overlay
  (AttentionSettings.surface), also through its dismiss flash.
- A turn end in the chat the person is looking at rings nothing; a finish
  within 900 ms of the last pulse rings at rest (AttentionMark.quiet).
- Tests: no mark, ring, glow, pulse or flash on an agent pane at the
  defaults; its own look and count when on; the viewed chat and the burst.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* cmux NEXT: drop the AgentTurnRing toggle the base merge brought back; catalog in base order

The squash of #23754 moved the merge base before it, so the merge took the
base's AgentTurnRing Debug tunable back (nothing reads it; agentChats
replaces it) and wrote Localizable.xcstrings in the branch's key order.
Remove the tunable again, and take the base catalog with the four new keys
inserted, so the diff is the 528 added lines only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* Rebuild the settings catalog from base plus the four attention keys

The merge driver reordered the catalog again; take base's copy and insert
only this PR's keys.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* Attention ring: look none stops a running flash; seed a terminal; prune quiet finishes

Codex review at 278ff23: switching the look to none mid dismiss-flash left the
flash and its glow running; the showcase seed could pick an agent chat tab;
quietAgentFinishes kept ids after a read, ack or dismiss.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* Attention ring: a look without glow stops a running flash glow

Codex re-review at 02cbd03: switching glow to ring mid dismiss-flash left the
flash glow animating over the zeroed shadow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
austinywang added a commit that referenced this pull request Oct 26, 2026
UnreadRingDismissTests and AgentTurnRingTests asserted the click default
from #22678; they now expect
focus to read the tab and keep the click-mode checks under an explicit
.click.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
austinywang added a commit that referenced this pull request Oct 27, 2026
…ixes #25662) (#25701)

* test(next): attention clears on selection and a showing ring stays as it is (red, #25662)

Fails on the base: the default dismissal is click, so selecting the pane or
entering its workspace keeps the ring and an event on the watched pane rings it
again; a further event on a showing ring replays its arrival swell.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(next): pane attention is one on/off state, cleared on selection (#25662)

Attention stacked: after the pane was selected the ring came back several
times before it cleared. Since #22678 the default dismissal was click, so
selecting the pane or entering its workspace kept the ring, every later event
on the pane the person was looking at rang it again, and each event on a ring
that already showed replayed its arrival swell.

- notifications.dismissal defaults to focus again, as in cmux classic:
  selecting the pane, including by entering its workspace, reads it at once
  and fully, and an event on the viewed pane sets no ring. click stays a
  choice in Settings.
- A ring that already shows stays as it is on a further event (no replayed
  animation); once cleared, a new event turns it on again.

Takes back #22678's click default at the request of its author.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Ring tests: focus is the default dismissal again

UnreadRingDismissTests and AgentTurnRingTests asserted the click default
from #22678; they now expect
focus to read the tab and keep the click-mode checks under an explicit
.click.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Overlay: a mark that arrived with no ring still shows when the look turns on

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Regenerate settings exports: focus is the default dismissal; release note says when workspace entry clears

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants