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
@@ -1,33 +1,33 @@
1
1
  import XCTest
2
2
  import AgentDeviceSnapshotPresentation
3
3
 
4
- // MARK: - Snapshot capture plans (ADR 0004)
5
- //
6
- // Each snapshot strategy declares an ordered chain of capture backends. One runner walks the
7
- // chain: capture, classify, accept the first payload the quality classifier calls usable, and
8
- // stamp the outcome with a structured quality verdict so the daemon renders state instead of
9
- // re-deriving it from node shapes. Recovery ordering is data here, never a per-call-site branch.
10
-
11
- /// Structured quality verdict shipped with every iOS snapshot payload.
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
12
  struct SnapshotQuality: Codable {
13
- /// healthy: first backend produced a usable tree. recovered: a later backend did.
14
- /// sparse: no backend produced a usable tree; the best attempt is returned as-is.
13
+
14
+
15
15
  let state: String
16
- /// Backend that produced the returned payload: tree | queries | private-ax.
16
+
17
17
  let backend: String
18
- /// Why recovery ran (first failure), why the payload is degraded, or why an internal backend
19
- /// selection was honored.
18
+
19
+
20
20
  let reason: String?
21
- /// Machine-readable reason: ax-rejected | sparse-tree | budget | no-nodes | capture-failed |
22
- /// presentation-failed | deferred | requested-backend.
21
+
22
+
23
23
  let reasonCode: String?
24
- /// Private AX ladder cap when the accepted tree is shallower than requested.
24
+
25
25
  let effectiveDepth: Int?
26
- /// Leaves that merge many labels — a container marked accessible hides its descendants.
26
+
27
27
  let collapsedLeafIndexes: [Int]?
28
- /// Coverage of the bounded custom-action pass, when the capture asked for one.
28
+
29
29
  let customActions: SnapshotCustomActionCoverage?
30
- /// Response-level timing for the accepted backend attempt, never repeated per node.
30
+
31
31
  var timing: SnapshotCaptureTiming? = nil
32
32
  }
33
33
 
@@ -41,18 +41,18 @@ struct EffectiveSnapshotCapturePlan {
41
41
  let plan: [SnapshotBackendKind]
42
42
  let xCTestChannelState: SnapshotXCTestChannelPlanState
43
43
  let treeCaptureSliceBudgetOverride: TimeInterval?
44
- /// Non-nil only when the plan was narrowed by an explicit internal backend preference. This
45
- /// keeps the quality marker tied to the plan decision rather than to an untrusted request field.
44
+
45
+
46
46
  let preferredBackend: SnapshotBackendKind?
47
47
  }
48
48
 
49
- /// What the plan runner does when every backend failed or stayed sparse.
49
+
50
50
  enum SnapshotCaptureTerminalPolicy {
51
- /// Return the best sparse payload; if the tree backend hit a real AX serialization failure
52
- /// on an interactive request, fail closed: invalidate the cached target and mark runnerFatal
53
- /// (AX-unavailable target invalidation, CONTEXT.md).
51
+
52
+
53
+
54
54
  case sparseWithFatalOnAXFailure
55
- /// Re-throw the tree backend's AX failure (raw diagnostics preserve errors, ADR 0004).
55
+
56
56
  case throwOnAXFailure
57
57
  }
58
58
 
@@ -79,9 +79,9 @@ extension RunnerTests {
79
79
  }
80
80
 
81
81
  static let sparseRecoveryTruncatedNodeThreshold = 8
82
- /// Umbrella wall-clock budget for one capture plan. Individual backends bound themselves,
83
- /// but chained recovery tiers must never stack past the 30s main-thread watchdog: when the
84
- /// budget is spent, remaining tiers are skipped and the best payload so far is returned.
82
+
83
+
84
+
85
85
  static let snapshotPlanBudget: TimeInterval = 20
86
86
  static let penalizedXCTestProbeTreeSliceBudget: TimeInterval = 1
87
87
  static let collapsedLeafMinimumSegments = 10
