acdream/docs/plans/2026-07-26-modern-runtime-slice-j8.md
Erik 953c469cac docs(runtime): close Slice J and activate Slice K
Record the shared graphical/no-window reset architecture, deterministic lifecycle evidence, exact rollback point, and synchronized project guidance before beginning the Linux headless host.

Co-authored-by: Codex <noreply@openai.com>
2026-07-27 01:01:41 +02:00

14 KiB
Raw Blame History

Modern runtime Slice J8 — no-window integration and Slice J closeout

Status: COMPLETE 2026-07-27 — SLICE J CLOSED Parent: 2026-07-25-modern-runtime-slice-j.md, J8 Authorization: the user approved Slices FL, including the J gameplay-owner gates, on 2026-07-24 Purpose: prove that the exact GameRuntime graph now used by the graphical client can run a complete deterministic client lifecycle without App, a window, rendering, retained UI, audio, or backend assemblies.

1. Entry state

J7.1 created the root at 96ddd165. J7.2/J7.3 cut the graphical host and shutdown transaction over to it at ce41efb9e5938f79a7580476b949d172f52a1e69. Focused, complete Release, connected lifecycle/reconnect, and canonical nine-stop automated gates pass. The user accepted J7's physical-display radar, paperdoll, Use/approach, combat-facing, and both-recall matrix on 2026-07-27. J8 implementation may begin from this accepted checkpoint.

Existing direct tests prove the individual pieces, but not the complete root:

  • RuntimeLiveSessionNoWindowTests proves a direct session can connect, enter, and stop.
  • RuntimeSimulationFixtureHostTests proves movement, use, attack, cast, and projectile behavior over separately constructed Runtime owners.
  • RuntimeWorldTransitDirectHostTests proves login, portal, cancellation, and host acknowledgements over a separately constructed transit owner.
  • GameRuntimeTests proves root construction, isolation, lazy events, leases, rollback, and terminal disposal.

J8 replaces those disconnected proofs with one end-to-end root-host proof. It does not remove the focused tests.

2. Fixed boundary

The integration host lives in AcDream.Runtime.Tests and references only AcDream.Runtime and its existing transitive Core/Core.Net/Content contracts. It is a test host, not the Slice-K CLI.

It constructs:

  • one GameRuntime;
  • one explicit no-window host lease;
  • one LiveSessionHost borrowing GameRuntime.Session;
  • one deterministic ILiveSessionOperations fixture with a real WorldSession and in-memory transport;
  • one generation-scoped inbound route;
  • one generation-scoped outbound command route;
  • one immutable fixture-content catalog for spell and world metadata;
  • one RuntimeTraceRecorder.

It must not construct an App adapter, duplicate entity directory, duplicate object table, duplicate gameplay owner, second clock, second transit owner, or second session controller.

Canonical per-generation reset contract

The audit found one production seam that must land before the direct host can prove reconnect honestly. GameRuntime owns every canonical per-session child, but the graphical LiveSessionResetManifest currently invokes those children one by one and interleaves them with App-only teardown. A no-window host that copied that list would create a second lifecycle definition and would not prove the Slice-K host can reuse the graphical runtime.

J8 therefore adds one Runtime-owned, retryable generation-reset transaction. The exact public contract has these phases:

  1. reset the root's canonical transit, communication, inventory, action, character, movement, object-table, and other per-generation state in the existing accepted order;
  2. call RuntimeEntityObjectLifetime.BeginSessionClear() exactly once and expose the returned exact-incarnation retirement set to one borrowed host retirement boundary;
  3. let the graphical host retire App render/physics/animation projections and drain their queued removals, while the no-window host immediately retires the same canonical records without constructing projections;
  4. require CompleteSessionClearIfConverged() before clearing the canonical player identity and permitting a new generation;
  5. retain every incomplete suffix after callback failure so the same reset can be retried without replaying a completed retirement.

The host boundary acknowledges projection retirement only. It owns no canonical dictionary, reset cursor, generation number, or cleanup order. App-only mouse capture, retained UI, camera, particle visibility, renderer, audio, input, and diagnostics remain outside the Runtime transaction. The graphical LiveSessionResetManifest invokes the Runtime transaction at its existing projection-safe point; NoWindowGameRuntimeHost invokes that same transaction with an immediate canonical-only acknowledgement. There is no test-only production injection API and no alternate reset manifest.

