acdream/docs/plans/2026-07-25-modern-runtime-slice-j2.md
Erik 9496c01be1 docs(runtime): close J2 session lifetime gate
Record the canonical Runtime session/transport cutover, exact rollback, full Release evidence, and exact-binary lifecycle acceptance. Advance the active execution pointer and durable memory to J3 identity and object ownership.

Validated by the existing 79 Runtime tests, 3,776 App tests with three skips, 8,428 complete Release tests with five skips, and logs/connected-world-gate-20260725-193936/report.json.

Co-authored-by: Codex <codex@openai.com>
2026-07-25 19:46:47 +02:00

203 lines
7.7 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 J2 — session lifetime and ordered transport
**Status:** COMPLETE 2026-07-25
**Parent:** `2026-07-25-modern-runtime-slice-j.md`, J2
**Production base:** `854d9e9cd13092bd5aaa3cf025d73eeb4600e9f8`
**Production commit:** `75930787741db40a83eab8663e4464dce8d687ba`
**J1 documentation:** `f84624b1e9b83f928debdbe65a5a1576b999ee34`
## 1. Objective
Move the one canonical live-session lifetime, transport generation, ordered
inbound subscription owner, and route activation/teardown transaction from
`AcDream.App` into `AcDream.Runtime`.
The move is structural. It must preserve the exact current connect, character
selection, EnterWorld, packet dispatch, command activation, tick, reconnect,
logout, and retryable cleanup order. App remains the graphical host and
supplies credentials, retained-UI/domain callbacks, the graphical command
projection, and presentation reset acknowledgements.
## 2. Fixed ownership after J2
`AcDream.Runtime` owns:
- the exact `WorldSession` generation and its connect/enter/tick/dispose
transaction;
- generation validation and live-session lifecycle state;
- the serial route lifecycle: attach inbound before Connect, activate outbound
only after EnterWorld, make commands inert before detaching inbound;
- the retryable teardown suffix and exact acknowledgement stages;
- the complete ordered inbound subscription set and all Core/Core.Net event
wiring;
- connection options with no dependency on App `RuntimeOptions`;
- the production endpoint/session operations and deterministic operations
seam used by no-window tests.
`AcDream.App` owns:
- conversion from `RuntimeOptions` into immutable Runtime connection options;
- graphical reset, identity, layout, toolbar, settings, dialog, and
presentation callbacks;
- the `ICommandBus` projection needed by the current UI until gameplay command
groups move in J4/J5;
- graphical source adapters for existing App interfaces while those consumer
groups await their own J3J6 migrations.
The App adapters borrow the Runtime session and command route. They do not
dispose the transport, track another generation, retain a second active route,
or mirror in-world state.
## 3. Type and file migration
### J2.1 — Runtime lifetime contracts
Add under `src/AcDream.Runtime/Session/`:
- `LiveSessionConnectOptions`
- `RuntimeLiveSessionController`
- `RuntimeLiveSessionHost`
- `RuntimeLiveSessionBinding`
- `IRuntimeLiveSessionLifecycleHost`
- `IRuntimeLiveSessionOperations`
- `IRuntimeLiveSessionEventRoute`
- `IRuntimeLiveSessionCommandRoute`
- the Runtime-only lifecycle host and retryable route rollback owner
The host implements the J1 `IRuntimeSessionCommands` surface directly. Start,
Reconnect, and Stop are generation-gated at that owner; the J1 App command
adapter no longer translates a second session result or invents teardown
stages.
`RuntimeLiveSessionController` exposes only borrowed state:
`CurrentSession`, `IsInWorld`, `Generation`, and `Tick`. It carries no UI
command bus and implements no App interface.
### J2.2 — Ordered inbound route move
Move the existing `LiveSessionEventRouter` and
`LiveSessionSubscriptionSet` into Runtime without changing subscription order:
1. object/property table wiring;
2. combat-state wiring;
3. entity and environment messages;
4. inventory/item state;
5. character/spell state;
6. social/chat state.
The existing accepting gate, reverse-order retryable unsubscribe, construction
rollback, and reentrant-cleanup rejection remain line-for-line. The route
bindings remain delegates over current owners for J2; their owner groups move
in J3/J4.
### J2.3 — Graphical host adapter
Replace the App lifetime implementation with focused adapters:
- a session source bridge for existing App `IsInWorld`, `CurrentSession`,
frame-tick, and retained-UI seams;
- a graphical route factory that constructs the moved Runtime event router and
the current App command projection;
- a single active-command projection whose retained UI reference becomes
inert before route detachment;
- graphical lifecycle callbacks for reset, selection, EnterWorld, connecting,
and connected presentation.
Delete the superseded App controller, lifecycle-host logic, subscription
owner, and route rollback implementation in the same commit. Do not keep
delegating compatibility copies of lifetime state.
### J2.4 — Test ownership
Move controller, host, lifecycle, event-router, and subscription tests into
`AcDream.Runtime.Tests`. Preserve every existing call-order, duplicate start,
reentrant reconnect/stop/dispose, rollback-failure, stale generation, malformed
packet, and retryable teardown case.
Keep graphical command-projection and App bridge tests in
`AcDream.App.Tests`. Add assertions that:
- the bridge has no generation or in-world backing fields;
- the command projection has at most one borrowed active route;
- stale command references are inert after replacement;
- press-time graphical input still reaches the same owner synchronously.
Add a Runtime-only construction test that creates the production lifetime
graph with deterministic transport operations, enters and exits a session,
and verifies that App, UI, Silk.NET, OpenAL, Arch, and ImGui assemblies are
not loaded.
## 4. Exact behavioral order
Start:
1. advance generation;
2. drain any retired teardown suffix;
3. reset the supplied host when required;
4. validate enabled state and credentials;
5. resolve endpoint and create the one `WorldSession`;
6. construct and attach all inbound routes;
7. publish connecting state;
8. Connect and receive the character list;
9. publish connected state;
10. select the first available character and publish identity;
11. EnterWorld;
12. activate the outbound command route;
13. mark in-world and publish entered-world presentation.
Stop/replacement:
1. advance generation and reject further old-generation commands;
2. make the active graphical command route inert;
3. detach inbound subscriptions in reverse order;
4. dispose `WorldSession`, preserving its graceful F653/disconnect behavior;
5. detach the exact host/session pair;
6. reset domain and presentation state;
7. acknowledge only the completed stages.
If a stage throws, the exact remaining suffix is retained. A retry never
replays a completed stage.
## 5. Acceptance
Focused:
- Runtime lifetime and event-route suites all pass after moving from App;
- App graphical bridge and command projection suites pass;
- J1 normalized traces are identical before and after the move;
- source/dependency guards find no Runtime presentation/backend dependency;
- Runtime-only session construction and teardown load no forbidden assembly.
Complete:
- `dotnet build AcDream.slnx -c Release`;
- full Release solution tests;
- connected capped login/six-checkpoint/logout plus fresh uncapped reconnect
on the exact binary;
- both processes exit gracefully;
- no packet/order, reveal, route, teardown, or resource-convergence failure.
J2 changes no pixels, input feel, or retail algorithm. A separate user visual
pause is therefore not required unless the connected gate exposes a
presentation symptom.
## 6. Result and rollback
All focused and complete gates passed: 79 Runtime tests, 3,776 App tests with
three skips, 8,428 complete Release tests with five skips, and the exact-binary
seven-checkpoint connected lifecycle/reconnect route. Both processes exited
gracefully; every checkpoint had zero render-shadow mismatch and zero pending
render delta. Evidence:
[`../research/2026-07-25-slice-j2-session-lifetime-closeout.md`](../research/2026-07-25-slice-j2-session-lifetime-closeout.md).
Exact J2 rollback:
```text
git revert 75930787741db40a83eab8663e4464dce8d687ba
```
J1 remains independently reversible:
```text
git revert 854d9e9cd13092bd5aaa3cf025d73eeb4600e9f8
```