fix(interaction): report an unsettled post-gesture surface instead of a definite miss - #2839
Conversation
Size Report
Startup median (7 runs, lower is better):
|
|
Reviewed at faec8d2. The test-side change looks sound, and there are no conflicts. The failing Smoke Tests job fails in two Swift runner tests, Not blocking: the mock probe in test/integration/ios-simulator-e2e-visibility-scroll.test.ts#L78 ignores scroll position. With |
faec8d2 to
bb059ec
Compare
Live evidence for bb059ec (lp2 simulator, iPhone 17 Pro / iOS 26.2)Unsettled path. Catalog tab: a fast Pre-fix (main): 3 Post-fix: 6/6 reads hit the timeout with
{"success":false,"error":{"code":"COMMAND_FAILED","message":"is absent could not prove absence for selector id=\"catalog-footer\": the surface was still changing after swipe 200 760 200 160","details":{"command":"is","reason":"predicate_failed","predicate":"absent","selector":"id=\"catalog-footer\"","matches":0,"observation":"unsettled","unsettledGesture":{"action":"swipe","positionals":["200","760","200","160"]}}}}The next read in each trial captured afresh, with no Scenario. Mutations (each makes a new test fail): no |
|
Both points are addressed in the rework at
The two Swift timeouts are unrelated. They are the occupancy and alert flakes that #2847 and #2843 fix. Live evidence: #2839 (comment) |
|
Adversarial review of the earlier test-only head
|
bb059ec to
d3f1988
Compare
|
|
Follow-up review at d3f1988 (after faec8d2). The fix still holds: an unsettled post-gesture surface is reported as unsettled, not as a definite miss. The delta (field renames, the contracts disclosure helper, the tree-only carrier, and find provenance via The live run was at bb059ec. The changes since then were checked by range-diff and the production-route unit tests, not by a new device run. Deferred interactions (click, press, fill by selector after a gesture) do not get the unsettled warning; the CHANGELOG already states this gap. CI was still running at review time. Smoke Tests ( |
d3f1988 to
0c1c110
Compare
|
Rebased onto main at
Size, measured against the base: production went from +182/−41 to +100/−44, and tests from +489/−11 to +287/−10. There is one test per invariant, and each fails under a named mutation. |
… a definite miss Post-gesture stabilization returned the latest capture of a still-moving surface when its budget expired, keeping the timeout only as a log diagnostic. `is visible` then answered a plain `selector_not_found` and `is absent` passed on a list that was still decelerating. When the last poll pair disagrees, the resolved capture stamps `unsettledGesture` on the tree, the one carrier. Selector reads (mutating `find` now keeps the captured tree) disclose it through one tree-fact helper shared with `targetActivation`, which now also lands on `error.details`; `snapshot` derives the warning in its builder; `is absent` refuses with `observation: "unsettled"`, `wait absent` keeps polling, and the session cache does not serve an unsettled tree.
The live scroll search now re-probes the same window once when a miss carries `unsettledGesture`, and its failure lists every probe and scroll.
0c1c110 to
c0b1b74
Compare
|
Simplified at |
|
c0b1b74 fixes what d3f1988 left open: the code now reports an unsettled post-gesture surface instead of a definite miss. This is ready for human merge. 20 checks pass on c0b1b74 and I don't see any conflicts. I read the tests only and didn't run the named mutations myself, and I reviewed the logical delta by diffing d3f1988 against c0b1b74 directly, since the packet's delta mixes in upstream rebase commits. Not blocking: |
Summary
Fixes the
smoke:automation-inputflakeid="automation-longpress" did not become visible after scrolling(20 failures on 18 branches, 3 on main, and #2832). Post-scroll captures never agreed (post_gesture_snapshot_stabilization_timeout), sois visiblereturned a plainselector_not_foundfor a moving surface.When the last poll pair disagrees, stabilization now stamps
unsettledGestureon the tree. The tree is the only carrier.is/get/find/waitreport it inerror.detailsordatawith a warning, through one helper shared withtargetActivation(which now also lands onerror.details). Mutatingfindkeeps the captured tree.snapshotadds the warning in its existing builder.is absentrefuses withobservation: "unsettled",wait absentkeeps polling, and the selector cache does not reuse the tree.The E2E helper keeps the forward-only 0.75 × 3 search. On
unsettledGestureorcaptureStalledit re-reads the same offset (at most twice per scroll) without using a scroll attempt. Follow-ups: #2853 (click/press/fill), #2856 (gestureNoEffecton the same stamp). The failing job's two Swift timeouts are fixed by #2847 and #2843. 22 files: production +134/−81, tests +220/−20.Validation
Tested at
c0b1b74541.pnpm check:affected --run: pass (6617 tests). Each new test fails under a named mutation.0c1c110373(same behaviour; later commits only simplify it), iPhone 17 Pro / iOS 26.2, fling then read:find … clickandis visiblecarryunsettledGesturein 6/6 trials;snapshotwarns in 3/3. Main returned plain misses.smoke:automation-input: 2/5 on this head and 2/5 on main. Every failure is a pre-existing localget text id="automation-event-name"miss at bootstrap. The longpress search never failed.