# Session Keep and Resume (https://jackin.tailrocks.com/roadmap/session-keep-and-resume/)



**Status**: Partially implemented — shipped baseline covers dirty/unsafe exit assessment with a rich exit dialog (return/keep/discard) and an optional file-level Inspect surface, durable per-instance host state, the "Unfinished jackin instances" restore picker, launch-recipe identity pins (role SHA, base image ref/digest, image tag), stopped-container `docker start` reconnect paths, and purge/prune machinery (terminal-status pruning, orphan-lock reaping, stale-`active` reconciliation). Remaining work is a "keep to resume" outcome for clean sessions, extending the per-workspace exit policy to clean exits, faithful recreate/rebuild tiers with full launch-recipe replay, socket-dir/sidecar rematerialization for the stopped-container restore path, launch-time index reconciliation (including the `failed_setup` mislabel after a host-level kill), and continuity-framed resume UX (Phase 2 — Live operator surface, [Agent Orchestration Program](/reference/research/agent-orchestration/program-research/)).

## Shipped facts [#shipped-facts]

A clean container exit already runs a real assessment: <RepoFile path="crates/jackin-isolation/src/finalize.rs">crates/jackin-isolation/src/finalize.rs</RepoFile> checks every isolated `worktree`/`clone` mount for uncommitted changes or unpushed commits, auto-deletes anything provably safe, and — when something is dirty/unpushed and the terminal is interactive — shows a rich exit dialog (`Return to agent` / `Exit and keep` / `Exit and clean up`) with an `I`-key Inspect surface that renders the full per-file diff for each preserved mount, not just a count. A per-workspace `dirty_exit_policy` config field (`ask` / `keep` / `discard`, versioned since config schema `v1alpha8`) already lets an operator skip the prompt entirely for dirty/unpushed exits.

Durable per-instance host state already survives `docker rm`: `~/.jackin/data/<container>/` holds the manifest, isolation records, every agent runtime's home (including plugins and auth slots), and the materialized worktree/clone trees. `resolve_restore_candidate()` in <RepoFile path="crates/jackin-runtime/src/runtime/launch.rs">crates/jackin-runtime/src/runtime/launch.rs</RepoFile> already presents a restore picker (currently labelled "Unfinished jackin instances") for `Crashed` / `PreservedDirty` / `PreservedUnpushed` / `RestoreAvailable` / `FailedSetup` instances, and `start_or_reconnect_capsule_client` in <RepoFile path="crates/jackin-runtime/src/runtime/attach.rs">crates/jackin-runtime/src/runtime/attach.rs</RepoFile> already calls `docker start` to reconnect a stopped-but-present container, used by both the hardline-attach path and the launch pipeline's `StartCurrentRole` restore resolution. The manifest also already carries launch-recipe identity fields — `image_tag`, `role_git_sha`, `base_image_ref`, `base_image_digest`, `role_source_git`/`role_source_ref`, and `DockerResources` — and the Tier 3 rebuild path already threads the pinned role SHA through when recreating a container whose image is gone.

The mirror-image cleanup path has also shipped: <RepoFile path="crates/jackin-runtime/src/runtime/cleanup.rs">crates/jackin-runtime/src/runtime/cleanup.rs</RepoFile> routes terminal statuses (`CleanExited`, `Superseded`, `FailedSetup`, `Purged`) through `purge_container_filesystem` (data dir, socket dir, sibling lock file) and `InstanceIndex::remove_many`, and `prune_instances` reconciles stale `active` rows whose container no longer exists down to `Crashed` and reaps orphaned name-claim lock files. None of this runs automatically from the live exit/launch flow yet — it is all reachable only through the manual `jackin prune instances` command today.

A detailed design write-up — problem narrative, TUI mockups for the exit/resume screens, the full restore-tier ladder, the launch-recipe field table, and the audited findings this status line summarizes — lives in [Session Keep and Resume Design](/reference/research/agent-orchestration/recovery/session-keep-and-resume-design/).

## Remaining work [#remaining-work]

