docs(runtime): close J3.4 and plan J3.5

This commit is contained in:
Erik 2026-07-26 06:09:28 +02:00
parent 5ef8b5371d
commit d3e96ff912
13 changed files with 562 additions and 58 deletions

View file

@ -14,7 +14,7 @@ banner cannot silently override the current program state.
[`plans/2026-07-23-world-interaction-completion.md`](plans/2026-07-23-world-interaction-completion.md).
The eight-slice `GameWindow` decomposition and its connected visual matrix
are complete.
- **Current active engineering program:** Slices AI and J0J3.3 of
- **Current active engineering program:** Slices AI and J0J3.4 of
[`plans/2026-07-24-modern-runtime-architecture.md`](plans/2026-07-24-modern-runtime-architecture.md)
are complete. Production uses prepared world/collision packages, typed
residence, retained render-scene/delta submission, bounded frame owners, and
@ -22,8 +22,10 @@ banner cannot silently override the current program state.
Runtime owns canonical session/transport and the sole live-entity
GUID/incarnation/local-ID directory. App materialized projections,
presentation worksets, and spatial visibility carry exact
`RuntimeEntityKey`. J3.4 canonical object-table ownership is next in
[`plans/2026-07-25-modern-runtime-slice-j3-object-table.md`](plans/2026-07-25-modern-runtime-slice-j3-object-table.md).
`RuntimeEntityKey`. One `RuntimeEntityObjectLifetime` owns the exact
directory and live object table; App and routing borrow both. J3.5 ordered
canonical entity/object deltas and direct borrowed views are next in
[`plans/2026-07-26-modern-runtime-slice-j3-delta-stream.md`](plans/2026-07-26-modern-runtime-slice-j3-delta-stream.md).
- **Completed gates:** R6 locomotion/collision/projectile/teleport/radar and
the final two-client portal-out/materialization observer comparison (`#218`).
- **Separate visual verification:** the shared-alpha lifestone/particle result
@ -32,12 +34,11 @@ banner cannot silently override the current program state.
`#116` (two narrowed slide-response cases), and divergence rows TS-50/TS-51.
- **Active engineering track:** complete Slice J's coherent Runtime lifetime
groups, then build the approved Linux/headless multi-session host in Slice K.
J3.3's exact rollback is `git revert e937cc36` followed by
`git revert 420e5eea`.
J3.4's exact rollback is `git revert 5ef8b537`.
- **Divergence audit:** 178 active rows — IA 17, AD 37, AP 85, TS 34,
and UN 5 — plus the retained retired TS-37 history note.
- **Latest automated baseline:** Release build succeeds; 8,444 tests pass and
five are intentionally skipped. The exact J3.3 connected lifecycle/reconnect
- **Latest automated baseline:** Release build succeeds; 8,453 tests pass and
five are intentionally skipped. The exact J3.4 connected lifecycle/reconnect
gate completed two sessions and seven checkpoints with graceful zero-code
exits, zero failures, zero render-shadow mismatches, and zero pending deltas.

View file

@ -212,9 +212,10 @@ src/
Entities/
RuntimeEntityDirectory.cs -> sole GUID/incarnation/local-ID authority
RuntimeEntityRecord.cs -> presentation-free accepted entity state
RuntimeEntityObjectLifetime.cs -> one entity/object lifetime root
InboundPhysicsStateController.cs -> retail timestamp/snapshot authority
ParentAttachmentState.cs -> generation-exact parent relations
-> J3.1-J3.3 complete; J3.4 canonical object-table ownership next
-> J3.1-J3.4 complete; J3.5 ordered deltas/direct borrowed views next
-> may reference Core, Core.Net, Content, and Plugin.Abstractions only
-> must never reference App, UI, Silk.NET, OpenAL, Arch, or ImGui

View file

