M4: add durable named Save Points
A Save Point is a name for a story position, and restoring one is head movement. That is the whole architecture, and it is what ADR 012 and BUILD-MILESTONES' note on M4 asked for: M3 made the head a stored (branch, depth) and made arriving at one a row lookup plus a state restore, so a Save Point needs no restore machinery of its own. What the user gets: - Name the moment they are reading, keep playing, restart the app, and come back to it. Restoring moves the story back and deletes nothing: the later turns stay, Redo still walks forward into them, and writing something different is what starts a new line while the old one is kept. - Rename, delete, and a list, in a Save Points panel beside the branch panel, with a Save Point button next to Undo and Redo. Both confirmations say what is *not* destroyed, because that is the part the screen cannot show. - Save Points survive export and import. What was deliberately not built: - No second restore path. `head.move_to_node` is the only new movement: its depth half is M3's `head.move_to` unchanged, and its branch half is the single assignment `switch_branch` already makes. No head field is written in the checkpoint router, nothing reconstructs state, nothing prunes a memory, nothing copies or deletes a turn, and restore never forks — the first write below the restored head does, through `fork_if_behind_head`. - No automatic cleanup. A Save Point behind the head, or naming a line the story left, is doing its job (STORY-BRANCH-SEMANTICS §19). The one removal is a cascade: deleting a branch takes its Save Points, as it takes its memories, because the story they named went with it. - No new ADR. ADR 012 already decides the architecture, and a table is not a decision. The one call the planning package did not already make: restore moves the branch half of the head only when the coordinate is off the path being read. Doing it unconditionally would quietly hand back an abandoned continuation whenever a Save Point in a shared prefix was restored; never doing it would make a Save Point on a departed line unrestorable, which contradicts §19. TECHNICAL-DESIGN §8.8 records it. Schema: a `checkpoints` table holding a name, an optional note and a (branch, depth) coordinate — no copy of any story. `create_all` builds it as it did `memories` and `branches`; migration 80 adds the index. No backfill, because nobody had named a position before M4. The coordinate is deliberately not an action id: one coordinate holds every attempt at a turn and exactly one is live, so a coordinate follows a retry where a row id would pin a take the story no longer tells. Tests: 680 pass (638 before). 42 new in tests/test_save_points.py covering D11-D14, I04, L03, E-series lineage and memory isolation after restore and divergence, the edge cases, and an M3-database migration. One pre-existing fixture in test_tree_migration.py needed `checkpoints` added to its drop list — SQLite refuses to drop a table another table references. Not verified: the browser. No session has had a usable one, so the Save Point panel's DOM behaviour is unobserved — as M3's Redo control still is. The twenty-step sequence was driven over HTTP against a live server with a real process restart instead, and all seventeen checks pass. M4 is implemented, not accepted: no review has been written. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PWU4gTfLYY6Qq9U7aa9Qw2
This commit is contained in:
co-authored by
Claude Opus 5
parent
3c8e91f644
commit
e08d49c3eb
+36
-2
@@ -1,8 +1,42 @@
|
||||
# Planning Package Version
|
||||
|
||||
- **Package:** Adventure Storyteller Planning Package v2.4
|
||||
- **Package:** Adventure Storyteller Planning Package v2.5
|
||||
- **Revision date:** 2026-09-03
|
||||
- **Status:** Phase 0 complete; architecture selected; **Milestones M1, M2 and M3 implemented and accepted**; M4 is next to brief.
|
||||
- **Status:** Phase 0 complete; architecture selected; **Milestones M1, M2 and M3 implemented and accepted**; **M4 implemented 2026-09-03 and awaiting review.**
|
||||
|
||||
## v2.5 — M4 Implementation (2026-09-03)
|
||||
|
||||
M4 added durable named Save Points. This revision records only what the
|
||||
implementation established as fact; **no product requirement changed**, and the
|
||||
milestone is **not** marked accepted — its review has not been written.
|
||||
|
||||
- `TECHNICAL-DESIGN.md` gains **§8.8** and **§9.2**: the Save Point as a name
|
||||
plus a coordinate holding no story, restore as head movement with a bounds
|
||||
check, the rule that the branch half of the head moves only when the
|
||||
coordinate is off the path being read, restore never forking, and the bundle
|
||||
carrying Save Points independently of the head.
|
||||
- `DATA-MODEL.md` **§8** records the pointer as implemented — `(branch, depth)`
|
||||
rather than a turn id, with the reason: one coordinate holds every attempt at
|
||||
a turn and exactly one is live, so a coordinate follows a retry where a row id
|
||||
would pin a superseded take. **§29** records the checkpoints in the export.
|
||||
- `BUILD-MILESTONES.md` **M4** gains a status block: what shipped, the one
|
||||
architectural decision the milestone had to make and why it needed no new ADR,
|
||||
the test count, and the outstanding browser condition.
|
||||
- `README.md` describes Save Points as a user-facing capability.
|
||||
|
||||
**No ADR was created.** ADR 012 already decides the architecture M4 needed —
|
||||
restore reuses active-head movement — and a table is not a decision. The one
|
||||
question ADR 012 does not answer, whether restore moves the branch half of the
|
||||
head, is that same mechanism applied to a coordinate ADR 012 already defines;
|
||||
`TECHNICAL-DESIGN.md` §8.8 records the answer rather than a new ADR asserting it.
|
||||
|
||||
`SPECIFICATION.md`, `SECURITY-THREAT-MODEL.md`, `STORY-BRANCH-SEMANTICS.md` and
|
||||
`V1-ACCEPTANCE-TESTS.md` are unchanged. M4 altered no product requirement, added
|
||||
no outbound path, and implemented the checkpoint semantics
|
||||
`STORY-BRANCH-SEMANTICS.md` §18-25 already specified rather than amending them.
|
||||
|
||||
**The browser smoke test remains unperformed, now for both M3 and M4.** No
|
||||
session has had a usable browser. See `BUILD-MILESTONES.md` M3 and M4.
|
||||
|
||||
## v2.4 — Documentation Consolidation (2026-09-03)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user