docs(runtime): close exact world host ownership

This commit is contained in:
Erik 2026-07-26 18:41:24 +02:00
parent 18d17d8bb1
commit 75f9510e10
13 changed files with 240 additions and 43 deletions

6
.gitignore vendored
View file

@ -57,6 +57,12 @@ __pycache__/
# Per-session scratch (Claude commit message drafts, ad-hoc temp files)
tmp/
# Disposable dotnet test/build output redirected by local validation runs
.test-out/
# Connected-gate, benchmark, and visual-capture artifacts are machine-local
logs/
# Git worktrees for isolated feature work
.worktrees/

View file

@ -335,8 +335,13 @@ history, both accepted F751/Position orders, the exact destination, and
generation/sequence/cell placement and materialization validation. App's
transit coordinator and destination mirror are deleted. Its 360 Runtime tests,
3,710 App tests / 3 skips, 8,631 complete Release tests / 5 skips, and
exact-binary lifecycle/reconnect route pass. J6.4 graphical-host
acknowledgement and owner cleanup is active.
exact-binary lifecycle/reconnect route pass. J6.4 landed at `18d17d8b`:
Runtime owns the exact generation/cell-scoped host acknowledgement suffix and
App owns only retryable graphical resource receipts. Its 365 Runtime tests,
3,716 App tests / 3 skips, 8,642 complete Release tests / 5 skips, and
exact-binary lifecycle/reconnect route pass with every environment,
transit, and pending-host ledger at zero. J6 is complete; J7 composition-root
convergence is active.
J0's rollback is
`git revert b632672e5ccabfb44c551e08f1c411ab2669c44a`.
J1's rollback is
@ -385,6 +390,8 @@ J6.2's rollback is, newest first,
`git revert a6860d5563ae845a2cbb916abacf2b4aee515cdb`.
J6.3's rollback is
`git revert 6a063a27d4c805cd166d5a487afc290c34c400fd`.
J6.4's rollback is
`git revert 18d17d8bb17ed9ff3ed01da8273e2948abe6398b`.
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
@ -409,7 +416,8 @@ closeout is
`docs/research/2026-07-26-slice-j5-6-projectile-ownership.md`; J5.7 closeout is
`docs/research/2026-07-26-slice-j5-7-simulation-ownership-closeout.md`; J6.3
closeout is
`docs/research/2026-07-26-slice-j6-3-teleport-correlation.md`. The exact G4
`docs/research/2026-07-26-slice-j6-3-teleport-correlation.md`; J6 closeout is
`docs/research/2026-07-26-slice-j6-4-host-acknowledgement.md`. The exact G4
visual rollback
is `git revert ef1d263337997bb030eadb7b8e71d73dc659907a`; do not revert G3 or
the portal-warmup corrections. Evidence:
@ -449,7 +457,7 @@ uncapped Release presentation is smooth, while physics, collision, and wire
truth remain correct.
See `docs/plans/2026-07-22-gamewindow-slice-8-composition-lifecycle.md` and
`docs/architecture/code-structure.md`. **Carried:** #153, #116, remaining
R6 ownership cleanup, TS-50/TS-51/TS-53, Modern Runtime Slice J+, and #225's
R6 ownership cleanup, TS-50/TS-51/TS-53, Modern Runtime Slice J7+, and #225's
lifestone/particle alpha visual gate.
Start structural work at `memory/project_gamewindow_decomposition.md` and

View file

@ -333,8 +333,13 @@ history, both accepted F751/Position orders, the exact destination, and
generation/sequence/cell placement and materialization validation. App's
transit coordinator and destination mirror are deleted. Its 360 Runtime tests,
3,710 App tests / 3 skips, 8,631 complete Release tests / 5 skips, and
exact-binary lifecycle/reconnect route pass. J6.4 graphical-host
acknowledgement and owner cleanup is active.
exact-binary lifecycle/reconnect route pass. J6.4 landed at `18d17d8b`:
Runtime owns the exact generation/cell-scoped host acknowledgement suffix and
App owns only retryable graphical resource receipts. Its 365 Runtime tests,
3,716 App tests / 3 skips, 8,642 complete Release tests / 5 skips, and
exact-binary lifecycle/reconnect route pass with every environment,
transit, and pending-host ledger at zero. J6 is complete; J7 composition-root
convergence is active.
J0's rollback is
`git revert b632672e5ccabfb44c551e08f1c411ab2669c44a`.
J1's rollback is
@ -383,6 +388,8 @@ J6.2's rollback is, newest first,
`git revert a6860d5563ae845a2cbb916abacf2b4aee515cdb`.
J6.3's rollback is
`git revert 6a063a27d4c805cd166d5a487afc290c34c400fd`.
J6.4's rollback is
`git revert 18d17d8bb17ed9ff3ed01da8273e2948abe6398b`.
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
@ -407,7 +414,8 @@ closeout is
`docs/research/2026-07-26-slice-j5-6-projectile-ownership.md`; J5.7 closeout is
`docs/research/2026-07-26-slice-j5-7-simulation-ownership-closeout.md`; J6.3
closeout is
`docs/research/2026-07-26-slice-j6-3-teleport-correlation.md`. The exact G4
`docs/research/2026-07-26-slice-j6-3-teleport-correlation.md`; J6 closeout is
`docs/research/2026-07-26-slice-j6-4-host-acknowledgement.md`. The exact G4
visual rollback
is `git revert ef1d263337997bb030eadb7b8e71d73dc659907a`; do not revert G3 or
the portal-warmup corrections. Evidence:
@ -447,7 +455,7 @@ uncapped Release presentation is smooth, while physics, collision, and wire
truth remain correct.
See `docs/plans/2026-07-22-gamewindow-slice-8-composition-lifecycle.md` and
`docs/architecture/code-structure.md`. **Carried:** #153, #116, remaining
R6 ownership cleanup, TS-50/TS-51/TS-53, Modern Runtime Slice J+, and #225's
R6 ownership cleanup, TS-50/TS-51/TS-53, Modern Runtime Slice J7+, and #225's
lifestone/particle alpha visual gate.
Start structural work at `memory/project_gamewindow_decomposition.md` and

