agent-device 0.21.11 → 0.21.13

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 (201) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.11.apk → agent-device-android-ime-helper-0.21.13.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.13.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.11.manifest.json → agent-device-android-ime-helper-0.21.13.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.11.apk → agent-device-android-snapshot-helper-0.21.13.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.13.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.11.manifest.json → agent-device-android-snapshot-helper-0.21.13.manifest.json} +6 -6
  7. package/apple/fold-helper/Fold.m +97 -0
  8. package/apple/macos-helper/Package.swift +3 -6
  9. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +3 -8
  10. package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/ScreenshotResponseTests.swift +15 -0
  11. package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +47 -1
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +99 -42
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/Info.plist +23 -0
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +17 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAppScreenCapture.swift +21 -13
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerScrollViewportPolicy.swift +1 -162
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +0 -9
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +0 -56
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +0 -48
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +0 -50
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +22 -568
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +21 -9
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+BlockingSystemModalResolution.swift +0 -36
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +630 -0
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +18 -2236
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -338
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +0 -12
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+GestureExecution.swift +165 -0
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +0 -24
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +0 -142
  31. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +90 -39
  32. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+MainThreadWork.swift +78 -106
  33. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +23 -2
  34. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +147 -95
  35. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +0 -209
  36. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +86 -10
  37. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollDragExecution.swift +287 -0
  38. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +1 -200
  39. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +0 -185
  40. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +75 -285
  41. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +23 -10
  42. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +0 -78
  43. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +83 -578
  44. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +106 -0
  45. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +142 -0
  46. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +49 -78
  47. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +0 -44
  48. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +27 -97
  49. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +1 -11
  50. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +11 -87
  51. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +2 -10
  52. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +1 -1
  53. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +0 -35
  54. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +0 -31
  55. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +2 -18
  56. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +34 -52
  57. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +0 -22
  58. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +142 -0
  59. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +22 -6
  60. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +140 -20
  61. package/dist/src/absence-observation-errors.js +1 -1
  62. package/dist/src/adapter.js +1 -1
  63. package/dist/src/agent-device-client.js +1 -1
  64. package/dist/src/alert-runtime.js +1 -1
  65. package/dist/src/android-adb.d.ts +1 -1
  66. package/dist/src/app-launch.js +2 -2
  67. package/dist/src/app-log-runtime2.js +3 -3
  68. package/dist/src/app-resolution.js +2 -2
  69. package/dist/src/back-mode.js +1 -1
  70. package/dist/src/capture-disclosure.js +1 -1
  71. package/dist/src/capture.js +1 -1
  72. package/dist/src/cli-config.js +1 -1
  73. package/dist/src/cli-help.js +10 -7
  74. package/dist/src/cli-runner.js +1 -1
  75. package/dist/src/cli.js +1 -1
  76. package/dist/src/client-types.d.ts +5 -8
  77. package/dist/src/code-signature.js +1 -1
  78. package/dist/src/command-schema.js +3 -3
  79. package/dist/src/command-tools.js +3 -3
  80. package/dist/src/connection.js +1 -1
  81. package/dist/src/daemon-client-lifecycle.js +1 -1
  82. package/dist/src/daemon-resolution.js +1 -1
  83. package/dist/src/device-claim-rule.js +2 -2
  84. package/dist/src/device-input-state.d.ts +1 -1
  85. package/dist/src/device-rotation.js +1 -1
  86. package/dist/src/device-session.js +1 -1
  87. package/dist/src/devicectl.js +1 -1
  88. package/dist/src/display-inventory.js +1 -1
  89. package/dist/src/doctor-facade.js +1 -1
  90. package/dist/src/find.js +1 -1
  91. package/dist/src/gesture-plan-types.d.ts +38 -0
  92. package/dist/src/harmonyos.js +1 -1
  93. package/dist/src/helper.js +2 -2
  94. package/dist/src/host.js +1 -1
  95. package/dist/src/install-source-network-transport.js +1 -1
  96. package/dist/src/install-source2.js +1 -1
  97. package/dist/src/interaction-ref-policy.js +1 -1
  98. package/dist/src/interaction2.js +1 -1
  99. package/dist/src/interactor-operation-catalog.js +1 -1
  100. package/dist/src/interactor.js +4 -4
  101. package/dist/src/interactor2.js +1 -1
  102. package/dist/src/internal/bin.js +1 -1
  103. package/dist/src/internal/daemon.js +2 -2
  104. package/dist/src/inventory2.js +1 -1
  105. package/dist/src/ios-snapshot-acquisition.js +1 -1
  106. package/dist/src/ios-snapshot-runtime.js +1 -1
  107. package/dist/src/limrun-runtime-dependencies.js +1 -1
  108. package/dist/src/limrun.d.ts +435 -4
  109. package/dist/src/linux.js +1 -1
  110. package/dist/src/local-interactor-operation-set.js +1 -1
  111. package/dist/src/macos-facade.js +1 -1
  112. package/dist/src/managed-device-scope.js +1 -1
  113. package/dist/src/mechanics.js +4 -4
  114. package/dist/src/mobile-snapshot-semantics.js +1 -1
  115. package/dist/src/perf-facade.js +1 -2
  116. package/dist/src/perf-runtime-plan.js +1 -1
  117. package/dist/src/perf-target.js +2 -0
  118. package/dist/src/physical-device-apps.js +1 -0
  119. package/dist/src/physical-device-control.js +1 -1
  120. package/dist/src/platform-request-scope.js +1 -1
  121. package/dist/src/platform-runtime-operation-host.js +1 -1
  122. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  123. package/dist/src/platform-runtime-unavailable.js +1 -1
  124. package/dist/src/platform-runtime.js +1 -1
  125. package/dist/src/platform-runtime2.js +1 -1
  126. package/dist/src/provider-webdriver.js +1 -1
  127. package/dist/src/proxy.js +1 -1
  128. package/dist/src/quality-warnings.js +1 -1
  129. package/dist/src/react-native.js +1 -1
  130. package/dist/src/record-runtime.js +1 -1
  131. package/dist/src/registry.js +35 -35
  132. package/dist/src/request-admission.js +1 -1
  133. package/dist/src/request-runtime-binding.js +1 -1
  134. package/dist/src/runner-client.js +1 -1
  135. package/dist/src/runner-dev-tools-security.js +1 -1
  136. package/dist/src/runner-device-readiness.js +1 -1
  137. package/dist/src/runner-disposal.js +1 -1
  138. package/dist/src/runner-error-classification.js +3 -0
  139. package/dist/src/runner-operations-facade.js +1 -1
  140. package/dist/src/runner-presentation.js +1 -1
  141. package/dist/src/runner.js +1 -1
  142. package/dist/src/runtime.js +3 -3
  143. package/dist/src/runtime10.js +1 -1
  144. package/dist/src/runtime2.js +2 -2
  145. package/dist/src/runtime4.js +5 -5
  146. package/dist/src/runtime5.js +1 -1
  147. package/dist/src/runtime6.js +1 -1
  148. package/dist/src/runtime7.js +1 -1
  149. package/dist/src/runtime8.js +1 -1
  150. package/dist/src/runtime9.js +1 -1
  151. package/dist/src/screen-recording-admission-ledger.js +1 -1
  152. package/dist/src/screen-recording-resource-recovery.js +1 -1
  153. package/dist/src/screen-recording-transport.js +1 -1
  154. package/dist/src/screenshot-runtime.js +1 -1
  155. package/dist/src/screenshot3.js +1 -1
  156. package/dist/src/script.js +1 -1
  157. package/dist/src/scroll-command.d.ts +377 -0
  158. package/dist/src/scroll-command.js +1 -1
  159. package/dist/src/sdk-batch.js +2 -2
  160. package/dist/src/sdk-contracts.d.ts +9 -0
  161. package/dist/src/sdk-device.js +1 -1
  162. package/dist/src/sdk-selectors.d.ts +23 -715
  163. package/dist/src/selection.js +0 -0
  164. package/dist/src/selector-runtime.js +1 -1
  165. package/dist/src/semantic-index.js +1 -1
  166. package/dist/src/server.js +1 -1
  167. package/dist/src/session-observation.js +1 -1
  168. package/dist/src/session-snapshot.js +1 -1
  169. package/dist/src/session2.js +2 -2
  170. package/dist/src/simctl-facade.js +1 -1
  171. package/dist/src/simctl.js +1 -1
  172. package/dist/src/simulator-facade.js +1 -1
  173. package/dist/src/simulator-state.js +1 -1
  174. package/dist/src/simulator.js +1 -1
  175. package/dist/src/snapshot-runtime-binding.js +1 -1
  176. package/dist/src/snapshot-runtime.js +1 -1
  177. package/dist/src/snapshot-state.js +1 -1
  178. package/dist/src/snapshot4.js +1 -1
  179. package/dist/src/src7.js +1 -1
  180. package/dist/src/text-entry-focus.js +1 -1
  181. package/dist/src/tool-provider.js +1 -1
  182. package/dist/src/touch-runtime.js +1 -1
  183. package/dist/src/tree.js +1 -1
  184. package/dist/src/update-check.js +1 -1
  185. package/dist/src/version.js +1 -1
  186. package/dist/src/web2.js +1 -1
  187. package/package.json +4 -2
  188. package/server.json +2 -2
  189. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.11.apk.sha256 +0 -1
  190. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.11.apk.sha256 +0 -1
  191. package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubPose.swift +0 -47
  192. package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubWindowInventory.swift +0 -65
  193. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubPose.swift +0 -225
  194. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubSidebar.swift +0 -57
  195. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubWindowDiscovery.swift +0 -108
  196. package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubPoseTests.swift +0 -30
  197. package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubWindowInventoryTests.swift +0 -65
  198. package/dist/src/app-inventory.d.ts +0 -4
  199. package/dist/src/apps-simctl.js +0 -1
  200. package/dist/src/cloud-artifacts.d.ts +0 -61
  201. package/dist/src/runner-contract.js +0 -3
