fix(ios): size the sole display from the system app, not the runner's UIScreen

TH
2h ago
+500-66

Summary

Fixes #4091. Synthesized landscape presses landed a fixed offset away from the requested point and still reported ok. soleDisplayFrame read UIScreen.main in the runner process. The generated AgentDeviceRunnerUITests-Runner.app has no launch screen, so that read can come back in compatibility mode (768x1024 on an iPad).

  • Display source: the AXRuntime system application frame, normalized to portrait. It is read once per command (~0.6–0.9 ms, measured), and only for turns that use the box (landscape and upside-down).
  • Unreadable display: portrait needs no box, so a tap is sent as given, even with no window. In landscape, an app the sole-screen rule (RunnerResolveSoleScreen) admits uses its window. With no window, or a placed iPad window (#3899), the gesture returns UNSUPPORTED_OPERATION before dispatch. Each case logs AGENT_DEVICE_RUNNER_APP_SCREEN_UNRESOLVED stage=rotation-basis.
  • Unchanged: multi-screen hosts keep the window route. No new private API is added; iPhone synthesis now also uses AXRuntime.

Rejected: a launch-screen key for the runner, which would mean patching Xcode's runner template and could not be proven here.

Validation

Base a42bc35282, head 00d36437ba.

  • The compatibility-mode test fails on base and passes on head.
  • AX-failure tests: portrait taps are dispatched, with or without a window. In landscape, iPhone dispatches about the window, a placed iPad window refuses, and a missing window refuses. Each test fails when its branch is removed.
  • The per-command cache test passes.
  • Live run with the branch runner on iOS 27.0: iPad 3/3 per orientation, iPhone 17 3/3 per landscape side.
  • Last local receipt: check:affected --run --head bf0b1ca48d passed all runnable checks, exactCommit=true (run-jWH5SD). The head 00d36437ba changes only two Swift test comments, which the gate does not compile. Gate reruns on that head failed only in unrelated TS unit tests, hit by stray GET / traffic on the host. CI is green on 00d36437ba. Swift runner gates run in CI.

Unverified: the live compatibility-mode offset did not reproduce on these runtimes. Possible follow-up: a unit test that fakes a two-screen XCUIScreen.screens; the single-screen guard is enforced in RunnerResolveSoleScreen and synthesizedRotationFrame.

šŸ¤– Generated with Claude Code