The catalog in packages/schema/builtins.ts now defines the original 17 components plus KinematicPlatform and PlatformRoute. Descriptors supply closed fields, bounds, persistence, visibility, authority and prediction metadata. The checked-in golden manifest freezes these development contracts; changes require versioning and migration rather than silently changing an existing published descriptor.
The catalog's schema fingerprint is 0d34e53f928c2d6d83334da341dd643b48f93b542c8c893e8ada851f589cd2f6. This is the component catalog identity. The beta room still negotiates its existing world/content fingerprint; component dictionary negotiation is a remaining networking integration gate.
The original 17-component manifest remains unchanged. Simulation checkpoint profile 7 explicitly migrates the earlier catalogs; schema addition alone does not enable shared platform replication. See canonical platforms.
#Catalog and current execution
| Component | Version | Fields and purpose | Current execution |
|---|---|---|---|
| Transform | 2 | Place-local position, quaternion rotation and scale | Player pose, hierarchy resolver and fixtures; ten float64 columns |
| PlaceMembership | 1 | Place ID | Player startup and immediate travel update; hierarchy place validation |
| Parent | 1 | Parent entity ID; absence means root | Validated reparenting and hierarchy fixtures |
| RenderMesh | 1 | Asset ID, visibility, shadow flags, LOD bias | Descriptor; imported-mesh/render protocol integration remains |
| MaterialRef | 1 | Up to 16 named material slots | Descriptor; material assets remain |
| Collider | 1 | Proxy asset ID, enable/sensor, friction/restitution, collision groups | Explicit platform box binding; general collider compiler remains |
| RigidBody | 1 | Body kind, linear/angular velocity, mass, gravity scale, sleeping | Canonical kinematic platform state; shared dynamic-body integration remains |
| CharacterMotor | 1 | Velocity, grounded/crouched state, support platform ID | Current player velocity/ground state and canonical support entity; crouched remains false |
| AnimationState | 1 | Clip, time, speed, loop | Descriptor; animation importer/runtime remains |
| InputOwner | 1 | Player identity | Descriptor; owner routing integration remains |
| AuthorityDomain | 1 | Domain, owner, uint64 epoch, authority profile | Descriptor; per-entity/domain routing remains |
| Interaction | 1 | Action, label, enabled state, radius | Descriptor; current authored action format still drives the beta |
| BehaviorState | 1 | Module, enabled state and another registered state component | Descriptor; behavior runtime remains |
| PersistentIdentity | 1 | Stable persisted identity | Spawn allocation and enforced ECS identity agreement; durable host mapping remains |
| AudioEmitter | 1 | Asset, gain, loop/play/spatial flags, range | Descriptor; entity-driven audio integration remains |
| Light | 1 | Kind, linear RGB, intensity, range, cone angles, shadows | Descriptor; existing place lights still drive rendering |
| Tags | 1 | Up to 64 bounded tag strings | Descriptor; authoring/search integration remains |
| KinematicPlatform | 1 | Pending target position/yaw and blocked state | Owned platform commands, native/ECS validation, place parking and full checkpoint restore |
| PlatformRoute | 1 | Bounded route time | Authored loop, ping-pong and one-way routes; blocked/inactive phase retention and checkpoint restore |
The player registers the catalog and writes Transform, PlaceMembership and CharacterMotor. Registration is not evidence that every listed runtime system is implemented. Descriptor bounds are structural contracts; system-specific checks, such as a spot light's cone ordering or permitted physics scaling, must be enforced by those systems before activation. Visibility/authority metadata does not itself filter network data or authorize writes.
BehaviorState points to a separately registered, versioned component for module data. It does not provide an unvalidated generic JSON payload that bypasses the registry. CharacterMotor is a current presentation/state record, not a complete physics-controller replay snapshot: the separate simulation checkpoint now captures jump-edge state, controller settings and native physics. Full milestone 3 motor coverage still remains.
#Numeric and coordinate conventions
Positions use meters and place-local right-handed coordinates, with Y up and initial forward −Z. Angles use radians. Transform quaternions are [x, y, z, w]; their norm must be within 1e-6 of one. Zero, non-finite and non-unit quaternions fail validation. Both quaternion signs are accepted as equivalent rotations; stored values are not silently rounded or rewritten.
Local position components are bounded to ±1,000,000; positive scale components range from 0.0001 through 10,000. Negative/zero scale is outside this initial Transform contract. Physics must separately decide which nonuniform scales it can represent. Matrix composition uses float64 values and normalizes the already validated quaternion for rotation construction. Tests compare its XYZ Euler conversion with the existing primitive renderer's orientation convention.
The schema vocabulary now includes a unit quaternion and canonical decimal uint64 string. Uint64 values reject leading zeros, signs, whitespace, exponent/fraction syntax and values above 18,446,744,073,709,551,615. Strings may declare a minimum length; references use nonempty IDs bounded to 256 UTF-16 code units. Unknown schema/descriptor fields are rejected, so a misspelled constraint cannot look like an enforced rule.
#Migration and beta compatibility
Transform version 1 was the player's three-number position tuple. Its explicit migration produces {position: oldPosition, rotation: [0,0,0,1], scale: [1,1,1]}. Old and current snapshots fix the expected result. Invalid legacy data rejects the baseline without changing live handles or reader cursors. Migration does not invent a place or parent; a spatial baseline must supply those identities separately before it can be resolved.
The beta's SavedGame format and authored world remain unchanged. This update does not reset local or room progress, migrate the live Coolify volume, or change the content fingerprint. The legacy save still does not persist facing/scale or a complete controller state; exporting an ECS snapshot and saving a full simulation checkpoint remain distinct operations; the new checkpoint API captures current controller/runtime state without changing the beta save format.
#Hierarchy behavior
resolveTransformNodes validates and composes a complete forest before returning any result. It rejects duplicate IDs, missing parents, cycles, cross-place parent links, invalid local values, unknown places when a place set is supplied, more than 65,536 nodes, depth above 128, and composed matrix magnitudes above 1e9. Roots have depth zero. Results are ordered by stable entity ID, regardless of input or dense-storage order.
Matrices preserve nonuniform-scale shear introduced by parent/child composition; the resolver never silently decomposes the result into a lossy world rotation/scale pair. Separate place roots remain separate coordinate frames. Portal transforms will be an explicit later connection between frames.
resolveTransforms reads the registered components from an EntityStore. setParent and setLocalTransform first validate a projected forest, then record the write. Reparenting preserves the local pose; clearing Parent makes that local pose a root pose. World-preserving reparenting and physics constraints are future editor/runtime work. EntityStore's find(id) returns a copied runtime handle; id(handle) rejects stale generations.
installSpatialInvariant(store, knownPlaces) now enforces this forest contract at transaction, direct-write and restore publication. The player installs it during startup. Related place/parent edits must use one transact batch; destroying a referenced parent is rejected unless the same batch detaches or removes every dependent child. Generic stores without the invariant still validate only component shapes. Automatic subtree transfer/deletion policy, world-preserving reparenting and complete physics/streaming transfer policy remain open; current-profile simulation restore has a separate checkpoint contract. See atomic mutation contracts.
#Headless/browser evidence
packages/testkit/transforms.ts captures the same catalog and five-node, two-place hierarchy in Node and a browser worker. The fixture includes parent rotation, nonuniform scale, nested attachments and independent place roots. Its checked-in canonical evidence has digest 2a4974bf75099daa820b93cc1dcaf66c7f6ecfcb881af7b6456fcbf44aa95f62.
The Engine Observatory adds a Runtime data contracts check, with bounded worker lifetime and a downloadable result. Browser acceptance compares the complete result with a fresh Node capture, not only a success flag. This proves agreement for this fixture on the tested Node/Chromium pair; it does not establish general cross-browser physics or floating-point replay determinism.
The clean-source browser report, eight probe results and single-player benchmark pin component source b7f61fb10bbd4549f9ad96c34d6996f4e34eae4a. Desktop and narrow captures show the updated Observatory. These historical measurements precede the atomic mutation increment.