refactor(move): own main-thread work in RunnerTests+MainThreadWork.swift
Summary
Pure move, no behavior change. runMainThreadWork, its work state, the busy/wedged state model, mainThreadExecutionTimeoutError, and their two unit tests leave the 2.9k-line RunnerTests+CommandExecution.swift for RunnerTests+MainThreadWork.swift. The suppression classifier test moves from RunnerTests+SnapshotCapturePlan.swift to UnitTests/RunnerTests+RecordedIssueSuppressionTests.swift, next to the other pure decision tests.
The one edit: mainThreadExecutionTimeoutError loses private, because its callers stay behind.
Base for #2621, whose reviewer asked for the move to ship apart from the fix. 4 files, +226/-212.
Validation
Tested commit 4c0f1ffa5 (rebased onto 465af7549; the rebase carried upstream's new reportsMainThreadBusy property into the moved enum). Earlier evidence at 169fdc2cd.
- iOS runner XCTest bundle builds; the moved tests pass on an iOS 26.2 simulator:
testRunMainThreadWorkExecutesOffMainCallerOnMainThread,testRunMainThreadWorkTimeoutMarksAbandonedUntilDrained,testSuppressedAxSnapshotIssueClassifier, plus the two busy/wedged dispatch tests that read the moved state. check:xctest-selectionstill reaches every declared test;check:packaged-runner-swiftparses all 46 files.- macOS host lane: CI only (unsigned bundle refused locally).
Conflict-resolution validation
Rebased onto 465af7549b; new head 889901395d. Preserved the upstream MainThreadBusyState.reportsMainThreadBusy property in the extracted module. The moved enum and helpers match current main. pnpm check:affected --run passed; iOS and macOS build-for-testing passed with unit tests enabled. New-head GitHub CI is pending.