fix(ios): keep the runner alive when XCTest cannot snapshot the app

Merged
TH
7d ago
+829-95

Summary

Fixes the iOS runner dying on trees XCTest cannot snapshot.

Root cause: an XCUICoordinate, and any unheld app.frame read, resolve through the application's accessibility snapshot. On such a tree that read fails, XCTest records an issue that ends the runner test, or the infinite point raises.

  • SynthesizedCoordinateContext.treeUnreadable carries this call's own windows proof; tapAt synthesizes on it.
  • heldAppFrame is the one held iOS read of the app frame; readableAppFrame refuses with a coded UNSUPPORTED_OPERATION plus hint where it does not read. Coordinate gestures resolve through resolveCoordinateWindow and refuse; other readers (snapshot viewport, window frame) keep an empty frame.
  • In a sequence, a refusal is that step's outcome, and its hint reaches the client (errorHint).
  • One per-command xCTestUnavailable decides the fill route, replacement guard and typing.

20 files (14 Swift, 2 TS, tests).

Validation

  • Head a19ff7b618: pnpm check:affected --run --head a19ff7b618 passed, exactCommit=true. CI: all checks green.
  • Runner unit tests (iOS 27.0 sim): new tests fail at d0bbf4b and pass at head; 135-test affected set passes (one timing flake, passes 2/2 alone). macOS and tvOS runner builds pass.
  • Live press 228 280 --double-tap, Bluesky composer: iOS 26.2 at d0bbf4b and iOS 27.0 at fab47a3 refuse step 0 with UNSUPPORTED_OPERATION and keep the runner. At a19ff7b618 on iOS 27.0 the tree read back, so the double tap was performed.
  • Risk: a fill reads the context once; a tree that stops answering mid-command is not re-read.

šŸ¤– Generated with Claude Code