@@ -0,0 +1,106 @@
1
+ import XCTest
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+ struct SnapshotCaptureTarget {
13
+ let app: XCUIApplication
14
+ let bundleId: String?
15
+ let processIdentifier: Int?
16
+ }
17
+
18
+
19
+ enum SnapshotCommandPreparation {
20
+ case response(Response)
21
+ case capture(SnapshotCaptureTarget, systemSurface: SystemSurfaceHost?)
22
+ }
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+ enum SnapshotProbePenaltyTarget: Equatable {
32
+
33
+ case prepared(bundleId: String?)
34
+
35
+ case mainOwnedTarget
36
+ }
37
+
38
+
39
+
40
+ final class SnapshotProbePenaltyIdentity {
41
+ private let lock = NSLock()
42
+ private var bundleId: String?
43
+ private let readsMainOwnedTarget: Bool
44
+
45
+ init(_ target: SnapshotProbePenaltyTarget) {
46
+ readsMainOwnedTarget = target == .mainOwnedTarget
47
+ if case .prepared(let bundleId) = target {
48
+ self.bundleId = bundleId
49
+ }
50
+ }
51
+
52
+
53
+
54
+ func captureFromMain(bundleId: String?) {
55
+ guard readsMainOwnedTarget else { return }
56
+ lock.lock()
57
+ self.bundleId = bundleId
58
+ lock.unlock()
59
+ }
60
+
61
+ var penalizedBundleId: String? {
62
+ lock.lock()
63
+ defer { lock.unlock() }
64
+ return bundleId
65
+ }
66
+ }
67
+
68
+ extension RunnerTests {
69
+
70
+ func takeSnapshotCaptureTarget(app: XCUIApplication) -> SnapshotCaptureTarget {
71
+ SnapshotCaptureTarget(
72
+ app: app,
73
+ bundleId: currentBundleId,
74
+ processIdentifier: currentAppProcessIdentifier
75
+ )
76
+ }
77
+
78
+
79
+
80
+
81
+ func applyMainOwnedSnapshotState(_ operation: String, _ write: @escaping () -> Void) {
82
+ if Thread.isMainThread {
83
+ write()
84
+ return
85
+ }
86
+ guard !hasAbandonedMainThreadWork() else {
87
+ NSLog("AGENT_DEVICE_RUNNER_SNAPSHOT_STATE_DEFERRED_XCTEST_OCCUPIED operation=%@", operation)
88
+ DispatchQueue.main.async(execute: write)
89
+ return
90
+ }
91
+ do {
92
+ try runMainThreadWork(
93
+ operation,
94
+ timeout: 1,
95
+ timeoutError: mainThreadExecutionTimeoutError,
96
+ write
97
+ )
98
+ } catch {
99
+ NSLog(
100
+ "AGENT_DEVICE_RUNNER_SNAPSHOT_STATE_FAILED operation=%@ error=%@",
101
+ operation,
102
+ String(describing: error)
103
+ )
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,142 @@
1
+ import XCTest
2
+ import AgentDeviceSnapshotPresentation
3
+
4
+ extension RunnerTests {
5
+ func executeSnapshotDispatched(command: Command) throws -> Response {
6
+ try executeDispatchedWithRecovery(command: command) {
7
+ try self.executeSnapshotDispatchedOnce(command: command)
8
+ }
9
+ }
10
+
11
+ private func executeSnapshotDispatchedOnce(command: Command) throws -> Response {
12
+ let preparation: SnapshotCommandPreparation = try runMainThreadWork(
13
+ "command_preparation",
14
+ timeout: mainThreadExecutionTimeout,
15
+ timeoutError: mainThreadExecutionTimeoutError
16
+ ) { () -> SnapshotCommandPreparation in
17
+ switch try self.prepareActiveCommandContextSafely(command: command, routeToSpringboard: false) {
18
+ case .response(let response):
19
+ return .response(response)
20
+ case .context(let context):
21
+ return .capture(
22
+ self.takeSnapshotCaptureTarget(app: context.app),
23
+ systemSurface: context.systemSurface
24
+ )
25
+ }
26
+ }
27
+ switch preparation {
28
+ case .response(let response):
29
+ return response
30
+ case .capture(let target, let systemSurface):
31
+ return try executeSnapshotPrepared(
32
+ command: command,
33
+ target: target,
34
+ systemSurface: systemSurface
35
+ )
36
+ }
37
+ }
38
+
39
+ private func prepareActiveCommandContextSafely(
40
+ command: Command,
41
+ routeToSpringboard: Bool
42
+ ) throws -> ActiveCommandPreparation {
43
+ var preparation: ActiveCommandPreparation?
44
+ let exceptionMessage = RunnerObjCExceptionCatcher.catchException({
45
+ preparation = self.prepareActiveCommandContext(
46
+ command: command,
47
+ routeToSpringboard: routeToSpringboard
48
+ )
49
+ })
50
+ if let exceptionMessage {
51
+ throw NSError(
52
+ domain: RunnerErrorDomain.exception,
53
+ code: RunnerErrorCode.objcException,
54
+ userInfo: [NSLocalizedDescriptionKey: exceptionMessage]
55
+ )
56
+ }
57
+ guard let preparation else {
58
+ throw NSError(
59
+ domain: RunnerErrorDomain.general,
60
+ code: RunnerErrorCode.commandReturnedNoResponse,
61
+ userInfo: [NSLocalizedDescriptionKey: "snapshot preflight returned no response"]
62
+ )
63
+ }
64
+ return preparation
65
+ }
66
+
67
+
68
+
69
+ static func presentationOptions(from command: Command) -> PresentationOptions {
70
+ let customActions = command.customActions ?? false
71
+ return PresentationOptions(
72
+ interactiveOnly: command.interactiveOnly ?? false,
73
+ depth: command.depth,
74
+ scope: command.scope,
75
+ raw: command.raw ?? false,
76
+
77
+
78
+
79
+ preferredBackend: command.preferredBackend
80
+ ?? (customActions ? SnapshotBackendKind.privateAX.rawValue : nil),
81
+ customActions: customActions
82
+ )
83
+ }
84
+
85
+ private func executeSnapshotPrepared(
86
+ command: Command,
87
+ target: SnapshotCaptureTarget,
88
+ systemSurface: SystemSurfaceHost?
89
+ ) throws -> Response {
90
+ let options = Self.presentationOptions(from: command)
91
+ do {
92
+ var payload: DataPayload
93
+ if options.raw {
94
+ payload = try snapshotRaw(target: target, options: options)
95
+ } else {
96
+ payload = try snapshotFast(target: target, options: options)
97
+ }
98
+ if let systemSurface {
99
+ payload.systemSurface = SystemSurfaceProvenancePayload(
100
+ bundleId: systemSurface.bundleId,
101
+ kind: systemSurface.kind.rawValue
102
+ )
103
+ }
104
+ setNeedsPostSnapshotInteractionDelay()
105
+ return Response(ok: true, data: payload)
106
+ } catch let failure as SnapshotCaptureFailure {
107
+ invalidateCachedTargetAfterSnapshotFailure()
108
+ return Response(
109
+ ok: false,
110
+ error: ErrorPayload(
111
+ code: failure.code,
112
+ message: failure.message,
113
+ hint: failure.hint
114
+ )
115
+ )
116
+ }
117
+ }
118
+
119
+ func setNeedsPostSnapshotInteractionDelay() {
120
+ guard !hasAbandonedMainThreadWork() else {
121
+ NSLog("AGENT_DEVICE_RUNNER_POST_SNAPSHOT_DELAY_MARK_SKIPPED_XCTEST_OCCUPIED")
122
+ return
123
+ }
124
+ do {
125
+ try runMainThreadWork(
126
+ "post_snapshot_delay_mark",
127
+ timeout: 1,
128
+ timeoutError: mainThreadExecutionTimeoutError
129
+ ) {
130
+ self.needsPostSnapshotInteractionDelay = true
131
+ }
132
+ } catch {
133
+ NSLog("AGENT_DEVICE_RUNNER_POST_SNAPSHOT_DELAY_MARK_FAILED=%@", String(describing: error))
134
+ }
135
+ }
136
+
137
+ func invalidateCachedTargetAfterSnapshotFailure() {
138
+ applyMainOwnedSnapshotState("target_invalidation") {
139
+ self.invalidateCachedTarget(reason: "ax_snapshot_failure")
140
+ }
141
+ }
142
+ }
@@ -57,6 +57,35 @@ struct SnapshotPhaseTimer {
57
57
  }
58
58
  }
59
59
 
60
+
61
+
62
+
63
+ final class SnapshotXCTestPenaltyWarmupExemption {
64
+ private let lock = NSLock()
65
+ private var pending = false
66
+
67
+ var isPending: Bool {
68
+ get {
69
+ lock.lock()
70
+ defer { lock.unlock() }
71
+ return pending
72
+ }
73
+ set {
74
+ lock.lock()
75
+ pending = newValue
76
+ lock.unlock()
77
+ }
78
+ }
79
+
80
+ func consume() -> Bool {
81
+ lock.lock()
82
+ defer { lock.unlock() }
83
+ let wasPending = pending
84
+ pending = false
85
+ return wasPending
86
+ }
87
+ }
88
+
60
89
  extension RunnerTests {
61
90
  struct SnapshotBackendAttempt {
62
91
  enum Outcome {
@@ -69,11 +98,25 @@ extension RunnerTests {
69
98
 
70
99
  let outcome: Outcome
71
100
  let timing: SnapshotCaptureTiming
101
+
102
+
103
+
104
+ let tierOutcome: SnapshotTierOutcome
105
+
106
+ init(
107
+ outcome: Outcome,
108
+ timing: SnapshotCaptureTiming,
109
+ tierOutcome: SnapshotTierOutcome = .completed
110
+ ) {
111
+ self.outcome = outcome
112
+ self.timing = timing
113
+ self.tierOutcome = tierOutcome
114
+ }
72
115
  }
73
116
 
74
117
 
75
118
 
76
- private static func snapshotXCTestPenaltyReason(
119
+ static func snapshotXCTestPenaltyReason(
77
120
  kind: SnapshotBackendKind,
78
121
  attempt: SnapshotBackendAttempt,
79
122
  slowThresholdMs: Double
@@ -84,6 +127,9 @@ extension RunnerTests {
84
127
  {
85
128
  return "\(kind.rawValue)_backend_timeout"
86
129
  }
130
+ if attempt.tierOutcome == .deadlineExhausted {
131
+ return "\(kind.rawValue)_backend_timeout"
132
+ }
87
133
  guard attempt.timing.acquisitionMs > slowThresholdMs else { return nil }
88
134
  return "slow_\(kind.rawValue)_capture_\(Int(attempt.timing.acquisitionMs))ms"
89
135
  }
@@ -91,6 +137,7 @@ extension RunnerTests {
91
137
  func recordXCTestSnapshotBackendAttemptIfNeeded(
92
138
  _ kind: SnapshotBackendKind,
93
139
  attempt: SnapshotBackendAttempt,
140
+ bundleId: String?,
94
141
  penaltySuppressed: Bool
95
142
  ) {
96
143
  guard !penaltySuppressed else { return }
@@ -102,84 +149,8 @@ extension RunnerTests {
102
149
  )
103
150
  else { return }
104
151
  penalizeSnapshotXCTestChannel(
105
- bundleId: currentBundleId,
152
+ bundleId: bundleId,
106
153
  reason: reason
107
154
  )
108
155
  }
109
156
  }
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
@@ -67,43 +67,6 @@ extension RunnerTests {
67
67
 
68
68
 
69
69
 
70
- func awaitSynthesizedFirstResponderCommit(
71
- app: XCUIApplication,
72
- target: TextEntryTarget,
73
- textBefore: String?,
74
- typedText: String
75
- ) -> SynthesizedTextCommitOutcome {
76
- guard let textBefore, !typedText.contains("\n"), !typedText.contains("\r") else {
77
- return .unobservable
78
- }
79
- let expectedText = textBefore + typedText
80
- let waitStartedAt = Date()
81
- NSLog("[DEBUG-1874] wait start expectedLen=%ld route=append", expectedText.count)
82
- let ingredients = synthesizedCommitPollingIngredients(app: app, target: target, expectedText: expectedText)
83
- let outcome = Self.awaitSynthesizedCommitOutcome(
84
- expectedText: expectedText,
85
- placeholder: ingredients.placeholder,
86
- now: { Date() },
87
- observe: ingredients.observe,
88
- waitForNextObservation: ingredients.waitForNextObservation
89
- )
90
- NSLog(
91
- "[DEBUG-1874] wait outcome=%@ elapsedMs=%.0f route=append",
92
- String(describing: outcome),
93
- waitStartedAt.timeIntervalSinceNow * -1000
94
- )
95
- return outcome
96
- }
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
70
 
108
71
  func awaitSynthesizedReplacementCommit(
109
72
  app: XCUIApplication,
@@ -163,13 +126,6 @@ extension RunnerTests {
163
126
 
164
127
 
165
128
 
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
129
  private func synthesizedCommitPollingIngredients(
174
130
  app: XCUIApplication,
175
131
  target: TextEntryTarget,
@@ -139,104 +139,34 @@ extension RunnerTests {
139
139
  fallbackAttempted: Bool
140
140
  ) {
141
141
  #if os(iOS)
142
- guard let context else {
143
- NSLog(
144
- "AGENT_DEVICE_RUNNER_SYNTHESIZED_GESTURE_POLICY kind=%@ context=unavailable fallbackAttempted=%@",
145
- kind.rawValue,
146
- fallbackAttempted.description
147
- )
148
- return
149
- }
150
- NSLog(
151
- "AGENT_DEVICE_RUNNER_SYNTHESIZED_GESTURE_POLICY kind=%@ axHealth=%@ frameSource=window keyboardPolicy=%@ fallbackPolicy=%@ fallbackAllowed=%@ fallbackAttempted=%@",
152
- kind.rawValue,
153
- context.accessibilityHealth.rawValue,
154
- context.keyboardPolicy.rawValue,
155
- context.fallbackPolicy.rawValue,
156
- context.allowsXCTestCoordinateFallback.description,
157
- fallbackAttempted.description
142
+ let line = Self.synthesizedGesturePolicyLine(
143
+ kind: kind,
144
+ context: context,
145
+ fallbackAttempted: fallbackAttempted
158
146
  )
159
- #endif
160
- }
161
- }
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
-
228
-
229
-
230
-
231
-
232
-
233
-
234
-
235
-
236
-
237
-
238
-
239
-
240
147
 
241
148
 
149
+ if lastLoggedGesturePolicyLines[kind] != line {
150
+ lastLoggedGesturePolicyLines[kind] = line
151
+ runnerMarkerWriter(line)
152
+ }
153
+ #endif
154
+ }
242
155
 
156
+ static func synthesizedGesturePolicyLine(
157
+ kind: SynthesizedGesturePolicyKind,
158
+ context: SynthesizedCoordinateContext?,
159
+ fallbackAttempted: Bool
160
+ ) -> String {
161
+ guard let context else {
162
+ return "AGENT_DEVICE_RUNNER_SYNTHESIZED_GESTURE_POLICY kind=\(kind.rawValue)"
163
+ + " context=unavailable fallbackAttempted=\(fallbackAttempted)"
164
+ }
165
+ return "AGENT_DEVICE_RUNNER_SYNTHESIZED_GESTURE_POLICY kind=\(kind.rawValue)"
166
+ + " axHealth=\(context.accessibilityHealth.rawValue) frameSource=window"
167
+ + " keyboardPolicy=\(context.keyboardPolicy.rawValue)"
168
+ + " fallbackPolicy=\(context.fallbackPolicy.rawValue)"
169
+ + " fallbackAllowed=\(context.allowsXCTestCoordinateFallback)"
170
+ + " fallbackAttempted=\(fallbackAttempted)"
171
+ }
172
+ }
@@ -9,7 +9,7 @@ extension RunnerTests {
9
9
  x2: Double,
10
10
  y2: Double,
11
11
  durationMs: Double,
12
- profile: SynthesizedDragProfile = .continuous,
12
+ profile: SynthesizedDragProfile,
13
13
  context: SynthesizedCoordinateContext? = nil
14
14
  ) -> RunnerInteractionOutcome {
15
15
  #if os(iOS)
@@ -48,16 +48,6 @@ extension RunnerTests {
48
48
  orientation: orientation
49
49
  )
50
50
  let message = switch profile {
51
- case .continuous:
52
- RunnerSynthesizedGesture.synthesizeContinuousDrag(
53
- withApplication: app,
54
- resolvedWindow: context.resolvedWindow,
55
- x: Double(start.x),
56
- y: Double(start.y),
57
- x2: Double(end.x),
58
- y2: Double(end.y),
59
- durationMs: durationMs
60
- )
61
51
  case .controlledScroll:
62
52
  RunnerSynthesizedGesture.synthesizeControlledScroll(
63
53
  withApplication: app,