Ymir/docs/architecture.md
Meta Vens 21e7c43777 Remove the Eve surface from Ymir.Core (parked at parked/ymir-eve-surface)
Eve is deprecated; per thing2:ruling:eve-dashboards-quarantined the surface builders, EveSurfaceDocument publication, GameCult.Eve.Surface reference and EveRoot are gone. YmirOperatorStateDocument and its publication stay.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 20:02:38 +02:00

11 KiB

Ymir Architecture

Objective

Expose Box3D as authoritative, typed, persistent GameCult physics without leaking an alpha native API into products, clients, or durable state.

Ymir's target is a stable embedded wrapper around retained Box3D worlds, not an independent physics-engine research project. Box3D supplies the physics mind. Ymir supplies the memory, nerves, names, and session boundary. The same boundary may optionally be hosted as a standalone daemon.

Target Owner

A long-lived Box3D b3World owns the physical decision: given the current world plus commands for a fixed step, what transforms, velocities, overlaps, casts, and contact transitions are true.

Ymir owns the enclosing session and contract:

  • pin and build the accepted Box3D release;
  • map stable GameCult ids to transient Box3D handles;
  • accept typed body, shape, filter, force, torque, field, query, and step commands;
  • project Box3D outputs into typed, deterministically ordered Ymir facts;
  • reconstruct sessions from CultCache checkpoints;
  • return typed state, contacts, queries, and receipts to an embedding product;
  • when running standalone, publish Ymir's own physics provider and operator surfaces through CultMesh;
  • supervise world lifetime, failure, replay, and observability.

Deployment Boundary

For Aetheria, Ymir is an embedded library. Aetheria owns the outer daemon, gameplay session, fixed tick, product commands and receipts, asset catalog, and advertised Eve/CultMesh surface. Generic Eve clients connect directly to the Aetheria daemon. They never import Ymir internals and do not route gameplay through a standalone Ymir or discovery service.

A standalone Ymir daemon is an optional hosting mode for physics tooling and other products. It hosts the same Ymir session primitive; it is not an Aetheria relay and cannot own a shadow copy of Aetheria's world.

Current Body

The runtime solver cut is complete: Box3D is the only integrator, collision engine, broadphase, query-geometry implementation, and contact source in the committed Ymir path. The public YmirSimulator.Step compatibility API creates an isolated internal session for one complete snapshot, projects its output, and disposes it. Public circle overlap and cast APIs invoke Box3D geometry over caller-supplied bodies.

The retained native session now has a public in-process YmirSession port with explicit spawn, remove, teleport, velocity, configuration, force, torque, step, and disposal operations. It emits revisioned receipts and typed Begin/Hit/End facts with stable Ymir identities. Ordinary retained steps do not accept complete body snapshots.

The embedded retained-session library has replay-backed reconstruction, durable command receipts, incremental journal-suffix capture, and bounded resume descriptors. Aetheria stores these in a second daemon-private CultCache: immutable chunks are flushed first, immutable per-frame resumes second, and the public Aetheria frame last. The public frame is the only commit marker. Orphaned private records cannot advance gameplay truth, and restart fails closed once the persistence capability has been activated. Complete replay history is not product state and never rides in public client frames. The current CLI still has no named session registry or CultMesh command lowerings; its CultCache output remains a regenerated diagnostic projection.

Target Inputs

  • stable body and shape definitions
  • fixed time step and explicit substep count
  • transient forces, torques, impulses, and target transforms
  • collision filters and material definitions
  • overlap, ray, and shape-cast queries
  • product-owned selections such as which pickup ids a tractor may affect

Aetheria chooses physical intent and gameplay eligibility. Box3D decides geometry membership and contact. Ymir carries the typed handoff.

Target Outputs

  • body transforms and linear/angular velocities
  • begin, end, and hit contact facts with stable Ymir ids
  • overlap and cast results sorted by distance and stable id
  • step receipts and replay/checkpoint provenance
  • provider-owned operator and debug projections

Box3D callback order is not a public contract. Ymir may sort facts, but it may not alter their membership or invent missing contacts.

Derived State

  • Box3D world, body, shape, contact, and joint handles are transient session state derived from stable Ymir definitions.
  • CultCache checkpoints are reconstruction inputs and publication records; they are not a second live solver.
  • SoA body documents are transport and inspection projections over the live session.
  • Unity GameObjects and Electron objects are render state only.
  • Aetheria damage, loot, capacity, faction, and scoring consequences are derived from Ymir facts plus Aetheria policy.

Dimensional Compatibility

The fossil Aetheria simulation uses a two-dimensional gameplay plane. During cutover, Ymir maps that plane into Box3D X/Z with translation on Y locked and rotation constrained to the plane normal. This is an explicit compatibility projection. It does not make Ymir a second 2D physics engine.

Sphere friction and inertia are not identical to planar disk behavior. Any mechanic that depends on that difference must be witnessed against the fossil and then expressed through Box3D configuration, not repaired by a parallel solver.

