Live-query subscribable field: contents. Projects each visible
contained Stuff as a REF_FIELDS-shape record so the inspection
pane (and any future container widget) can render the inside-of
view from a single subscription without a per-child round trip.
Per-viewer visibility filter mirrors LookController.lookAtLocation's
structural policy:
self) IS are excluded — a player listing
their own container shouldn't see themselves in it.AdornmentMixin items are excluded (they're part of the
host's structure, not loose contents).VisibleMixin items are excluded (they can't be
referenced in prose anyway).dependsOnFields: ['contents'] keys the dependency-index entry
to the FieldChangedEvent { field: 'contents' } fires installed
on addContainable / removeContainable below — the field is
not a persistent field (Hydrator never reflects into it) and
setter-shaped invariants don't fit, so the events fire from the
primitives.
Framework cleanup (S1 — evacuate to outer container).
When a Container destructs, every Containable currently held
is re-parented to the destructing Container's own outer
container via ContainmentApi.move. Top-of-containment
(Container that isn't also Containable, or whose
getContainer() is null) has no outer; per-item policy
applies:
HasInteractive items (Avatars with a live connection)
escape to the void singleton (/domain/void) so an
active session never ends up with a null environment.
The void is in the bootstrap manifest, so the sync
findByTemplatePath lookup here is guaranteed to find
a live instance.onMoved(from, to) witnesses fire for each item that's
evacuated; onDestruct fires for each item that cascades.
Walk order matters: this fires BEFORE Containable. cleanupOnDestruct for a Container+Containable composition,
so the evacuation completes while getContainer() still
returns the outer. Snapshot first — removeContainable
mutates the live set during iteration.
Limitation: only the DIRECT contents of the destructing host
are policy-targeted. A HasInteractive nested inside a
non-HasInteractive Container that itself sits inside a
top-of-containment host will be cascade-destructed when its
containing Container destructs (which moves it to the
top-host while that's mid-destruct, then R2.3 self-heal
nulls its container). If that nested-HI case becomes real,
lift the rule into ContainmentApi.move as a chokepoint.
Command provider for inventory management commands