Skip to main content

zagens_runtime_adapters/snapshot/
mod.rs

1//! Workspace snapshots — pre/post-turn safety net.
2//!
3//! Each turn the engine takes a `pre-turn:<seq>` snapshot of the user's
4//! workspace into a side git repo at
5//! `~/.deepseek/snapshots/<project_hash>/<worktree_hash>/.git`, then a
6//! matching `post-turn:<seq>` snapshot when the turn finishes. Users
7//! can roll back via `/restore N` (slash command) or, when the model
8//! recognises an "undo my last edit" intent, the `revert_turn` tool.
9//!
10//! ## Why a side repo?
11//!
12//! - The user's own `.git` is never touched. `--git-dir` and
13//!   `--work-tree` are *always* set together when we shell out to git;
14//!   that single invariant is what keeps snapshots and the user's repo
15//!   completely independent.
16//! - Workspaces without git still get snapshots.
17//! - `git`'s own deduplication (object packfiles) keeps the disk
18//!   footprint tractable — typical 100 MB workspace × 12 turns ≈ 1.2 GB
19//!   uncompressed but git's content-addressed storage usually brings
20//!   that down 10-30×. We mitigate further with:
21//!     - 7-day default retention (`session_manager` prunes at session
22//!       start via [`prune::prune_older_than`]).
23//!     - `gc.auto = 0` on the side repo (we don't want background gcs
24//!       firing mid-turn) plus an explicit `git gc --prune=now` after
25//!       prune.
26//!
27//! ## Failure model
28//!
29//! Pre/post-turn snapshot calls are **non-fatal**. If `git` is missing,
30//! the disk is full, or the workspace is on a read-only filesystem, the
31//! turn proceeds and the engine logs a warning. The snapshot is a
32//! safety net, not a correctness gate.
33
34pub mod paths;
35pub mod prune;
36pub mod repo;
37pub mod size;
38
39#[allow(unused_imports)]
40pub use paths::{snapshot_dir_for, snapshot_git_dir};
41pub use prune::{DEFAULT_MAX_AGE, prune_older_than};
42#[allow(unused_imports)]
43pub use repo::{Snapshot, SnapshotId, SnapshotRepo};
44pub use size::{
45    DEFAULT_SNAPSHOT_MAX_WORKSPACE_GB, estimate_workspace_bytes, workspace_exceeds_size_limit,
46};