@@ -90,21 +90,21 @@ extension RunnerTests {
90
90
  payload?.nodes?.count ?? 0
91
91
  }
92
92
 
93
- // MARK: Plan definitions
93
+
94
94
 
95
95
  static let regularVisiblePlan: [SnapshotBackendKind] = [.recursiveTree, .querySweep, .privateAX]
96
- /// Derived from the backend trait rather than hand-listed: a backend that cannot serve the raw
97
- /// projection drops out of the raw plan by construction, and a new one joins it by declaring the
98
- /// trait instead of by someone remembering this line.
96
+
97
+
98
+
99
99
  static let rawDiagnosticPlan: [SnapshotBackendKind] = regularVisiblePlan.filter(\.supportsRawProjection)
100
100
 
101
- // MARK: XCTest accessibility channel penalty (cross-attempt memory, #1105/#1156)
102
- //
103
- // On some deep/dynamic screens the XCTest bulk snapshot no longer fails fast with
104
- // kAXErrorIllegalArgument (the #758 signature) — it grinds for many seconds first. One slow
105
- // grind is tolerable; re-grinding on every subsequent capture of the same screen buries the
106
- // main thread past the execution watchdog. After a slow, timed-out, or abandoned XCTest-backed
107
- // capture, later plans for the same bundle use non-XCTest recovery tiers until the penalty expires.
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
108
 
