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:
@@ -47,6 +47,30 @@ cp -r template/ ~/my-module
|
||||
cd ~/my-module
|
||||
```
|
||||
|
||||
**Run every check on the untouched copy before you change a line.** Jump ahead to
|
||||
*Build it* and run all of it — the tests, the build, the three guards — on the
|
||||
template exactly as it arrived:
|
||||
|
||||
```bash
|
||||
npm ci --prefix server && npm test --prefix server
|
||||
npm run check:imports --prefix server
|
||||
npm run check:swagger --prefix server
|
||||
npm ci --prefix client && npm run build --prefix client
|
||||
npm run check:externals --prefix client && npm test --prefix client
|
||||
```
|
||||
|
||||
It takes two minutes and it buys you a **baseline**. Every one of those commands
|
||||
is green on a pristine template, so from here on a red one is something you did —
|
||||
and you will know which edit did it, because you were green a moment ago. Without
|
||||
that, the first failure is ambiguous forever: is this my mistake, or was the
|
||||
template already like this?
|
||||
|
||||
That is not a hypothetical. The kit's own acceptance run
|
||||
([`kit-acceptance.md`][acceptance]) found `check:swagger` failing on an untouched
|
||||
copy on Windows, with a message that blamed the reader's routes. It is fixed, and
|
||||
the reason the run *found* it rather than being derailed by it is that it had a
|
||||
baseline.
|
||||
|
||||
Your module id is the single most load-bearing string in it: it is the directory
|
||||
core loads you from, the key in core's database, the URL segment every one of your
|
||||
pages hangs under, and the prefix every one of your tables must carry. It must
|
||||
@@ -242,3 +266,4 @@ module must never do.
|
||||
[api]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/MODULE_API.md
|
||||
[issues]: https://gitea.whitlocktech.com/RunicGateway/Integration-kit/issues
|
||||
[renamecheck]: ../scripts/checkRenameSites.js
|
||||
[acceptance]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/modules/kit-acceptance.md
|
||||
|
||||
@@ -392,12 +392,34 @@ and empty states, the async hook every data page uses, and read-only access to t
|
||||
session and site settings. Enough to build a page that looks like the site it is
|
||||
installed in, and nothing else.
|
||||
|
||||
**`PublicLayout` needs a `shell`, and this is the one that will catch you.** The
|
||||
layout is the *chrome* — header, footer, the flex column they sit in. The `shell`
|
||||
prop is the *body*: the centred max-width column, the vertical padding, and the
|
||||
element whose `flex: 1` is the only thing holding the footer at the bottom of the
|
||||
viewport.
|
||||
|
||||
```jsx
|
||||
<PublicLayout shell="narrow"> // 'narrow' · 'mid' · 'wide'
|
||||
```
|
||||
|
||||
Omit it and your content starts hard against the left edge of the window with no
|
||||
padding, and the footer climbs up underneath it. It reads as a stylesheet bug in
|
||||
your module and it is not one — core's own pages write that wrapper by hand, and
|
||||
before `MODULE_API_VERSION` 1.5.0 a module had no way to. **Name a width, never a
|
||||
class:** the class names are core's stylesheet's and it is free to rename them,
|
||||
which is exactly why they are not in the contract and this prop is.
|
||||
|
||||
That paragraph exists because the kit's acceptance run
|
||||
([`kit-acceptance.md`][acceptance]) built a module by following this chapter to the
|
||||
letter, and its page rendered outside the site. Everything else it wrote was right.
|
||||
|
||||
**It is curated and closed, not a re-export of core's component library.** Adding
|
||||
to it is a minor version bump; changing a kit component's props is a major one.
|
||||
to it is a minor version bump, and so is adding an optional prop to a member;
|
||||
changing an existing prop is a major one.
|
||||
That is a real constraint on core, and it is the price of the boundary being worth
|
||||
anything.
|
||||
|
||||
So: when you want an eighth thing, bundle it. Tables, chips, tabs, editors — those
|
||||
So: when you want something it does not have, bundle it. Tables, chips, tabs, editors — those
|
||||
are yours, and your chunk carries them. Reaching into core's tree for a component
|
||||
is the one thing that is never available, and `template/server/scripts/checkImports.js`
|
||||
exists to make sure a moment of weakness fails the build instead of shipping.
|
||||
@@ -433,10 +455,26 @@ nothing at runtime will ever say so.
|
||||
The trap: **swagger-autogen reports a broken annotation and then prints
|
||||
`Success`.** It logs a syntax error, drops that annotation, and exits zero. The
|
||||
template's generator captures those diagnostics and fails on them — keep that.
|
||||
Two ways an annotation breaks are an object literal one brace short, and a `"` or
|
||||
a backtick inside a single-quoted description. A third is only visible in a
|
||||
rendered page: an escaped apostrophe (`\'`) survives literally into the output,
|
||||
because the annotation is never evaluated as JavaScript. Use a typographic `’`.
|
||||
The usual cause is an object literal one brace short.
|
||||
|
||||
**A quote character is worse, because it does not log anything.** These
|
||||
annotations are evaluated as JavaScript literals, so a `'` or a `"` inside a
|
||||
single-quoted description ends the string early — and for a `"` in the middle of
|
||||
a sentence the result is not an error at all. The value is silently **truncated**
|
||||
at that character:
|
||||
|
||||
```js
|
||||
// #swagger.summary = 'A "quoted" world status'
|
||||
// → "summary": "A \"" and swagger-autogen still prints Success
|
||||
```
|
||||
|
||||
Nothing throws, so the generator's error capture has nothing to capture. The only
|
||||
signal is `check:swagger` calling the fragment stale, with a message that blames
|
||||
your routes. **If that check fires and your routes did not change, look for a
|
||||
quote in an annotation first.** Backticks are safe — Markdown spans survive
|
||||
verbatim. And an escaped apostrophe (`\'`) is a third case, visible only in a
|
||||
rendered page: the annotation is never evaluated as JavaScript by the reader, so
|
||||
Swagger UI shows the backslash. Use a typographic `’` throughout.
|
||||
|
||||
## Packaging and release
|
||||
|
||||
@@ -485,3 +523,4 @@ it** — an outbound socket is not statically detectable the way an internal
|
||||
the next chapter is for.
|
||||
|
||||
[api]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/MODULE_API.md
|
||||
[acceptance]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/modules/kit-acceptance.md
|
||||
|
||||
Reference in New Issue
Block a user