docs(modules): close Phase 5 — the acceptance run, and the page shell it found

Slice 3 of Phase 5 (MODULE_SYSTEM.md 2.11.1), and the phase's last slice.

docs/modules/kit-acceptance.md is decision 5's deliverable: a cold agent given the
Integration Kit and the documents it links to — never core's source, never
module-uo — built a working module for a second game, which was then installed
into a real core and taken through MODULE_API.md 7.7's browser smoke. Verdict
recorded whichever way it went, and it went **yes, with caveats**: one pass, no
core source, and three of the four normative documents never opened.

The finding that justifies the two-stage shape is the one the agent structurally
could not reach, because it had no core to render against. A module page built
exactly as the kit teaches renders OUTSIDE the site: PublicLayout supplies the
chrome and not the body, and the `shell-... page-body` wrapper every core public
page writes for itself is two class names that appear in no contract. That is
3.4's own stated failure — "a module page that does not look like the site it is
installed in" — reached by following 3.4.

Fixed in core rather than documented at the reader, so the class names stay
core's private business and the theming workstream keeps its freedom to rename
them: PublicLayout takes an opt-in `shell` width, MODULE_API_VERSION 1.5.0
(website#148, merges first).

- MODULE_API.md 1.1: 1.5.0's entry, and a new bump-table row — adding an
  OPTIONAL prop or argument is minor. "A member's signature changes" is major
  because a call already written changes meaning, and an optional prop changes
  none; the table now says what it means rather than leaving it to be argued.
- MODULE_API.md 3.4: the shell prop, why a module names a width and never a
  class, and the eight-vs-seven miscount the run also turned up — the kit had
  faithfully carried it out of the contract into the template, which is the
  never-re-specify rule working exactly as designed on a wrong input.
- rust-dryrun.md: coreApi ^1.3.0 -> ^1.5.0, as a dated correction per decision 33.
  It is the only complete module.json in the kit's reading path and nothing
  checks a JSON block inside a Markdown file, which is the reusable half.
- MODULE_SYSTEM.md 2.11.1: slice 3 recorded, plus the third finding worth
  generalising — a check whose failure message asserts a diagnosis has to be
  right about it. `check:swagger` failed on a pristine template on Windows
  (CRLF) while blaming the routes, green on the Linux runner forever.
- Decision 34: core owns the page body as well as the chrome.

The banner does not come off. Decision 32 makes that a person's to remove, this
run exercised the website-module half only (the module has no sidecar, so
chapters 3 and 4 were never tested), and an agent does not skim or give up.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-12 14:28:26 -05:00
parent c6f4c2478f
commit 3116e7bbf6
4 changed files with 248 additions and 12 deletions

View File

@@ -27,7 +27,7 @@ in. If the contract survives that, "game-agnostic" means something.
"id": "rust",
"name": "Rust",
"version": "0.1.0",
"coreApi": "^1.3.0",
"coreApi": "^1.5.0",
"server": "server/index.js",
"client": { "entry": "client/dist/entry.js" },
"schema": "server/db/schema.sql",
@@ -42,6 +42,17 @@ in. If the contract survives that, "game-agnostic" means something.
}
```
> **Correction, 2026-08-12.** `coreApi` read `^1.3.0` here until the Integration Kit's acceptance run
> ([`kit-acceptance.md`](kit-acceptance.md)) found it. The contract was at 1.3.0 when this design was
> written and has moved twice since; the number is now `^1.5.0`. Left as a correction rather than a
> silent edit because *why* it went stale is the reusable part: this is the only complete `module.json`
> in the kit's reading path, so it is what a newcomer copies — and unlike the template, which CI holds
> against core's `MODULE_API_VERSION` on every pull request
> ([`../website/MODULE_SYSTEM.md`](../website/MODULE_SYSTEM.md) §2.11.1 d2), **a JSON block inside a
> Markdown document has nothing checking it.** A range is also the shape least likely to be noticed
> when it rots: `^1.3.0` is *satisfied* by a 1.5.0 core, so a module copied from here would have loaded
> fine and simply been wrong about what it was written against.
One prefix per tier, named for the module rather than for a feature — the opposite of module-uo's
`/shard` + `/atlas` + `/uo-link`, and the better choice for anything new. Module-uo's prefixes are
what they are because §1.2 froze the URLs core already served; a module written today has no such