docs(website): record slice 3, and MODULE_API 1.3.0 #138

Merged
whitlocktech merged 1 commits from docs/module-extract-client into main 2026-08-12 00:35:17 +00:00
Member

The docs third of Phase 3 slice 3 — Module-uo#4 (merge first) and website#139.

MODULE_API.md — 1.2.0 → 1.3.0

Three client additions, all because the extraction needed them and none speculative:

  • icon on a nav item (§3.3), with the rule that core supplies no fallback and a module should match the nav its row lands in — the admin sidebar draws at 18px/1.6 stroke, the portal at 16px/2. Deliberately not in the kit: putting core's icon frame in the contract would make changing it a major bump.
  • player.invite.accepted, a third slot (§3.7).
  • api.BASE, which §3.5 specified from the first draft and shared.js had never published — nothing needed it until a module had to build an EventSource URL.

Two corrections to text that was wrong rather than merely incomplete:

§2.3's narrowing note said ctx.settings is three functions because the model's other names are "registration/game-signup/app-links policy that is core's business". Game-signup was wrong in both directions: the setting's help text names Bridge.cfg, so it was never core's — and slice 1 had shipped a ported controller calling settings.isGameAccountSignupEnabled(), which the narrowing does not expose, so POST /player/shard/account answered 500 for every caller until slice 3 found it. A narrowing is only as safe as the tests that cross it.

§3.7 gains the rule the invite slot forced. Slice 2 said there is no hasExtension to branch on, full stop; that is right about decoration and wrong about control flow. The rule is now: core may ask whether a slot is filled when the answer changes control flow, never when it changes decoration — decoration goes inside <Slot wrap>, which is the footer-separator bug. AcceptInvite is the only caller in core.

