docs(website): record slice 2, and what the browser changed about it

The contract as written had core branch on hasExtension to decide about its own
decoration around a slot. That is right when nothing is installed and wrong when
something is installed and fails: the slot IS filled, so the separator renders,
and the component then throws into the boundary and leaves the separator behind
on its own. Core decorates through <Slot wrap> now, inside the boundary, and
hasExtension is gone rather than kept as a trap for the next caller. Every unit
test passed both before and after -- the 7.7 browser smoke is what saw it.

Also recorded, neither a defect: core's own fill occupies a slot, so a module
cannot fill either one until the client half deletes core's (worth stating,
because a module written against 1.2.0 today cannot use them); and core's UO
sections on the user-detail page now fail to load, which is slice 1 removing the
routes rather than anything this slice did.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-11 16:46:11 -05:00
parent 262c86ad4f
commit 96b364b0bc
2 changed files with 50 additions and 3 deletions

View File

@@ -882,6 +882,35 @@ Two decisions inside it, both settled with the org lead 2026-08-11:
`registries.registerCore()` already use — so the rendered page is unchanged and the mechanism is
proved by core's own content before a line of it moves.
#### Slice 2 — the slots (website#138, 2026-08-11)
`modules/registry.js` grows `declareSlot` / `registerExtension` / `extensionFor`; `modules/Slot.jsx`
is the read side and core's only error boundary. `SiteFooter`'s link becomes `ShardStatusLink.jsx`
and `UserDetail`'s six UO sections become `UserShardSections.jsx`, both registered by `main.jsx`
under owner id `core`. 616 server + **169 client** tests (+9), manifest still 158, swagger
byte-identical.
**The §7.7 browser smoke earned its place again, and this time by finding something no test would
have.** A throwaway module filled both slots: the footer rendered the module's own label and target
in core's `linkStyle`, the admin page received `userId`, and a deliberate render failure was
contained to its own spot with the slot named in the console — but the footer was left showing
`email · · Admin`. The separator was rendered *beside* the slot, guarded on `hasExtension`, which is
right when nothing is installed and wrong when something is installed and fails. Core now decorates
through `<Slot wrap>`, inside the boundary, and `hasExtension` is gone rather than kept as a trap for
the next caller. Every unit test passed both before and after.
Two more things the smoke settled, neither of them a defect:
- **Core's own fill occupies the slot, so a module cannot fill it** — first fill wins and core
registers first, so the smoke module's call was rejected naming `core`. That is correct and
temporary: the client half deletes core's two fills in the change that registers the module's. It
is worth stating in the contract, because a module written against 1.2.0 today cannot use either
slot.
- **Core's UO sections on the user-detail page now fail to load, and that is slice 1's doing, not
this slice's** — core stopped serving `/admin/users/:id/shard/*` when the server half left, and
with no module installed there is nothing at the other end. Identical before and after this change;
the client half is what puts a live module behind it.
**Criterion 1 is a grep over code, not over prose** — see [API §5.2](MODULE_API.md#52-zero-uo-identifiers-in-core-ci-website-repo)
for what that means precisely. Core's marketing copy says "shard" in a dozen places, and a literal
word grep would have made every one of them a CI failure while proving nothing about the boundary.