Skip to main content

Module resume_preflight

Module resume_preflight 

Source
Expand description

Answer “will this pane resume its conversation, or start a new one?” at pane-open time, before anything is spawned.

§Why this exists

The persistent controller spawns lazily, on the first message — so every signal that reports what actually happened to a resume (agentmux_session_outcome, session:resume_failed, SPEC_AGENT_PANE_HISTORY_ALIGNMENT_2026_08_05.md Part A) can only speak after the user has already typed. The lived experience that produces is the one this module exists to remove: the pane opens showing a long prior conversation, the user types into it, and only then does the transcript clear and announce a new session. The information was knowable the whole time; nothing asked for it.

§Why it can be known in advance

--resume <sid> fails for exactly one reason in practice: the session’s .jsonl isn’t under the CLAUDE_CONFIG_DIR the CLI is about to run with. That is a file-existence question, and session_backfill::session_is_reachable answers it using the same path scheme and the same home-dir expansion the spawn path itself uses. So the preflight is not a heuristic or a guess about CLI behaviour — it evaluates the same condition the CLI will, just earlier.

§Faithfulness to the real spawn path

preflight deliberately mirrors the decision sequence in persistent/spawn.rs and persistent/resume_retry.rs rather than modelling an idealized one, so its verdict and the eventual outcome can’t disagree:

Pane stateSpawn doesVerdict
sid held, transcript present--resume <sid> succeedsVerdict::Resume
sid held, transcript missing, another session on diskrejected → retry_after_resume_failure → find_recovery_session_id resumes that oneVerdict::Recover
sid held, transcript missing, nothing else on diskrejected → retry finds nothing → blankVerdict::Fresh
no sid, pane renders history whose session is reachablefirst spawn continues it (find_continuation_session_id)Verdict::Resume
no sid otherwisespawns with no --resume; no disk scan runs on this pathVerdict::Fresh
provider has no resume flagresume isn’t a concept hereVerdict::Unknown

The no-sid rows are the case docs/status/STATUS_CROSS_CHANNEL_RESUME_STALE_SESSION_ID_2026_08_20.md recorded: a pane opened in a new channel or version shows the agent’s whole prior conversation, but its spawn held no id. Since SPEC_DURABLE_CONVERSATION_MEMORY_2026_09_23.md §5 P0a the spawn continues the session of that rendered history. It still never scans the provider’s dir for some other session: one may be sitting there — Preflight::recoverable_session_id reports it when so — but “largest on disk” can be an archived conversation or a subagent’s, so it stays evidence, not a verdict.

Structs§

Preflight
The full answer, including the trail of how it was reached.
PreflightInput
Everything preflight needs, lifted out of block meta by the caller so this stays a pure-ish function over plain values (one is_file and at most one read_dir of a single directory — no store, no block, no RPC types).
Step
One line in the pane’s progress list while the preflight runs. Mirrors the launcher splash’s StageEntry row (crates/launcher/src/splash_core.rs) so the two read as the same idea in two places.

Enums§

Verdict
What will happen to this pane’s conversation on its next spawn.

Functions§

gate 🔒
The spawn’s resume gate (PersistentSubprocessController::apply_resume_gate_with), mirrored: a candidate that isn’t the chain head is redirected to the head when reachable here, else refused. None when the candidate stands.
preflight
Decide, without spawning anything, what the next spawn will do to this pane’s conversation. See the module doc for the mapping this mirrors.
step 🔒