Hover rules in Rust, step B: Swift calls the Rust hover rules; the Swift reducers are deleted
Step B of the hover FFI move (B8): the app's hover rules now run in Rust. Step A (#31927) landed the Rust rules and their C ABI, and the re-pins #32391 and #32459 put them in the app's CCmuxAppFFI. This PR switches the Swift types to call them and deletes the Swift copies of the rules. Nothing the person sees should change: the same rules, the same timing values, now in one place.
This PR changes no Rust: git diff origin/feat-cmux-next...HEAD -- cmux-tui is empty, and Package.swift's pin is feat's. So the Rust panic step does not apply.
What changes
The public Swift API stays the same, so HoverCardCoordinator, HoverCardPanel, TooltipPresenter and their tests do not change.
HoverCardMachinekeeps the Rust machine's state as the C struct and callscmux_hover_card_reduceonce per event (no JSON, no heap for effects).HoverCardHandlesmaps eachHoverTargetIDto the 64-bit handle the rule compares, and converts events and effects.HoverIntent(tooltips) callscmux_hover_intent_call(HoverIntentHandlesholds the target handles).CGRect.isAimedAtcallscmux_hover_is_aimed_at.HoverCardEscapeGeometry(init, zone, room, rowBand, edgeGap) calls the C functions.keepsCard(at:)reads the Rust zone and maps it, with no rule of its own.rowGapstays a Swift constant (0 pt): the C ABI exports no row gap, and moving one design token would need a new step A.HoverCardTimingandHoverIntentTiming.standardreadcmux_hover_timing; the tunables' seconds go throughcmux_hover_duration_from_seconds.GroupHoverCardSummary.makecalls thegroup_hover_summaryJSON op once per card show (GroupHoverCardSummaryWire) and puts its typed lines into the localized strings.webviews/test/hover-intent-parity.test.tsreads cmux-motion'shover/timing.rs, and two comments inwebviews/src/ui/hoverIntent.tsname it. This is this PR's own diff, not the feat merge's: the pages keep a copy of the native hover timing (HOVER_INTENT), and the test that holds the two equal readHoverIntent.swift. That Swift file no longer holds the numbers (they come from Rust), so the test now reads the Rust file. The values are unchanged (450, 500, 200 and 300 ms).plans/cmux-next/layer-ownership.md: the hover card and tooltip rules are Rust's; hit tests, the timer and the panel stay Swift's.HoverCardSweepBench(off unlessCMUX_HOVER_SWEEP_BENCH=1) measures the main-thread cost per pointer move of a sidebar sweep, for the perf A/B below.
Swift logic lines
python3 -I scripts/cmux-next/swift-logic-lines.py --repo . --rev <sha> --json:
| sha | swift_logic_lines | mirror_lines | unlisted lines | |
|---|---|---|---|---|
| base (merge base with feat) | 736181335c94 | 421367 | 71121 | 172468 |
| head | f7d0d978de25 | 420569 | 71121 | 172468 |
-798 logic lines. The C glue and the JSON wire are their own declarations, classified PLATFORM in plans/cmux-next/swift-logic-classes.tsv. The bench added since is a test file (not counted).
Tests
- Swift compile at the head: job 7f664a66c0e59bf8fe0f4bca (result here when it ends).
- Swift suites on a Mac (proof-step.py): WorkspaceHoverCardBehaviorTests, HoverCardEscapeGeometryTests, HoverCardRowAlignmentTests, HoverCardWindowClampTests, HoverCardFlushTests, GroupHoverCardSummaryTests, TabHoverCardTimingTests, TooltipHoverIntentTests, ThemedTooltipTests and the SidebarHoverCard*Tests (job ids here after the compile passes).
bun test test/hover-intent-parity.test.tsat the head: 1 pass, 11 expect() calls.- Web lint (
python3 scripts/web_lint_prepush.py --base origin/feat-cmux-next --head HEAD, the pre-push hook's and CI'sbun run checkfor webviews) at 06911b587d06: "web-lint: web lint passed in 24.7s (webviews)". - The Rust rules' own tests are step A's (#31927).
Perf
Mini scheduler A/B, both arms on cmux18, --measurement, release build, HoverCardSweepBench: arm A the Swift rules (scratch ref rust-migration/hover-ab-base: the merge base 736181335c94 plus the bench), arm B this head. Specs rmhv-b8-ab-r1-a.json and -b.json; results here when they end. Main-thread time per pointer move must not rise.
Risk
risk:normal. Every hover card and tooltip runs through the new path; the Swift behavior suites above prove the same behavior.
Changelog
none
Observed / Not run
Observed: the merge with feat (no Rust and no pin diff), the line accounting, the pre-push gate, the web parity test and web lint.
Not run yet: the Swift compile, the Mac suites and the perf A/B (all queued above). No capture: no UI changes.