bench(terminal-resize): probe the drag, accept held terminals, A/B key resizes in one launch
Summary
The terminal-resize bench (split-spring.sh --suite=terminal-resize) measured nothing in the FRAME OWNER S4 A/B. Both arms failed "no terminal resized in the drag" in every light and STRESS round (cmux24: OFF job b945a41db0fdb7242ba64532, ON job a88aa2f9047582ad48f9d6de). There were two causes:
terminalDrag.holdSurface(on by default since #32006) keeps each terminal's size and text through a divider drag. The bench drag ends where it began, so no terminal resizes in either arm. The run could not tell this case from a drag that missed the divider.- The bench counted only Ghostty's
full_resize. A held grid's new size draws through the reflow preview, which Ghostty counts asfull_swap(jobb5834b1d8ebc36c55386d7cd:full_resize0,full_swapequal to the grids sent).
Changes:
- Probe. Each drag layout first runs one drag that ends 40 pt (
--probe-pt) left of the divider, then one drag back. The probe checks that the divider moved, that a terminal fits a new grid, and that the render counters counted it. It prints its ownTERMINAL-RESIZE-PROBEline. If it fails, the layout fails before any timed round. - Resized means that
full_resize + full_swapgrew (terminal_resize_verdict.resized). - Held drag. Each drag round records
holds_terminals(debug.tunables get terminalDrag.holdSurface) as it ran. A held round needs a counted frame and a view layout count above 0, not resized terminals. - Key-resize layouts.
keyshas 4 terminals in a 2x2 grid;keys-stressuses the STRESS session. Both pressresizePaneRightthenresizePaneLeft(Ctrl-Shift-L, Ctrl-Shift-H); use--key-repeatand--key-gap-msfor a held key. Per round: frame intervals and main ms per frame (all frames, and the frames that laid out a view), missed refreshes, and per press the most grids one terminal got (debug.terminal_final_grid; a round fails when the trace does not start). - One-launch A/B.
--ab KEYruns each drag and key round with the boolean tunable off and on in one launch (debug.tunables set). The arm order alternates per round.terminal_resize_armspools each arm into p50/p95/p99/max. The bench resets KEY after each A/B layout. Each round keeps its raw per-frame arrays in the report. - bench_ab.py puts an
--abround in its arm's series (<layout>/off,<layout>/on). - One STRESS session per launch, shared by
stress,keys-stressandsplit-resize-stress(a second build refuses: STRESS has 60 workspaces in all).
The default layouts and the timed drag rounds do not change. The probe runs before the timed rounds. split-spring.sh does not change, so its measure version stays the same.
Testing
Red, then green (each red commit fails for its reason, the next commit makes it pass):
382dbb9c5b7(red: 4 failures, 3 errors) →b89e408b703: the held drag, the key layouts, the arms.bc0d8785dd7(red: 2 errors) →83b0c67714d: a swap counts as a resize.e2acda51d45(red: 2 failures in the resize tests, 1 error in bench-ab) →436bab30919: the review's findings 2, 5 and 7.
At the head 26d8678795e:
python3 scripts/cmux-next/tests/test_bench_terminal_resize.py: 25 tests pass.python3 -I scripts/measure/tests/bench-ab.test.py: 33 tests pass.
Reviews: the independent review at b89e408b703 was BLOCK (comment 6632166848, 7 findings). The re-review at 436bab30919 was SHIP (comment 6633157756): findings 1, 2, 3 and 7 fixed; 4 and 5 partly fixed (low); 6 written down. 26d8678795e changes only text: the lines the review named and two more lines of the module docstring. The short re-review at 26d8678795e was SHIP (comment 6633574554).
Observed / Not run
- Observed:
- the unit tests above, and
prepush-gate.pypasses; - a dry run against a fake app socket that holds terminals through a drag (
--layouts=keys,light --ab=motion.frameOwner.terminals): the probe line printed first, the held light drag passed, the keys arms alternated, and the key was reset after each layout; a drag that missed the divider failed at the probe and exited 1; - a real run of the earlier bench head
8c981e32979on cmux24 (jobb5834b1d8ebc36c55386d7cd): the keys layouts measured (one grid per press in both arms). Its drag layouts failed at the probe because of cause 2, which83b0c67714dfixes.
- the unit tests above, and
- Not run yet: a real run at this head. pixel-perfect's S4 A/B runs it from
fix/frame-owner-s4-abbench-nomerge(the S4 ON code plus these commits up to83b0c67714d). - Low items left open (reviews):
- with
--key-repeatabove 1, grids are counted per press window, not per press; - a timed STRESS drag that missed the divider while other views lay out could pass (the probe just before it hits the same divider);
- on a DEBUG build, the reset also removes a value the developer set before the run;
- with
--ab terminalDrag.holdSurface, the layout fielddrag_holds_terminalsshows the last arm (the verdict reads each round'sholds_terminals); - the tunable store stays active after an A/B layout (later layouts run with default values);
- no unit test runs the round loops of
measure()andmeasure_keys()(the fake-app dry runs above are their evidence).
- with
Changelog
none