fix(apple): recover runner snapshot bridge after a wedge or restart

Merged
TH
11h ago
+502-76

Summary

Retire a runner's snapshot bridge when an abandoned reader remains blocked for five seconds. Each runner session owns its circuit and target cache, so a replacement retries the bridge and late failures cannot retire the replacement's generations. Session-scoped refusals retain their scope in warnings and diagnostics. Fixes #4241.

15 files changed across the runner bridge, routing, tests, refusal fixture, and ADR.

Validation

Base: b42c7c265f0765045b1ce5c53dd426512e11108d. Head: e25fef03950b54543ca29a71fbfaede8f4586cd4.

  • Original regression tests failed on base and passed at 4e78ccc; the updated focused suites pass at this head (84 tests).
  • Xcode 26.2 iOS Simulator native test passed: abandoned → in-flight before five seconds → wedged at five seconds → admitted after release. The reader was held on a semaphore and the clock was controlled.
  • pnpm check:affected --run --head e25fef03950b54543ca29a71fbfaede8f4586cd4 passed: run-pvhLTv, exactCommit=true, checkoutChanged=false. Coverage and native/device lanes remain GitHub-owned or skipped; provider integration was deduplicated against related tests.

Live evidence: on Limrun iOS at e25fef0395, a real bridge-read-abandoned refusal (triggered by a 1 ms budget) retired the generation. After the runner was replaced through stopIosRunnerSession, the route logged the session change and served simulator-ax-bridge for the same app generation with no warning. The PR comment has the details. No data shows finite remote reads crossing 5 s: no Limrun run has returned an abandoned, deadline, or wedged refusal without fault injection.