fix(platform-apple): do not start an alert read the remaining budget cannot hold

PC
1d ago
+58-0

Fixes #4018

Root cause

awaitAppleAlert (and actOnAppleAlert) sleep ALERT_POLL_INTERVAL_MS after each ALERT_NOT_FOUND and start another read with remainingBudgetMs(...), which returns Math.max(1, remaining). Nothing checks that the remainder can hold a read, so the last read can get a few tens of ms. The runner answers it with a main-thread timeout, which is not a typed absence, so it is rethrown and the open --launch-url probe reports launchConfirmationProbeFailure: "alert-read" instead of "no alert".

Fix

After the sleep, if the remaining budget is below MIN_ALERT_READ_BUDGET_MS (500 ms), no further read is started: the window ends as "alert wait timed out" (wait) or with the last absence plus the fallback hint (act). Real read failures still propagate as themselves.

The 500 ms floor is a chosen value: nothing in the runner contract defines a minimum read time, so it is a single constant and easy to change if another value fits better.

Tests

Two new tests in packages/platform-apple/src/__tests__/alert.test.ts (wait and act, typed absences, fake timers; no read starts with under 500 ms). Both fail before the fix (2 red) and pass after; all of packages/platform-apple/src is green, and lint, oxfmt and tsc are clean.


This change was prepared with the assistance of an AI coding agent (Claude) and is submitted for human review.

🤖 Generated with Claude Code