agent-device 0.21.13 → 0.21.15

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 (298) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.13.apk → agent-device-android-ime-helper-0.21.15.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.15.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.13.manifest.json → agent-device-android-ime-helper-0.21.15.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.15.apk +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.15.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.13.manifest.json → agent-device-android-snapshot-helper-0.21.15.manifest.json} +6 -6
  7. package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +11 -1
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +110 -2
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +4 -2
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerMainOwnedState.swift +27 -0
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +8 -2
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +26 -1
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +12 -19
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +59 -20
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AlertObservation.swift +2 -3
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +179 -91
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +21 -24
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+GestureExecution.swift +9 -13
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +36 -49
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+MainThreadWork.swift +11 -15
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +136 -29
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +20 -21
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +3 -0
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +6 -5
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollDragExecution.swift +12 -24
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +22 -42
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +15 -18
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +73 -31
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +20 -11
  31. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +9 -7
  32. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +5 -4
  33. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +2 -2
  34. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +51 -19
  35. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +5 -2
  36. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +78 -10
  37. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +32 -2
  38. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +7 -4
  39. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +23 -0
  40. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +17 -10
  41. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +8 -9
  42. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +9 -15
  43. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +12 -11
  44. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +16 -19
  45. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +24 -9
  46. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +66 -10
  47. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +12 -10
  48. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +1 -0
  49. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +27 -5
  50. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFoldProjection.swift +1 -0
  51. package/dist/src/adapter.js +1 -1
  52. package/dist/src/adb-executor.js +1 -1
  53. package/dist/src/adb-failure.js +1 -1
  54. package/dist/src/adb-transport.js +1 -1
  55. package/dist/src/agent-browser-provider.js +1 -1
  56. package/dist/src/agent-browser-tool.js +1 -1
  57. package/dist/src/agent-device-client.js +2 -2
  58. package/dist/src/ai-sdk.js +1 -1
  59. package/dist/src/alert-runtime.js +1 -1
  60. package/dist/src/android-adb.d.ts +1 -8
  61. package/dist/src/android-input-ownership.js +1 -1
  62. package/dist/src/android-snapshot-quality.js +1 -0
  63. package/dist/src/android-system-chrome.js +1 -1
  64. package/dist/src/android.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.js +1 -1
  68. package/dist/src/app-launch.js +1 -1
  69. package/dist/src/app-lifecycle.js +1 -1
  70. package/dist/src/app-lifecycle2.js +1 -1
  71. package/dist/src/app-log-files.js +1 -1
  72. package/dist/src/app-log-runtime2.js +1 -1
  73. package/dist/src/app-resolution.js +2 -2
  74. package/dist/src/apple-runner-platform.js +1 -1
  75. package/dist/src/application-lifecycle-interaction.js +1 -1
  76. package/dist/src/archive.js +1 -1
  77. package/dist/src/artifact-download.js +1 -1
  78. package/dist/src/auth-session.js +1 -1
  79. package/dist/src/auth.js +1 -1
  80. package/dist/src/backend-snapshot-options.js +1 -1
  81. package/dist/src/boot-diagnostics.js +1 -1
  82. package/dist/src/capture-disclosure.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 +2 -2
  86. package/dist/src/cli.js +4 -4
  87. package/dist/src/click-button.js +1 -1
  88. package/dist/src/client-metro.js +1 -1
  89. package/dist/src/client-types.d.ts +102 -95
  90. package/dist/src/clipboard-shell-response.js +1 -1
  91. package/dist/src/command-schema.js +1 -1
  92. package/dist/src/command-tools.js +3 -3
  93. package/dist/src/connection-runtime.js +1 -1
  94. package/dist/src/connection.js +1 -1
  95. package/dist/src/contracts.d.ts +1 -1
  96. package/dist/src/contracts.js +1 -1
  97. package/dist/src/daemon-client-lifecycle.js +1 -1
  98. package/dist/src/daemon.js +1 -1
  99. package/dist/src/debug-symbols-facade.js +1 -1
  100. package/dist/src/device-claim-rule.js +2 -2
  101. package/dist/src/device-input-state.d.ts +15 -2
  102. package/dist/src/device-inventory-context.js +1 -1
  103. package/dist/src/device-rotation.js +1 -1
  104. package/dist/src/device-selection-resolver.js +1 -1
  105. package/dist/src/device-session.js +1 -1
  106. package/dist/src/device-shell.js +1 -1
  107. package/dist/src/device2.js +1 -1
  108. package/dist/src/devicectl.js +1 -1
  109. package/dist/src/diagnostics.js +1 -1
  110. package/dist/src/dispatch-resolve.js +1 -1
  111. package/dist/src/doctor2.js +1 -1
  112. package/dist/src/engine-eval-script.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/format.js +1 -1
  118. package/dist/src/gesture-plan-types.d.ts +1 -1
  119. package/dist/src/gesture-plan.js +1 -1
  120. package/dist/src/gesture-runtime.js +1 -1
  121. package/dist/src/harmonyos.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 +7 -3
  126. package/dist/src/index.js +1 -1
  127. package/dist/src/input-actions.js +1 -1
  128. package/dist/src/input-actions2.js +1 -1
  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-operation-binding.js +1 -1
  136. package/dist/src/interactor.js +4 -4
  137. package/dist/src/interactor2.js +1 -1
  138. package/dist/src/interactors.js +1 -1
  139. package/dist/src/internal/bin.js +1 -1
  140. package/dist/src/internal/daemon.js +2 -2
  141. package/dist/src/internal/png-worker.js +1 -1
  142. package/dist/src/internal/run-script-http-child.js +1 -1
  143. package/dist/src/inventory.js +1 -1
  144. package/dist/src/inventory2.js +1 -1
  145. package/dist/src/inventory3.js +1 -1
  146. package/dist/src/inventory5.js +1 -1
  147. package/dist/src/ios-snapshot-acquisition.js +1 -1
  148. package/dist/src/ios-snapshot-engine.js +1 -0
  149. package/dist/src/ios-snapshot-runtime.js +1 -1
  150. package/dist/src/lease.js +1 -1
  151. package/dist/src/limrun-download-file.js +1 -1
  152. package/dist/src/limrun-runtime-dependencies.js +1 -1
  153. package/dist/src/limrun.d.ts +16 -3
  154. package/dist/src/linux.js +1 -1
  155. package/dist/src/location-coordinates.js +1 -1
  156. package/dist/src/managed-device-scope.js +1 -1
  157. package/dist/src/mechanics.js +17 -17
  158. package/dist/src/mobile-snapshot-semantics.js +1 -1
  159. package/dist/src/multitouch-support.js +1 -1
  160. package/dist/src/native-build-cache.js +1 -0
  161. package/dist/src/observation.js +1 -1
  162. package/dist/src/overlay.js +3 -0
  163. package/dist/src/parameterized-recorded-fill.js +1 -1
  164. package/dist/src/perf-facade.js +1 -1
  165. package/dist/src/perf-runtime-operation-builder.js +1 -1
  166. package/dist/src/perf-runtime-plan.js +1 -1
  167. package/dist/src/perf-target.js +2 -2
  168. package/dist/src/perf.js +1 -1
  169. package/dist/src/physical-device-control.js +1 -1
  170. package/dist/src/platform-runtime-host.js +1 -1
  171. package/dist/src/platform-runtime-managed-owner.js +1 -1
  172. package/dist/src/platform-runtime-open-target.js +1 -1
  173. package/dist/src/platform-runtime-operation-host.js +4 -4
  174. package/dist/src/platform-runtime-runtime-hints.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-screen-recording-process-host.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-crop-bytes.js +1 -1
  181. package/dist/src/png-size.js +1 -1
  182. package/dist/src/png-worker-client.js +1 -1
  183. package/dist/src/png.js +1 -1
  184. package/dist/src/prepare-kind.js +1 -1
  185. package/dist/src/provider-session-ownership.js +1 -1
  186. package/dist/src/provider-webdriver.js +1 -1
  187. package/dist/src/proxy.js +1 -1
  188. package/dist/src/quality-warnings.js +1 -1
  189. package/dist/src/react-native.js +1 -1
  190. package/dist/src/record-runtime.js +1 -1
  191. package/dist/src/recording.js +1 -1
  192. package/dist/src/rect-center.js +1 -1
  193. package/dist/src/register-builtins.js +1 -1
  194. package/dist/src/registry.js +36 -36
  195. package/dist/src/remote-config2.js +1 -1
  196. package/dist/src/replay-divergence.js +1 -1
  197. package/dist/src/replay.js +1 -1
  198. package/dist/src/reporting.js +1 -1
  199. package/dist/src/request-admission.js +1 -1
  200. package/dist/src/request-cancel.js +1 -1
  201. package/dist/src/request-runtime-binding.js +1 -1
  202. package/dist/src/retry.js +1 -1
  203. package/dist/src/runner-cache-metadata.js +1 -1
  204. package/dist/src/runner-client.js +1 -1
  205. package/dist/src/runner-dev-tools-security.js +1 -1
  206. package/dist/src/runner-device-readiness.js +1 -1
  207. package/dist/src/runner-disposal.js +1 -1
  208. package/dist/src/runner-error-classification.js +1 -1
  209. package/dist/src/runner.js +1 -1
  210. package/dist/src/runtime-transport-hints.js +1 -1
  211. package/dist/src/runtime.js +1 -3
  212. package/dist/src/runtime10.js +2 -2
  213. package/dist/src/runtime2.js +4 -4
  214. package/dist/src/runtime3.js +1 -1
  215. package/dist/src/runtime4.js +5 -5
  216. package/dist/src/runtime5.js +1 -1
  217. package/dist/src/runtime6.js +1 -1
  218. package/dist/src/runtime7.js +1 -1
  219. package/dist/src/runtime8.js +1 -1
  220. package/dist/src/runtime9.js +1 -1
  221. package/dist/src/screen-recording-admission-ledger.js +1 -1
  222. package/dist/src/screen-recording-completion.js +1 -1
  223. package/dist/src/screen-recording-options.js +1 -1
  224. package/dist/src/screen-recording-resource-recovery.js +1 -1
  225. package/dist/src/screenshot-density.js +1 -1
  226. package/dist/src/screenshot-image.js +1 -1
  227. package/dist/src/screenshot-overlay-draw.js +1 -1
  228. package/dist/src/screenshot-runtime.js +1 -1
  229. package/dist/src/screenshot.js +1 -1
  230. package/dist/src/screenshot3.js +1 -1
  231. package/dist/src/script.js +1 -1
  232. package/dist/src/scroll-command.d.ts +13 -6
  233. package/dist/src/scroll-command.js +1 -1
  234. package/dist/src/scroll-gesture.js +1 -1
  235. package/dist/src/sdk-batch-runner.js +2 -2
  236. package/dist/src/sdk-batch.js +2 -2
  237. package/dist/src/sdk-contracts.d.ts +59 -12
  238. package/dist/src/sdk-contracts.js +2 -2
  239. package/dist/src/sdk-device.js +1 -1
  240. package/dist/src/sdk-finders.d.ts +1 -1
  241. package/dist/src/sdk-io.js +1 -1
  242. package/dist/src/sdk-remote-config.js +1 -1
  243. package/dist/src/sdk-selectors.d.ts +1 -1
  244. package/dist/src/selection.js +0 -0
  245. package/dist/src/selector-runtime.js +1 -1
  246. package/dist/src/server.js +1 -1
  247. package/dist/src/session-allocation.js +1 -1
  248. package/dist/src/session-routing.js +1 -1
  249. package/dist/src/session-runtime-admission.js +1 -1
  250. package/dist/src/session-snapshot.js +1 -1
  251. package/dist/src/session-store.js +1 -1
  252. package/dist/src/session.js +1 -1
  253. package/dist/src/session2.js +4 -4
  254. package/dist/src/settings.js +1 -1
  255. package/dist/src/settings2.js +1 -0
  256. package/dist/src/simctl.js +1 -1
  257. package/dist/src/simulator-state.js +1 -1
  258. package/dist/src/simulator.js +1 -1
  259. package/dist/src/snapshot-capture-annotations.js +1 -1
  260. package/dist/src/snapshot-desktop-projection.js +1 -1
  261. package/dist/src/snapshot-runtime-binding.js +1 -1
  262. package/dist/src/snapshot-runtime.js +1 -1
  263. package/dist/src/snapshot-state.js +1 -1
  264. package/dist/src/snapshot2.js +1 -1
  265. package/dist/src/snapshot3.js +1 -1
  266. package/dist/src/snapshot4.js +1 -1
  267. package/dist/src/src.js +1 -1
  268. package/dist/src/src4.js +1 -1
  269. package/dist/src/src7.js +1 -1
  270. package/dist/src/src8.js +1 -1
  271. package/dist/src/string-enum.js +1 -1
  272. package/dist/src/surface-snapshot.js +1 -1
  273. package/dist/src/takeover.js +1 -1
  274. package/dist/src/text-entry-focus.js +1 -1
  275. package/dist/src/tool-provider-facade.js +1 -1
  276. package/dist/src/tool-provider.js +2 -2
  277. package/dist/src/tool-provider2.js +1 -1
  278. package/dist/src/touch-runtime.js +1 -1
  279. package/dist/src/transport.js +1 -1
  280. package/dist/src/tree.js +1 -1
  281. package/dist/src/tv-remote.js +1 -1
  282. package/dist/src/type-text-runtime.js +1 -1
  283. package/dist/src/verified-file.js +1 -1
  284. package/dist/src/video.js +1 -1
  285. package/dist/src/viewport.js +1 -1
  286. package/dist/src/web.js +1 -1
  287. package/dist/src/web2.js +1 -1
  288. package/dist/src/webdriver-source.js +1 -1
  289. package/package.json +1 -1
  290. package/server.json +2 -2
  291. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.13.apk.sha256 +0 -1
  292. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.13.apk +0 -0
  293. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.13.apk.sha256 +0 -1
  294. package/dist/src/absence-observation-errors.js +0 -1
  295. package/dist/src/runner-presentation.js +0 -1
  296. package/dist/src/semantic-index.js +0 -1
  297. package/dist/src/snapshot-process.js +0 -1
  298. package/dist/src/snapshot-scope.js +0 -1
