Repository navigation
Keyboard resize rules in Rust: cmux-layout-reducer shown_resize over the app FFI, proven equal to Swift on a 3,203-case corpus (step A) - #35848
Conversation
…s.swift), the geometry gathered in the wrapper; a seeded corpus test (no behavior change) The keyboard resize rules move to cmux-layout-reducer (swift-logic owner, step A). To prove the Rust port equal before the app calls it, the Swift rules first run over the values they read from the geometry: ratioRule, columnWidthRule, dockWidthRule, tradeRule (the move and the two width pairs to try; the wrapper still places each pair and keeps the first that moves only the divider) and rowHeightsRule. Each is the former method body with the geometry reads replaced by inputs, in the same order of operations. ShownResizeRangeCorpusTests records their answers for a seeded corpus (recordCorpus) and checks every case against the recorded file (corpusMatchesTheFixture); the Rust test reads the same file.
…or 3,203 seeded inputs (recorded on the fleet) Recorded by ShownResizeRangeCorpusTests.recordCorpus at f0f3cd0 (branch fix/shown-resize-record-nomerge: the same tree with record = true), fleet step 6f6123fc3742bbec3124c9f6 on aws-m4pro-3, artifact sha256 5a487a0ca811. 403 ratio, 300 width, 400 dock, 1,200 trade and 900 row cases, each kind with at least 152 answers that move.
…over the app FFI (cmux_shown_resize_*) The rules of ShownResizeRange+Rules.swift ported one operation at a time (Swift's min and max on a tie and NaN, rounded() as round half away from zero, the column width through f32 as the daemon keeps it): ratio, column_width, dock_width, trade (the move and the two width pairs to try) and row_heights. Unit tests per rule; tests/shown_resize_corpus.rs checks every case of the recorded corpus bit for bit. cmux-layout-reducer-ffi exports them as typed C calls with no allocation (cmux_shown_resize_ratio, _column_width, _dock_width, _trade, _row_heights); its test runs the same corpus through the C calls and checks the struct layouts and null pointers.
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
red: cmux-next checks (god files, concurrency, crash safety, l10n); NEW: Shipped in:
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/41930990041 at a7fac9e failed: cmux-next crash ends the app. |
|
Found 6 test failures on Blacksmith runners: Failures
|
|
Review (independent review subagent): SHIP at 9c0844a Base 2d102f8, head 9c0844a. Correctness first. I did not build or test Swift or Rust; the evidence is CI on this head, the author's fleet steps, and an independent Python port of the Swift rules (below). Checks
Findings (none blocking)
|
|
Expected red for the lander: the app FFI pin step of |
teamleaderleo
left a comment
There was a problem hiding this comment.
Review (codex gpt-6.1-sol xhigh, next-review, since=20261104T212538Z): BLOCK at 9c0844a
BLOCK at 9c0844a
Visual verdict: no images; Leo tries the build.
-
[P1] [blocking] [category:tests] [finding:F1] [outcome:pending]
ShownResizeRangeCorpusTests.swift:89(and the similar calls through line 111) passesCGFloatvalues tohex(_:), which only acceptsDoubleat line 189. Swift does not implicitly convertCGFloattoDouble, so the new test target cannot compile; convert explicitly or overloadhex. -
[P2] [follow-up] [category:correctness] [finding:F2] [outcome:pending]
cmux-layout-reducer/src/shown_resize.rs:56usesdenominator <= 0.0where the Swift rule guardsdenominator > 0. For a NaN viewport or gap, Rust falls through and returns NaN bounds instead of Swift’sDEFAULT_WIDTH; the parity tests contain no NaN cases.
Follow-ups:
- F2: preserve Swift’s non-positive-or-NaN fallback in
fraction.
…app FFI, step A: Rust port, C ABI, Swift split and parity corpus (no behavior change) (#35886) * ClosingPanes: its rules over plain numbers (ClosingPanes+Rules.swift), the geometry gathered in the wrapper; the rules ported to cmux-layout-reducer closing_panes with a C ABI (cmux_closing_panes_*); a seeded corpus test in both (no behavior change) Move 3 of the swift-logic plan (lead order): the springing-close rules of FRAME OWNER S3c/S3d leave Swift in two steps (the repo's app FFI path, as #35848). This is step A's code; the corpus of answers is recorded from the Swift rules on the fleet in the next commit. - ClosingPanesRules (Swift): the former ClosingPanes bodies with the geometry reads replaced by inputs, in the same order of operations; panes, scroll areas and row columns are numbers the wrapper hands out. The wrapper keeps ClosingPanes' API and every call site. - cmux-layout-reducer closing_panes: the same rules in Rust (Swift's min, max and Sequence.min/max kept, so ties and NaN answer the same), with unit tests. The per-frame rects reuses the handle's buffers (no allocation in steady state). - cmux-layout-reducer-ffi closing_panes: one handle per screen, typed calls, no JSON; begin and remove return 1 for an answer and 0 for none (documented beside OK), outputs written only on an answer, the Safety text forbids an out pointer overlapping an input; struct sizes and field offsets tested. - ClosingPanesCorpusTests (Swift), closing_panes_corpus (Rust) and the FFI test replay the same corpus: each call's answer and a hash of the whole state after it, bit for bit. The neighbour lists were already sorted by pane id; the gaps' min and max were read in Dictionary order (seeded per process) and are now read in pane order: only the sign of a zero gap could differ, never a value. * closing_panes: the state hash in the crate and over the C ABI (cmux_closing_panes_state_hash), so step B's Swift test still compares the whole state after each corpus call * closing_panes corpus: the answers and state of the Swift springing-close rules for 160 seeded scripts, 1,767 calls (recorded on the fleet: step cf0ccca08931af31dadbcbf3 at a5b46f9, artifact sha256 1e485a58030f) * closing_panes: a tie in Swift's min keeps its first argument (fix the unit test's expectation); clippy: plain boolean forms and Sequence.min(by:) as a loop (no behavior change; the corpus passed through both) * cmux-layout-reducer closing_panes: a NaN row travel is no travel, as in Swift (red: Rust skips only abs < 0.5, so NaN travels) * cmux-layout-reducer closing_panes: skip a NaN row travel as Swift does; read the close order with get() (panic ratchet: indexing_slicing 70 > 69)
…r over the app FFI; the Swift copy goes (step B of #35848) (#35938) * ShownResizeRange: the keyboard resize rules run in cmux-layout-reducer over the app FFI; the Swift copy goes (step B) ShownResizeRange+Rules.swift keeps its entry points and maps them to cmux_shown_resize_ratio, _column_width, _dock_width, _trade and _row_heights (one call per key press, no allocation on the Rust side; the dock and row arrays are passed in place). ShownResizeRangeCorpusTests now checks the FFI against the corpus the former Swift rules recorded in step A. Needs the CCmuxAppFFI pin that carries cmux_shown_resize_*. * swift-logic table: ShownResizeRange+Rules is PLATFORM (rule c: each rule is one cmux_shown_resize_* call), ShownResizeRange MIXED 15 (its placement check stays Swift)
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Summary
Move 2 of the swift-logic plan (lead order after 18:00Z; PL-motion-core did not take STATUS 12205): the keyboard resize rules of
ShownResizeRangemove tocmux-layout-reducer(shown_resize), called throughcmux-layout-reducer-ffi(cmux_shown_resize_*). This is step A of the repo's two-step app FFI move (as #34982, #33660): the Rust rules, the C ABI and the parity proof land now; the app keeps calling the Swift rules until theCCmuxAppFFIrelease that carries the new symbols is pinned. Step B (branchswift-logic/shown-resize-range-ffi-switch, head b83c6bd, ready) then switches Swift to the C calls and deletes the Swift rule copy.Owner: PL-motion-core (pane geometry, OWNERS.md "Layout motion"); you may take this over.
What changes:
ShownResizeRange+Rules.swift: the five rules (ratioRule,columnWidthRule,dockWidthRule,tradeRule,rowHeightsRule) over the values they read from the geometry, the former method bodies with the reads replaced by inputs, same order of operations.ShownResizeRange.swiftkeeps its API and call sites, gathers the inputs and calls them; the trade's placement check (movesOnlyTheDivider, aScreenGeometry.compute) stays in Swift. No behavior change.ShownResizeRangeCorpusTests: a seeded corpus (3,203 inputs: 403 ratio, 300 width, 400 dock, 1,200 trade, 900 rows; each kind with at least 152 answers that move) and its answers recorded from the Swift rules on the fleet, floats as IEEE-754 bit patterns, incmux-tui/crates/cmux-layout-reducer/tests/data/shown_resize_corpus.txt.cmux-layout-reducer/src/shown_resize.rs: the rules in Rust, ported one operation at a time (Swift'smin/maxon a tie and NaN,rounded()as half away from zero, the column width throughf32as the daemon keeps it), with unit tests per rule.cmux-layout-reducer-ffi/src/shown_resize.rsand the header: five typed C calls, no handle, no JSON, no allocation (catch_unwind, null checks,ERR_NULL/ERR_PANICwith nothing written).Numbers
swift-logic-lines.py(swift_logic_lines):ShownResizeRange+RulesPLATFORM (each rule onecmux_shown_resize_*call),ShownResizeRangeMIXED 15 (its placement check stays Swift). -183 against the base; the row stays red (+363 at this base) because new feat code rose since 15:38Z.Changelog
none
Observed / Not run
Observed (fleet):
fix/shown-resize-record-nomerge, this tree withrecord = true; never lands):recordCorpuspassed; artifact sha256 5a487a0ca811, the committed fixture.ShownResizeRangeCorpusTestsand all 17KeyboardResize*suites, 46 tests, passed.test/shown-resize-ffi-proof-never-merge: this head plus the FFI crate in the cmux-tui workspace, as the R-INPUT S1a proof did; never lands):cmux-tui-rust-check.sh test shown_resizestep 2e06bda6c1cd76f246f6eda1: 15 of 15 passed, both corpus tests included (Rust and C calls, bit for bit);clippystep 2546fc85bfe70b8cbe220ea6: green;fmtstep a7216178c64c: red only on base files (cmux-app-manifest, cmux-tui-core, cmux-tui link/sync_cli), none in this PR.python3 scripts/cmux-next/prepush-gate.py: no new violations.Not run:
ShownResizeRangehas no// perf-hotmark and no row inperf-hot-benches.json; it runs once per resize key press, not per frame. The step B C calls do no allocation on the Rust side; the Swift side builds two small arrays per row press, as today.CCmuxAppFFIpin (it imports the new symbols).Display fleet run (gui-session-v1)
cmux-ci run --class light --display --script scripts/ci/package-test-lane.sh --arg suite --arg Packages/macOS/CmuxNext --arg <18 suites> --ref 9c0844ac2e973b88020c27b8582fda6008efc9ef(the command of S4's display step 538dccf3f6002506fb3b7549, with the suites that exist at this head): step 777a3be61b678960b38cbaef on cmux14.local, display worker, console session: "All 18 suites passed.", exit 0.