fix(ios): keep the runner alive through hostile snapshots

Merged
OK
2mo ago
+602-329

Stacked on #2630 (pure move of the main-thread work machinery). Review this PR from its second commit.

Summary

On a live React Native feed (Bluesky Home) the iOS runner died after every snapshot: each next command paid an xcodebuild boot.

Cause: the query-sweep tier records 19 XCTest issues per capture worded Failed to resolve query: … kAXErrorIllegalArgument …. record(_:) only muted the sibling Failed to get matching snapshot wording, and XCTest ends testCommand once the main-thread block that recorded an unmuted failure returns.

Changes, on top of the move (7 files modified, 1 added):

  • Mute AX-server rejections in both fetch wordings; timeouts and Application X is not running keep recording.
  • One abandoned-main-thread-work counter: runMainThreadWork takes an operation label and logs abandon/drain. An abandoned viewport read or tree XPC now skips the query sweep: first hostile capture ~2.5 s instead of ~4.5 s. The tree slice timeout penalizes through its attempt outcome, so the warmup exemption applies.
  • Separate commit: a failed capture queues its cached-target drop behind abandoned work instead of waiting a second for it.
  • Docs: CHANGELOG, ADR 0004.

Validation

Tested commit ab34abc27 (rebased onto 465af7549). Earlier evidence at 7e2b10caf.

  • iOS runner XCTest suite: 243 tests, 0 failures. Both new tests fail on a copy with the fix reverted: 2 of 2 fail (4 assertions).
  • Live Bluesky feed through the runner path: 1 runner boot for 58 commands, 0 recorded XCTest failures. Before: one boot per hostile snapshot.
  • Local gates pass: format, lint, typecheck, xctest-selection, packaged-runner-swift, gate-manifest. pnpm check:affected --run: every runnable check passes except mutation-model (ownership.test.ts, "a kernel is owned by tests that reach it indirectly"), pre-existing on main: this branch changes no TypeScript.
  • macOS host lane: CI only (unsigned bundle refused locally).

Conflict-resolution validation

Rebased onto the updated #2630 extraction; new head 0bdf5a04a5. All three behavior/gate commits are unchanged by git range-diff. iOS and macOS build-for-testing passed with unit tests enabled. pnpm check:affected --run stopped at the pre-existing mutation-model assertion “a kernel is owned by tests that reach it indirectly” (scripts/mutation/ownership.test.ts:40); the same failure was reproduced on unchanged main 465af7549b. Earlier device evidence remains attributed to the earlier head; no new device run was performed. New-head GitHub CI is pending.