Repository navigation
fix(settle): iOS broad-transition confirmation fires on tab switches and pushes and is coupled to the default quiet window #3470
Description
Problem
The iOS broad-transition confirmation in src/commands/interaction/runtime/stable-capture.ts (stableCaptureTransitionQuietMs, stableCaptureTransitionBaseline) was added in #1831 for one case: Element's modal dismissal, where a coherent but transitional tree beat the quiet window. In practice it also fires on ordinary navigation, and it is switched on and off by the requested window rather than by the transition.
- It fires on ordinary navigation. It fires whenever fewer than 50% of node identities are shared with the pre-action tree. With a complete viewport projection, that is true of most tab switches and screen pushes. Each one then costs 1.5 s.
-
Measured on an iPhone 17 simulator with the RN test app, 4 runs per step, median
waitedMs:Settings Push Pop Tab Fill Default (rule on) 2302 1808 1795 1796 150 ms, rule off 812 474 442 458 -
With the rule off, no step settled early. Each settled tree matched a capture taken 2 s later.
-
A push followed by a tap on the new screen's control, using the ref from the settle diff, landed 8 of 8 times.
-
- It is tied to the requested window. It is skipped when
requestedQuietMs < DEFAULT_STABLE_QUIET_MS, so--settle-quiet 499behaves completely differently from 500. tester-army/e2e passessettleQuietMs: 150and therefore never gets the guard.
Required behavior
- Narrow trigger. Arm the confirmation only for the transition it was built for: dismissal of a presented surface. Tab switches and pushes must not trigger it. The existing
hasTinyPresentedBaselinearm is the starting point; arming on a complete viewport projection alone is not enough. If a better presentation signal exists, use it. - Independent of the window. Whether the confirmation applies must not depend on
requestedQuietMsversus the default. Decide and document what an explicit short window means. Today's teststable-capture.test.ts:206encodes the old coupling. - Keep fix: derive iOS transition snapshots from visible presentation #1831 covered. Its regression tests (
stable-capture.test.ts:60-166) still pass: coherent transitional room, private-AX recovery, delayed replacement, advanced stored snapshot, missing provenance, rootless replacement.
Done when
- Unit tests show a tab switch and a push no longer extend the window. The fix: derive iOS transition snapshots from visible presentation #1831 cases still do, at any requested window.
- Live A/B on an iOS simulator at the default window, 4 or more runs, recording
waitedMsand late diffs. Tab switch, push, pop and fill no longer pay about 1.5 s, with no new late diffs.
Related: #3469 (keyboard chrome) also affects this rule's input. A follow-up may change the default window per capture backend (see below), stacked on this change.
Follow-up layer (stacked PR, same worker): default window per capture backend
Delayed-effect probe on the same devices (6 runs per cell; caught = the settled diff already shows the result):
- iOS XCTest (~250 ms per capture): 150 ms catches effects up to 500 ms but only 1 of 6 at 800 ms. 300 and 500 catch 800 ms.
- Android helper (~100 ms per capture): 150 ms catches 2 of 6 at 250 ms; 300 ms catches 0 of 6 at 500 ms; 500 ms catches 0 of 6 at 800 ms.
Proposal: iOS XCTest tree capture defaults to 300 ms; everything else keeps 500, including standalone wait stable. Key the default on the capture backend, not the platform name.
Measure before and after. If the median saving on local changes is under 10%, close the follow-up and report back rather than shipping. It is a user-visible change, so update the --settle-quiet description (packages/command-registry/src/flag-definitions-action.ts:203) and src/commands/post-action-observation-grammar.ts:36.
Activity
fix(settle): scope the broad-transition confirmation to presented-sur…
test(settle): split the dismissal-floor case out of settle.test.ts
fix(settle): decide the broad-transition confirmation by the transiti…
fix(settle): decide the broad-transition confirmation by the transiti…
DRAFT fix(settle): arm the confirmation on the dismissed surface, not…
DRAFT fix(settle): arm the confirmation on the dismissed surface, not…
fix(settle): arm the iOS broad-transition confirmation at any request…
DRAFT fix(settle): arm the confirmation on the dismissed surface, not…
DRAFT fix(settle): arm the confirmation on the dismissed surface, not…
DRAFT fix(settle): arm the confirmation on the dismissed surface, not…