acdream/docs/plans/2026-07-26-modern-runtime-slice-j7.md

182 lines
8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Modern runtime Slice J7 — one `GameRuntime` composition root
**Status:** ACTIVE
**Parent:** `2026-07-25-modern-runtime-slice-j.md`, J7
**Authorization:** the user approved Slices FL, including the J gameplay-owner
gates, on 2026-07-24
**Purpose:** compose the already-proven Runtime lifetime groups behind one
instance-scoped owner without changing retail behavior, update order, command
latency, rendering, retained UI, or portal presentation.
## 1. Baseline problem
The canonical state is already in `AcDream.Runtime`, but production constructs
its owners at separate graphical composition points:
| Owner | Baseline construction site |
|---|---|
| entity/object/physics lifetime | `GameWindow` field initializer |
| inventory, character, communication, actions | `GameWindow` constructor |
| local movement | `GameWindow` field initializer |
| world environment | `GameWindow` through `WorldEnvironmentController` |
| world transit/reveal | `LivePresentationComposition` |
| session/transport | `SessionPlayerComposition` |
| simulation clock | inside App's `UpdateFrameClock` |
| normalized view/events | App `CurrentGameRuntime*Adapter` objects |
These are not duplicate gameplay models, but the split construction and
teardown graph makes it possible to assemble incompatible owners or retire
them in the wrong order. It also prevents a no-window host from constructing
the exact same complete kernel in one operation.
## 2. Fixed boundary
Add one public, presentation-independent `GameRuntime` in
`AcDream.Runtime`. It owns exactly:
- canonical session/transport lifetime;
- local player server identity;
- entity/object/physics lifetime;
- inventory, character, communication, and action lifetime groups;
- local movement intent/controller lifetime;
- world environment and world transit/reveal state;
- the instance simulation clock;
- normalized borrowed views and the lazy ordered Runtime event source;
- the terminal ownership ledger and retryable teardown cursor.
`GameRuntime` may depend only on Runtime's existing operation interfaces,
Core/Core.Net/Content/Plugin.Abstractions, and injected clock/log/session
operations. It never imports App, UI, Silk.NET, OpenAL, Arch, or ImGui.
App keeps:
- DAT/GL/audio/UI objects;
- physical input, camera, selection presentation, and command translation;
- render-space origin and portal tunnel presentation;
- synchronous adapters that borrow one `GameRuntime`;
- generation-scoped graphical resource receipts.
Input, command execution, UI state reads, simulation, and rendering stay in the
same host frame. No queue, snapshot copy, worker hop, or extra frame boundary is
introduced.
## 3. Ownership invariants
1. A production `GameWindow` stores exactly one `GameRuntime` field.
2. Composition dependency records receive that root, not independently paired
Runtime owners.
3. Runtime children are created once by the root and are never replaced.
4. Graphical adapters may borrow children but cannot dispose or rebind them.
5. The session is quiesced by the root before App route/projection teardown.
6. App projection owners retire before the Runtime root's terminal disposal.
7. Root disposal is ordered, retryable, and resumes at the exact failed suffix.
8. Construction failure retires every already-created child in reverse order.
9. The event source attaches to owner events only while observers exist and is
detached before owner disposal.
10. A disposed graphical adapter is inert without disposing the Runtime root.
11. Two roots never share identity, clock, event sequence, world, gameplay,
physics, or session state.
12. Root construction and direct views load no graphical/audio/UI backend.
## 4. Execution
### J7.1 — Runtime root, identity, events, and terminal ledger
**Complete 2026-07-26 at `96ddd165`.**
- Add `GameRuntime`, typed construction dependencies, local-player identity,
construction fault points, ownership snapshot, and exact teardown stages.
- Move the normalized view/checkpoint implementation into the root.
- Move the lazy entity/inventory/chat event fanout into Runtime.
- Add session ownership accounting.
- Prove reverse construction rollback, exact retryable disposal, two-instance
isolation, lazy subscriptions, and zero presentation dependencies.
Gate: focused Runtime tests pass and dependency/source guards find no App or
backend reference.
Result: one `GameRuntime` now constructs and owns session, local identity,
entity/object/physics, gameplay, movement, environment, transit, clock, and
lazy normalized events. Typed host leases prevent early retirement.
Construction rollback drains acquired children in reverse; terminal disposal
uses an exact stage cursor and ownership ledger. The focused 18-test root
matrix, all 383 Runtime tests, Release build, and complete 8,660-test /
5-skip solution pass. Production still uses the existing graphical
construction path until J7.2 performs the isolated cutover.
### J7.2 — production composition cutover
- Construct one root in `GameWindow`.
- Make `UpdateFrameClock` borrow the root clock.
- Make `WorldEnvironmentController` and `WorldGenerationAvailabilityState`
graphical adapters over root children.
- Make live presentation borrow root transit rather than construct it.
- Make session composition borrow root session rather than construct/transfer
it.
- Change composition dependency records to carry the root instead of
independent Runtime owners.
- Replace App's view/event reconstruction with one inertable graphical command
adapter over the root.
- Delete superseded App view/event adapters and direct production constructors.
Gate: App composition/failure-injection tests prove one exact root and no
partial publication or borrowed-owner disposal.
### J7.3 — one shutdown transaction
- Replace individual Runtime roots in `GameWindowShutdownRoots` with
`GameRuntime`.
- Quiesce its session at the existing ingress barrier.
- Retire every graphical borrower before terminal root disposal.
- Make root disposal preserve the exact suffix through callback failure and
re-entrancy.
- Extend checkpoint/terminal ledgers with root/session/event ownership.
Gate: every shutdown fault point converges on retry; no subscriber, route,
entity, physics, gameplay, transit, or session debt remains.
### J7.4 — validation and closeout
- Focused Runtime and App tests.
- Release solution build.
- Complete Release suite.
- Exact-binary connected lifecycle/reconnect route.
- Canonical nine-stop route and allocation/frame-time comparison against J6.
- Physical-display visual checks for login, world objects, radar, inventory
paperdoll, use/approach, combat facing, portal tunnel, and portal exit.
- Update architecture, code structure, milestone, roadmap, parent/umbrella
plans, AGENTS/CLAUDE, divergence ledger, and durable memory.
## 5. Adversarial matrix
- construction failure after every child owner;
- disposal failure at every root teardown stage;
- re-entrant session stop/dispose;
- observer removal and addition during event dispatch;
- observer failure while another observer remains;
- App adapter disposal while Runtime remains live;
- root disposal while an App borrower is still registered;
- session start/reconnect during disposal;
- duplicate disposal and retry after partial teardown;
- two simultaneous roots with different clocks, identities, entities, portals,
and event observers;
- portal host acknowledgement pending at shutdown;
- graphical composition failure before and after session host creation;
- same-frame selection/use/combat/magic/UI response before and after cutover;
- no Runtime load of App/UI/Silk/OpenAL/Arch/ImGui.
## 6. Commit and rollback discipline
Each production sub-slice lands separately after its focused and complete
Release gates. Record its full production SHA and exact `git revert <sha>` here
before beginning the next sub-slice. Documentation-only commits are not
behavior rollback points.
J7.1 exact rollback:
```text
git revert 96ddd16539e670a5ce9b1f86677530e3fbc3f635
```
No compatibility owner, service locator, asynchronous command queue, timeout,
forced-ready path, or alternate headless behavior is permitted.