@@ -66,10 +66,12 @@ are failure/debug artifacts, not happy-path requirements.
6666
6767The daemon adapter may retain the provider snapshot behind a successful observation without exposing it
6868through the engine contract. A following target resolution may use that snapshot only as semantic
69- evidence. Maestro selector semantics continue to use the raw provider nodes, except for equivalent iOS
70- accessibility wrapper chains described below. On iOS, the adapter derives the provider's canonical
71- interactive presentation from that same snapshot solely to determine atomic selector uniqueness; it
72- does not perform another capture. A unique exact, canonically hittable match may be dispatched with its
69+ evidence. Maestro selector semantics use the shared structurally normalized provider snapshot, before
70+ iOS canonical interactive presentation. They deliberately do not request the public ` snapshot --raw `
71+ shape, whose output contract bypasses shared pruning and overlay annotations. On iOS, the adapter derives the provider's canonical
72+ interactive presentation from that same snapshot without another capture. Raw matching still selects
73+ the node and authored index; when that same source node has canonical interactive bounds, tap-like
74+ actions use those bounds. A unique exact, canonically hittable match may be dispatched with its
7375resolved point so XCTest binds the live selector identity and coordinate delivery atomically; a
7476structured live-selector miss, ambiguity, point mismatch, or off-screen result
7577falls back to fresh Maestro resolution. All other targets capture fresh geometry before coordinate
@@ -87,22 +89,33 @@ matches. It does not adopt the public agent-device command surface's unique-matc
8789suppressed by Maestro ` optional ` ; atomic iOS dispatch handles that result by performing fresh Maestro
8890resolution, as described above. Cancellation and infrastructure failures are likewise non-optional.
8991
90- Every ` tapOn ` waits for hierarchy stability before the next command, matching Maestro's tap boundary.
91- ` retryTapIfNoChange ` defaults to false; when explicitly enabled, the runtime compares the stable hierarchy
92- with the target-resolution hierarchy and retries once when nothing changed. The stable result primes the
93- next command, so the tap boundary does not add another hierarchy read there.
94-
95- Successful gestures and scrolls require stabilization before the next command executes. The runtime
96- port records that requirement without capturing a hierarchy in the gesture command itself. At the next
97- command boundary, it samples at the compatibility polling cadence until the observation is stable, then
98- retains that final observation for the immediately following read. This keeps mutation ordering explicit,
99- prevents a later gesture or assertion from overtaking an in-flight transition, and avoids paying for the
100- same stable observation twice.
92+ Mutations that can leave an in-flight transition record a pending stabilization boundary. Before another
93+ mutating command, the runtime samples at the compatibility polling cadence until the hierarchy is stable
94+ and retains that final observation for the next read. Commands with specialized completion semantics settle
95+ inline instead. Hierarchy signatures project the available semantic attributes, tree topology, and
96+ fixed-order integer edges while excluding provider-only metadata, object-key order, and subpixel noise.
97+
98+ An authored observation after a mutation skips the pending barrier and polls its own condition immediately.
99+ Its successful snapshot becomes the baseline for the boundary but does not discharge mutation ordering. If
100+ another mutation follows, the runtime waits one polling interval and compares a fresh hierarchy with that
101+ baseline, continuing until stable when the UI is still changing. If no later mutation follows, it performs no
102+ extra capture. This intentionally differs from upstream Maestro, which settles before evaluating an assertion,
103+ and retains the previous agent-device compatibility engine's faster read behavior without allowing a later
104+ tap, gesture, scroll, or input to overtake an in-flight transition.
105+
106+ ` retryTapIfNoChange ` defaults to false. When explicitly enabled, the runtime compares the stable hierarchy
107+ with the target-resolution hierarchy. On iOS, an unchanged hierarchy triggers the same screenshot comparison
108+ used by Maestro; the runtime retries once only when both surfaces remain unchanged. Screenshot evidence is
109+ best-effort because a failed capture cannot prove that repeating a mutation is safe. The stable hierarchy
110+ primes the next command, so the retry policy does not add another hierarchy read there.
101111
102112` waitForAnimationToEnd ` uses its own screenshot-stability operation, matching upstream's two immediate
103113captures per attempt and 0.005% normalized absolute RGB-difference threshold. These captures explicitly
104114bypass ordinary screenshot stabilization so the command observes the application rather than
105- recursively waiting on another settling policy.
115+ recursively waiting on another settling policy. Screenshot stability does not discharge a pending
116+ mutation boundary; a later mutating command still verifies hierarchy stability before dispatch. On iOS,
117+ comparison captures use the persistent runner's screenshot surface so both frames come from one warmed
118+ transport and avoid simulator screenshot setup between polls.
106119
107120Upstream Maestro is a version-pinned development reference, not a production dependency. The current
108121opt-in conformance script compares a small checked-in parser corpus against manually captured Maestro
@@ -118,14 +131,15 @@ The migration cannot switch production routing until Android and iOS satisfy all
118131and react-navigation corpora:
119132
120133- total wall time is no slower than the pre-migration compatibility engine;
121- - target interactions perform one outcome query after the compatibility polling interval and prime that
122- result for the next command ;
134+ - an observation immediately after a mutation polls its authored condition directly; a later mutation uses
135+ that result as its stabilization baseline ;
123136- no command captures a second hierarchy merely to re-verify evidence produced within that command;
124137- absolute coordinate swipes perform one direct viewport query and no accessibility capture;
125- - gesture stabilization is deferred to the next command boundary and primes the following observation ;
138+ - mutation-to-mutation stabilization is deferred to the next command boundary and primes the following read ;
126139- percentage swipe conversion preserves authored endpoints exactly;
127140- helper/runner startup remains amortized across a suite;
128- - p50/p95 command latency, captures, retries, and transferred hierarchy bytes are reported separately;
141+ - p50/p95 command latency, hierarchy and screenshot captures, tap retries, and transferred hierarchy
142+ bytes are reported separately;
129143- failure-only diagnostics are excluded from happy-path latency comparisons.
130144
131145Android verification must prove the bundled helper backend and version. iOS verification must separate
0 commit comments