fix(kit): everything the acceptance run found — Phase 5 slice 3
A cold agent was given this repo and the documents it links to, and nothing else — no core source, no module-uo — and asked to build a module for a second game. It did, in one pass. The record is docs/modules/kit-acceptance.md; this is the repair list, plus the two things it recommended that were not defects. The one it could not find, because it had no core to render against: a module page built exactly as this kit teaches renders OUTSIDE the site. PublicLayout is the chrome, not the body. Core grew an opt-in `shell` prop for it (MODULE_API_VERSION 1.5.0, website#148); the template passes shell="narrow" and chapter 2 explains why you name a width and never a class. Fixed: - **F1, and the worst of them, because it lands in the first twenty minutes.** `npm run check:swagger` failed on a PRISTINE template on Windows: the check compared the committed fragment byte-for-byte and a default Windows clone is CRLF while the generator writes LF. The message blamed "the routes or their annotations". Now `template/.gitattributes` pins `eol=lf` and the comparison normalises line endings anyway — a check may only fail for the reason it names, and this one names a diagnosis. - **F3** — `.gitea/workflows/release.yml` carries `gitea.example.com` and `your-org/your-module` under a literal `# CHANGE THESE`, was not in the rename checklist, and `checkRenameSites.js` could not match it, so CI was silent by construction. Row added, pattern widened. (The agent reported both workflow flavours; only the Gitea one is affected — GitHub supplies its own variables. Corrected in the record.) The near-miss is kept in the check's comments and its suite: the obvious widening is `example\.com`, which fires on a fixture URL in checkImports.test.js. Every alternative has to be a string that cannot occur by accident, which is the same rule that made the id `examplegame`. - **F4** — the release bundle's include list was hardcoded, so adding `server/utils/` would have silently dropped it from every release while the bundle check stayed green. Inverted to an exclusion list, in both flavours, and run by hand because a release workflow never executes in CI. - **F5** — the annotation-quoting warning was wrong in both directions, and the correction is measured rather than reasoned. A backtick is harmless (the template's own description has two spans and they survive). A `"` is not, and it does not throw: `'A "quoted" status'` is silently TRUNCATED to `A "` while swagger-autogen prints Success and the error capture sees nothing. The only signal is check:swagger blaming your routes. - **F6** — `template/.gitignore`, so a copied template that is `git init`ed inherits ignore rules instead of nothing. - **F7** — the UI kit is eight exports across five rows, not seven. The contract said seven and this kit had faithfully carried the miscount out of it. Adopted, not defects: - Chapter 1 now says to run every check on the untouched copy first. That is what found F1; without a baseline the first failure is ambiguous forever. - The template ships the §2.7 self-check the agent wrote for itself. The rule has no CI in general — an outbound socket is not statically detectable — but a module can make a decidable claim about its own tree. Ported from its code with a header explaining how to NARROW it when a sidecar client arrives, since talking to your sidecar is the expected shape and is not what §2.7 forbids. The pin moves to website edge 4ad8b2b, the 1.5.0 bump, and template/module.json declares ^1.5.0 — so checkCoreApi's equality assertion still holds and the template uses a member that exists only at that ref and later. 32 server + 18 client template tests, 21 kit-script tests, all four checks green. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -45,14 +45,14 @@ if (createElement !== rg.react.createElement || createRoot !== rg.reactDom.creat
|
||||
)
|
||||
}
|
||||
|
||||
// The curated kit (§3.4). Seven members, and it is CLOSED: layout, headings, the
|
||||
// The curated kit (§3.4). Eight exports, and it is CLOSED: layout, headings, the
|
||||
// three data-page states, the fetch hook, and read-only access to the session and
|
||||
// the site's settings. Anything else your pages need — tables, tabs, an editor —
|
||||
// you bundle yourself, in a `components/` directory of your own.
|
||||
//
|
||||
// Closed is a real constraint and it is the price of the boundary being worth
|
||||
// anything: adding a member is a minor `MODULE_API_VERSION` bump, and changing a
|
||||
// kit component's props is a major one. Use them, though. A module page that
|
||||
// anything: adding a member is a minor `MODULE_API_VERSION` bump, and changing an
|
||||
// existing prop on a kit component is a major one. Use them, though. A module page that
|
||||
// ships its own layout is a page that stops looking like the site it is installed
|
||||
// in, and drifts further every time core changes.
|
||||
export const {
|
||||
|
||||
@@ -3,13 +3,24 @@
|
||||
// An ordinary React component. Nothing about being inside a module changes how
|
||||
// you write one — the only differences are where React comes from (core, via the
|
||||
// aliases in vite.config.js, so the import below looks completely normal and is
|
||||
// not) and where the chrome comes from (`../../core.js`, the seven-member kit).
|
||||
// not) and where the chrome comes from (`../../core.js`, the shared UI kit).
|
||||
//
|
||||
// **Render `PublicLayout` yourself.** Core wraps your public routes in its
|
||||
// maintenance gate and nothing else, so a page that omits the layout renders
|
||||
// bare — no header, no footer, no site chrome — which looks like a bug and is
|
||||
// the contract (§3.3). Admin and player routes are the other way round: core
|
||||
// wraps those in their layouts for you.
|
||||
//
|
||||
// **And pass a `shell`.** The layout is the chrome; `shell` is the body — the
|
||||
// centred column, the vertical padding, and the thing that holds the footer at
|
||||
// the bottom of the viewport. Without it your content starts hard against the
|
||||
// left edge of the window and the footer rides up underneath it, which reads as
|
||||
// a CSS bug in your module and is not one. Widths are 'narrow', 'mid' and
|
||||
// 'wide'; name a width, never a class, because the classes belong to core's
|
||||
// stylesheet and it is free to rename them (§3.4, MODULE_API_VERSION 1.5.0).
|
||||
//
|
||||
// This is here because the kit's acceptance run got it wrong by following the
|
||||
// kit: a module built to the letter of chapter 2 rendered outside the site.
|
||||
|
||||
import { ErrorState, Loading, PageHeader, PublicLayout, useAsync } from '../../core.js'
|
||||
import api from '../../api.js'
|
||||
@@ -34,7 +45,7 @@ export default function WorldStatus() {
|
||||
const { data, loading, error } = useAsync(() => api.world.status(), [])
|
||||
|
||||
return (
|
||||
<PublicLayout>
|
||||
<PublicLayout shell="narrow">
|
||||
<PageHeader
|
||||
title="World status"
|
||||
subtitle="What the game server last told us about itself"
|
||||
|
||||
Reference in New Issue
Block a user