docs(runtime): close J3.2 canonical identity gate

Record the exact f46ddb5c rollback, 8,441-test Release gate, and seven-checkpoint connected lifecycle/reconnect pass. Update the canonical project state and pin J3.3's exact-key App projection-store execution plan.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-25 20:14:29 +02:00
parent f46ddb5cdb
commit e18df84437
8 changed files with 306 additions and 8 deletions

View file

@ -0,0 +1,133 @@
# Modern runtime J3.3 — exact-key App projection store
**Status:** READY AFTER J3.2 CONNECTED GATE
**Parent:** `2026-07-25-modern-runtime-slice-j3.md`
**Required base:** `f46ddb5cdb1e145752bea49aeb1d62bfe71284d3`
## Objective
Make every materialized App-side live-object owner use the exact
`RuntimeEntityKey` (`Runtime local ID + INSTANCE_TS`) issued by
`RuntimeEntityDirectory`.
Runtime remains the only server-GUID authority. App may carry GUID as immutable
metadata for diagnostics and outbound commands, but no App dictionary may use
GUID to decide which incarnation is current.
No asynchronous projection queue, extra input frame, renderer behavior change,
or local-ID allocation-order change is permitted.
## Fixed model
There are three distinct states:
1. **Canonical-only registration** — Runtime accepted an incarnation, but no
graphical host has claimed a local ID. No materialized projection exists.
2. **Materialized projection** — Runtime has claimed the local ID and App owns
exactly one sidecar under the resulting `RuntimeEntityKey`.
3. **Retryable teardown** — Runtime retains the exact canonical tombstone while
App retains only the unfinished teardown suffix for that exact key. A
registration that failed before local-ID claim has no graphical tombstone.
A small synchronous construction context may carry a canonical record between
registration and materialization. It is not a retained App identity map.
## Execution
### 1. Introduce `LiveEntityProjectionStore`
- Store materialized sidecars in
`Dictionary<RuntimeEntityKey, LiveEntityRecord>`.
- Resolve GUID only by asking `RuntimeEntityDirectory` for the current
canonical record, reading its exact key, then querying the store.
- Reject key reuse, local-ID mismatch, incarnation mismatch, and stale
canonical records.
- Preserve insertion order and allocation-free borrowed enumeration.
- Retain teardown progress under the exact key; use canonical-reference storage
only for the exceptional pre-materialization registration rollback which has
no key.
### 2. Move sidecar creation to local-ID claim
- `RegisterLiveEntity` returns canonical registration facts without allocating
a graphical sidecar.
- `MaterializeLiveEntity` claims the Runtime local ID at the same point as
today, creates the exact-key sidecar, then calls the projection factory.
- Same-incarnation refresh before materialization mutates only Runtime state.
- Same-incarnation refresh after materialization resolves the existing sidecar
through its exact key.
- Factory, resource-registration, and rollback failures retain exactly the
currently unfinished ownership suffix.
### 3. Re-key every presentation workset
Convert the following from GUID/local-ID-only maps to exact-key maps:
- materialized and visible `WorldEntity` projections;
- animation and spatial-animation owners;
- remote-motion and spatial-remote-motion owners;
- projectile and spatial-projectile owners;
- ordinary root object workset;
- effect profile, visibility publication, hydration, and teardown lookups.
Local-ID-only iteration views validate the incarnation through the projection
store before yielding. No stale entry can match a replacement that reused the
same numeric local ID after wraparound.
### 4. Cut consumers over to borrowed queries
- Replace direct GUID dictionary access in selection, radar, combat targeting,
local-player animation/mode, teleport, physics update, diagnostics, and
composition with typed `TryGet...`, exact-key, or borrowed-enumeration
methods.
- Keep synchronous press-time reads; do not publish a copied frame snapshot.
- Preserve server GUID in yielded metadata where outbound commands need it.
- Remove `MaterializedWorldEntities`, `WorldEntities`, and component
dictionaries once all consumers use the focused queries.
### 5. Delete the J3.2 compatibility view
- Delete `ActiveRecordView`.
- Delete `_activeRecords` and every App GUID-keyed live-object/component map.
- Remove the detached `LiveEntityRecord(EntitySpawn)` fixture constructor;
component tests construct exact Runtime identities through a shared fixture.
- Add source guards rejecting:
- App `Dictionary<uint, LiveEntityRecord>`;
- App live-object/component maps keyed by server GUID;
- an App reverse GUID/local-ID map;
- a projection store key other than `RuntimeEntityKey`.
### 6. Failure and parity gate
Exercise:
- create without materialization;
- same-incarnation refresh before and after materialization;
- factory throw before sidecar publication;
- resource register failure with successful and failed rollback;
- loaded/pending rebucket and visibility reentrancy;
- delete/recreate with the same GUID;
- local-ID wraparound and stale-key rejection;
- parent/pickup/Hidden transitions;
- session clear during every projection callback;
- retryable teardown with a live replacement.
Run:
- focused Runtime and App identity/projection tests;
- all App tests;
- Release solution build;
- complete Release tests;
- exact-binary connected lifecycle/reconnect;
- render-scene identity/digest referee at every checkpoint.
## Acceptance
- Runtime owns the only GUID/incarnation/local-ID authority.
- Every materialized App owner is keyed by exact `RuntimeEntityKey`.
- App retains no GUID identity dictionary or reverse local-ID authority.
- A stale key cannot query, update, withdraw, or tear down a replacement.
- Local-ID allocation order is unchanged.
- No new allocation appears in steady-state live-object traversal.
- No callback is delayed to another frame.
- All automated and connected gates pass on the exact commit.