Saxonberg Server API
    Preparing search index...

    Hierarchy

    Index

    Constructors

    Properties

    stuffId: string

    Runtime ID for this object (generated using nanoid). This is NOT the MongoDB _id - it's a runtime identifier.

    _mixinName: string = 'SingletonMixin'
    BAR_DIRECTION: "north" = 'north'

    Direction host→Dave's (cardinal; auto-inverse 'south').

    BAR_OPPOSITE: "south" = 'south'
    BAR_PATH: "/domain/lounge/bar" = '/domain/lounge/bar'

    Dave's Bar — the singleton external-neighbor shell.

    DEFAULT_BUD_THRESHOLD: 10
    DEFAULT_MERGE_WATERMARK: 3
    DEFAULT_REAP_GRACE_MS: 60000 = 60_000
    LOUNGE_TEMPLATE: "/domain/lounge/lounge" = '/domain/lounge/lounge'

    The one lounge-room template every instance clones from.

    subscribableFields: SubscribableFieldDescriptor[] = ...

    Universal live-query subscribable fields — fields every Stuff exposes regardless of mixin composition. Currently just displayName, a derived render that delegates to Stuff.getPresentation (Named's name or Visible's shortDescription, falling through to the baked-in 'something').

    Declared here rather than in a substrate-private synthetic table because every Stuff genuinely owns the concept — there is no "what if this Stuff has no displayable identity?" case. The descriptor uses dependsOnFields to declare the leaf source fields it depends on (name, shortDescription); the substrate installs precise (FieldChangedEvent, 'field', dep) index entries automatically. Shadow lifecycle support rides on ShadowChangedEvent in changes (declared-but-unfired until the shadow subsystem wires it).

    Mixin layers above Stuff add their own subscribableFields for mixin-owned state; the substrate's prototype-chain walk hasOwnProperty-checks at every level and unions the descriptors.

    Future universal renders (pronoun, articleName, etc.) land here too. Mixin-gated renders go on the mixin that owns the gate.

    WARREN_PATH: "/domain/lounge/warren" = '/domain/lounge/warren'

    Seeded Warren-definition path; the startLocation spawn reference.

    Methods

    • Register m as a member. Idempotent. The SOLE writer of the Pattern-B back-ref (alongside removeMember): when m composes WarrenMemberMixin, stamps m.setWarren(this). A plain-Location member just lives in the set.

      Single-warren guard (Q2b): a member already owned by a DIFFERENT Warren is rejected — it stays where it is and we warn. The declared seed path can initiate a membership but never re-home an owned one; the owner always wins.

      Returns true when m is a member of this Warren after the call.

      Parameters

      • m: MemberStuff

      Returns boolean

    • Seat an arrival the host can't hold. Sync prefix seats into the least-full eligible satellite (so the re-seat completes within the triggering move — single perception); only when none is eligible do we await a fresh bud.

      Parameters

      • host: MemberStuff
      • actor: Stuff

      Returns Promise<void>

    • Consent seam for the residency (self-eviction) sweep. The sweep asks each idle object whether it may be culled; the object decides, reading its own knowledge. Default is cull ({ ok: true }) — a fresh backing class is reclaimable by default and only becomes sticky when its author deliberately vetoes, the correct bias for a leak-plugger. Return { ok: false, reason } to veto.

      Vetoes layer on the mixin/class that owns the relevant relationship, composed via super.canEvict(context) — base Stuff stays permissive and does not reach into Container/Shadow/Avatar/ Exit knowledge. The relational vetoes derive from the R2.x ref-cleanup rules: an object in an owned/symmetric live-ref relationship vetoes while its anchor is alive (see docs/subsystems/residency.md).

      Distinct from canDestruct: an object that permits eviction can still canDestruct-veto, so the sweep's enforce path tolerates a DestructError (logs + continues). The sweep calls this on the raw target (via RAW_TARGET) so asking never counts as a touch.

      Parameters

      Returns VetoResult

      Invoked by the residency sweep (ResidencyLogic) on idle candidates. Veto seam{ ok: false, reason } keeps the object resident. Override on the owning mixin/class and chain super.canEvict(context) so composed layers run. Public and ungateable (a subclass's super.canEvict() is author code).

    • Bud = clone the one lounge-room template (it self-registers via its warren instruction field). Instances share the template path; their hub exits use live refs (keepLiveDestination), so there is no need to re-key per-instance paths.

      Returns Promise<MemberStuff>

    • Create one member through the per-Warren serialization chain so two concurrent creations never clone the same template path at once.

      Returns Promise<MemberStuff>

    • Make m the host and wire its host-only fixtures. No exit changes to other members (a fresh host has no satellites yet). Re-seats any registered self-seating fixtures last — a no-op on the first-ever designation (none registered yet), but it revives fixtures that died with a previously lost host when the graph stands up fresh.

      Parameters

      • m: MemberStuff

      Returns Promise<void>

    • Destroy this object.

      Locked down by @CallSecurity(ApiOnly) — only callers under mud/api/ (in practice, StuffApi.destruct) may invoke it. @Unshadowable because the unregistration path must always run; a shadow that intercepts and skips it would leak the object into the registry forever. @Final because subclass overrides would defeat the same invariant — the loader hook throws FinalViolationError at import time on any subclass redefinition.

      Subclass cleanup belongs on the optional onDestruct() witness (consulted by StuffApi.destruct while the target is still live); refusal logic belongs on canDestruct(). This terminal destroy() is the unshadowable mark-and-unregister step only.

      Returns void

    • The current host member (or null when empty / lost), pruned. For subclass policy (reconcile) that must skip the host. Does NOT create one — use getHost() for the create-if-absent kernel.

      Returns MemberStuff | null

    • The reusable placement kernel. Returns the current host, creating the graph's first instance (which becomes host) when empty, or migrating the role to a survivor when the prior host was force- destroyed. Both avatar sign-in (startLocation) and future item-spawn share this.

      Returns Promise<MemberStuff>

    • Read the recency timestamp. Read by the residency sweep — which calls it on the raw target (via RAW_TARGET) so the sweep's own introspection never counts as a touch.

      Returns number

    • Live members, R2.3-pruned. A destructed member is dropped from the set on read (defends against any destruct path that bypassed the R2.4 cleanup).

      Returns MemberStuff[]

    • Self-presentation — the casual-register render string for this object, the answer to "what does this Stuff call itself?" Three- step resolution:

      1. Named.name if present and non-empty — the object's proper name ("Alice", "Excalibur", "Town Square").
      2. Visible.shortDescription if present and non-empty — the object's visual identity ("a heavy oak door").
      3. The baked-in fallback (DEFAULT_PRESENTATION).

      For a Globbable stack (quantity !== 1) the count folds in as an affix — "30 coins" — pluralized via GrammarApi.pluralize (which honors host-side getPluralForm() overrides for irregulars). Named takes precedence over Visible so a Named-with-description renders by its proper name; code that needs the formal register calls getFullName() when typed as Named.

      Viewer-blind by design. This is the shared baseline every Stuff exposes; the viewer-aware naming step (recognition / identification — see docs/subsystems/belief.md) composes on top of it. Left shadowable (NOT @Final) so masking / disguise effects can override the rendered identity via a method shadow.

      Returns string

    • Build the composable Mml fragment for this object's display name — the Mml sibling of getPresentation. Mml.ref (and so every <item> / <name> / … identity tag) renders this, not a raw string, so a name joins the compose chain as a fragment like everything else. The label is the already-resolved, viewer-aware name (recognition runs in the render layer and hands it in).

      Return null for the plain default — Mml.ref then wraps the label in Mml.text, which escapes it exactly once, so player-authored names / status decoration are safe by construction and the fragment is never re-escaped downstream. Override to build a richer fragment (a TPA terminal wraps its name in <color> to tint by state). The plain-string getPresentation stays the surface for non-prose consumers (logs, context.note, MQL scalars).

      Parameters

      • _label: string

      Returns Mml | null

    • Read seam. Instance method, but unwraps via ProxyApi.unwrap before reaching the # slot — this inside an instance method called through the proxy is the proxy, and the # slot lives on the raw target.

      Returns string | null

    • Sync host check (no clone). True iff room is the current host.

      Parameters

      • room: MemberStuff

      Returns boolean

    • Check if this object has been destroyed.

      @Unshadowable: the destroyed-state read is a framework invariant — any shadow that lied about it would let consumers touch a torn-down Stuff. @Final: subclasses overriding this would defeat the same invariant; the loader hook throws FinalViolationError at import time on any subclass that redefines it.

      Returns boolean

    • Migrate the host role to newHost after the prior host was force- destroyed. The dead host's outbound hub exits were destructed by its own Exitable.onDestruct, but the satellite-side inverses were left BLOCKED (the asymmetry) — so for each survivor we explicitly remove and destruct the dead exit toward the old host, then re-point every other survivor's hub exit at newHost, swap the host-only fixtures, and update the host pointer.

      Parameters

      • newHost: MemberStuff

      Returns Promise<void>

    • A member's HasInteractive population changed. Coalesces a reconcile() onto a microtask so a burst of arrivals/departures runs the policy once. Event-driven — no polling.

      Parameters

      • _room: MemberStuff

      Returns void

    • Terminal onDestruct no-op. Exists so subclasses and mixins overriding onDestruct can call super.onDestruct() without the cast-to-optional-callable dance — the chain is guaranteed to bottom out here. StuffApi.destruct invokes the hook via the optional-method dispatcher in api/stuff.ts; that path still works (always finds a function on the prototype).

      Override (not extend with super) at any layer that wants cleanup; chain to super.onDestruct() from the override so intermediate layers in a mixin chain run too.

      Returns void

      Invoked by StuffApi.destruct (and forceDestruct) while the target is still live, after canDestruct passes and before shadow-detach + destroy(). Witness — the return value is ignored (it cannot veto; canDestruct is the veto seam). Override to release resources/listeners and chain super.onDestruct() so mixin layers run.

    • Destruct a member, draining any occupants to the host first and tearing down BOTH sides of its hub exit. Never reaps the host.

      Order is load-bearing for the exit-teardown asymmetry: remove + destruct the host-side exit FIRST (which clears the member-side inverse pointer via Exit.onDestruct), so the member's own Exitable.onDestruct doesn't try to block an already-dead inverse.

      Parameters

      • m: MemberStuff

      Returns void

    • Population reconcile — merge-low only (budding is handled eagerly by the arrival witness). A satellite below the merge watermark schedules a drain-and-reap after the grace; the timer re-checks at fire time (no thrash) and the host is never reaped. No live rebalancing of healthy rooms.

      Returns Promise<void>

    • Register a self-seating fixture so it re-seats when the host migrates or the graph stands back up. Called by FixtureMixin.seatSelf when its seatIn target is this Warren. Stores the fixture's template path — the durable handle that survives the fixture's death-with-host; a path-less fixture can't be revived and is logged.

      Parameters

      Returns void

    • Drop m from the member set. Clears the back-ref iff it still names us (R2.2 symmetric). When m was the host and survivors remain, the host role is lost and re-designated lazily on the next getHost(). Returns true when m was present.

      Parameters

      • m: MemberStuff

      Returns boolean

    • Narrow a room to an Exitable container, failing early when it isn't. A Warren that wires hub/fixture exits requires its rooms to compose ExitableMixin; a non-Exitable room is a composition error worth surfacing loudly rather than papering over with a cast.

      Parameters

      • m: MemberStuff

      Returns ExitableContainer

    • Stamp this Stuff's templatePath and re-key the byTemplatePath index so future findByTemplatePath lookups see the new path. No-op when path matches the current value.

      Locked down by @CallSecurity(ApiOnly) because flipping a Stuff's identity post-clone would break FromTemplate policies and any caller-side caching of template-path identity. @Final @Unshadowable because the index update has to run for every successful set — a subclass override that forgot the index call (or a shadow that intercepted) would silently desync byTemplatePath.

      Unwraps via ProxyApi.unwrap so the #-slot access lands on the raw target (see comment on #templatePath above).

      Parameters

      • path: string

      Returns void

    • Runtime tuning seam (the band is the lounge's personality). v1 ships code-constant defaults; this is the hook tests use to drive small thresholds and the migration target when the knobs move to app settings (AppApi).

      Parameters

      • opts: { budThreshold?: number; mergeWatermark?: number; reapGraceMs?: number }

      Returns void

    • Set the spatial zone. Gated by FromSpatialZone — only the SpatialZone class and its subclasses (CartesianZone, SphericalZone) may call this through the proxy. The addLocation / removeLocation chokepoints on the zone side are the legitimate callers; everyone else is rejected.

      Clone-time seeding from StuffApi.#cloneInner doesn't go through this method — it uses the caller-allowlisted _stampZone seam below.

      @Final @Unshadowable because the index of substrate invariants that consult getZone() (containment's cross-zone gate, Mobile.traverse, MQL scope walks) trusts the slot's value; a subclass override or shadow that lied about it could break those invariants. No legitimate subclass needs to extend this anyway — the only legitimate write paths are the SpatialZone chokepoints and clone-time.

      Parameters

      Returns void

    • Clone a fresh satellite (via the policy createMember), ensure it is registered, and wire its hub exit to the current host. Returns the new member.

      Returns Promise<MemberStuff>

    • Tear the whole graph down — destruct every member (host last) and clear all state. Used on shutdown / HMR; the Warren Idea itself persists only as a definition and the graph reconstitutes lazily.

      Returns void

    • Get a string representation of this idea (for debugging). Subclasses should override to provide more specific information.

      Returns string

    • Refresh the recency timestamp to now. Timestamp-fixed (no caller-supplied value). Called on the raw target by the security gate on every successful dispatch (Phase 2) and by the residency presence walk.

      Returns void

    • Remove the host-only fixture's neighbor-side half (Dave's south) left dangling when the old host was destroyed, so wireHostFixtures can re-install it onto the new host cleanly. Idempotent — no-op when Dave's isn't loaded or the exit is gone.

      Returns Promise<void>

    • Tear down the host-side half of m's hub exit and destruct that Exit object (the asymmetry fix — removeExit alone leaks the Exit and leaves a blocked dead entry). The member-side half is left to m's own Exitable.onDestruct when m is being reaped; when this is called for a still-living m the member-side inverse is cleared by the host-exit's Exit.onDestruct.

      Parameters

      • m: MemberStuff

      Returns void

    • Wire the one host-only fixture: a north exit to Dave's Bar. The host is a non-singleton clone (a shared template path), so the back-exit (bar→host) holds a live ref. Satellites reach Dave's by walking to the host.

      Parameters

      • host: MemberStuff

      Returns Promise<void>

    • Wire a bidirectional hub exit between the current host and m, recording the host-side direction so teardown can find it. No-op when m IS the host or there is no host yet.

      Parameters

      • m: MemberStuff

      Returns Promise<void>