Finding
On the GitHub-hosted iOS Smoke job's simulator (ios.yml → "Run fixture-backed iOS simulator E2E smoke", iPhone 17 Pro, iOS 26.2), the XCUITest runner's XCUIApplication(bundleIdentifier:).state reports .runningForeground for the runner's own target app while a foreign app is demonstrably holding the screen.
Consequence inside the runner (RunnerTests+Lifecycle.swift targetNeedsActivation → RunnerTests+CommandExecution.swift prepareActiveCommandContext): the activation preflight is skipped, the capture is served from the backgrounded app, and no targetActivation fact is stamped (#2682) — correctly so, given the state it read. The divergence is between that state read and the device's actual foreground app, not in the disclosure path.
Evidence
- Failed lane run: https://github.com/callstack/agent-device/actions/runs/35460535722/job/105943468492 —
smoke-ios-target-activation.test.ts, "no foreground disclosure within 90000ms of the handoff to com.apple.Preferences".
- Uploaded artifact for that run proves both sides of the contradiction: the pre-handoff screenshot shows the session app rendered (
wait label="Gesture lab" had already passed), the post-handoff screenshot shows Settings on screen, and the 31 snapshot -i responses in between each returned a healthy tree for com.callstack.agentdevicelab in ~450 ms with targetActivation absent.
- The same runner build on a local simulator (iPhone 17 Pro, iOS 26.2) discloses on the first capture after the identical handoff:
{"reason":"bundle_changed","priorState":"runningBackground","otherActiveApplicationPid":<pid>}, pid resolvable to com.apple.Preferences/MobileSafari by host ps, and the following capture discloses nothing.
- Same-shape symptom on the Android lane of the same job family is unrelated (
wait timed out for text: Automation lab, a fixture launch issue).
Required behavior
Decide which of these the repo believes, and encode it where the claim lives:
- The runner must not trust
XCUIApplication.state alone as the foreground oracle when the session's app can be observed to be backgrounded by another signal (e.g. the runner's own activeApplications probe, which already yields soleOtherActiveApplicationPid). Then a CI-simulator capture of a backgrounded app activates and discloses like every other host.
- Or the runner documents that target-foreground equality is not observable on CI-hosted simulators, and the live activation lane is declared manual/env-gated with the reason stated at the lane (its current state) so no automatic gate ever waits on that assertion.
Completion conditions
Non-goals
Not a claim that physical devices misreport foreground; the physical lane for #2682 is tracked in .device-evidence/CHECKLIST.md.
Finding
On the GitHub-hosted iOS Smoke job's simulator (
ios.yml→ "Run fixture-backed iOS simulator E2E smoke", iPhone 17 Pro, iOS 26.2), the XCUITest runner'sXCUIApplication(bundleIdentifier:).statereports.runningForegroundfor the runner's own target app while a foreign app is demonstrably holding the screen.Consequence inside the runner (
RunnerTests+Lifecycle.swifttargetNeedsActivation→RunnerTests+CommandExecution.swiftprepareActiveCommandContext): the activation preflight is skipped, the capture is served from the backgrounded app, and notargetActivationfact is stamped (#2682) — correctly so, given the state it read. The divergence is between that state read and the device's actual foreground app, not in the disclosure path.Evidence
smoke-ios-target-activation.test.ts, "no foreground disclosure within 90000ms of the handoff to com.apple.Preferences".wait label="Gesture lab"had already passed), the post-handoff screenshot shows Settings on screen, and the 31snapshot -iresponses in between each returned a healthy tree forcom.callstack.agentdevicelabin ~450 ms withtargetActivationabsent.{"reason":"bundle_changed","priorState":"runningBackground","otherActiveApplicationPid":<pid>}, pid resolvable tocom.apple.Preferences/MobileSafariby hostps, and the following capture discloses nothing.wait timed out for text: Automation lab, a fixture launch issue).Required behavior
Decide which of these the repo believes, and encode it where the claim lives:
XCUIApplication.statealone as the foreground oracle when the session's app can be observed to be backgrounded by another signal (e.g. the runner's ownactiveApplicationsprobe, which already yieldssoleOtherActiveApplicationPid). Then a CI-simulator capture of a backgrounded app activates and discloses like every other host.Completion conditions
targetNeedsActivation).targetActivation, and it passes.test/integration/smoke-ios-target-activation.test.tsstates the divergence at the lane, and no CI job depends on that assertion.Non-goals
Not a claim that physical devices misreport foreground; the physical lane for #2682 is tracked in
.device-evidence/CHECKLIST.md.