cmux-next sidebar: create and close move only their own row (attention re-sort shows when it changes)
Summary
Creating or closing a workspace in the cmux NEXT sidebar made other rows slide around afterwards.
Root cause: attention ordering (notifications.attention.moveToTop, on by default) sorts rows by needs-input > failed > working > done > idle, but only in SidebarRows.show(), the structural rebuild. A status change (unread, waiting, working, done) arrives as a row patch, is written in place, and is not re-sorted. Every row whose attention changed since the last rebuild therefore moved at the next rebuild, which is usually the user's next Cmd-N or close. That move happened inside the 2 s user-intent window, so it ran on the spring along with the create or close.
Fix:
SidebarRows.patchre-sorts when a row's attention bucket changes, at the time it changes. It does this as a quiet set (SidebarModel.setSections(_:quiet:)): no spring even inside the user-intent window, and held while the pointer is over the rows (calm-sidebar-movement). A create or close then moves only its own row.- A patch that changes no bucket (title, progress, ports) costs nothing: there is a per-row bucket map.
- Any animated reload first shows a change held under the pointer in one step. A held re-sort never slides along with the user's create, close, fold or drag.
- A quiet re-sort waits while a drag, drop or landing runs. A settling drop ignores it (
loudRevision), so the settle is not cut short.
Behavior note: when a background change is being held (pointer over the list), the user's next create or close snaps instead of animating. That is the "one change, no extra movement" the report asked for.
Not in this PR: the Cmd-N row that draws at its slot and then jumps on the sidebar document (the shown lag). https://github.com/manaflow-ai/cmux/pull/21914 covers that.
Testing
All runs are fleet package-test-lane.sh suite steps with Xcode 26.6.
- Red, base plus the new test only, at
a2e7ae3a25f037a64c1391d92bc48070ed9e91e0(step42924065e1f299d0a493cbf3):anAttentionChangeReordersWhenItArrivesNotAtTheNextCreatefails (order stays w1..w4). The two motion tests were skipped on that worker (no awake display). - Green at
080afb5d20b4190fce30721a34298725d6a8ef8f(stepa5ca1dc40c7c61362dbab252):SidebarAttentionResortTestspasses 3 of 3; the motion tests ran.SidebarBackgroundChangeCalmTests,SidebarPriorityTestsandWindowCloseNeighborTestspass.RapidWorkspaceCreateTests.fiftyCmdNDrawEachRowAtItsPressInPressOrderfails. It also fails on the base3cc9733dfcfba(step6af10151d7ff57a40f485e26, with 2 issues there, including the final order). That is the placement bug https://github.com/manaflow-ai/cmux/pull/21914 targets. Here, the final order is correct.
scripts/cmux-next/prepush-gate.py: no new violations.
Review
Correctness review (subagent), first pass REVISE:
- A quiet re-sort during a drag or drop slid rows and ended the settle early. Fixed: it is held, and settling uses
loudRevision. - A held re-sort rode direct gesture reloads. Fixed:
reload(animated:)shows the held change unanimated first. - Patch cost O(n log n) on every patch. Fixed: the bucket gate.
Second pass APPROVE. Its NITs:
- Turning attention ordering on left the bucket map empty. Fixed: the next patch sorts quietly.
- The Layout comment now notes that a drop or landing in flight still springs its rows.
- Open: if focusing the newly selected row after a close clears its unread state, that row re-sorts quietly once. This is unverified in the running app.
Changelog
- Fixed: Creating or closing a workspace no longer makes other sidebar rows slide around.
š¤ Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes the cmux NEXT sidebar so creating or closing a workspace moves only that row, not the others around it.
Attention ordering (needs-input > failed > working > done > idle) only ran on structural rebuilds, so a status change arriving as a row patch stood in place until the next rebuild ā usually the user's next create or close ā which then slid every row whose attention had changed. Now a patch that changes a row's attention bucket re-sorts immediately, as a quiet set: no spring, and held while the pointer is over the rows.
- A quiet re-sort waits during a drag, drop, or landing, and a settling drop ignores it so its spring isn't cut short.
- Any animated reload shows a held re-sort in one step first, so it never rides the user's create, close, fold, or drag.
- Title, progress, and port patches cost nothing: only a bucket change triggers a re-sort.
- Behavior note: with a background change held under the pointer, the next create or close snaps instead of animating.
- Not in this PR: the Cmd-N row drawing at its slot and then jumping on the sidebar document (PR #21914).