PLAN.md §16 phase 17, built on the org lead's answers of 2026-10-22,
recorded as D75-D79 (count of record 79).
- D75: core marketing pages describe what a game module adds in core's
words. "Game intelligence" became "What a game module adds"; each
game's own list moved to src/data/games/ and renders only on the new
/modules/uo/ and /modules/rust/. /modules/ is a card per game.
- The page-side capability check is per game (assertGameCoverage), the
item phase 13 moved here.
- D76: the homepage keeps its game screenshot, labelled. screens.mjs
entries may carry `game` (D67); Screenshot.astro and the app grid
print the game's name and mark the figure data-game.
- D77: /app/ describes the Rust screens (released the same day).
- D78: /runicnpc/, the standalone page, is in the header and footer;
the narrow header was re-measured so five links keep two rows.
- D79: checkTerms.mjs --built reads every built page's visible text
after the build; game routes and data-game elements allow their
game's words. Proven against ten plants. Still the twelfth check.
- Re-read fixes: /architecture/'s "two machines is also the maximum",
Discord "guild" on /integrations/, and collection.mjs against what
Steam sign-in and the Rust module keep (PLAY_DATA_SAFETY.md
regenerated; the Play answers are unchanged).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
platform.json drops the single protocol/bundle/capability list for a
`games` object (uo, rust) plus a `runicnpc` block. checkFacts.mjs loops
the protocol, plugin-protocol, capability and bundle checks over both
games, reads the schema-2 bundles at v2/<game>/current.json, checks each
module's coreApi, and reads RunicNPC's plugin.toml. 41 facts, up from 19;
clears the two that were red on main (Module API 1.17.0, installer
v0.8.0).
D66: the hero, footer and structured data show the Module API only; each
game's protocol and bundle go on that game's pages, and the docs landing
table splits into shared versions plus one column per game.
The re-read section 1 requires found, and this fixes:
- three hard-coded "1.6.0" Module API versions in the module docs
- module-lifecycle saying modules load alphabetically (the loader now
refuses a second module, W19), and the install pages never mentioning
the one-module rule
- "there is one module" in five places, now two modules both built
inside this project; the Integration Kit keeps its draft banner
- the homepage diagram's ServUO/uo-link sub-labels (D63 wording now)
notBuilt drops `second-module` (resolved by Module-Rust's release) and
rewords `multi-module`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
PLAN.md §13 phase 4: /features/, /architecture/, /modules/, /integrations/, and
/community/ — plus the two scope items the phase table never assigned to anyone.
Six decisions taken by the org lead before coding, recorded in PLAN.md §10 as
D20-D25:
- D20 /features/ is the homepage's list with a `detail` line, not a second list.
One data file, two renderings, so they cannot disagree about what exists.
- D21 /architecture/ draws reasons, not reference: three new inline SVGs, one per
boundary. No endpoint tables, no config keys — those are phase 8's and stay
canonical in docs/.
- D22 The deliberate absences of §2 become one tagged data file, rendered on the
three pages that promise them.
- D23 Phase 4 absorbs /community/ (specified in §10 and §14 N3, linked from the
header since phase 1, built by no phase) and checkLinks.mjs.
- D24 `needsModule`: writing the Teams detail exposed a false claim phase 3
shipped. Teams are module-sourced only — teams.module_id is NOT NULL, there is
no create route, sync is gated on providerModuleId() — so the Community group
no longer says a bare core does all of it.
- D25 The per-capability demo affordance brand.json had promised since phase 2 is
a deep link, filled at boot from data-demo-path.
checkLinks.mjs reads the built HTML rather than src/, because half these links
are assembled from data files and template literals. Its PLANNED_ROUTES list is
checked in both directions, so it cannot rot into a permanent exemption.
applyBrand.mjs gained a pass that recomputes deep links from their immutable
path, making it idempotent and reversible; checkBrand.mjs lifts that pattern out
and runs it against the stock markup so the two cannot drift. Both proved
against a real mount, in both directions.
Fixes a cascade bug the checks could not see: [data-demo-url=''] and a scoped
component class are both specificity 0,1,0, so .demo-link's `display` beat the
hide rule and twelve links to a nonexistent demo rendered, each resolving to the
current page. The rule is now !important.
The four diagrams' shared SVG vocabulary moved to src/styles/diagram.css.
Verified from a clean checkout: npm ci, all five checks, astro check (0 errors),
production build, and a live browser pass at desktop and 390px.
Co-Authored-By: Claude <noreply@anthropic.com>