Reconcile J3 with later gameplay lifetime groups, inventory the current mixed entity/object ownership, and define the staged canonical identity, projection, object-table, delta, teardown, and no-window gates. Co-authored-by: Codex <codex@openai.com>
12 KiB
Modern runtime Slice J3 — canonical identity, properties, and object table
Status: ACTIVE
Parent: 2026-07-25-modern-runtime-slice-j.md, J3
Production base: 9496c01b
J2 production commit: 75930787741db40a83eab8663e4464dce8d687ba
1. Objective
Move the one canonical server-object identity/incarnation owner, accepted
CreateObject/property/timestamp state, parent relation state, and
ClientObjectTable lifetime into AcDream.Runtime.
App becomes a projection host. Its world entity, animation, effect, light, selection, paperdoll, spatial bucket, and hydration state is keyed by a Runtime-issued local identity plus exact incarnation. App must not retain a second server-GUID map or decide whether a packet belongs to the current incarnation.
This is a structural move. Existing named-retail CreateObject, timestamp, parenting, pickup, Hidden, delete, and generation-replacement behavior remains unchanged. No renderer, particle, streaming, GL, or retained-UI type may enter Runtime.
2. Scope reconciliation
The umbrella J3 text overlaps later lifetime groups. This detailed plan is the authoritative split:
- J3 moves raw accepted entity identity, immutable spawn/property snapshots, timestamp gates, parent relations, and the canonical client object/container table.
- J4 moves higher-level inventory transactions, vitals, enchantments, spell/component state, cooldown services, chat, and their ViewModel-facing revisions.
- J5 moves movement/physics/interaction/combat authority.
J3 may retain existing Core physics references already stored on the entity record while separating presentation, but it does not redesign or relocate their behavior. That coherent move remains J5.
3. Fixed ownership after J3
AcDream.Runtime owns:
- server GUID to current incarnation;
- exact Runtime local identity allocation and reverse lookup;
- accepted
INSTANCE_TSand every retail packet-channel timestamp; - the latest accepted immutable
WorldSession.EntitySpawn; - logical create, same-incarnation refresh, pickup, parent, Hidden/state, delete, generation replacement, tombstone, and session-clear state;
- unresolved/staged/committed parent relations;
ClientObjectTable, containers, placement indices, pending authoritative property state, and generation-aware removal;- ordered immutable entity/object deltas;
- retryable logical teardown state and the acknowledgement from an attached projection host.
AcDream.App owns:
WorldEntityand render-scene projection;- loaded/pending spatial buckets and visibility derived from streaming;
- animation, remote-motion presentation, projectile presentation, effects, lights, selection geometry, radar presentation, and private paperdolls;
- projection hydration/recovery transaction state;
- render/resource registration and its exact retryable teardown suffix.
App projection keys are:
RuntimeLocalEntityId + INSTANCE_TS
Server GUID may be carried as immutable metadata for diagnostics and outbound commands, but it is not an App lookup authority.
4. Runtime contracts
Introduce or finish contracts equivalent to:
public readonly record struct RuntimeEntityKey(
uint LocalEntityId,
ushort Incarnation);
public readonly record struct RuntimeEntityDelta(
ulong Sequence,
RuntimeGenerationToken SessionGeneration,
RuntimeEntityKey Entity,
RuntimeEntityDeltaKind Kind,
RuntimeEntitySnapshot Snapshot);
public interface IRuntimeEntityProjectionHost
{
RuntimeProjectionAcknowledgement Register(RuntimeEntitySnapshot entity);
RuntimeProjectionAcknowledgement Update(RuntimeEntityDelta delta);
RuntimeProjectionAcknowledgement Withdraw(RuntimeEntityKey entity);
RuntimeProjectionAcknowledgement TearDown(RuntimeEntityKey entity);
}
The concrete names may follow existing project vocabulary, but these invariants are mandatory:
- Runtime issues identity before App creates a projection.
- Every App callback carries the exact local identity and incarnation.
- Callback acknowledgement is exact and retryable.
- Completed teardown work never replays.
- App cannot query or mutate Runtime by a stale local identity/incarnation.
- Runtime emits deltas only after canonical state commits.
- Callback reentrancy may supersede the outer operation; the outer operation must revalidate generation/incarnation/operation version before continuing.
5. Execution slices
J3.0 — oracle and ownership inventory
- Pin the current field/method ownership table for
LiveEntityRecord,LiveEntityRuntime,InboundPhysicsStateController,ParentAttachmentState,ClientObjectTable,GpuWorldState, hydration, and teardown owners. - Reuse the existing retail pseudocode and citations; no behavior is being invented. Add research only where a current branch lacks a cited oracle.
- Capture normalized existing traces for create, same-generation refresh, parent/unparent, pickup, Hidden, delete/recreate, GUID reuse, container placement, and session clear.
- Record baseline render-scene identity/digest at deterministic fixtures.
J3.1 — move narrow accepted-wire owners
- Move
InboundPhysicsStateController,ParentAttachmentState, their result types, and their complete tests into Runtime. - Preserve timestamp cursor/order behavior and parent candidate ordering line-for-line.
- App's existing
LiveEntityRuntimetemporarily composes those Runtime owners; no second state is introduced. - Add Runtime dependency/load guards around the moved types.
Gate: all timestamp, malformed, wraparound, parent-generation, and packet-order tests pass in Runtime; App behavior and complete suite remain unchanged.
J3.2 — canonical Runtime entity directory
- Extract current GUID/incarnation maps, accepted snapshot state, session lifetime version, operation versions, tombstones, delete/generation replacement, and local-ID allocation into one Runtime owner.
- Split
LiveEntityRecordinto canonical Runtime state and an App projection sidecar. Canonical fields never reference App interfaces orWorldEntity. - Preserve current local-ID allocation order during graphical hydration for parity; Runtime owns the allocator and claim, while a no-window host may claim immediately.
- Retain exact reentrant supersession and retryable tombstone behavior.
- Keep physics/movement fields structurally in place where required for J5, but remove every renderer/effect/hydration reference from the canonical record.
Gate: the complete existing LiveEntityRuntimeTests identity/timestamp/
teardown subset moves to Runtime and produces the same normalized trace.
J3.3 — App projection store and cutover
- Add one App projection store keyed only by Runtime local identity plus incarnation.
- Move
WorldEntity, spatial visibility, hydration/recovery flags, animation, remote-motion presentation, projectile presentation, effect profiles, resource flags, and active presentation worksets into that store. - Convert
GpuWorldState, hydration, equipped children, render journal, animation/effect/light owners, selection/radar queries, and teardown to the exact projection key. - Replace App's mixed
LiveEntityRuntimefacade with focused Runtime directory and App projection-store dependencies; delete its GUID maps and mixed record. - Preserve current register-once, rebucket-only, withdraw-without-destroy, Hidden, and retryable logical teardown order.
Gate: projection identity/digest and all existing hydration, rebucket, visibility, effect, animation, projectile, selection, and teardown tests match. Source guards reject any App server-GUID authority map.
J3.4 — canonical object-table ownership
- Add a Runtime entity/object lifetime-group root that owns the canonical
entity directory and the existing Core
ClientObjectTable. - Construct it before either graphical UI or live presentation; both borrow the same instances.
- Remove the public
ClientObjectTableowner field fromGameWindow. - Route J2 inbound object/property/container updates directly to the Runtime group.
- Keep UI controllers, item icons, paperdoll, grids, cooldown drawing, and interaction presentation as App borrowers.
- Preserve synchronous press-time reads and current event ordering; add no queue or copied inventory model.
Gate: object add/update/remove, placement, container replacement, optimistic move rollback, stack response, GUID reuse, and session-clear traces match.
J3.5 — ordered deltas and borrowed views
- Publish one monotonic per-session Runtime entity/object delta stream.
- Make J1
IGameRuntimeView.Entitiesand inventory snapshots read the Runtime owners directly rather than App adapters. - Feed App projection mutation from the same committed deltas/acknowledgements; do not create a second queue or frame delay.
- Remove superseded App entity/object event mirroring and source adapters.
- Assert same-thread graphical input and inbound presentation remain synchronous.
Gate: direct-host and graphical-host normalized traces are identical, including sequence, generation, identity, properties, placement, and teardown edges.
J3.6 — hardening and closeout
- Failure-inject every projection registration/update/withdraw/teardown stage.
- Exercise callback reentrancy, duplicate CreateObject, stale/equal/wrapped timestamps, delete/recreate with the same GUID, pending-to-loaded movement, parent events before either object, malformed property packets, and session reset during callbacks.
- Prove zero leaked canonical records, tombstones, App projections, resources, container entries, parent candidates, queued deltas, or subscriptions.
- Add a Runtime-only entity/object fixture that performs create, property updates, parent/container moves, Hidden, delete/recreate, clear, and teardown without loading presentation/backend assemblies.
- Run Release build, focused suites, complete tests, exact-binary connected lifecycle/reconnect, and the canonical world route.
- Because J3 changes projection identity plumbing, run the existing automated render digest/referee at every checkpoint. Pause for user visual verification only if the referee or connected client exposes a pixel/interaction symptom.
6. Commit order
refactor(runtime): move accepted entity wire staterefactor(runtime): own canonical entity identity and incarnationsrefactor(app): key live projections by runtime identityrefactor(runtime): own canonical object tablefeat(runtime): publish ordered entity and object deltastest(runtime): close J3 entity ownership parity
Each commit is independently buildable and bisectable. The exact rollback for each lands in this document before that commit's connected or visual gate.
7. Acceptance
J3 is complete only when:
- Runtime owns the only server-GUID/incarnation map and object table;
- App projections are keyed by local identity plus incarnation;
- Runtime has no App/UI/backend dependency;
- App has no authoritative GUID map or accepted timestamp gate;
- no mirrored collection, asynchronous seam, or added input frame exists;
- normalized direct/graphical traces match;
- deterministic render identity/digests match;
- Runtime-only no-window entity/object lifecycle passes;
- Release build and complete tests pass;
- exact-binary connected login/travel/logout/reconnect passes gracefully;
- every teardown owner converges to zero.
8. Current rollback chain
git revert 75930787741db40a83eab8663e4464dce8d687ba
git revert 854d9e9cd13092bd5aaa3cf025d73eeb4600e9f8
git revert b632672e5ccabfb44c551e08f1c411ab2669c44a
These are J2, J1, and J0 respectively. Do not use them for a J3 sub-slice failure; record and revert only the exact failing J3 commit.