agent-device 0.21.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.0.apk → agent-device-android-ime-helper-0.21.1.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.1.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.0.manifest.json → agent-device-android-ime-helper-0.21.1.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.0.apk → agent-device-android-snapshot-helper-0.21.1.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.1.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.0.manifest.json → agent-device-android-snapshot-helper-0.21.1.manifest.json} +6 -6
  7. package/apple/snapshot-bridge/README.md +58 -1
  8. package/apple/snapshot-bridge/SnapshotBridge.m +6 -0
  9. package/apple/snapshot-bridge/SnapshotBridgeCapture.h +25 -0
  10. package/apple/snapshot-bridge/SnapshotBridgeCapture.m +138 -0
  11. package/apple/snapshot-bridge/SnapshotBridgeRuntime.h +1 -0
  12. package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +32 -3
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +12 -0
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +20 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +15 -15
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +72 -0
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +63 -14
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +668 -82
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +14 -4
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+BlockingSystemModalResolution.swift +39 -4
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +1065 -223
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +290 -0
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +1 -1
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +10 -10
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +249 -61
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +101 -42
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +13 -13
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +51 -43
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +71 -4
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +144 -7
  31. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +13 -1
  32. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +216 -17
  33. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +206 -22
  34. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +289 -42
  35. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +92 -22
  36. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +617 -122
  37. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +79 -4
  38. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +71 -71
  39. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +83 -5
  40. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +67 -67
  41. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +4 -4
  42. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +17 -17
  43. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +30 -30
  44. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryReadiness.swift +31 -31
  45. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +28 -0
  46. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputProbe.swift +101 -0
  47. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +19 -19
  48. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +55 -17
  49. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +26 -5
  50. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +125 -75
  51. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +9 -9
  52. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +9 -9
  53. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-trim.swift +4 -4
  54. package/dist/src/adapter.js +1 -1
  55. package/dist/src/adb-executor.js +1 -1
  56. package/dist/src/adb-failure.js +1 -1
  57. package/dist/src/agent-browser-process-record.js +1 -1
  58. package/dist/src/agent-browser-provider.js +1 -1
  59. package/dist/src/agent-browser-tool.js +1 -1
  60. package/dist/src/agent-device-client.js +2 -2
  61. package/dist/src/ai-sdk.d.ts +1 -1
  62. package/dist/src/ai-sdk.js +1 -1
  63. package/dist/src/alert-runtime.js +1 -1
  64. package/dist/src/android-input-ownership.js +1 -1
  65. package/dist/src/app-catalog.js +1 -1
  66. package/dist/src/app-deployment-resolution.js +1 -1
  67. package/dist/src/app-inventory-contract.js +1 -1
  68. package/dist/src/app-inventory.js +1 -1
  69. package/dist/src/app-launch.js +2 -2
  70. package/dist/src/app-lifecycle.js +3 -3
  71. package/dist/src/app-lifecycle2.js +1 -1
  72. package/dist/src/app-log-files.js +1 -1
  73. package/dist/src/app-log-runtime2.js +3 -3
  74. package/dist/src/app-resolution.js +1 -1
  75. package/dist/src/apple-runner-platform.js +1 -0
  76. package/dist/src/application-lifecycle-interaction.js +1 -1
  77. package/dist/src/archive.js +1 -1
  78. package/dist/src/artifact-download.js +1 -1
  79. package/dist/src/auth-session.js +1 -1
  80. package/dist/src/auth.js +1 -1
  81. package/dist/src/backend-snapshot-options.js +1 -1
  82. package/dist/src/boot-diagnostics.js +1 -1
  83. package/dist/src/capture.js +1 -1
  84. package/dist/src/cli-config.js +1 -1
  85. package/dist/src/cli-help.js +25 -21
  86. package/dist/src/cli-runner.js +1 -1
  87. package/dist/src/cli.js +4 -4
  88. package/dist/src/click-button.js +1 -1
  89. package/dist/src/client-metro-companion.js +1 -1
  90. package/dist/src/client-metro.js +1 -1
  91. package/dist/src/client-types.d.ts +27 -13
  92. package/dist/src/code-signature-cache.js +1 -1
  93. package/dist/src/code-signature.js +1 -1
  94. package/dist/src/command-schema.js +3 -3
  95. package/dist/src/command-tools.js +2 -2
  96. package/dist/src/command.js +1 -1
  97. package/dist/src/connection-runtime.js +1 -1
  98. package/dist/src/connection.js +3 -3
  99. package/dist/src/contracts.d.ts +1 -1
  100. package/dist/src/contracts.js +1 -1
  101. package/dist/src/daemon-client-lifecycle.js +1 -1
  102. package/dist/src/daemon.js +1 -1
  103. package/dist/src/debug-symbols-facade.js +1 -1
  104. package/dist/src/device-claim-rule.js +1 -1
  105. package/dist/src/device-inventory-context.js +1 -1
  106. package/dist/src/device-rotation.js +1 -1
  107. package/dist/src/device-selection-resolver.js +1 -1
  108. package/dist/src/device-session.js +1 -1
  109. package/dist/src/device2.js +1 -1
  110. package/dist/src/diagnostics.js +1 -1
  111. package/dist/src/dispatch-resolve.js +1 -1
  112. package/dist/src/doctor2.js +1 -1
  113. package/dist/src/error.js +1 -1
  114. package/dist/src/exec.js +1 -1
  115. package/dist/src/file.js +1 -1
  116. package/dist/src/find.js +1 -1
  117. package/dist/src/generic-settle.js +1 -1
  118. package/dist/src/gesture-plan.js +1 -1
  119. package/dist/src/gesture-runtime.js +1 -1
  120. package/dist/src/harmonyos.js +1 -1
  121. package/dist/src/hdc.js +1 -1
  122. package/dist/src/helper.js +2 -2
  123. package/dist/src/human-control-contract.js +1 -1
  124. package/dist/src/human-control.js +1 -1
  125. package/dist/src/index.d.ts +1 -1
  126. package/dist/src/index.js +1 -1
  127. package/dist/src/input-actions.js +1 -1
  128. package/dist/src/input-actions2.js +2 -2
  129. package/dist/src/install-artifact-facade.js +1 -1
  130. package/dist/src/install-source-network-transport.js +1 -1
  131. package/dist/src/install-source2.js +1 -1
  132. package/dist/src/interaction-positionals.js +1 -1
  133. package/dist/src/interaction-ref-policy.js +1 -1
  134. package/dist/src/interaction2.js +1 -1
  135. package/dist/src/interactor.js +5 -5
  136. package/dist/src/interactor2.js +1 -1
  137. package/dist/src/interactors.js +1 -1
  138. package/dist/src/internal/bin.js +1 -1
  139. package/dist/src/internal/daemon.js +2 -2
  140. package/dist/src/internal/png-worker.js +1 -1
  141. package/dist/src/internal/run-script-http-child.js +1 -1
  142. package/dist/src/inventory.js +2 -2
  143. package/dist/src/inventory2.js +1 -1
  144. package/dist/src/inventory3.js +1 -1
  145. package/dist/src/inventory5.js +1 -1
  146. package/dist/src/ios-snapshot-runtime.js +1 -1
  147. package/dist/src/ios-system-surface.js +1 -0
  148. package/dist/src/lease-scope.js +1 -1
  149. package/dist/src/lease.js +1 -1
  150. package/dist/src/limrun-runtime-dependencies.js +1 -1
  151. package/dist/src/limrun.d.ts +1 -1
  152. package/dist/src/linux.js +1 -1
  153. package/dist/src/location-coordinates.js +1 -1
  154. package/dist/src/managed-device-scope.js +1 -1
  155. package/dist/src/mechanics.js +16 -16
  156. package/dist/src/multitouch-support.js +1 -1
  157. package/dist/src/observation.js +1 -1
  158. package/dist/src/open-target-resolution.js +1 -0
  159. package/dist/src/owner-identity.js +3 -3
  160. package/dist/src/parameterized-recorded-fill.js +1 -1
  161. package/dist/src/perf-facade.js +2 -2
  162. package/dist/src/perf-process-identity.js +1 -0
  163. package/dist/src/perf-runtime-operation-builder.js +1 -1
  164. package/dist/src/perf-runtime-plan.js +1 -1
  165. package/dist/src/perf.js +1 -1
  166. package/dist/src/physical-device-control.js +1 -1
  167. package/dist/src/platform-runtime-android-adb-host.js +1 -1
  168. package/dist/src/platform-runtime-app-log-process.js +1 -1
  169. package/dist/src/platform-runtime-host.js +1 -1
  170. package/dist/src/platform-runtime-managed-owner.js +1 -1
  171. package/dist/src/platform-runtime-open-target.js +1 -1
  172. package/dist/src/platform-runtime-operation-host.js +2 -2
  173. package/dist/src/platform-runtime-runtime-hints.js +2 -2
  174. package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
  175. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
  176. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  177. package/dist/src/platform-runtime-unavailable.js +1 -1
  178. package/dist/src/platform-runtime.js +1 -1
  179. package/dist/src/platform-runtime2.js +1 -1
  180. package/dist/src/png-worker-contract.js +1 -1
  181. package/dist/src/prepare-kind.js +1 -1
  182. package/dist/src/provider-device-runtime.js +1 -1
  183. package/dist/src/provider-session-ownership.js +1 -1
  184. package/dist/src/provider-webdriver.js +1 -1
  185. package/dist/src/proxy.js +1 -1
  186. package/dist/src/react-native.js +1 -1
  187. package/dist/src/record-runtime.js +1 -1
  188. package/dist/src/rect-center.js +1 -1
  189. package/dist/src/register-builtins.js +1 -1
  190. package/dist/src/registry.js +37 -36
  191. package/dist/src/remote-config2.js +1 -1
  192. package/dist/src/replay-divergence.js +1 -1
  193. package/dist/src/replay.js +2 -2
  194. package/dist/src/reporting.js +9 -8
  195. package/dist/src/request-admission.js +1 -1
  196. package/dist/src/request-cancel.js +1 -1
  197. package/dist/src/request-runtime-binding.js +1 -1
  198. package/dist/src/retry.js +1 -1
  199. package/dist/src/runner-cache-metadata.js +2 -2
  200. package/dist/src/runner-client.js +1 -1
  201. package/dist/src/runner-disposal.js +1 -1
  202. package/dist/src/runner-operations-facade.js +1 -1
  203. package/dist/src/runner.js +1 -1
  204. package/dist/src/runtime-transport-hints.js +1 -1
  205. package/dist/src/runtime.js +3 -3
  206. package/dist/src/runtime2.js +4 -4
  207. package/dist/src/runtime3.js +1 -1
  208. package/dist/src/runtime4.js +5 -4
  209. package/dist/src/runtime5.js +1 -1
  210. package/dist/src/runtime6.js +1 -1
  211. package/dist/src/runtime7.js +1 -1
  212. package/dist/src/runtime8.js +1 -1
  213. package/dist/src/runtime9.js +1 -1
  214. package/dist/src/screen-recording-live-handle.js +1 -1
  215. package/dist/src/screen-recording-options.js +1 -1
  216. package/dist/src/screen-recording-resource-recovery.js +1 -1
  217. package/dist/src/screenshot-density.js +1 -1
  218. package/dist/src/screenshot-runtime.js +1 -1
  219. package/dist/src/screenshot.js +1 -1
  220. package/dist/src/screenshot3.js +3 -3
  221. package/dist/src/script.js +1 -1
  222. package/dist/src/scroll-command.js +1 -1
  223. package/dist/src/scroll-gesture.js +1 -1
  224. package/dist/src/sdk-batch-runner.js +2 -2
  225. package/dist/src/sdk-batch.js +2 -2
  226. package/dist/src/sdk-contracts.d.ts +44 -1
  227. package/dist/src/sdk-contracts.js +2 -2
  228. package/dist/src/sdk-device.js +1 -1
  229. package/dist/src/sdk-finders.d.ts +1 -1
  230. package/dist/src/sdk-io.js +1 -1
  231. package/dist/src/sdk-remote-config.d.ts +1 -1
  232. package/dist/src/sdk-remote-config.js +1 -1
  233. package/dist/src/sdk-selectors.d.ts +69 -13
  234. package/dist/src/selector-runtime.js +1 -1
  235. package/dist/src/server.js +3 -3
  236. package/dist/src/session-allocation.js +1 -1
  237. package/dist/src/session-observation.js +1 -0
  238. package/dist/src/session-routing.js +1 -1
  239. package/dist/src/session-runtime-admission.js +1 -1
  240. package/dist/src/session-snapshot.js +1 -1
  241. package/dist/src/session-store.js +3 -3
  242. package/dist/src/session-target-evidence.js +1 -1
  243. package/dist/src/session2.js +5 -5
  244. package/dist/src/settings.js +1 -1
  245. package/dist/src/simulator.js +1 -1
  246. package/dist/src/snapshot-quality-backend-capabilities.js +1 -1
  247. package/dist/src/snapshot-quality-verdict.js +1 -1
  248. package/dist/src/snapshot-runtime-binding.js +1 -1
  249. package/dist/src/snapshot-runtime.js +1 -1
  250. package/dist/src/snapshot-state.js +1 -1
  251. package/dist/src/snapshot2.js +1 -1
  252. package/dist/src/snapshot3.js +1 -1
  253. package/dist/src/snapshot4.js +1 -1
  254. package/dist/src/src.js +1 -1
  255. package/dist/src/src7.js +2 -2
  256. package/dist/src/src8.js +2 -2
  257. package/dist/src/string-enum.js +1 -1
  258. package/dist/src/takeover.js +1 -1
  259. package/dist/src/tool-provider.js +2 -2
  260. package/dist/src/tool-provider2.js +1 -1
  261. package/dist/src/tool-provider3.js +1 -1
  262. package/dist/src/toolchain-probe.js +1 -1
  263. package/dist/src/touch-reference-frame.js +1 -0
  264. package/dist/src/touch-runtime.js +1 -1
  265. package/dist/src/transport.js +1 -1
  266. package/dist/src/tv-remote.js +1 -1
  267. package/dist/src/type-text-runtime.js +1 -1
  268. package/dist/src/update-check.js +1 -1
  269. package/dist/src/verified-file.js +1 -1
  270. package/dist/src/video.js +1 -1
  271. package/dist/src/web.js +1 -1
  272. package/dist/src/web2.js +1 -1
  273. package/dist/src/webdriver-source.js +1 -1
  274. package/dist/src/window-state.js +1 -0
  275. package/package.json +3 -2
  276. package/server.json +2 -2
  277. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.0.apk.sha256 +0 -1
  278. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.0.apk.sha256 +0 -1
  279. package/dist/src/back-mode.js +0 -1
  280. package/dist/src/format.js +0 -2
  281. package/dist/src/platform-runtime-apple-resources.js +0 -1
  282. package/dist/src/runner-selector-query.js +0 -1
