test(cmux-next Home): the click harness no longer stops the test process's run loop (one-process CmuxNextAppTests exit 0 at ~44 s)
The one-process CmuxNextAppTests run (the PR job "cmux-next swift test") exits 0 partway through, with no Test run with summary, and most of its tests never run. That's the truncated "N tests never finished" runs other lanes see, and the reason suites that pass alone fail in the full run.
Cause: HomeOpenFocusesComposerTests.Harness.click queued its mouse-up with NSApp.postEvent(_:atStart:). AppKit's -[NSEvent _postAtStart:] calls CFRunLoopStop on the running loop to wake an event wait. In a swift-testing process, that loop is the outermost one: the async main runs CFRunLoopRun and calls exit(0) when it returns. The stop flag belongs to that outermost run level, so nested runs never clear it. At the test's next suspension the outer loop returns and the process exits.
Fix, test-first:
- Red, f77f0ae6:
aClickLeavesTheRunLoopItRanInRunningruns a click inside one pass of a private run-loop mode (so the pass runs nothing but the click) and expects the pass to end.finished, not.stopped. - Fix, 6bcebd46: the harness posts the mouse-up from a pass of its own private mode (
CFRunLoopPerformBlockplusCFRunLoopRunInModeoncom.cmuxterm.next.tests.post-event, then a wake). The stop ends only that pass. The event stays queued for the list's tracking loop and thenextEventdrain inclick.
Test-only: one file, +45/ā1. No new timer or observer: each private-mode pass runs once and returns as soon as its block has run (1 s and 5 s caps).
Adopted by composer-adopt (for composer-opus) for the stale-PR reconciler: rebased onto feat-cmux-next 3491d08c874. A Codex review asked for the detector to run in a private mode instead of the default mode, where other suites' main-actor jobs could run inside it.
Verification (fleet, scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext ..., Xcode 26.6)
- Red commit f77f0ae6,
HomeOpenFocusesComposerTests: fails,result ā CFRunLoopRunResult(rawValue: 2)) == (.finished ā ... 1), "the click stopped the run loop it ran in" (step 1b7472486ed041a8f68c3820). - Head 6bcebd46,
HomeOpenFocusesComposerTests: 2 of 2 pass; the detector returns in 0.7 s (step 2c52968f0d20513cbe9c8f62). - Base 3491d08c874, whole
CmuxNextAppTestsin one process:exit()fromswift_task_asyncMainDrainQueueright after this suite passes, at 29 s, 550 of 3,094 started tests finished, no summary (step 8a5fdb2eccb3b7277dace84b). - Head 6bcebd46, whole
CmuxNextAppTestsin one process: the process runs on past this suite (4,587 tests finished) until the 900 s hang watchdog stops it inClassicUpgrade*simulation tests, which this PR does not touch (step 82c5701a202c5ae9bdeeba52). An earlier run at the same head ended at 67 s with SIGTRAP while ~1,750 unrelated tests were in flight; it did not recur.
Observed / Not run
- Observed: the four fleet steps above;
cmux-next app compile (build fleet)green at the head; independent Codex review (gpt-6-astra, xhigh): SHIP at 6bcebd464e8d0f190f1b1e27a47683a582d4e326. - PR reds, none from this file: Script tests (
release-compile-derived-data.test.sh), release-notary and Guard status are red on base; the review-link, intent-warning and fast-gates post jobs failed on the GitHub installation's rate limit (fast gates themselves passed). - Not run: the PR's own
cmux-next swift testjob (queued when merged); the whole target to completion (at the head an unrelated hang in the ClassicUpgrade simulation tests stops it at 900 s; on base the process exits long before reaching them).
Risk: low (test harness only).
No capture: test-only change, no UI.
Changelog
none
Agent session: huge-blue
š¤ Generated with Claude Code