Skip to content

refactor: migrate the gesture family to the request-bound device runtime - #1952

Merged
thymikee merged 1 commit into
mainfrom
claude/wave5-gestures-cutover
Aug 24, 2026
Merged

refactor: migrate the gesture family to the request-bound device runtime#1952
thymikee merged 1 commit into
mainfrom
claude/wave5-gestures-cutover

Conversation

@thymikee

@thymikee thymikee commented Aug 21, 2026

Copy link
Copy Markdown
Member

Summary

Move gesture, swipe, and scroll to the request-bound platform runtime.

Each request binds only the operations it can execute. swipe uses the one-contact gesture plan with an admitted snapshot fallback, edge scrolling binds snapshot capture with scrolling, and the legacy scroll dispatcher and capability admission are removed. The result composes with the touch-runtime migration already on main.

Validation

Verified gesture and scroll behavior on Apple, Android, HarmonyOS, Web, Vega, AWS Device Farm, and Limrun before the rebase. The rebuilt head passes the full affected repository gate. Linux remains covered by contracts and provider scenarios; expanded live Linux gesture testing is intentionally deferred.

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 2.39 MB 2.40 MB +11.0 kB
JS gzip 802.5 kB 805.1 kB +2.6 kB
npm tarball 926.7 kB 929.4 kB +2.7 kB
npm unpacked 3.21 MB 3.22 MB +11.0 kB

npm unpacked components

Component Base Current Diff
JS / dist source 2.54 MB 2.55 MB +11.0 kB
Apple runner source/project 570.6 kB 570.6 kB 0 B
macOS helper source 54.5 kB 54.5 kB 0 B
Android helper artifacts 0 B 0 B 0 B
Other package files 44.5 kB 44.5 kB 0 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 27.5 ms 27.4 ms -0.1 ms
CLI --help 81.0 ms 80.7 ms -0.4 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/app-inventory-contract.js +3.3 kB +1.1 kB
dist/src/internal/daemon.js +2.4 kB +677 B
dist/src/interaction.js +1.9 kB +420 B
dist/src/runtime4.js +1.6 kB +378 B
dist/src/sdk-batch-runner.js +1.3 kB +337 B

Top changed packed files

Packed file Base Current Diff
dist/src/scroll-edge-state.js 3.4 kB 0 B -3.4 kB
dist/src/app-inventory-contract.js 41.1 kB 44.4 kB +3.3 kB
dist/src/dispatch.js 14.0 kB 10.7 kB -3.3 kB
dist/src/internal/daemon.js 101.5 kB 103.9 kB +2.4 kB
dist/src/interaction.js 35.2 kB 37.0 kB +1.9 kB
dist/src/keyboard-runtime.js 5.4 kB 7.1 kB +1.7 kB
dist/src/runtime4.js 43.8 kB 45.4 kB +1.6 kB
dist/src/sdk-batch-runner.js 76.7 kB 78.0 kB +1.3 kB
dist/src/gesture-admission.js 0 B 944 B +944 B
dist/src/app-log-runtime2.js 15.3 kB 16.2 kB +885 B

@thymikee

Copy link
Copy Markdown
Member Author

Not ready at da775b2e. The runtime cutover itself is coherent, but two required boundaries remain. First, this 70-file unit claims owner cells across Apple, Android, Linux, HarmonyOS, Web, Vega, Limrun, and WebDriver, while the changed-path live table covers only Apple/Android. ADR 0019’s unit guide requires a real-target result for every claimed family/owner denominator; record the missing Linux/HarmonyOS/Web/provider paths and refusal cells, or formally narrow the unit’s claims. Second, packages/platform-apple/src/runtime.ts grows by ~100 lines to 553, crossing AGENTS.md’s hard ‘extract before adding behavior past 500’ rule. Move the Apple gesture/scroll admission facts into a focused sibling owner with its matching tests, keeping runtime.ts as composition. Also refresh the size/body metadata to exact CI (+12.0 kB unpacked, 70 files) and itemize the final growth/smaller-design rejection. iOS/Android/Coverage are still running.

@thymikee

Copy link
Copy Markdown
Member Author

Addressed at 6cdff5c25.

1. Apple runtime.ts past 500 lines. Extracted the gesture/scroll cell table into
packages/platform-apple/src/gesture-facts.ts (118 lines) with its own gesture-facts.test.ts
(9 tests, moved out of runtime.test.ts). runtime.ts is 459 lines — below the 500 hard rule,
and within 6 lines of its pre-unit size (453 on main), so it stays composition.

