Skip to content

S131 — A host publishes new content while running - #589

Merged
The-Running-Dev merged 1 commit into
mainfrom
slice/S131-content-channel
Oct 9, 2026
Merged

The-Running-Dev merged 1 commit into
mainfrom
slice/S131-content-channel

Conversation

@The-Running-Dev

Copy link
Copy Markdown
Owner

What

A host can now publish a new build of its content without restarting. createContentArchive({ kinds, initial }) is the reference archive and channel from 16 §4.3:

  • publish re-runs every campaign's validateCampaign against the publication's strings.
  • It refuses a held (campaignId, campaignVersion) whose content differs, with content_version_conflict. Content identity is 16 §3.4's digest: 11 §6's campaign digest plus the full strings table, sorted by key.
  • It stores deep-frozen copies. migrateState is kept by reference.
  • latest() is the last successful publication, and current(scope) answers that publication's version of the scope's campaign.

An engine given the archive as its archive resolves both old and new epochs.

Criteria

  • S131.1 — met: archive.test.ts › S131.1. initial resolves at its versions, and an unknown key is undefined. An initial that fails validation throws, and so does one with an unregistered kind. bulgaria-bureaucracy.archive.test.ts publishes the real campaign's validated registry and republishes it as a no-op.

  • S131.2 — met: archive.test.ts › S131.2. The validator's errors are returned, nothing is stored and latest() is the same object. Validation runs against the publication's own strings.

  • S131.3 — met: archive.test.ts › S131.3. 3 refusals:

    • changed content under a held key: a new key in the same publication is not stored either;
    • one changed string;
    • one added string.

    3 successes:

    • an identical republish with strings reordered returns [];
    • a republish differing only in migrateState returns [];
    • a new key returns its EpochRef, and a held key in the same publication does not.
  • S131.4 — met: archive.test.ts › S131.4. After publishing, changing the content, the campaign map and the strings changes nothing resolve answers. Mutating what it serves throws on content, campaign fields, set, delete and clear. migrateState is the same function, and resolution is kept.

  • S131.5 — met: archive.test.ts › S131.5. current follows each success across sessions and profiles, stays put on a refusal, and is undefined for a campaign the latest publication lacks, which still resolves.

  • S131.6 — met: archive.test.ts › S131.6. A game on epoch 1, played after epoch 2 is published, serializes byte-identically to the same game on an engine with no archive. Its scene reads epoch 1's content, and epoch 2 is playable alongside it.

  • S131.7 — met: archive.test.ts › S131.7. content_version_conflict is in BASE_REASON_CODES and has a message. createContentArchive, ContentArchive, ContentChannel, ContentScope and EpochRef are imported from the package root.

Differs from design

Four interpretations are recorded in 90-decisions.md:

  • An unregistered kind refuses a publication with unknown_kind. Core-owned Tier 1 checks are not re-run.
  • includes counts toward the digest only when it is present and non-empty. This follows 11 §6, which §3.4 cites.
  • Successfully republishing an older epoch makes it the latest again, which is how a host rolls the channel back.
  • A key resolves to the registry it was first published in, and is never repointed.

ContentChannel and ContentScope live in the archive module. SessionHost.content does not exist yet; it arrives with the adoption points.

Verified

  • npm run typecheck, npm run lint, npm test: 117 files, 2278 tests passing.

  • ./build/ConvertTo-HumanDocumentation.ps1 and ./build/Test-Documentation.ps1 pass. git diff --check is clean.

  • Reverting each guard makes its tests fail:

    Guard removed Tests that fail
    conflict check 3
    copy at publish 2
    validation 4
    strings in the digest 2
  • One run of the full suite timed out long-horizon.replay.test.ts › long-horizon-win round-trips through deserialize: 5.5 s against a 5 s limit, under parallel load. The test takes 1.7 s alone, and it passed on the next full run. This slice does not touch it.

  • Not run locally: ./docs.ps1 -BuildOnly (no installed docs.ps1). The Verify Documentation Build check covers it.

@The-Running-Dev
The-Running-Dev merged commit 95eb907 into main Oct 9, 2026
8 checks passed
@The-Running-Dev
The-Running-Dev deleted the slice/S131-content-channel branch October 9, 2026 10:30
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