The host applies already-decoded deterministic packets through the same Runtime owner APIs that the graphical session route uses. Core.Net parser correctness remains covered by Core.Net wire fixtures; J8 verifies ownership, ordering, commands, state, generation, and teardown after decode. Test reflection may raise a WorldSession event only where the public event source deliberately has no injection API; no production test-only hook is added.

3. Scenario and exact ordering

One canonical scenario runs in this order:

  1. Construct the root and host; capture the empty checkpoint.
  2. Start generation 1 through LiveSessionHost.
  3. Bind inbound before connect, select the first fixture character, install exact local identity, enter world, and activate outbound commands.
  4. Deliver decoded inbound fixtures:
    • local-player CreateObject;
    • one hostile creature;
    • one usable world object;
    • one container and one inventory item;
    • one inventory/container mutation;
    • one system chat line and one local speech line;
    • one vital/character update;
    • one environment/time update.
  5. Advance the instance clock and execute through the root's exact owners:
    • movement;
    • selection plus use;
    • combat mode plus attack;
    • learned-spell cast;
    • one projectile simulation commit.
  6. Drive one accepted teleport destination through typed destination readiness, materialization, host projection acknowledgements, world-visible acknowledgement, and completion.
  7. Capture and compare the ordered Runtime event/checkpoint trace.
  8. Stop generation 1; prove the old inbound and outbound routes are inert.
  9. Reconnect as generation 2 in the same process.
  10. Reuse one server GUID with a new incarnation; prove no generation-1 identity, command, packet, event sequence, inventory, physics, or portal state leaks into generation 2.
  11. Stop, release the no-window lease, dispose the root, and require GameRuntimeOwnershipSnapshot.IsConverged.

The fixture trace records lifecycle, entity, inventory, chat, movement, portal, command, and checkpoint rows. Sequence numbers must be strictly increasing within a generation and restart only when the generation changes.

4. Execution

J8.1 — one direct root host

Complete at a9a822f2. RuntimeGenerationReset is the single retryable canonical-generation reset transaction. Graphical App reset borrows that transaction and retains only its presentation stages; the no-window host uses the same Runtime root and reset owner directly.

  • Add the Runtime-owned generation-reset transaction and its narrow borrowed host-retirement acknowledgement.
  • Replace the child-by-child canonical portions of App's reset bindings with that transaction while preserving every App-only stage and the current projection-before-identity order.
  • Prove first reset, callback-fault retry, duplicate reset, and populated-root reconnect converge without replaying completed entity retirement.
  • Add a reusable test-only NoWindowGameRuntimeHost.
  • Move the existing J5 direct-host scenario onto host.Runtime rather than separately constructing six owners.
  • Borrow root identity, session, entity/object, inventory, character, communication, action, movement, environment, transit, clock, and event source.
  • Acquire and release one named host lease.
  • Prove the test assembly/process loads no App, UI, Silk.NET, OpenAL, Arch, ImGui, or renderer/audio/window type.

Gate: graphical and no-window session reset use the same Runtime transaction; the direct root host constructs, captures a checkpoint, resets a populated generation, and converges without a presentation assembly or duplicate owner.

J8.2 — deterministic transport/content lifecycle

Complete at a9a822f2. NoWindowGameRuntimeHost drives the production root through connect, enter, decoded state, movement, use, combat, casting, projectile work, portal completion, stop, reconnect, stale-route rejection, GUID reuse, and terminal convergence.

  • Build deterministic session operations and in-memory transport.
  • Bind the exact session lifecycle order: reset → attach inbound → connect → select identity → enter → activate outbound.
  • Install immutable spell/world fixture metadata before its dependent packet.
  • Route decoded entity, object, inventory, chat, character, environment, and transit fixtures into the root.
  • Execute movement, use, attack, cast, and projectile work through root-owned state.
  • Complete one portal using the same typed host acknowledgement contract as App.
  • Stop and reconnect, then verify generation isolation and GUID reuse.

Gate: one normalized golden trace proves all state and commands share the same root, accepted ordering is stable, and old-generation routes are inert.

J8.3 — cancellation, faults, isolation, and credentials