2. Live coverage of the claimed denominator. Ran the four owners I can reach locally. Full
tables are in the PR body; the short version:

Owner Live result
HarmonyOS (nova 14) scroll / swipe / pan all move content; both refusal cells — pinch with no fact hint, drag with the target-authored-drag hint
Web (managed backend) platform smoke passes; scroll down changes 36.8% of pixels; gesture pinch and swipe refused — and swipe reports gesture fling is not supported on web, its normalized intent, exactly as the retired admission did
Vega (local VVD) all four cells refused, and it is the cleanest demonstration of the per-tier hint split: scroll→vega scroll hint, fling→vega gesture hint, pinch→no hint, drag→drag hint
Apple / Android as before, plus the macOS refusal pair

That is six owners with live coverage. Three genuinely could not be covered here:

  • platform-linux — no Linux target on this macOS host. Its bound execution is exercised
    end-to-end by request-handler-chain.test.ts, which drives a real Linux swipe through the
    composed gateway into the real createLocalLinuxToolProvider drag primitive and asserts the
    exact values [10, 20, 110, 20, 100]; the CI Linux lane covers the runtime path.
  • provider-webdriver / provider-limrun — cloud, billed. I did not spend without your okay.
    Worth noting the WebDriver provider scenario already earned its keep here: it caught a real
    defect in this unit (facts advertised scrollDirection with no bound operation).

Your call, and I'll do either: authorize the two provider cells and I'll run them for real, or I
narrow the unit's claims to the six owners with live coverage and say so in the record.

3. Size/body metadata. Body now carries the exact CI numbers — +12.0 kB unpacked, +2.5 kB
tarball, +2.3 kB gzip, 71 files
— with the growth itemized against the two real deletions
(dispatch.js −3,178 B, validation.js −3,383 B) and a stated rejection of the two smaller
designs (single performGesture keyed by tier data; folding gestureViewport into the plan
operation). My earlier local figure of +10.4 kB was wrong for the PR body — CI's build is the
authoritative one and that is what is quoted now.

pnpm check:affected --run green after the extraction.

@thymikee

Copy link
Copy Markdown
Member Author

The Apple extraction and local-owner evidence address the earlier points. One blocker remains: this head still changes the direct WebDriver and Limrun runtime cells, while its evidence expressly omits live runs for both. ADR 0019’s unit denominator includes direct provider runtimes, so we cannot narrow the claim in prose while those migrations ship. Please either run one representative changed command/refusal cell through each provider (record exact head and result), or remove those provider migrations from this unit; then re-request review.

@thymikee

Copy link
Copy Markdown
Member Author

Code review is clean at 6cdff5c25: the handler binds once per selected tier, owner facets/facts remain narrow and fail closed, and the superseded gesture/scroll dispatch and admission paths are removed. Exact-head CI is fully green.

Residual blocker to merge-ready status: this unit changes direct provider-webdriver and provider-limrun gesture/scroll facts and bindings, but the PR explicitly records no live run for either owner. ADR 0019 unit guidance requires changed-path evidence on at least one real target per claimed family, and fixture/provider scenarios do not replace it. Please either record representative direct WebDriver and Limrun live gesture/scroll evidence, or remove those provider migrations from this unit. Until then this is published/reported with strong static evidence, not merge-ready.

@thymikee

Copy link
Copy Markdown
Member Author

New blocker after main moved: this head is now 12 commits behind and conflicts across runtime/registry/dispatch surfaces. Rebase must preserve #1969’s granular contracts architecture: the PR’s new value imports from wide @agent-device/contracts/platform and missing granular exports for the new gesture/scroll modules would fail current closure gates if resolved by choosing the PR side.

Also remove the type workaround in scroll-runtime.ts: the plan.kind === edge ? bind(plan.use) : bind(plan.use) branches are identical, then widen to optional captureSnapshot and repair the lost proof at runtime. Bind/execute through the discriminated plan (or a generic plan-admission helper) so edge scroll statically requires capture and ordinary scroll cannot expose it.

All green CI and +12 kB size evidence is against the old base. After rebase, rerun the full exact-head suite and remeasure/rejustify size.

@thymikee
thymikee force-pushed the claude/wave5-gestures-cutover branch from 6cdff5c to 420d6e1 Compare August 24, 2026 09:30
@thymikee

