Background
V2 needs an explicit policy for pruning filesystem snapshots from disk. Today the legacy snapshot store writes Git tree objects under the per-project/worktree snapshot gitdir and runs git gc --prune=7.days on a background loop. That is age-based Git object cleanup, not reachability from durable session state.
If V2 stores snapshot hashes in session messages/revert metadata and sessions are indefinitely resumable from the database, Git does not know those DB references are live. A 7-day prune can therefore delete snapshot tree/blob objects that old-but-resumable sessions still need for diff/revert/undo.
Related prior evidence:
Question to settle
What guarantee should V2 make for snapshot-backed file history?
Options:
- Strong default: if a session is still in the DB and exposes snapshot-backed history, referenced snapshots remain available.
- Weak/cache default: old sessions remain resumable as chat, but old snapshot-backed file diff/revert/undo is best-effort and may disappear.
- Bounded default: snapshot history is retained for an explicit window/budget/session lifecycle, and the UI/API degrades clearly after that boundary.
Likely implementation direction if we choose the strong default
- Treat the DB/session tables as the source of live snapshot hashes.
- Add a
SnapshotGC/maintenance job that scans reachable snapshot hashes from session messages, parts, revert state, summaries, etc.
- Pin live hashes in the snapshot gitdir with Git refs so
git gc can preserve them.
- One possible shape: create a tiny commit pointing at the snapshot tree and update
refs/opencode/snapshots/<hash> to that commit.
- The DB can continue to store the original tree hash; the ref/commit is only a reachability pin.
- Remove pins for hashes no longer referenced by retained session state.
- Keep
git gc --prune=7.days or similar only as orphan cleanup / race grace, not as the semantic retention guarantee.
Things to decide
- Are all DB sessions considered retained forever, or do we have/need session archival/deletion semantics?
- Does compaction ever deliberately drop old file-history capability? If yes, it should remove snapshot references or mark them collectible.
- Should snapshot retention be user-configurable by age/size, and if so is that a weaker opt-in mode?
- What should the product show when a snapshot reference is missing: unavailable diff/revert, degraded resume, repair prompt, etc.?
- How do we migrate/handle existing snapshot hashes that may already be unpinned or missing?
Acceptance criteria
- V2 has a documented snapshot retention guarantee.
- The pruning job cannot collect snapshot objects still referenced by sessions under that guarantee.
- Orphaned/unreferenced snapshot objects are eventually reclaimable.
- Missing snapshot objects degrade explicitly rather than failing silently.
Background
V2 needs an explicit policy for pruning filesystem snapshots from disk. Today the legacy snapshot store writes Git tree objects under the per-project/worktree snapshot gitdir and runs
git gc --prune=7.dayson a background loop. That is age-based Git object cleanup, not reachability from durable session state.If V2 stores snapshot hashes in session messages/revert metadata and sessions are indefinitely resumable from the database, Git does not know those DB references are live. A 7-day prune can therefore delete snapshot tree/blob objects that old-but-resumable sessions still need for diff/revert/undo.
Related prior evidence:
git gc --prune=7.days, breaking review diffs.Question to settle
What guarantee should V2 make for snapshot-backed file history?
Options:
Likely implementation direction if we choose the strong default
SnapshotGC/maintenance job that scans reachable snapshot hashes from session messages, parts, revert state, summaries, etc.git gccan preserve them.refs/opencode/snapshots/<hash>to that commit.git gc --prune=7.daysor similar only as orphan cleanup / race grace, not as the semantic retention guarantee.Things to decide
Acceptance criteria