diff --git a/AGENTS.md b/AGENTS.md index aafe9ebc..8d3177c2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -205,13 +205,23 @@ App retains only option conversion, graphical callbacks, and one borrowed inertable UI command projection. Runtime tests pass 79/79, App tests pass 3,776/3 skips, the complete Release suite passes 8,428/5 skips, and the exact- binary seven-checkpoint gate passes with graceful exits and zero render-shadow -mismatches or pending deltas. J3 canonical identity, properties, and -object-table extraction is active. J0's rollback is +mismatches or pending deltas. J3.1 moved accepted physics timestamp/snapshot +and parent-relation owners into Runtime at `f7442d13`. J3.2 is complete at +`f46ddb5c`: `RuntimeEntityDirectory` now owns the only active GUID/incarnation, +teardown tombstone, local-ID/reverse, accepted-wire, parent, and session- +operation maps; `RuntimeEntityRecord` is presentation-free and App records are +graphical sidecars. Runtime tests pass 110/110, App tests pass 3,758/3 skips, +the complete Release suite passes 8,441/5 skips, and the exact-binary seven- +checkpoint lifecycle/reconnect gate passes with graceful exits, zero render- +shadow mismatches, and zero pending deltas. J3.3 exact-key App projection-store +cutover is next. J0's rollback is `git revert b632672e5ccabfb44c551e08f1c411ab2669c44a`. J1's rollback is `git revert 854d9e9cd13092bd5aaa3cf025d73eeb4600e9f8`. J2's rollback is `git revert 75930787741db40a83eab8663e4464dce8d687ba`. +J3.2's rollback is +`git revert f46ddb5cdb1e145752bea49aeb1d62bfe71284d3`. Slice H's retained UI/frame, bounded-light, and pooled/borrowed/direct network work is complete; the exact seven-checkpoint connected lifecycle/reconnect gate passes. Slice I is closed in diff --git a/CLAUDE.md b/CLAUDE.md index 23c914b5..00f49791 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -203,13 +203,23 @@ App retains only option conversion, graphical callbacks, and one borrowed inertable UI command projection. Runtime tests pass 79/79, App tests pass 3,776/3 skips, the complete Release suite passes 8,428/5 skips, and the exact- binary seven-checkpoint gate passes with graceful exits and zero render-shadow -mismatches or pending deltas. J3 canonical identity, properties, and -object-table extraction is active. J0's rollback is +mismatches or pending deltas. J3.1 moved accepted physics timestamp/snapshot +and parent-relation owners into Runtime at `f7442d13`. J3.2 is complete at +`f46ddb5c`: `RuntimeEntityDirectory` now owns the only active GUID/incarnation, +teardown tombstone, local-ID/reverse, accepted-wire, parent, and session- +operation maps; `RuntimeEntityRecord` is presentation-free and App records are +graphical sidecars. Runtime tests pass 110/110, App tests pass 3,758/3 skips, +the complete Release suite passes 8,441/5 skips, and the exact-binary seven- +checkpoint lifecycle/reconnect gate passes with graceful exits, zero render- +shadow mismatches, and zero pending deltas. J3.3 exact-key App projection-store +cutover is next. J0's rollback is `git revert b632672e5ccabfb44c551e08f1c411ab2669c44a`. J1's rollback is `git revert 854d9e9cd13092bd5aaa3cf025d73eeb4600e9f8`. J2's rollback is `git revert 75930787741db40a83eab8663e4464dce8d687ba`. +J3.2's rollback is +`git revert f46ddb5cdb1e145752bea49aeb1d62bfe71284d3`. Slice H's retained UI/frame, bounded-light, and pooled/borrowed/direct network work is complete; the exact seven-checkpoint connected lifecycle/reconnect gate passes. Slice I is closed in diff --git a/docs/plans/2026-04-11-roadmap.md b/docs/plans/2026-04-11-roadmap.md index c0aa1ada..504e90cd 100644 --- a/docs/plans/2026-04-11-roadmap.md +++ b/docs/plans/2026-04-11-roadmap.md @@ -1682,8 +1682,13 @@ port in any phase — no separate listing here. > and retryable teardown into Runtime at `75930787`. Its 79 Runtime tests, > 3,776 App tests / 3 skips, 8,428-test / 5-skip complete Release suite, and > exact-binary seven-checkpoint gate pass with graceful exits and zero render- -> shadow mismatches. J3 canonical identity, properties, and object-table -> extraction is now active. +> shadow mismatches. J3.1 moved accepted timestamp/snapshot and parent state. +> J3.2 at `f46ddb5c` now gives Runtime the only canonical GUID/incarnation, +> tombstone, local-ID/reverse, accepted-wire, parent, and operation-version +> maps. Its 110 Runtime tests, 3,758 App tests / 3 skips, 8,441-test / 5-skip +> complete Release suite, and exact-binary seven-checkpoint connected gate pass +> with graceful exits and zero render-shadow mismatch. J3.3 exact-key App +> projection storage is next. > The historical exact cutover > rollback remains > `git revert ef1d263337997bb030eadb7b8e71d73dc659907a`. Slice H is complete: diff --git a/docs/plans/2026-05-12-milestones.md b/docs/plans/2026-05-12-milestones.md index 2553051c..2be2b117 100644 --- a/docs/plans/2026-05-12-milestones.md +++ b/docs/plans/2026-05-12-milestones.md @@ -156,13 +156,21 @@ residency is `0/0/0` at every stable checkpoint and teardown converges. Slice I gracefully. J2 moved canonical session/transport lifetime and ordered inbound routing into Runtime at `75930787`; 79 Runtime tests, 3,776 App tests / 3 skips, 8,428 full Release tests / 5 skips, and its exact-binary - seven-checkpoint gate pass with graceful exits. J3 canonical identity, - properties, and object-table extraction is active under + seven-checkpoint gate pass with graceful exits. J3.1 moved accepted physics + timestamp/snapshot and parent-relation state into Runtime. J3.2 at + `f46ddb5c` now owns the only canonical GUID/incarnation, tombstone, + local-ID/reverse, accepted-wire, parent, and operation-version maps in + Runtime. Its 110 Runtime tests, 3,758 App tests / 3 skips, 8,441 full Release + tests / 5 skips, and exact-binary seven-checkpoint connected gate pass with + graceful exits and zero render-shadow mismatch. J3.3 exact-key App projection + storage is next under [`2026-07-25-modern-runtime-slice-j.md`](2026-07-25-modern-runtime-slice-j.md). Slice-I closeout evidence is [`../research/2026-07-25-slice-i7-closeout.md`](../research/2026-07-25-slice-i7-closeout.md). Slice-J2 closeout evidence is [`../research/2026-07-25-slice-j2-session-lifetime-closeout.md`](../research/2026-07-25-slice-j2-session-lifetime-closeout.md). +Slice-J3.2 closeout evidence is +[`../research/2026-07-25-slice-j3-2-canonical-entity-directory-closeout.md`](../research/2026-07-25-slice-j3-2-canonical-entity-directory-closeout.md). The historical exact G4 visual rollback remains `git revert ef1d263337997bb030eadb7b8e71d73dc659907a`. diff --git a/docs/plans/2026-07-25-modern-runtime-slice-j3-projection-store.md b/docs/plans/2026-07-25-modern-runtime-slice-j3-projection-store.md new file mode 100644 index 00000000..109d3e52 --- /dev/null +++ b/docs/plans/2026-07-25-modern-runtime-slice-j3-projection-store.md @@ -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`. +- 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`; + - 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. diff --git a/docs/plans/2026-07-25-modern-runtime-slice-j3.md b/docs/plans/2026-07-25-modern-runtime-slice-j3.md index 7d74b72e..f7e9f134 100644 --- a/docs/plans/2026-07-25-modern-runtime-slice-j3.md +++ b/docs/plans/2026-07-25-modern-runtime-slice-j3.md @@ -5,6 +5,25 @@ **Production base:** `9496c01b` **J2 production commit:** `75930787741db40a83eab8663e4464dce8d687ba` +## 0. Current checkpoint + +| Slice | Status | Commit / evidence | +|---|---|---| +| J3.0 ownership inventory | complete | `b0fecc5f65ed26042c61a1651fb134aeb432c141`; `docs/research/2026-07-25-slice-j3-entity-ownership-inventory.md` | +| J3.1 accepted-wire owners | complete | `f7442d13e9ae7d5b077ffecb1f8a10899ad46edd`; 110 Runtime tests and complete Release parity remain green after J3.2 | +| J3.2 canonical Runtime entity directory | complete | `f46ddb5cdb1e145752bea49aeb1d62bfe71284d3`; 8,441 Release tests / 5 skips and `logs/connected-world-gate-20260725-200749/report.json` pass | +| J3.3 App projection store | next | [`2026-07-25-modern-runtime-slice-j3-projection-store.md`](2026-07-25-modern-runtime-slice-j3-projection-store.md): key every graphical sidecar/workset by `RuntimeEntityKey` and remove the compatibility view | + +J3.2 passes the Release solution build and 8,441 complete tests with five +expected skips. Its exact-binary seven-checkpoint connected +lifecycle/reconnect route also passes with graceful exits, zero render-shadow +mismatches, and zero pending deltas. It adds no frame queue, backend +dependency, or gameplay behavior change. The exact rollback for J3.2 is: + +```text +git revert f46ddb5cdb1e145752bea49aeb1d62bfe71284d3 +``` + ## 1. Objective Move the one canonical server-object identity/incarnation owner, accepted @@ -263,3 +282,12 @@ 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. + +J3 sub-slices are independently reversible: + +```text +git revert f46ddb5cdb1e145752bea49aeb1d62bfe71284d3 +git revert f7442d13e9ae7d5b077ffecb1f8a10899ad46edd +``` + +Revert J3.2 before J3.1 when rolling back both. diff --git a/docs/research/2026-07-25-slice-j3-2-canonical-entity-directory-closeout.md b/docs/research/2026-07-25-slice-j3-2-canonical-entity-directory-closeout.md new file mode 100644 index 00000000..7cc74024 --- /dev/null +++ b/docs/research/2026-07-25-slice-j3-2-canonical-entity-directory-closeout.md @@ -0,0 +1,79 @@ +# Modern runtime J3.2 canonical entity directory closeout + +## Result + +J3.2 is complete at production commit +`f46ddb5cdb1e145752bea49aeb1d62bfe71284d3`. + +`AcDream.Runtime.Entities.RuntimeEntityDirectory` now owns the only: + +- active server-GUID to exact-incarnation map; +- exact-incarnation teardown tombstone map; +- Runtime local-ID allocation and reverse lookup; +- accepted inbound snapshot/timestamp owner; +- parent-relation owner; +- session lifetime epoch and per-GUID operation versions. + +`RuntimeEntityRecord` owns the presentation-free canonical spawn, `INSTANCE_TS`, +cell/state authority, retail object clock, authority versions, and the +PhysicsBody/physics-host facts deliberately carried until J5. + +App's `LiveEntityRecord` is now a graphical sidecar over that canonical record. +Its temporary dictionary-shaped `ActiveRecordView` stores no GUID map: it asks +Runtime for the current canonical record and resolves the sidecar by record +reference. J3.3 replaces that compatibility seam with an exact +`RuntimeEntityKey` projection store. + +No renderer, UI, Silk.NET, ImGui, OpenAL, or App type entered Runtime. No +asynchronous queue or input-frame delay was added. + +## Automated acceptance + +At the production commit: + +- Runtime tests: 110 passed; +- App tests: 3,758 passed / 3 skipped; +- complete Release solution: 8,441 passed / 5 skipped; +- Release solution build: pass. + +Coverage includes active-incarnation uniqueness, exact old-generation +tombstones, local-ID wrap/reverse lookup, stale identity release, session epoch +replacement, accepted snapshot authority, separate delete/teardown edges, +resource registration rollback, reentrant clear/delete, GUID reuse, and source +guards that reject presentation/backend state on the canonical record. + +## Connected lifecycle acceptance + +Raw evidence: +`logs/connected-world-gate-20260725-200749/report.json`. + +Result: PASS on the exact production commit. + +- Capped process: login, Aerlinthe, Rynthid, Facility Hub, Holtburg after the + dungeon, and Aerlinthe revisit all completed. +- Fresh uncapped process: reconnect completed. +- Seven of seven checkpoints passed. +- Both processes exited gracefully with exit code zero. +- Every checkpoint reported zero render-shadow mismatches and zero pending + render deltas. +- No gate failure was recorded. +- The only warning was 25 expected world-edge landblock misses. + +This proves that moving identity, incarnation, tombstone, accepted-wire, and +local-ID ownership into Runtime preserved connected object creation, +same-location revisit, dungeon/outdoor replacement, packet routing, rendering, +and graceful teardown on the exact binary. + +## Exact rollback + +```text +git revert f46ddb5cdb1e145752bea49aeb1d62bfe71284d3 +``` + +J3.1 remains independently reversible with: + +```text +git revert f7442d13e9ae7d5b077ffecb1f8a10899ad46edd +``` + +When reverting both, revert J3.2 before J3.1. diff --git a/docs/research/2026-07-25-slice-j3-entity-ownership-inventory.md b/docs/research/2026-07-25-slice-j3-entity-ownership-inventory.md index e6887924..ba73e438 100644 --- a/docs/research/2026-07-25-slice-j3-entity-ownership-inventory.md +++ b/docs/research/2026-07-25-slice-j3-entity-ownership-inventory.md @@ -8,6 +8,31 @@ The accepted J2 binary passes 8,428 Release tests with five skips and the seven-checkpoint connected lifecycle/reconnect gate at `logs/connected-world-gate-20260725-193936/report.json`. +## J3.2 ownership checkpoint + +Commit `f46ddb5cdb1e145752bea49aeb1d62bfe71284d3` implements the first +canonical split: + +- `RuntimeEntityDirectory` owns the only active GUID map, exact-incarnation + tombstones, reverse local-ID map, session lifetime epoch, per-GUID operation + versions, accepted inbound snapshot owner, and parent-relation owner; +- `RuntimeEntityRecord` owns the presentation-free canonical snapshot, + `INSTANCE_TS`, authoritative cell/state/timestamp versions, object clock, + PhysicsBody/physics-host facts carried for J5, and Runtime-issued local ID; +- App's `LiveEntityRecord` is now a projection sidecar around that canonical + record; +- the temporary `ActiveRecordView` is dictionary-shaped only to preserve the + large synchronous App call surface during J3.2. It stores no GUID map and + resolves every lookup through `RuntimeEntityDirectory`; J3.3 deletes it; +- Runtime-only ownership/lifetime tests and App source guards protect the + boundary. + +The checkpoint passes 110 Runtime tests, 3,758 App tests with three skips, and +8,441 complete Release tests with five skips. Its exact-binary connected gate +also passes all seven checkpoints with graceful exits, zero render-shadow +mismatches, and zero pending deltas: +`logs/connected-world-gate-20260725-200749/report.json`. + At this baseline: - `LiveEntityRuntime.cs` is 2,866 lines and is referenced by roughly 100 App