Copy link
Copy Markdown
Member Author

Rebased onto 296447707 and reconciled with what landed since — pushed at 420d6e1ea.

#1955 collided head-on, so this is a real reconciliation rather than a replay:

Three test expectations changed for real reasons, not to make them pass:

  • request-router-replay-scope: the replay flow runs scroll down, which no longer reaches dispatchCommand. Now asserts one dispatch (app-switcher) and one bound scrollDirection call.
  • request-router-response-level case (e): scroll was the arbitrary "no registered view" command and no longer reaches the mocked dispatcher; it now drives the bound operation, and the assertion checks the owner payload passes through beside scroll's own result fields.
  • Web coverage manifest/counts re-derived on top of refactor: migrate back/home/orientation/tv-remote/keyboard to the request-bound device runtime #1955's reclassifications.

pnpm check:affected --run green. Full unit suite 1031 files / 7678 tests, 0 failures.

One process note worth flagging: the first rebase attempt silently reverted #1955's additions in platform-runtime-unavailable.tsgit rerere replayed stale resolutions recorded against an older main (686 cached entries). I caught it by diffing the merge result against origin/main, aborted, and redid the rebase with rerere disabled. Worth knowing if anyone else rebases a long-lived branch here.

The open question from your review is unchanged: Linux and the two cloud providers still have no live coverage — say the word and I'll either run the provider cells or narrow the unit's claims.

@thymikee

Copy link
Copy Markdown
Member Author

Request changes at 420d6e1.

The rebase resolves the conflicts and granular-contract import blocker, but the prior scroll proof blocker remains. scrollEdgeUse correctly requires captureSnapshot; resolveBoundScrollRuntime then executes identical plan.kind branches, widens both results to BoundScrollOperations with optional capture, and repairs the lost edge guarantee with a runtime missing-operation guard. That is not ADR 0019's selected non-optional operation projection. Split the direction/edge execution closures or use a discriminated generic helper so the edge closure receives captureSnapshot non-optionally and ordinary scroll cannot expose it; delete the widened type and runtime proof repair. Add a type-level/structural regression rather than only testing unavailable facts.

Readiness also still lacks changed-path live evidence for the direct WebDriver and Limrun gesture/scroll facts and bindings. Run representative direct changed cells/refusals for both, or remove those provider migrations from this unit. Current deterministic gates are green, but native smoke lanes remain pending. Refresh the size figures after the final change (current diff is 76 files and CI reports about +11.4 kB unpacked).

@thymikee

Copy link
Copy Markdown
Member Author

Addressed at 05573d765.

1. Scroll's edge proof is now static

You were right that the previous shape gave up the guarantee. Fixed properly:

  • ScrollRuntimePlan's edge member now carries the edge alongside the discriminant, so narrowing to edge yields the exact use and the edge value.
  • The identical branches are gone. Each branch passes its own closure: executeDirectionScroll is typed on a binding with scrollDirection only, executeEdgeScroll on one where captureSnapshot is non-optional (BoundDeviceRuntime keeps required operations non-optional).
  • The widened BoundScrollOperations type and the runtime missing-operation guard are deleted. The edge path reads runtime.operations.captureSnapshot(...) directly.
  • Ordinary scroll cannot expose a capture: keyof its binding's operations is exactly 'scrollDirection' — absent, not optional.

Both executors route their pass through a single scrollOnce owner so the cutover gate's one-owner proof for scrollDirection still holds; that costs the edge path none of its own guarantee.

Type-level regression added in scroll-runtime.test.ts: it asserts the exact required key set of each binding, not just unavailable facts. Planted-red proof — demoting captureSnapshot from required to preferred fails in two places:

Mutation Caught by
scrollEdgeUse: required: ['scrollDirection','captureSnapshot']required: ['scrollDirection'], preferred: ['captureSnapshot'] scroll-runtime.test.ts (the required-key assertion) and scroll-runtime.ts (executeEdgeScroll's signature rejects the widened binding)

Restored byte-identical.

2. Direct provider evidence — I need a decision from you

I checked whether I could run these locally rather than ask for spend. I cannot:

  • provider-webdriver ships exactly two definitions, BrowserStack and AWS Device Farm. There is no self-hosted/Appium/localhost target in the provider definitions, so it cannot be pointed at the local emulator or simulator.
  • provider-limrun is Limrun cloud.

And I do not think "remove those provider migrations from this unit" is available, for two reasons — please tell me if you read either differently:

  1. It would regress provider devices. Today gesture/scroll/swipe on a provider device reach the provider's own interactor through getInteractorgetProviderDeviceInteractor (WebDriver implements performGesture/gestureViewport/scroll; Limrun's Android leg reuses createAndroidInteractor). After this unit those commands are device-runtime with no legacy path left, so provider owners without facts+bindings would refuse them outright.
  2. ADR 0019 §6 requires them here: "one command across every runtime cell where it is currently supported: … transport-composed providers, and direct provider runtimes." Dropping the provider cells would make the unit non-atomic by the ADR's own definition.

