P0 RESIZE KEYS: a keyboard resize press starts its spring in the key's own turn (first frame in the next refresh)
Summary
P0 RESIZE KEYS (cmux-ad; lead 2026-11-02 21:1xZ, Lawrence's case: "the first frame of the move is in the next refresh after the key"). A keyboard resize press (resizePane*, Ctrl-Shift-H/J/K/L and Ctrl-Cmd-arrows) wrote the layout model; the layout heard it through its observation task, a later main-actor turn, so a display tick that ran first moved nothing and the first moved frame came a refresh later. PaneResize.press now calls LayoutRootView.syncWithModel() after the model write (the call the App already makes after a daemon tree, so a split's frame has its panes): the spring starts in the key's own turn and the very next display frame moves. The observation finds nothing new afterwards; no extra layout work.
Measured (films at 120 Hz, real HID keys, before = base ddcaf92 build fddf4464, after = this fix + K3 hold build f44441a2, same minis): the first film frame that shows the move, median 2.81 -> 2.00 refreshes after the key (max 4 -> 3). A divider drag, which moves panes in its own event turn, shows 2.7 (dogfood-2f3a572-rv5-120x1/col-drag-fast): the rest is the compositor and capture pipeline, the same for every input.
Testing
On the fleet (scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext ...), compile-checks first (c8da2865 red, 88ad54f3 head: passed):
-
Red d8c15d4a863 (
KeyboardResizeFirstFrameTests): step7feeecc6f9ee88f61ff483ee(aws-m4pro-9) FAILED: the first display frame after the press did not move (.left, .right). -
Green + GUI proof (display worker gui-session-v1, CMUX_TEST_REQUIRE_GUI=1) at the exact head 1b1f02a02e4a7a511c0d1e1b2581c028bbb26130: step
2656ce63b22d79998fdd4459(cmux10s) PASSED: KeyboardResizeFirstFrameTests 2/2, KeyboardResizeShownLimitTests 2/2, PaneResizeGestureTests 4/4; 0 skipped. -
Independent review: SHIP at the exact head (comment 6590259429). Its follow-up note:
equalizeSplitslikely has the same one-refresh delay (no sync in its handler); not in this PR.
Observed / Not run
- Observed: the steps and films above (gallery: https://cmux-orchestrator-1.tail137216.ts.net/resize-videos/ rk-k3ff-k1..k5-120x2, rk-befk-*-120x2).
- Not run: a film of this fix alone (the after films carry the K3 hold too; the first-frame change is the only one on the key turn's timing).
No capture: motion timing, filmed by the RESIZE KEYS kit.
Changelog
- Fixed: a keyboard pane resize starts moving in the next display frame after the key.
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes keyboard pane resize so the spring starts in the key's own turn: the very next display frame moves the pane, instead of one refresh later.
Previously, a resize press (Ctrl-Shift-H/J/K/L, Ctrl-Cmd-arrows) wrote the layout model, but the layout only heard the change through its observation task in a later main-actor turn, so a display tick that ran first moved nothing. PaneResize.press now calls LayoutRootView.syncWithModel() immediately after the model write — the same call the App makes after a daemon tree — so the observation finds nothing new and no extra layout work runs. Adds KeyboardResizeFirstFrameTests verifying the first display frame after the press moves, for both left and right directions.