@@ -4,23 +4,23 @@ import AgentDeviceSnapshotPresentation
4
4
  extension RunnerTests {
5
5
  private static let privateAXSnapshotMaxNodes = 5_000
6
6
 
7
- /// Upper bound on element-rooted follow-up snapshot requests per capture. A
8
- /// depth-capped Bluesky-class tree resolves in 1-3 chained requests (~100-300ms
9
- /// each); the bound exists so a pathological tree cannot stack requests past
10
- /// the capture-plan deadline, which is also enforced per call.
11
- private static let privateAXDeepExtensionCallLimit = 8
12
-
13
- /// Upper bound on per-element custom-action reads per capture. Each is its own
14
- /// AX round trip (~100ms on an idle simulator), so this caps the opt-in cost
15
- /// at roughly a second on top of the capture; the capture-plan deadline stops
16
- /// it earlier under load. A screenful of merged cards is well under this.
7
+
8
+
9
+
10
+
11
+ static let privateAXDeepExtensionCallLimit = 8
12
+
13
+
14
+
15
+
16
+
17
17
  private static let privateAXCustomActionLimit = 12
18
18
 
19
- /// A capture is depth-limited unless its frontier extension resolved every
20
- /// capped node: frontiers left pending (budget/deadline) or missed (element
21
- /// vanished, re-rooted request failed) mean subtrees are still absent, and
22
- /// presenting such a capture as complete would hide exactly the content the
23
- /// extension exists to recover. nil extension counts = extension never ran.
19
+
20
+
21
+
22
+
23
+
24
24
  static func privateAXDepthLimited(
25
25
  effectiveDepth: Int,
26
26
  requestedDepth: Int,
@@ -31,17 +31,17 @@ extension RunnerTests {
31
31
  guard let pendingFrontiers, let missedFrontiers else { return true }
32
32
  return pendingFrontiers > 0 || missedFrontiers > 0
33
33
  }
34
- /// Deep React Native trees make the AX server reject bulk snapshot requests outright with
35
- /// kAXErrorIllegalArgument once the requested depth crosses a tree-size-dependent limit
36
- /// (observed between depth 56 and 64 on the Bluesky Home feed; the limit moves with live
37
- /// content). Retrying the same request at a shallower depth succeeds, so on failure we walk
38
- /// this ladder instead of giving up. Capped at 4 attempts to bound worst-case latency on
39
- /// apps where the AX surface is genuinely unavailable.
34
+
35
+
36
+
37
+
38
+
39
+
40
40
  static let privateAXSnapshotDepthLadder = [56, 40, 24, 12]
41
41
 
42
- /// Ladder rungs for one capture. A remembered accepted depth (recorded when a prior capture's
43
- /// deep request was rejected) drops the rungs above it, so the known-rejected deep request is
44
- /// not re-paid on every capture of the same screen class.
42
+
43
+
44
+
45
45
  static func privateAXAttemptDepths(requestedDepth: Int, rememberedDepth: Int?) -> [Int] {
46
46
  var depths = [requestedDepth]
47
47
  depths.append(contentsOf: privateAXSnapshotDepthLadder.filter { $0 < requestedDepth })
@@ -49,17 +49,17 @@ extension RunnerTests {
49
49
  return depths.filter { $0 <= remembered }
50
50
  }
51
51
 
52
- /// The bridge omits the key entirely when the capture did not ask for custom
53
- /// actions, which is the difference between "nothing to disclose" and "read
54
- /// none of them" — so a missing key must stay nil, never (0, 0).
52
+
53
+
54
+
55
55
  static func privateAXCustomActionCoverage(_ raw: Any?) -> SnapshotCustomActionCoverage? {
56
56
  guard let coverage = raw as? [String: Any],
57
57
  let read = (coverage[RunnerAXSnapshotCustomActionsReadKey] as? NSNumber)?.intValue,
58
58
  let candidates = (coverage[RunnerAXSnapshotCustomActionsCandidatesKey] as? NSNumber)?.intValue
59
59
  else { return nil }
60
- // read/candidates are the ratio and must both be present; the truncation
61
- // count is additive, so an older bridge that omits it reads as zero rather
62
- // than voiding the whole coverage.
60
+
61
+
62
+
63
63
  let truncated =
64
64
  (coverage[RunnerAXSnapshotCustomActionsTruncatedKey] as? NSNumber)?.intValue ?? 0
65
65
  let blocked = (coverage[RunnerAXSnapshotCustomActionsBlockedKey] as? NSNumber)?.boolValue ?? false
@@ -67,9 +67,68 @@ extension RunnerTests {
67
67
  read: read, candidates: candidates, truncated: truncated, blocked: blocked)
68
68
  }
69
69
 
70
+ struct PrivateAXLadderOutcome {
71
+ let response: [String: Any]
72
+ let effectiveDepth: Int
73
+ let deadlineSpent: Bool
74
+ let lastError: String
75
+
76
+ var succeeded: Bool { response["ok"] as? Bool == true }
77
+ }
78
+
79
+
80
+
81
+
82
+ static func privateAXLadderCapture(
83
+ attemptDepths: [Int],
84
+ deadline: Date,
85
+ capture: (Int) -> [String: Any]
86
+ ) -> PrivateAXLadderOutcome {
87
+ var response: [String: Any] = [:]
88
+ var effectiveDepth = attemptDepths.first ?? 0
89
+ var lastError = "unknown private AX snapshot failure"
90
+ for depth in attemptDepths {
91
+ if depth != attemptDepths.first, Date() >= deadline {
92
+ NSLog("AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_BUDGET_EXHAUSTED depth=%ld", depth)
93
+ return PrivateAXLadderOutcome(
94
+ response: response, effectiveDepth: effectiveDepth, deadlineSpent: true,
95
+ lastError: lastError)
96
+ }
97
+ response = capture(depth)
98
+ if response["ok"] as? Bool == true {
99
+ effectiveDepth = depth
100
+ break
101
+ }
102
+ lastError = response["error"] as? String ?? lastError
103
+ NSLog(
104
+ "AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_DEPTH_RETRY depth=%ld error=%@",
105
+ depth,
106
+ lastError
107
+ )
108
+ }
109
+ return PrivateAXLadderOutcome(
110
+ response: response, effectiveDepth: effectiveDepth, deadlineSpent: false, lastError: lastError)
111
+ }
112
+
113
+
114
+
115
+
116
+ func recordPrivateAXAcceptedDepth(
117
+ exactDepthRequested: Bool,
118
+ effectiveDepth: Int,
119
+ attemptDepths: [Int]
120
+ ) {
121
+ guard !exactDepthRequested, effectiveDepth != attemptDepths.first else { return }
122
+ rememberPrivateAXAcceptedDepth(
123
+ bundleId: currentBundleId,
124
+ processIdentifier: currentAppProcessIdentifier,
125
+ depth: effectiveDepth
126
+ )
127
+ }
128
+
70
129
  func rememberPrivateAXAcceptedDepth(bundleId: String?, processIdentifier: Int?, depth: Int) {
71
- // No PID means no way to notice a relaunch later; record nothing rather than risk serving
72
- // a stale shallow rung to a fresh process.
130
+
131
+
73
132
  guard let processIdentifier else { return }
74
133
  privateAXAcceptedDepthLock.lock()
75
134
  privateAXAcceptedDepthBundleId = bundleId
@@ -111,8 +170,8 @@ extension RunnerTests {
111
170
  ) -> SnapshotAcquisition? {
112
171
  #if os(iOS) && targetEnvironment(simulator)
113
172
  let requestedDepth = hint.rawTraversalDepth ?? 64
114
- // An explicit --depth request is honored as asked: no accepted-depth
115
- // memory, no frontier extension past it.
173
+
174
+
116
175
  let exactDepthRequested = hint.rawTraversalDepth != nil
117
176
  let rememberedDepth =
118
177
  exactDepthRequested
@@ -125,22 +184,13 @@ extension RunnerTests {
125
184
  requestedDepth: requestedDepth,
126
185
  rememberedDepth: rememberedDepth
127
186
  )
128
- var response: [String: Any] = [:]
129
- var effectiveDepth = requestedDepth
130
- var lastError = "unknown private AX snapshot failure"
131
- for depth in attemptDepths {
132
- // The first rung always runs (the plan gated entry on its own budget); later rungs
133
- // stop when the capture-plan deadline is spent so ladder retries can never stack
134
- // past the runner's main-thread watchdog (#1105).
135
- if depth != attemptDepths.first, Date() >= deadline {
136
- NSLog("AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_BUDGET_EXHAUSTED depth=%ld", depth)
137
- break
138
- }
139
- // Declared residue (#1797): the bridge caps the tree at 5000 nodes while serializing,
140
- // BEFORE either projection exists, so a raw capture of a huge screen is bounded rather
141
- // than failing the way the tree backend's own raw cap does. The cap is disclosed as
142
- // `truncated`, and it applied to the acquired tree before this projection split too.
143
- response = RunnerAXSnapshotBridge.snapshotTree(
187
+
188
+
189
+
190
+
191
+ let ladder = Self.privateAXLadderCapture(attemptDepths: attemptDepths, deadline: deadline) {
192
+ depth in
193
+ RunnerAXSnapshotBridge.snapshotTree(
144
194
  for: app,
145
195
  maxDepth: depth,
146
196
  maxNodes: Self.privateAXSnapshotMaxNodes,
@@ -148,31 +198,18 @@ extension RunnerTests {
148
198
  customActionLimit: hint.customActions ? Self.privateAXCustomActionLimit : 0,
149
199
  deadline: deadline
150
200
  )
151
- if response["ok"] as? Bool == true {
152
- effectiveDepth = depth
153
- break
154
- }
155
- lastError = response["error"] as? String ?? lastError
156
- NSLog(
157
- "AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_DEPTH_RETRY depth=%ld error=%@",
158
- depth,
159
- lastError
160
- )
161
201
  }
162
- guard response["ok"] as? Bool == true else {
163
- NSLog("AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_FAILED=%@", lastError)
202
+ let response = ladder.response
203
+ let effectiveDepth = ladder.effectiveDepth
204
+ guard ladder.succeeded else {
205
+ NSLog("AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_FAILED=%@", ladder.lastError)
164
206
  return nil
165
207
  }
166
- // Only a capture that actually descended records memory: a first-rung success on a
167
- // remembered depth deliberately does NOT refresh the TTL, so expiry re-probes the full
168
- // requested depth once per window instead of capping this screen class forever.
169
- if !exactDepthRequested, effectiveDepth != attemptDepths.first {
170
- rememberPrivateAXAcceptedDepth(
171
- bundleId: currentBundleId,
172
- processIdentifier: currentAppProcessIdentifier,
173
- depth: effectiveDepth
174
- )
175
- }
208
+ recordPrivateAXAcceptedDepth(
209
+ exactDepthRequested: exactDepthRequested,
210
+ effectiveDepth: effectiveDepth,
211
+ attemptDepths: attemptDepths
212
+ )
176
213
  guard let root = response["root"] as? [String: Any] else {
177
214
  NSLog("AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_FAILED=missing root")
178
215
  return nil
@@ -185,17 +222,17 @@ extension RunnerTests {
185
222
  hint: hint,
186
223
  viewport: viewport
187
224
  )
188
- // Serialization-level emptiness only: an acquired-but-fully-clipped tree is presentation's
189
- // verdict now, surfaced by the plan's sparse classifier on the presented payload (#1797).
225
+
226
+
190
227
  if nodes.count <= 1 {
191
228
  NSLog("AGENT_DEVICE_RUNNER_PRIVATE_AX_SNAPSHOT_SPARSE=%ld", nodes.count)
192
229
  return nil
193
230
  }
194
231
 
195
- // A capture whose frontier extension resolved every capped node is
196
- // complete despite the per-request depth cap — reporting it as
197
- // depth-limited would send agents chasing deeper content that is not
198
- // there. Pending or missed frontiers keep the depth-limited verdict.
232
+
233
+
234
+
235
+
199
236
  let deepExtension = response[RunnerAXSnapshotDeepExtensionKey] as? [String: Any]
200
237
  let depthLimited = Self.privateAXDepthLimited(
201
238
  effectiveDepth: effectiveDepth,
@@ -224,10 +261,10 @@ extension RunnerTests {
224
261
  #endif
225
262
  }
226
263
 
227
- /// The viewport read is XCTest main-thread work — the exact channel the penalty marks as
228
- /// grinding on this screen class. Under penalty it reliably burns its full timeout and
229
- /// falls back anyway (~1s added to every private AX capture on the Bluesky bench feed),
230
- /// so honor the penalty here the same way capture plans do.
264
+
265
+
266
+
267
+
231
268
  func shouldReadPrivateAXViewportViaXCTest() -> Bool {
232
269
  !hasAbandonedTreeCapture() && !isSnapshotXCTestChannelPenalized(bundleId: currentBundleId)
233
270
  }
@@ -273,3 +310,552 @@ extension RunnerTests {
273
310
  }
274
311
  }
275
312
 
313
+
314
+
315
+
316
+
317
+
318
+
319
+
320
+
321
+
322
+
323
+
324
+
325
+
326
+
327
+
328
+
329
+
330
+
331
+
332
+
333
+
334
+
335
+
336
+
337
+
338
+
339
+
340
+
341
+
342
+
343
+
344
+
345
+
346
+
347
+
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+
358
+
359
+
360
+
361
+
362
+
363
+
364
+
365
+
366
+
367
+
368
+
369
+
370
+
371
+
372
+
373
+
374
+
375
+
376
+
377
+
378
+
379
+
380
+
381
+
382
+
383
+
384
+
385
+
386
+
387
+
388
+
389
+
390
+
391
+
392
+
393
+
394
+
395
+
396
+
397
+
398
+
399
+
400
+
401
+
402
+
403
+
404
+
405
+
406
+
407
+
408
+
409
+
410
+
411
+
412
+
413
+
414
+
415
+
416
+
417
+
418
+
419
+
420
+
421
+
422
+
423
+
424
+
425
+
426
+
427
+
428
+
429
+
430
+
431
+
432
+
433
+
434
+
435
+
436
+
437
+
438
+
439
+
440
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+
450
+
451
+
452
+
453
+
454
+
455
+
456
+
457
+
458
+
459
+
460
+
461
+
462
+
463
+
464
+
465
+
466
+
467
+
468
+
469
+
470
+
471
+
472
+
473
+
474
+
475
+
476
+
477
+
478
+
479
+
480
+
481
+
482
+
483
+
484
+
485
+
486
+
487
+
488
+
489
+
490
+
491
+
492
+
493
+
494
+
495
+
496
+
497
+
498
+
499
+
500
+
501
+
502
+
503
+
504
+
505
+
506
+
507
+
508
+
509
+
510
+
511
+
512
+
513
+
514
+
515
+
516
+
517
+
518
+
519
+
520
+
521
+
522
+
523
+
524
+
525
+
526
+
527
+
528
+
529
+
530
+
531
+
532
+
533
+
534
+
535
+
536
+
537
+
538
+
539
+
540
+
541
+
542
+
543
+
544
+
545
+
546
+
547
+
548
+
549
+
550
+
551
+
552
+
553
+
554
+
555
+
556
+
557
+
558
+
559
+
560
+
561
+
562
+
563
+
564
+
565
+
566
+
567
+
568
+
569
+
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+
598
+
599
+
600
+
601
+
602
+
603
+
604
+
605
+
606
+
607
+
608
+
609
+
610
+
611
+
612
+
613
+
614
+
615
+
616
+
617
+
618
+
619
+
620
+
621
+
622
+
623
+
624
+
625
+
626
+
627
+
628
+
629
+
630
+
631
+
632
+
633
+
634
+
635
+
636
+
637
+
638
+
639
+
640
+
641
+
642
+
643
+
644
+
645
+
646
+
647
+
648
+
649
+
650
+
651
+
652
+
653
+
654
+
655
+
656
+
657
+
658
+
659
+
660
+
661
+
662
+
663
+
664
+
665
+
666
+
667
+
668
+
669
+
670
+
671
+
672
+
673
+
674
+
675
+
676
+
677
+
678
+
679
+
680
+
681
+
682
+
683
+
684
+
685
+
686
+
687
+
688
+
689
+
690
+
691
+
692
+
693
+
694
+
695
+
696
+
697
+
698
+
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+
707
+
708
+
709
+
710
+
711
+
712
+
713
+
714
+
715
+
716
+
717
+
718
+
719
+
720
+
721
+
722
+
723
+
724
+
725
+
726
+
727
+
728
+
729
+
730
+
731
+
732
+
733
+
734
+
735
+
736
+
737
+
738
+
739
+
740
+
741
+
742
+
743
+
744
+
745
+
746
+
747
+
748
+
749
+
750
+
751
+
752
+
753
+
754
+
755
+
756
+
757
+
758
+
759
+
760
+
761
+
762
+
763
+
764
+
765
+
766
+
767
+
768
+
769
+
770
+
771
+
772
+
773
+
774
+
775
+
776
+
777
+
778
+
779
+
780
+
781
+
782
+
783
+
784
+
785
+
786
+
787
+
788
+
789
+
790
+
791
+
792
+
793
+
794
+
795
+
796
+
797
+
798
+
799
+
800
+
801
+
802
+
803
+
804
+
805
+
806
+
807
+
808
+
809
+
810
+
811
+
812
+
813
+
814
+
815
+
816
+
817
+
818
+
819
+
820
+
821
+
822
+
823
+
824
+
825
+
826
+
827
+
828
+
829
+
830
+
831
+
832
+
833
+
834
+
835
+
836
+
837
+
838
+
839
+
840
+
841
+
842
+
843
+
844
+
845
+
846
+
847
+
848
+
849
+
850
+
851
+
852
+
853
+
854
+
855
+
856
+
857
+
858
+
859
+
860
+
861
+