Fix the six most common macOS hang patterns from Sentry
This PR fixes the six most common macOS app-hang patterns in Sentry over the last 14 days (0.65.x). Each pattern has its own issue, its own commits, and a regression test.
| Pattern | Issue | Fix |
|---|---|---|
| P1 SwiftUI update storm (largest; about 27% of 0.65.2 devices) | https://github.com/manaflow-ai/cmux/issues/22703 | The Bonsplit split root kept one withObservationTracking registration per SwiftUI update. After 25 updates, one change re-rendered the tree 26 times. It now keeps one live registration (https://github.com/manaflow-ai/bonsplit/pull/291, carried by https://github.com/manaflow-ai/bonsplit/pull/292). |
| P2 session checkpoint and autosave on main | https://github.com/manaflow-ai/cmux/issues/22704 | Per-candidate settings paths, UserDefaults reads, process-table lookups and file removal are hoisted or moved off the main thread. |
| P3 terminal portal re-attach | https://github.com/manaflow-ai/cmux/issues/22705 | Re-attaching an unchanged surface skips geometry, background, blur, accessibility and active-space work. |
| P4 sidebar rows | https://github.com/manaflow-ai/cmux/issues/22706 | The row height cache ignores chrome-only fields, NSTextView is used only for Markdown lines, heights are noted selectively, and WorkstreamItem lookups use a request-id index. |
| P5 welcome carousel | https://github.com/manaflow-ai/cmux/issues/22708 | https://github.com/manaflow-ai/cmux/pull/25585 already landed the cached playhead on main. What remains here takes the pager's duration from the loaded asset instead of the player. |
| P6 small blocking calls on main | https://github.com/manaflow-ai/cmux/issues/22709 | Fixes in activation policy, hotkey keyboard layout, PaneMemoryGuardrail defaults, socket marker write, remote feature flags, and the browser history merge (was O(n²)). Skipped: 3WW9 (scrubber; moving capture off main is a policy decision, https://github.com/manaflow-ai/cmux/issues/12790) and 20CS (the time is AppKit's own icon redraw; no safe fix without measuring). |
Related: https://github.com/manaflow-ai/cmux/issues/21260, https://github.com/manaflow-ai/cmux/pull/20250, https://github.com/manaflow-ai/cmux/issues/21352, https://github.com/manaflow-ai/cmux/issues/12790. This does not cover https://github.com/manaflow-ai/cmux/pull/21451, which landed separately and does not fix P1.
Merge order:
- https://github.com/manaflow-ai/bonsplit/pull/292, with a real merge commit, so
2803bccstays reachable from Bonsplitmain. It contains https://github.com/manaflow-ai/bonsplit/pull/291 and the pointermainpins today (58b73fd), which is not on Bonsplitmaineither. - This PR, after checking that
vendor/bonsplit(2803bcc) is reachable from Bonsplitmain. If https://github.com/manaflow-ai/bonsplit/pull/292 is squashed, re-pin to the landed SHA first.
Complements https://github.com/manaflow-ai/cmux/pull/22748, which also targets https://github.com/manaflow-ai/cmux/issues/22703. That PR stops the idle agent-index reload bursts that re-render every pane. This PR's Bonsplit change stops each of those renders from multiplying through leaked observation registrations. No files overlap.
Testing
Current head 5025858, P1 against today's code:
- Red: Bonsplit run 41941235173 at
35f9009, which is cmuxmain's pointer58b73fdplus only the test.SplitTreeObservationTestsfailed: 26 and 53 tree renders where 1 and 2 are expected. - Green: Bonsplit run 40420806256 at
2803bcc, the pointer on this PR.SplitTreeObservationTestspassed. - Fleet build job
28d32972c71b59dec9a5a246at5025858(tag22703-swiftui-graph-update-hang): built and installed, and the app'sCMUXCommitis5025858db. - PR CI run 41974550264 at
5025858: compile admission,swift-package-testsand all CLI regression shards passed, and so did five of the seven app-host shards. Shards 1/7 and 6/7 are red only on suitesmainalso fails:Cloud Machines header count(fix: https://github.com/manaflow-ai/cmux/pull/35974) andRemoteTmuxMirrorCloseDetachTests. Both are in main run 41915901489, and this PR changes neither. - Focused run 41952355399 at
33902b3, one test-only change set before this head: 54 tests in 3 suites passed, coveringWorkspaceContentViewVisibilityTests,WorkspaceProcessWideObserverRetirementTestsandCloudWelcomeTests.
The receipts below are from older heads, kept as history.
P1, Bonsplit CI, SplitTreeObservationTests:
- Red at
83a0903: 26 and 53 tree renders where 1 and 2 are expected. https://github.com/manaflow-ai/bonsplit/actions/runs/39540663317 - Green at
aed1a61: https://github.com/manaflow-ai/bonsplit/actions/runs/39540846201
P2 review fixes, cmuxTests/SessionScrollbackCheckpointCoordinatorTests (15 tests):
- With the fix, at
3d0a81e: passed. https://github.com/manaflow-ai/cmux/actions/runs/39542033857 - Red at
53fe696: failed as expected. Exactly the two new tests failed (interruptedCheckpointStillRemovesThePlannedStaleFile,seedBeforeTheStartupListingIsStillTracked). https://github.com/manaflow-ai/cmux/actions/runs/39542031403
P2–P6 focused suites at 3d0a81e, on owned Macs:
- P2: passed. 37 tests in 5 suites (https://github.com/manaflow-ai/cmux/actions/runs/39542321675) and 2 tests in 2 suites (https://github.com/manaflow-ai/cmux/actions/runs/39542347356).
- P5: passed, 28 tests. https://github.com/manaflow-ai/cmux/actions/runs/39542232197
- P6: passed, 74 tests in 5 suites. https://github.com/manaflow-ai/cmux/actions/runs/39552556729
- P3: passed at
0d6daeb, after the test-setup fix that waits for the runtime surface. https://github.com/manaflow-ai/cmux/actions/runs/39567263789 - P4, three earlier failures, all now fixed:
- First run, at
3d0a81e: https://github.com/manaflow-ai/cmux/actions/runs/39542257224. The existing testmetadataRowReconfigurationClearsMutuallyExclusiveStatecaught a real regression, the hidden Markdown view keeping stale text and links; fixed in9f2940a. The new testlistWideRepaintNotesOnlyRowsWhoseHeightChangedfirst applied at clip width 0; its setup was fixed in0d6daeb. - Second run, at
0d6daeb: https://github.com/manaflow-ai/cmux/actions/runs/39567284707.reapplyingUnchangedMarkdownMetadataKeepsTextStorageasserted the stale storage was kept, which contradicts the existing contract. It now expects the view to clear, at6ce3b1c. Repeated applies of the same Markdown entry are still edit-free.
- First run, at
- P4 at
6ce3b1c: passed, 109 tests in 3 suites. https://github.com/manaflow-ai/cmux/actions/runs/39581316781
Observed / Not run
- Observed:
- Bonsplit red and green runs.
- P2 red and green runs.
- P2–P6 focused app-host suites, all green on the head commits above.
- cmux-ci package steps.
- Fleet build of
3d0a81e(compiled, signed, packaged). - Correctness reviews (comments below).
- Base-red checks on
mainforAgentLaunchEnvironmentPolicyandSettingsRowAnchorResolution(comment below).
- Not run:
- P2-P6 focused suites were not rerun individually on
5025858; PR CI on the head covers them. - Field proof: no release contains this fix, so Sentry can't show its effect yet.
- Live-app dogfood of the render storm; the regression test hosts real SwiftUI in a window instead.
- Per-pattern red runs for P3-P6; those regression tests were committed alongside each fix.
- P5 changes a carousel's timing source; no visual change is intended.
- P2-P6 focused suites were not rerun individually on
No visible UI change is intended.
Changelog
Fixed: fewer app hangs from split-view re-render storms, session checkpoints, terminal re-attach, sidebar rows, the Cloud welcome carousel and blocking main-thread calls.
🤖 Generated with Claude Code
Summary by CodeRabbit
-
Bug Fixes
- Improved reliability of session restoration, scrollback checkpoints, agent status tracking, and terminal visibility.
- Preserved existing sidebar row heights during presentation-only updates, while still resizing rows when their content changes.
- Prevented unnecessary rewrites of unchanged socket markers and redundant preference updates.
- Improved browser history merging and shortcut key resolution.
-
Performance
- Reduced unnecessary work when updating terminal surfaces, sidebar content, and session snapshots.
- Made request identity lookups and agent liveness checks more efficient.