View file

@ -241,7 +241,7 @@ src/
World/
RuntimeWorldEnvironmentState.cs -> canonical calendar/time/weather owner
RuntimeWorldTransitState.cs -> canonical reveal generation/readiness owner
-> J3J5 and J6.1J6.3 complete; J6.4 host acknowledgement active
-> J3J6 complete; J7 composition-root convergence active
-> may reference Core, Core.Net, Content, and Plugin.Abstractions only
-> must never reference App, UI, Silk.NET, OpenAL, Arch, or ImGui
@ -879,9 +879,16 @@ readiness may fall as resources transition without closing the accepted edge.
`WorldRevealCoordinator` is the graphical host adapter. It evaluates App's
`WorldRevealReadinessBarrier`, acknowledges that typed result to Runtime, and
owns only the streaming destination reservation, render-resource profile,
selection/audio projection edges, and viewport release. App's former lifecycle
telemetry/generation owner is deleted and
owns only generation-scoped graphical resource receipts: the streaming
destination reservation, render-resource profile, selection/audio projection
edges, and viewport release. Runtime issues an exact
`RuntimeWorldHostProjectionToken` for the reveal generation and destination
cell, then retains the typed registration, simulation-release,
reservation-release, and terminal acknowledgement suffix until App has
actually projected it. Wrong-generation/cell acknowledgements cannot consume
another reveal's work. Callback failure and re-entrancy preserve the exact
remaining suffix instead of duplicating or leaking a reservation. App's former
lifecycle telemetry/generation owner is deleted and
`WorldGenerationAvailabilityState` is a read-only Runtime projection. While the
normal world viewport is withheld, mesh and composite upload owners may admit
more small destination items per frame, but retain the ordinary 8 MiB byte,
@ -899,15 +906,15 @@ thread, never from the streaming worker. This is acdream's asynchronous equivale
`SmartBox::UseTime` holding position completion while
`CellManager::blocking_for_cells` is set.
`WorldRevealLifecycleTelemetry` is an observation seam owned by the
coordinator, not a second lifecycle state machine. It records generation-scoped
edges and rejects a normal-world viewport observed before canonical readiness.
`WorldLifecycleAutomationController` consumes only coordinator snapshots plus
resource counters; `FrameScreenshotController` performs the requested
default-framebuffer readback after world and retained UI draw on the render
thread. The external connected gate launches normal Release processes and
observes these artifacts, but never mutates streaming, physics, GL, or entity
state from a worker thread.
`RuntimeStateCheckpoint` is the normalized observation seam. It records the
canonical reveal snapshot plus environment and transit ownership ledgers; it is
not a second lifecycle state machine. `WorldLifecycleAutomationController`
consumes that borrowed Runtime checkpoint plus graphical resource counters and
rejects a stable checkpoint while any host acknowledgement remains.
`FrameScreenshotController` performs the requested default-framebuffer readback
after world and retained UI draw on the render thread. The external connected
gate launches normal Release processes and observes these artifacts, but never
mutates streaming, physics, GL, or entity state from a worker thread.
### Teleport cell identity at the streaming boundary

View file

