refactor(ios): bind surface geometry and synthesis orientation

Merged
TH
2d ago
+969-429

Summary

Bind Apple window, screen and digitizer coordinates to measured geometry. Preserve lit-display admission and refuse repeated presses after orientation changes, including 20-step and time-budget chunk boundaries, with completed-action disclosure and global indices.

37 files, +969/−429. Base is main at 7d42395ff7e1c03b643c2cf56683808bf5427cf3; the parent #4122 is merged as 0d5e5d6ae913deef546fbf1c75cfda3a94dd7513. ElementSearch and surface-policy layers remain held.

Validation

The branch is rebased onto current main. The rebase changed one file: main's #4187 renamed RunnerAlert.buttons to actions, so the alert test now reads alert.actions.first and keeps this branch's synthesis stub. Local git range-diff and per-file diff comparison against both the pre-rebase head and 2a775092b4e2934f4713c51999870a73194be075 report no lost hunk on either side.

At 2b9940af2a9e3e91c44e14535c026f96a2c2ac41 the local check:affected --run --head gate passed with exactCommit=true and checkoutChanged=false (receipt .tmp/validation/run-oXhSEW). Hosted coverage and integration checks are running at this head; draft smoke lanes stay skipped.

Device evidence, recorded in docs/evidence/surface-geometry-4189-2026-11-03.md:

Open limitation

The early windowQueryRejected route is now proved on a sole-display iPhone, iPhone 17 Pro, iOS 26.2, through back --in-app: the rejected applicationDefinedResizableWindows query short-circuits before any hit-test, the sole-screen marker is the only screen log, synthesis logs point=(32.2,84.0) referenceFrame=(0,0,402,874) interfaceOrientation=1 displayId=1, the navigation canary moves Liked posts: 0 to 1, and VISUAL_VERIFICATION changed=yes. Coordinate tap, hold and a sampled gesture pan deliver on the same window with fresh canaries. The probe is a natural rejection, not a patch: the heavy-feed snapshot exceeds the XCTest serializable depth, so the public query raises kAXErrorIllegalArgument while private AX still answers, which is why snapshots keep working. Confirmed only on that one simulator, device shape and feed shape; no foldable, physical device or scoped set, and not a global AX outage.

Default inner portrait refusal, scoped unsupported-device-scope and the new route are device-level limitations, not release blockers.

Earlier native proof and receipts remain attributed to fea9dbd85668d2d72be2f526eb350917c73f8d0d; prior b45 full gate, native methods, and live evidence retain their original attribution.