So the compliant paths are, as I see it:

  • (a) You authorize cloud spend and I run one representative changed cell plus one refusal on each — BrowserStack/AWS Device Farm and Limrun — recording exact head and result; or
  • (b) You accept the provider cells on static evidence for this unit (owner cell tests, plus the packaged Cloud WebDriver provider scenario, which already caught a real defect here), recorded explicitly as an accepted gap.

I have not spent anything. Say which and I will finish it.

3. Size refreshed

PR body now carries the post-rebase CI figures: +11.4 kB unpacked, +2.9 kB tarball, +3.0 kB gzip, 76 files — measured against 296447707, which already contains #1955 and #1969. ~3.8 kB per migrated command, inside the R40 band. Itemized against the deletions, including one the earlier measurement did not have: LEGACY_LINUX_DEVICE_EXECUTION retires with scroll, its last consumer.

For the record, CI on the previous head 420d6e1ea finished 28/28 green, native smoke lanes included. Deterministic gates are green again on 05573d765 (pnpm check:affected --run, full unit suite 1031 files / 7679 tests); native lanes are running now.

@thymikee

Copy link
Copy Markdown
Member Author

scroll-runtime.ts simplified at 71ac805b0 — net −45 lines (279 → 234), 37 added / 82 removed.

Bound shapes are derived, not restated. The two hand-written Readonly<{ operations: … }> shapes are gone:

type BoundScrollDirection = BoundDeviceRuntime<
  Extract<ScrollRuntimePlan, { kind: 'direction' }>['use']
>;
type BoundScrollEdge = BoundDeviceRuntime<Extract<ScrollRuntimePlan, { kind: 'edge' }>['use']>;

Each binding now comes straight from its declared use, so the file no longer repeats what the use already says — and the non-optional captureSnapshot on the edge side follows from scrollEdgeUse rather than from a shape I typed out by hand. ScrollRuntimeOperations, CaptureSnapshotInput and SnapshotResult are no longer imported here at all.

Ceremony removed:

  • ScrollDistance deleted. resolveScrollExecutionOptions spreads its input, so the resolved options already carry amount/pixels — the parallel parameter was threading the same two values through four signatures.
  • scrollResult and buildScrollResult merged into one result shaping function instead of two layers.
  • Both executors now take target rather than target decomposed into loose parameters.
  • Trimmed the comments to the two that carry non-obvious information (why the bindings are separate; why one lexical owner exists for the gate). The rest was restating the code.

I kept scrollOnce. It is not decoration: the cutover gate counts literal x.operations.op(…) calls and requires exactly one owner per operation, so if both executors called scrollDirection directly the R48 row would see two. Passing the selected operations in instead would also break it — the gate matches on the .operations member expression, so operations.scrollDirection(…) counts as zero. One tiny owner is the shape that satisfies both the gate and the static proof.

The planted mutant still fails in the same two places after the simplification: demoting captureSnapshot to preferred breaks the required-key assertion in scroll-runtime.test.ts and executeEdgeScroll's signature. Restored byte-identical.

pnpm check:affected --run green; full unit suite 1031 files / 7679 tests.


On the provider item: I read "this requires authorization for cloud spend" as stating the constraint rather than granting it, so I have not spent anything. To be unambiguous — reply "authorized" and I will run one representative changed cell plus one refusal on BrowserStack/AWS Device Farm and on Limrun, recording exact head and results. If you would rather not spend on this unit, say so and I will record the two provider cells as an explicit accepted gap in the PR body and the tracker entry instead.

@thymikee
thymikee force-pushed the claude/wave5-gestures-cutover branch from 71ac805 to 860ceda Compare August 24, 2026 11:22
@thymikee

Copy link
Copy Markdown
Member Author

Rebased onto c34d27e3f and fixed the Coverage failure at 860ceda6f.

