Summary
On an iOS Simulator, snapshot -i can take 30–39 seconds when a SpringBoard-owned system alert is visible, even though ordinary app snapshots are fast. The system-modal probe runs before the bounded snapshot capture plan, so the existing plan deadline and XCTest recovery protections do not bound this path.
Observed with agent-device 0.19.1, which is also the latest release at the time of this report.
Observed behavior
From 68 recorded iOS snapshot operations in one investigation:
- median: 330 ms
- p90: 5,032 ms
- p95: 29,962 ms
- maximum: 39,208 ms
- 10 exceeded 1 second
- 8 exceeded 5 seconds
- 6 exceeded 20 seconds
Every 30–39 second outlier occurred while a SpringBoard system alert was displayed. Two repeatable examples were:
- An
ASWebAuthenticationSession consent prompt of the form “App Wants to Use example.com to Sign In”.
- The standard notification permission prompt of the form “App Would Like to Send You Notifications”.
The command eventually returned the alert's semantic nodes, but only after the long stall. Ordinary app-owned snapshots in the same environment generally returned in hundreds of milliseconds.
Reproduction shape
- Boot an iOS Simulator and open an app that presents one of the system dialogs above.
- While the dialog is visible, run:
agent-device snapshot -i --platform ios --session <session>
- Observe that the command may take roughly 30–39 seconds before returning the alert tree.
The issue was seen with both the authentication consent dialog and notification permission dialog, so it does not appear specific to one alert's contents.
Source-path analysis
Both snapshotFast and snapshotRaw call blockingSystemAlertSnapshot() before calling runSnapshotCapturePlan(...).
blockingSystemAlertSnapshot() performs SpringBoard alert/sheet enumeration and descendant queries through safeElementsQuery. That helper delegates to safely, which catches Objective-C exceptions but does not impose a time limit.
As a result:
- the 20-second
snapshotPlanBudget has not started yet;
- the bounded XCTest tree-capture slices do not apply;
- a slow
springboard.alerts.allElementsBoundByIndex, sheet query, or descendant query can block the request outside the normal capture/recovery envelope.
Relevant files on current main:
apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift
apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift
apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift
apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift
The recent bounded iOS capture work in #1107, #1144, and #1158 protects the normal capture plan, but this pre-plan system-modal path bypasses those protections.
This also appears distinct from #1231 / #1232, which concern remote-hosted AccessorySetupKit UI on physical iOS and missing/flaky modal detection rather than long-running SpringBoard queries on a simulator.
Expected behavior
- System-modal detection is included in a bounded request/capture budget.
- A normal SpringBoard alert returns its actionable semantic nodes promptly.
- If the modal query exceeds its budget, the command fails or falls back with an explicit, actionable degraded-state result rather than blocking for 30–39 seconds.
- A slow modal query does not wedge the runner, destroy the daemon, or invalidate unrelated sessions.
- Diagnostics identify which system-modal probe timed out and how long it ran.
Possible direction
Treat system-modal detection as a bounded capture tier rather than an unbounded preflight. For example, run the SpringBoard query through the same bounded main-thread work/watchdog mechanism and share the overall capture deadline, stopping remaining alert/sheet/descendant queries once the deadline is exhausted.
The exact implementation is best left to the maintainers; the important contract is that the special system-modal path cannot bypass the snapshot command's timeout and recovery guarantees.
Summary
On an iOS Simulator,
snapshot -ican take 30–39 seconds when a SpringBoard-owned system alert is visible, even though ordinary app snapshots are fast. The system-modal probe runs before the bounded snapshot capture plan, so the existing plan deadline and XCTest recovery protections do not bound this path.Observed with
agent-device 0.19.1, which is also the latest release at the time of this report.Observed behavior
From 68 recorded iOS snapshot operations in one investigation:
Every 30–39 second outlier occurred while a SpringBoard system alert was displayed. Two repeatable examples were:
ASWebAuthenticationSessionconsent prompt of the form “App Wants to Use example.com to Sign In”.The command eventually returned the alert's semantic nodes, but only after the long stall. Ordinary app-owned snapshots in the same environment generally returned in hundreds of milliseconds.
Reproduction shape
The issue was seen with both the authentication consent dialog and notification permission dialog, so it does not appear specific to one alert's contents.
Source-path analysis
Both
snapshotFastandsnapshotRawcallblockingSystemAlertSnapshot()before callingrunSnapshotCapturePlan(...).blockingSystemAlertSnapshot()performs SpringBoard alert/sheet enumeration and descendant queries throughsafeElementsQuery. That helper delegates tosafely, which catches Objective-C exceptions but does not impose a time limit.As a result:
snapshotPlanBudgethas not started yet;springboard.alerts.allElementsBoundByIndex, sheet query, or descendant query can block the request outside the normal capture/recovery envelope.Relevant files on current
main:apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swiftapple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swiftapple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swiftapple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swiftThe recent bounded iOS capture work in #1107, #1144, and #1158 protects the normal capture plan, but this pre-plan system-modal path bypasses those protections.
This also appears distinct from #1231 / #1232, which concern remote-hosted AccessorySetupKit UI on physical iOS and missing/flaky modal detection rather than long-running SpringBoard queries on a simulator.
Expected behavior
Possible direction
Treat system-modal detection as a bounded capture tier rather than an unbounded preflight. For example, run the SpringBoard query through the same bounded main-thread work/watchdog mechanism and share the overall capture deadline, stopping remaining alert/sheet/descendant queries once the deadline is exhausted.
The exact implementation is best left to the maintainers; the important contract is that the special system-modal path cannot bypass the snapshot command's timeout and recovery guarantees.