Skip to content

S129 — Every game plays the content it names - #587

Merged
The-Running-Dev merged 1 commit into
mainfrom
slice/S129-resolve-by-state
Oct 9, 2026
Merged

The-Running-Dev merged 1 commit into
mainfrom
slice/S129-resolve-by-state

Conversation

@The-Running-Dev

Copy link
Copy Markdown
Owner

What

A host can now keep more than one published version of a campaign available at once. Every game plays the version it names, not whichever version the host registered under the campaign's name. EngineHost.archive?: ResolutionArchive is optional. Without it, the engine uses an archive holding only the construction-time registry. Engine.content exposes whichever archive is in use.

  • Every state-taking operation takes KindContext.registry and .campaign from content.resolve(state.campaignId, state.campaignVersion).
  • createGame(config, campaignVersion?) starts on a named epoch.
  • deserialize and migrate refuse a state whose epoch does not resolve, with unknown_campaign. This closes the S125.5 gap.

Criteria

  • S129.1 — met: engine.test.ts › S129.1 — the archive in use
    • the default archive holds only the registry;
    • content is the supplied archive, and withEmitter keeps it;
    • construction throws on an archive missing the registry's epoch, or answering it with another version.
  • S129.2 — met: S129.2 — every state-taking operation reads its own epoch
    • one engine, two epochs differing in one node's text;
    • scene, view, availableActions, submitAction, previewAction, deserialize and migrate each read the state's own epoch.
  • S129.3 — met: S129.3 — createGame starts on the default or a named epoch
    • default version, named version, and unknown_campaign for an unresolved version or id.
  • S129.4 — met: S129.4 — deserialize and migrate refuse an epoch that does not resolve
    • unknown_campaign plus exactly one core.deserialize.rejected, for a known id at another version.
    • Verified by reverting: both cases fail against the pre-slice kernel.
  • S129.5 — met: the full suite passes with no existing test, golden file or corpus fixture changed (2,220 tests).
  • S129.6 — met: engine.test.ts imports ResolutionArchive from src/index.ts, and the typecheck proves the root export.

Differs from design

  • createEngine copies the registry's campaign map once, so a later mutation does not change the default epoch. One existing store test mutates the registry under a live engine. Recorded in 90-decisions.md, 2026-10-09.
  • An archive answer whose registry holds the campaign at a different version counts as unresolved. Recorded in 90-decisions.md, 2026-10-09.

Verified

  • npm run typecheck, npm run lint: clean.
  • npm test: 115 files, 2,220 tests passed.
  • ./build/Test-Documentation.ps1: passed (drift check across 19 generated pages; 135 Markdown files).
  • git diff --check: clean.
  • Advisory test-design.ts reported 13 findings. All are path fragments such as /authoring read as slash commands. They predate this change, and none are in lines this PR touches.
  • Not run locally: ./docs.ps1 -BuildOnly (no installed docs.ps1). The Verify Documentation Build check covers it.

Engine resolves every state's content through a ResolutionArchive keyed by
(campaignId, campaignVersion); EngineHost.archive is optional and defaults to the
construction-time registry, read once. createGame takes an optional starting
version; deserialize and migrate refuse an epoch the archive does not hold.
@The-Running-Dev
The-Running-Dev merged commit 97b7057 into main Oct 9, 2026
8 checks passed
@The-Running-Dev
The-Running-Dev deleted the slice/S129-resolve-by-state branch October 9, 2026 09:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant