diff --git a/AcDream.slnx b/AcDream.slnx
index 238ab20c..5fc96499 100644
--- a/AcDream.slnx
+++ b/AcDream.slnx
@@ -8,6 +8,7 @@
+
@@ -22,6 +23,7 @@
+
diff --git a/docs/architecture/acdream-architecture.md b/docs/architecture/acdream-architecture.md
index 4bba7034..28f6fc32 100644
--- a/docs/architecture/acdream-architecture.md
+++ b/docs/architecture/acdream-architecture.md
@@ -202,6 +202,11 @@ src/
WorldSession.cs -> done (wire-compatible with ACE)
NetClient.cs -> done
Messages/ -> done (CreateObject, MoveToState, etc.)
+
+ AcDream.Runtime/ presentation-independent client kernel boundary
+ RuntimeAssemblyMarker.cs -> J0 dependency boundary; owner moves start after I6/I7
+ -> may reference Core, Core.Net, Content, and Plugin.Abstractions only
+ -> must never reference App, UI, Silk.NET, OpenAL, Arch, or ImGui
AcDream.Plugin.Abstractions/ Layer 5: plugin interfaces
IAcDreamPlugin.cs -> done
diff --git a/docs/architecture/code-structure.md b/docs/architecture/code-structure.md
index a8812cd0..58dea220 100644
--- a/docs/architecture/code-structure.md
+++ b/docs/architecture/code-structure.md
@@ -166,6 +166,7 @@ Today:
- `tests/AcDream.Core.Tests/` ← `src/AcDream.Core/`
- `tests/AcDream.Core.Net.Tests/` ← `src/AcDream.Core.Net/`
+- `tests/AcDream.Runtime.Tests/` ← `src/AcDream.Runtime/`
- `tests/AcDream.UI.Abstractions.Tests/` ← `src/AcDream.UI.Abstractions/`
- `tests/AcDream.App.Tests/` ← `src/AcDream.App/`
diff --git a/docs/plans/2026-07-24-modern-runtime-architecture.md b/docs/plans/2026-07-24-modern-runtime-architecture.md
index 87a1ec2a..029e850c 100644
--- a/docs/plans/2026-07-24-modern-runtime-architecture.md
+++ b/docs/plans/2026-07-24-modern-runtime-architecture.md
@@ -2,8 +2,11 @@
**Date:** 2026-07-24
-**Status:** Slices A–H and I0–I3 are complete. Slices F–L were explicitly
-approved 2026-07-24; Slice I4 is active.
+**Status:** Slices A–H are complete. Slice I6's flat-authoritative production
+cutover is committed and awaits the final user collision/visual gate before
+parsed-graph deletion. Slices F–L were explicitly approved 2026-07-24. Slice
+J0's dependency-boundary preparation is complete without moving gameplay
+owners. J1 remains behind the I6/I7 user collision/visual closeout.
**Scope:** Reconcile and sequence the existing Modern Pipeline (`MP`) and
Linux/headless (`LH`) tracks using the 2026-07-24 connected performance audit.
@@ -499,6 +502,41 @@ It exposes:
- Deterministic `Tick`.
- Retryable, complete shutdown.
+#### 9.2.1 Structural teardown protocol
+
+Every graphical or headless host follows one retryable, generation-scoped
+teardown transaction. New runtime owners register through the same
+`CompositionAcquisitionScope` lease discipline already used by the graphical
+composition root; release order is encoded by leases and acknowledgements,
+never remembered by callers.
+
+1. **Cancel scheduler generations.** Make commands inert, cancel the active
+ session/runtime generation, stop new receive publication, and prevent any
+ timer, bot, plugin, or worker callback from creating more work for it.
+2. **Drain or poison journals and queues.** Detach inbound producers, drain
+ already-accepted ordered events through the generation boundary, then
+ poison every command/event/delta queue so delayed callbacks fail against
+ their exact generation instead of entering a replacement session.
+3. **Unpublish presentation.** The graphical host consumes the final ordered
+ withdrawals and acknowledges that the render scene, retained gameplay UI,
+ audio/effect projections, selection, radar, and private viewports no longer
+ expose the runtime generation. Headless hosts acknowledge this stage
+ immediately because they construct no presentation owners.
+4. **Release residency after fences.** Withdraw content owners, finish
+ streaming/landblock retirement, and allow GPU-backed stores to retire only
+ after their existing frame-flight fences signal. A failed fence or release
+ retains the exact unfinished lease and resumes without replaying completed
+ stages.
+5. **Release the shared `ContentStore` last.** Session-scoped collision/content
+ leases go away before the runtime instance. The immutable mapped content
+ store outlives every runtime and presentation host and is disposed only by
+ the process host after all registered sessions have acknowledged teardown.
+
+Logout, session reset, mid-portal disconnect, reconnect replacement, ordinary
+window close, and construction rollback all use this protocol. No stage may
+clear another generation's state, and no teardown failure may be converted
+into a best-effort purge.
+
### 9.3 Hosts
`GraphicalGameHost` provides input, camera, rendering, UI, audio, frame pacing,
diff --git a/docs/plans/2026-07-25-modern-runtime-slice-j.md b/docs/plans/2026-07-25-modern-runtime-slice-j.md
new file mode 100644
index 00000000..863eccd9
--- /dev/null
+++ b/docs/plans/2026-07-25-modern-runtime-slice-j.md
@@ -0,0 +1,230 @@
+# Modern runtime Slice J — presentation-independent runtime
+
+**Status:** J0 COMPLETE — lifetime plan, project boundary, and dependency
+guards; J1 waits for the Slice I6/I7 user collision/visual closeout
+**Parent:** `2026-07-24-modern-runtime-architecture.md`, Slice J
+**Authorization:** the user approved Slices F–L, including the otherwise-frozen
+Slice J gameplay-owner moves, on 2026-07-24
+**Purpose:** move the existing authoritative client kernel into a
+presentation-independent assembly without creating a second world, changing
+retail behavior, or making the graphical host a special case.
+
+Slice J is a lifetime-group campaign, not one large move. Each sub-slice keeps
+the graphical client on the same owner instance, establishes host parity, and
+deletes the replaced App production path before the next group moves.
+
+## 1. Fixed invariants
+
+1. `LiveEntityRuntime` remains the sole server-GUID/incarnation owner. There is
+ never a second GUID map or synchronized gameplay world.
+2. Runtime types do not reference `AcDream.App`, either UI assembly, Silk.NET,
+ OpenAL, Arch, ImGui, a native window, or an OpenGL resource.
+3. App projection state is keyed by runtime-issued local entity identity plus
+ incarnation. It may not recover or mirror server GUID ownership.
+4. The accepted update order, packet ordering, timestamp gates, outbound
+ cadence, and retail-shaped gameplay algorithms do not change during the
+ extraction.
+5. Contracts expose borrowed/immutable views, typed commands, and ordered
+ deltas. They do not expose App render components or deep per-frame object
+ graphs.
+6. All clocks, queues, random sources, diagnostics identity, plugin behavior,
+ and mutable caches that can differ between sessions are instance-scoped.
+7. Immutable prepared content may be shared. Session state and mutable query
+ scratch may not.
+8. Every new owner participates in the structural teardown protocol in parent
+ plan §9.2.1 through acquisition leases and exact acknowledgements.
+9. A headless construction path is proved after every coherent move. “No
+ window” means no App, Silk, OpenAL, retained UI, particle, or render assembly
+ is loaded—not a hidden graphical process.
+10. The user collision/visual gate for Slice I6 still controls parsed-graph
+ deletion. J0 may land independently; gameplay-owner moves begin only after
+ the active I6/I7 closeout has reconciled the final collision owner shape.
+
+## 2. Target dependency direction
+
+```text
+AcDream.App ───────────────► AcDream.Runtime
+AcDream.Headless (Slice K) ─► AcDream.Runtime
+ ├──► AcDream.Core.Net
+ ├──► AcDream.Core
+ ├──► AcDream.Content
+ └──► AcDream.Plugin.Abstractions
+
+AcDream.Runtime -X► AcDream.App / AcDream.UI.* / Silk.NET / OpenAL / Arch
+```
+
+Runtime-emitted entity events contain incarnation, transform, flags, and
+property deltas only. An App-side projection adapter translates them into
+`IRenderScene` journal operations. Render vocabulary never enters Runtime.
+
+## 3. Teardown transaction
+
+The exact order is:
+
+1. cancel scheduler/session generations and make commands inert;
+2. detach producers, drain accepted ordered events, and poison queues;
+3. withdraw and acknowledge graphical presentation;
+4. retire session residence and GPU-backed owners through existing fences;
+5. dispose the process-owned immutable `ContentStore` only after every runtime
+ and host has completed.
+
+Completed stages never replay. Failure retains the exact remaining suffix.
+Logout, reset, mid-portal disconnect, reconnect replacement, construction
+rollback, and native close all traverse the same transaction.
+
+## 4. Execution slices
+
+### J0 — boundary, plan, and dependency enforcement
+
+**Completed 2026-07-25.**
+
+- Add `AcDream.Runtime` and `AcDream.Runtime.Tests`.
+- Permit references only to Core, Core.Net, Content, and Plugin.Abstractions.
+- Add App → Runtime as the future host dependency; Runtime never references
+ App.
+- Add direct-reference, dependency-closure, source-project, and assembly-load
+ guards that fail if a presentation/backend dependency enters Runtime.
+- Add only an assembly boundary marker; do not introduce a facade
+ `GameRuntime`, mirror state, or move behavior in J0.
+- Pin this lifetime-group plan and parent-plan teardown protocol.
+
+Gate: Release build and full tests pass; the Runtime test process loads no App,
+UI, Silk, OpenAL, Arch, or ImGui assembly; graphical behavior is byte-for-byte
+unchanged because no runtime path changed.
+
+Evidence: four focused dependency tests pass, the Release solution builds with
+zero errors, and the complete Release suite passes 8,406 tests with five
+pre-existing skips. The exact rollback commit is recorded below after landing.
+
+### J1 — read, command, event, clock, and lifecycle contracts
+
+- Define `IGameRuntimeView`, typed command interfaces, ordered event/delta
+ records, instance clock, lifecycle states, generation tokens, and teardown
+ acknowledgements.
+- Build App adapters over the current owners first. Adapters borrow; they do
+ not copy mutable collections or own lifetime.
+- Add a normalized parity trace of accepted inbound events, runtime commands,
+ state revisions, and lifecycle edges.
+- Prove press-time graphical input reaches the same current owners through the
+ command contract with no extra frame of latency.
+
+Gate: adapter and direct-host traces are identical over deterministic session,
+entity, inventory, chat, movement, and portal fixtures; no canonical owner has
+moved yet.
+
+### J2 — session lifetime and ordered transport group
+
+- Remove App presentation dependencies from `LiveSessionController`,
+ `LiveSessionHost`, lifecycle host, event router, and command router.
+- Move the same owner instances into Runtime with Core.Net transport and
+ instance-scoped clocks/queues.
+- Preserve bind-before-connect, publish-after-EnterWorld, exact generation
+ rechecks, receive ordering, ack placement, graceful F653/disconnect, and
+ retryable replacement.
+- Let App provide only endpoint credentials, presentation bindings, and
+ graphical lifecycle acknowledgements.
+
+Gate: connected login/logout/reconnect and malformed/reentrant lifecycle suites
+produce the same packet/order trace; no-window construction can connect and
+disconnect without loading App or a backend.
+
+### J3 — canonical identity, properties, and object-table group
+
+- Strip renderer, particle, Wb, and streaming components from the canonical
+ record into an App projection store keyed only by local identity/incarnation.
+- Move `LiveEntityRuntime`, accepted spawn/state/property timestamps,
+ `ClientObjectTable`, container/inventory indices, vitals, enchantments,
+ spell state, target/combat state, and their exact teardown into Runtime.
+- Emit ordered create/update/rebucket/hidden/withdraw/delete deltas.
+- Keep DAT-backed visual hydration, render registrations, effects, lights,
+ paperdoll, selection markers, and radar projections in App.
+
+Gate: GUID reuse, equal-generation updates, parent/child identity,
+inventory/container mutations, Hidden, delete/recreate, and portal teardown
+match current traces; App has no server-GUID ownership.
+
+### J4 — chat, inventory, magic, and gameplay-state services
+
+- Move canonical chat history/channel state, inventory transactions, spell and
+ component state, enchantments, vitals, skills/attributes, and gameplay
+ cooldown state by coherent owner groups.
+- Keep retained panel layout, text shaping, icons, paperdoll rendering, and
+ status-bar presentation in App.
+- Route plugins and future bots through the same typed command/event surface
+ as graphical UI.
+
+Gate: deterministic command/response traces and graphical ViewModel revisions
+match; no Runtime type references UI abstractions.
+
+### J5 — movement, physics, interaction, and combat group
+
+- Move presentation-free movement interpretation, authoritative/predicted
+ physics state, selection identity, approach/use transactions, combat intent,
+ projectiles, and outbound movement cadence.
+- Replace input and camera dependencies with typed commands and runtime views.
+- Keep camera, mouse look, selection markers/highlight, combat/spell bars,
+ animated pose composition, sounds, and particles in App.
+- Share immutable flat collision content while retaining per-session transition
+ scratch.
+
+Gate: bit-identical collision/trajectory fixtures, target-facing and
+auto-approach traces, outbound packet timing, combat/magic commands, and
+graphical feel gates remain unchanged.
+
+### J6 — world, portal, environment, and projection handshake
+
+- Move authoritative teleport/session cell identity, world clock, weather
+ state, and reveal-generation state required by gameplay.
+- Keep streaming publication, terrain/EnvCell rendering, portal tunnel,
+ materialization VFX, sky drawing, audio, and UI in App.
+- Define the destination-ready/withdrawal acknowledgements between Runtime and
+ the graphical or headless host without making visual readiness gameplay
+ authority.
+
+Gate: fresh login, repeated recall/portal, world edge, dungeon, reconnect, and
+mid-portal disconnect traces match; the graphical screenshots remain accepted.
+
+### J7 — one `GameRuntime` composition root
+
+- Compose all moved lifetime groups into one instance-scoped `GameRuntime`.
+- Make `GameWindow`/App own exactly one Runtime instance plus presentation
+ adapters.
+- Delete temporary direct-owner adapters and every superseded App production
+ path.
+- Register all Runtime and App projection owners with structural acquisition
+ leases and the exact teardown transaction.
+
+Gate: graphical connected lifecycle/resource routes pass with no mirrored
+state, no extra update latency, and no performance regression.
+
+### J8 — no-window integration and Slice J closeout
+
+- Build a transport/content test host that constructs Runtime directly.
+- Connect, enter world, receive chat/inventory/world updates, move, use,
+ fight/cast through deterministic fixtures, portal, log out, reconnect, and
+ tear down without loading App/Silk/OpenAL/UI.
+- Add cancellation, failure injection, same-process multiple-instance
+ isolation, credential-safe diagnostics, and zero-presentation-allocation
+ gates.
+- Update architecture, milestone, roadmap, issue/divergence ledgers, and
+ durable memory.
+
+Final gate: Release build/full tests, connected graphical route, no-window
+integration, resource teardown, packet/order/timing parity, and the user visual
+matrix all pass. Slice K may then build the Linux multi-session host without
+another gameplay extraction.
+
+## 5. Commit order
+
+1. `arch(runtime): establish presentation-independent boundary`
+2. `feat(runtime): define borrowed views commands and ordered events`
+3. `refactor(runtime): move session lifetime and ordered transport`
+4. `refactor(runtime): move canonical entity and property ownership`
+5. `refactor(runtime): move gameplay state services`
+6. `refactor(runtime): move movement physics interaction and combat`
+7. `refactor(runtime): separate world authority from presentation`
+8. `refactor(runtime): compose one graphical game runtime`
+9. `test(runtime): close no-window parity and teardown`
+
+Each commit is independently buildable and retains an exact rollback command
+in this plan before its connected gate.
diff --git a/src/AcDream.App/AcDream.App.csproj b/src/AcDream.App/AcDream.App.csproj
index bba735d3..68338dd5 100644
--- a/src/AcDream.App/AcDream.App.csproj
+++ b/src/AcDream.App/AcDream.App.csproj
@@ -39,6 +39,7 @@
+
diff --git a/src/AcDream.Runtime/AcDream.Runtime.csproj b/src/AcDream.Runtime/AcDream.Runtime.csproj
new file mode 100644
index 00000000..7b33b2b2
--- /dev/null
+++ b/src/AcDream.Runtime/AcDream.Runtime.csproj
@@ -0,0 +1,19 @@
+
+
+ net10.0
+ enable
+ enable
+ latest
+ true
+ AcDream.Runtime
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AcDream.Runtime/RuntimeAssemblyMarker.cs b/src/AcDream.Runtime/RuntimeAssemblyMarker.cs
new file mode 100644
index 00000000..ee784b90
--- /dev/null
+++ b/src/AcDream.Runtime/RuntimeAssemblyMarker.cs
@@ -0,0 +1,10 @@
+namespace AcDream.Runtime;
+
+///
+/// Identifies the presentation-independent runtime assembly.
+///
+///
+/// Slice J0 establishes only the dependency boundary. Runtime owners move here
+/// in coherent lifetime groups during the later Slice J steps.
+///
+internal static class RuntimeAssemblyMarker;
diff --git a/tests/AcDream.Runtime.Tests/AcDream.Runtime.Tests.csproj b/tests/AcDream.Runtime.Tests/AcDream.Runtime.Tests.csproj
new file mode 100644
index 00000000..fd27c566
--- /dev/null
+++ b/tests/AcDream.Runtime.Tests/AcDream.Runtime.Tests.csproj
@@ -0,0 +1,22 @@
+
+
+ net10.0
+ enable
+ enable
+ false
+ latest
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/AcDream.Runtime.Tests/RuntimeDependencyBoundaryTests.cs b/tests/AcDream.Runtime.Tests/RuntimeDependencyBoundaryTests.cs
new file mode 100644
index 00000000..949dc51d
--- /dev/null
+++ b/tests/AcDream.Runtime.Tests/RuntimeDependencyBoundaryTests.cs
@@ -0,0 +1,127 @@
+using System.Text.Json;
+using System.Xml.Linq;
+
+namespace AcDream.Runtime.Tests;
+
+public sealed class RuntimeDependencyBoundaryTests
+{
+ private static readonly string[] ForbiddenDependencyPrefixes =
+ [
+ "AcDream.App",
+ "AcDream.UI.",
+ "Silk.NET",
+ "OpenAL",
+ "Arch",
+ "ImGui",
+ ];
+
+ [Fact]
+ public void RuntimeAssemblyHasNoDirectPresentationOrBackendReferences()
+ {
+ var references = typeof(RuntimeAssemblyMarker).Assembly
+ .GetReferencedAssemblies()
+ .Select(static reference => reference.Name ?? string.Empty)
+ .ToArray();
+
+ Assert.DoesNotContain(references, IsForbidden);
+ }
+
+ [Fact]
+ public void RuntimeDependencyClosureHasNoPresentationOrBackendLibraries()
+ {
+ var depsPath = Path.ChangeExtension(
+ typeof(RuntimeDependencyBoundaryTests).Assembly.Location,
+ ".deps.json");
+
+ using var document = JsonDocument.Parse(File.ReadAllText(depsPath));
+ var libraries = document.RootElement
+ .GetProperty("libraries")
+ .EnumerateObject()
+ .Select(static library => LibraryName(library.Name))
+ .ToArray();
+
+ Assert.DoesNotContain(libraries, IsForbidden);
+ }
+
+ [Fact]
+ public void RuntimeProjectDeclaresOnlyApprovedProjectDependencies()
+ {
+ var repositoryRoot = FindRepositoryRoot();
+ var projectPath = Path.Combine(
+ repositoryRoot,
+ "src",
+ "AcDream.Runtime",
+ "AcDream.Runtime.csproj");
+ var project = XDocument.Load(projectPath);
+ var projectDirectory = Path.GetDirectoryName(projectPath)!;
+
+ var actualReferences = project
+ .Descendants("ProjectReference")
+ .Select(reference => reference.Attribute("Include")?.Value)
+ .Where(static include => !string.IsNullOrWhiteSpace(include))
+ .Select(include => Path.GetFullPath(Path.Combine(projectDirectory, include!)))
+ .Order(StringComparer.OrdinalIgnoreCase)
+ .ToArray();
+ var expectedReferences = new[]
+ {
+ "AcDream.Content",
+ "AcDream.Core",
+ "AcDream.Core.Net",
+ "AcDream.Plugin.Abstractions",
+ }
+ .Select(projectName => Path.Combine(
+ repositoryRoot,
+ "src",
+ projectName,
+ $"{projectName}.csproj"))
+ .Order(StringComparer.OrdinalIgnoreCase)
+ .ToArray();
+
+ Assert.Equal(expectedReferences, actualReferences);
+ Assert.Empty(project.Descendants("PackageReference"));
+ }
+
+ [Fact]
+ public void LoadingRuntimeMarkerDoesNotLoadPresentationOrBackendAssemblies()
+ {
+ _ = typeof(RuntimeAssemblyMarker).Assembly;
+
+ var loadedAssemblies = AppDomain.CurrentDomain
+ .GetAssemblies()
+ .Select(static assembly => assembly.GetName().Name ?? string.Empty)
+ .ToArray();
+
+ Assert.DoesNotContain(loadedAssemblies, IsForbidden);
+ }
+
+ private static string FindRepositoryRoot()
+ {
+ var directory = new DirectoryInfo(AppContext.BaseDirectory);
+ while (directory is not null)
+ {
+ if (File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
+ {
+ return directory.FullName;
+ }
+
+ directory = directory.Parent;
+ }
+
+ throw new DirectoryNotFoundException(
+ $"Could not find AcDream.slnx above {AppContext.BaseDirectory}.");
+ }
+
+ private static string LibraryName(string libraryIdentity)
+ {
+ var separatorIndex = libraryIdentity.IndexOf('/');
+ return separatorIndex < 0
+ ? libraryIdentity
+ : libraryIdentity[..separatorIndex];
+ }
+
+ private static bool IsForbidden(string assemblyName)
+ {
+ return ForbiddenDependencyPrefixes.Any(prefix =>
+ assemblyName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
+ }
+}