Closes M4. The review's three findings are fixed, the durability rule the specification always implied is now enforced, and M3's and M4's browser behaviour has been verified in a real browser for the first time. B-1 -- the Save Point list was an N+1 that loaded whole Action rows, narration included, to answer "does a row exist here". It is now one bulk two-column coordinate query plus one lineage: 53 SELECTs for 25 Save Points became 5, and the count no longer grows with the list. The clause is an OR of exact (branch, depth) pairs rather than two IN lists, because the cross product would report a Save Point resolved on the strength of another one's depth existing on this one's branch. A test builds exactly that trap. B-2 -- reclassified during closeout from "missing warning" to a behaviour defect, and fixed as one. STORY-BRANCH-SEMANTICS §19 says a named checkpoint remains until explicitly deleted, and §28 already required future cleanup to retain checkpoint-referenced paths; a cascade that silently removed Save Points with a branch violated both, and a warning would only have documented the violation. A branch a Save Point names can no longer be deleted. The request is refused with the offending Save Points named, the user deletes them explicitly -- which deletes no story -- and the branch then goes. The scope is the subtree, because deleting a branch takes its descendants. Both delete controls disable and explain. Recorded as a new §19.1; models.py, TECHNICAL-DESIGN §8.8 and DATA-MODEL §8 had all recorded the cascade as the rule and now record the refusal. An earlier pass in this same closeout had kept the cascade and added a warning. That was the wrong fix and its tests were replaced rather than left standing, since they pinned the defect. B-3 -- the D11/L03 automation never left one process, so it could not distinguish durable state from a live Python object. It now spawns real server processes, kills the first, and reads the campaign back with the second. C-5 -- creating a Save Point takes the campaign's turn lock. "Save where I am" has to name one committed position, and the head is what a turn in flight is about to move. Rename and Delete deliberately do not take it. The architecture is untouched: a Save Point is still name + note + (branch, depth), and restore is still coordinate -> head.move_to_node -> head.move_to -> attempts.restore_state. No second restore path, no state copied into a checkpoint, no fork on restore. Browser verification -- the first in this project, and it covers both milestones. Firefox 154.0.1 through geckodriver over the W3C WebDriver protocol, driving the rendered DOM: 47/47 checks, twice, on independent databases, no console errors. M3's Undo/Redo enable states, transcript movement, Retry and the take pager, divergence retiring Redo; M4's whole Save Point lifecycle, both confirmations, and the new branch-delete refusal including its recovery. No dependency was added: the WebDriver client is stdlib HTTP. No application defect was found by the browser. Four failures occurred, all in the harness -- a wrong SPA route, a wait comparing transcript length when the empty-story placeholder is longer than the first turn, a fixture deleting the branch it was reading, and a reload assertion that sampled once instead of waiting. The last was checked against the app before being called a harness bug. Tests: 698 backend pass (was 680), 60 M4, 94 M3 history, 66 export/ migrations, 93 security/local-only. Frontend lint and build clean, Docker build clean, loopback binding unchanged. No assertion weakened, no skip added. Planning: STORY-BRANCH-SEMANTICS §19.1 is the only behavioural change and it strengthens §19. V1-ACCEPTANCE-TESTS records D11-D14, I04, L03 and the E-series, keeping automated, live-runtime and browser evidence distinct, and weakens no pass condition. DATA-MODEL records the coordinate with the retry measurement that settles it. BROWSER-UX-SPEC rules for Moment over Turn. BUILD-MILESTONES marks M4 COMPLETE, closes M3's browser condition, and lists what M5 inherits. VERSION adds v2.6. No new ADR: ADR 005 already decides that history is preserved rather than overwritten, and §19.1 is that decision applied to checkpoint-referenced history. M4 is closed. M5 may now be briefed; it has not been started. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PWU4gTfLYY6Qq9U7aa9Qw2
983 lines
27 KiB
Markdown
983 lines
27 KiB
Markdown
# Adventure Storyteller — Story Branch Semantics
|
|
|
|
**Status:** v1.0 — behavior confirmed after Phase 0B
|
|
**Purpose:** Define exactly how Undo, Redo, Retry, Edit, Restore, checkpoints, and abandoned history should behave.
|
|
|
|
## 1. Design Goal
|
|
|
|
The user experience should remain simple.
|
|
|
|
The user should not need to think in terms of Git branches, tree structures, or database lineage during normal storytelling.
|
|
|
|
The primary controls should be:
|
|
|
|
- Undo
|
|
- Redo
|
|
- Retry
|
|
- Edit
|
|
- Save Checkpoint
|
|
- Restore Checkpoint
|
|
|
|
Internally, however, the system should preserve enough history to make these operations safe, reversible, and state-consistent.
|
|
|
|
The core rule is:
|
|
|
|
> User-facing history should feel like normal Undo/Redo, while internal history may use branch-like lineage to avoid destructive edits.
|
|
|
|
## 2. User-Facing Philosophy
|
|
|
|
### 2.1 Branching is an implementation detail
|
|
|
|
The normal UI should not require explicit actions such as:
|
|
|
|
- Create Branch
|
|
- Switch Branch
|
|
- Merge Branch
|
|
- Compare Branches
|
|
|
|
Those concepts may exist internally.
|
|
|
|
The user should instead see familiar operations.
|
|
|
|
### 2.2 Abandoned history is retained but disposable
|
|
|
|
When the user goes backward and continues differently:
|
|
|
|
- the original future should not be immediately deleted,
|
|
- it should be marked as abandoned/disposable,
|
|
- it should no longer appear as the active story,
|
|
- it may be pruned later by a future cleanup feature,
|
|
- it may optionally become recoverable through a future discarded-history screen.
|
|
|
|
No automatic cleanup policy is required for v1.
|
|
|
|
### 2.3 Named checkpoints are intentionally durable
|
|
|
|
A named checkpoint is different from ordinary undo history.
|
|
|
|
Named checkpoints remain until explicitly deleted.
|
|
|
|
## 3. Definitions
|
|
|
|
### Active History
|
|
The currently selected sequence of accepted turns from campaign root to the current head.
|
|
|
|
### Story Head
|
|
The current endpoint of active history.
|
|
|
|
### Abandoned History
|
|
Previously accepted turns that are no longer part of the active continuation because the user undid, restored, edited, or retried and then continued differently.
|
|
|
|
### Disposable History
|
|
Abandoned history that is retained for safety/recovery but may be eligible for future cleanup.
|
|
|
|
### Named Checkpoint
|
|
A durable user-created pointer to a specific accepted story position.
|
|
|
|
### Alternate Take
|
|
A different narrator response to the same user input.
|
|
|
|
### Divergence
|
|
The point where active story history begins following a different continuation than previously accepted history.
|
|
|
|
## 4. Undo
|
|
|
|
Undo moves the active story head backward by one accepted story step.
|
|
|
|
Example:
|
|
|
|
```text
|
|
Turn 47
|
|
You enter the tavern.
|
|
|
|
Turn 48
|
|
You accuse Mara of stealing the key.
|
|
|
|
Turn 49
|
|
Mara draws a knife.
|
|
```
|
|
|
|
After one Undo:
|
|
|
|
```text
|
|
Active head: Turn 48
|
|
Redo candidate: Turn 49
|
|
```
|
|
|
|
After two Undos:
|
|
|
|
```text
|
|
Active head: Turn 47
|
|
Redo candidate: Turn 48
|
|
```
|
|
|
|
## 5. Undo Depth
|
|
|
|
Preferred behavior:
|
|
|
|
> Unlimited Undo across retained campaign history.
|
|
|
|
If the selected base architecture makes unlimited Undo substantially harder or unsafe, the minimum acceptable behavior is:
|
|
|
|
> At least five consecutive Undo operations.
|
|
|
|
Phase 0B demonstrated repeated non-destructive Undo well beyond the minimum five-step requirement. The selected head-cursor design should therefore support Undo across retained active-lineage history up to the root unless a later implementation defect forces a documented exception.
|
|
|
|
### Undo crosses fork points (settled in M3)
|
|
|
|
Undo continues backward through story a branch **inherited** from the line it
|
|
forked from, up to the campaign opening. It does not stop at the fork.
|
|
|
|
This reverses the behavior of the pre-M3 base, and the reversal follows from the
|
|
history model rather than from a change of mind about the product. Undo used to
|
|
delete the turns it stepped over, and the turns before a fork belong to the
|
|
parent line's story as well, so refusing at the fork was the only way to stop
|
|
one line's Undo from destroying story another line was still telling. Undo now
|
|
moves the reading position and deletes nothing, so there is nothing to protect
|
|
the parent from: a forked story includes the story it was forked out of, and
|
|
walking back through it is a reader moving backward, not a branch reaching into
|
|
another branch's history.
|
|
|
|
The only floor is the campaign opening. There is no pre-campaign position to
|
|
reach, and Undo at the opening reports that there is nothing to undo.
|
|
|
|
One consequence is worth stating plainly for anyone reading a transcript: a
|
|
single Undo on a forked story can step back over a turn that was originally
|
|
written on the line it forked from. Nothing about that turn changes; it simply
|
|
stops being part of what is currently being told.
|
|
|
|
## 6. State Restoration on Undo
|
|
|
|
Undo must restore more than visible transcript text.
|
|
|
|
When moving the story head backward, the system must restore the corresponding:
|
|
|
|
- authoritative narrative state,
|
|
- current location,
|
|
- entity states,
|
|
- relationships,
|
|
- facts,
|
|
- active story threads,
|
|
- scene state,
|
|
- summary lineage,
|
|
- memory lineage,
|
|
- relevant prompt/retrieval lineage.
|
|
|
|
The system must not leave current state from a later turn attached to an earlier transcript position.
|
|
|
|
## 7. Redo
|
|
|
|
Redo moves forward along the previously active continuation after Undo.
|
|
|
|
Example:
|
|
|
|
```text
|
|
47 -> 48 -> 49
|
|
```
|
|
|
|
User undoes to 47:
|
|
|
|
```text
|
|
Active: 47
|
|
Redo path: 48 -> 49
|
|
```
|
|
|
|
Pressing Redo restores 48.
|
|
|
|
Pressing Redo again restores 49.
|
|
|
|
## 8. Redo Invalidation
|
|
|
|
Redo remains available only while the user has not created a new continuation.
|
|
|
|
Example:
|
|
|
|
```text
|
|
47 -> 48A -> 49A
|
|
```
|
|
|
|
User undoes to 47 and then enters a new action:
|
|
|
|
```text
|
|
47 -> 48B
|
|
```
|
|
|
|
At that point:
|
|
|
|
- 48B becomes active,
|
|
- 48A -> 49A becomes abandoned/disposable history,
|
|
- ordinary Redo should no longer move into 48A.
|
|
|
|
The old history is retained internally but is no longer part of the standard Redo stack.
|
|
|
|
## 9. Retry
|
|
|
|
Retry means:
|
|
|
|
> Generate another narrator response to the same user input.
|
|
|
|
Example:
|
|
|
|
```text
|
|
User:
|
|
I open the door.
|
|
|
|
Take A:
|
|
A dragon lunges through the doorway.
|
|
```
|
|
|
|
Retry:
|
|
|
|
```text
|
|
Take B:
|
|
The room beyond is dark and silent.
|
|
```
|
|
|
|
The user should be able to move among recent alternate takes before continuing.
|
|
|
|
## 10. Retry Selection
|
|
|
|
Before the user continues the story, alternate narrator takes should remain selectable.
|
|
|
|
Conceptually:
|
|
|
|
```text
|
|
User action
|
|
|
|
|
+-- Take A
|
|
+-- Take B
|
|
+-- Take C
|
|
```
|
|
|
|
One take is selected as active.
|
|
|
|
If the user continues from Take B:
|
|
|
|
```text
|
|
User action
|
|
|
|
|
+-- Take A [inactive/disposable]
|
|
+-- Take B [selected]
|
|
|
|
|
+-- next user turn
|
|
+-- Take C [inactive/disposable]
|
|
```
|
|
|
|
Inactive takes should remain retained initially.
|
|
|
|
### Selecting a take while a later story is off screen (settled in M3)
|
|
|
|
Selecting a different take is a change to what the story says at a position that
|
|
already has a story after it. While that later story is on screen, the choice is
|
|
plainly visible and the user can see what they are changing.
|
|
|
|
It is not, once the later story has been moved out of view — undone and not yet
|
|
redone, or left behind by a new continuation. Silently switching the take
|
|
underneath it would leave retained history continuing from words the story no
|
|
longer says, and the user would have no way to see that it had happened.
|
|
|
|
The system must therefore refuse to switch the selected take in that situation
|
|
and say why, rather than switching it quietly. The user resolves it by deciding
|
|
what they mean:
|
|
|
|
- **Redo**, bringing the later story back into view, and then choose freely; or
|
|
- **play the turn again from here**, which starts a new continuation and keeps
|
|
the old one as retained history.
|
|
|
|
The same rule and the same two resolutions apply to editing a turn's text in
|
|
place; see §14A.
|
|
|
|
## 11. Retry vs Branch
|
|
|
|
Retry should not be presented to the user as “creating a branch.”
|
|
|
|
It is an alternate narrator attempt for the same user instruction.
|
|
|
|
Internally, the implementation may represent retries as sibling turn nodes, alternate takes under one turn request, or another equivalent lineage mechanism.
|
|
|
|
The physical representation is still provisional.
|
|
|
|
## 12. Retry of Older Narration
|
|
|
|
If the user selects an older narrator response and retries it:
|
|
|
|
- the system first returns to that story position,
|
|
- the existing future becomes abandoned/disposable history,
|
|
- the new narrator take becomes a new continuation candidate.
|
|
|
|
The system must restore the state corresponding to the retry point before generating the new response.
|
|
|
|
## 13. Editing User Input
|
|
|
|
The user should be able to edit an earlier user input.
|
|
|
|
Semantics:
|
|
|
|
> Editing an earlier user input is equivalent to returning to the parent story state and creating a new continuation using the edited input.
|
|
|
|
Example:
|
|
|
|
Original:
|
|
|
|
```text
|
|
47: Arrive at tavern
|
|
48: "I accuse Mara of taking the key."
|
|
49: Mara draws a knife.
|
|
```
|
|
|
|
User edits Turn 48 to:
|
|
|
|
```text
|
|
"I quietly ask Mara whether she has seen the key."
|
|
```
|
|
|
|
Result:
|
|
|
|
```text
|
|
47
|
|
├── 48A original accusation
|
|
│ └── 49A knife response
|
|
└── 48B edited question
|
|
└── new narrator response
|
|
```
|
|
|
|
The old future is retained as disposable history.
|
|
|
|
## 14. Editing Narrator Output
|
|
|
|
The user should be able to directly correct narrator prose.
|
|
|
|
Example:
|
|
|
|
Original:
|
|
|
|
```text
|
|
Mara enters wearing a red cloak.
|
|
```
|
|
|
|
User changes it to:
|
|
|
|
```text
|
|
Mara enters wearing a green cloak.
|
|
```
|
|
|
|
The edited narration becomes authoritative for the active continuation.
|
|
|
|
## 15. Effects of Narrator Edit
|
|
|
|
Editing narrator output may affect structured state.
|
|
|
|
Therefore the system must:
|
|
|
|
1. return to the state immediately before the edited narration,
|
|
2. treat the edited text as the accepted narrator output,
|
|
3. re-evaluate state changes implied by that output,
|
|
4. create a new active continuation,
|
|
5. retain the original narration/future as disposable history.
|
|
|
|
The system must not simply replace visible text while leaving stale state behind.
|
|
|
|
## 14A. Editing In Place, Before §14-15 Are Implemented
|
|
|
|
§14 and §15 describe the finished behavior: a narrator edit becomes
|
|
authoritative, the state it implies is re-evaluated, a new continuation is
|
|
created, and the original narration and its future are retained. That
|
|
requirement stands in full and is **not** weakened by this section.
|
|
|
|
It is not yet built. Re-evaluating the state implied by prose a user typed
|
|
requires the authoritative narrative-state extraction that the genre-neutral
|
|
state milestone introduces, so the finished behavior is completed there. What
|
|
exists in the meantime is a plain correction: it changes the words of one turn
|
|
and re-evaluates nothing.
|
|
|
|
That correction is safe while everything descending from the turn is on screen,
|
|
because the user can see what their change has to stay consistent with. It is
|
|
not safe when a continuation descends from the turn and is **off screen** —
|
|
undone and not yet redone, or left behind by a divergence — because the edit
|
|
would then silently change the words that retained story was written from, and
|
|
nothing on screen would show it. Retained history is not permitted to be made to
|
|
disagree with itself in a way the user cannot see.
|
|
|
|
Until §14-15 are implemented, the system must therefore **refuse** an in-place
|
|
edit of a turn that has story descending from it which is not currently being
|
|
shown, and say why. The user resolves it the same two ways as §10:
|
|
|
|
- **Redo**, bringing the later story back into view; or
|
|
- **play the turn again from here**, which is the §13 shape — return to the
|
|
parent position, continue differently, and keep the old line as retained
|
|
history.
|
|
|
|
Refusing is the minimum that keeps the invariant. It is not the destination.
|
|
|
|
## 16. Manual State / Canon Correction
|
|
|
|
The user should be able to correct authoritative story state without rewriting prose.
|
|
|
|
Example:
|
|
|
|
> Mara never learned about the silver key.
|
|
|
|
This should be available through an explicit operation such as:
|
|
|
|
- Edit Story State
|
|
- Edit Canon
|
|
- Correct Fact
|
|
|
|
Exact UI terminology is still open.
|
|
|
|
## 17. State Correction Semantics
|
|
|
|
A manual correction should:
|
|
|
|
- record the old value,
|
|
- record the new value,
|
|
- record that the source was a manual user correction,
|
|
- record when the correction occurred,
|
|
- affect future story context,
|
|
- remain auditable.
|
|
|
|
A manual correction should not silently rewrite historical transcript text.
|
|
|
|
If historical consistency requires a deeper rewind, the UI may warn the user.
|
|
|
|
## 18. Checkpoints
|
|
|
|
A checkpoint is a user-created durable save point.
|
|
|
|
Example names:
|
|
|
|
- Before entering Blackwood
|
|
- Arrival at Ceres Station
|
|
- Before confronting Mara
|
|
- Before opening the vault
|
|
|
|
A checkpoint points to a specific accepted story position.
|
|
|
|
## 19. Checkpoint Durability
|
|
|
|
Named checkpoints remain until explicitly deleted.
|
|
|
|
They should not be removed by:
|
|
|
|
- Undo,
|
|
- Redo,
|
|
- Retry,
|
|
- Edit,
|
|
- Restore,
|
|
- branch divergence,
|
|
- ordinary history cleanup.
|
|
|
|
### 19.1 A checkpoint protects the history it names
|
|
|
|
Added at M4 closeout, from implementation evidence.
|
|
|
|
§19's durability rule is only meaningful if something enforces it against the
|
|
operations that delete history. Deleting a branch deletes that branch and
|
|
everything forked from it, so a checkpoint naming a position anywhere in that
|
|
subtree would go with it — and go silently, because the story is what the user
|
|
asked to delete and the named moments are not mentioned in the request.
|
|
|
|
Therefore:
|
|
|
|
- **A branch cannot be deleted while a checkpoint names a position on it, or on
|
|
any branch forked from it.** The deletion is refused, not amended: nothing is
|
|
half-deleted, and no checkpoint is quietly relocated or dropped.
|
|
- **The refusal names the checkpoints standing in the way**, so the user knows
|
|
what to act on rather than being told only that something is in the way.
|
|
- **The user resolves it by deleting the checkpoint explicitly**, which is
|
|
§19's "until explicitly deleted" being honoured rather than worked around.
|
|
Deleting a checkpoint still deletes no story (§25), so the recovery costs the
|
|
user nothing they wanted to keep.
|
|
- **The scope is the subtree**, not the named branch alone.
|
|
|
|
This is the same rule §28 already anticipates for a future cleanup feature —
|
|
*retain paths referenced by checkpoints* — applied to the one deletion path that
|
|
exists today. A cleanup or discarded-history feature added later must honour it
|
|
too, and must not acquire a way to delete a checkpoint as a side effect of
|
|
deleting history.
|
|
|
|
Campaign deletion is not an exception to this and needs no rule: deleting a
|
|
campaign deletes everything in it, checkpoints included, and that is what the
|
|
user asked for.
|
|
|
|
## 20. Checkpoint Restore
|
|
|
|
Restoring a checkpoint:
|
|
|
|
1. moves the active story head to the checkpoint turn,
|
|
2. restores authoritative state for that turn,
|
|
3. restores corresponding scene state,
|
|
4. restores compatible summary/memory lineage,
|
|
5. prepares the story to continue from that position.
|
|
|
|
Restore itself does not need to create a new branch immediately. The existing continuation remains the Redo/retained path until the user creates a different continuation; the first divergent write then creates the new continuation.
|
|
|
|
The original later story remains retained as abandoned/disposable history.
|
|
|
|
## 21. Restore Does Not Delete
|
|
|
|
Example:
|
|
|
|
```text
|
|
Checkpoint: Before Fortress
|
|
|
|
100 -> 101 -> 102 -> 103 -> 104
|
|
```
|
|
|
|
Restore checkpoint at 100 and continue:
|
|
|
|
```text
|
|
100
|
|
├── 101A -> 102A -> 103A -> 104A [old/disposable]
|
|
└── 101B -> 102B [active]
|
|
```
|
|
|
|
The UI does not need to show this tree during normal play.
|
|
|
|
## 22. Model Settings on Restore
|
|
|
|
A checkpoint primarily preserves story position and state.
|
|
|
|
It does not need to force restoration of the exact narrator model/settings used at the time.
|
|
|
|
Every historical turn should separately preserve its original model/settings for auditability.
|
|
|
|
When continuing after restore, the system should normally use the user's current configured model/settings.
|
|
|
|
A future optional control may allow restoring historical model settings.
|
|
|
|
## 23. Checkpoint Renaming
|
|
|
|
Checkpoint labels may be renamed.
|
|
|
|
Renaming does not change the referenced story position.
|
|
|
|
## 24. Moving Checkpoints
|
|
|
|
v1 should not casually allow an existing checkpoint to be moved to another turn.
|
|
|
|
Preferred behavior:
|
|
|
|
- rename checkpoint, or
|
|
- delete checkpoint and create a new one.
|
|
|
|
This keeps checkpoint meaning auditable.
|
|
|
|
## 25. Deleting Checkpoints
|
|
|
|
Checkpoint deletion must be explicit.
|
|
|
|
Deleting a checkpoint:
|
|
|
|
- removes the named pointer,
|
|
- does not delete the story turn,
|
|
- does not delete story history.
|
|
|
|
## 26. Abandoned / Disposable History
|
|
|
|
When a different continuation becomes active, the displaced future becomes conceptually:
|
|
|
|
```text
|
|
abandoned = true
|
|
disposable = true
|
|
```
|
|
|
|
Equivalent metadata may be used.
|
|
|
|
The exact database representation is implementation-specific.
|
|
|
|
## 27. No Automatic Cleanup in Initial Version
|
|
|
|
v1 should not automatically purge disposable history.
|
|
|
|
Reasons:
|
|
|
|
- text/state records are inexpensive,
|
|
- early cleanup risks destroying useful recovery data,
|
|
- branch/state correctness is easier to verify when history remains,
|
|
- generated media will consume much more storage than text.
|
|
|
|
Cleanup should be designed only after real usage shows it is necessary.
|
|
|
|
## 28. Future Cleanup
|
|
|
|
A later cleanup feature may offer:
|
|
|
|
- prune abandoned history older than N days,
|
|
- prune abandoned history older than N turns,
|
|
- prune all unprotected discarded paths,
|
|
- retain paths referenced by checkpoints,
|
|
- retain paths containing manually preserved alternates,
|
|
- show estimated space savings before deletion.
|
|
|
|
No specific cleanup policy is committed for v1.
|
|
|
|
## 29. Possible Future Discarded-History Recovery Screen
|
|
|
|
A future feature may expose discarded/abandoned history.
|
|
|
|
Possible uses:
|
|
|
|
- recover a discarded continuation,
|
|
- inspect earlier alternate takes,
|
|
- restore something accidentally abandoned,
|
|
- compare old and current story paths.
|
|
|
|
This is a possible later feature, not a committed v1 requirement.
|
|
|
|
## 30. Active History Visibility
|
|
|
|
Normal transcript display should show only:
|
|
|
|
- the active history,
|
|
- currently selected narrator take,
|
|
- current story state.
|
|
|
|
Discarded history should not clutter normal play.
|
|
|
|
## 31. History Integrity
|
|
|
|
The system must never create a transcript/state mismatch such as:
|
|
|
|
```text
|
|
Visible transcript says:
|
|
Mara never saw the key.
|
|
|
|
Structured state says:
|
|
Mara knows about the key because of abandoned Turn 52.
|
|
```
|
|
|
|
Only active-lineage facts, memories, summaries, and state may influence the current continuation.
|
|
|
|
## 32. Summary Lineage
|
|
|
|
Summaries are derived from specific story history.
|
|
|
|
When the active story diverges:
|
|
|
|
- summaries containing abandoned future turns must not be applied to the new continuation,
|
|
- unaffected ancestral summaries may remain valid,
|
|
- new summaries may be generated when required.
|
|
|
|
The system should record source turn ranges or lineage for every summary.
|
|
|
|
## 33. Memory Lineage
|
|
|
|
Retrieved story memory must respect active lineage.
|
|
|
|
A memory from an abandoned future must not appear as something that happened in the active story.
|
|
|
|
Example:
|
|
|
|
Discarded path:
|
|
|
|
```text
|
|
Mara reveals she is a spy.
|
|
```
|
|
|
|
New active path:
|
|
|
|
```text
|
|
Mara has never revealed this.
|
|
```
|
|
|
|
The memory retriever must not feed:
|
|
|
|
```text
|
|
Mara is known to be a spy.
|
|
```
|
|
|
|
to the narrator merely because that fact exists in an abandoned path.
|
|
|
|
This is a critical correctness requirement.
|
|
|
|
## 34. Imported Knowledge Is Different
|
|
|
|
Imported Canon / Reference / Inspiration files are not normally branch-specific.
|
|
|
|
They remain available across branches unless the source is explicitly campaign-state-dependent or the user disables/removes the source.
|
|
|
|
Story memories and story-derived facts, by contrast, must be lineage-aware.
|
|
|
|
## 35. Scene Lineage
|
|
|
|
Scene snapshots must also follow active history.
|
|
|
|
A scene from an abandoned future must not become the current scene after Undo or Restore.
|
|
|
|
Generated media attached to an abandoned scene may remain stored, but it should no longer be treated as current-story media.
|
|
|
|
## 36. Prompt Provenance
|
|
|
|
Every generated narrator take should preserve enough information to determine:
|
|
|
|
- parent story position,
|
|
- user input,
|
|
- selected history,
|
|
- current state,
|
|
- summaries used,
|
|
- memories used,
|
|
- imported knowledge used,
|
|
- model/settings,
|
|
- resulting output.
|
|
|
|
This remains true even for abandoned/disposable history until it is explicitly pruned.
|
|
|
|
## 36A. Export / Import Must Preserve the Active Head
|
|
|
|
Non-destructive Undo means retained history may extend beyond the current active head.
|
|
|
|
Export must therefore preserve both:
|
|
|
|
- the retained history/branch graph, and
|
|
- the exact active branch/head position.
|
|
|
|
Import must reopen the campaign at that active head. It must not infer that the newest retained turn is current merely because later history still exists.
|
|
|
|
Backward compatibility may treat the retained tip as the head only for older export formats that contain no explicit head coordinate.
|
|
|
|
## 37. Failure During Retry / Edit / Continue
|
|
|
|
If generation fails:
|
|
|
|
- the previously accepted active history remains valid,
|
|
- no partial state mutation should be committed,
|
|
- no successful prior take should be lost.
|
|
|
|
The user should be able to retry generation.
|
|
|
|
## 38. Atomic Acceptance
|
|
|
|
A newly generated continuation should become accepted only when the application can coherently commit:
|
|
|
|
- narration,
|
|
- lineage,
|
|
- state changes,
|
|
- scene update,
|
|
- provenance.
|
|
|
|
A failure in state extraction should not silently leave partially applied state.
|
|
|
|
Exact failure-repair handling will be specified later.
|
|
|
|
## 39. User-Facing Control Summary
|
|
|
|
### Undo
|
|
Move backward one accepted story step.
|
|
|
|
### Redo
|
|
Move forward again, until a new continuation is created.
|
|
|
|
### Retry
|
|
Generate another narrator response to the same user input.
|
|
|
|
### Edit User Input
|
|
Return to that point and create a new continuation using edited input.
|
|
|
|
### Edit Narrator Output
|
|
Replace the active narration through a new auditable continuation and re-evaluate state.
|
|
|
|
### Save Checkpoint
|
|
Create a durable named pointer to the current story position.
|
|
|
|
### Restore Checkpoint
|
|
Return to that state; later history becomes retained disposable history.
|
|
|
|
### Correct State / Canon
|
|
Explicitly change an authoritative fact without rewriting transcript prose.
|
|
|
|
## 40. Not Required in v1 UI
|
|
|
|
Do not require:
|
|
|
|
- branch tree visualization,
|
|
- manual branch creation,
|
|
- merge,
|
|
- cherry-pick,
|
|
- branch comparison,
|
|
- branch IDs,
|
|
- discarded-history browser,
|
|
- automatic branch cleanup.
|
|
|
|
Internal lineage may still use branch/tree structures.
|
|
|
|
## 41. Minimum v1 Undo Requirement
|
|
|
|
Acceptance requirement:
|
|
|
|
- at least 5 consecutive Undo operations must be supported.
|
|
|
|
Preferred:
|
|
|
|
- unlimited Undo across retained history.
|
|
|
|
Phase 0B demonstrated that the preferred behavior is practical in the selected base. The production implementation should retain that capability while enforcing the correct campaign-root floor.
|
|
|
|
## 42. Example: Simple Mistake
|
|
|
|
Initial:
|
|
|
|
```text
|
|
10: Enter tavern
|
|
11: Accuse Mara
|
|
12: Mara becomes hostile
|
|
```
|
|
|
|
User Undo x2:
|
|
|
|
```text
|
|
Active head = 10
|
|
```
|
|
|
|
User enters:
|
|
|
|
```text
|
|
I ask Mara privately whether she saw anyone near my room.
|
|
```
|
|
|
|
Result:
|
|
|
|
```text
|
|
10
|
|
├── 11A Accuse Mara
|
|
│ └── 12A Mara hostile
|
|
└── 11B Ask privately
|
|
└── 12B New narration
|
|
```
|
|
|
|
User sees only:
|
|
|
|
```text
|
|
10 -> 11B -> 12B
|
|
```
|
|
|
|
The A path is retained but disposable.
|
|
|
|
## 43. Example: Retry
|
|
|
|
```text
|
|
User: I open the airlock door.
|
|
|
|
Take A:
|
|
A maintenance robot is waiting.
|
|
|
|
Retry
|
|
|
|
Take B:
|
|
The corridor beyond is filled with smoke.
|
|
```
|
|
|
|
User selects Take B and continues.
|
|
|
|
Take A remains retained/disposable.
|
|
|
|
## 44. Example: Named Checkpoint
|
|
|
|
```text
|
|
Checkpoint:
|
|
"Before entering the alien structure"
|
|
|
|
Turn 220
|
|
```
|
|
|
|
Story continues to Turn 245.
|
|
|
|
User restores checkpoint and chooses another approach.
|
|
|
|
Turns 221-245 remain retained/disposable.
|
|
|
|
The checkpoint remains attached to Turn 220 until explicitly deleted.
|
|
|
|
## 45. Example: Manual Canon Correction
|
|
|
|
Narrator incorrectly establishes:
|
|
|
|
```text
|
|
The Persephone has an FTL drive.
|
|
```
|
|
|
|
Campaign canon says:
|
|
|
|
```text
|
|
FTL does not exist.
|
|
```
|
|
|
|
User corrects state/canon.
|
|
|
|
The correction should be recorded explicitly and future context must treat:
|
|
|
|
```text
|
|
The Persephone has no FTL capability.
|
|
```
|
|
|
|
as authoritative.
|
|
|
|
If desired, the user may also edit the narration, but that is a separate operation.
|
|
|
|
## 46. Phase 0B Findings Applied
|
|
|
|
Phase 0B established the following implementation facts for the selected AI-DnD base:
|
|
|
|
- shipped Undo was destructive and therefore did not satisfy this document,
|
|
- alternate-take Retry and branch lineage were genuinely non-destructive,
|
|
- a disposable spike demonstrated head-cursor Undo/Redo without deleting accepted turns,
|
|
- writes below a moved-back head can fork through existing branch machinery,
|
|
- branch-scoped memory isolation remained correct with real local embeddings,
|
|
- practical repeated Undo across retained history worked beyond the minimum five-step requirement,
|
|
- retry/add-take paths still need to be routed through the production fork-if-behind-head rule,
|
|
- abandoned history still needs explicit disposable/inactive marking,
|
|
- export/import must carry the active head coordinate or it silently redoes an undone story.
|
|
|
|
These findings select an implementation direction; the disposable spike itself is not production code to merge unchanged.
|
|
|
|
## 47. Acceptance Criteria
|
|
|
|
The final implementation must satisfy:
|
|
|
|
- Undo restores transcript and state together by moving the active head, not deleting accepted turns.
|
|
- At least five Undo steps are guaranteed; the selected architecture should support Undo across all retained active-lineage history up to the root.
|
|
- Redo works until a new continuation is created.
|
|
- Retry preserves alternate narrator takes.
|
|
- Editing old user input creates a safe new continuation.
|
|
- Editing narrator output re-evaluates state.
|
|
- Named checkpoints remain until explicitly deleted.
|
|
- Restoring a checkpoint does not delete later history.
|
|
- Checkpoint restore may reuse the existing continuation until the first divergent write.
|
|
- Abandoned history is retained and marked disposable.
|
|
- No automatic abandoned-history cleanup is required in v1.
|
|
- Abandoned history does not influence active summaries, memories, state, or prompts.
|
|
- Manual state/canon corrections are auditable.
|
|
- Export/import preserves the exact active head even when retained history exists after it.
|
|
- Normal UI does not require branch management.
|
|
- A future discarded-history recovery/cleanup screen remains possible without schema redesign.
|
|
|
|
## 48. Selected Implementation Model
|
|
|
|
Use a simple linear user experience backed by retained lineage and a movable active head.
|
|
|
|
```text
|
|
USER EXPERIENCE
|
|
|
|
Undo
|
|
Redo
|
|
Retry
|
|
Edit
|
|
Save Point
|
|
Restore
|
|
|
|
↓
|
|
|
|
INTERNAL MODEL
|
|
|
|
Parent-linked retained history
|
|
Alternate takes
|
|
Active branch + active head
|
|
Retained branch tip/future
|
|
Typed state events + snapshots/cache
|
|
Disposable abandoned history
|
|
Lineage-aware summaries/memory
|
|
Exported active-head coordinate
|
|
```
|
|
|
|
The selected AI-DnD base supplies most of the lineage infrastructure; production work replaces destructive Undo, adds Redo/checkpoints/disposable marking, and preserves the head through export/import.
|