Repository navigation
Commit 3a4bcbe
authored
feat(snapshot): publish the viewport a snapshot's rects are measured in (#3210)
* feat(snapshot): publish the viewport a snapshot's rects are measured in (#3182)
Carry a SnapshotViewportSize from each producer through the state, response,
serialization, digest view, and client reader, published once at response level
and only through the kernel guard that makes a zero-size viewport unrepresentable.
Android: the snapshot helper reports the DisplayMetrics extent beside the density
it already declares; the host converts the pair to a viewport at the helper-result
boundary and keeps only the response fact. Apple: the host publishes the viewport
evidence the presentation fold already resolves, with no new runner wire key.
* test(snapshot): prove each Android/viewport producer claim (#3182)
Kernel: the construction guard and the wire re-read refuse zero, non-finite, and
the infinite sentinel as absence. Android: both helper transports read the display
pair, snapshotAndroid publishes the display beside an empty tree, the publication
adapter carries it, and the backend metadata keeps no second copy.
* test(platform-apple): pin the viewport an Apple capture publishes (#3182)
The capture publishes the fold's app-window evidence, follows the quality payload
the fold prefers, refuses zero/infinite boxes as absence, and the desktop runner
publishes none because window-space rects answer to no single box.
* test(snapshot): pin viewport publication across runtime, state, digest, client (#3182)
Runtime command publishes what its producer measured and omits what it didn't; the
session state carries the box so find-path consumers read the same one; the digest
survives the tree collapse; serialization emits it once; the client re-reads it
through the kernel guard so a broken payload stays absent.
* test(core): satisfy the Android provenance pair in the viewport absence case
* test(provider): declare the viewport in the published snapshot key set (#3182)
The proxied iOS capture now publishes the app-window box the presentation fold
resolves; the parity table names it rather than the guard loosening to a size.
* test(platform-android): move the helper display-pair proof to the capture test (#3182)
parseAndroidSnapshotHelperOutput lives in snapshot-helper-capture.ts, so its viewport claim
follows the source topology instead of the legacy aggregation; the capture fixture gains result
lines rather than keeping a second output builder.
* docs(snapshot): document the viewport a snapshot publishes (#3182)
`--json` consumers now read the box the rects are measured in off the
response instead of inferring one from the largest rect on screen.
commands.md names each producer's answer, the absence rule, and the
separation from content-safe gesture bounds.
* feat(capture-kit): publish the viewport a provider acquisition already holds (#3182)
presentIosSnapshotAcquisition is the one seam that turns an acquisition into a snapshot result for
the simulator AX bridge, an Appium source, and a Limrun tree, and it had the viewport evidence in
hand while returning no viewport. That left the default local-iOS producer without the field the
issue's first Done-when line asks for. Like the runner fold, it publishes only the box the regular
projection measured against: raw validates no box at all.
* fix(kernel): recognise a failed viewport read without its origin (#3182)
The published shape carries no origin, so a wire payload with the CGRectInfinite extents and no
coordinates used to mint (0, 0) around them and pass the guard, handing the caller the largest
number on the wire as the screen every rect is measured in (#2891). Both viewport gates now read
the extents themselves. kernel/record keeps its inlined rect rule and points at the other half of
that seam.
* fix(platform-apple): publish the viewport only when the fold validated it (#3182)
The runner fold published the largest root even on a raw projection, where the engine validates no
box at all — reinstating the largest-rect guess #3182 exists to retire under the name of a measured
fact, on a payload the regular projection refuses outright. Publication now follows the validated
projection, and the absence cases are pinned off the runnerFatal early return.
* docs(snapshot): name the producers that actually answer the viewport question (#3182)
The contract and user docs claimed a web producer that does not exist: platform-web hands over a
tree and never reads a screen, and neither does Linux. They now name the two surfaces that answer
and the absences that are real, including raw, which validates no box. The Node client page gains
the field, following how readiness was documented.
* fix(snapshot): carry a backend's own viewport through the state seam (#3182)
normalizeBackendSnapshot returned a backend-built state verbatim, so a producer that named its own
keyboard band or viewport box beside that state lost it on the one path where the backend was the
authority. The two Android rejection helpers advertise a capture they can never yield and now say
never, and the helper's one-read claim is scoped to what the code guarantees: density and extent
from one DisplayMetrics, not a metrics sample taken with the dump. Proves the display read answers
the geometry-free-tree case the issue came from.
* fix(platform-android): keep the display read across the re-capture window (#3182)
The re-capture loop #3160 split out of helper capture declared the plain xml+metadata pair, so the
display read a usable attempt made was invisible to the caller while it travelled inside the object.
Declaring the capture type makes the viewport the loop already carries part of its contract.
* test(snapshot): prove the empty-screen case each producer can answer (#3182)
The issue's second Done-when line is a capture of an empty screen that still reports the box. On the
provider acquisition seam that is now a test: the fold runs with no nodes and the reported viewport
still reaches the result.
* fix(platform-android): read the real display extent around the tree dump (#3182)
Resources.getSystem() reports the app display, which excludes a persistent
navigation bar, while the tree's getBoundsInScreen rects span the full panel.
Read the real extent instead (WindowManager.getMaximumWindowMetrics on API 30+,
Display.getRealMetrics below) before and after each dump on both the one-shot
and the session path, and publish it only when the two reads agree so a
rotation mid-dump omits the viewport instead of pairing one rotation's bounds
with the other's dimensions.
* refactor(kernel): make the viewport invariant a branded type (#3182)
A plain structural { width, height } accepted the zero the type claimed was
unrepresentable, and readSnapshotViewportSize stood as a second constructor
beside snapshotViewportSizeFrom. Brand the type with a token only kernel/rect
imports, so a literal with a zero in it stops being assignable, and let the
reader delegate to snapshotViewportSizeFrom so one guard decides what a usable
box is. Test fixtures now mint their viewport through the guard, which is the
mutation that proves the brand bites.
* refactor(capture-kit): return the validated viewport from the iOS fold (#3182)
The engine already resolves the box the regular projection validates against;
hand it over on the presentation result and publication instead of making
snapshot-presentation.ts and ios-snapshot-runtime.ts each re-derive the rule
that regular validates a box and raw does not. Callers now only pass the
returned rect through the shared construction guard, so the rule lives with
its owner.
* refactor(platform-android): derive the viewport once in snapshotAndroid (#3182)
The capture carrier held a pre-derived viewport beside its metadata, so every
re-capture hop had to thread the sibling through; a second copy of the display
pair also meant two lifetimes for one fact. Carry the raw helper metadata on
AndroidUiHierarchyCapture instead and answer the viewport question only in
snapshotAndroid, through the shared guard, so both the healthy and the
presentation-failed return publish the same box the tree was measured against.
* docs(snapshot): limit the --raw viewport absence to Apple targets (#3182)
Android publishes its viewport under --raw too: the display the helper reads is
the same screen the raw rects are measured on. Only the Apple projection
validates no box, so only there does --raw omit viewport.
* fix(commands): keep clickability evidence across the snapshot state merge (#3182)
The state seam added the backend's keyboard and viewport facts to the state
without carrying the private clickability evidence over, and that evidence is
retained by object identity. Android Maestro taps then read
`exact-evidence-not-retained`, skip clickable-first ordering, and tap the
document-order duplicate of a requested id — the Android smoke lane's
no-index `tapOn` failure, which is this PR's, not a flake.
The mutation that makes the new test fail: remove the copy and the evidence
read on the published result is undefined.1 parent 97aa811 commit 3a4bcbe
45 files changed
Lines changed: 1219 additions & 32 deletions
File tree
- android/snapshot-helper/src
- main/java/com/callstack/agentdevice/snapshothelper
- test/java/com/callstack/agentdevice/snapshothelper
- packages
- capture-kit/src
- ios-snapshot-engine
- snapshot
- __tests__
- contracts/src
- kernel/src
- platform-android/src
- __tests__
- platform-apple/src
- __tests__
- runner
- __tests__
- src
- __tests__
- commands
- capture/runtime
- output
- core/__tests__
- daemon
- __tests__
- test/integration/provider-scenarios
- website/docs/docs
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
77 | 78 | | |
78 | 79 | | |
79 | 80 | | |
| 81 | + | |
80 | 82 | | |
81 | 83 | | |
| 84 | + | |
| 85 | + | |
82 | 86 | | |
83 | 87 | | |
84 | 88 | | |
85 | 89 | | |
86 | 90 | | |
87 | | - | |
| 91 | + | |
88 | 92 | | |
89 | 93 | | |
90 | 94 | | |
| |||
114 | 118 | | |
115 | 119 | | |
116 | 120 | | |
117 | | - | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
118 | 125 | | |
119 | 126 | | |
120 | 127 | | |
| |||
124 | 131 | | |
125 | 132 | | |
126 | 133 | | |
127 | | - | |
128 | | - | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
129 | 145 | | |
130 | 146 | | |
131 | 147 | | |
| |||
232 | 248 | | |
233 | 249 | | |
234 | 250 | | |
| 251 | + | |
235 | 252 | | |
236 | 253 | | |
| 254 | + | |
| 255 | + | |
237 | 256 | | |
238 | | - | |
| 257 | + | |
239 | 258 | | |
240 | 259 | | |
241 | 260 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
49 | 52 | | |
50 | 53 | | |
51 | 54 | | |
| |||
143 | 146 | | |
144 | 147 | | |
145 | 148 | | |
| 149 | + | |
146 | 150 | | |
147 | 151 | | |
148 | 152 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
29 | 36 | | |
30 | 37 | | |
31 | 38 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
| |||
51 | 52 | | |
52 | 53 | | |
53 | 54 | | |
| 55 | + | |
| 56 | + | |
54 | 57 | | |
55 | 58 | | |
56 | 59 | | |
| |||
89 | 92 | | |
90 | 93 | | |
91 | 94 | | |
| 95 | + | |
92 | 96 | | |
93 | 97 | | |
94 | 98 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
0 commit comments