feat(screenshot): accept --crop-on on physical iOS devices
Summary
Accept screenshot --crop-on <selector> on physical iOS devices. Adds a measured geometry fixture and updates tests, help and documentation: 7 files. Refs #2276.
agent-device screenshot out.png --crop-on 'label="Continue"' --platform ios --udid "$UDID"
The ios-physical cell also admits physical iPadOS. No iPad, including Split View, was verified.
Validation
Retested unmodified 7ffc88bedf4dfe7459961e5a7d6dc3b0e8fdd130 on 2026-10-19: clean checkout, freshly rebuilt CLI, isolated daemon/session, normal CoreDevice capture route; no forced-runner patch.
Device: physical iPhone 12 (iPhone13,2), iOS 27.0.1 (24A446), Xcode 26.6 (17F113), wired. App: fiddl gallery. Snapshot viewport: 390×844 pt; 23 objects bounds: approximately (255.6667, 73.6667, 54.3333, 14.3333) pt.
From that checkout, with $UDID selecting the test phone:
node bin/agent-device.mjs screenshot crop.png --crop-on 'label="23 objects"' --platform ios --udid "$UDID" --session pr3839 --state-dir /private/tmp/ad-reverify-3839-state --json
xcrun devicectl device capture screenshot --device "$UDID" --destination raw.png
Both exited 0. The CLI returned success: true, width 163, height 43. Independent raw capture: 1170×2532.
Comparing decoded pixels against raw origin (767, 221): all 7,009 RGBA pixels identical, maximum channel difference 0, mean absolute RGB difference 0. Controls: one row down 8.0689; one crop-height down 21.9517. Best ±4 px offset: (0, 0).
Existing pnpm check:affected --run --head 7ffc88be receipt: passed, Node 22.20, exactCommit=true. GitHub-only/manual lanes were skipped, not passed.
This replaces the provisional base-plus-local-change evidence. The legacy xctest device backend remains unverified.