* fix(ios): use XCTest runner for screenshots on physical devices
`xcrun devicectl device screenshot` was removed in Xcode 26.x, causing
`agent-device screenshot` to fail on physical iOS devices with exit code 64.
This fix routes physical device screenshots through the AgentDeviceRunner
XCTest runner (already used for snapshot/interaction commands) instead:
- Add `screenshot` command to the Swift runner's `CommandType` enum
- Implement the handler using `XCUIScreen.main.screenshot()`, writing a
timestamped PNG to the app's temp directory (returned as `tmp/<file>`)
- If `appBundleId` is provided, activate the target app before capturing
so the screenshot shows the app under test rather than the runner itself
- In `screenshotIos()`, pass `appBundleId` to the runner command then pull
the file back to the host via `xcrun devicectl device copy from` (same
mechanism used by the recording feature)
- Thread `appBundleId` through `Interactor.screenshot()` → `dispatch.ts`
→ `screenshotIos()` so the active session's app is always captured
- Extract `IOS_RUNNER_CONTAINER_BUNDLE_IDS` to `runner-client.ts` so it
can be shared between `apps.ts` and `record-trace.ts`
Fixes: screenshots failing with "Failed to capture iOS screenshot" on
devices using Xcode 26.x / devicectl 506.6+
* fix: clean up iOS screenshot fallback follow-ups
---------
Co-authored-by: Michał Pierzchała <thymikee@gmail.com>
* fix: add MAIN/LAUNCHER flags to Android launcher activity resolver
The `resolve-activity` fallback command was missing `-a android.intent.action.MAIN`
and `-c android.intent.category.LAUNCHER`, causing it to resolve the wrong activity
on multi-entry apps like Microsoft Outlook. This adds the correct intent flags so
the resolver consistently returns the launcher activity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: detect am start silent failures and fall back to resolved component
am start -p <package> can exit 0 while printing "Error: Activity not
started" to stdout. The previous try/catch never entered the fallback
because runCmd did not throw. Now we check the output for error
indicators via isAmStartError() and proceed to the resolve-activity
fallback when the primary launch silently fails.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: EarthXP <15072042+EarthXP@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add open --relaunch and persist replay semantics
* Update agent-device skill docs for open --relaunch
* Disambiguate relaunch and save-script examples
* Support non-hierarchical deep links in open target detection
* ci: add manual iOS runner prebuild cache for iOS workflow
* ci: simplify manual iOS prebuild workflow
* ci: pin cache actions in iOS workflows
* ci: fix iOS workflow env paths for parser compatibility
* ci: increase daemon timeout for iOS boot preflight
* ios: harden simulator state timeout and reuse preflight session
* ci: remove redundant iOS boot preflight step
* ios: retry transient simctl launch failures on simulator
* ci: pin iOS integration test target to resolved 26.2 simulator
* ci: harden iOS prebuild cache keys and remove derived-data copy path
* ci: simplify iOS workflow caching and drop redundant prebuild workflow
- Remove standalone ios-runner-prebuild.yml (redundant — ios.yml builds on cache miss)
- Switch from actions/cache/restore to actions/cache (auto-saves on miss)
- Drop restore-keys and -stable suffix (no longer needed without prebuild workflow)
- Remove UDID resolution step (test falls back to --platform ios)
- Use point-free shouldRetry for isTransientSimulatorLaunchFailure
Co-authored-by: Cursor <cursoragent@cursor.com>
* ios: increase simctl launch retry budget for CI simulators
SpringBoard can take several seconds after boot to accept app launches.
Increase from 3 attempts / 500ms–2s to 5 attempts / 1s–5s to give CI
simulators enough time.
Co-authored-by: Cursor <cursoragent@cursor.com>
* ios: use deadline-based retry for simulator app launch
The fixed-attempt retry (5 attempts, ~12s window) is too short for CI
simulators where SpringBoard needs 30-60s after boot to accept app
launches — especially when the build step is cached and provides zero
warm-up time.
Switch to a deadline-based approach matching ensureBootedSimulator:
- Default 30s timeout (configurable via AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS)
- CI sets 60s to handle cold-boot scenarios
- maxAttempts set high (30) so the deadline is the real limit
Co-authored-by: Cursor <cursoragent@cursor.com>
* ci(ios): keep tests platform-based and stabilize simulator selection
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* Refine reinstall flow and add agent-focused coverage
* Avoid duplicate readiness preflight in open flow
* Document boot and reinstall in website docs and skill
* Bound iOS boot commands and enforce runCmd timeouts
* Align boot readiness with timeout profiles across platforms
* Refine boot docs: troubleshooting-only and non-CI wording
* Clarify open vs boot fallback guidance
* Complete issue #39 phase diagnostics telemetry and boot command
* Address review findings for boot diagnostics and command gating
* Use agent-device boot preflight in iOS CI workflow
* Run iOS boot preflight via source CLI in CI