M9: a campaign you can actually get back
A campaign could already be exported and imported. What could not survive the trip was everything that explains it: the state events behind the authoritative document, the prompt each turn was actually given, the passages it was shown, the summaries that carry long-story continuity, and which take belonged to which turn. An imported campaign could be read and could no longer say why it was what it was — and a manual correction, the one state change no narration explains, was indistinguishable from something the story had established. The bundle is now `ai-dnd-adventure-v3`, and the version is the design rather than a side effect. Everything added here could have been another optional key, the way persona, Save Points, narrative state and imported knowledge each were. That mechanism stops working at exactly this addition: a v2 file with no prompt provenance is ambiguous between "written before M9" and "written by M9 from a campaign that has none", and those are different facts about a campaign. A version number is how a recovery file states what it was capable of recording. v1 and v2 still import, and every seam from pre-active-head onward is tested for the rule that an older file is never reinterpreted under a newer assumption. Two categories became three. "Chosen travels, derived is recomputed" was enough until stored prompts had to be decided: they are derived, and they must travel anyway. The test that separates evidence from cache is not "could this be recomputed" but "would a recomputation answer the same question" — a rebuilt search index answers the same question, a rebuilt prompt says what the turn would be told *now*, which is the opposite of what the inspector is for. Also here: a real SQLite backup, through the online backup API rather than a file copy, taken while the application is running and verified before it is kept; story cards settled as compatibility-only legacy data and taken out of the narrator's prompt, because they were the untracked path around knowledge authority that IMPORTED-KNOWLEDGE-DESIGN §73 already forbade; and no schema change at all, proved against a database M8's own code wrote. Three defects, found by running the milestone's own tests rather than by reading them. Deleting a campaign leaked its FTS index rows, and SQLite then handed the freed ids to the next source imported into any campaign, which failed with an integrity error that Reindex could not repair — both ends are closed, and a database already carrying the damage now repairs itself. An imported node with no state snapshot was being stamped with the campaign's head state, so an Undo to turn 2 showed what the story knew at turn 20. And the snapshot relink did not persist at all, because it mutated a dict in place on a column SQLAlchemy tracks by assignment: it looked correct in memory and wrote the wrong ids to disk. Carrying per-turn prompts looked like it would halve the length of campaign that can be restored. Measured — and after compressing them inside the file — everything M9 added costs 12% of it: the import ceiling moves from about 318 turns to about 279, against a 100-turn certification target. The dominant cost is not M9's at all. The per-position narrative state document is 74% of a bundle, and v2 already carried it. Backend 1,102 passed / 14 skipped / 0 failed. Frontend 145 passed. Lint, production build and Docker build clean. Verified across two server processes with two data directories, and in a real browser against a real narrator. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qyn3oRd4D6pi72nKBG725B
This commit is contained in:
co-authored by
Claude Opus 5
parent
1ce9972760
commit
44edece67e
+96
-3
@@ -1,8 +1,101 @@
|
||||
# Planning Package Version
|
||||
|
||||
- **Package:** Adventure Storyteller Planning Package v3.3
|
||||
- **Revision date:** 2026-09-06
|
||||
- **Status:** Phase 0 complete; architecture selected; **Milestones M1-M8 implemented and accepted** (M8 closed out 2026-09-06). M9 is next and has not been started.
|
||||
- **Package:** Adventure Storyteller Planning Package v3.5
|
||||
- **Revision date:** 2026-09-07
|
||||
- **Status:** Phase 0 complete; architecture selected; **Milestones M1-M8 implemented and accepted**; **M9 implemented and awaiting independent review** (2026-09-07). M10 has not been started.
|
||||
|
||||
## v3.5 — Post-M8 hands-on playtest findings recorded (2026-09-07)
|
||||
|
||||
**Documentation only. No application code changed, and M9's verified result is
|
||||
untouched** — see the note at the end of this entry.
|
||||
|
||||
A real play session against **accepted, signed M8** (real browser, trusted-LAN
|
||||
Ollama, `qwen2.5:3b-instruct-16k`, disposable database since destroyed) surfaced
|
||||
four product-quality observations. **None is an M9 defect, none was caused by
|
||||
M9, and none blocks M9 acceptance.** They are recorded so they cannot be lost
|
||||
when the M9 report is archived.
|
||||
|
||||
| Document | Change | Kind |
|
||||
| --- | --- | --- |
|
||||
| `reports/M9-IMPLEMENTATION-REPORT.md` | **New §Y**, the full write-up with the verification behind each mechanism, plus a pointer from §W. Explicitly labelled as not-M9. | observation record |
|
||||
| `BUILD-MILESTONES.md` | **New section before M10**, the durable copy owned by M11; a note bounding M10 out of it; the four items added to M11's scope list. | milestone sequencing |
|
||||
| `V1-ACCEPTANCE-TESTS.md` | **New §P**, three items as **test-design tasks, explicitly not acceptance tests**, each naming what must be settled before it could become one. No existing test changed or weakened. | test design |
|
||||
| `BROWSER-UX-SPEC.md` | **New §8A.** §8's *"The current endpoint should be clear"* was satisfied while a real reader was lost, so it could not hold the behaviour. States the orientation requirement; **prescribes no wording**. | requirement clarification |
|
||||
| `TEST-CAMPAIGN-FIXTURE.md` | **New Appendix A** proposing a companion `Multi-Character Identity Test`. The established deterministic fixture is **unchanged** — altering it would invalidate earlier milestones' comparisons. | test design |
|
||||
|
||||
**What was verified rather than assumed**, since the playtest campaign no longer
|
||||
exists and root causes largely cannot be proven:
|
||||
|
||||
- The browser title genuinely is `AI D&D` (`frontend/index.html`), and **no
|
||||
accepted document ever claimed otherwise** — so this is an uncovered gap, not
|
||||
documentation needing correction. Nothing was corrected and nothing was
|
||||
renamed: *Adventure Storyteller* is itself narrower than the genre-agnostic
|
||||
engine `SPECIFICATION.md` requires, and the naming decision is the owner's.
|
||||
- The narration-length setting adds **one English sentence** and changes **no
|
||||
generation budget**, while the numeric hint derived from the global
|
||||
`max_output_tokens` is **identical for every setting** — measured at the
|
||||
default as *"must not exceed 506 words, and it should not stop short of about
|
||||
177."* Recorded as a mechanism to check first, **not** as the proven cause.
|
||||
- The narrative state **permits two entities to share a display name and
|
||||
reports nothing** — `DUPLICATE_ENTITY` rejects a repeated key only. That is
|
||||
one of the identity finding's failure modes; it establishes nothing about what
|
||||
actually happened.
|
||||
|
||||
**M9 is unaffected.** No application file changed in this pass, so M9's final
|
||||
verified result stands exactly as recorded: **1,102 backend passed / 14 skipped
|
||||
/ 0 failed**, 145 frontend, 36/36 browser. The expensive M9 suites were
|
||||
deliberately **not** re-run, because only Markdown changed.
|
||||
|
||||
## v3.4 — M9 Implementation (2026-09-07)
|
||||
|
||||
M9 — Export, Backup, Recovery, and Migration Hardening — is implemented on
|
||||
`m9-recovery` from the signed M8 commit `1ce9972`. This revision records what the
|
||||
implementation settled. It is **not** an acceptance: the milestone report is
|
||||
written for a reviewer and the tree is staged for the repository owner's signed
|
||||
commit.
|
||||
|
||||
**Requirement corrections:** none. M9 altered no product requirement.
|
||||
`SPECIFICATION.md` and `SECURITY-THREAT-MODEL.md` are unchanged — §16 already
|
||||
required the export to preserve the exact active position, §6.1 already required
|
||||
an exact prompt/context snapshot per turn, and M9 implements both rather than
|
||||
redefining either.
|
||||
|
||||
| Document | Change | Kind |
|
||||
| --- | --- | --- |
|
||||
| `DATA-MODEL.md` §29 | The v3 format, the three-category rule (chosen / evidence / rebuildable), what each version can be trusted to say, the encoding of the snapshots, and the two pointers the import translates. | implementation fact |
|
||||
| `TECHNICAL-DESIGN.md` §9.3 | Why the version was bumped when §9.1 and §9.2 each correctly declined one; the third data category; the two-phase transaction and the warning path for a failed derived rebuild. | implementation fact |
|
||||
| `TECHNICAL-DESIGN.md` §9.4 | **New.** The SQLite backup: the online backup API rather than a file copy, the verify-then-rename order, and why there is no restore endpoint. | implementation fact |
|
||||
| `IMPORTED-KNOWLEDGE-DESIGN.md` §73 | **New subsection.** Story Cards settled as compatibility-only legacy data and removed from the narrator's prompt, with the evidence that they were the "alternate untracked path" §73 already forbade. | newly settled design decision |
|
||||
| `V1-ACCEPTANCE-TESTS.md` I01-I07, L02-L04 | Results recorded. I05's M7-era limit is marked closed with the original paragraph kept, because the M9 decision is only legible against it. L04 records the defect running it found. | implementation fact |
|
||||
| `BUILD-MILESTONES.md` M9 | Marked complete, with what it delivered, the three defects it found, the story-card decision, and the debt carried forward. | implementation fact |
|
||||
| `README.md`, `VERSION.md` | Status. | implementation fact |
|
||||
| `DEVELOPMENT.md` | **New section**: the two recovery tools and when each applies, taking a backup, and the stop-move-start restore procedure. Plus a note that an imported long campaign meets a small context ceiling on its first turn rather than gradually. | implementation fact |
|
||||
|
||||
**The four M8 handoff questions, answered**
|
||||
|
||||
| | Answer |
|
||||
| --- | --- |
|
||||
| **A. Complete campaign portability** | Every family travels and is measured family by family, before and after, by a tool a reviewer can rerun. |
|
||||
| **B. Historical prompt provenance** | **It belongs in the bundle, and it is in it.** An old turn in a restored campaign shows what it was actually given, after the source has been deleted and the canon edited. |
|
||||
| **C. Legacy story cards** | Compatibility-only. Carried in both directions; removed from the narrator's prompt; still the summariser's character roster. |
|
||||
| **D. Context-window portability** | The campaign travels; the machine's model configuration does not. Importing changes no setting of the destination's, and a campaign imports whether or not any model is installed. The window itself remains M11's. |
|
||||
|
||||
**What the implementation found rather than assumed**
|
||||
|
||||
Three defects, all found by running the milestone's own tests rather than by
|
||||
reading: an FTS index leak that made an ordinary import fail in an unrelated
|
||||
campaign and that Reindex could not repair; an imported node with no state
|
||||
snapshot being stamped with the campaign's *head* state; and a snapshot pointer
|
||||
that was not being translated because the code mutated a dict in place. The
|
||||
first two predate M9.
|
||||
|
||||
One measurement changed a plan, and then corrected the conclusion drawn from it.
|
||||
Carrying per-turn prompts looked like it would halve the length of campaign that
|
||||
can be restored. Measured, and after compressing them inside the file, everything
|
||||
M9 added costs **12%** of reachable campaign length — the import ceiling moves
|
||||
from about 318 turns to about 279, against a 100-turn certification target. The
|
||||
dominant cost is not M9's at all: the **per-position narrative state document is
|
||||
74% of a bundle**, and v2 already carried it.
|
||||
|
||||
## v3.3 — M8 Closeout (2026-09-06)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user