feat: ADR-0006 §8 step 6 — .snapshots/ gitignore + export + cleanup

The undo ring is local working state, handled at all three
project-file seams (R13):
- .gitignore template ignores /.snapshots/
- export excludes .snapshots/ (like playground.db / history.log)
- safely_delete_temp_project allowlists .snapshots/ so a temp that
  was modified then undone back to empty stays auto-deletable
- undo::SNAPSHOTS_DIR is now a pub const referenced by all three
- tests: gitignore content, export exclusion, cleanup allowlist

1693 passed / 0 failed / 1 ignored; clippy clean.
This commit is contained in:
claude@clouddev1
2026-05-24 20:53:00 +00:00
parent 25800e3eb5
commit d6c5674bf5
5 changed files with 56 additions and 4 deletions
+18
View File
@@ -494,6 +494,24 @@ fn safely_delete_allows_migration_backups_and_tmp_files() {
assert!(!path.exists());
}
#[test]
fn safely_delete_allows_undo_snapshot_ring() {
// A temp that was modified then undone back to empty can still
// carry the `.snapshots/` ring; it must remain auto-deletable
// (ADR-0006 Amendment 1).
let data = tempdir();
let project = project::open_or_create(None, Some(data.path())).unwrap();
let path = project.path().to_path_buf();
let snaps = path.join(".snapshots");
fs::create_dir_all(snaps.join("3")).unwrap();
fs::write(snaps.join("index.yaml"), "next_id: 4\nundo: []\nredo: []\n").unwrap();
fs::write(snaps.join("3").join("playground.db"), [0u8; 16]).unwrap();
drop(project);
safely_delete_temp_project(&path, data.path()).expect("should delete");
assert!(!path.exists());
}
#[cfg(unix)]
#[test]
fn safely_delete_refuses_symlink_top_level() {
+2
View File
@@ -43,6 +43,8 @@ fn no_args_creates_temp_project_under_data_root() {
// .gitignore must NOT include history.log (ADR-0007 amendment).
let gi = fs::read_to_string(path.join(GITIGNORE)).unwrap();
assert!(!gi.contains("history.log"));
// …but it must ignore the undo ring (ADR-0006 Amendment 1).
assert!(gi.contains("/.snapshots/"));
}
#[test]