Scroll the TUI with the mouse wheel, one frame per input burst

Closed
VA
17h ago
+2228-207

What

Wheel notches move three transcript rows. Motions from one terminal read fold against bounds in order, publish one followed layout-file change and render once. Prompt routing returns an owning iterator; the input loop reuses its effect storage and the file handler folds motions without another collection.

Alternate-screen setup enables SGR button-event reporting after confirming the alternate screen is active. One journal entry retains each exclusive mouse selection: protocols 9/1000/1001/1002/1003 and encodings 1005/1006/1015/1016. Before a nested SET completes, the same journal record retains resets for every possibly active selection; only a completed SET compacts it. Nested switches preserve the original selection, including displaced pixel encoding 1016 and the earlier 1000/1003 cases. The same tables drive negotiation queries, reply acceptance and restoration.

Checkpoint-only follow wakes advance cursors without rendering. Settings reload only when task selection changes; cleanup visits the previous task's UI directory by exact key range. Visible observations survive cancellation until their settings snapshot completes, including A-to-B-to-A changes during that snapshot.

These remove the classes of lossy selection restoration, per-notch collections, checkpoint-driven redraws, retained-command scans and cancellation-lost observations. Input acquisition stays on the existing production path.

Verification

  • At 32/64 notches, prompt routing allocates exactly zero objects/bytes. Warmed burst storage also allocates exactly zero objects/bytes. File-motion folding has identical allocation counts and bytes at N/2N with a selected task. Restoring each redundant collection fails the same assertions.
  • The independent baseline compares every ordered effect, editor state and observer trace. Shrinking properties compare ordered/coalesced scrolling at both bounds, layout-file persistence and rendered positions. The production multiplexer reaches exactly one actual Terminal.draw callback after input and ready follows; redraw-every-wake fails that assertion. Settings visits are exactly zero at N/2N retained commands; always-scan fails that assertion.
  • The 865d9d03b regression checks restoration immediately after a failed switch, before subsequent setup and again after Drop. Every ordered pair of reporting protocols and encodings is checked at each SET byte boundary. Removing the previous selection reset from real guard output fails the same immediate oracle.
  • An independent VT mouse model covers all original protocol/encoding combinations, nested switches and every derived setup/teardown byte failure boundary. Reset-only encoding restoration and omitted-query negative controls fail the same assertions. Unknown/permanent selections are preserved. Parser round-trip/chunk properties and mouse-selection fuzz seeds are retained.
  • Exhaustive Shuttle models exercise the real multiplexer/settings path under cancellation for A-to-B and A-to-B-to-A. Losing the pending observation deadlocks the negative control. The modeled I/O gate opens permanently after release; DFS exploration is unbounded.
  • Linux bb1 7742d2489: production paths at bb1109731 (unchanged at final head): native build 18m01s; input 37 / 0.46 s, terminal 23 / 0.26 s, decoder 6 / 0.00 s, negotiation 4 / 0.28 s, terminal library 14 / 0.18 s, frames 13 / 0.05 s, faults 3 / 0.02 s, multiplexer 2 / 0.01 s, settings visits 2 / 0.01 s, GraphCoder scroll 8 / 0.15 s, archive 1 / 0.05 s, help 2 / 0.62 s. Lifecycle Loom models 5 / 0.00 s and owner models 2 / 0.01 s; model build 33.55 s. Windows GNU proof 5m30s. Final cancellation-model refinement: 2 passed / 0.35 s, including the lost-observation negative control; native rebuild 3m45s and final Windows GNU proof 17.78 s. The integrated checks ran sequentially in one batch; the final test-model-only refinement reused unchanged production results and rebuilt the same native closure before its GNU proof.
  • macOS ivar at bb1109731: build 9.68 s; terminal library 14 / 0.22 s, terminal 23 / 0.60 s, input 37 / 0.09 s, decoder 6 / 0.00 s, negotiation 4 / 1.57 s, terminal frames 13 / 0.04 s, frame faults 3 / 0.02 s. Negative controls included; one real-terminal measurement is ignored.
  • Historical real-Windows ConPTY measurement: wheel 10/200 and PageUp x3 in 3 writes, about 2 KB and 215–223 ms; earlier main ignored wheel events and used 6 writes / 552 ms for PageUp x3. These are earlier implementation measurements, not a new current-head benchmark.