@ -275,7 +275,7 @@ src/AcDream.App/
├── Streaming/
│ ├── LandblockPresentationPipeline.cs # DAT build/apply/retire transaction and resource publication
│ ├── StreamingController.cs # typed frame scheduler + reveal destination reservation
│ ├── WorldRevealCoordinator.cs # canonical readiness, quiesce, and reservation lifetime
│ ├── WorldRevealCoordinator.cs # graphical reveal projection and exact host receipts
│ └── ... # shipped streamer/world-state owners
├── Input/ # (already exists)
├── Audio/ # (already exists)
@ -472,14 +472,14 @@ useful ordering seam, but its ownership status is **partial**.
| World environment | **J6.1 complete Runtime ownership** | `RuntimeWorldEnvironmentState` owns the instance-scoped Dereth calendar, synchronized clock, weather progression/state, selected day group, AdminEnvirons state, and typed debug overrides. App converts immutable DAT sky definitions once and projects the borrowed Runtime snapshot into rendering; no process-global Region origin or second App clock/weather owner remains (`902076c0`). TS-54/TS-55 register the remaining centered UI sound and full fog/ambient/radar behavior gaps. |
| Live identity/lifetime | **J3 complete** | `RuntimeEntityObjectLifetime` owns the sole `RuntimeEntityDirectory`, live `ClientObjectTable`, direct views, and ordered entity/object stream. 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. Exact receipts precede fallible callbacks, re-entrant commits drain synchronously in sequence, and stable reset/disposal must converge the complete ledger to zero (`f46ddb5c`, `420e5eea`, `e937cc36`, `5ef8b537`, `ce3ac310`, `119b7c11`). |
| 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/transit | **J6.3 complete Runtime ownership** | `RuntimeWorldTransitState` owns the sole monotonic login/portal reveal generation, wrap-safe F751 history, pending/active teleport sequence, both accepted F751/Position packet orders, exact destination, typed atomic readiness latch, generation/sequence/cell placement and materialization validation, simulation edge, viewport observation, completion, cancellation, retail wait cue, and portal count. `WorldRevealCoordinator` and `LocalPlayerTeleportController` are graphical host adapters over App readiness/reservations, render-space placement, tunnel, and UI; `WorldGenerationAvailabilityState` borrows Runtime truth and owns no mutable generation. The App transit coordinator and accepted-destination mirror are deleted (`a6860d55`, `acb845d8`, `6a063a27`). |
| World reveal/transit | **J6 complete Runtime ownership** | `RuntimeWorldTransitState` owns the sole monotonic login/portal reveal generation, wrap-safe F751 history, pending/active teleport sequence, both accepted F751/Position packet orders, exact destination, typed atomic readiness latch, generation/sequence/cell placement and materialization validation, simulation edge, viewport observation, completion, cancellation, retail wait cue, portal count, and exact typed graphical-host acknowledgement suffix. `WorldRevealCoordinator` and `LocalPlayerTeleportController` are graphical adapters over App readiness, generation-scoped resource receipts, render-space placement, tunnel, and UI; failure/re-entrancy retains the exact unacknowledged suffix. `WorldGenerationAvailabilityState` borrows Runtime truth and owns no mutable generation. The App transit coordinator and accepted-destination mirror are deleted (`a6860d55`, `acb845d8`, `6a063a27`, `18d17d8b`). |
| 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. |
| Action/combat/magic/movement | **J5 complete** | Runtime `RuntimeActionState` owns the exact selection, temporary target mode, interaction transactions, combat attack/target/mode, and spell-cast intent children. Interaction owns use/appraisal/pickup identity, ordered FIFO, and exact post-arrival token while borrowing J4's sole busy gate. `RuntimeLocalPlayerMovementState` owns the exact local controller, construction seam, autorun latch, typed view, and outbound MTS/jump/AP cadence. Retained bars, physical input, world/content queries, transport, lighting, toasts, drag/drop, effects, and animation remain App adapters/presentation. One combined Runtime ledger spans entity/object, gameplay, physics, remote, and projectile ownership (`b298f99f`, `f5f7b417`, `20df9d15`, `aa3f4a60`, `cdee7a4b`). |
| Physics/remote simulation | **J5.5 complete** | `RuntimePhysicsState` owns one per-session engine, production cache/cell graph, transition scratch, shadow registry, typed collision admissions, canonical bodies/hosts/remotes, keyed ordinary/remote worksets, simulation, and cell commits. App streaming supplies immutable prepared collision; animation/shape adapters supply graphical inputs and project committed snapshots only (`7e6033d0`). |
| Projectile simulation | **J5.6 complete** | `RuntimeEntityRecord`/`RuntimePhysicsState` own the canonical projectile component, exact-key workset, prediction/correction state, unchanged retail quantum/integration/sweep/collision loop, and cell commits. App resolves immutable Setup/DAT shape input and projects committed render, shadow, and effect-pose results only (`2aee3356`). |
| 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 at J6.4** | Canonical identity, retained-object lifetime, direct views, ordered entity/object deltas, J4 gameplay state, and the complete J5 action/combat/magic/movement/physics/remote/projectile simulation graph share failure-safe Runtime owners while exact graphical sidecars stay in App. J5 closeout proves Runtime-only parity and one terminal ownership ledger. J6.1J6.3 moved world environment, reveal-generation truth, and exact F751/Position destination correlation; J6.4 now closes typed graphical-host acknowledgements before J7 composes one `GameRuntime` root. |
| Unified `GameEntity` | **Slice J active at J7** | Canonical identity, retained-object lifetime, direct views, ordered entity/object deltas, J4 gameplay state, and the complete J5 action/combat/magic/movement/physics/remote/projectile simulation graph share failure-safe Runtime owners while exact graphical sidecars stay in App. J5 closeout proves Runtime-only parity and one terminal ownership ledger. J6 moved world environment, reveal-generation truth, exact F751/Position destination correlation, and typed graphical-host acknowledgement into Runtime. J7 now composes those already-proven owners behind one `GameRuntime` root without adding another state layer. |
### 4.3 Revised extraction sequence

View file

