cmux-next: session continuity gate in the restore journey (agent chats, terminal agents; daemon crash, reboot)

Merged
TE
18d ago
+619-17

What

scripts/cmux-next/restore-journey.py becomes the session continuity gate. restore-journey-slot.sh JOB OUT -- --continuity runs it on a fleet capture slot (never on a laptop, never on a person's app).

It seeds:

  • agent chats with the test agent as a Claude Code harness (a non-default model picked) and as a Codex harness, two turns and an unsent draft each;
  • terminal tabs running claude and codex stand-ins (rj_fake_cli_agent.py), started with launch flags and their own account folder in CLAUDE_CONFIG_DIR / CODEX_HOME. They report SessionStart through the app's hook helper, the way the real hooks do. A stand-in started without its account prints Claude Code's "Not logged in".

Then four variants, each followed by checks that every session is back in its tab with its transcript, model, draft and flags, signed in, and answering a new turn:

  • quit: the Cmd-Q path.
  • crash: SIGKILL of the app.
  • daemon (new): SIGKILL of the app's cmux-tui daemon while the app keeps running. The app must start a new daemon and re-attach every view without input.
  • reboot (new): the quit, then SIGKILL of every process the app's bundle started, plus its terminal hosts and everything running in them.

The run also no longer depends on terminal line wrapping: the stand-ins log to a JSONL file and the journey reads that, not the screen.

Result on feat-cmux-next 5f64d5f (fleet build 07c0ce2d081a5e16815f6a7f, capture slot cmux-mac-mini-cua-5)

668 rows pass and 10 fail:

  • 8 rows, the reboot terminal agents. After a host loss, NEXT types claude --resume <id> / codex resume <id> without Enter and drops the launch flags and the account directory, so the agent is not running and a non-default account would be "Not logged in". Fix to follow, one PR.
  • 2 rows, agent.status ready -> idle. After a quit or crash, acpmux restarts with the app (its daemon pid changes on every quit), and one chat's agent process is sometimes not re-adopted. It answers again on the next message. This failure is intermittent.

Everything else passes in all four variants: chats (bound, harness, model, draft, transcript, live), terminal agents after quit, crash and daemon crash, and terminals re-attaching after a daemon crash.

Proof

Not UI: a test script and its stand-in; no app code changes.

Runtime test: restore-journey-slot.sh 07c0ce2d081a5e16815f6a7f OUT -- --continuity on fleet capture slot cmux-mac-mini-cua-5 with this branch's script (runs rj3-rj6 while developing; the final run gave the counts above). python3 -m py_compile on both scripts.

๐Ÿค– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

restore-journey.py becomes the session continuity gate: after a quit, crash, daemon crash, or reboot, seeded Claude and Codex agent chats and terminal agents must come back in their tabs with transcript, model, draft, and launch flags, signed in, and answering a new turn. Adds a --continuity mode to restore-journey-slot.sh plus a claude/codex CLI stand-in (rj_fake_cli_agent.py); the gate runs on a fleet capture slot, never on a laptop.

Two new variants are covered. daemon SIGKILLs the cmux-tui daemon while the app keeps running, which must start a new daemon and re-attach every view without input. reboot quits, then SIGKILLs every process the app's bundle started, including terminal hosts and their programs. The stand-ins log to a JSONL file the journey reads, so results no longer depend on terminal line wrapping.

Robustness

  • A reboot requires the running agent to be a newly resumed process, not one that outlived the reboot.
  • On reboot, kills only processes this app owns, matched by the hosts' --owner bundle id or by the bundle path (hosts run with a bare cmux-tui argv[0]).
  • Reconnects to acpmux after it is killed, retrying the connect itself; never resends a request that timed out.
  • Tolerates a half-written agent log line and closes the old socket before reconnecting.
  • Claude is seeded with an approval bypass, so its resumed session is checked to wait for a Return that confirms it; Codex resumes run by themselves.

Known failures (on feat-cmux-next 5f64d5f, 668 rows pass, 10 fail)

  • 8 reboot terminal agent rows: the app resumes claude/codex without Enter and drops the launch flags and account directory.
  • 2 agent.status ready โ†’ idle rows, intermittent: one chat's agent process is sometimes not re-adopted after a restart.