Paired command: build cargo test --locked -p acyclic-harness-tui -p acyclic-harness -p graphcoder --lib --bin graphcoder --test input --test terminal --test terminal_decoder --test terminal_negotiation --test terminal_frames --test terminal_frame_faults --features acyclic-harness/filesystem-local,acyclic-harness/native-execution,acyclic-harness/terminal,acyclic-harness/tui,acyclic-harness/test-support,acyclic-harness/grpc,acyclic-harness/search-http,acyclic-harness-tui/tui --no-run, then run the built binaries with filters routing_allocations, mouse::, tests::scroll, client::native_input, and settings_tests. Positive and negative controls use the same exact assertions with independent fixtures.

  • macOS ivar at 865d9d03b: build 25.91 s; terminal library 14 / 0.21 s and terminal 25 / 0.60 s, including negative controls. RUSTC_WRAPPER=/opt/homebrew/bin/sccache; the lane target and source copy were removed immediately after the run and absence verified.

  • Linux bb2 at 865d9d03b: native build 18.37 s; terminal 25 / 0.11 s and terminal library 14 / 0.08 s. A production-source mutant removes the prior-selection retention line, rebuilds the same terminal target (1.77 s), and the exact immediate-restoration regression fails in 0.0023 s. Candidate source and its original built test binary are restored before GNU compilation. Windows GNU proof: passed in 6m25s (TUI, Harness and GraphCoder libraries/tests). The corrected batch queued for 10m06s; the first attempted batch rejected the invalid package/feature selection before compilation, then the native command was corrected to cargo test --locked -p acyclic-harness-tui --lib --test terminal --features tui --no-run.

  • Current candidate 9651708a2 fixes the redundant-journal-copy finding: undo bytes are written into their owned buffer, retained across partial SET, then compacted in place only after SET succeeds. Ordinary alternate setup is exactly16 allocations/504 bytes, recovering the reviewed baseline from22/552. Warm nested32/64 switches add only the pre-existing device SET formatting:32/256B and64/512B. Full output bytes and independent VT restoration are checked before allocation assertions.

  • Native Windows current-head fixture: TUI build2.72s; mouse/journal11/0.047s; routing2/0.015s. Physical ConPTY32/64-notch packets decode and route in exact order with0 allocations/0B. Per-notch collection controls produce32/1792B and64/3584B and fail the same zero-work assertion. Break, close and blocked-output paths each restore physical mouse modes1002/1006, original console flags and code pages; combined runtime0.875s. Removing actual production undo writes fails the identical physical mode1002 restoration assertion in1.922s (mutant build1.359s); restoring source and the saved candidate binary passes0.766s.

  • Linux current candidate: native build12.440s; input37/0.037s, terminal27/0.120s, decoder6/0.003s, negotiation4/0.326s, terminal library14/0.083s. The actual production-copy mutant fails the same setup assertion with22/552 (candidate16/504) in0.004s and warmed32-switch assertion with64/768 (candidate32/256) in0.003s; mutant build4.355s. Original source and candidate binary were restored before the Windows GNU libraries/tests check, which passed in11.213s. Candidate ordinary suites were not recompiled or rerun in the control continuation.

