perf(cmux CLI): workspace list reads the app window without the app's read barrier (CLI-1)
Summary
Under the TYPING UNDER LOAD L6 load (STATUS 6075, cmux20), a CLI workspace list took up to 4,173 ms (8 workers); with 32 workers (video-extra-2's base self-check) p50 903 ms and a tight cluster at 4.08-4.36 s.
Cause: after the daemon answers workspace list (or show, rename, move), the CLI asks the app which workspace its window shows (snapshot.get, the focused overlay, cli/app_focus.rs). Every CLI app request carries the read barrier after: "sync" by default (cli/app.rs with_read_barrier). The app answers it only after a MainActor.run hop, an identify round trip on its one daemon connection, and a wait for the main actor to publish a snapshot past that sequence, within its 2 s deadline (ControlRouter+Barrier.swift, AppControl+Barrier.swift). Under load the deadline passes, and the CLI asks once more (is_retryable_read): 2 s + 2 s = the 4.1 s cluster. A list waited for the app's main thread, against the rule "a list call is a read, it must never wait behind the main thread".
Fix: the overlay first reads the app's last published snapshot (after: 0), which needs no daemon round trip (the storm's plain snapshot.get took 2.5 ms p50 under the same load). The app may still refresh a stale snapshot on its main actor before it answers (fresh()), as before. Focus goes through the app's focus actions, which answer after the window moved, so a focus is in that snapshot. One daemon write can leave the snapshot behind: closing the workspace the window shows. When a workspace list of the app's session lacks the window's workspace, the overlay reads the window once more with after: "sync".
Not changed: every other CLI app request keeps after: "sync".
Owners: the cmux CLI (cmux-tui/crates/cmux-tui, no OWNERS row) and the app control router (PL-socket / app control, not changed here).
Changelog
- Fixed:
cmux workspace listno longer waits seconds for a busy app window under load.
Testing
Regression test: workspace_list_reads_the_window_without_waiting_for_the_apps_read_barrier (cmux-tui, cli/app_focus/tests.rs). A fake app answers a request with after: "sync" with its own deadline error (a busy main actor) and any other request with the window snapshot. The list must read the window in one request and set focused from it.
- Red at 71e905afd93 (test only): step 2aead6b11fc5501ea879bc28 FAILED as expected: the CLI sent 2
snapshot.getcalls, bothafter: "sync"(the first timed out, the retry timed out), sofocusedstayed the daemon's. - Green and full cmux-tui suite at 8185ff03dbd: step f574cdf961d469f5334df65f: 15,231 of 15,234 passed, the new test among them. The failures are not in files this PR touches: acpmux
usage_stats::the_session_list_and_info_carry_what_the_chats_transcript_says(base red on every head today), cmux-tuievery_safe_transport_operation_has_a_noun_first_path(workspace_group.create has catalog fields with no exercised CLI representation: a base red of feat 706ef7fff2d, the catalog op came from another PR), and acpmuxsubsessions_safety(passed when rerun alone: a load flake).
Command: cmux-ci run --class isolated --script scripts/ci/cmux-tui-rust-check.sh --ref SHA --os linux --arg test --arg workspace_list_reads_the_window_without
Review fix (first review SHIP at 8185ff03 with a Medium: after workspace close <shown>; workspace list, the fast snapshot can still show the closed workspace): when a list of the app's session lacks the window's workspace, the overlay reads the window once more with after: "sync". Test a_list_without_the_window_s_workspace_reads_the_window_again_with_the_barrier.
- Red at fe8272889f3: step 0b0f825ef5a8431668352fd5 FAILED as expected (only one
after: 0read was sent). - Green at 82312c5f64a: step 3c90020eb58a5a13f5a46cf6, app_focus and agents tests 14 of 14.
Observed / Not run
Observed: the raw L6 calls (8 and 32 workers), the code path, the red and green steps above.
Not run: an L6 round in the real app with this CLI. The A/B needs the app under load; the measurement owner (video-extra-2) has the daemon-stats capture ready for the next L6 rounds.
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes cmux workspace list waiting seconds for a busy app window under load. The list asked the app which workspace its window shows (snapshot.get) with the default read barrier after: "sync", which waits for the app's main thread; under load each attempt hit the app's 2 s deadline and the CLI asked twice, so a list took up to 4.2 s.
The overlay now reads the app's last published snapshot (after: 0), answered off the main actor. Which workspace a window shows is the app's own state, and no daemon write of the caller changes it. Other CLI app requests keep after: "sync".
Testing
- Adds a regression test with a fake app whose read barrier never settles, verifying the list reads the window in one request and sets
focusedfrom it.