@ -470,14 +470,14 @@ useful ordering seam, but its ownership status is **partial**.
| Startup options | **Complete** | `RuntimeOptions` owns startup configuration (`eda936dc`). Remaining direct environment reads are legacy runtime diagnostics, not startup configuration. |
| Network session | **Complete Runtime ownership** | `RuntimeLiveSessionController` owns the sole `WorldSession` generation and resolve/create/Connect/selection/EnterWorld/Tick/stop/reconnect/disposal transaction. Runtime route owners preserve exact inbound/outbound ordering and retryable teardown. App supplies immutable options, graphical/domain callbacks, and one borrowed inertable UI command projection—no mirrored session or reset plan (`75930787`). |
| World environment | **Complete ownership** | `WorldEnvironmentController` solely owns WorldTime, the loaded DAT sky, current day group, Weather, server synchronization, AdminEnvirons bridging, and debug time/weather cycles. `GameWindow` keeps ABI-compatible readonly aliases to the same clock/weather instances and composes one render source plus the two live-session callbacks. TS-54/TS-55 register the remaining centered UI sound and full fog/ambient/radar behavior gaps. |
| Live identity/lifetime | **J3.3 complete** | `RuntimeEntityDirectory` owns the sole GUID/incarnation/local-ID identity, accepted snapshots/timestamps, parent state, operation versions, and tombstones. `LiveEntityProjectionStore` owns App graphical sidecars by exact `RuntimeEntityKey`; hydration, presentation components, `GpuWorldState` residence/visibility, and retryable teardown preserve that key without another GUID authority (`f46ddb5c`, `420e5eea`, `e937cc36`). |
| Live identity/lifetime | **J3.4 complete** | `RuntimeEntityObjectLifetime` owns the sole `RuntimeEntityDirectory` and live `ClientObjectTable`. The directory owns canonical GUID/incarnation/local-ID identity, accepted snapshots/timestamps, parent state, operation versions, and tombstones. `LiveEntityProjectionStore` owns App graphical sidecars by exact `RuntimeEntityKey`; hydration, presentation components, `GpuWorldState` residence/visibility, and retryable teardown preserve that key without another authority (`f46ddb5c`, `420e5eea`, `e937cc36`, `5ef8b537`). Authoritative delete removes retained object state; dormant projection pruning does not. |
| Inbound/object-frame order | **Complete App orchestration** | `UpdateFrameOrchestrator` owns the complete typed host phase graph; `RetailInboundEventDispatcher`, `RetailLiveFrameCoordinator`, `LiveObjectFrameController`, `LiveSpatialPresentationReconciler`, streaming/input/teleport/player-mode/camera owners preserve the accepted order. `GameWindow.OnUpdate` is one profiler-scoped handoff (`e91f3102`). |
| World reveal | **Complete** | `WorldRevealCoordinator` owns login/portal readiness, generation quiescence, and the exact streaming destination reservation. Login auto-entry and portal completion close only their active generation; stale completion cannot clear its replacement. Delayed portals retain the authored tunnel and centered retail wait notice rather than force-revealing incomplete content. Quiesced destination projections may become spatially resident for renderer preparation while all availability-gated gameplay consumers stay closed. |
| Retained gameplay UI | **Mostly complete feature ownership** | `RetailUiRuntime` and focused panel/controllers own layout and behavior. `GameWindow.OnLoad` still performs substantial service composition, which is allowed until the final composition cleanup. |
| Selection/interaction | **Complete** | `WorldSelectionQuery` owns read-only picking/classification/range queries; `SelectionInteractionController` owns selection intent, Use/PickUp transport, exact-incarnation queues, and auto-walk deferral; `ItemInteractionController` owns ItemHolder policy plus the shared retail inventory-request transaction. `GameWindow` retains construction and narrow lifecycle forwarding only. |
| Landblock presentation | **Complete** | `LandblockBuildFactory` owns the captured-origin DAT transaction; concrete render/physics/DAT-static publishers and `LandblockPresentationPipeline` own typed-meter publication and exact retryable retirement. `StreamingController` owns stable destination/control/unload/Near/Far queues and destination reservation. CPU mesh-cache restaging requires an exact live owner. `StreamingOriginRecenterCoordinator` serializes old-window retirement with teleport/session origin lifetimes. `GameWindow` retains construction and one pipeline field only (`c79d0a49`, closeout `4a205a3e`; Slice E closeout `91e82c3c`). |
| Render-frame orchestration | **Complete** | `RenderFrameOrchestrator` owns the GPU-flight, resource, world/PView/shared-alpha, private-presentation, diagnostics, screenshot, and recovery graph. `GameWindow.OnRender` takes one logical window-size snapshot and performs one immutable handoff (`9d7df1bf`). |
| Unified `GameEntity` | **Slice J active** | Canonical identity is now in Runtime and exact graphical sidecars are in App. J3.4 next moves `ClientObjectTable`; later J4J7 move coherent gameplay lifetime groups before one Runtime composition root. |
| Unified `GameEntity` | **Slice J active** | Canonical identity and retained-object lifetime now share one Runtime owner while exact graphical sidecars stay in App. J3.5 next replaces App-reconstructed entity/inventory views and events with one committed Runtime delta stream; later J4J7 move coherent gameplay lifetime groups before one Runtime composition root. |
### 4.3 Revised extraction sequence

View file

@ -1693,8 +1693,14 @@ port in any phase — no separate listing here.
> exact `RuntimeEntityKey`; the compatibility GUID view is deleted. Its 3,761
> App tests / 3 skips, 8,444-test / 5-skip complete Release suite, and exact-
> binary seven-checkpoint gate pass with two graceful exits, zero failures,
> zero render-shadow mismatches, and zero pending deltas. J3.4 canonical object-
> table ownership is next.
> zero render-shadow mismatches, and zero pending deltas. J3.4 is complete at
> `5ef8b537`: one Runtime entity/object lifetime root owns the sole canonical
> directory and live `ClientObjectTable`; App and routing borrow both. Its 118
> Runtime tests, 3,762 App tests / 3 skips, 8,453-test / 5-skip complete
> Release suite, and exact-binary seven-checkpoint gate pass with graceful
> exits, zero failures, zero render-shadow mismatches, and zero pending deltas.
> J3.5 ordered canonical entity/object deltas and direct borrowed views are
> next.
> The historical exact cutover
> rollback remains
> `git revert ef1d263337997bb030eadb7b8e71d73dc659907a`. Slice H is complete:

