docs(teams): the Teams bet, as built (Teams cutover 6/6) #169

Merged
whitlocktech merged 32 commits from edge into main 2026-08-19 09:02:16 +00:00
Showing only changes of commit 9f90a99362 - Show all commits

View File

@@ -2165,6 +2165,11 @@ makes §0.1's roster possible:
Every phase is independently shippable and leaves the site working. Phases 1 and 2 are the only hard
serial dependency in the list.
**Phase 11 is the exception to "independently shippable", and it is last on purpose** (org lead,
2026-08-18). The integration kit teaches an outside audience to build against this contract; Teams
expands the contract, so the book is the last thing owed before `edge` becomes `main`. It is also the
only phase that cannot merge until the cutover exists — see its own note.
### Phase 0 — a one-guild roster spike (`servuo-plugins` + `link`, throwaway)
**Not a deliverable — insurance on the phase that gates everything else.** `servuo-plugins` has no CI
@@ -2505,6 +2510,56 @@ rendering the admin UI from the declaration rather than from a hardcoded "Discor
purpose: extracting a capability surface from one working implementation is honest; designing it before
one exists is speculation.
### Phase 11 — the integration kit (`integration-kit`) — **the last phase before the cutover**
The kit is the instruction book for putting a *different* game on this platform, written for an
audience outside this org. Teams expands the contract that book teaches against, so the book is the
last thing this bet owes before `edge` becomes `main`.
**One sentence in it is already wrong.** `book/02-website-module.md` states, of extension slots,
"**core declares a slot; a module may only fill one**". Phase 3 inverted exactly that: with
`declareModuleSlot` a MODULE declares a place on its own page and CORE fills it, and by phase 6
`module-uo` declares three. A new game's module cannot implement Teams at all without the inverted
direction, so this is not a stale detail — it is the shape the reader needs and does not have.
**Two genuinely new shapes to teach, and only two:**
- **The inverted slot** (§3.7a) — a module declaring a place for core, why the name is namespaced under
the module's own id, and why a module wants *separate* slots rather than one (it decides where each
of core's contributions sits on a page it owns).
- **`registerTeamProvider`** — the first registration where **core calls the module and waits**. Every
other one is the module claiming a mount or core notifying it. The envelope, the 10-second budget,
and the asymmetry that matters: every call fails **stale** (core keeps what it has) except
`projectRoster`, which fails **closed**, because for a visibility question "keep what you have"
means serving the roster unprojected.
`pageUrlTemplate` is a footnote beside those — one optional string, and the reader meets it while
reading the provider.
**What this phase explicitly does NOT do: enumerate the contract.** The kit already teaches only four
members and has never mentioned `registerNotificationStreams`, `registerAnnounceLeg` or
`registerPostHook`, all of which predate Teams. That is the design, not a gap:
[`MODULE_API.md`](MODULE_API.md) is normative and the kit teaches one path end to end and links out.
The question this phase answers is "did the teaching path change", and the answer is yes in two
places and no everywhere else.
**Then the two mechanical lines:** `ci/core-ref.json`'s sha moves to the cutover commit and
`template/module.json`'s `coreApi` becomes `^1.6.0`, which puts `scripts/checkCoreApi.js` back to
green. That check is an **equality**, and its going red is the mechanism rather than a bug — a
contract bump is meant to turn that repo red until someone has re-read the chapters. Moving the pin is
that person saying they have.
> **Ordering, stated because it is genuinely awkward.** This phase is written *before* the cutover and
> can only *merge after* it. CI clones the pinned sha and checks the template against that core's
> `MODULE_API_VERSION` — and 1.6.0 does not exist on `main` until the cutover lands, so there is no sha
> to pin and no core for the template to build against until then. Write the chapters last, open the
> PR once the cutover merge exists, and put the pin move in it.
**Checks that gate it** (all dependency-free Node scripts, run from the repo root — which is also how a
reader runs them): `checkLinks`, `checkRenameSites`, `checkChapterPaths`, `checkCoreApi --core .core`,
plus the template's own `npm ci` / `check:imports` / `build` / `check:externals` / `npm test` on both
halves. Build the client **before** the client tests; two of them read the built chunk.
### Cross-cutting, every phase that touches the server
`npm run swagger` regenerated and committed · `npm run routes:manifest -- --check` zero-line diff ·