cmux-next: continuity gate kills and freezes the daemon mid agent turn, times recovery, checks the recovery UI
The session continuity gate (#22187) killed the cmux-tui daemon only between turns. It didn't time the recovery, didn't look at what the app showed meanwhile, and never froze the daemon. This PR covers those cases.
Journey (scripts/cmux-next/restore-journey.py)
daemon: SIGKILL while an agent chat turn is in flight. The turn is the test agent'sgate:turn, which streams and then waits on a FIFO.- Rows give the seconds from the kill to a new daemon, to the app connected to it, and to restore settled.
- The turn must end (
end_turn) and its answer must show on the chat page.
daemon-stop(new): SIGSTOP the daemon, as a wedged owner.- The app must notice and offer Restart cmux-tui.
- Restart, on the button's path after its confirm, must start a new daemon, reconnect and bring every view back. Rows time each step.
- The stopped process is ended at the end, and at exit, if it's still there.
- Both variants sample
debug.daemonanddebug.surfacesevery 250 ms during recovery. The row fails if any of these happens:- a window shows neither its workspace nor the connecting view;
- a pane is blank;
- a shown terminal is disconnected without reconnecting for over a second.
--continuitynow runsquit,crash,daemon,daemon-stop,reboot. An explicit--variantsoverrides that list.
App (DEBUG builds only): debug.daemon reports:
- the local daemon's startup and connection state, and its pid;
DaemonRecovery'soffers_restart,is_restartingandrestart_failure;- per window, whether it shows workspace content or the connecting view.
{action: "restart"} runs DaemonRecovery.restart(), the same call the Restart button makes after its confirm. {action: "retry"} runs Retry Now.
Proof
Swift test (failing first, df6041feef6), on the fleet:
package-test-lane.sh suite Packages/macOS/CmuxNext DaemonRestartTests: RED_RESULT on the test commit, GREEN_RESULT on the head.
Runtime test: JOURNEY_RESULT
Review: REVIEW_RESULT
Observed / Not run
OBSERVED
Changelog
none
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Extends the session continuity gate to kill or freeze the cmux-tui daemon while an agent chat turn is in flight, timing each recovery step and checking what the app shows meanwhile.
Journey (scripts/cmux-next/restore-journey.py)
daemonkills mid turn: the turn streams, waits on a gate, and must end and show on its page after the reconnect.- New
daemon-stopvariant freezes the daemon instead; the app must offer Restart and restart through the button's path. - Both variants sample
debug.daemonanddebug.surfacesevery 250 ms: each window shows its workspace or connecting view, no pane is blank, every shown terminal stays connected/restoring/reconnecting, and neither call may go silent for over a second. --continuityrunsquit,crash,daemon,daemon-stop,reboot; an explicit--variantsoverrides the list.
Debug builds
debug.daemonlives inCmuxNextDaemonService(the app's size cap refused it) and reports the daemon's startup, connection, pid, recovery state, and per-window shows, omitting absent fields.{action: "restart"}runsDaemonRecovery.restart()on the button's confirm path;{action: "retry"}runs Retry Now.
Proof
Swift test covering the report and Restart/Retry paths (failing first), plus the runtime journey result: JOURNEY_RESULT. Review: REVIEW_RESULT.
Observed / Not run
OBSERVED
Changelog
none