chore(facts): protocol 5, Module API 1.9.0, and the 2026.09.01 bundle #27

Merged
whitlocktech merged 4 commits from docs/platform-facts-protocol-5 into edge 2026-09-01 17:45:18 +00:00
Member

Engagement Phase 12b, now fillable. Pairs with #26 (Phase 12a, merged).

Phase 13 landed while this branch waited, so the values it was holding for exist. Everything below is what checkFacts.mjs itself reports as the authority's answer, not a value anyone chose:

bundle.tag          2026.08.19 -> 2026.09.01
bundle.sidecar      v2.0.0     -> v2.1.0
bundle.overlay      v1.0.0     -> v1.1.0
releases.link       v2.0.0     -> v2.1.0
releases.Module-uo  v1.0.2     -> v1.1.0
protocol            4          -> 5
moduleApi           1.6.0      -> 1.9.0
verifiedOn          2026-08-19 -> 2026-09-01

npm run verify is green end to end: checkFacts 19/19, checkLinks 2605, checkQuickstart 59, checkReference 22, checkSidebar 5+42, checkScreens 17, checkA11y 52, checkCsp 52, 42 unit tests, 7 served-header tests.

No page hardcodes any of those numbers — every quote is an interpolation of platform.bundle.* or platform.releases.* — so connect-a-game-server, the-shard-connection, docs/index, requirements, the hero and the footer all moved with the file.

moduleApi is 1.9.0, not the 1.7.0 §12 named: Phase 11 moved it twice after that sentence was written (1.8.0 for the admin ceiling, 1.9.0 for the module seed API).

The check was failing on a stale copy, not on a stale site

The fill-in step was supposed to be mechanical. It was not, and the reason is worth keeping.

checkFacts.mjs reported:

FAIL  moduleApi
      platform.json says : 1.9.0
      website main:server/src/modules/version.js says : 1.6.0

website main says 1.9.0. The check was reading a two-week-old blob: the API's raw route answers Cache-Control: public, max-age=21600, so the CDN in front of Gitea had served a copy from 18 August (cf-cache-status: HIT, Age: 15713). No edit in this repository could have made that pass.

The same run also reported the bundle triple as still current when it had already been republished — so a stale read fails both ways, and the false pass is the dangerous one: this repo's whole bargain is that the check goes red when the platform moves.

Fixed at the source rather than with a cache-buster: contents answers private, must-revalidate, which the CDN bypasses, so it is always the ref's current blob. All three cross-repository checks — checkFacts, checkQuickstart, checkReference — now read that way, and PLAN.md §12 records why next to the check it constrains. (checkReference's canonical-document loop already used contents, which is why that half was never wrong.)

Two things this leaves behind for someone else to decide, neither touched here:

  • This PR gets no CI. pr-checks.yml triggers on PRs into main only, so the first real run of these checks is the edgemain cutover PR. Without this commit that cutover would have gone red for a reason nobody could fix from the diff.
  • DEPLOY.md tells an operator to curl the compose file from the web raw/branch/main route, which is cached the same way. Six hours of stale docker-compose.yml on a fresh install is a much smaller problem than a lying check, so it is recorded rather than changed.

The one page whose whole subject is the protocol number was the one page that hardcoded it

platform.json's own header says no version number is ever hardcoded in prose. architecture/protocol-versions.mdx had 4 written out three times — the headline sentence and both declaration-site rows — so the page most likely to be quoted about the protocol was the page that would have gone on saying 4 after everything else moved. It imports platform.json now, like every other page that quotes a fact.

The interpolation sits outside the code spans, deliberately. MDX does not evaluate an expression inside backticks, so `PROTOCOL_VERSION: u32 = {platform.protocol}` would have rendered the braces literally on a published page. Verified in the built HTML: "currently 5", and no platform.protocol survives anywhere in the output.

Same page: "version 4 was the first bump that needed one" (a store migration) read as though every bump does. v5 needed none — it only widens frames the store already keeps whole (docs link/v5.md) — so the sentence now says which did and which did not, and v5.md joins v4.md under canonical documents.


Merging this leaves the edgemain cutover (7 of 7) as the last step of the workstream.

AI-assisted: written with Claude Code.

🤖 Generated with Claude Code