@ -68,7 +68,7 @@ accepted-divergence entries (#96, #49, #50).
|---|---|---|---|---|---|
| AD-38 | Outgoing teleport viewports retire when retail's quantized animation level exceeds the last captured visible level 1022 (index 96), suppressing levels 1023/1024 up to 20.2 ms before retail's literal `elapsed >= 1.0` state edge. Incoming fades retain the exact timer. | `src/AcDream.Core/World/TeleportAnimSequencer.cs` (`OutgoingViewportReachedTerminalProjection`) | An uncapped 2000 FPS pass can publish the finite tunnel at levels 1023/1024 even though the paired 2013 retail capture switches viewports after 1022. The table-level cutover preserves the captured visible viewport ordering without throttling the application. | Exit sound, viewport replacement, and logout tunnel entry can occur at most two easing-table quanta (about 20.2 ms) earlier than retail's logical timer. | `UIGlobals::GetAnimLevel @ 0x004EE540`; `gmSmartBoxUI::UseTime @ 0x004D6E30`; paired retail/acdream captures documented in `docs/research/2026-07-15-retail-portal-space-pseudocode.md` |
| AD-1 | Lost-cell machinery replaced by recoverable outdoor demote (**#107** safety net) + outdoor-restore `max(terrainZ, z)` under-terrain lift; retail goes `GotoLostCell` | `src/AcDream.Core/Physics/PhysicsEngine.cs:553` (+ :808) | acdream has no lost-cell state machine; outdoor landcell is the recoverable equivalent; the #107 auto-entry hold should make the demote branch unreachable | Gap in the hold → player committed to outdoor terrain inside/under a building (fake-grounded spawn, fall-through); a legit below-heightmap server restore is silently lifted — upward warp vs server | `GotoLostCell` pc:283418; `SetPositionInternal` 0x00515bd0, pc:283892-283945 |
| AD-2 | Async readiness gates replace retail's synchronous destination cell load. **#229 refinement (2026-07-20):** login and F751 portal-space exit now share `WorldRevealReadinessBarrier`, so neither path can expose the normal viewport until the same render-publication, composite-texture, and collision domains converge. A hydratable indoor claim requires its owning Near-tier static/EnvCell mesh set, destination composites, and exact EnvCell physics (`IsSpawnCellReady`); an outdoor claim requires those render domains plus terrain/collision residency for the required Near ring. Hard-recenter generations and tier-aware completion application prevent stale overlapping loads/unloads or Far/Near jobs from opening or erasing the gate; mesh upload remains separate from balanced landblock ownership. Claims beyond NumCells still take the loud unhydratable-placement path. `WorldRevealCoordinator` owns this shared lifetime; diagnostic telemetry observes its generation without defining another readiness path. **Slice E3 refinement (2026-07-24):** the same generation now publishes an immediate `WorldGenerationQuiescence` edge: old-world drawing/spatial queries, simulation/effect clocks, reconciliation, targeting, and 3-D audio stop while retained physical teardown advances through metered cursors and destination network/UI/streaming/readiness remain live. **Slice E4 refinement (2026-07-24):** accepted render/physics/static publication may span update frames through retained exact cursors, but reveal still consumes only the completed spatial/render-ready generation; building and EnvCell snapshots remain invisible until complete and the final spatial identity swap stays observer-atomic. **Slice E5 refinement (2026-07-24):** the reveal generation owns one exact destination reservation across every typed budget dimension. Stale completion cannot consume or clear its replacement, and hydratable incomplete content is never force-revealed; portal transit retains the DAT tunnel and centered retail wait cue until readiness converges. The hold→materialize→regain-control lifecycle remains owned by `TeleportAnimSequencer`. | `src/AcDream.App/Streaming/WorldRevealCoordinator.cs`; `src/AcDream.App/Streaming/WorldGenerationQuiescence.cs`; `src/AcDream.App/Streaming/WorldRevealReadinessBarrier.cs`; `src/AcDream.App/Streaming/StreamingOriginRecenterCoordinator.cs`; `src/AcDream.App/Streaming/LandblockPresentationPipeline.cs`; `src/AcDream.App/Streaming/StreamingController.cs`; `src/AcDream.App/Rendering/PortalTunnelPresentation.cs`; `src/AcDream.App/UI/PortalWaitNoticeController.cs`; `src/AcDream.App/Streaming/GpuWorldState.cs` (`IsRenderReady`); `src/AcDream.App/Rendering/Wb/LandblockSpawnAdapter.cs`; `src/AcDream.Core/Physics/PhysicsEngine.cs` (`IsSpawnCellReady`, `IsNeighborhoodTerrainResident`) | This is the asynchronous equivalent of retail leaving `SmartBox::position_update_complete` false while `CellManager::blocking_for_cells` is set: neither initial login nor portal arrival may reveal or continue simulating an old/partial collision world, a terrain-only Far shell, or a published-but-not-drawable GPU landblock. Indoor does not require a terrain heightmap, only the owning render landblock and exact EnvCell. | Gate opens early → grey/untextured first login or portal reveal, free-fall, wrong-cell rooting, missing scenery, or a still-active old generation; predicate never satisfies (streamer/DAT/upload failure) → login remains behind the world render gate, while portal transit remains in the authored tunnel and presents the centered wait cue after five seconds. | `SmartBox::UseTime` 0x00455410; `gmSmartBoxUI::UseTime` 0x004D6E30; `gmSmartBoxUI::EndTeleportAnimation` 0x004D65A0 |
| AD-2 | Async readiness gates replace retail's synchronous destination cell load. **#229 refinement (2026-07-20):** login and F751 portal-space exit now share `WorldRevealReadinessBarrier`, so neither path can expose the normal viewport until the same render-publication, composite-texture, and collision domains converge. A hydratable indoor claim requires its owning Near-tier static/EnvCell mesh set, destination composites, and exact EnvCell physics (`IsSpawnCellReady`); an outdoor claim requires those render domains plus terrain/collision residency for the required Near ring. Hard-recenter generations and tier-aware completion application prevent stale overlapping loads/unloads or Far/Near jobs from opening or erasing the gate; mesh upload remains separate from balanced landblock ownership. Claims beyond NumCells still take the loud unhydratable-placement path. `RuntimeWorldTransitState` owns the shared reveal generation, accepted readiness, transit correlation, and exact generation/cell-scoped host-acknowledgement suffix. `WorldRevealCoordinator` is a graphical adapter holding only App resource receipts; normalized Runtime checkpoints observe ownership without defining another readiness path. **Slice E3 refinement (2026-07-24):** the same generation now publishes an immediate `WorldGenerationQuiescence` edge: old-world drawing/spatial queries, simulation/effect clocks, reconciliation, targeting, and 3-D audio stop while retained physical teardown advances through metered cursors and destination network/UI/streaming/readiness remain live. **Slice E4 refinement (2026-07-24):** accepted render/physics/static publication may span update frames through retained exact cursors, but reveal still consumes only the completed spatial/render-ready generation; building and EnvCell snapshots remain invisible until complete and the final spatial identity swap stays observer-atomic. **Slice E5 refinement (2026-07-24):** the reveal generation owns one exact destination reservation across every typed budget dimension. Stale completion cannot consume or clear its replacement, and hydratable incomplete content is never force-revealed; portal transit retains the DAT tunnel and centered retail wait cue until readiness converges. The hold→materialize→regain-control lifecycle remains owned by `TeleportAnimSequencer`. | `src/AcDream.Runtime/World/RuntimeWorldTransitState.cs`; `src/AcDream.App/Streaming/WorldRevealCoordinator.cs`; `src/AcDream.App/Streaming/WorldGenerationQuiescence.cs`; `src/AcDream.App/Streaming/WorldRevealReadinessBarrier.cs`; `src/AcDream.App/Streaming/StreamingOriginRecenterCoordinator.cs`; `src/AcDream.App/Streaming/LandblockPresentationPipeline.cs`; `src/AcDream.App/Streaming/StreamingController.cs`; `src/AcDream.App/Rendering/PortalTunnelPresentation.cs`; `src/AcDream.App/UI/PortalWaitNoticeController.cs`; `src/AcDream.App/Streaming/GpuWorldState.cs` (`IsRenderReady`); `src/AcDream.App/Rendering/Wb/LandblockSpawnAdapter.cs`; `src/AcDream.Core/Physics/PhysicsEngine.cs` (`IsSpawnCellReady`, `IsNeighborhoodTerrainResident`) | This is the asynchronous equivalent of retail leaving `SmartBox::position_update_complete` false while `CellManager::blocking_for_cells` is set: neither initial login nor portal arrival may reveal or continue simulating an old/partial collision world, a terrain-only Far shell, or a published-but-not-drawable GPU landblock. Indoor does not require a terrain heightmap, only the owning render landblock and exact EnvCell. | Gate opens early → grey/untextured first login or portal reveal, free-fall, wrong-cell rooting, missing scenery, or a still-active old generation; predicate never satisfies (streamer/DAT/upload failure) → login remains behind the world render gate, while portal transit remains in the authored tunnel and presents the centered wait cue after five seconds. | `SmartBox::UseTime` 0x00455410; `gmSmartBoxUI::UseTime` 0x004D6E30; `gmSmartBoxUI::EndTeleportAnimation` 0x004D65A0 |
| AD-3 | Outdoor seeds always walk the transit array (retail skips the walk when the seed CLandCell is null/unloaded); per-cell lookups no-op on unhydrated data | `src/AcDream.Core/Physics/CellTransit.cs:503` | Equivalence argument: with nothing hydrated every lookup inside the walk no-ops, so the result matches retail's skipped walk | Near partially-streamed landblocks, building-transit promotion silently can't fire until structs hydrate — membership stays outdoor while the player is inside a building | `CObjCell::find_cell_list` 0052b535-0052b56c (null-CLandCell case) |
| AD-4 | `point_in_cell` against an unhydrated CellBSP returns false (skip) rather than the null-node "inside" default; retail never queries unloaded cells | `src/AcDream.Core/Physics/CellTransit.cs:588` | The null-node default would make an unhydrated cell spuriously claim every point; skipping is the conservative streaming-safe choice | During hydration, a point genuinely inside a not-yet-loaded cell resolves outdoor/stale — transient membership misclassification driving wrong collision set and render root | `CEnvCell::find_visible_child_cell` :311397; cell-BSP vtable[0x84] |
| AD-5 | Outdoor `point_in_cell` is an identity compare against the global XY-column cell from `LandDefs.AdjustToOutside` (no per-cell containment test) | `src/AcDream.Core/Physics/CellTransit.cs:865` | Landcells are disjoint 24 m columns — identity-compare against the column under the sphere centre is exactly equivalent to retail's per-candidate test | If block-origin/lcoord math is wrong at a landblock seam, the compare silently never matches — outdoor membership freezes at boundaries (the pre-#106 symptom) | `find_cell_list` pick pc:308788-308825; `CLandCell::point_in_cell` (get_block_offset pc:308804) |

View file

@ -1,6 +1,6 @@
# acdream — strategic roadmap
**Status:** Living document. Updated 2026-07-26. **M3 landed; M4 is active.** M3's retail casting/UI, R6 locomotion/collision/projectile/teleport/radar rebaseline, deterministic fresh-login/portal world lifecycle, and final two-client portal observer flow are user-gated. All eight slices of the behavior-preserving ownership campaign in [`docs/architecture/code-structure.md`](../architecture/code-structure.md), their automated closeout, and the user's connected visual matrix are complete. Modern Runtime J3 canonical entity/object lifetime and J4 gameplay-state ownership are closed at `89e6b207`; J5.1 canonical selection/combat/target-mode ownership is closed at `b298f99f`, J5.2 interaction transactions at `f5f7b417`, J5.3 combat/magic intent at `20df9d15`, J5.4 local movement/outbound cadence at `aa3f4a60`, J5.5 per-session physics/remote simulation at `7e6033d0`, J5.6 projectile simulation at `2aee3356`, and J5.7 combined simulation closeout at `cdee7a4b`. J6.1 world-environment ownership is closed at `902076c0`; J6.2 canonical reveal generation and typed destination readiness is closed at `a6860d55` plus `acb845d8`; J6.3 exact F751/Position destination correlation is closed at `6a063a27`; J6.4 graphical-host acknowledgement and owner cleanup is active. Issue #225's lifestone/particle alpha comparison remains a separate rendering visual gate.
**Status:** Living document. Updated 2026-07-26. **M3 landed; M4 is active.** M3's retail casting/UI, R6 locomotion/collision/projectile/teleport/radar rebaseline, deterministic fresh-login/portal world lifecycle, and final two-client portal observer flow are user-gated. All eight slices of the behavior-preserving ownership campaign in [`docs/architecture/code-structure.md`](../architecture/code-structure.md), their automated closeout, and the user's connected visual matrix are complete. Modern Runtime J3 canonical entity/object lifetime and J4 gameplay-state ownership are closed at `89e6b207`; J5.1 canonical selection/combat/target-mode ownership is closed at `b298f99f`, J5.2 interaction transactions at `f5f7b417`, J5.3 combat/magic intent at `20df9d15`, J5.4 local movement/outbound cadence at `aa3f4a60`, J5.5 per-session physics/remote simulation at `7e6033d0`, J5.6 projectile simulation at `2aee3356`, and J5.7 combined simulation closeout at `cdee7a4b`. J6.1 world-environment ownership is closed at `902076c0`; J6.2 canonical reveal generation and typed destination readiness is closed at `a6860d55` plus `acb845d8`; J6.3 exact F751/Position destination correlation is closed at `6a063a27`; J6.4 exact graphical-host acknowledgement and owner cleanup is closed at `18d17d8b`. J7 composition-root convergence is active. Issue #225's lifestone/particle alpha comparison remains a separate rendering visual gate.
**Purpose:** One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under `docs/superpowers/specs/`, not in this file.
---
@ -1792,7 +1792,11 @@ port in any phase — no separate listing here.
> validation; the App transit coordinator and destination mirror are deleted.
> Its 360 Runtime tests, 3,710 App tests / 3 skips, 8,631-test / 5-skip complete
> Release suite, and exact-binary lifecycle/reconnect route pass. J6.4
> graphical-host acknowledgement and owner cleanup is active.
> completed at `18d17d8b`: Runtime owns exact generation/cell-scoped host
> obligations and App owns only retryable graphical resource receipts. Its 365
> Runtime tests, 3,716 App tests / 3 skips, 8,642-test / 5-skip complete Release
> suite, and exact-binary lifecycle/reconnect route pass with zero ownership
> debt at every checkpoint. J7 composition-root convergence is active.
> The historical exact cutover
> rollback remains
> `git revert ef1d263337997bb030eadb7b8e71d73dc659907a`. Slice H is complete:

View file

@ -266,8 +266,13 @@ residency is `0/0/0` at every stable checkpoint and teardown converges. Slice I
destination, and generation/sequence/cell placement and materialization
validation; App's transit coordinator and destination mirror are deleted.
Its 360 Runtime tests, 3,710 App tests / 3 skips, 8,631 complete Release tests
/ 5 skips, and exact-binary lifecycle/reconnect route pass. J6.4 graphical-
host acknowledgement and owner cleanup is active under
/ 5 skips, and exact-binary lifecycle/reconnect route pass. J6.4 completed at
`18d17d8b`: Runtime owns the exact generation/cell-scoped graphical-host
acknowledgement suffix while App owns only retryable resource receipts.
Its 365 Runtime tests, 3,716 App tests / 3 skips, 8,642 complete Release tests
/ 5 skips, and exact-binary lifecycle/reconnect route pass with every
environment/transit/host ledger at zero. J7 composition-root convergence is
active 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).
@ -303,6 +308,8 @@ Slice-J5.6 closeout evidence is
[`../research/2026-07-26-slice-j5-6-projectile-ownership.md`](../research/2026-07-26-slice-j5-6-projectile-ownership.md).
Slice-J6.3 closeout evidence is
[`../research/2026-07-26-slice-j6-3-teleport-correlation.md`](../research/2026-07-26-slice-j6-3-teleport-correlation.md).
Slice-J6 closeout evidence is
[`../research/2026-07-26-slice-j6-4-host-acknowledgement.md`](../research/2026-07-26-slice-j6-4-host-acknowledgement.md).
The historical exact G4 visual rollback remains
`git revert ef1d263337997bb030eadb7b8e71d73dc659907a`.

View file

@ -21,9 +21,10 @@ and combat ownership closed at `cdee7a4b` after canonical action state
(`20df9d15`), local movement/outbound cadence (`aa3f4a60`), and per-session
physics/remote simulation (`7e6033d0`), projectile simulation (`2aee3356`),
and the combined simulation ledger/Runtime-only closeout moved to Runtime.
J6.1J6.3 moved world environment, canonical reveal generation/readiness, and
exact F751/Position destination correlation into Runtime. J6.4 graphical-host
acknowledgement and owner cleanup is active.
J6 completed at `18d17d8b`: Runtime owns world environment, canonical reveal
generation/readiness, exact F751/Position destination correlation, and the
generation/cell-scoped graphical-host acknowledgement suffix. J7
composition-root convergence is active.
**Scope:** Reconcile and sequence the existing Modern Pipeline (`MP`) and
Linux/headless (`LH`) tracks using the 2026-07-24 connected performance audit.
@ -1288,8 +1289,11 @@ environment, the reveal generation/readiness lifetime, wrap-safe
F751/Position correlation, and the exact generation/sequence/cell placement
handshake. Its 360 Runtime tests, 3,710 App tests / 3 skips, 8,631-test /
5-skip Release suite, and exact-binary lifecycle/reconnect gate pass. J6.4
graphical-host acknowledgement and owner cleanup is the current execution
point.
completed at `18d17d8b`: Runtime owns the exact outstanding graphical-host
projection stages and App owns only retryable resource receipts. Its 365
Runtime tests, 3,716 App tests / 3 skips, 8,642-test / 5-skip complete Release
suite, and exact-binary lifecycle/reconnect gate pass with zero ownership debt
at every stable checkpoint. J7 is the current execution point.
Evidence:
[`../research/2026-07-25-slice-g5-production-profile.md`](../research/2026-07-25-slice-g5-production-profile.md)
and

View file

@ -354,16 +354,19 @@ graphical feel gates remain unchanged.
### J6 — world, portal, environment, and projection handshake
**J6.0J6.3 complete; J6.4 active 2026-07-26.** The instance-scoped Runtime
**J6 complete 2026-07-26.** The instance-scoped Runtime
environment owner landed at `902076c0`. The canonical reveal generation and
typed readiness owner landed at `a6860d55` plus `acb845d8`; App's duplicate
lifecycle owner is deleted and the exact connected lifecycle/reconnect gate
passes with zero reveal invariants. Canonical F751/Position correlation and
exact generation/sequence/cell placement handshake landed at `6a063a27`; the
App transit coordinator and accepted-destination mirror are deleted. Its
360 Runtime tests, 3,710 App tests / 3 skips, 8,631-test / 5-skip complete
Release suite, and exact-binary lifecycle/reconnect route pass. Evidence:
[`../research/2026-07-26-slice-j6-3-teleport-correlation.md`](../research/2026-07-26-slice-j6-3-teleport-correlation.md).
App transit coordinator and accepted-destination mirror are deleted. Exact
typed host acknowledgement and retryable graphical-resource receipts landed at
`18d17d8b`; Runtime now retains every outstanding host obligation through
failure, re-entrancy, cancellation, supersession, and reset. Its 365 Runtime
tests, 3,716 App tests / 3 skips, 8,642-test / 5-skip complete Release suite,
and exact-binary lifecycle/reconnect route pass. Evidence:
[`../research/2026-07-26-slice-j6-4-host-acknowledgement.md`](../research/2026-07-26-slice-j6-4-host-acknowledgement.md).
Detailed owner inventory, retail ordering, host-acknowledgement contract,
execution ledger, adversarial matrix, and current plan:
[`2026-07-26-modern-runtime-slice-j6.md`](2026-07-26-modern-runtime-slice-j6.md).

View file

@ -1,6 +1,6 @@
# Modern runtime Slice J6 — world, transit, and host handshake
**Status:** J6.0J6.3 COMPLETE; J6.4 ACTIVE
**Status:** J6 COMPLETE
**Parent:** `2026-07-25-modern-runtime-slice-j.md`, J6
**Authorization:** the user approved Slices FL, including gameplay-owner
moves, on 2026-07-24
@ -53,11 +53,11 @@ the teleport generation, destination identity, materialization state, or
simulation availability. A headless host supplies the same acknowledgement
contract using its own required domains.
## 2. Current owner inventory
## 2. Baseline owner inventory (before J6)
### 2.1 Authoritative state incorrectly retained in App
### 2.1 Authoritative state that J6 removed from App
| Current owner | State | J6 destination |
| Baseline App owner | State | Final J6 owner |
|---|---|---|
| `WorldEnvironmentController` | server-synced world clock, selected day group, weather, AdminEnvirons override, debug overrides | `RuntimeWorldEnvironmentState` |
| static `DerethDateTime.OriginOffsetTicks` | mutable Region calendar origin shared by every process session | instance `DerethCalendar` owned by each environment |
@ -292,6 +292,8 @@ warning. Evidence:
### J6.4 — projection acknowledgement and owner cleanup
**Complete 2026-07-26 at `18d17d8b`.**
- Make App presentation registration/withdrawal use typed generation-scoped
acknowledgements.
- Ensure simulation release, viewport reveal, reservation release, and final
@ -306,8 +308,19 @@ warning. Evidence:
Gate: source/dependency guards find no App authority or Runtime presentation
dependency; every failure-injection ledger converges to zero.
Result: Runtime owns an exact host-projection token and typed remaining-stage
ledger for each reveal generation/destination. App retains only graphical
resource receipts attached to that token. Registration, simulation release,
reservation release, terminal completion, cancellation, supersession, and
reset preserve an exact retryable suffix through callback failure and
re-entrancy. Normalized checkpoints expose environment and transit ownership,
including pending host acknowledgements. Direct Runtime fixtures complete
login, portal, cancellation, and reset without loading App or a backend.
### J6.5 — connected and documentation closeout
**Complete 2026-07-26.**
- Run focused Core, Runtime, and App projects.
- Run `dotnet build AcDream.slnx -c Release`.
- Run the complete Release test suite.
@ -318,6 +331,14 @@ dependency; every failure-injection ledger converges to zero.
- Update architecture, code structure, milestone, roadmap, parent plan,
AGENTS/CLAUDE, divergence ledger, and durable memory.
Runtime tests pass 365/365, App tests pass 3,716/3 skips, and the complete
Release suite passes 8,642/5 skips. Exact-binary report
`logs/connected-world-gate-20260726-182805/report.json` records six capped
checkpoints and one uncapped fresh-process reconnect, graceful code-zero exits,
zero failures, and zero environment/transit/host ownership debt at every
stable checkpoint. Evidence:
[`../research/2026-07-26-slice-j6-4-host-acknowledgement.md`](../research/2026-07-26-slice-j6-4-host-acknowledgement.md).
J6 is complete only when automated and connected evidence proves:
- one Runtime environment owner;
@ -375,6 +396,12 @@ J6.3 exact rollback:
git revert 6a063a27d4c805cd166d5a487afc290c34c400fd
```
J6.4 exact rollback:
```text
git revert 18d17d8bb17ed9ff3ed01da8273e2948abe6398b
```
Documentation-only research/plan commits are not behavior rollback points.
No workaround, timer, forced-ready path, duplicated owner, or alternate
headless behavior is permitted.

View file

@ -661,6 +661,30 @@ destination.
- The portal object is synthetic and never enters `LiveEntityRuntime`, world
picking, collision, radar, or server GUID ownership.
## Modern-runtime host projection mapping (Slice J6)
The accepted retail sequence remains authoritative; Slice J6 changes only
which process-local owner proves each edge:
```text
Runtime accepts exact generation + destination
App prepares destination resources
App acknowledges typed readiness to Runtime
Runtime advances materialization / simulation availability
App projects that exact generation into graphical state
App acknowledges simulation release
App releases the exact destination reservation
App acknowledges reservation release
App observes the normal viewport for that generation
App acknowledges terminal projection
Runtime may retire the completed host record
```
The Runtime token includes both generation and destination cell. A callback
failure leaves the exact unacknowledged suffix live; a superseding portal
cannot consume it. This is ownership bookkeeping around the existing retail
order, not a timer, asynchronous UI queue, or alternate portal behavior.
## Cross-reference notes
- `references/WorldBuilder` supplies the extracted setup/GfxObj mesh and modern

View file

@ -0,0 +1,99 @@
# Slice J6.4 closeout — exact graphical-host acknowledgement
**Status:** COMPLETE
**Production commit:** `18d17d8bb17ed9ff3ed01da8273e2948abe6398b`
**Exact rollback:** `git revert 18d17d8bb17ed9ff3ed01da8273e2948abe6398b`
## Result
`RuntimeWorldTransitState` now owns the complete presentation-independent
login/portal lifetime, including the exact work still owed by a graphical or
headless host. App no longer infers completion from local booleans. Instead,
Runtime issues one `RuntimeWorldHostProjectionToken` for the exact reveal
generation and destination cell and records the remaining typed
acknowledgements:
1. host projection registered;
2. simulation release projected;
3. destination reservation released;
4. terminal completion projected.
Wrong-generation, wrong-cell, duplicate, empty, composite, reordered, and
post-terminal acknowledgements are rejected. Cancellation and supersession
retain the exact remaining suffix. Session reset refuses to erase an
outstanding host obligation.
`WorldRevealCoordinator` is now a strict graphical adapter. Its local records
contain only App resource receipts associated with a Runtime token. The drain
is serialized and re-entrancy safe: callback failure leaves the exact suffix
retryable, while a callback that starts or cancels another reveal cannot
overwrite or leak the prior destination reservation. `WorldGenerationQuiescence`
uses the same edge-before-callback rule and converges audio to the newest
desired state after failure or re-entrancy.
Normalized runtime traces and connected checkpoints now expose both canonical
ownership ledgers:
- `RuntimeWorldEnvironmentOwnershipSnapshot`;
- `RuntimeWorldTransitOwnershipSnapshot`, including host projection and
pending-host-acknowledgement counts.
The connected gate rejects a stable checkpoint unless the environment owner is
initialized with one active day group and all transit/host obligations have
converged to zero.
## Retail ordering preserved
The ownership change preserves the already accepted retail order documented in
`2026-07-15-retail-portal-space-pseudocode.md` and
`2026-07-16-portal-completion-pseudocode.md`:
- destination identity is accepted before placement;
- readiness remains latched once accepted;
- simulation is released only after materialization;
- the normal viewport is observed before terminal completion;
- incomplete destinations remain in the authored portal tunnel;
- presentation resources retire after their final consumer edge.
No portal timer, forced-ready path, alternate animation, additional frame
queue, or new retail divergence was introduced.
## Automated evidence
- Focused Runtime host/ownership fixtures: 58 passed.
- Focused App reveal/quiescence fixtures: 52 passed.
- `AcDream.Runtime.Tests`: 365 passed.
- `AcDream.App.Tests`: 3,716 passed / 3 skipped.
- `dotnet build AcDream.slnx -c Release`: passed, zero errors.
- Complete Release solution: 8,642 passed / 5 skipped.
- Dependency/source guards prove the direct Runtime host loads no
App/UI/Silk/OpenAL/Arch/ImGui assembly and that App has no replacement
transit-authority field.
- Failure-injection fixtures cover registration, simulation release,
reservation release, terminal completion, audio projection, reset, and
callback re-entrancy. Every ownership ledger converges to zero.
The direct Runtime-only fixture completes login, portal, cancellation, and
reset without constructing `GameWindow` or loading a graphical/audio backend.
## Connected exact-binary evidence
Report:
`logs/connected-world-gate-20260726-182805/report.json`
- exact commit:
`18d17d8bb17ed9ff3ed01da8273e2948abe6398b`;
- capped route: login → Aerlinthe → Rynthid → Facility Hub → Holtburg →
Aerlinthe revisit;
- uncapped route: fresh-process reconnect;
- seven stable checkpoints;
- both processes exited gracefully with code zero;
- zero failures and only the expected world-edge landblock-miss warning;
- every checkpoint reports `DayGroupDefinitionCount = 20`,
`ActiveDayGroupCount = 1`, `IsSessionIdle = true`,
`HostProjectionCount = 0`, and
`PendingHostAcknowledgementCount = 0`.
This closes J6.4 and J6.5. Slice J6 has one Runtime environment owner, one
Runtime transit/reveal owner, an exact host acknowledgement protocol, and no
remaining App reconstruction of portal authority.