Forbidden Writers

  • managed integration, impulse resolution, collision geometry, or broadphase code in Ymir;
  • persisted force or torque replayed as if it were continuing authority;
  • Aetheria rectangle, capsule, overlap, or contact tests deciding gameplay physics;
  • Unity collision callbacks deciding hits, destruction, or pickup collection;
  • renderer transforms pushing hidden corrections into the world;
  • transport endpoints or dashboards owning world state;
  • Box3D opaque ids stored as durable GameCult identity.

Target Shared Paths

Direct player commands, agent commands, programmatic spawns, server ticks, imports, reconnects, replay, and checkpoint recovery will enter the same Ymir session primitive for their named world. Today, DTO compatibility methods lower into an isolated Box3D session; they may not run an alternate step or infer retained identity from a body list.

Session identity must be explicit. A process-wide simulator object, zone index, or repeated stable body id is not enough to join two calls to the same world. Aetheria owns run and zone lifetime and creates, retains, and disposes the corresponding embedded Ymir session. Projectile sweep and stationary mine proximity integration can use Ymir's revision-checked retained-session circle-cast and overlap queries. They observe the current stable-id body projection; they do not invent a contact episode or mutate the Box3D world.

Radial gravity and tractor attraction are typed force-generation inputs. They are applied to Box3D before stepping. Pickup collection remains an Aetheria transaction triggered exactly once by a Ymir/Box3D contact fact.

Native Boundary

extern/box3d pins the accepted upstream source. native/Ymir.Box3D owns a small stable C ABI facade. Managed Ymir code binds only to that facade; it does not scatter hundreds of direct P/Invokes across the daemon.

The native facade must remain boring:

  • caller-owned blittable buffers;
  • explicit version and precision facts;
  • no GameCult gameplay policy;
  • no JSON state boundary;
  • no public exposure of Box3D internal handles;
  • first-class RID packaging before production consumers depend on it.

Target Persistence Contract

Canonical deterministic replay starts from the same initial definitions and creation order, then applies the complete command stream under the pinned Box3D build and accepted runtime configuration.

A checkpoint restart is a different promise. Its schema must contain enough typed definitions and state to reconstruct an equivalent Box3D world: stable ids, 3D transforms, linear and angular velocity, body/shape/material/filter definitions, session tuning, and provenance. Box3D does not expose every internal solver cache, so arbitrary mid-world checkpoint restart is tested against named numeric state tolerances rather than claimed as bit-identical continuation. Contact membership, ordering, and exactly-once lifecycle identity are binary contracts, not tolerance checks. Authoritative contact facts resume only after canonical history has been replayed through the checkpoint tick; a checkpoint alone cannot emit gameplay contact facts.

gamecult.ymir.session_checkpoint.replay.v1 implements that promise. It stores the initial definitions, complete typed command journal, logical session generation, command digest, body-generation counter, world verification projection, active contact-episode verification records, and pinned runtime fingerprint. Restore replays into a new Box3D world with outward publication suppressed, then compares the reconstructed boundary exactly before returning a live session. The bounded binary codec rejects incompatible, corrupt, or trailing data and checksums the complete encoded payload. ABI v5 validates the exact pinned native build id, not merely Box3D's public version. Native Box3D identities never enter the checkpoint.

gamecult.ymir.world_state.v2 appends Box3D body type, bullet, field-participation, and collision filter arrays to the v1 layout. The v1 and v0 readers are explicit migration paths; keys are not reassigned. Torque is transient command state and is intentionally absent. Version 2 is a compatibility world snapshot, not a complete retained-session checkpoint: it does not preserve full shape, material, filter, session tuning, provenance, or warm contact state.

Transient forces and torques are commands, not durable body state. Derived mass and inertia are published only when useful for inspection. Old checkpoint versions must migrate explicitly or fail closed; they may not silently decode under a reassigned MessagePack layout.

Cut Line

The managed integrator and circle impulse solver have been deleted from the runtime path. Any uncommitted YmirQueryPrimitives or YmirSpatialIndex work is obsolete and must not be annexed. The retained-session cut continues until Box3D-backed sessions prove:

  1. fixed-step body state projection;
  2. begin/end/hit contact lifecycle;
  3. overlap and shape-cast lowering;
  4. continuous collision event timing and same-step Box3D cast witnesses;
  5. transient force and torque application;
  6. checkpoint reconstruction and replay (implemented; journal compaction and long-running storage remain operational work);
  7. Aetheria gravity, tractor, pickup, and payload smokes.

There is no managed fallback after that cut. A native load or compatibility failure fails closed and reports the missing capability.

Required Verification

  • Box3D parity tests record released upstream law at the native boundary.
  • Ymir differential tests compare public projections with the same Box3D session facts.
  • Negative source checks prove custom solver and spatial-index authorities are absent after cutover.
  • Aetheria smokes prove gravity, tractor attraction, contact-gated pickup collection/rejection, physical payload hits, and restart continuation through the retained contract. Destruction loot remains Aetheria gameplay state gated by Ymir contact facts where collection occurs.
  • Released-client witnesses prove generic Eve clients only observe Ymir and Aetheria provider contracts, never native implementation details.