Engagement **Phase 12b**, now fillable. Pairs with **#26** (Phase 12a, merged). Phase 13 landed while this branch waited, so the values it was holding for exist. Everything below is what `checkFacts.mjs` itself reports as the authority's answer, not a value anyone chose: ``` bundle.tag 2026.08.19 -> 2026.09.01 bundle.sidecar v2.0.0 -> v2.1.0 bundle.overlay v1.0.0 -> v1.1.0 releases.link v2.0.0 -> v2.1.0 releases.Module-uo v1.0.2 -> v1.1.0 protocol 4 -> 5 moduleApi 1.6.0 -> 1.9.0 verifiedOn 2026-08-19 -> 2026-09-01 ``` `npm run verify` is green end to end: **checkFacts 19/19**, checkLinks 2605, checkQuickstart 59, checkReference 22, checkSidebar 5+42, checkScreens 17, checkA11y 52, checkCsp 52, 42 unit tests, 7 served-header tests. No page hardcodes any of those numbers — every quote is an interpolation of `platform.bundle.*` or `platform.releases.*` — so `connect-a-game-server`, `the-shard-connection`, `docs/index`, `requirements`, the hero and the footer all moved with the file. `moduleApi` is **1.9.0**, not the **1.7.0** §12 named: Phase 11 moved it twice after that sentence was written (1.8.0 for the `admin` ceiling, 1.9.0 for the module seed API). ## The check was failing on a stale copy, not on a stale site The fill-in step was supposed to be mechanical. It was not, and the reason is worth keeping. `checkFacts.mjs` reported: ``` FAIL moduleApi platform.json says : 1.9.0 website main:server/src/modules/version.js says : 1.6.0 ``` `website` `main` says **1.9.0**. The check was reading a two-week-old blob: the API's `raw` route answers `Cache-Control: public, max-age=21600`, so the CDN in front of Gitea had served a copy from 18 August (`cf-cache-status: HIT`, `Age: 15713`). No edit in this repository could have made that pass. The same run also reported the bundle triple as *still current* when it had already been republished — so a stale read fails **both** ways, and the false pass is the dangerous one: this repo's whole bargain is that the check goes red when the platform moves. Fixed at the source rather than with a cache-buster: `contents` answers `private, must-revalidate`, which the CDN bypasses, so it is always the ref's current blob. All three cross-repository checks — `checkFacts`, `checkQuickstart`, `checkReference` — now read that way, and `PLAN.md` §12 records why next to the check it constrains. (`checkReference`'s canonical-document loop already used `contents`, which is why that half was never wrong.) Two things this leaves behind for someone else to decide, neither touched here: - **This PR gets no CI.** `pr-checks.yml` triggers on PRs into `main` only, so the first real run of these checks is the `edge` → `main` cutover PR. Without this commit that cutover would have gone red for a reason nobody could fix from the diff. - **`DEPLOY.md` tells an operator to `curl` the compose file from the web `raw/branch/main` route**, which is cached the same way. Six hours of stale `docker-compose.yml` on a fresh install is a much smaller problem than a lying check, so it is recorded rather than changed. ## The one page whose whole subject is the protocol number was the one page that hardcoded it `platform.json`'s own header says *no version number is ever hardcoded in prose*. `architecture/protocol-versions.mdx` had `4` written out **three times** — the headline sentence and both declaration-site rows — so the page most likely to be quoted about the protocol was the page that would have gone on saying 4 after everything else moved. It imports `platform.json` now, like every other page that quotes a fact. **The interpolation sits outside the code spans, deliberately.** MDX does not evaluate an expression inside backticks, so `` `PROTOCOL_VERSION: u32 = {platform.protocol}` `` would have rendered the braces literally on a published page. Verified in the built HTML: *"currently 5"*, and no `platform.protocol` survives anywhere in the output. Same page: *"version 4 was the first bump that needed one"* (a store migration) read as though every bump does. **v5 needed none** — it only widens frames the store already keeps whole (`docs link/v5.md`) — so the sentence now says which did and which did not, and `v5.md` joins `v4.md` under canonical documents. --- Merging this leaves the `edge` → `main` cutover (7 of 7) as the last step of the workstream. AI-assisted: written with Claude Code. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wtclaude added 1 commit 2026-09-01 13:15:08 +00:00
Engagement Phase 12b. **This branch is deliberately red and must not be merged until the
Phase 13 cutover has landed link and servuo-plugins on `main` and CI has republished the
bundle.** checkFacts.mjs fetches every value from the source repo's `main`, so it fails
today exactly as designed:

  FAIL  protocol (sidecar)   platform.json 5   link main 4
  FAIL  protocol (overlay)   platform.json 5   servuo-plugins main 4
  FAIL  moduleApi            platform.json 1.9.0   website main 1.6.0
  FAIL  protocol (bundle)    platform.json 5   installer bundles:current.json 4

Every other check is green on this branch: checkLinks 2503, checkReference 22, checkA11y,
checkCsp, checkSidebar, 42 tests.

