fix(kit): everything the acceptance run found — Phase 5 slice 3
All checks were successful
PR Checks / prose (pull_request) Successful in -38s
PR Checks / template (pull_request) Successful in 29s

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:
2026-08-12 14:40:02 -05:00
parent d5a8520ce0
commit f8f7014d53
16 changed files with 362 additions and 36 deletions

View File

@@ -19,13 +19,21 @@
// 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. It
// re-quotes `"` and a backtick to `'` first, so either one inside a
// single-quoted description ends the string early — and when it cannot parse
// an annotation it drops that annotation, prints an error, and then reports
// success. Use a typographic apostrophe () in prose. `swaggerFragment.js`
// captures those errors and makes them fatal, which is the only reason you
// will find out.
// • 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.