refactor(apple): make runner surface policy explicit
Summary
Replace the RUNNER_COMMAND_RESOLVES_SURFACE boolean with an explicit RunnerSurfacePolicy: none, app-windows, observed-screen and resolved-modal. TypeScript and Swift both check it against one shared fixture. The host names the lit panel for app-windows and observed-screen, and the runner books an app window only for app-windows. ADR 0025 drops the drifted command lists and keeps the typed refusal contract, one sentence per rule, each linked to its owner or test. Follow-up to #4122 and #4189; independent of #4250. 11 files, no scope expansion.
Simplicity pass: the fixture is now a command→policy map. Parity is one assertion in the existing runner-command-traits.test.ts and one Swift XCTAssertEqual. The unconsumed unavailable panel-read variant (three reasons, no reader) is gone. Size: +347/−70 (net +277) → +170/−61 (net +109).
Validation
Head 67d90c8124: pnpm check:affected --run --head passed, exactCommit=true, unit suite included (run-4poRjw). The ADR-only commit follows d2de6a8702, where the evidence below was taken:
- iOS and macOS runner builds and the isolation scan passed. The Swift parity and read-only fixture tests pass on iPhone 17 Pro Max.
- Live, worktree CLI, iPhone Duo unfolded with the inner panel lit:
press 'label="Form"',fill,get text,snapshot -iandreadTextpassed in portrait, landscape-left and landscape-right.screenshot(669×951 lit panel) andrecord start/stopalso passed. iPhone 17 Pro Max single-panel snapshot and tap passed. Duo folded back; simulators shut down.
CI owns coverage, integration and device lanes.
🤖 Generated with Claude Code