docs: ADR-0006 §8 step 8 — mark undo/snapshot implemented
- requirements.md U1/U2: [ ] -> [x] with implementation notes - CLAUDE.md Safety bullet: implemented; drop U-series from the deliberately-deferred list - ADR-0006 Amendment 1: "not yet implemented" -> implemented, plus an Implementation note (index.yaml, source-gated snapshots, non-fatal snapshot-failure policy, batch primitive, testing + accepted gaps) - ADR README index: undo/snapshot half marked implemented
This commit is contained in:
@@ -96,8 +96,8 @@ implementation, and **supersedes the original Decision's
|
||||
"snapshots only before destructive operations" model** and its
|
||||
confirmation rationale. Written with explicit user approval; the
|
||||
implementation plan is `docs/plans/20260524-adr-0006-undo-snapshots.md`.
|
||||
**Not yet implemented** at the time of writing — this records the
|
||||
agreed design.
|
||||
**Implemented 2026-05-24** (see the Implementation note at the end of
|
||||
this amendment).
|
||||
|
||||
### Snapshot scope — every mutation (single-step undo)
|
||||
|
||||
@@ -207,3 +207,39 @@ is turned off. CLI-only for v1 (no in-app toggle).
|
||||
- The Phase-3 N/A matrix row ("auto-snapshot fires for SQL DML the same
|
||||
as DSL") becomes non-vacuous: the snapshot hook lives in the worker
|
||||
dispatch and covers DSL and SQL mutations uniformly.
|
||||
|
||||
### Implementation note (2026-05-24)
|
||||
|
||||
Shipped across §8 steps 1–7 of the plan. Details and decisions made
|
||||
during implementation, user-confirmed where they extended the design:
|
||||
|
||||
- **Ring storage** is `src/undo.rs` (`SnapshotStore`): per-snapshot
|
||||
payload dirs under `<project>/.snapshots/<id>/` plus an
|
||||
**`index.yaml`** manifest (YAML reuses the existing `serde_yml`
|
||||
dependency — no `serde_json` added). Monotonic ids, reconciled
|
||||
against on-disk dirs so a crash can't reuse one; `cleanup()` on
|
||||
open sweeps `.staging/` and orphan payloads.
|
||||
- **Worker hook**: `snapshot_then` brackets all 19 mutating dispatch
|
||||
arms in `src/db.rs` (stage → run → finalise/discard); restore
|
||||
(undo/redo) runs in `worker_loop` with `&mut Connection`. Snapshots
|
||||
are **gated on a user command `source`** — internal operations that
|
||||
pass `source = None` (notably the open-time rebuild when `.db` is
|
||||
missing) are not recorded, so `rebuild` is undoable as a user
|
||||
command but opening a project never creates a spurious entry.
|
||||
- **Snapshot-failure policy** (user-confirmed): staging / finalise /
|
||||
discard failures are **non-fatal** (logged) — the real persistence
|
||||
is the durable state and a backup hiccup must not fail the user's
|
||||
work. Only *restore* failures surface (as `UndoFailed`).
|
||||
- **Batch** uses `BeginBatch`/`EndBatch` worker requests; `replay`
|
||||
wraps its loop so a multi-command replay is one undo step,
|
||||
finalised only if a mutation committed.
|
||||
- **Testing**: `src/undo.rs` Tier-1 (ring/redo/eviction/restore),
|
||||
`tests/undo_snapshots.rs` Tier-3 (worker, DSL+SQL, db+csv
|
||||
consistency, persistence across reopen), plus App-level Tier-1
|
||||
(dispatch/modal) and parse/replay-filter tests. The thin runtime
|
||||
glue (`spawn_prepare_undo` / `spawn_undo` + Action arms) is not
|
||||
loop-tested — the same accepted gap recorded for ADR-0034, with the
|
||||
App side and worker side each tested. No Tier-2 insta render test
|
||||
was added for the confirmation modal: the existing modals
|
||||
(`rebuild` / path / load) are tested at the state level only, and
|
||||
the undo modal matches that.
|
||||
|
||||
Reference in New Issue
Block a user