docs(builder): phase 8 — modules, architecture and reference
All checks were successful
PR checks / checks (pull_request) Successful in 1m13s

Twenty pages completing the tree section 10 planned: Modules (8), Architecture
(5) and Reference (7). Four decisions, D38-D41, recorded in PLAN.md section 10.

D39 is the one that shaped the phase. Section 1 forbids re-specifying a
contract, and a Reference section is exactly where that rule is most tempting to
break, so the line is drawn at names: every environment variable, config key,
installer command, visibility rung and canonical document is listed with one
terse line saying what it is FOR, while shapes, semantics and every "why" stay
in the canonical document.

That is only safe because the names are checked. checkReference.mjs compares six
enumerations against the repositories that own them, over the Gitea API, as set
comparisons in BOTH directions -- and the second direction is the one that earns
its keep, because a reference page does not usually rot by describing something
that vanished, it rots by quietly not mentioning what was added since.

The check went green on its first run, which is the least trustworthy possible
outcome, so it was verified by breaking it: seven mutations, all caught. The one
worth keeping is the visibility ladder REORDERED with its membership unchanged
-- it is a security boundary, and a set comparison alone would have passed it.

D41 turns plannedSidebar from a checklist into a checked invariant, and finding
out why was the phase's first defect: it had already drifted, because phase 7
added the Content page under D37 and never updated the list. Nothing failed,
because nothing read it. checkSidebar.mjs now asserts the two trees agree on
groups, labels and order -- order because the order of Getting started IS the
installation path.

Two more things the writing found. PLAN.md's page count was wrong and had been
since section 10 was written ("roughly 38, 37 planned" for a tree of forty).
And module.json's `mounts` and the SPA's paths are different mechanisms that no
single document stated plainly -- module-uo declares admin: ["/shard",
"/uo-link"] while its screen lives at /admin/uo/link, because API routes are
deliberately NOT namespaced while SPA routes are. That is precisely the
distinction the installer got wrong in v0.1.0, and it now has a named home.

D40: the docs link to /architecture/'s drawn diagrams rather than importing
them. Those components carry marketing chrome and depend on diagram.css, which
Starlight does not load; the docs use text diagrams, which paste into an issue.

npm run verify green: 40 pages across 5 groups agree with plannedSidebar, 2390
internal links resolve, 123 repository links point at a branch, 19 facts, 59
quickstart checks, 22 reference enumerations, astro check 0 errors, 36 tests.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-24 12:17:31 -05:00
parent e8cb6061fe
commit d89ce06bb8
27 changed files with 2794 additions and 8 deletions

82
PLAN.md
View File

