feat(kit): the two shapes Teams added, taught and built (Teams phase 11) #6
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/teams-phase11"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Teams phase 11, the last of the bet, and the one that could only merge after the cutover:
checkCoreApiis an equality against a core onmain, and 1.6.0 did not exist there untilRunicGateway/website#161landed. The pin move rides in this PR, as planned.One sentence in the book was wrong
Chapter 2 said, of extension slots: "Only core may declare a slot; a module may only fill one". 1.6.0 inverted exactly that. It is not a stale detail — a new game's module cannot implement Teams at all without the inverted direction, so it is the shape the reader needs and did not have.
The two shapes, taught and built
{ core }naming which contribution goes there, and why asking for one core does not offer throws when almost everything else in that registry fails open.registerTeamProvider, in "Becoming the source of Teams" — the first registration where core calls you and waits, which is where every rule in it comes from: the envelope, the ten-second budget, refusing as a normal answer, and the mistake worth naming (answering{ ok: true, teams: [] }because the game is unreachable, which core reads as authoritative and acts on).projectRostergets its own treatment as the exception that fails closed;pageUrlTemplateis the footnote it was meant to be.The template grew a working version of each —
model/clans/, its own/clansroutes (deliberately not/teams, which is core's and which the loader would refuse), a clan list and a clan page declaring three slots. 47 server tests, 20 client. The purge test finally proves something: two of the three tables are now a parent and its child.What this phase does not do: enumerate the contract. The kit teaches one path end to end and links out; it has never mentioned three pre-Teams registrations and that is the design.
It found a defect in core, which is what it is for
Core's inverted-slot fills named three of
module-uo's slots literally, so the direction worked for that one module and silently did nothing for any other game — an empty page, no error, nothing logged. Fixed inwebsite#160/Module-uo#15/docs#165before this chapter could teach it, and amended into 1.6.0 in place.And it was walked on a real core
The template was installed into a running website — real MariaDB, the real loader, a browser. Core reconciled two Teams out of the provider on first boot,
/public/teams/<slug>/membersansweredprojected: true, and the clan page rendered core's activity feed and forum in slots declared by a module namedexamplegame.module-uo's guild page was walked on the same core and is unchanged.The walk found one thing no test could:
PageHeadertakeslead, notsubtitle, and React drops an unknown prop in silence — so every page built from this template had been rendering its heading with nothing under it since the template was written. Fixed on all three pages, and the chapter now says to check prop names against §3.4 rather than guessing them, beside the paragraph aboutshellthat exists for the same reason.Checks
checkLinks·checkRenameSites·checkChapterPaths·checkCoreApi --coreagainst963d734(1.6.0 ✓) · the two script suites · templatecheck:imports,check:swagger,build,check:externals, and both test suites.AI disclosure
Written with Claude Code (Opus 5). Commits carry the
Co-Authored-Bytrailer.MODULE_API 1.6.0 expands the contract this book teaches against, so the book owes two shapes and one correction. Chapter 2 gains both and the template grows a working version of each, because a reader following a snippet has no way to find out whether it runs. ONE SENTENCE WAS WRONG. Chapter 2 said, of extension slots, "Only core may declare a slot; a module may only fill one". 1.6.0 inverted exactly that: a module declares a place on its OWN page and core fills it. That is not a stale detail - a new game's module cannot implement Teams at all without the inverted direction, so it is the shape the reader needs and did not have. THE TWO SHAPES - The inverted slot. A new "Slots go the other way too" section: why the direction has to invert (core owns the Team, not the word for one), the namespace rule, one slot per PLACE, the optional { core } naming which of core's three contributions goes there, and why asking for one core does not offer throws when almost everything else in that registry fails open. - registerTeamProvider, in "Becoming the source of Teams". The first registration where core calls YOU and waits, which is where every rule in it comes from: the envelope, the ten-second budget, refusing as a normal answer, and the one mistake worth naming - answering with an empty list because the game is unreachable, which core reads as authoritative and acts on. projectRoster gets its own treatment because it is the exception that fails CLOSED. pageUrlTemplate is a footnote beside it, as intended. WHAT THE TEMPLATE GREW model/clans/ - the provider over two tables, with the guards that matter: an unreachable game refuses rather than reporting no clans, an empty roster is refused unless the game says the clan is empty (which is why the schema keeps a member count the rows cannot supply), and the audience rule lives in one file that both projectRoster and the module's own page consult, because a second copy drifts in the direction that publishes what core is withholding. Its own /clans routes, deliberately not /teams - core mounts that itself, and the loader would refuse the collision. A clan list page and a clan page that declares three slots for core. 12 provider tests and three registration tests, 47 server and 20 client in total. The purge test finally proves something: two of the three tables are now a parent and its child. WHAT IT DOES NOT DO. Enumerate the contract. The kit teaches one path end to end and links out; it has never mentioned three pre-Teams registrations and that is the design, not a gap. FOUND WHILE WRITING IT: core filled three literal uo.guild.* slot names, so the inverted direction reached exactly one module and every other game's page came up empty with nothing logged. Fixed in website#160 / Module-uo#15 / docs#165 before this chapter could teach it - which is what this phase is for. The ci/core-ref.json pin moves in a later commit on this branch: checkCoreApi is an equality against a core on main, and 1.6.0 does not reach main until the cutover. Co-Authored-By: Claude <noreply@anthropic.com>