Two findings from surveying the client half, and one org-lead decision that
turns them into the same piece of work.
The client half does not divide into public and admin after all. Routes slice by
area, but useShardFeed and shardEvents are imported by eight public pages AND
three admin views, and a shared leaf moves with its last consumer -- the same
rule the server half taught. Of the three ways out, two trade a real cost for a
boundary that lasts one review, so the client half is one slice. The nav rows
keep their feature provider as a consequence (rows without it fail open, so
disabled surfaces would advertise themselves again), and VendorSales turns out
to have no public consumer at all.
Its three consumers include core's own UserDetail, which renders six UO sections
with nowhere to put them: the server got declareSlot/registerExtension in phase
2 PR 4 and the client never got the twin. SiteFooter's link to a URL the
extraction deletes is the same gap one component over.
So slice 2 is core-only and adds rather than moves: client extension slots
(API 3.7), the site.footer.status and admin.users.detail slots, core filling
both itself. MODULE_API_VERSION goes to 1.2.0.
A slot is named for a PLACE, never for a meaning -- core supplies the position
and the styling, the module owns the label, the target, the data and whether it
renders at all. Typing a slot by its content would put game semantics back into
core, which is what this phase removes.
This is also the one slice where core merges before module-uo, because a chunk
cannot call registerExtension before the function exists. Harmless here: the
slice only adds, and core fills both slots with its own components under owner
id `core`, so the page is unchanged and the mechanism is proved before anything
moves.
Co-Authored-By: Claude <noreply@anthropic.com>