@@ -236,7 +236,7 @@ Taken by the org lead (Colby Whitlock) on 2026-08-19. Recorded so they are not r
**Decisions after D13 are recorded where they were taken**, in the section describing the phase that
raised them, rather than appended here — a decision is only re-litigated when its reasoning is
somewhere other than the thing it decided. The count of record is **thirty-seven**:
somewhere other than the thing it decided. The count of record is **forty-one**:
| # | Where | What it settled |
|---|---|---|
@@ -246,6 +246,7 @@ somewhere other than the thing it decided. The count of record is **thirty-seven
| D26D29 | §8, "How phase 5 built the app and the beta" | The screenshot slot reserved for phase 9, the demo as the tester target, `/beta` handling its own POST, equal billing for the APK and the beta |
| D30D33 | §9, "How phase 6 built the legal pages" | One logging hop and no edge provider, eighteen or older, no governing-law clause, the Data Safety notes as a generated document |
| D34D37 | §10, "How phase 7 built the documentation journey" | One PR for all twenty pages, a self-contained install quickstart with a drift check, every admin screen walked before it was described, a thirteenth Administration page for content |
| D38D41 | §10, "How phase 8 built the builder and reference docs" | One PR for all twenty pages again, Reference enumerates names and checks every one of them, the docs section links to the drawn diagrams rather than importing them, `plannedSidebar` becomes a checked invariant |
---
@@ -837,7 +838,7 @@ Reference Environment variables · Installer CLI · sidecar.toml ·
Bridge.cfg · HTTP API · Event catalog · Canonical documents
```
Roughly 38 pages — 37 planned, plus the Content page D37 added in phase 7. Every Reference page is a **navigable summary plus a link to the canonical
**Forty pages** — thirty-nine planned, plus the Content page D37 added in phase 7. (This said "roughly 38, 37 planned" until phase 8 counted the tree: 7 + 13 + 8 + 5 + 7. `checkSidebar.mjs` now keeps the count honest.) Every Reference page is a **navigable summary plus a link to the canonical
document** — never a re-specification, per §1.
### The installation path
@@ -938,6 +939,79 @@ and phase 6 (the card void) for the same lesson.
---
### How phase 8 built the builder and reference docs
Twenty more pages — Modules (8), Architecture (5), Reference (7) — completing the tree §10
planned. Four decisions, taken by the org lead before anything was written.
**D38 — one PR for all twenty pages, again.** The alternative on the table was splitting the
prose (Modules + Architecture) from Reference, since only Reference needed new checking
machinery. Rejected for the same reason D34 was: the three sections cross-reference each
other heavily, and a split means either landing pages whose links point at nothing yet or
writing the links twice.
**D39 — Reference enumerates the NAMES, and checks every one of them.** This is the phase's
central decision, because §1 forbids re-specifying a contract and a Reference section is
exactly where that rule is most tempting to break.
The line drawn: **names are on the page, semantics are not.** Every environment variable,
config key, installer command, visibility rung and canonical document is listed, with one
terse line saying what it is *for*. Shapes, defaults that matter, interactions and every
"why" stay in the canonical document.
That is only safe because `scripts/checkReference.mjs` compares each list against the
repository that owns it — six sources, over the Gitea API, never from a working tree — as a
**set comparison in both directions**. The second direction is the one that earns its keep:
a reference page does not usually rot by describing something that vanished, it rots by
quietly not mentioning the three things added since it was written.
The alternative considered was strict summary-plus-link with nothing enumerated. It needs no
machinery and cannot rot — but a Reference section that cannot answer "what variables are
there?" without a click-through is a link farm, and the checking machinery turned out to be
one script.
Descriptions are deliberately **not** checked, and the script says so. Nothing can know
whether a one-line summary is still true; keeping them short enough to re-read is the
mitigation, not a check.
**D40 — the docs link to the drawn diagrams rather than importing them.** `/architecture/`'s
three diagrams are Astro components carrying marketing chrome and depending on
`src/styles/diagram.css`, which Starlight does not load. Reusing them inside the docs would
have coupled the two layouts for one page's benefit. The docs use text diagrams in code
blocks — which are also copy-pasteable into an issue — and link out to the drawn versions.
**D41 — `plannedSidebar` stops being a checklist and becomes a checked invariant.** It was
written in phase 1 so phases 7 and 8 had their checklist where they would be working. With
every page now written it is a second, hand-maintained copy of the live tree, which is the
exact shape §1 warns about — so `checkSidebar.mjs` asserts the two agree on groups, labels
**and order**.
Order, because the order of "Getting started" *is* the installation path, and a reordering
nobody noticed would be a worse defect than a missing page.
**What the checks found, before any of the pages shipped.**
- **`plannedSidebar` had already drifted.** Phase 7 added the Content page under D37 and
never updated the planned list. Nothing failed, because nothing read it — which is the
whole argument for D41. Reproduced by deleting the entry again and watching the new check
catch it.
- **The page count in this document was wrong**, and had been since §10 was written: it said
"roughly 38 — 37 planned", where the tree it describes is forty.
- **`module.json`'s `mounts` and the SPA's paths are different mechanisms**, which is not
stated plainly in any one place. `module-uo` declares `admin: ["/shard", "/uo-link"]` and
its screen lives at `/admin/uo/link`; API routes are deliberately *not* namespaced while
SPA routes are. That is the distinction the installer got wrong in v0.1.0, and it now has
a named home on *The module system*.
**The check was verified by breaking it, not by watching it pass.** It went green on its
first run, which is the least trustworthy possible outcome, so seven mutations were fed
through it — a stale name, an omitted name, a renamed key in each of three sources, a
canonical document that moved, and the visibility ladder **reordered with its membership
unchanged**. All seven failed the build. The ladder case is the one worth keeping: it is a
security boundary, and a set comparison alone would have passed it.
---
## 11. Visual direction
**"Modern infrastructure software with an arcane identity."** Dark-first. Marketing pages are
@@ -1053,10 +1127,10 @@ a mechanism rather than diligence:
| **5** | The app and the beta: `/app/`, `/beta/`, the signup handler, the SQLite store, rate limiting, the export CLI (§8). **Also the repository's first `node --test` suite**, and phase 9 inherits an emulator pass (D26) |
| **6** | Legal: `/privacy/`, `/terms/`, footer links, and the Play Data Safety notes (§9) |
| **7** | Docs — the journey: Getting started (7) + Administration (**13**, per D37) — twenty pages in one PR (D34), with the install page self-contained and drift-checked (D35) and every admin screen walked before it was described (D36). **The installation path is the priority of the whole project** |
| **8** | Docs — builder and reference: Modules (8) + Architecture (5) + Reference (7) |
| **8** | Docs — builder and reference: Modules (8) + Architecture (5) + Reference (7) — twenty pages in one PR (D38), with Reference enumerating names and **checking every one of them** against its source (D39), and `plannedSidebar` becoming a checked invariant (D41) |
| **9** | Screenshots (D4): stand up the local review stack, seed presentable content, capture the admin panel, Teams, forums, marketplace, spawn atlas and shard console; build the screenshot components. **Plus an emulator pass against the same seeded stack** to fill `/app/`'s reserved slot (D26) |
| **10** | Polish: responsive, accessibility, SEO/OpenGraph/sitemap/robots, full-text search, CSP headers |
| **11** | Validation: `astro check`, production build, **all six check scripts** (tokens, brand, links, facts, quickstart, data safety), mobile layout verified in a real browser, a signup walked end to end |
| **11** | Validation: `astro check`, production build, **all eight check scripts** (tokens, brand, links, facts, quickstart, data safety, reference, sidebar), mobile layout verified in a real browser, a signup walked end to end |
| **12** | Delivery: Dockerfile, `docker-compose.yml` with both bind mounts documented, Gitea Actions workflow publishing to the registry, README, CONTRIBUTING with the AI-disclosure requirement, and an operator note covering DNS, TLS and the reverse proxy (D6) |
Phases 5 and 6 are deliberately adjacent and early: the beta cannot start without `/privacy`, and