Per-Detail Material overrides — flat map from detailKey to the
Material's templatePath. Stored as a plain Record (not a
Map) so default JSON serialization handles it without a
marshaller.
Path to the bulk default Material singleton. Resolved lazily on
each getMaterial() call so HMR replacement is observed
immediately.
Protected_Runtime-only auxiliary support pointer — Pattern B live ref.
Holds a direct reference to the supporting Surfaced host
(null when no support). NOT in persistentFields; resets to
null on hydrate. R2.3 self-heal in getRestingOn clears the
slot if the supporter has been destructed.
Pattern B chosen over Pattern A templatePath stamping because non-singleton surfaces (e.g., multiple identical tables in a dining hall) can't be addressed unambiguously by templatePath. The cross-restart loss is small — items reappear in their container, just without the on-surface precision.
Path to the Species singleton this organism belongs to. Resolved lazily on each getSpecies() call so HMR replacement is observed immediately.
Years (or species-appropriate units; v1 doesn't enforce). 0 at birth/clone-time. Aging is deferred to follow-on builds.
ProtectedalternateMedium-tag override ('air'/'water'/'vacuum'); null = default.
Cached resolved humidity (%) for the wet-bulb read.
ProtectedcontentsThe contained items. Read access goes through getContents();
mutation goes through addContainable / removeContainable,
which only Containable.setContainer may legitimately invoke.
The digestion-buffer per-tag pools (%-fill to deliver per tag).
Cached effective ambient (raw K) — biome + warmth + clo + transforms.
ProtectedenvironmentLive reference to the container. NOT a persistent field —
cross-Stuff references would round-trip badly through the
Hydrator's reflection. The container relationship is rebuilt
at clone time via the applyContainer instruction-field path
(see static instructionFields above) or by direct
ContainmentApi.move calls after hydration.
Auxiliary restingOn is different — it's a Pattern A
path-string (_restingOnPath) that DOES persist; see static
persistentFields below.
Protected OptionalhonorificProtectedillustrationCached resolved ambient (raw K) the object is drifting toward.
Last-eaten material name — for vomit prose only (no accounting).
Current lifecycle state — one of the species' valid set
('alive', 'dead', 'undead', 'powered', 'unpowered',
'destroyed'). Initial value lives on the leaf template's
data per slate. Empty default keeps unhydrated test fixtures
trivially constructable.
Liquid sub-volume (litres) — filled by drink / sip.
ProtectedlongGame-time (seconds) of the last reconcile; 0 = unseeded.
ProtectednameProtected OptionalnameStorage — public for the Hydrator.
The only persisted field — the drain's elapsed anchor.
Setpoint (K) the body defends — the movable fever/magic seam.
ProtectedshortProtectedslotsLive runtime occupancy. Direct refs (proxy framework intercepts
on use). Each slot's value is the set of current occupants;
empty set when unoccupied. Not in persistentFields — starts
empty on clone / hydrate.
Solid sub-volume (litres) — filled by eat.
Stamped temperature T0 (raw K) — the decomposed scalar.
Authoring data — only used by the default getSlotNames /
getSlotSpec implementation. Hosts that override the universe
surface (BodyPlanSlots, Adornable) leave this empty.
ReadonlystuffRuntime ID for this object (generated using nanoid). This is NOT the MongoDB _id - it's a runtime identifier.
Protected OptionalsurnameGame-time (seconds) of the last reconcile / re-stamp; 0 = unseeded.
Game-time (seconds) of the last regulation reconcile; 0 = unseeded.
Sparse per-toxin body burdens (Wave 2; created on first exposure).
Static_StaticcommandCommand provider for inventory management commands
StaticfieldField-marshaller binding. mass round-trips via the kg-bound
QuantityMarshaller; the runtime accessor pair stays strict on
Quantity<'kg'>. Authoring-shape coercion (mass: heavy,
mass: "12000 g", bare numeric) lives in the marshaller's
fromStored and only runs on the persistence path.
StaticinstructionInstruction field — declarative spawn target. Consumed by
Phase 2 of the Hydrator. There is NO paired getContainer(path)
declaration accessor; the live getContainer() ref is the
only runtime getter.
StaticmarkupMarkup-augmenter contribution. senseStripAugmenter reads the
per-call filter from AugmentOpts and the viewer's sensorium
(derived from BodyPlan.getModalities()), and drops
<sense channel="X">…</sense> regions and <detail sense="X">
wrappings whose channel isn't in filter ∩ sensorium.
Lives on VisibleMixin (not DetailedMixin) because <sense>
regions can appear in any Visible-mixed long, with or without
detail authoring. Ordering: VisibleMixin sits above Detailed
in the typical composition chain, so the parent-first walker
runs senseStripAugmenter BEFORE wrapDetailKeysAugmenter —
strip-then-wrap is correct because wrapping inside a region
destined for the strip is wasted work.
StaticpersistentPersistent fields declared by this mixin. Used by PersistApi for automatic synchronization.
StaticsubscribableDerived readouts surfaced through the live-query / inspection
substrate (the Tangible.mass precedent). No event wiring in v1 —
these are pure derived reads re-resolved on demand.
ProtectedfullHost-internal accessor for the formal canonical form. Public
surface is getFullName(). Used at introductions, character
info screens, disambiguation — not the default for everyday
prose. Most callers should read getName() directly.
Layout:
[honorific] [name] [surname][, nameSuffix]
The comma before nameSuffix is universal for credentials
("John Smith, MD", "John Smith, PhD", "John Smith, Esq.") and
a defensible older-style for generational suffixes ("John
Smith, Jr.") — common in legal documents and personal
signatures even where AP/Chicago have dropped it. Regnal
numerals ("Henry VIII") would render incorrectly here, but
those aren't a v1 use case; if they become one, model them
via alternateNames rather than nameSuffix.
ProtectedmassPrivileged setter for the auxiliary restingOn pointer.
Reachable only from ContainmentApi.move /
ContainmentApi.placeOn. Pass null to clear.
Stores the supporting Surfaced ref directly (Pattern B); runtime-only — see the field declaration's JSDoc for the persistence rationale.
ProtectedabsorbStep 1 — drain each pooled tag toward its reserve at its own rate, and shrink the sub-volumes proportionally so the stomach empties as it digests (reopening the cap). Wave 2 routes toxin pools into burdens here.
ProtectedabsorbDrain a toxin's un-absorbed pool dose into its body burden. Alcohol
(storeRaw) accumulates the raw absorbed grams; every other toxin
accumulates absorbed × potency / bodyMass (dose-response). The
burden entry is created on first exposure and never widened.
State-mutation primitive. Locked down — only callable from
Containable.setContainer. Use ContainmentApi.move(item, container) from application code.
Fires FieldChangedEvent { field: 'contents' } after a real
addition so the MQL subscription substrate's dependency index
picks up containment-shape changes for the contents descriptor.
The substrate matches on (KIND, 'field', 'contents') only —
oldValue / newValue are inspected by the diff pass via
re-projection of the host, not by the index, so the count
delta carried here is informational (debugging / future
coarse-grain optimizations) rather than load-bearing.
Add a condition (a Trauma value or an AfflictionRecord).
Antidote = accelerated clearance. Crashes a toxin burden in one
shot (far faster than natural clearance would), so its banded
condition clears on the next reconcile. The minimal consumer of
the vitals ResolutionSpec treatment seam (no treatment verb is
required by this build — the callable seam + crash mechanism is).
Phase 2 applier — see the interface docstring for semantics.
Compare-and-move idempotency: no-op when the current container's
templatePath matches the declared path; otherwise resolve the
target via StuffApi.singleton and ContainmentApi.move into
it. The singleton-target invariant is enforced at template-save
time by TemplateApi.validateSingletonContainerTarget.
ProtectedapplyProtectedbasalStep 2 — basal metabolic drain on satiation + hydration, scaled by body mass and the (inert v1) thermal-strategy multiplier.
ProtectedbodyPassive-drift time constant (R·C) for the body — the rate the core
floats toward effective ambient when regulation is off. Reuses
ThermalMixin.getTau (the body's mass × material × medium/wall
resistance); a heavier body drifts slower.
ProtectedclearClear path once value re-enters threshold by the hysteresis margin.
ProtectedclearStep 4 — burden clearance. Each live burden falls at its seed's
(zero-order) clearanceRate; the entry is deleted at zero.
Drop the imposed disguise. Worn coverings are unaffected.
ProtectedcontentsHeat capacity (J/K) of a vessel's interior fluid, or 0 if empty.
ProtectedcoupledStep 3 — coupled recovery: at rest the body rebuilds endurance
by spending satiation + hydration (hydration the tighter
leash), rate-limited and scaled by posture × restQuality ×
spo2-throttle (the last inert in v1). This is the keystone — why
recovery lives in metabolism, not encumbrance.
ProtectedcurrentThe restQuality of the host whose posture slot this body
occupies, or 1.0 (the floor / standing with no host). Only an
actor that can occupy slots (Slottable) has a host; a bare
Creature reads the default.
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.
Draw down endurance for one loaded self-powered traverse.
ProtecteddriftPassive Newton's drift of the core toward the effective ambient.
ProtectedeffectiveResolve the body's effective ambient — biome ambient + occupied
warming-slot warmth + the wind-chill (cold side) / heat-index
(hot side) transforms, read through the surrounding medium's
conductivity (immersion). async and run only at re-stamp events
(placement/move, ambient shift, don/doff); the per-slice reconcile
reads the cache effectiveAmbientK synchronously. (Worn clo is
applied as a band-widening in integrateThermalSlice, not here.)
ProtectedeffectiveSeries heat-exchange resistance R (K/W).
ProtectedemitProtectedensureLet the held breath out — clear the grace.
ProtectedfindFiltered view of alternate names. Pass a kind to narrow.
Returns a copy, so callers can iterate without disturbing
mutation order.
Optionalkind: NameKindBlood-alcohol concentration via Widmark — the alcohol burden
stores ethanol mass (grams), normalized at the read by body mass
and the sex-derived r. BAC (g/L) = grams / (mass_kg × r);
converted to g/dL (the 'bac' scale unit). Storing mass keeps
the read state-dependent (a lighter / dryer body reads higher).
Total weighted weight this body bears (carried + worn + held).
The species breathable set (default ['air']; water-breaters ['water']).
What this body can comfortably carry (physiology-derived).
The accessible band over blood-volume fraction + vitals-out-of-
band. Reserves and trauma fold additional
load in at the marked seam. A corpse (lifecycleState: 'dead')
reads dead; otherwise the band reflects the substrate — it
can read critical from a floored vital with NO lifecycle
transition (the deferred driver owns transitions).
Consciousness below death — derived from blood volume + SpO₂.
Gates animate verbs like death but is recoverable. A corpse reads
dead. Head trauma is folded in below.
Snapshot of contained items as an array.
Held-fluid temperature (vessels) — the object's own temperature in v1.
Walk the containment tree depth-first pre-order, starting
from this Container's immediate contents, and return every
Containable encountered. Used by MQL's :I transform and
any controller that wants the full nested inventory.
Effective merged disguise (worn + imposed), or null if unmasked.
Vomit — flush the un-absorbed digestion pools (those tags
never reach their handlers) and empty both sub-volumes. Leaves
absorbed state intact: reserves already filled and toxinBurdens
already accumulated stay. That asymmetry IS the purge mechanic —
inducing it early (pools un-absorbed) saves you; late doesn't.
Called by the vomit verb and by the involuntary cascade trigger.
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.
Burden / capacity (dimensionless; 0 capacity → 0/Infinity).
Get the long description with fallback to short, then default.
Affordance-annotated long description — see the interface
docstring for the augmenter pipeline contract. Calls
Mml.augment with the host (this), the supplied viewer,
and the per-call opts (the senses build threads
opts.filter through here for verb-specific sense filtering).
Every contributing mixin's augmenters run in
parent-first → child-last order.
Optionalopts: AugmentOptsMass override that lazy-seeds the body-grounded default. When the
instance authored no mass of its own (still 0), resolve
species → bodyPlan → baseMass and adopt it; an explicitly-authored
mass is the deviation that wins (the guard short-circuits and this is
a plain super.getMass()).
Runs lazily here rather than from a post-hydrate hook: the
postRegister chain is not uniformly threaded below CommandGiver
(e.g. Avatar.postRegister does not super-call), so a read-time
seed is the one seam that makes mass honest for every reader of
every Creature subclass, the moment a body plan is resolvable. The
"is mass still 0?" check is the idempotency guard — no persistent
"seeded" flag (the project rule); a genuinely 0-mass sessile body
simply re-checks cheaply.
OptionaldetailKey: stringThe body's parts, each merged with its instance delta. Walks the
shared BodyPlan.bodyParts and overlays bodyPartDeltas. Returns
[] for a body with no species/bodyplan (no anatomy without a
species) — graceful, not an error.
Postmortem-progression seam. Death is living-stop + postmortem-start:
living processes freeze and postmortem changes (algor / rigor / livor
/ decomposition) would begin here. v1 ships ZERO — returns []; the
seam exists for a future forensics wave.
Self-presentation — the casual-register render string for this object, the answer to "what does this Stuff call itself?" Three- step resolution:
Named.name if present and non-empty — the object's
proper name ("Alice", "Excalibur", "Town Square").Visible.shortDescription if present and non-empty —
the object's visual identity ("a heavy oak door").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.
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).
Resolve the auxiliary restingOn pointer. Pattern B live ref;
R2.3 self-heal clears the slot if the supporting surface has
been destructed since the last set.
Returns null when no support OR the supporter has been
destructed. The caller can't tell the two apart from the
return value; that's deliberate — absence of support is the
same observable as a stale ref.
Walk the container chain to the topmost non-null environment.
Returns null when already at the root.
Containment is acyclic by construction (a Container can't
contain its own ancestor — setContainer's atomic update is
the chokepoint), so the loop is bounded by the depth of the
world's nesting.
Get the short description with fallback.
Absolute lift cap = capacity × OVERLOAD_FACTOR.
Exterior temperature — ≈ ambient for an insulated object, ≈ core for a bare one.
Time constant τ = R·C.
The lazy temperature read (SYNC) — reconcile-on-read against game-time.
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.
Lookup the valid sex set from the host's species'
sex-determination system. If the host doesn't compose
OrganismMixin (degenerate), or the species is unset, returns
an empty set — the setter then rejects every value.
The survivable band for a sign — from the host's species
vitalProfile, or the universe default. Requires OrganismMixin
(runtime-guarded). The "always composed with Organism" rule lives
here, not in a comment.
Get the spatial zone. Unwraps via RAW_TARGET because the
# slot lives on the raw target only and this inside an
instance method called through the proxy is the proxy.
Make ingest real: route the consumed material into the
digestion buffer. Picks the sub-volume by phase (the verb
decides — eat solid, drink/sip liquid), caps intake at the
remaining sub-capacity (the bulk partial-transfer shape — refuse
the excess), and fans the material's nutrient tags into per-tag
pools scaled by the accepted volume.
Returns the litres actually accepted, so a caller can hold to
result.applied-style semantics (the eat verb consumes a
discrete item only on full acceptance).
Take and hold a breath — extend the breath-hold grace (free-diving).
Install the default biological reserves if absent (idempotent).
ProtectedintegrateOne integration slice (game-seconds), flows in fixed order: (1) digestion absorption, (2) basal drain, (3) coupled recovery. (Wave 2 inserts toxin clearance at step 4.) Each slice is small enough that the per-flow linear approximation is honest and the coupling is respected slice-to-slice.
ProtectedintegrateOne integration slice (game-seconds). Resolves the effective ambient (cached), the setpoint, and the clo-widened band, then branches on strategy: an ectotherm / dead / no-fuel body drifts; an endotherm spends to hold the setpoint within the affordable regimes.
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.
Whether a voluntary/automatic breath-hold is currently active.
Whether this body respires at all (the respires opt-out).
Coarse part→slot coupling: a missing part disables its slots.
ProtectedmediumThe dominant series conductivity (W/(m·K)): the barrier medium
when sealed (a Sealable host that is closed → vacuum), else
the barrier override, else air (the default surrounding
medium for a bare Phase-1 object; the body lifts this to its
resolved immersion medium in Phase 2).
ProtectedmetabolicIn-session game-time (seconds), or null when no world clock is
present in the world. Metabolism ticks only when a WorldClock
registry is bootstrapped (indexed by templatePath) — production
always has one; a unit test that hasn't set one up reads null
and stays idle (no getNow lazy-create with a wall-clock anchor).
ProtectednoteProtectednoteTerminal 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.
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.
Containment-move witness — the onMoved hook ContainmentApi.move
fires on every mover (carried items, dropped corpses, vessels,
bodies). Re-stamps so the object freezes its current temperature
under the old scope's ambient and starts drifting toward the new
scope's. Load-bearing under the cached-ambient model (Step 1.6
trigger 1): with a sync read there is no lazy re-resolve, so a
move that didn't re-stamp would drift toward a stale ambient
forever. This is the one event thermal listens to (the genuine
divergence from metabolism's pure-lazy model). Chains any inner
onMoved witness first.
The traverse hook (the Mobile.onTraversed shape) — fires reassess on every move.
ProtectedreadThe central event-driven re-resolve: engage/cancel the crisis drain.
ProtectedreconcileMirror MetabolicMixin.reconcileCascade for the single anoxia
affliction: while spo2 dwells at/below the lethal floor, accrue
dwell-time on the asphyxiation affliction and fire the death seam
when it exceeds the lethal dwell; clear it on recovery above the
floor. Returns whether death fired this tick.
ProtectedreconcileThe cascade — metabolism is the first condition-driver. After the
sub-stepped integration, ensure each floored biological reserve's
floorEffect-named condition exists, clear it on recovery
(hysteresis), and progress the lethal ones toward the death seam.
Integrate elapsed in-session game-time since the last reconcile. Sub-steps the gap into fixed slices so the coupled flows (basal drain, digestion absorption, recovery, burden clearance) stay honest over a long mixed-activity gap. Freezes on absence (linkdead now; logout via the far-past guard) — real-life absence never starves you. Cheap no-op when too little time has passed or the world clock isn't running.
Lazy reconcile — drift the stamped temperature over elapsed game-time.
ProtectedreconcileAfter the slices, spawn / clear the thermal conditions off the
driven core (hypothermia / torpor below survivableMin,
hyperthermia above survivableMax), accrue dwell, and fire the
death seam on lethal accrual. Mirrors metabolism's cascade.
Lazy reconcile — drive coreTemperature over elapsed game-time.
ProtectedreconcileFor each live toxin burden, ensure its one banded condition
exists and recompute its severity live — from the derived BAC for
alcohol (storeRaw), or the raw burden otherwise — against the
seed-authored bands. Cleared when the level falls below the
lowest band (no per-band spawn/clear churn; one condition per
toxin, severity is a live read on stage).
ProtectedregRemove a condition by reference; true if it was present.
Remove the first alternate matching value. Returns true if
something was removed.
Remove primitive. Same lockdown as addContainable. Fires the
matching FieldChangedEvent { field: 'contents' } on a real
removal.
ProtectedreserveProtectedresolveResolve a toxin's authored rate params off its Condition seed.
Emission body of the drain engagement (delegated from RespirationDrain).
ProtectedrespirationIn-session game-time (seconds), or null when no world clock runs
(pre-boot, or a unit test that hasn't bootstrapped one) — the
metabolism presence guard verbatim, so unit tests stay idle.
ProtectedrouteFan the accepted intake through the per-tag router into the
digestion pools. Wave 1 routes the energy tags; Wave 2 extends
routeTag to the full macro set + toxins. A static switch over
the curated vocabulary, NOT a registry — unknown tags are a
no-op so authoring a novel tag never crashes intake.
ProtectedrouteThe static tag dispatch — one caller (the ingest decomposition), so a private method, not a security-gated Api. Maps a known nutrient tag to its routing; unknown tags return null (no-op).
ProtectedseedResolve the body-plan baseMass and adopt it as this body's mass,
returning the seeded quantity (or null when there is no plan /
baseMass is absent or 0). Does not read getMass() — the
zero-guard lives in getMass, so this stays recursion-free and
is the single place the body-grounded default is applied.
State-mutation chokepoint. Reachable only from
ContainmentApi.move; cross-Container contents mutation must
not be subclass-extensible (@Final) or shadow-bypassable
(@Unshadowable).
Atomic across three updates: detach from the old container,
attach to the new, update the field. null argument is the
detach case; the policy rejects calls from anywhere other than
ContainmentApi, so setContainer(null) outside the Api
throws — the legitimate detach is ContainmentApi.move(item, null).
Set the fluid temperature directly and re-anchor the drift clock — the bulk-coupling primitive (refill to incoming, calorimetric mix blend, pour-preserve-at-reduced-C). Freezes the current temperature to now under the existing ambient first, then adopts the supplied value and restarts drift from it.
ProtectedsetImpose a transient disguise (active-effect; not persisted).
Strict on Quantity<'kg'>. Callers holding a raw number wrap
via Quantity.of(n, 'kg') at the call site; tag / alt-unit
authoring is the marshaller's job, not a runtime API concern.
OptionaldetailKey: stringStamp 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).
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.
Protectedspo2Respiration read — low spo2 would throttle recovery. v1 reads
the sign for the seam's presence but returns 1.0 unconditionally;
lights up when respiration drives spo2.
ProtectedstrategyProtectedthermalHeat capacity C = mass × specificHeat (J/K). For a vessel whose
Thermal IS its contents (Bulkable interior with fluid), C
derives from the held fluid — more contents → larger C → slower
cooling, free (a full thermos holds heat longer than a near-empty
one). Falls back to the host's own mass × material when empty / not
a vessel.
ProtectedthermalQ10 temperature coefficient on basal metabolic rate. Reads the
driven coreTemperature (the thermal build's getVitalSign
override drives it) and scales basal drain by
Q10 ^ ((core − reference) / 10). For an endotherm pinned at its
setpoint this is ≈ 1 (the core sits at the reference); for an
ectotherm whose core floats to the weather, basal drain swings —
a cold reptile burns far less fuel. The strategy difference falls
out of where the core sits, so no branch is needed here. The dials
live in METABOLIC_DEFAULTS (metabolism owns its rates).
ProtectedthermalIn-session game-time (seconds), or null when no world clock is
bootstrapped — thermal stays idle (the metabolism now-source guard
verbatim). Production always has a clock; a unit test that hasn't
set one up reads null and never drifts.
Get a string representation of this object (for debugging).
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.
Flush the un-absorbed digestion pools (vomit) — absorbed state stays.
ProtectedwetWet-bulb temperature (K) — the simplified Stull approximation.
ProtectedwornWorn-slot clo sum, expressed as a Kelvin band-widening.
Would lifting candidate (as loose carry) push burden past the ceiling?
Staticcleanup
Creature concrete class — a living body.
Characterextends this and adds agency.Agentalready registers the top-level branch;Creaturedoes not re-register.