@@ -27,6 +27,7 @@ extension RunnerTests {
27
27
  )
28
28
  }
29
29
 
30
+ @MainActor
30
31
  func executeScrollDragGesture(
31
32
  activeApp: XCUIApplication,
32
33
  x: Double,
@@ -65,6 +66,7 @@ extension RunnerTests {
65
66
 
66
67
 
67
68
 
69
+ @MainActor
68
70
  func executeDragGesture(
69
71
  activeApp: XCUIApplication,
70
72
  x: Double,
@@ -125,6 +127,7 @@ extension RunnerTests {
125
127
  return gestureResponse(message: message, timing: timing, frame: .drag(dragFrame))
126
128
  }
127
129
 
130
+ @MainActor
128
131
  private func executeSynthesizedDragGesture(
129
132
  activeApp: XCUIApplication,
130
133
  x: Double,
@@ -149,19 +152,6 @@ extension RunnerTests {
149
152
  context: context
150
153
  )
151
154
  else {
152
- if context?.allowsXCTestCoordinateFallback == true {
153
- logSynthesizedGesturePolicyDecision(kind: policyKind, context: context, fallbackAttempted: true)
154
- return executeCoordinateDragFallback(
155
- activeApp: activeApp,
156
- x: x,
157
- y: y,
158
- x2: x2,
159
- y2: y2,
160
- durationMs: durationMs,
161
- message: message,
162
- fallback: nil
163
- )
164
- }
165
155
  logSynthesizedGesturePolicyDecision(kind: policyKind, context: context, fallbackAttempted: false)
166
156
  return Response(
167
157
  ok: false,
@@ -179,7 +169,7 @@ extension RunnerTests {
179
169
  y2: plan.points.y2,
180
170
  referenceFrame: plan.referenceFrame
181
171
  )
182
- let (timing, outcome) = performGesture(activeApp, idleTimeout: false) {
172
+ switch performSynthesizedGesture(activeApp, kind: policyKind, context: plan.context, synthesize: {
183
173
  synthesizedDragAt(
184
174
  app: activeApp,
185
175
  x: plan.points.x,
@@ -190,13 +180,10 @@ extension RunnerTests {
190
180
  profile: profile,
191
181
  context: plan.context
192
182
  )
193
- }
194
- if case .performed = outcome {
195
- logSynthesizedGesturePolicyDecision(kind: policyKind, context: plan.context, fallbackAttempted: false)
183
+ }) {
184
+ case .performed(let timing):
196
185
  return gestureResponse(message: message, timing: timing, frame: .drag(dragFrame))
197
- }
198
- if plan.context.allowsXCTestCoordinateFallback {
199
- logSynthesizedGesturePolicyDecision(kind: policyKind, context: plan.context, fallbackAttempted: true)
186
+ case .xctestFallback(let fallbackMessage, let hint):
200
187
  return executeCoordinateDragFallback(
201
188
  activeApp: activeApp,
202
189
  x: plan.points.x,
@@ -205,16 +192,17 @@ extension RunnerTests {
205
192
  y2: plan.points.y2,
206
193
  durationMs: durationMs,
207
194
  message: message,
208
- fallback: gestureFallback(strategy: "xctest-coordinate-drag", from: outcome)
195
+ fallback: GestureFallback(strategy: "xctest-coordinate-drag", message: fallbackMessage, hint: hint)
209
196
  )
197
+ case .refused(_, let refusalMessage, let hint):
198
+ return unsupportedResponse(message: refusalMessage, hint: hint)
210
199
  }
211
- logSynthesizedGesturePolicyDecision(kind: policyKind, context: plan.context, fallbackAttempted: false)
212
- return unsupportedResponse(for: outcome)
213
200
  #else
214
201
  return nil
215
202
  #endif
216
203
  }
217
204
 
205
+ @MainActor
218
206
  private func executeCoordinateDragFallback(
219
207
  activeApp: XCUIApplication,
220
208
  x: Double,
@@ -223,7 +211,7 @@ extension RunnerTests {
223
211
  y2: Double,
224
212
  durationMs: Double,
225
213
  message: String,
226
- fallback: GestureFallback?
214
+ fallback: GestureFallback
227
215
  ) -> Response {
228
216
  let dragPoints = keyboardAvoidingDragPoints(app: activeApp, x: x, y: y, x2: x2, y2: y2)
229
217
  let dragFrame = resolvedDragVisualizationFrame(
@@ -19,6 +19,7 @@ extension RunnerTests {
19
19
  let gestureEndUptimeMs: Double
20
20
  }
21
21
 
22
+ @MainActor
22
23
  func executeSequence(command: Command, activeApp: XCUIApplication) -> Response {
23
24
  guard let steps = command.steps, !steps.isEmpty else {
24
25
  return sequenceInvalidArgs("sequence requires at least one step")
@@ -136,6 +137,7 @@ extension RunnerTests {
136
137
  return nil
137
138
  }
138
139
 
140
+ @MainActor
139
141
  private func performSequenceStep(
140
142
  _ step: SequenceStep,
141
143
  activeApp: XCUIApplication,
@@ -143,51 +145,21 @@ extension RunnerTests {
143
145
  ) -> SequenceStepOutcome {
144
146
  let x = step.x ?? 0
145
147
  let y = step.y ?? 0
146
-
147
-
148
-
149
- if step.kind == "tap", step.synthesized == true {
150
- let policyKind = SynthesizedGesturePolicyKind.synthesizedDrag
151
- #if os(iOS)
152
- guard let synthesizedContext else {
153
- let nowMs = ProcessInfo.processInfo.systemUptime * 1000
154
- logSynthesizedGesturePolicyDecision(kind: policyKind, context: nil, fallbackAttempted: false)
155
- return SequenceStepOutcome(
156
- outcome: .unsupported(
157
- message: "synthesized coordinate tap could not resolve a finite coordinate frame",
158
- hint: "Retry after the app is foregrounded, or use a plain screenshot to choose coordinates."
159
- ),
160
- gestureStartUptimeMs: nowMs,
161
- gestureEndUptimeMs: nowMs
162
- )
163
- }
164
- #endif
165
- let (timing, outcome) = performGesture(activeApp, idleTimeout: false) {
148
+ if let policyKind = synthesizedPolicyKind(forSequenceStep: step) {
149
+ switch performSynthesizedGesture(activeApp, kind: policyKind, context: synthesizedContext, synthesize: {
166
150
  synthesizedTapAt(app: activeApp, x: x, y: y, context: synthesizedContext)
167
- }
168
- if case .performed = outcome {
169
- logSynthesizedGesturePolicyDecision(kind: policyKind, context: synthesizedContext, fallbackAttempted: false)
170
- if let pauseMs = step.pauseMs, pauseMs > 0 {
171
- sleepFor(min(max(pauseMs, 0), 10000) / 1000.0)
172
- }
173
- return SequenceStepOutcome(
174
- outcome: outcome,
175
- gestureStartUptimeMs: timing.gestureStartUptimeMs,
176
- gestureEndUptimeMs: timing.gestureEndUptimeMs
151
+ }) {
152
+ case .performed(let timing):
153
+ return finishedSequenceStep(step, timing: timing, outcome: .performed)
154
+ case .refused(let timing, let message, let hint):
155
+ return finishedSequenceStep(
156
+ step,
157
+ timing: timing,
158
+ outcome: .unsupported(message: message, hint: hint)
177
159
  )
160
+ case .xctestFallback:
161
+ break
178
162
  }
179
- #if os(iOS)
180
- guard synthesizedContext.allowsXCTestCoordinateFallback else {
181
- logSynthesizedGesturePolicyDecision(kind: policyKind, context: synthesizedContext, fallbackAttempted: false)
182
- return SequenceStepOutcome(
183
- outcome: outcome,
184
- gestureStartUptimeMs: timing.gestureStartUptimeMs,
185
- gestureEndUptimeMs: timing.gestureEndUptimeMs
186
- )
187
- }
188
- logSynthesizedGesturePolicyDecision(kind: policyKind, context: synthesizedContext, fallbackAttempted: true)
189
- #endif
190
-
191
163
  }
192
164
  let (timing, outcome) = performGesture(activeApp) {
193
165
  switch step.kind {
@@ -201,6 +173,14 @@ extension RunnerTests {
201
173
  return tapAt(app: activeApp, x: x, y: y)
202
174
  }
203
175
  }
176
+ return finishedSequenceStep(step, timing: timing, outcome: outcome)
177
+ }
178
+
179
+ private func finishedSequenceStep(
180
+ _ step: SequenceStep,
181
+ timing: (gestureStartUptimeMs: Double, gestureEndUptimeMs: Double),
182
+ outcome: RunnerInteractionOutcome
183
+ ) -> SequenceStepOutcome {
204
184
 
205
185
 
206
186
 
@@ -21,9 +21,8 @@ extension RunnerTests {
21
21
  struct SnapshotTraversalContext {
22
22
  let queryRoot: XCUIElement
23
23
  let rootSnapshot: XCUIElementSnapshot
24
- let viewport: CGRect
25
24
 
26
- let interfaceOrientation: Int
25
+ let viewport: SnapshotViewport
27
26
 
28
27
 
29
28
 
@@ -36,6 +35,7 @@ extension RunnerTests {
36
35
  let label: String
37
36
  let identifier: String
38
37
  let valueText: String?
38
+ let placeholder: String?
39
39
  let focused: Bool
40
40
  let selected: Bool
41
41
  }
@@ -176,6 +176,7 @@ extension RunnerTests {
176
176
  )
177
177
  }
178
178
 
179
+ @MainActor
179
180
  func recursiveTreeSnapshotAcquisition(
180
181
  context: SnapshotTraversalContext,
181
182
  hint: CaptureHint
@@ -278,8 +279,7 @@ extension RunnerTests {
278
279
  nodes: nodes,
279
280
  truncated: false,
280
281
  effectiveDepth: nil,
281
- viewport: context.viewport,
282
- interfaceOrientation: context.interfaceOrientation
282
+ viewport: context.viewport
283
283
  )
284
284
  }
285
285
 
@@ -329,7 +329,7 @@ extension RunnerTests {
329
329
  private func boundedBlockingSystemAlertSnapshotBody(
330
330
  deadline: Date,
331
331
  penaltyTarget: SnapshotProbePenaltyTarget,
332
- probe: @escaping (Date) -> DataPayload?
332
+ probe: @escaping @MainActor (Date) -> DataPayload?
333
333
  ) -> DataPayload? {
334
334
  #if os(macOS)
335
335
  return nil
@@ -363,7 +363,7 @@ extension RunnerTests {
363
363
  )
364
364
  }
365
365
  ) {
366
- penaltyIdentity.captureFromMain(bundleId: self.currentBundleId)
366
+ penaltyIdentity.captureFromMain(bundleId: self.mainOwned.bundleId)
367
367
  return probe(probeDeadline)
368
368
  }
369
369
  } catch {
@@ -435,11 +435,11 @@ extension RunnerTests {
435
435
  nodes: nodes,
436
436
  truncated: false,
437
437
  effectiveDepth: nil,
438
- viewport: context.viewport,
439
- interfaceOrientation: context.interfaceOrientation
438
+ viewport: context.viewport
440
439
  )
441
440
  }
442
441
 
442
+ @MainActor
443
443
  func querySweepSnapshotAcquisition(
444
444
  app: XCUIApplication,
445
445
  hint: CaptureHint,
@@ -455,14 +455,13 @@ extension RunnerTests {
455
455
  nodes: nodes,
456
456
  truncated: false,
457
457
  effectiveDepth: nil,
458
- viewport: .infinite,
459
- interfaceOrientation: RunnerInterfaceOrientation.unknown
458
+ viewport: .missing(reason: .notProvided)
460
459
  ),
461
460
  .completed
462
461
  )
463
462
  }
464
463
 
465
- let viewport = safeSnapshotViewport(app: app)
464
+ let viewport = safeSnapshotViewport(app: app, readingOrientation: false)
466
465
  var seen = Set<String>()
467
466
  var candidates: [RawAXNode] = []
468
467
  let flatElements = flatInteractiveElements(app: app, deadline: deadline)
@@ -494,9 +493,7 @@ extension RunnerTests {
494
493
 
495
494
 
496
495
 
497
- let rootRect = viewport.isInfinite || viewport.isNull || viewport.isEmpty
498
- ? interactiveRootFrame(for: candidates)
499
- : viewport
496
+ let rootRect = viewport.rect ?? interactiveRootFrame(for: candidates)
500
497
  nodes[0] = interactiveRootNode(rect: rootRect)
501
498
  for candidate in candidates {
502
499
  nodes.append(
@@ -506,6 +503,7 @@ extension RunnerTests {
506
503
  label: candidate.label,
507
504
  identifier: candidate.identifier,
508
505
  value: candidate.value,
506
+ placeholder: candidate.placeholder,
509
507
  rect: candidate.rect,
510
508
  enabled: candidate.enabled,
511
509
  focused: candidate.focused,
@@ -524,8 +522,7 @@ extension RunnerTests {
524
522
  nodes: nodes,
525
523
  truncated: outcome == .deadlineExhausted,
526
524
  effectiveDepth: nil,
527
- viewport: viewport,
528
- interfaceOrientation: RunnerInterfaceOrientation.unknown
525
+ viewport: viewport
529
526
  ),
530
527
  outcome
531
528
  )
@@ -534,7 +531,7 @@ extension RunnerTests {
534
531
  func snapshotAccessibilityUnavailable(failure: SnapshotCaptureFailure) -> DataPayload {
535
532
  NSLog("AGENT_DEVICE_RUNNER_SNAPSHOT_AX_UNAVAILABLE=%@", failure.message)
536
533
  applyMainOwnedSnapshotState("ax_unavailable_invalidation") {
537
- self.runnerAccessibilityHealth = .unavailable
534
+ self.mainOwned.accessibilityHealth = .unavailable
538
535
  self.invalidateCachedTarget(reason: Self.axSnapshotUnavailableReason)
539
536
  }
540
537
 
@@ -542,7 +539,7 @@ extension RunnerTests {
542
539
  return sparseTruncatedSnapshotPayload(
543
540
  message: recoveredSnapshotMessage(failure),
544
541
  snapshotQuality: SnapshotQuality(
545
- state: "sparse",
542
+ state: .sparse,
546
543
  backend: SnapshotBackendKind.recursiveTree.rawValue,
547
544
  reason: failure.message,
548
545
  reasonCode: "ax-rejected",
@@ -38,27 +38,22 @@ extension RunnerTests {
38
38
  captureDeadline: Date = .distantFuture,
39
39
  treeCaptureSliceBudgetOverride: TimeInterval? = nil
40
40
  ) throws -> SnapshotTraversalContext? {
41
+ let treeSliceBudget = treeCaptureSliceBudgetOverride ?? treeCaptureSliceBudget
42
+ let slice = min(treeSliceBudget, max(0.5, captureDeadline.timeIntervalSinceNow))
43
+ guard let rootSnapshot = try captureSnapshotRootBounded(app, sliceSeconds: slice) else {
44
+ return nil
45
+ }
46
+
41
47
 
42
48
 
43
49
 
44
- let geometry = try runMainThreadWork(
50
+ let viewport = try runMainThreadWork(
45
51
  "snapshot_viewport",
46
52
  timeout: min(1.0, max(0.1, captureDeadline.timeIntervalSinceNow)),
47
- timeoutError: snapshotMainThreadTimeoutError("preparing tree snapshot")
53
+ timeoutError: snapshotMainThreadTimeoutError("reading snapshot viewport")
48
54
  ) {
49
- (
50
- viewport: self.safeSnapshotViewport(app: app),
51
- interfaceOrientation: self.capturedInterfaceOrientation(app: app)
52
- )
55
+ self.safeSnapshotViewport(app: app, readingOrientation: true)
53
56
  }
54
- let viewport = geometry.viewport
55
- let interfaceOrientation = geometry.interfaceOrientation
56
- let treeSliceBudget = treeCaptureSliceBudgetOverride ?? treeCaptureSliceBudget
57
- let slice = min(treeSliceBudget, max(0.5, captureDeadline.timeIntervalSinceNow))
58
- guard let rootSnapshot = try captureSnapshotRootBounded(app, sliceSeconds: slice) else {
59
- return nil
60
- }
61
-
62
57
 
63
58
 
64
59
 
@@ -70,7 +65,6 @@ extension RunnerTests {
70
65
  queryRoot: app,
71
66
  rootSnapshot: rootSnapshot,
72
67
  viewport: viewport,
73
- interfaceOrientation: interfaceOrientation,
74
68
  keyboardBand: keyboardBand
75
69
  )
76
70
  }
@@ -99,7 +93,7 @@ extension RunnerTests {
99
93
  }
100
94
  }
101
95
 
102
- private func treeCaptureTimeoutError(sliceSeconds: TimeInterval) -> () -> Error {
96
+ private func treeCaptureTimeoutError(sliceSeconds: TimeInterval) -> @Sendable () -> Error {
103
97
  {
104
98
  SnapshotCaptureFailure(
105
99
  code: Self.xCTestSnapshotTimeoutCode,
@@ -109,7 +103,7 @@ extension RunnerTests {
109
103
  }
110
104
  }
111
105
 
112
- func snapshotMainThreadTimeoutError(_ operation: String) -> () -> Error {
106
+ func snapshotMainThreadTimeoutError(_ operation: String) -> @Sendable () -> Error {
113
107
  {
114
108
  SnapshotCaptureFailure(
115
109
  code: Self.xCTestSnapshotTimeoutCode,
@@ -140,8 +134,18 @@ extension RunnerTests {
140
134
  return nil
141
135
  }
142
136
 
143
- func safeSnapshotViewport(app: XCUIApplication) -> CGRect {
144
- safely("SNAPSHOT_VIEWPORT", CGRect.infinite) { snapshotViewport(app: app) }
137
+
138
+
139
+
140
+ func safeSnapshotViewport(app: XCUIApplication, readingOrientation: Bool) -> SnapshotViewport {
141
+ safely("SNAPSHOT_VIEWPORT", .missing(reason: .notProvided)) {
142
+ .reported(
143
+ box: snapshotAppFrame(app: app),
144
+ interfaceOrientation: readingOrientation
145
+ ? capturedInterfaceOrientation(app: app)
146
+ : RunnerInterfaceOrientation.unknown
147
+ )
148
+ }
145
149
  }
146
150
 
147
151
  private func describeSnapshotError(_ error: Error) -> String {
@@ -185,6 +189,7 @@ extension RunnerTests {
185
189
  label: label,
186
190
  identifier: identifier,
187
191
  valueText: valueText,
192
+ placeholder: placeholderText(snapshot.placeholderValue),
188
193
  focused: snapshotHasFocus(snapshot),
189
194
  selected: snapshotIsSelected(snapshot)
190
195
  )
@@ -205,6 +210,7 @@ extension RunnerTests {
205
210
  label: evaluation.label.isEmpty ? nil : evaluation.label,
206
211
  identifier: evaluation.identifier.isEmpty ? nil : evaluation.identifier,
207
212
  value: evaluation.valueText,
213
+ placeholder: evaluation.placeholder,
208
214
  rect: SnapshotRect(snapshot.frame),
209
215
  enabled: snapshot.isEnabled,
210
216
  focused: evaluation.focused ? true : nil,
@@ -231,16 +237,32 @@ extension RunnerTests {
231
237
  return text.isEmpty ? nil : text
232
238
  }
233
239
 
234
- private func snapshotViewport(app: XCUIApplication) -> CGRect {
240
+
241
+
242
+
243
+ func placeholderText(_ placeholderValue: String?) -> String? {
244
+ let text = placeholderValue?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
245
+ return text.isEmpty ? nil : text
246
+ }
247
+
248
+
249
+
250
+
251
+ static let placeholderElementTypes: Set<XCUIElement.ElementType> = [
252
+ .textField, .secureTextField, .searchField, .textView,
253
+ ]
254
+
255
+ func elementPlaceholderText(_ element: XCUIElement, type: XCUIElement.ElementType) -> String? {
256
+ guard Self.placeholderElementTypes.contains(type) else { return nil }
257
+ return placeholderText(element.placeholderValue)
258
+ }
259
+
260
+ private func snapshotAppFrame(app: XCUIApplication) -> CGRect {
235
261
  #if os(iOS)
236
- let appFrame = onScreenWindowFrame(app: app)
262
+ return onScreenWindowFrame(app: app)
237
263
  #else
238
- let appFrame = app.frame
264
+ return app.frame
239
265
  #endif
240
- if !appFrame.isNull && !appFrame.isEmpty {
241
- return appFrame
242
- }
243
- return .infinite
244
266
  }
245
267
 
246
268
  static func snapshotTraversalIdentity(
@@ -341,6 +363,7 @@ extension RunnerTests {
341
363
  label: node.label,
342
364
  identifier: node.identifier,
343
365
  value: node.value,
366
+ placeholder: node.placeholder,
344
367
  rect: node.rect,
345
368
  enabled: node.enabled,
346
369
  focused: node.focused,
@@ -376,7 +399,8 @@ extension RunnerTests {
376
399
  let label = element.label.trimmingCharacters(in: .whitespacesAndNewlines)
377
400
  let identifier = element.identifier.trimmingCharacters(in: .whitespacesAndNewlines)
378
401
  let valueText = snapshotValueText(element)
379
- let hasContent = !label.isEmpty || !identifier.isEmpty || valueText != nil
402
+ let placeholder = elementPlaceholderText(element, type: elementType)
403
+ let hasContent = !label.isEmpty || !identifier.isEmpty || valueText != nil || placeholder != nil
380
404
  if !hasContent { return }
381
405
  if sameSemanticElement(
382
406
  containerSnapshot: containerSnapshot,
@@ -395,6 +419,7 @@ extension RunnerTests {
395
419
  label: label.isEmpty ? nil : label,
396
420
  identifier: identifier.isEmpty ? nil : identifier,
397
421
  value: valueText,
422
+ placeholder: placeholder,
398
423
  rect: SnapshotRect(frame),
399
424
  enabled: element.isEnabled,
400
425
  focused: elementHasFocus(element) ? true : nil,
@@ -417,13 +442,27 @@ extension RunnerTests {
417
442
  }
418
443
 
419
444
  private func snapshotHasFocus(_ snapshot: XCUIElementSnapshot) -> Bool {
420
- var focused = false
445
+ return focusBool(snapshot as! NSObject)
446
+ }
447
+
448
+
449
+
450
+
451
+
452
+
453
+
454
+ func focusBool(_ object: NSObject) -> Bool {
455
+ return kvcBool(object, forKey: "hasKeyboardFocus") || kvcBool(object, forKey: "hasFocus")
456
+ }
457
+
458
+ private func kvcBool(_ object: NSObject, forKey key: String) -> Bool {
459
+ var result = false
421
460
  _ = RunnerObjCExceptionCatcher.catchException({
422
- if let value = (snapshot as! NSObject).value(forKey: "hasFocus") as? Bool {
423
- focused = value
461
+ if let value = object.value(forKey: key) as? Bool {
462
+ result = value
424
463
  }
425
464
  })
426
- return focused
465
+ return result
427
466
  }
428
467
 
429
468
  private func snapshotIsSelected(_ snapshot: XCUIElementSnapshot) -> Bool {
@@ -461,6 +500,7 @@ extension RunnerTests {
461
500
  return containerLabel == label && containerIdentifier == identifier
462
501
  }
463
502
 
503
+ @MainActor
464
504
  func flatInteractiveElements(
465
505
  app: XCUIApplication,
466
506
  deadline: Date
@@ -519,6 +559,7 @@ extension RunnerTests {
519
559
  return (elements, .completed)
520
560
  }
521
561
 
562
+ @MainActor
522
563
  func snapshotElementsQuery(
523
564
  _ fetch: () -> [XCUIElement]
524
565
  ) -> (elements: [XCUIElement], axUnavailable: Bool) {
@@ -558,6 +599,7 @@ extension RunnerTests {
558
599
  label: label.isEmpty ? nil : label,
559
600
  identifier: identifier.isEmpty ? nil : identifier,
560
601
  value: valueText,
602
+ placeholder: elementPlaceholderText(element, type: elementType),
561
603
  rect: SnapshotRect(frame),
562
604
  enabled: enabled,
563
605
  focused: elementHasFocus(element) ? true : nil,
@@ -9,10 +9,20 @@ import AgentDeviceSnapshotPresentation
9
9
 
10
10
 
11
11
 
12
- struct SnapshotQuality: Codable {
13
12
 
14
13
 
15
- let state: String
14
+ enum SnapshotQualityState: String, Codable, CaseIterable {
15
+
16
+ case healthy
17
+
18
+ case recovered
19
+
20
+ case sparse
21
+ }
22
+
23
+
24
+ struct SnapshotQuality: Codable {
25
+ let state: SnapshotQualityState
16
26
 
17
27
  let backend: String
18
28
 
@@ -391,7 +401,7 @@ extension RunnerTests {
391
401
  return stampedSnapshotPayload(
392
402
  capture,
393
403
  backend: kind,
394
- state: recovered ? "recovered" : "healthy",
404
+ state: recovered ? .recovered : .healthy,
395
405
  reason: recovered || firstFailure?.code == "requested-backend" ? firstFailure : nil
396
406
  )
397
407
  }
@@ -416,11 +426,11 @@ extension RunnerTests {
416
426
  }
417
427
 
418
428
  let fallbackPayload =
419
- best.map { stampedSnapshotPayload($0.capture, backend: $0.kind, state: "sparse", reason: firstFailure) }
429
+ best.map { stampedSnapshotPayload($0.capture, backend: $0.kind, state: .sparse, reason: firstFailure) }
420
430
  ?? stampedSnapshotPayload(
421
431
  SnapshotBackendCapture(payload: sparseTruncatedSnapshotPayload(), effectiveDepth: nil),
422
432
  backend: effectivePlan.last ?? plan.last ?? .recursiveTree,
423
- state: "sparse",
433
+ state: .sparse,
424
434
  reason: firstFailure
425
435
  )
426
436
  return fallbackPayload
@@ -513,8 +523,7 @@ extension RunnerTests {
513
523
  let normalizedAcquisition = acquisition.replacingNodes(
514
524
  SnapshotGeometrySpace.normalized(
515
525
  nodes: acquisition.nodes,
516
- viewport: acquisition.viewport,
517
- interfaceOrientation: acquisition.interfaceOrientation
526
+ viewport: acquisition.viewport
518
527
  )
519
528
  )
520
529
 
@@ -641,7 +650,7 @@ extension RunnerTests {
641
650
  guard Self.structuralOnlyNodeTypes.contains(node.type) else { return false }
642
651
  guard !isRootContainer else { return true }
643
652
 
644
- let isFullScreenContainer = !node.hittable && rootRects.contains { rootRect in
653
+ let isFullScreenContainer = node.hittable != true && rootRects.contains { rootRect in
645
654
  rootRect.x == node.rect.x && rootRect.y == node.rect.y
646
655
  && rootRect.width == node.rect.width && rootRect.height == node.rect.height
647
656
  }
@@ -680,12 +689,12 @@ extension RunnerTests {
680
689
  func stampedSnapshotPayload(
681
690
  _ capture: SnapshotBackendCapture,
682
691
  backend: SnapshotBackendKind,
683
- state: String,
692
+ state: SnapshotQualityState,
684
693
  reason: (reason: String, code: String)?
685
694
  ) -> DataPayload {
686
695
  let health: RunnerAccessibilityHealth = reason?.code == "ax-rejected" ? .unavailable : .healthy
687
696
  applyMainOwnedSnapshotState("accessibility_health") {
688
- self.runnerAccessibilityHealth = health
697
+ self.mainOwned.accessibilityHealth = health
689
698
  }
690
699
  let payload = capture.payload
691
700
  let quality = SnapshotQuality(
@@ -705,7 +714,7 @@ extension RunnerTests {
705
714
 
706
715
 
707
716
 
708
- truncated: payload.truncated == true || state == "sparse" || capture.effectiveDepth != nil,
717
+ truncated: payload.truncated == true || state == .sparse || capture.effectiveDepth != nil,
709
718
  qualityPayload: capture.qualityPayload.flatMap { quality in
710
719
  guard let nodes = quality.nodes else { return nil }
711
720
  return SnapshotQualityPayload(nodes: nodes, truncated: quality.truncated == true)
@@ -8,7 +8,6 @@ import XCTest
8
8
 
9
9
 
10
10
 
11
-
12
11
  struct SnapshotCaptureTarget {
13
12
  let app: XCUIApplication
14
13
  let bundleId: String?
@@ -67,32 +66,35 @@ final class SnapshotProbePenaltyIdentity {
67
66
 
68
67
  extension RunnerTests {
69
68
 
69
+ @MainActor
70
70
  func takeSnapshotCaptureTarget(app: XCUIApplication) -> SnapshotCaptureTarget {
71
71
  SnapshotCaptureTarget(
72
72
  app: app,
73
- bundleId: currentBundleId,
74
- processIdentifier: currentAppProcessIdentifier
73
+ bundleId: mainOwned.bundleId,
74
+ processIdentifier: mainOwned.processIdentifier
75
75
  )
76
76
  }
77
77
 
78
78
 
79
79
 
80
80
 
81
- func applyMainOwnedSnapshotState(_ operation: String, _ write: @escaping () -> Void) {
81
+ func applyMainOwnedSnapshotState(_ operation: String, _ write: @escaping @MainActor () -> Void) {
82
82
  if Thread.isMainThread {
83
- write()
83
+ _ = runOnMainActor(write)
84
84
  return
85
85
  }
86
86
  guard !hasAbandonedMainThreadWork() else {
87
87
  NSLog("AGENT_DEVICE_RUNNER_SNAPSHOT_STATE_DEFERRED_XCTEST_OCCUPIED operation=%@", operation)
88
- DispatchQueue.main.async(execute: write)
88
+ DispatchQueue.main.async {
89
+ _ = runOnMainActor(write)
90
+ }
89
91
  return
90
92
  }
91
93
  do {
92
94
  try runMainThreadWork(
93
95
  operation,
94
96
  timeout: 1,
95
- timeoutError: mainThreadExecutionTimeoutError,
97
+ timeoutError: Self.mainThreadExecutionTimeoutError,
96
98
  write
97
99
  )
98
100
  } catch {