| 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 | |
| 34 | pub mod paths; |
| 35 | pub mod prune; |
| 36 | pub mod repo; |
| 37 | |
| 38 | #[allow(unused_imports)] |
| 39 | pub use paths::{snapshot_dir_for, snapshot_git_dir}; |
| 40 | pub use prune::{DEFAULT_MAX_AGE, prune_older_than}; |
| 41 | #[allow(unused_imports)] |
| 42 | pub use repo::{Snapshot, SnapshotId, SnapshotRepo}; |
| 43 |