Coverage was failing for a real reason, not flake. #1965 landed the per-package eager-closure probe (for this same tracker) and #1990 replaced the façade closure test with lint + budget rows. My branch pushed 16 rows over their pins. That probe is not in the local test:unit project, which is why my local runs were green — the coverage lane runs a wider set.

Most of it was a genuine loading-shape regression, so I fixed the imports rather than moving pins:

  • gesture-tier.ts is now type-only, and its classifier moved into platform-runtime-operations.ts as a module-private function. It was a value import there, so every *-plan.ts module that imports the use catalog was eagerly evaluating one extra module. That alone cleared 9 of the 16 rows.
  • Dropped the gesture-runtime / scroll-runtime / gesture-admission re-exports from the wide platform façade. Every real consumer already imports the granular subpath, so the façade re-export was pure closure weight; the one straggler (smoke-tvos-platform-coverage.test.ts) now imports @agent-device/contracts/gesture-admission directly.

What genuinely grew, with the reason each row moved:

Row Was Now Why
contracts/apple-multitouch-support.ts 5 6 shares apple-os-display-names.ts with gesture-admission — one copy of the Apple OS wording rather than two
contracts/platform-runtime-unavailable.ts 20 22 needs both new facts factories at runtime to build the everything-unavailable catalog
contracts/facades/platform.ts 47 50 the two facts factories reach it transitively through the line above, plus the shared display-name module
src/platform-runtime.ts 36 38 composition root, two new facets

And two rows the ratchet asked me to lower, which this unit earns:

Row Was Now Why
src/core/dispatch.ts 94 90 handleScrollCommand, dispatchGesturePlan and the scroll imports retire
src/core/capabilities.ts 76 75 requireGestureSupported and its imports retire

Three new rows added for the new export surfaces: gesture-admission 6, gesture-runtime 5, scroll-runtime 4.

pnpm check:affected --run green. Full unit suite 1031 files / 7904 tests — the one failure locally is runner-client.test.ts, which this branch does not touch and which passes in isolation (it is the known wall-clock flake under contention).

The scroll simplification from 71ac805b0 carried through the rebase unchanged, and its planted mutant still fails in both places.

Provider evidence is still the one open item — I have not spent anything, and I am still holding for an explicit yes or no on cloud spend.

@thymikee

Copy link
Copy Markdown
Member Author

Direct provider evidence recorded — run live at head 860ceda6f. PR body updated with the full tables; summary here.

provider-webdriver — AWS Device Farm, Apple iPhone 17 Pro / iOS 26.3.1

Project Test-agent-device, us-west-2. Settings was the surface: the leased device had no network (status bar showed SOS), so Safari never loaded a page — recorded rather than worked around.

Cell Result
scrollDirection (bound) Airplane Mode rect y 499 → off-screen; visible set became Display & Brightness / Home Screen & App Library
performGesturePlan (bound, via swipe) "Flung"; Airplane Mode came back to y 499
performMultiTouchGesturePlan REFUSEDgesture pinch is not supported on physical iOS devices + "Two-finger gesture synthesis is iOS-simulator only — not available on physical iOS devices."

That is exactly what webDriverMultiTouchCell declares: the provider owns physical devices only, so two-contact synthesis is denied while every other tier executes.

provider-limrun — Android instance

Cell Result
scrollDirection Network & internet rect y 558 → off-screen
performMultiTouchGesturePlan (gesture pinch 2.0) 18.9% of pixels changed
performGesturePlan (swipe) visible set Navigate up / Use location / Recent accessTap to set up / Phone / Contacts

provider-limrun — iOS instance

The deliberate behavior change, observed live. All four tiers refuse at admission now, each carrying the interactor's own wording verbatim:

Cell Message Hint
gesture pinch gesture pinch is not supported on physical iOS devices Limrun iOS direct sessions do not expose portable gesture execution yet.
gesture pan gesture pan is not supported on ios same
swipe gesture fling is not supported on ios same
gesture drag gesture drag is not supported on ios same
scrollDirection admittedGeneral rect y 13.7 → off-screen

That last row is the point of the split: Limrun's iOS session exposes scrolling directly, so scroll keeps working while the gesture tiers refuse. The message subjects also differ exactly as the unit's subject table says — multi-touch reports physical iOS devices, the other tiers report raw ios.

Billing hygiene

