fix(ios): press Open again when the runner watchdog abandons the launch-URL accept
TH
2h ago+675+675+012345678901234567890123456789-19-19-01234567890123456789
Summary
A freshly started runner can fail the "Open in" accept with MAIN_THREAD_TIMEOUT (typed details.runnerErrorCode) while the prompt stays up. open then failed with launch_confirmation_unanswered. Now it presses Open again, but only when the request's remaining time covers a whole press and its read: 2 × (1 s preflight + 10 s watchdog).
- The deadline gates only that re-press. The first press and every read keep main's bounds.
- Deadline: the enforced daemon deadline (batch, replay), otherwise the admitting transport's client-envelope end less the 30 s result margin. Nested attempts inherit their parent's; under an unbounded
testnothing is re-pressed. - Shared runner code: only the moved preflight constant and the typed timeout predicate.
Follow-ups: #4023 (runner-wide deadline), #4024 (bounded test-attempt deadline).
Fixes #3861
Validation
- Regression tests written first; each failed on its prior head. A first press with 5 s left is refused on
101a8cef38and sent now. index-launch-confirmation.test.ts: real alert legs and runner client; the verify read passes twoRUNNER_BUSYresends, then the second press lands.- Live, iPhone 17e (iOS 27.0), fresh schemes: one plain attempt accepted on the first press. Three attempts paused this simulator's SpringBoard 12 s after the accept: watchdog abandoned,
RUNNER_BUSYresends, drain, re-press (remainingMs36822/36533/33523), second pressok=1,launchConfirmation: "accepted", no alert left. Logs are in the review reply. iOS 17.5 not measured. pnpm check:affected --run --head e3fe452aed: all runnable checks passed (exactCommit).
🤖 Generated with Claude Code