109
109
  func penalizeSnapshotXCTestChannel(bundleId: String?, reason: String) {
110
110
  snapshotXCTestChannelPenaltyLock.lock()
@@ -133,7 +133,7 @@ extension RunnerTests {
133
133
  snapshotXCTestChannelPenaltyLock.lock()
134
134
  defer { snapshotXCTestChannelPenaltyLock.unlock() }
135
135
  guard Date() < snapshotXCTestChannelPenaltyUntil else { return false }
136
- // A penalty recorded without a bundle id applies to whatever target is current.
136
+
137
137
  guard let penalized = snapshotXCTestChannelPenaltyBundleId else { return true }
138
138
  return penalized == bundleId
139
139
  }
@@ -144,16 +144,16 @@ extension RunnerTests {
144
144
  return pending
145
145
  }
146
146
 
147
- /// The pre-seeded first-failure a penalized plan stamps into its verdict. The deferred case
148
- /// uses the dedicated 'deferred' code: the breaker pre-selected the backend, nothing new
149
- /// degraded on this capture, and the daemon keys warning suppression and the settle budget
150
- /// reset off exactly that distinction. The bounded probe keeps 'budget': its short XCTest
151
- /// slice genuinely constrains what this capture could read.
152
- ///
153
- /// `requestPinnedBackend` separates the two ways the plan can arrive at the same
154
- /// deferred shape. A capture that ASKED for a private-AX-only reading (custom
155
- /// actions) degraded nothing, so reporting slow accessibility work would name a
156
- /// cause that does not exist.
147
+
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
157
  static func xcTestChannelStateFirstFailure(
158
158
  _ state: SnapshotXCTestChannelPlanState,
159
159
  requestPinnedBackend: Bool = false,
@@ -187,10 +187,10 @@ extension RunnerTests {
187
187
  }
188
188
  }
189
189
 
190
- /// Pure gate: a capture is planned as penalized when the channel penalty is
191
- /// active OR the daemon pinned the private-AX backend (same-backend evidence
192
- /// probe) — both mean "do not enter XCTest tree work first, and stamp the
193
- /// pre-selection as 'deferred' rather than a degradation".
190
+
191
+
192
+
193
+
194
194
  static func snapshotXCTestChannelTreatedAsPenalized(
195
195
  penalized: Bool,
196
196
  preferredBackend: String?
@@ -198,11 +198,11 @@ extension RunnerTests {
198
198
  penalized || preferredBackend == SnapshotBackendKind.privateAX.rawValue
199
199
  }
200
200
 
201
- /// Pure plan-reorder rule: an internal preferred backend pins the regular plan to that backend;
202
- /// this is the only force seam used by same-backend evidence and conformance captures. A
203
- /// penalized XCTest accessibility channel uses independent backends when the platform has one,
204
- /// otherwise it keeps XCTest work on a short probe. The raw diagnostic plan keeps tree-first
205
- /// errors, and unknown plans are left untouched.
201
+
202
+
203
+
204
+
205
+
206
206
  static func effectiveSnapshotCapturePlan(
207
207
  _ plan: [SnapshotBackendKind],
208
208
  xCTestChannelPenalized: Bool,
@@ -252,7 +252,7 @@ extension RunnerTests {
252
252
  kind.usesXCTestAccessibilityChannel && hasAbandonedTreeCapture()
253
253
  }
254
254
 
255
- // MARK: Plan runner
255
+
256
256
 
257
257
  func runSnapshotCapturePlan(
258
258
  _ plan: [SnapshotBackendKind],
@@ -264,16 +264,16 @@ extension RunnerTests {
264
264
  var best: (kind: SnapshotBackendKind, capture: SnapshotBackendCapture)?
265
265
  var firstFailure: (reason: String, code: String)?
266
266
  var axFailure: SnapshotCaptureFailure?
267
- // A caller may share the pre-plan system-modal probe's deadline; otherwise own the full budget (#1244).
267
+
268
268
  let deadline = deadline ?? Date().addingTimeInterval(Self.snapshotPlanBudget)
269
269
  let suppressXCTestPenalty = consumeSnapshotXCTestPenaltyWarmupExemption()
270
270
 
271
- // Reorder is iOS-only because hostile screens can make XCTest tree/query work grind while
272
- // the app remains visually responsive. Simulators can avoid that channel through private AX;
273
- // physical devices have no independent semantic backend yet, so they use a bounded probe.
274
- // A daemon-preferred private-AX capture (same-backend evidence probe) takes the exact
275
- // penalized route: privateAX-first plan, 'deferred' verdict — the backend was pre-selected
276
- // deliberately, so no degradation warning should render for it.
271
+
272
+
273
+
274
+
275
+
276
+
277
277
  var xCTestChannelPenalized = false
278
278
  var xCTestChannelPenalizedByBreaker = false
279
279
  #if os(iOS)
@@ -290,8 +290,8 @@ extension RunnerTests {
290
290
  preferredBackend: options.preferredBackend
291
291
  )
292
292
  let effectivePlan = effective.plan
293
- // Only a customActions-implied pin is request-pinned; the daemon's
294
- // same-backend evidence probe pins for its own reasons and keeps 'deferred'.
293
+
294
+
295
295
  firstFailure = Self.xcTestChannelStateFirstFailure(
296
296
  effective.xCTestChannelState,
297
297
  requestPinnedBackend: options.customActions && !xCTestChannelPenalizedByBreaker,
@@ -314,8 +314,8 @@ extension RunnerTests {
314
314
  }
315
315
  break
316
316
  }
317
- // While an abandoned tree capture is still grinding inside testmanagerd, XCTest-backed
318
- // tiers would block behind it; only independent backends stay responsive (#1105).
317
+
318
+
319
319
  if shouldSkipSnapshotBackendForAbandonedTreeCapture(kind) {
320
320
  NSLog("AGENT_DEVICE_RUNNER_SNAPSHOT_TIER_SKIPPED_XCTEST_OCCUPIED tier=%@", kind.rawValue)
321
321
  if firstFailure == nil {
@@ -384,11 +384,11 @@ extension RunnerTests {
384
384
  case .throwAxFailure:
385
385
  throw axFailure
386
386
  case .failClosed:
387
- // Fail closed on any interactive AX serialization failure that no backend recovered:
388
- // invalidate the cached target so the next command reacquires it (AX-unavailable target
389
- // invalidation, CONTEXT.md). A sparse `best` from a later tier (e.g. the query sweep's
390
- // synthetic root) must NOT suppress this — reaching the terminal already means no backend
391
- // produced a usable tree.
387
+
388
+
389
+
390
+
391
+
392
392
  return snapshotAccessibilityUnavailable(failure: axFailure)
393
393
  case .sparseBest:
394
394
  break
@@ -415,22 +415,6 @@ extension RunnerTests {
415
415
  ) throws -> SnapshotBackendAttempt {
416
416
  let hint = SnapshotPresentation.captureHint(for: options)
417
417
  var timer = SnapshotPhaseTimer()
418
- // Scoped depth is relative to a presentation-selected root, so its hint stays broad and the
419
- // backend capability gate applies only to an unscoped regular frontier.
420
- let requestedRegularDepth = options.raw || SnapshotScopePolicy.isActive(options.scope)
421
- ? nil
422
- : options.depth
423
- guard kind.canServeRegularPresentedDepth(requestedRegularDepth) else {
424
- NSLog(
425
- "AGENT_DEVICE_RUNNER_SNAPSHOT_BACKEND_DEPTH_UNSUPPORTED backend=%@ depth=%ld",
426
- kind.rawValue,
427
- requestedRegularDepth ?? -1
428
- )
429
- return SnapshotBackendAttempt(
430
- outcome: .noCapture,
431
- timing: timer.timing
432
- )
433
- }
434
418
  let acquisition: SnapshotAcquisition?
435
419
  do {
436
420
  acquisition = try timer.measure(.acquisition) {
@@ -523,8 +507,8 @@ extension RunnerTests {
523
507
  )
524
508
  }
525
509
 
526
- /// A backend that answers a request with the other projection loses its tier and says why, so
527
- /// the miss lands in the quality verdict instead of shipping as a correct-looking capture.
510
+
511
+
528
512
  static func snapshotProjectionMismatchFailure(
529
513
  _ kind: SnapshotBackendKind,
530
514
  requested: CaptureHint.Projection,
@@ -538,9 +522,9 @@ extension RunnerTests {
538
522
  )
539
523
  }
540
524
 
541
- // MARK: Quality classifier (the single source of "is this snapshot degraded")
542
525
 
543
- /// Returns a degradation reason + machine code when the payload is too degraded to accept.
526
+
527
+
544
528
  static func sparsePayloadReason(_ payload: DataPayload) -> (reason: String, code: String)? {
545
529
  guard let nodes = payload.nodes, !nodes.isEmpty else {
546
530
  return ("snapshot returned no nodes", "no-nodes")
@@ -554,9 +538,9 @@ extension RunnerTests {
554
538
  return nil
555
539
  }
556
540
 
557
- /// Terminal action when a capture plan exhausted every backend with an AX serialization
558
- /// failure still pending. Pure so the fail-closed-vs-sparse policy is unit-testable without
559
- /// a live app (the ordering gap the architecture review flagged).
541
+
542
+
543
+
560
544
  enum SnapshotPlanTerminalAction: Equatable {
561
545
  case throwAxFailure
562
546
  case failClosed
@@ -581,8 +565,8 @@ extension RunnerTests {
581
565
  node.type == "Application" || node.type == "Window" ? node.rect : nil
582
566
  }
583
567
  return nodes.allSatisfy { node in
584
- // Application/Window labels are just the app/window name, and full-screen roots
585
- // compute as hittable; neither says anything about tree health.
568
+
569
+
586
570
  let isRootContainer = node.type == "Application" || node.type == "Window"
587
571
  guard Self.structuralOnlyNodeTypes.contains(node.type) else { return false }
588
572
  guard !isRootContainer else { return true }
@@ -598,18 +582,18 @@ extension RunnerTests {
598
582
  }
599
583
  }
600
584
 
601
- /// Private AX can stringify an unserializable accessibility label as the JavaScript object
602
- /// placeholder. It is transport residue, not UI content, and must not make a shell-only tree
603
- /// look healthy.
585
+
586
+
587
+
604
588
  static func isSemanticSnapshotText(_ text: String?) -> Bool {
605
589
  guard let text else { return false }
606
590
  let normalized = text.trimmingCharacters(in: .whitespacesAndNewlines)
607
591
  return !normalized.isEmpty && normalized.lowercased() != "[object object]"
608
592
  }
609
593
 
610
- /// A leaf whose label joins many short segments is a container marked as an accessibility
611
- /// element: the platform folds every descendant into one merged node. Nothing below it can
612
- /// be addressed — by automation or by assistive tech. This is app-side; no backend recovers it.
594
+
595
+
596
+
613
597
  static func collapsedLeafIndexes(_ nodes: [PresentedNode]) -> [Int]? {
614
598
  let parents = Set(nodes.compactMap { $0.parentIndex })
615
599
  let collapsed = nodes.filter { node in
@@ -621,7 +605,7 @@ extension RunnerTests {
621
605
  return collapsed.isEmpty ? nil : collapsed.map(\.index)
622
606
  }
623
607
 
624
- // MARK: Outcome stamping
608
+
625
609
 
626
610
  private func stampedSnapshotPayload(
627
611
  _ capture: SnapshotBackendCapture,
@@ -642,13 +626,13 @@ extension RunnerTests {
642
626
  timing: capture.timing
643
627
  )
644
628
  return DataPayload(
645
- // Legacy human text for older daemons that read message instead of snapshotQuality.
629
+
646
630
  message: Self.legacyQualityMessage(quality) ?? payload.message,
647
631
  nodes: payload.nodes,
648
- // Completeness, never provenance: a whole tree that a later backend produced (state
649
- // "recovered") stays untruncated, so strict absence reads can trust it. Only a real cap
650
- // (payload truncation, a depth-limited private AX capture) or a sparse terminal payload
651
- // is truncated.
632
+
633
+
634
+
635
+
652
636
  truncated: payload.truncated == true || state == "sparse" || capture.effectiveDepth != nil,
653
637
  qualityPayload: capture.qualityPayload.flatMap { quality in
654
638
  guard let nodes = quality.nodes else { return nil }
@@ -660,14 +644,14 @@ extension RunnerTests {
660
644
  )
661
645
  }
662
646
 
663
- /// Response level, one line per incompleteness. An unread merged element is
664
- /// byte-identical to one with no actions, and a clipped list looks complete,
665
- /// so both have to name themselves.
647
+
648
+
649
+
666
650
  static func customActionCoverageWarnings(_ coverage: SnapshotCustomActionCoverage) -> [String] {
667
651
  var lines: [String] = []
668
652
  if coverage.blocked {
669
- // Scrolling is the remedy for a budget stop, not for this one — saying it
670
- // here would send the reader off doing something that cannot help.
653
+
654
+
671
655
  lines.append(
672
656
  "Custom actions were not read: an earlier accessibility read is still hung, so this "
673
657
  + "capture skipped the read pass instead of queueing behind it. No element's actions "
@@ -719,9 +703,9 @@ extension RunnerTests {
719
703
  }
720
704
  parts.append(contentsOf: customActionWarnings)
721
705
  if let depth = quality.effectiveDepth {
722
- // No --depth remedy here: an explicit --depth capture disables the
723
- // frontier extension, so following it would return strictly less than
724
- // this capture did. A plain re-run retries with a fresh extension budget.
706
+
707
+
708
+
725
709
  parts.append(
726
710
  "The accessibility server rejected deeper requests; content below depth \(depth) may be missing — re-run snapshot to retry deeper content."
727
711
  )
@@ -730,3 +714,514 @@ extension RunnerTests {
730
714
  }
731
715
  }
732
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
+
862
+
863
+
864
+
865
+
866
+
867
+
868
+
869
+
870
+
871
+
872
+
873
+
874
+
875
+
876
+
877
+
878
+
879
+
880
+
881
+
882
+
883
+
884
+
885
+
886
+
887
+
888
+
889
+
890
+
891
+
892
+
893
+
894
+
895
+
896
+
897
+
898
+
899
+
900
+
901
+
902
+
903
+
904
+
905
+
906
+
907
+
908
+
909
+
910
+
911
+
912
+
913
+
914
+
915
+
916
+
917
+
918
+
919
+
920
+
921
+
922
+
923
+
924
+
925
+
926
+
927
+
928
+
929
+
930
+
931
+
932
+
933
+
934
+
935
+
936
+
937
+
938
+
939
+
940
+
941
+
942
+
943
+
944
+
945
+
946
+
947
+
948
+
949
+
950
+
951
+
952
+
953
+
954
+
955
+
956
+
957
+
958
+
959
+
960
+
961
+
962
+
963
+
964
+
965
+
966
+
967
+
968
+
969
+
970
+
971
+
972
+
973
+
974
+
975
+
976
+
977
+
978
+
979
+
980
+
981
+
982
+
983
+
984
+
985
+
986
+
987
+
988
+
989
+
990
+
991
+
992
+
993
+
994
+
995
+
996
+
997
+
998
+
999
+
1000
+
1001
+
1002
+
1003
+
1004
+
1005
+
1006
+
1007
+
1008
+
1009
+
1010
+
1011
+
1012
+
1013
+
1014
+
1015
+
1016
+
1017
+
1018
+
1019
+
1020
+
1021
+
1022
+
1023
+
1024
+
1025
+
1026
+
1027
+
1028
+
1029
+
1030
+
1031
+
1032
+
1033
+
1034
+
1035
+
1036
+
1037
+
1038
+
1039
+
1040
+
1041
+
1042
+
1043
+
1044
+
1045
+
1046
+
1047
+
1048
+
1049
+
1050
+
1051
+
1052
+
1053
+
1054
+
1055
+
1056
+
1057
+
1058
+
1059
+
1060
+
1061
+
1062
+
1063
+
1064
+
1065
+
1066
+
1067
+
1068
+
1069
+
1070
+
1071
+
1072
+
1073
+
1074
+
1075
+
1076
+
1077
+
1078
+
1079
+
1080
+
1081
+
1082
+
1083
+
1084
+
1085
+
1086
+
1087
+
1088
+
1089
+
1090
+
1091
+
1092
+
1093
+
1094
+
1095
+
1096
+
1097
+
1098
+
1099
+
1100
+
1101
+
1102
+
1103
+
1104
+
1105
+
1106
+
1107
+
1108
+
1109
+
1110
+
1111
+
1112
+
1113
+
1114
+
1115
+
1116
+
1117
+
1118
+
1119
+
1120
+
1121
+
1122
+
1123
+
1124
+
1125
+
1126
+
1127
+
1128
+
1129
+
1130
+
1131
+
1132
+
1133
+
1134
+
1135
+
1136
+
1137
+
1138
+
1139
+
1140
+
1141
+
1142
+
1143
+
1144
+
1145
+
1146
+
1147
+
1148
+
1149
+
1150
+
1151
+
1152
+
1153
+
1154
+
1155
+
1156
+
1157
+
1158
+
1159
+
1160
+
1161
+
1162
+
1163
+
1164
+
1165
+
1166
+
1167
+
1168
+
1169
+
1170
+
1171
+
1172
+
1173
+
1174
+
1175
+
1176
+
1177
+
1178
+
1179
+
1180
+
1181
+
1182
+
1183
+
1184
+
1185
+
1186
+
1187
+
1188
+
1189
+
1190
+
1191
+
1192
+
1193
+
1194
+
1195
+
1196
+
1197
+
1198
+
1199
+
1200
+
1201
+
1202
+
1203
+
1204
+
1205
+
1206
+
1207
+
1208
+
1209
+
1210
+
1211
+
1212
+
1213
+
1214
+
1215
+
1216
+
1217
+
1218
+
1219
+
1220
+
1221
+
1222
+
1223
+
1224
+
1225
+
1226
+
1227
+