Baseline checked before allocating (no RUNNING sessions). All three sessions closed via agent-device close. Post-run AWS orphan check is empty; no provider device remains in any state directory. Each provider ran under its own isolated AGENT_DEVICE_STATE_DIR.

One honesty note: I confirmed Limrun teardown through the CLI close plus the absence of any Limrun device in devices, not through an independent Limrun-side listing — the API endpoint I tried did not return JSON. If you want a belt-and-braces check on their dashboard, that is the one thing I could not verify from here.

Remaining

platform-linux is the only owner still without a live run — there is no Linux target on this macOS host. Its bound execution is exercised end-to-end in request-handler-chain.test.ts against the real createLocalLinuxToolProvider drag primitive, and the CI Linux lane covers the runtime path.

Deterministic gates green; CI was 28/28 on this head before this run, which touched no code.

@thymikee

Copy link
Copy Markdown
Member Author

Still not merge-ready at 860ceda6f despite the new provider verification and 28/28 green checks.

  1. swipe overdeclares runtime authority. normalizePublicSwipeMotion always yields a coordinate fling, so resolveGestureRuntimePlan can only select gesturePlanUse / performGesturePlan; however the descriptor assigns all four gestureRuntimePlanUses, including directional-fling, multi-touch, and target-authored-drag. Declare a swipe-specific one-use tuple and add an exact descriptor regression.
  2. Linux still lacks live changed-path evidence. The Linux smoke replay does not execute gesture, scroll, or swipe; its manifest classifies gesture/scroll as contract-only and swipe as a gap. Add representative observable Linux execution to the CI replay (or provide another real Linux run).

The AWS Device Farm and Limrun evidence does resolve the prior provider blocker and matches the migrated facts/bindings. Refreshing the stale size/file-count prose is non-blocking.

@thymikee

Copy link
Copy Markdown
Member Author

This was generated by AI during triage.

Readiness check per docs/agents/pull-requests.md — this PR is currently neither "published and reported" nor "merge-ready":

  1. CI never ran on the current head. Head is 11fbd16ad (pushed 2026-08-24 12:54), but the last workflow runs on this branch are at 860ceda6 (11:22, green). No checks exist for the head commit — only the CodeQL default-setup analyzes report. The PR body's evidence is stamped at older commits; per the readiness rules CI on the actual head is the authority still to come, and right now it has not started.

  2. The branch conflicts with main. refactor: move Wave 5 touch commands to platform runtime #1987 (Wave 5 touch commands) and refactor(lint): retire the facade closure test for a budget row and a lint rule #1990/fix(ios): verify fill's synthesized-replacement route before reporting success #1995 landed in packages/contracts/src/platform-runtime*.ts and the platform runtimes; git merge-tree shows ~30 conflict-marker regions across packages/contracts (platform-runtime.ts, platform-runtime-operations.ts, facades/platform.ts, platform-runtime-unavailable.*), platform-android/runtime*, and platform-apple/runtime.ts. Since refactor: move Wave 5 touch commands to platform runtime #1987 migrated the touch family through the same runtime seam this PR builds on, the conflict resolution is semantic (cell tables / operation keys), not mechanical — worth re-checking the parity test after rebasing.

Suggested order: rebase onto current main, push, and let a full CI run establish the head baseline before merge. The unit record, mutants, and live evidence in the body remain valid as of their named commits.

@thymikee
thymikee force-pushed the claude/wave5-gestures-cutover branch from 11fbd16 to 5216bdd Compare August 24, 2026 13:17
@thymikee
thymikee force-pushed the claude/wave5-gestures-cutover branch from 5216bdd to d00bb6c Compare August 24, 2026 13:46
@thymikee

Copy link
Copy Markdown
Member Author

Re-reviewed exact head d00bb6c8. The gesture viewport fallback now stays inside the same admitted runtime binding: every tier binds its perform operation with snapshot capture, keeps the owner viewport read preferred, and the Linux regression proves one bind plus one bound capture. Swipe still declares only its one-contact tier, legacy gesture/scroll routes remain removed, and the full affected gate passes (1,098 files / 8,142 tests). Expanded live Linux gesture testing remains intentionally deferred; existing contract/provider evidence is unchanged.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Aug 24, 2026
@thymikee
thymikee merged commit bcca714 into main Aug 24, 2026
28 of 29 checks passed
@thymikee
thymikee deleted the claude/wave5-gestures-cutover branch August 24, 2026 13:54
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-08-24 13:55 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant