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>
59 lines
3.5 KiB
JavaScript
59 lines
3.5 KiB
JavaScript
// ── Public · World ────────────────────────────────────────────────────────
|
||
//
|
||
// Mounted at `/api/v1/public/world` by `index.js`. One express Router, built
|
||
// from CORE's express (`core.express`) — never from a `require('express')` of
|
||
// your own, which would not resolve from here anyway (MODULE_API.md §7.2).
|
||
//
|
||
// **The tier's gate is already on.** This router sits inside core's public tier,
|
||
// which is behind nothing by design — the public API is public. Per-route
|
||
// middleware goes on top, and `siteMode` below is the one worth understanding:
|
||
// it is what makes a page respect the operator's maintenance switch. Core applies
|
||
// it to its own content routes (`/posts`, `/wiki`) and deliberately does not
|
||
// apply it to its status endpoints, because status is exactly what an operator
|
||
// wants visible *during* maintenance. Which of those two your route is depends on
|
||
// what it serves, and it is your decision to make.
|
||
//
|
||
// ── About the `#swagger` comments ─────────────────────────────────────────
|
||
//
|
||
// They are not documentation *of* the code, they are the source the OpenAPI
|
||
// fragment is generated from — `npm run swagger` parses this file (§2.8). Two
|
||
// rules that cost this project real time:
|
||
//
|
||
// • swagger-autogen reads these as JavaScript literals it evaluates, so a
|
||
// QUOTE CHARACTER inside a single-quoted description ends the string early.
|
||
// Both `'` and `"` — use a typographic apostrophe (’) in prose, and rewrite
|
||
// a quoted phrase without the quotes. A backtick is fine: Markdown spans like
|
||
// `online: false` below survive verbatim, and the fragment shows them.
|
||
//
|
||
// **The failure is silent, and this is the part worth remembering.** It is
|
||
// not always a parse error you get told about. A `"` in the middle of a
|
||
// description truncates the value at that character — `'A "quoted" status'`
|
||
// becomes `A "` — while swagger-autogen prints `Success` in green and the
|
||
// error capture below sees nothing to capture, because nothing threw. The
|
||
// only signal is `npm run check:swagger` reporting the fragment stale, whose
|
||
// message will blame your routes. When it does and your routes did not
|
||
// change, look for a quote in an annotation before you look anywhere else.
|
||
// (Measured, not inferred: docs/modules/kit-acceptance.md, F5.)
|
||
// • A `\'` escape is valid JavaScript and wrong here: the annotation is never
|
||
// evaluated as JS by the reader, so Swagger UI renders the backslash.
|
||
|
||
const core = require('../../core')
|
||
|
||
const express = core.express
|
||
const world = require('./world.controller')
|
||
const { siteMode } = core.middleware
|
||
|
||
const worldRouter = express.Router()
|
||
|
||
worldRouter.get(
|
||
'/status',
|
||
// #swagger.tags = ['Public · Example Game']
|
||
// #swagger.summary = 'The game world’s current status'
|
||
// #swagger.description = 'What the game server last reported: whether it is up, how many players are on, and when that was. Answers with `online: false` and `stale: true` rather than failing when the game or its sidecar is unreachable — the site’s availability does not depend on the game’s.'
|
||
/* #swagger.responses[200] = { description: 'The world’s status', content: { "application/json": { schema: { $ref: "#/components/schemas/ExamplegameWorldStatus" } } } } */
|
||
siteMode,
|
||
world.getStatus,
|
||
)
|
||
|
||
module.exports = worldRouter
|