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

Merged
whitlocktech merged 1 commits from docs/module-phase5-slice3 into main 2026-08-12 19:34:04 +00:00
Member

Slice 3 of Phase 5 (§2.11.1), and the phase's last slice. Second of four PRswebsite#148 should merge first (it carries 1.5.0, which this documents and which the kit's CI then pins to).

docs/modules/kit-acceptance.md — decision 5's deliverable

A cold agent, given the kit and the five documents it links to and denied core's source and module-uo, was asked to build a module for a second game. What it produced was then installed into a real core on edge and taken through MODULE_API.md §7.7's browser smoke.

Verdict: yes, with caveats. One pass, no core source, and three of the four normative documents never opened. It built module-rust — two public routes over two tables, a chunk with two pages and a nav row, 44 server + 18 client tests, every guard green — and it loaded into a real core against an empty database: schema replayed, onBoot ran, started, both routes serving, deep-linked param route rendering on a cold load, zero CSP reports, zero console errors.

The record includes the method, the findings, and an honest note that isolation was a clean tree plus instructions plus a self-reported read list, not a sandbox — a subagent inherits the workspace as its shell default. A future run should put the agent somewhere it cannot reach core.

The finding that justifies the two-stage shape

The agent could not have found the worst defect: 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; the shell-… page-body wrapper each of core's nine public pages writes for itself is two class names appearing in no contract. Content at x=0, no padding, footer riding up underneath. 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.

Contract changes

  • §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 at the next bump.
  • §3.4 — the shell prop, why a module names a width and never a class, the footer symptom (it looks like a CSS bug in the module rather than a missing wrapper), and the eight-vs-seven miscount the run also turned up. The kit had faithfully carried that miscount out of the contract and into the template — the never-re-specify rule working exactly as designed, on a wrong input.
  • rust-dryrun.mdcoreApi ^1.3.0^1.5.0, as a dated correction (decision 33). It is the only complete module.json in the kit's reading path, and the reusable half is that nothing checks a JSON block inside a Markdown file — where the template has CI holding it against core's version on every PR. 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.
  • §2.11.1 — slice 3 recorded, including 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 vs the LF it writes) while blaming "the routes or their annotations" — green on the Linux runner forever, and the first command the kit tells a reader to run.
  • Decision 34 — core owns the page body as well as the chrome.

Also from the run, adopted rather than merely recorded

Chapter 1 will tell readers to run every check on the untouched copy first (that is what found the CRLF defect — without a baseline the agent would have blamed its own edits), and the template will ship the §2.7 self-check the agent wrote for itself: the rule has no CI in general, but a module can make a decidable claim about its own tree. Both land in the Integration-kit PR.

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, get frustrated, or give up.

Sequencing

website#148 → this → Integration-kit (template + chapters, six findings, pin moves to 1.5.0) → .profile.


  • AI-assisted: written with Claude Code (Claude Opus 5); commits carry a Co-Authored-By trailer.
Slice 3 of Phase 5 (§2.11.1), and the phase's last slice. **Second of four PRs** — `website#148` should merge first (it carries 1.5.0, which this documents and which the kit's CI then pins to). ## `docs/modules/kit-acceptance.md` — decision 5's deliverable A cold agent, given the kit and the five documents it links to and **denied core's source and `module-uo`**, was asked to build a module for a second game. What it produced was then installed into a real core on `edge` and taken through `MODULE_API.md` §7.7's browser smoke. **Verdict: yes, with caveats.** One pass, no core source, and three of the four normative documents never opened. It built `module-rust` — two public routes over two tables, a chunk with two pages and a nav row, 44 server + 18 client tests, every guard green — and it loaded into a real core **against an empty database**: schema replayed, `onBoot` ran, `started`, both routes serving, deep-linked param route rendering on a cold load, zero CSP reports, zero console errors. The record includes the method, the findings, and an honest note that isolation was a clean tree plus instructions plus a self-reported read list, **not a sandbox** — a subagent inherits the workspace as its shell default. A future run should put the agent somewhere it cannot reach core. ## The finding that justifies the two-stage shape The agent **could not** have found the worst defect: 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; the `shell-… page-body` wrapper each of core's nine public pages writes for itself is two class names appearing in no contract. Content at x=0, no padding, footer riding up underneath. 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**. ## Contract changes - **§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 at the next bump. - **§3.4** — the `shell` prop, why a module names a *width* and never a class, the footer symptom (it looks like a CSS bug in the module rather than a missing wrapper), and the **eight-vs-seven** miscount the run also turned up. The kit had faithfully carried that miscount *out* of the contract and into the template — 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 (decision 33). It is the only complete `module.json` in the kit's reading path, and the reusable half is that **nothing checks a JSON block inside a Markdown file** — where the template has CI holding it against core's version on every PR. 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. - **§2.11.1** — slice 3 recorded, including 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 vs the LF it writes) while blaming "the routes or their annotations" — green on the Linux runner forever, and the first command the kit tells a reader to run. - **Decision 34** — core owns the page body as well as the chrome. ## Also from the run, adopted rather than merely recorded Chapter 1 will tell readers to run every check on the untouched copy first (that is what found the CRLF defect — without a baseline the agent would have blamed its own edits), and the template will ship the §2.7 self-check the agent wrote for itself: the rule has no CI *in general*, but a module can make a decidable claim about its own tree. Both land in the `Integration-kit` PR. **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, get frustrated, or give up. ## Sequencing `website#148` → this → `Integration-kit` (template + chapters, six findings, pin moves to 1.5.0) → `.profile`. --- - [x] AI-assisted: written with Claude Code (Claude Opus 5); commits carry a `Co-Authored-By` trailer.
wtclaude added 1 commit 2026-08-12 19:28:58 +00:00
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>
whitlocktech merged commit 4eec823741 into main 2026-08-12 19:34:04 +00:00
whitlocktech deleted branch docs/module-phase5-slice3 2026-08-12 19:34:05 +00:00
Sign in to join this conversation.
No description provided.