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:
@@ -63,9 +63,9 @@ Current decisions at a glance (each backed by an ADR):
|
||||
(U1/U2): `undo` / `redo` app commands (no sigil) with auto-snapshot
|
||||
before **every** mutation into a persisted N=50 ring; hybrid
|
||||
whole-project snapshot (db backup API + yaml/csv copy); `--no-undo`
|
||||
to disable (ADR-0006 **Amendment 1**). *(Designed + amended +
|
||||
planned in `docs/plans/20260524-adr-0006-undo-snapshots.md`; not
|
||||
yet implemented.)*
|
||||
to disable (ADR-0006 **Amendment 1**). *(Implemented 2026-05-24 —
|
||||
`src/undo.rs` ring + worker hook in `src/db.rs`; one undo step per
|
||||
user command, batch ops collapse to one, `import` excluded.)*
|
||||
- **Sharing:** `export` command produces a zip without the `.db`;
|
||||
no hosted publishing (ADR-0007).
|
||||
- **Testing:** four-tier strategy from `cargo test` units up to
|
||||
@@ -203,8 +203,6 @@ not yet implemented:
|
||||
- **Strong syntax-help in parse errors** (H1a): point users at
|
||||
missing keywords/clauses rather than the unexpected
|
||||
character.
|
||||
- **Snapshot/replay/undo** (U-series): designed in ADR-0006;
|
||||
not yet implemented.
|
||||
- **Tutorial/lesson system**: acknowledged as in scope for
|
||||
design; needs its own ADR.
|
||||
- **Session log + Markdown export** (V4): the bigger UX
|
||||
|
||||
@@ -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.
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ This directory contains the project's ADRs, recorded per
|
||||
- [ADR-0003 — Input modes and command dispatch](0003-input-modes-and-command-dispatch.md)
|
||||
- [ADR-0004 — Project file format](0004-project-file-format.md)
|
||||
- [ADR-0005 — Column type vocabulary](0005-column-type-vocabulary.md)
|
||||
- [ADR-0006 — Undo snapshots and replay log](0006-undo-snapshots-and-replay-log.md) — **Accepted**. The **replay/journal half** (U3/U4) shipped via ADR-0034; the **undo/snapshot half** (U1/U2) is settled by **Amendment 1 (2026-05-24)** but **not yet implemented** (plan: `docs/plans/20260524-adr-0006-undo-snapshots.md`). Amendment 1 **supersedes the original "snapshots only before destructive operations" model**: a snapshot is taken before **every** data/schema mutation (DSL + SQL) for familiar single-step (Ctrl-Z) undo — so the confirmation collapses to *naming the one command being undone* (no db-diff). Snapshot is a **hybrid whole-project copy** — database via the online backup API **plus** `project.yaml`/`data/*.csv` as files — reconciling this ADR with ADR-0015's "text is authoritative, db is derived"; undo restores all three directly. Staged before the mutation's transaction, finalised after the db commit (preserves ADR-0015 §6 commit-db-last); rolled-back ops leave no snapshot. **Persisted** ring under `.snapshots/`, **N = 50** (raised from 10), git-ignored + export-excluded + temp-cleanup-aware. `redo` supported, **redo stack discarded on new work**. **Batch ops record one undo step** (`replay` + future batch via a Begin/EndBatch worker primitive); **`import` is outside undo** (it switches projects per ADR-0015 §11, leaving the current project untouched). A **`--no-undo` CLI flag** disables snapshotting (hardware escape hatch). Adds the `backup` feature to `rusqlite`
|
||||
- [ADR-0006 — Undo snapshots and replay log](0006-undo-snapshots-and-replay-log.md) — **Accepted**. The **replay/journal half** (U3/U4) shipped via ADR-0034; the **undo/snapshot half** (U1/U2) is settled by **Amendment 1 (2026-05-24)** and **implemented 2026-05-24** (plan: `docs/plans/20260524-adr-0006-undo-snapshots.md`; ring in `src/undo.rs`, worker hook in `src/db.rs`). Amendment 1 **supersedes the original "snapshots only before destructive operations" model**: a snapshot is taken before **every** data/schema mutation (DSL + SQL) for familiar single-step (Ctrl-Z) undo — so the confirmation collapses to *naming the one command being undone* (no db-diff). Snapshot is a **hybrid whole-project copy** — database via the online backup API **plus** `project.yaml`/`data/*.csv` as files — reconciling this ADR with ADR-0015's "text is authoritative, db is derived"; undo restores all three directly. Staged before the mutation's transaction, finalised after the db commit (preserves ADR-0015 §6 commit-db-last); rolled-back ops leave no snapshot. **Persisted** ring under `.snapshots/`, **N = 50** (raised from 10), git-ignored + export-excluded + temp-cleanup-aware. `redo` supported, **redo stack discarded on new work**. **Batch ops record one undo step** (`replay` + future batch via a Begin/EndBatch worker primitive); **`import` is outside undo** (it switches projects per ADR-0015 §11, leaving the current project untouched). A **`--no-undo` CLI flag** disables snapshotting (hardware escape hatch). Adds the `backup` feature to `rusqlite`
|
||||
- [ADR-0007 — Sharing and export](0007-sharing-and-export.md)
|
||||
- [ADR-0008 — Testing approach](0008-testing-approach.md)
|
||||
- [ADR-0009 — DSL command syntax conventions](0009-dsl-command-syntax-conventions.md)
|
||||
|
||||
+12
-7
@@ -365,7 +365,7 @@ handoff-14 cleanup; 449 after B2/C2.)
|
||||
|
||||
## Undo and replay (per ADR-0006)
|
||||
|
||||
- [ ] **U1** Auto-snapshot before **every** data/schema mutation
|
||||
- [x] **U1** Auto-snapshot before **every** data/schema mutation
|
||||
(DSL + SQL) into a persisted ring buffer (size N=50, tunable),
|
||||
per ADR-0006 Amendment 1 (single-step undo, superseding the
|
||||
original destructive-only model). Snapshot is a hybrid
|
||||
@@ -374,14 +374,19 @@ handoff-14 cleanup; 449 after B2/C2.)
|
||||
finalised after the db commit (preserves ADR-0015 §6). A batch
|
||||
command (`replay` / future batch ops) records one boundary
|
||||
snapshot; `import` takes none. A `--no-undo` CLI flag disables
|
||||
snapshotting. *(Designed + amended + planned in
|
||||
`docs/plans/20260524-adr-0006-undo-snapshots.md`; not yet
|
||||
implemented.)*
|
||||
- [ ] **U2** `undo` restores the most recent snapshot (database +
|
||||
snapshotting. *(Implemented 2026-05-24, plan
|
||||
`docs/plans/20260524-adr-0006-undo-snapshots.md`: `src/undo.rs`
|
||||
ring + worker dispatch hook in `src/db.rs`; snapshots gated on a
|
||||
user command `source` so internal ops like open-time rebuild are
|
||||
not recorded; snapshot-bookkeeping failures are non-fatal, restore
|
||||
failures surface.)*
|
||||
- [x] **U2** `undo` restores the most recent snapshot (database +
|
||||
text, directly); `redo` re-applies (redo stack discarded on new
|
||||
work); both prompt for confirmation naming the command being
|
||||
undone / re-applied (`Y` confirms). *(Designed + amended; not yet
|
||||
implemented — see U1's plan.)*
|
||||
undone / re-applied (`Y` confirms). *(Implemented 2026-05-24:
|
||||
`undo` / `redo` app commands, `Modal::UndoConfirm`, runtime
|
||||
prepare→confirm→restore→refresh; `--no-undo` reports undo is off,
|
||||
empty stacks report "nothing to undo/redo".)*
|
||||
- [x] **U3** `history.log` records every submitted command in
|
||||
append-only form, tagged with its outcome (Iteration 2;
|
||||
broadened by ADR-0034). Format: `<ISO-8601 Z>|<status>|<source>`
|
||||
|
||||
Reference in New Issue
Block a user