1. **A "keep to resume" outcome for clean sessions.** `finalize_clean_exit` returns `Cleaned` immediately whenever no mount is dirty/unpushed — this happens even under `dirty_exit_policy = keep`, since that policy is only consulted after the dirty/unpushed check. `CleanExited` also is not a restore candidate (`is_restore_candidate()` excludes it). A clean session has no way to say "keep this for tomorrow."
2. **Extend the exit policy to clean exits, not just dirty ones.** The existing `dirty_exit_policy` field (`ask`/`keep`/`discard`) is the natural home for the proposed `ask`/`keep`/`clean` per-workspace policy — reuse it rather than adding a parallel setting. Whether this needs a new config schema version (new variant, new field) or is a pure behavior change to the already-migrated field needs to be settled before implementation.
3. **Continuity-framed restore UX.** Reframe the restore picker from "Unfinished jackin instances" to a resume/continuity framing, and include kept-clean instances alongside dirty/unpushed ones.
4. **Full launch-recipe replay for recreate/rebuild tiers.** The manifest stores role SHA and base image ref/digest, but the mount plan, env-var names + source refs, and Docker run shape are not yet captured or replayed on Tier 2/3 restore — those tiers still re-resolve from current config instead of the launch-time snapshot.
5. **Socket-dir and sidecar rematerialization for the stopped-container restore path.** `start_or_reconnect_capsule_client` calls `docker start` but never re-writes `/jackin/run/agent.toml` into the socket dir or re-checks `-dind` sidecar health first — only a fresh `docker run` currently writes `agent.toml`.
6. **Launch-time index reconciliation.** The stale-`active`-row reconciliation in `prune_instances` needs to also run on launch/console flows, not only the manual prune command, so restore decisions are made against accurate state.
7. **Honest status for host-level kills.** A daemon/VM crash currently mislabels every killed session `failed_setup`; there is no distinct status for "killed by host" versus "setup actually failed."
8. **Unpushed-branch detail and a required acknowledge step.** The exit dialog's Inspect surface already shows full file diffs; it still doesn't surface the unpushed branch name/ahead-count, and reviewing it is optional rather than required before Keep/Discard.
9. **Clone-specific assessment tests and cleanup.** `force_cleanup_clone` is `rm -rf` only, and the dirty/unpushed assessment path has no clone-specific test coverage alongside the worktree tests.
10. **In-place bind sessions.** A session with a direct host bind (no worktree/clone isolation) still orphans its home on clean exit; the exit/resume flow needs a "skip mount verification, still keep-to-resume the home" path for this class.
11. **Stale doc reference.** `finalize.rs` cites a `worktree-cleanup-assessment.mdx` that does not exist; fold the cited policy table into a real doc and fix the reference.
12. **Operator docs.** Once the above lands, document the resume flow in operator-facing guides without leaking internal paths or Rust names.

## Out of scope [#out-of-scope]

* The immutable-snapshot / undo-to-pre-launch-state model — that is the opposite direction, tracked separately in [Session snapshot and rollback](/roadmap/session-snapshot-rollback/).
* In-container agent session log resumption (e.g. `claude --resume` after a Tier 2/3 rebuild) — overlaps [Console agent session control](/roadmap/console-agent-session-control/) Phase 4 and should be scoped there.

## Related work [#related-work]

* [Session Keep and Resume Design](/reference/research/agent-orchestration/recovery/session-keep-and-resume-design/) — full design notes, TUI mockups, restore-tier ladder, and audit findings.
* [Launch Progress TUI](/roadmap/launch-progress-tui/) — the rich surface the exit cockpit and resume picker render into.
* [Console agent session control](/roadmap/console-agent-session-control/) — instance discovery and the selection surface; Phase 4 session reconciliation is the in-container continuity counterpart.
* [Session snapshot and rollback](/roadmap/session-snapshot-rollback/) — the orthogonal direction: *undo* a session back to its pre-launch host state, where this item *resumes* a session forward to continue it.
* [Déjà Vu](/reference/research/agent-orchestration/conversation-capture/deja-vu/) — the backstop for "never lose valuable context": even when a session is unrecoverable, the cross-agent conversation archive survives instance teardown.
* [Runtime Instance Model](/reference/runtime/runtime-instance-model/) — the per-instance host layout this item rebinds on resume.
