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>
14 KiB
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 F–L, 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:
RuntimeLiveSessionNoWindowTestsproves a direct session can connect, enter, and stop.RuntimeSimulationFixtureHostTestsproves movement, use, attack, cast, and projectile behavior over separately constructed Runtime owners.RuntimeWorldTransitDirectHostTestsproves login, portal, cancellation, and host acknowledgements over a separately constructed transit owner.GameRuntimeTestsproves 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
LiveSessionHostborrowingGameRuntime.Session; - one deterministic
ILiveSessionOperationsfixture with a realWorldSessionand 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:
- reset the root's canonical transit, communication, inventory, action, character, movement, object-table, and other per-generation state in the existing accepted order;
- call
RuntimeEntityObjectLifetime.BeginSessionClear()exactly once and expose the returned exact-incarnation retirement set to one borrowed host retirement boundary; - 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;
- require
CompleteSessionClearIfConverged()before clearing the canonical player identity and permitting a new generation; - 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:
- Construct the root and host; capture the empty checkpoint.
- Start generation 1 through
LiveSessionHost. - Bind inbound before connect, select the first fixture character, install exact local identity, enter world, and activate outbound commands.
- 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.
- 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.
- Drive one accepted teleport destination through typed destination readiness, materialization, host projection acknowledgements, world-visible acknowledgement, and completion.
- Capture and compare the ordered Runtime event/checkpoint trace.
- Stop generation 1; prove the old inbound and outbound routes are inert.
- Reconnect as generation 2 in the same process.
- 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.
- 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.Runtimerather 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