View file

@ -169,7 +169,14 @@ residency is `0/0/0` at every stable checkpoint and teardown converges. Slice I
is deleted. Its 3,761 App tests / 3 skips, 8,444 full Release tests / 5 skips,
and exact-binary seven-checkpoint connected gate pass with two graceful
exits, zero failures, zero render-shadow mismatches, and zero pending deltas.
J3.4 canonical `ClientObjectTable` ownership is next under
J3.4 is complete at `5ef8b537`: one presentation-free
`RuntimeEntityObjectLifetime` owns the sole entity directory and live
`ClientObjectTable`; App and routing borrow the exact instances. Its 118
Runtime tests, 3,762 App tests / 3 skips, 8,453 full Release tests / 5 skips,
and exact-binary seven-checkpoint connected gate pass with graceful exits,
zero failures, zero render-shadow mismatches, and zero pending deltas.
J3.5 ordered canonical entity/object deltas and direct borrowed views are
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).
@ -179,6 +186,8 @@ 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).
Slice-J3.3 closeout evidence is
[`../research/2026-07-25-slice-j3-3-exact-projection-store.md`](../research/2026-07-25-slice-j3-3-exact-projection-store.md).
Slice-J3.4 closeout evidence is
[`../research/2026-07-26-slice-j3-4-canonical-object-lifetime.md`](../research/2026-07-26-slice-j3-4-canonical-object-lifetime.md).
The historical exact G4 visual rollback remains
`git revert ef1d263337997bb030eadb7b8e71d73dc659907a`.

View file

