# Slice J5.5 — per-session physics and remote-simulation ownership Date: 2026-07-26 Scope: ownership relocation only; no retail algorithm or gameplay-policy change ## Objective Make one `AcDream.Runtime` instance own one complete mutable physics world: - one `PhysicsEngine`, its transition-scratch arena, and its shadow registry; - one production `PhysicsDataCache`/cell graph; - canonical physics bodies and physics hosts; - canonical remote movement/interpolation state; - loaded/cell-backed ordinary and remote update worksets. App remains responsible for DAT/package preparation, streaming policy, animation pose production, render projection, effects, meshes, debug drawing, and UI. It publishes immutable prepared collision records and animation-root inputs to the Runtime owner, then applies committed Runtime snapshots to graphical objects. This is the J5.5 boundary from `docs/plans/2026-07-26-modern-runtime-slice-j5.md`. Projectile component ownership and prediction remain explicitly deferred to J5.6. ## Named-retail oracle Primary source: `docs/research/named-retail/acclient_2013_pseudo_c.txt`. - `CPhysics::UseTime` `0x00509950` - `CPhysicsObj::UpdatePositionInternal` `0x00512C30` - `CPhysicsObj::transition` `0x00512DC0` - `CPhysicsObj::SetPositionInternal(CTransition const*)` `0x00515330` - `CPhysicsObj::UpdateObjectInternal` `0x005156B0` - `CPhysicsObj::update_object` `0x00515D10` - `CPhysicsObj::MoveOrTeleport` `0x00516330` - `CPhysicsObj::add_shadows_to_cells` `0x00514AE0` The complete translated control flow is already pinned in `docs/research/2026-07-19-r6-update-object-order-pseudocode.md`. The current Core/App implementation was cross-checked there and in the R6/physics digest against ACE's `PhysicsObj` interpretation and the extracted WorldBuilder collision/content pipeline. J5.5 reuses that port unchanged. ## Preserved pseudocode ```text for each ordinary object in the active object table: elapsed = current physics time - object update time apply retail epsilon / stale-quantum / subdivision gates if object is Active: if not Hidden: advance PartArray and obtain the complete root-motion Frame apply PositionManager correction to that Frame compose the candidate position and orientation if not Hidden: integrate acceleration, velocity, and omega drain object animation hooks if the candidate frame moved: run Transition against the object's current full cell commit accepted frame, contact state, and full cell update the object's collision shadows DetectionManager.CheckDetection TargetManager.HandleTargetting MovementManager.UseTime PartArray.HandleMovement PositionManager.UseTime ParticleManager.UpdateParticles ScriptManager.UpdateScripts ``` The App/Runtime seam may split pose production from simulation, but it must not change this observable ordering. In particular: - root motion and the position-manager delta are complete before collision; - the transition's swept full cell is canonical; - a Hidden object is not the same as an inactive or deleted object; - exact record/incarnation, authority version, and object-clock epoch are revalidated after every callback; - remote shadows follow the committed body frame, never a raw server sample; - `CellGraph.CurrCell` remains local-player-only state. ## Baseline ownership gap The canonical `RuntimeEntityRecord` already owns `PhysicsBody`, `IPhysicsObjHost`, full cell, final physics state, accepted authority versions, and `RetailObjectQuantumClock`. The remaining duplicate boundary is: - `GameWindow` constructs the session `PhysicsEngine` and production `PhysicsDataCache`; - App `LiveEntityRecord` stores the remote-motion component; - App `LiveEntityRuntime` stores remote and ordinary spatial workset indexes; - App updaters both mutate canonical simulation and project `WorldEntity`; - App streaming mutates the engine directly. That baseline shape prevented a no-window Runtime from owning the same simulation graph and made two simultaneous sessions harder to prove isolated. J5.5 retires this gap. ## Target ownership `RuntimeEntityObjectLifetime` constructs one `RuntimePhysicsState` beside its entity directory. `RuntimePhysicsState` owns: - the exact `PhysicsEngine` and production cache; - remote components and physics hosts stored on `RuntimeEntityRecord`; - keyed ordinary/remote worksets containing exact `RuntimeEntityKey` values; - typed collision admission/withdrawal receipts; - simulation commits and immutable presentation snapshots; - reset/disposal convergence and an ownership ledger. App acknowledgements contain no gameplay policy: ```text prepared collision publication -> Runtime typed admission -> receipt render spatial visibility edge -> Runtime workset acknowledgement animated root Frame -> Runtime remote/ordinary tick Runtime committed snapshot -> App WorldEntity/rebucket/pose projection ``` The immutable prepared collision payload may originate in App streaming. The engine, transition scratch, cell graph, body, shadow registry, interpolation, manager state, and workset are never shared across Runtime instances. ## Implemented boundary - `RuntimeEntityObjectLifetime` constructs and disposes exactly one `RuntimePhysicsState`. - `RuntimePhysicsState` constructs the production `PhysicsDataCache` and the sole `PhysicsEngine`, including its ten-deep reusable transition scratch and shadow registry. App borrows both objects and cannot construct alternatives. - `RuntimeEntityRecord` owns the canonical `PhysicsBody`, `RemoteMotion`, `EntityPhysicsHost`, full cell, object clock, and exact-incarnation binding guards. - `RuntimePhysicsState` owns keyed ordinary/remote worksets, body acquisition, host installation/rebinding/lookup, remote component binding, and typed canonical cell commits. - `RuntimeRemotePhysicsUpdater` and `RuntimeOrdinaryPhysicsUpdater` contain the unchanged presentation-free retail simulation. Their App adapters supply DAT-derived shape/animation inputs and project immutable pose snapshots only. - `LandblockPhysicsPublisher` publishes the prepared collision root through a generation-scoped `RuntimeCollisionAdmission`; demotion and withdrawal cross the same typed Runtime boundary. - Runtime cell commits synchronously publish `RuntimePhysicsCellCommit`. The graphical subscriber revalidates the exact record and spatial-authority version before rebucketing the render projection. - Two Runtime instances own distinct engines, caches, cell graphs, scratch arenas, shadow registries, components, hosts, bodies, and worksets. No retail algorithm, constant, order, packet, or gameplay policy changed, and this ownership relocation introduces no retail-divergence row. ## Staged implementation boundary 1. Construct engine/cache under `RuntimePhysicsState`; make App borrow them. 2. Move presentation-free `RemoteMotion` and `EntityPhysicsHost` types into Runtime and store the remote component on `RuntimeEntityRecord`. 3. Move remote/ordinary keyed worksets and their visibility acknowledgements into `RuntimePhysicsState`. 4. Split remote/ordinary update into Runtime simulation commits and App presentation acknowledgements without changing update order. 5. Replace direct streaming mutation with typed Runtime admission/withdrawal receipts. 6. Remove App simulation mirrors and prove reset/two-instance isolation. Each intermediate state must build and retain exact behavior. The production commit remains independently revertible as the single J5.5 ownership unit. ## Acceptance evidence - existing flat-collision conformance corpus remains bit-identical; - reused versus fresh transition scratch stays equivalent and allocation-free; - local and remote position/cell/orientation fixtures remain exact; - crowd, doors, stairs, cell seams, Hidden, teleport, delete, and GUID-reuse fixtures pass; - two Runtime instances have distinct engine, cache, scratch, shadows, bodies, hosts, remote components, and worksets; - App production source cannot construct a `PhysicsEngine`, `PhysicsDataCache`, canonical remote component, or simulation workset; - Release build, focused Runtime/App suites, complete Release suite, connected lifecycle/reconnect, and the canonical movement route pass. Automated gate on the J5.5 production tree: - Release solution build: zero warnings and zero errors. - Core collision/physics suite: 3,273 passed / 2 skipped. - Runtime suite: 314 passed. - App suite: 3,718 passed / 3 skipped. - Complete solution: 8,588 passed / 5 skipped. - Source ownership guards prove App does not construct a `PhysicsEngine` or production cache, does not contain the remote/ordinary transition solver, and cannot directly admit/remove streamed landblock collision. Connected gates pass on exact production commit `7e6033d0adcd0b572c20e89dd275746fb442d52f`: - `logs/connected-world-gate-20260726-134107/report.json` completed capped login and uncapped fresh-process reconnect, all 7 readiness checkpoints, graceful code-zero exits, and zero failures; - `logs/connected-r6-soak-20260726-134638.report.json` matched source and binary SHA, materialized all 9 destinations with render and collision ready, passed forward/jump/combat/authoritative movement exercises at Caul, Holtburg, and Caul return, and exited gracefully with code zero and zero failures. Exact production rollback: ```text git revert 7e6033d0adcd0b572c20e89dd275746fb442d52f ```