Complete at a9a822f2. Focused gates cover reset retry/no-replay, portal cancellation before and after readiness, observer failure containment, two simultaneous isolated roots, stale-generation routes, and credential-safe traces.

  • Cancel during connect, after inbound attach, during portal readiness, and with a host acknowledgement pending.
  • Inject route-construction, route-detach, observer, projection acknowledgement, and terminal callback failures.
  • Retry the exact retained suffix and require convergence.
  • Run two roots simultaneously with different credentials, clocks, GUIDs, inventory, chat, combat, spell, projectile, and portal state.
  • Assert logs contain endpoint/user context only where intended and never contain the password, credential record, or exception text that embeds it.
  • Prove a disposed/old route cannot mutate the new generation.

Gate: every fault converges; two roots remain isolated; diagnostics are credential-safe.

J8.4 — complete Slice J gate

Complete. The exact committed binary passed:

  • 395/395 Runtime tests;
  • 3,731 App tests / 3 skips;
  • 8,696 complete-solution tests / 5 intentional skips;
  • connected lifecycle/reconnect: logs/connected-world-gate-20260727-004418/report.json;
  • canonical nine-stop route: logs/connected-r6-soak-20260727-004942.report.json;
  • the already accepted J7 physical-display matrix.

The no-window process loads no App, UI, renderer, audio, Silk.NET, OpenAL, Arch, or ImGui assembly. The dependency and divergence audits found no new retail deviation. Retail chat-history research also confirmed that session end does not clear the bounded transcript: CPlayerSystem::OnEndCharacterSession at 0x00562870 reinitializes the character session, while the explicit ClientCommunicationSystem::DoClear at 0x0056E600 owns chat-buffer clearing.

  • Run focused Runtime tests.
  • Run the Release solution build.
  • Run the complete Release suite.
  • Run exact-binary connected graphical lifecycle/reconnect.
  • Run the canonical graphical nine-stop route.
  • Reconfirm the accepted J7 physical-display matrix.
  • Audit dependency closure, presentation assembly loads, duplicate constructors, mutable statics, retail divergences, and teardown ledgers.
  • Update architecture, code structure, milestones, roadmap, parent and umbrella plans, AGENTS/CLAUDE, and durable memory.

Gate: graphical and no-window hosts use the same root and owner graph; packet and command ordering remains stable; terminal ownership converges; no presentation/backend assembly enters the direct process. Slice J is then closed and Slice K may add the Linux multi-session CLI and scheduler without extracting gameplay again.

5. Adversarial matrix

  • missing credentials and no characters;
  • connect failure before and after route attachment;
  • duplicate Start, stale Start, Stop, and Reconnect generations;
  • inbound packet before selection and after Stop;
  • command before world entry and after route retirement;
  • duplicate CreateObject and GUID reuse across reconnect;
  • observer throws during entity, inventory, chat, command, movement, or portal dispatch;
  • generation reset fails before host retirement, during one projection retirement, during the drain acknowledgement, and after canonical convergence but before identity clear;
  • reset retry does not replay an already retired canonical incarnation;
  • route creation succeeds but activation fails;
  • detach throws once, then succeeds;
  • portal cancellation before readiness, after readiness, and with each host acknowledgement outstanding;
  • projectile projection callback throws;
  • host lease retained during root disposal;
  • root terminal disposal retries after each stage;
  • two roots use the same server GUID without sharing local IDs;
  • password-shaped marker absent from trace, logs, exception messages, and test output;
  • App/UI/Silk/OpenAL/Arch/ImGui assemblies absent from the loaded-assembly set.

6. Non-goals

  • No Linux executable or bot scheduler; those are Slice K.
  • No hidden graphical process.
  • No renderer, audio, UI, particle, camera, selection-marker, or portal-tunnel stub.
  • No new network parser or alternate packet order.
  • No asynchronous command queue or extra frame boundary.
  • No gameplay-state mirror, facade dictionary, service locator, or test-only production injection API.
  • No retail behavior change and therefore no divergence row unless the audit discovers a pre-existing unregistered difference.

7. Commit and rollback discipline

J8 implementation landed as one test/integration closeout commit after the J7 visual entry gate. Its exact rollback is:

git revert a9a822f206cc6021bc099988144488f3bd7c397b

J8 did not modify the J7 rollback point:

git revert ce41efb9e5938f79a7580476b949d172f52a1e69