Current-head macOS validation (9651708a2)

  • ivar with RUSTC_WRAPPER=/opt/homebrew/bin/sccache and the sole lane target ~/mac-target/tui-perf: native build 617.499 s. Terminal library 14 / 0.617 s, terminal 27 / 0.776 s, input 37 / 0.259 s, decoder 6 / 0.159 s, negotiation 4 / 1.525 s. These include the mouse-selection/failure matrix and input allocation controls.
  • Full Harness cancellation models 2 / 1.898 s, production multiplexer 2 / 0.008 s, settings visit counts 2 / 0.007 s. GraphCoder scroll/allocation checks 8 / 0.346 s, help 2 / 0.148 s, full-screen differential 1 / 0.068 s, observed-layout write property 1 / 0.030 s, per-command-output negative control 1 / 0.027 s. Every suite remains below 10 s.
  • Independent paired GraphCoder render measurement (PERF_LINES=1000 <graphcoder-test-binary> tests::perf::baseline --exact --ignored --nocapture) completed 0.792 s. Wheel: per-command 2075.1 writes/event, 327 allocations/event, 103.0 us/event; frame 0.7 writes/event, 326 allocations/event, 104.0 us/event. Idle: per-command 18 writes/event, 200 allocations/event, 70.5 us/event; frame 0 writes/event, 199 allocations/event, 70.6 us/event. These bounded samples show output savings; they do not establish a CPU-speed improvement for this scene. Input routing's separate exact zero-allocation assertions cover the per-notch regression.
  • Mac journal candidate: setup exactly 16 allocations / 504 B, warmed 32/64 switches 32 / 256 B and 64 / 512 B. The actual production-copy mutant fails the same setup assertion with 22 / 552 B and the warmed 32-switch assertion with 64 / 768 B. Candidate build 8.177 s, control build 1.967 s; setup candidate/control 0.147 / 0.153 s, warmed candidate/control 0.004 / 0.004 s. Executables are selected from Cargo artifact metadata. The earlier additional control attempt selected the unchanged candidate executable and is not counted as evidence; this corrected control run completed successfully.
  • Both Mac runs removed the lane target and stable source copy immediately; absence was checked and 55 GiB free remained. No tarballs or per-commit source copies were created. Logs: Q:/lanes/co-tui-906-current-mac.log and Q:/lanes/co-tui-906-copy-mac.log.

Guarantee

  • Class: G (unfinished effects), Iv (oracle masks a fault), H (repeated allocation/work), and B (consumed observations lost across cancellation). All exclusive-selection mutations enter RestoreGuard::enable_mode; its private single record retains the possible prior and attempted selections until SET completes. The record appends directly into owned storage and compacts it in place only after successful SET. Exact allocation tests reject reintroduced copies. One input-burst fold, checkpoint-consuming multiplexer and retained pending observation own the input/settings paths.
  • Proof: exhaustive independent VT initial-state and byte-failure matrices, every ordered mouse-selection pair (the transition basis for arbitrary nested chains: completed SET leaves one possible selection, a partial SET leaves the prior/attempted pair, and failed undo retains that union), shrinking state/input/scroll properties, exact production allocation/visit/draw counts, and real-path cancellation/lifecycle models. The current journal regression is checked before later setup and after Drop. The production-source mutant removes the prior-selection retention line and must fail the same regression. Existing controls restore redundant work and lost observations. Focused suites stay under 10 s. co-dst owns the whole-system F15 scenario independently; the PR's own proof is its merge gate, per the 09:20Z ordering clarification.
  • Entry points: direct RestoreGuard::{setup,enable_mode,restore,Drop}; Unix Tty::{setup,enable_mode,restore,suspend,Drop}, split Output::Drop, and signal/lifecycle restore/resume; Windows Tty::{setup,enable_mode,restore,Drop} and Output::Drop through the console owner; all converge on the same journal. Production entry coverage uses terminal/mouse matrices, terminal PTY/library tests, lifecycle/owner models and GNU Windows compilation. Input reaches PromptInput::event -> input_burst -> file_tui_inputs/scroll_tui; command/layout/display/completion follows enter the production native multiplexer and retained settings observation. Their exact-count and cancellation suites cover those paths.
  • Gaps: none. The current-head Linux exact-work/source-copy controls, Windows GNU compile proof, real Windows ConPTY wheel/restoration checks and controls, and macOS terminal/Harness/GraphCoder allocation/model checks are complete. Native Windows checks include independent per-notch allocation and physical restoration controls; current-head Mac results and paired render measurements are above. This closes WHEEL-restore and the #906 portion of TUI-platform. co-dst owns the F15 whole-system scenario independently under the 09:20 ordering clarification; the separate #869 platform work is outside this PR.

Decisions

Preserve pushed history by merging main when GitHub reports conflicts. The current integration includes merged #923 attribute/cursor recovery. Fold motions in order because clamping is order-dependent; use the device notch rate without an extra application acceleration curve. Mouse protocols and encodings follow xterm's mutually exclusive selections.

Deletion count against current main: 202 lines removed; 2025 added across 29 files.

Live steps

None pending for #906. macOS used sccache and one lane target, and both the target and stable source copy were deleted after each run. Native Windows wheel/routing/restoration and its negative controls passed at the current head; GNU compilation is recorded separately as compile proof.