@ -2,14 +2,14 @@
**Date:** 2026-07-24
**Status:** Slices AI and J0J3.3 are complete. Flat-authoritative collision, zero-
**Status:** Slices AI and J0J3.4 are complete. Flat-authoritative collision, zero-
allocation resolve scratch, parsed-graph removal, connected correctness/
lifetime acceptance, and Slice-I closeout landed 2026-07-25. Slices FL were
explicitly approved 2026-07-24. Slice J0J1 established the enforced Runtime
boundary and borrowed contract seam; J2 moved canonical session/transport
lifetime and ordered inbound routing; J3.1J3.3 moved canonical entity identity
to Runtime and exact graphical projection identity to App. J3.4 is the active
execution point.
lifetime and ordered inbound routing; J3.1J3.4 moved canonical entity identity
and object-table lifetime to Runtime and exact graphical projection identity
to App. J3.5 is the active execution point.
**Scope:** Reconcile and sequence the existing Modern Pipeline (`MP`) and
Linux/headless (`LH`) tracks using the 2026-07-24 connected performance audit.
@ -1250,11 +1250,13 @@ gameplay before removing every production parsed collision graph. Slice I7
passes 8,413 Release tests / 5 skips plus both exact-binary connected routes;
every stable checkpoint reports zero retained parsed collision graphs. J1 is
complete with borrowed contracts, and J2 owns canonical session/transport
lifetime plus ordered inbound routing in Runtime. J3.1J3.3 are complete:
lifetime plus ordered inbound routing in Runtime. J3.1J3.4 are complete:
Runtime owns the only entity GUID/incarnation/local-ID directory, and App's
materialized sidecars plus spatial/presentation worksets carry exact
`RuntimeEntityKey`. J3.4 canonical `ClientObjectTable` ownership is the current
execution point.
`RuntimeEntityKey`. One `RuntimeEntityObjectLifetime` also owns the exact live
`ClientObjectTable`; App is a synchronous borrower. J3.5's ordered canonical
entity/object delta stream and direct borrowed views are the current execution
point.
Evidence:
[`../research/2026-07-25-slice-g5-production-profile.md`](../research/2026-07-25-slice-g5-production-profile.md)
and
@ -1284,7 +1286,7 @@ honest metrics + committed baselines (A — exit criteria block C)
-> delta GPU submission (G)
-> residual frame cleanup (H-a, H-b, H-c)
-> flat collision assets (I — COMPLETE)
-> presentation-independent runtime (J — CURRENT at J3.4)
-> presentation-independent runtime (J — CURRENT at J3.5)
-> Linux/headless/multi-session (K)
-> evidence-gated GPU jobs (L)
```

View file

@ -1,7 +1,7 @@
# Modern runtime Slice J — presentation-independent runtime
**Status:** J0J2 COMPLETE; J3.1J3.3 COMPLETE; J3.4 canonical object-table
ownership is next
**Status:** J0J2 COMPLETE; J3.1J3.4 COMPLETE; J3.5 ordered canonical
entity/object deltas and borrowed views are next
**Parent:** `2026-07-24-modern-runtime-architecture.md`, Slice J
**Authorization:** the user approved Slices FL, including the otherwise-frozen
Slice J gameplay-owner moves, on 2026-07-24
@ -183,14 +183,17 @@ git revert 75930787741db40a83eab8663e4464dce8d687ba
**Detailed execution plan:**
[`2026-07-25-modern-runtime-slice-j3.md`](2026-07-25-modern-runtime-slice-j3.md).
**Current checkpoint:** J3.1J3.3 are complete. Runtime owns accepted entity
**Current checkpoint:** J3.1J3.4 are complete. Runtime owns accepted entity
wire state and the only canonical identity/incarnation/local-ID directory.
App's `LiveEntityProjectionStore` and every materialized presentation/spatial
workset are keyed by exact `RuntimeEntityKey`; the temporary GUID-shaped
compatibility view is deleted. The final J3.3 binary `e937cc36` passes 8,444
Release tests / 5 skips and the exact seven-checkpoint connected gate at
`logs/connected-world-gate-20260725-221008/report.json`. J3.4 now moves the
existing `ClientObjectTable` under the Runtime entity/object lifetime root.
compatibility view is deleted. `RuntimeEntityObjectLifetime` now owns the
exact entity directory and live `ClientObjectTable`; App, routing, interaction,
and UI borrow both. The J3.4 binary `5ef8b537` passes 8,453 Release tests / 5
skips and the exact seven-checkpoint connected gate at
`logs/connected-world-gate-20260726-055713/report.json`. J3.5 now publishes
one committed Runtime entity/object delta stream and replaces App-reconstructed
entity/inventory views and events.
- Strip renderer, particle, Wb, and streaming components from the canonical
record into an App projection store keyed only by local identity/incarnation.

View file

@ -1,9 +1,11 @@
# Modern runtime J3.4 — canonical object-table ownership
**Status:** READY
**Status:** COMPLETE
**Parent:** `2026-07-25-modern-runtime-slice-j3.md`
**Required production base:** `e937cc36df39cf6ea1eaba2f9c0243d1929da702`
**Prior closeout:** `docs/research/2026-07-25-slice-j3-3-exact-projection-store.md`
**Production commit:** `5ef8b5371d8990f0380acd939e71cd711289d429`
**Closeout:** `docs/research/2026-07-26-slice-j3-4-canonical-object-lifetime.md`
## Objective
@ -222,8 +224,39 @@ exposes an inventory, paperdoll, selection, or interaction symptom.
## Rollback
Record the exact J3.4 production commit here before its connected gate. J3.3
remains independently reversible; do not use its rollback for a J3.4 failure.
The exact J3.4 rollback is:
```text
git revert 5ef8b5371d8990f0380acd939e71cd711289d429
```
J3.3 remains independently reversible; do not use its rollback for a J3.4
failure.
## Result
`RuntimeEntityObjectLifetime` now constructs and owns the one
`RuntimeEntityDirectory` and one live `ClientObjectTable`. `GameWindow`,
session routing, retained UI, interaction, and the graphical projection host
borrow those exact instances.
Accepted CreateObject mutation revalidates the exact canonical record and
`CreateIntegrationVersion` before, during, and after synchronous object-table
callbacks. Authoritative DeleteObject acceptance uses an exact, single-use
Runtime token: the active identity is retired first and retained-object
removal then commits before App resource teardown. Dormant/offscreen pruning
does not remove retained object information.
Final gates:
- Runtime: 118 passed;
- App: 3,762 passed / 3 skipped;
- complete Release solution: 8,453 passed / 5 skipped;
- exact-binary connected lifecycle/reconnect:
`logs/connected-world-gate-20260726-055713/report.json`;
- two sessions, seven checkpoints, graceful zero-code exits, zero failures,
zero render-shadow mismatches, zero pending deltas, and zero pending live
teardown/publication/retirement work.
## Final J3 goal

View file

@ -1,6 +1,6 @@
# Modern runtime Slice J3 — canonical identity, properties, and object table
**Status:** ACTIVE
**Status:** ACTIVE — J3.1J3.4 COMPLETE; J3.5 NEXT
**Parent:** `2026-07-25-modern-runtime-slice-j.md`, J3
**Production base:** `9496c01b`
**J2 production commit:** `75930787741db40a83eab8663e4464dce8d687ba`
@ -13,20 +13,22 @@
| 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 | complete | `420e5eea70fd2c29cf9c8614e6298a1f84d64045` + `e937cc36df39cf6ea1eaba2f9c0243d1929da702`; 8,444 Release tests / 5 skips and `logs/connected-world-gate-20260725-221008/report.json` pass |
| J3.4 canonical object-table ownership | next | [`2026-07-25-modern-runtime-slice-j3-object-table.md`](2026-07-25-modern-runtime-slice-j3-object-table.md): move the existing `ClientObjectTable` into the Runtime entity/object lifetime group while App remains a synchronous borrower |
| J3.4 canonical object-table ownership | complete | `5ef8b5371d8990f0380acd939e71cd711289d429`; 118 Runtime tests, 3,762 App tests / 3 skips, 8,453 complete Release tests / 5 skips, and `logs/connected-world-gate-20260726-055713/report.json` pass |
| J3.5 ordered deltas and borrowed views | next | [`2026-07-26-modern-runtime-slice-j3-delta-stream.md`](2026-07-26-modern-runtime-slice-j3-delta-stream.md): one committed Runtime entity/object stream and direct borrowed views for graphical and no-window hosts |
J3.3 passes the Release solution build, 3,761 App tests with three skips, and
8,444 complete tests with five expected skips. Its final exact-binary
seven-checkpoint connected lifecycle/reconnect route also passes with graceful
exits, zero render-shadow mismatches, and zero pending deltas. Runtime is now
the sole GUID/incarnation/local-ID authority; every materialized App sidecar,
presentation workset, and live spatial visibility edge uses the exact
`RuntimeEntityKey`. It adds no frame queue, backend dependency, allocation-order
change, or gameplay behavior change. The exact rollback for J3.3 is:
J3.4 passes the Release solution build, 118 Runtime tests, 3,762 App tests with
three skips, and 8,453 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. Runtime
now owns one entity/object lifetime root containing both the sole
GUID/incarnation/local-ID authority and the sole live `ClientObjectTable`.
Graphical presentation and UI borrow those exact instances. Authoritative
delete removes retained object information; dormant/offscreen pruning does
not. No frame queue, backend dependency, allocation-order change, or gameplay
behavior change was added. The exact rollback for J3.4 is:
```text
git revert e937cc36df39cf6ea1eaba2f9c0243d1929da702
git revert 420e5eea70fd2c29cf9c8614e6298a1f84d64045
git revert 5ef8b5371d8990f0380acd939e71cd711289d429
```
## 1. Objective
@ -222,6 +224,9 @@ move rollback, stack response, GUID reuse, and session-clear traces match.
### J3.5 — ordered deltas and borrowed views
**Detailed execution plan:**
[`2026-07-26-modern-runtime-slice-j3-delta-stream.md`](2026-07-26-modern-runtime-slice-j3-delta-stream.md).
- Publish one monotonic per-session Runtime entity/object delta stream.
- Make J1 `IGameRuntimeView.Entities` and inventory snapshots read the Runtime
owners directly rather than App adapters.
@ -294,12 +299,13 @@ failure; record and revert only the exact failing J3 commit.
J3 sub-slices are independently reversible:
```text
git revert 5ef8b5371d8990f0380acd939e71cd711289d429
git revert e937cc36df39cf6ea1eaba2f9c0243d1929da702
git revert 420e5eea70fd2c29cf9c8614e6298a1f84d64045
git revert f46ddb5cdb1e145752bea49aeb1d62bfe71284d3
git revert f7442d13e9ae7d5b077ffecb1f8a10899ad46edd
```
Revert J3.3's exact-spatial correction before its main projection-store
commit. Revert J3.3 before J3.2, and J3.2 before J3.1, when rolling back more
than one sub-slice.
Revert J3.4 before J3.3. Revert J3.3's exact-spatial correction before its
main projection-store commit. Revert J3.3 before J3.2, and J3.2 before J3.1,
when rolling back more than one sub-slice.

View file

@ -0,0 +1,315 @@
# Modern runtime J3.5 — committed entity/object deltas and borrowed views
**Status:** READY
**Parent:** `2026-07-25-modern-runtime-slice-j3.md`
**Required production base:** `5ef8b5371d8990f0380acd939e71cd711289d429`
**Prior closeout:** `docs/research/2026-07-26-slice-j3-4-canonical-object-lifetime.md`
## Objective
Publish one synchronous, monotonic, generation-stamped stream from the
canonical Runtime entity/object lifetime and make both graphical and
no-window/direct hosts observe those same committed facts.
`IGameRuntimeView.Entities` and `IGameRuntimeView.Inventory` must read the
Runtime-owned `RuntimeEntityDirectory` and `ClientObjectTable` directly.
`CurrentGameRuntimeEventAdapter` must stop reconstructing entity changes from
App projection visibility and inventory changes from an App-owned event seam.
This slice adds no later-frame queue, copied world, inventory mirror, input
delay, renderer dependency, or gameplay behavior change.
## Current seam at the production base
- `RuntimeEntityObjectLifetime` owns the exact directory and object table.
- `CurrentGameRuntimeViewAdapter.EntityView` still reads App
`LiveEntityRuntime`, so a direct host cannot enumerate canonical entities
without constructing the graphical projection host.
- Its inventory view reads the right table but asks `LiveEntityRuntime` to
recover incarnation metadata.
- `CurrentGameRuntimeEventAdapter` owns a separate sequencer and reconstructs:
- entity events only from `ProjectionVisibilityChanged`; and
- inventory events by subscribing directly to object-table callbacks.
- Registered, refreshed, parented, picked-up, state-updated, cellless, and
authoritative-delete canonical edges therefore do not have one complete
Runtime stream.
- Runtime local IDs are still claimed at App materialization rather than at
canonical registration, even though direct and graphical hosts require one
stable cross-host identity.
The J1 adapter was intentionally temporary. J3.5 deletes these superseded
entity/object adapter responsibilities.
## Fixed contracts
### One canonical stream owner
Add one instance-scoped stream under `AcDream.Runtime.Entities`, owned by
`RuntimeEntityObjectLifetime`.
It exposes a narrow subscription equivalent to:
```csharp
public interface IRuntimeEntityObjectObserver
{
void OnEntity(in RuntimeEntityDelta delta);
void OnInventory(in RuntimeInventoryDelta delta);
}
public interface IRuntimeEntityObjectEventSource
{
IDisposable Subscribe(IRuntimeEntityObjectObserver observer);
}
```
Entity and inventory deltas share one sequence owner. There is no entity queue
plus inventory queue and no App repeater. Every stamp carries the exact
`RuntimeGenerationToken` and current Runtime frame number.
Sequence rules:
- sequence starts at one for each live session generation;
- entity and inventory commits consume the same monotonic sequence;
- rejected/stale packets consume no sequence;
- callback reentrancy appends later sequence values in actual commit order;
- session reset publishes its committed withdrawals/removals/clear edge, then
the retired generation is sealed;
- a replacement generation cannot publish through the retired stream context.
### Canonical entity identity and snapshot
Runtime claims a local ID when it creates the canonical active record, before
any graphical projection callback. The ID remains stable for that incarnation
until canonical teardown; graphical hydration failure must not release a
still-active Runtime identity.
The public entity view is canonical and presentation-free:
- server GUID;
- Runtime local ID;
- exact `INSTANCE_TS` incarnation;
- full cell;
- final physics state;
- accepted position/snapshot facts.
Graphical hydration, loaded/pending visibility, and render-resource state do
not become gameplay truth. If retained diagnostic contracts still need
attached-host counts, those are supplied by a separate projection
acknowledgement/diagnostic seam and are not mixed into canonical entity
identity.
### Commit ordering
An entity delta is created only after the exact Runtime record mutation
commits. The graphical projection host receives that same immutable committed
delta synchronously and returns an exact acknowledgement; public observers
then observe the same sequence. There is no second conversion step and no
frame boundary.
Required entity edges:
- `Registered` after active-record/local-ID commit;
- `Updated` after same-incarnation CreateObject, ObjDesc, vector, movement,
accepted position, parent, or equivalent canonical refresh;
- `Rebucketed` after a canonical full-cell change;
- `Hidden` after a committed Hidden state transition;
- `Withdrawn` after pickup/accepted parent/cellless exit-world while the
incarnation remains logically alive;
- `Deleted` after authoritative identity retirement and retained-object
removal acceptance;
- generation replacement orders old `Deleted`/withdrawal before new
`Registered`.
Loaded-to-pending renderer visibility is not a canonical withdrawal and emits
no gameplay entity delta.
Required inventory edges remain the exact object-table callback order:
- `Added`;
- `Updated`;
- `Moved`;
- `Removed` with exact removed generation;
- `Cleared`.
Unknown-object move notices retain the object ID and placement facts rather
than disappearing because no `ClientObject` instance exists.
### Borrowed views
The Runtime lifetime group exposes concrete allocation-free
`IRuntimeEntityView` and `IRuntimeInventoryView` implementations:
- entity enumeration walks `RuntimeEntityDirectory.ActiveRecords`;
- entity lookup resolves directly through the directory;
- inventory enumeration/lookup walks `ClientObjectTable`;
- inventory incarnation comes from the exact Runtime directory or the
object's retained generation, never an App sidecar;
- visitors receive value snapshots and may not retain mutable owners.
`CurrentGameRuntimeViewAdapter` borrows those view objects. It retains only
the still-unmoved J4+ chat/movement/portal/lifecycle composition.
## Execution
### 1. Pin the pre-cutover normalized oracle
Add a focused deterministic fixture covering:
- create, same-incarnation refresh, and generation replacement;
- ObjDesc/property and accepted state/vector/movement/position updates;
- parent, pickup, cellless withdrawal, and re-entry;
- object add/update/move/remove/clear;
- optimistic move, confirm, rejection rollback, and container replacement;
- authoritative delete and delete/recreate with the same GUID;
- reset and next-generation reuse;
- callback reentrancy.
Record both the canonical final state and exact event order. Preserve existing
retail-facing object-table callback order; add missing canonical entity edges
without treating projection visibility as gameplay truth.
### 2. Add the Runtime entity/object stream
- Add the stream owner and narrow observer/source contracts in Runtime.
- Give it one per-generation sequencer and explicit session-generation/frame
context.
- Use copy-on-write subscriber storage so steady dispatch allocates no observer
list and unsubscribe is exact.
- Reject duplicate subscriptions, cross-owner subscriptions, stale
generations, and dispatch after disposal.
- Keep callback execution on the existing update/network-drain thread.
- Revalidate generation/incarnation/operation version after any callback that
can re-enter Runtime.
### 3. Move identity allocation to canonical registration
- Claim the Runtime local ID in the same transaction that installs an active
canonical record.
- Preserve current allocation range and wrap/exhaustion behavior.
- Stop releasing the ID when only App materialization rolls back.
- Release it only when the canonical incarnation reaches terminal teardown.
- Prove pending/unhydrated and direct-host entities still have exact keys.
- Prove GUID reuse gets a new key and stale keys never resolve.
### 4. Publish canonical entity commits
- Centralize accepted canonical mutations behind
`RuntimeEntityObjectLifetime` transaction methods.
- Publish only after state commits and only while the exact operation remains
current.
- Carry the complete immutable accepted snapshot required by a graphical or
direct projection host.
- Replace App's projection-visibility-derived entity event reconstruction.
- Preserve synchronous graphical projection application and exact retryable
teardown acknowledgements.
- Do not emit on renderer rebucket, loaded/pending visibility, hydration
retries, or other presentation-only changes.
### 5. Publish exact object-table commits
- Bind the stream to its owned `ClientObjectTable`.
- Convert callbacks to immutable `RuntimeInventoryItemSnapshot` values with
generation metadata resolved by Runtime.
- Preserve add/update/move/remove/clear order and callback reentrancy.
- Keep optimistic movement and rollback synchronous.
- Ensure an authoritative delete produces the exact entity/object ordering
pinned by J3.4.
- Do not add a second retained inventory collection.
### 6. Replace App entity/object view and event adapters
- Make `CurrentGameRuntimeViewAdapter.Entities` and `.Inventory` return the
Runtime group's borrowed views.
- Remove its `LiveEntityRuntime` dependency for canonical entity/inventory
reads.
- Make `CurrentGameRuntimeEventAdapter` forward the Runtime stream directly.
- Remove its `ProjectionVisibilityChanged` and object-table subscriptions.
- Retain command, lifecycle, chat, movement, and portal adapter work only until
their scheduled J4J6 owner moves.
- Add source guards preventing a new App entity/object mirror, sequencer, or
owner-event reconstruction.
### 7. Direct/graphical parity and teardown
- Build one no-App Runtime fixture and one graphical-host fixture over the
same input script.
- Compare normalized generation, sequence, identity, cell/state, properties,
placement, and terminal edges exactly.
- Verify subscriber removal and Runtime disposal leave zero observers.
- Verify reset seals the old generation and a new session begins at sequence
one without stale delivery.
- Verify graphical callbacks remain same-thread and press-time object reads
remain immediate.
## Adversarial cases
- Observer adds/removes an observer during dispatch.
- Observer creates, deletes, or replaces the same GUID reentrantly.
- Observer clears the session during create or object-table callbacks.
- Graphical projection callback throws after canonical commit.
- Same-incarnation CreateObject arrives while a prior projection teardown is
retained.
- Authoritative delete races a dormant exact-incarnation record.
- Equal, stale, and wrapped timestamps.
- Local-ID wrap and namespace exhaustion.
- Graphical hydration fails before and after resource registration.
- Unknown-object move and removal.
- Container replacement mutates contents from inside an event callback.
- Multiple Runtime groups use identical GUIDs and session-generation values.
- Subscription disposal is replayed and Runtime disposal occurs during a
callback.
## Mandatory gates
Run in this order:
1. Runtime stream, borrowed-view, sequence, reentrancy, and identity tests.
2. Core `ClientObjectTable*` and `ObjectTableWiring*` tests.
3. Focused App Runtime-adapter, hydration, update, rebucket, deletion, reset,
inventory, paperdoll, selection, interaction, and cooldown tests.
4. Direct-host versus graphical-host normalized parity fixture.
5. All Runtime tests.
6. All App tests.
7. `dotnet build AcDream.slnx -c Release`.
8. `dotnet test AcDream.slnx -c Release --no-build`.
9. Exact-binary connected lifecycle/reconnect gate.
10. At every connected checkpoint: zero render-shadow mismatches, zero pending
deltas, graceful process exit, and exact canonical/projection teardown
convergence.
A user visual pause is required only if an automated or connected gate exposes
a visible inventory, selection, radar, paperdoll, or world-object symptom.
## Acceptance
- Runtime owns one per-session ordered entity/object stream.
- Entity and inventory deltas share one generation/sequence order.
- Runtime views read the directory and object table directly.
- Every active canonical entity has a Runtime key before App projection.
- App reconstructs neither entity nor inventory events.
- Projection visibility is not emitted as canonical gameplay withdrawal.
- Graphical and no-window normalized traces are identical.
- No copied collection, queue, extra input frame, or backend dependency exists.
- Reentrant callbacks cannot resurrect or mutate a superseded incarnation.
- Reset/disposal leaves zero observers, queued deltas, and retained stream
state.
- Complete Release and exact connected gates pass on one committed binary.
## Rollback
Record the exact J3.5 production commit here before its connected gate. J3.4
remains independently reversible:
```text
git revert 5ef8b5371d8990f0380acd939e71cd711289d429
```
Do not revert J3.4 as a shortcut for a J3.5 failure.
## Next boundary
J3.6 failure-injects the complete canonical entity/object lifecycle and proves
zero records, tombstones, projections, resources, container entries, parent
candidates, subscriptions, or pending deltas after reset and disposal. That
closeout is required before J4 moves chat, inventory transactions, vitals,
enchantments, spells/components, cooldowns, and ViewModel-facing revisions.

View file

@ -0,0 +1,112 @@
# Slice J3.4 closeout — canonical entity/object lifetime
## Outcome
J3.4 is complete at:
```text
5ef8b5371d8990f0380acd939e71cd711289d429
```
`AcDream.Runtime.Entities.RuntimeEntityObjectLifetime` is now the one
presentation-free owner of the live session's:
- canonical `RuntimeEntityDirectory`; and
- canonical `ClientObjectTable`.
The graphical host, session router, retained UI, inventory interaction,
paperdoll, magic, cooldown, and diagnostic owners borrow those exact
instances. `GameWindow` no longer allocates or publicly owns a live object
table, and `LiveEntityRuntime` no longer allocates its own entity directory.
## Transaction boundary
CreateObject and DeleteObject retain the established retail-facing synchronous
order.
For an accepted create:
1. Runtime accepts or refreshes the exact canonical incarnation.
2. The Runtime lifetime group applies the retained-object mutation.
3. The group revalidates the exact canonical record and
`CreateIntegrationVersion` before, during, and after callbacks.
4. App continues graphical hydration only while the same acceptance remains
current.
For an authoritative delete:
1. Runtime issues one exact `RuntimeEntityDeleteAcceptance`.
2. The active canonical identity is retired.
3. The acceptance commits retained-object removal exactly once.
4. App completes the retryable graphical/resource teardown suffix.
The acceptance rejects replay and use by another Runtime instance.
## Important lifecycle distinction
An authoritative server delete and an offscreen/dormant prune are not the same
operation.
- Authoritative DeleteObject removes the retained `ClientObject`.
- Dormant liveness pruning withdraws the graphical/live projection but keeps
retained object information.
A focused regression test exposed an early implementation that deleted object
information during every unregister. The final implementation carries an
explicit `removeRetainedObject` decision and keeps freshness authority in
Runtime. This preserves existing behavior without a timing guard or retry
workaround.
## Architecture checks
- Runtime can construct the lifetime group without App, UI, Silk, OpenAL,
Arch, or ImGui.
- Two Runtime groups can own conflicting GUIDs and objects independently.
- Production App source guards reject `new ClientObjectTable()` and
`new RuntimeEntityDirectory()`.
- Studio/sample-data tables remain independent fixture owners.
- There is no copied inventory model, asynchronous seam, extra input frame, or
backend dependency in Runtime.
- Session reset clears the Runtime-owned object table before graphical
projection teardown, matching the established retryable manifest order.
## Verification
Final automated results:
- Runtime tests: 118 passed;
- Core `ClientObjectTable` focus: 86 passed;
- Core `ObjectTableWiring` focus: 6 passed;
- inventory/item/paperdoll/magic/cooldown/runtime-adapter focus: 273 passed;
- hydration/runtime/reset/composition focus: 172 passed;
- App tests: 3,762 passed / 3 skipped;
- complete Release solution: 8,453 passed / 5 skipped;
- Release build: pass, with only the 17 pre-existing Core warnings.
Exact-binary connected evidence:
```text
logs/connected-world-gate-20260726-055713/report.json
```
The route used two sessions and seven checkpoints. Both processes exited
gracefully with code zero. It reported zero failures, zero render-scene shadow
mismatches, zero pending deltas, zero pending live teardown, and zero pending
retirement/publication/upload work. The only warning was the route's expected
25 world-edge landblock misses.
## Rollback
```text
git revert 5ef8b5371d8990f0380acd939e71cd711289d429
```
Do not revert J3.3 as a shortcut for a J3.4 failure.
## Next boundary
J3.5 publishes one monotonic, per-session entity/object delta stream from
committed Runtime state. Both direct/no-window and graphical hosts must observe
the same sequence and borrow the same views. It must replace the current App
event reconstruction without adding a second queue, copied world, or frame of
latency.