feat(ios): route iPad Simulator snapshots through the host AX bridge
Summary
iPad Simulators (appleOs: 'ipados') now use the host AX bridge. The route and launch observation admitted only ios, so every iPad capture went to XCTest (#3844). hasSimulatorBridge now uses isHandheldAppleSimulator; devices, providers, tvOS, visionOS, and macOS stay excluded.
Live checks found two iPad gaps, fixed here:
- Floating tab items are
Cell/Otherwith the tab-button trait (bit 28). XCTest types themButton; the bridge now does too. - Windowed Apps and Stage Manager report frames relative to the window, so bridge taps missed. The guest refuses (
app-window-not-full-screen, capture-scoped) when the app frame โ the screen frame. The XCTest fallback is also offset there (runner gap, not fixed; the warning says so).
14 files; ADR 0004 and bridge README amended. Refs #3844.
Validation
Head 4fa5bd595e: check:affected --run --head and pnpm gate unit-ci pass except apple-platform-output-guard (record exceeds 20 s; same with base sources) and one 5 s timeout in coordinate.contract errorTaxonomy under load (passes alone, cause unproven). New tests fail at base.
iOS 27.0 iPad Pro 11" M5, iPad Air 11" M4, iPhone 17 Pro; bridge vs forced tree:
| Case | Bridge | Parity |
|---|---|---|
| Portrait, landscape, keyboard | served | rects equal |
| Alert, sheet | served | rects equal |
| Apple Pay | XCTest, then bridge | โ |
| Permission alert | XCTest (ownership) | โ |
| Windowed, Stage Manager | XCTest (new refusal) | runner offset |
| Bluesky feed | 285 vs 453 ms p50 | 266/266 types |
| iPhone | 140 vs 241 ms p50 | unchanged |
Slide Over untested.
๐ค Generated with Claude Code