moduleApi is **1.9.0**, not the 1.7.0 the plan named -- Phase 11 moved it twice after that
sentence was written (1.8.0 for the `admin` ceiling, 1.9.0 for the module seed API).

## Also: the one page whose whole subject is the protocol number was the one page that
## hardcoded it

platform.json's own header says no version number is ever hardcoded in prose, and
`architecture/protocol-versions.mdx` had `4` written out three times -- the headline
sentence and both declaration-site rows. It now imports platform.json like every other
page that quotes a fact, so it moves with the JSON and cannot say 4 while the JSON says 5.

Note the interpolation is OUTSIDE the code spans: MDX does not evaluate an expression
inside backticks, so `PROTOCOL_VERSION: u32 = {platform.protocol}` would have rendered the
braces literally. Verified in the built HTML -- "currently 5", and no `platform.protocol`
survives anywhere in the output.

The same page's "what a bump obliges" section said version 4 was the first bump to need a
store migration, which read as though every bump does. v5 needed none (it only widens
frames the store already keeps whole -- docs link/v5.md), so the sentence now says which
did and which did not, and v5.md joins v4.md under canonical documents.

## The fill-in step, at merge time

Three values are not knowable today because the artefact does not exist yet. After the
bundle republishes, run:

    GITEA_TOKEN=<token> node scripts/checkFacts.mjs

and copy what it prints in the "says" column into src/data/platform.json:

  * bundle.tag, bundle.sidecar, bundle.overlay -- from installer bundles:current.json
  * releases.Module-uo -- if the cutover cuts a new module release
  * verifiedOn -- the date you ran it

Then re-read `getting-started/connect-a-game-server` and `administration/the-shard-connection`,
which quote the bundle, before merging. The check is green when all 19 agree.

AI-assisted: written with Claude Code.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech added 1 commit 2026-09-01 13:19:51 +00:00
wtclaude added 1 commit 2026-09-01 17:36:30 +00:00
Phase 13 landed while this branch waited: link/servuo-plugins/website/Module-uo
are all on main, the bundle was republished at 2026.09.01, and Module-uo cut
v1.1.0. These are the four values PLAN.md 12 said could not be written until the
republish existed, plus the two releases that moved with it.

Every one is the value checkFacts.mjs itself reports as the authority's answer:

  bundle.tag       2026.08.19 -> 2026.09.01
  bundle.sidecar   v2.0.0     -> v2.1.0
  bundle.overlay   v1.0.0     -> v1.1.0
  releases.link    v2.0.0     -> v2.1.0
  releases.Module-uo v1.0.2   -> v1.1.0
  verifiedOn       2026-08-19 -> 2026-09-01

No page hardcodes any of them -- every quote is an interpolation of
platform.bundle.* or platform.releases.*, so there is nothing else to re-read.

Co-Authored-By: Claude <noreply@anthropic.com>
wtclaude added 1 commit 2026-09-01 17:41:07 +00:00
The three checks that read another repository -- checkFacts, checkQuickstart,
checkReference -- fetched source files from the API's `raw` route, which answers
`Cache-Control: public, max-age=21600`. The CDN in front of Gitea caches that,
so the checks can read a blob most of a working day old.

It bit on cutover day. checkFacts reported

    FAIL  moduleApi
          platform.json says : 1.9.0
          website main:server/src/modules/version.js says : 1.6.0

against a `main` that says 1.9.0 -- the served copy was two weeks old
(`cf-cache-status: HIT`, `Age: 15713`, `last-modified: 18 Aug`). No edit in this
repository could have made it pass, and the same run reported a bundle triple
that had already been republished as still current: a stale read fails BOTH
ways, and the false pass is the dangerous one.

The `contents` endpoint answers `private, must-revalidate`, which the CDN
bypasses, so it is always the ref's current blob. The cost is a JSON parse and a
base64 decode. checkReference's canonical-document existence loop already used
it, which is why that half was never affected.

PLAN.md 12 records the finding next to the check it constrains.

Co-Authored-By: Claude <noreply@anthropic.com>
wtclaude changed title from WIP: chore(facts): protocol 5 and Module API 1.9.0 — DO NOT MERGE until the cutover to chore(facts): protocol 5, Module API 1.9.0, and the 2026.09.01 bundle 2026-09-01 17:41:55 +00:00
whitlocktech merged commit 5c6735bd1d into edge 2026-09-01 17:45:18 +00:00
whitlocktech deleted branch docs/platform-facts-protocol-5 2026-09-01 17:45:18 +00:00
Sign in to join this conversation.
No description provided.