fix(cmux-next): keep next-turn pacer alive during tab replacement

Merged
TE
9d ago
+57-5

Summary

Opening a second agent tab while the first turn is starting could release the first AgentPaneNextTurnPacer while its next-turn task was queued, or while installTransport() synchronously replaced an unused default pacer. The pacer task now retains its owner until the flush completes, replaced pacers are released on the main actor with an explicit lifetime barrier, and this stateless pacer has executor-independent teardown. Regression tests cover both lifetimes.

Changelog

Fixed next-turn pacer lifetime during agent tab replacement.

Validation

  • Red before fix: fleet step f6cdd2fe938a7b95eae14034 on test-only commit c9e37c523183e6b3e38e541eb472da4e9603ddf6; AgentPaneHopOrderTests failed at aQueuedTurnKeepsItsPacerAliveUntilTheFlushCompletes because the weak pacer was already released.
  • Green focused run: fleet step 27667ca4fb9f35cc0a06167f on 51bbb6525426184c840433eae1c2c4a6c9fdd4de; all 4 AgentPaneHopOrderTests passed.
  • Green exact-head CI: cmux-next swift test passed on 1003995780c3530f6dfbe970950d943d616470fd.
  • Fleet compile-only build f978158e724d9d43a6c9e0e8 completed successfully on the exact head, including packaging and dependency readiness.
  • python3 scripts/verify-local.py: project, wiring, package groups, feature flags, and migration checks passed; localization is red on the current base with 27,573 pre-existing parity errors.

🤖 Generated with Claude Code