§7.7 gains what running the smoke against the real module found, as opposed to a throwaway: the unguarded portal icon (React error #130, blank portal), the relative-MODULES_DIR trap, and two operational notes — a copied module needs its own npm ci --omit=dev before it will register, and copy the directory rather than symlinking it.

MODULE_SYSTEM.md — the slice 3 record

The measurement is corrected in the slice table: 35 files / 5,332 lines, not 51 / ~3,700. Fewer files, more lines; the table is corrected rather than the count re-derived to match it.

The record covers the /player index (resolved from the base nav rather than named, so a future merged logged-in area reuses it instead of unwinding a landing page), the game_account_signup move and the slice-1 crash it exposed, the accepted Android break, what the browser found, and the two checkExternals.js defects — a false positive that rejected the build over the word "import" in a button label, and the false negative underneath it that could never see import{useState}from"react", the one shape a minified build emits.

The nav-override cost is recorded as worse than it was predicted to be. Decision 9 was accepted as "a hidden row may reappear". The review instance shows the real shape: the operator had gathered the nine UO rows into a dropdown section, and every one of those override keys now matches nothing — the section is empty and the rows render flat across two lines of the header. The release note is that an operator's ordering, labels, hidden state and grouping of the UO rows are lost and must be redone.

Also

  • BACKEND_DESIGN.md: /public/settings no longer derives gameAccountSignup.
  • android/PLAN.md: an OWED note for the shipped app, which reads that field and will silently stop offering game-account creation. One DTO field, one ViewModel line, two tests — deferred by the org lead, but it must land before the workstream's cutover reaches main.
  • api-route-inventory.json was a slice stale (228 routes, pre-slice-1); refreshed to the 158 core actually serves. Worth noting for the next slice: this mirror is hand-copied and slice 1's docs PR missed it.

AI disclosure

Written with Claude Code.

Co-Authored-By: Claude noreply@anthropic.com

The docs third of Phase 3 slice 3 — Module-uo#4 (merge first) and website#139. ## `MODULE_API.md` — 1.2.0 → 1.3.0 Three client additions, all because the extraction needed them and none speculative: - **`icon`** on a nav item (§3.3), with the rule that core supplies **no fallback** and a module should match the nav its row lands in — the admin sidebar draws at 18px/1.6 stroke, the portal at 16px/2. Deliberately not in the kit: putting core's icon frame in the contract would make changing it a major bump. - **`player.invite.accepted`**, a third slot (§3.7). - **`api.BASE`**, which §3.5 specified from the first draft and `shared.js` had never published — nothing needed it until a module had to build an EventSource URL. Two corrections to text that was wrong rather than merely incomplete: **§2.3's narrowing note** said `ctx.settings` is three functions because the model's other names are "registration/game-signup/app-links policy that is core's business". Game-signup was wrong in both directions: the setting's help text names *Bridge.cfg*, so it was never core's — and slice 1 had shipped a ported controller calling `settings.isGameAccountSignupEnabled()`, which the narrowing does not expose, so `POST /player/shard/account` answered **500 for every caller** until slice 3 found it. A narrowing is only as safe as the tests that cross it. **§3.7** gains the rule the invite slot forced. Slice 2 said there is no `hasExtension` to branch on, full stop; that is right about decoration and wrong about control flow. The rule is now: core may ask whether a slot is filled **when the answer changes control flow, never when it changes decoration** — decoration goes inside `<Slot wrap>`, which is the footer-separator bug. `AcceptInvite` is the only caller in core. **§7.7** gains what running the smoke against the *real* module found, as opposed to a throwaway: the unguarded portal icon (React error #130, blank portal), the relative-`MODULES_DIR` trap, and two operational notes — a copied module needs its own `npm ci --omit=dev` before it will register, and copy the directory rather than symlinking it. ## `MODULE_SYSTEM.md` — the slice 3 record The measurement is corrected in the slice table: **35 files / 5,332 lines**, not 51 / ~3,700. Fewer files, more lines; the table is corrected rather than the count re-derived to match it. The record covers the `/player` index (resolved from the base nav rather than named, so a future merged logged-in area reuses it instead of unwinding a landing page), the `game_account_signup` move and the slice-1 crash it exposed, the accepted Android break, what the browser found, and the two `checkExternals.js` defects — a false positive that rejected the build over the word "import" in a button label, and the false negative underneath it that could never see `import{useState}from"react"`, the one shape a minified build emits. **The nav-override cost is recorded as worse than it was predicted to be.** Decision 9 was accepted as "a hidden row may reappear". The review instance shows the real shape: the operator had gathered the nine UO rows into a **dropdown section**, and every one of those override keys now matches nothing — the section is empty and the rows render flat across two lines of the header. The release note is that an operator's ordering, labels, hidden state **and grouping** of the UO rows are lost and must be redone. ## Also - **`BACKEND_DESIGN.md`**: `/public/settings` no longer derives `gameAccountSignup`. - **`android/PLAN.md`**: an OWED note for the shipped app, which reads that field and will silently stop offering game-account creation. One DTO field, one ViewModel line, two tests — deferred by the org lead, but it must land before the workstream's cutover reaches `main`. - **`api-route-inventory.json`** was a slice stale (228 routes, pre-slice-1); refreshed to the 158 core actually serves. Worth noting for the next slice: this mirror is hand-copied and slice 1's docs PR missed it. ## AI disclosure Written with Claude Code. Co-Authored-By: Claude <noreply@anthropic.com>
wtclaude added 1 commit 2026-08-12 00:02:39 +00:00
The client half's move: 35 files / 5,332 lines (the table said 51 / ~3,700 and
is corrected, not re-derived to match). The seven-kit-members-plus-format claim
held exactly, so the kit needed no additions.

Contract, 1.2.0 -> 1.3.0, all additive: `icon` on a nav item, a third slot
`player.invite.accepted`, and `api.BASE` — which §3.5 specified from the first
draft and shared.js had never published, because nothing needed it until a
module had to build an EventSource URL.

§2.3's narrowing note said game-signup policy was core's business. It was wrong
in both directions: the setting's help text names Bridge.cfg, and slice 1 had
shipped a controller calling a function the narrowing does not expose, so
POST /player/shard/account answered 500 for every caller until this slice.

§3.7 gains the rule the invite slot needed: core may ask whether a slot is
filled when the answer changes CONTROL FLOW, never when it changes decoration.
Decoration goes inside `<Slot wrap>` — that is the footer-separator bug.

§7.7 gains what running it against the real module found, rather than a
throwaway: the unguarded portal icon, the relative-MODULES_DIR trap, and the two
operational notes (a module needs its own npm ci; copy the directory, never
symlink it).

Also recorded: the nav-override cost is worse than "a hidden row may reappear" —
the review instance had the nine UO rows gathered into a dropdown section, and
the whole section is lost. And `api-route-inventory.json` was a slice stale at
228 routes; refreshed to the 158 core actually serves.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech approved these changes 2026-08-12 00:34:50 +00:00
whitlocktech merged commit 1b8c2e4806 into main 2026-08-12 00:35:17 +00:00
whitlocktech deleted branch docs/module-extract-client 2026-08-12 00:35:18 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RunicGateway/docs#138
No description provided.