acdream/docs/plans/2026-07-26-modern-runtime-slice-j7.md
Erik b8c90c1959 docs(runtime): record J7 root cutover gates
Capture the exact production rollback, complete automated evidence, connected route results, and the still-active physical-display acceptance without declaring J7 closed early.

Co-authored-by: OpenAI Codex <codex@openai.com>
2026-07-26 19:29:18 +02:00

239 lines
11 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:** AUTOMATED GATES COMPLETE — PHYSICAL-DISPLAY VISUAL GATE 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
**Complete 2026-07-26 at
`ce41efb9e5938f79a7580476b949d172f52a1e69`.**
- 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.
Result: production `GameWindow` constructs and stores one `GameRuntime`.
Every App composition record receives that root and borrows its session,
clock, environment, transit, identity, gameplay, entity, and movement
children. The former App view/event reconstructions are deleted. Source guards
prove that no production App site constructs an independent Runtime child.
### J7.3 — one shutdown transaction
**Complete 2026-07-26 in the same coherent production cutover
`ce41efb9e5938f79a7580476b949d172f52a1e69`.** J7.2 and J7.3 are one
bisectable ownership change because publishing the root without replacing the
old child-by-child shutdown would create two incompatible lifetime graphs.
- 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.
Result: ingress quiesces the root session, App retires every graphical
borrower, and only then releases the graphical host lease and disposes the
root. Construction rollback and shutdown-fault tests prove the borrowed root
is never disposed by App rollback and that the terminal root ledger converges
without route, publication, entity, physics, gameplay, transit, session, or
host-lease debt.
### J7.4 — validation and closeout
**Automated portion complete 2026-07-26; physical-display visual acceptance
is active.**
- 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.
Automated evidence:
- 383 focused Runtime tests pass.
- 3,717 App tests pass / 3 skip.
- Release solution build passes.
- 8,661 complete Release tests pass / 5 skip.
- Exact-binary lifecycle/reconnect report
`logs/connected-world-gate-20260726-190919/report.json` passes at the exact
production SHA. The capped process crosses six checkpoints in 242.324
seconds; the fresh uncapped reconnect completes in 61.332 seconds. Both exit
gracefully. All seven checkpoints retain zero host projections, pending host
acknowledgements, live teardowns, and landblock retirements.
- Exact-binary canonical route
`logs/connected-r6-soak-20260726-191605.report.json` passes all nine
destinations, movement, jump, combat, portal, revisit, and graceful-exit
gates. Against the J5.7 canonical baseline, median turn CPU/GPU/update p95
improves from 22.9/9.7/2.3 ms to 16.4/1.3/0.7 ms; turn allocation p50
improves from 5,812.9 to 75.1 KiB. Median stationary CPU/GPU/update p95
improves from 21.4/7.0/1.3 ms to 15.2/1.1/0.6 ms. Peak working set falls
from 2,326.8 to 1,953.2 MiB while peak private bytes remain effectively flat
at 1,732.1 MiB.
- Captured physical-display login, facility-hub, Holtburg-after-dungeon, and
reconnect frames are intact. The live user gate covers radar, paperdoll,
near/distant Use, combat facing, `/ls`, spell recall, portal tunnel, and
portal exit before J7 is declared closed.
- No AC behavior changed and the divergence audit found no new row to add.
## 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
```
J7.2/J7.3 exact rollback:
```text
git revert ce41efb9e5938f79a7580476b949d172f52a1e69
```
No compatibility owner, service locator, asynchronous command queue, timeout,
forced-ready path, or alternate headless behavior is permitted.