# Slice J5.1 — canonical action state **Date:** 2026-07-26 **Production commit:** `b298f99f913249d299796e6a71f7a9b6b283ac1a` **Parent:** `docs/plans/2026-07-26-modern-runtime-slice-j5.md` ## Result Selection identity, combat mode/known target health, and retail's temporary Use/Examine/Use-Item-On-Target mode now form one presentation-independent Runtime lifetime group. `RuntimeActionState` constructs and owns the exact three mutable children. `GameWindow` owns one Runtime action root, while Program/plugin selection, retained UI, session routing, input/combat consumers, and current-runtime commands/views borrow its exact children. No production App path can construct another selection, combat, or interaction-mode owner. The old `AcDream.App.UI.InteractionState` moved to `AcDream.Runtime.Gameplay`. `ItemInteractionController` now requires the exact injected state and has no private fallback. ## Retail behavior preserved No selection, combat, or item-use algorithm changed. - `SelectionState` retains `ACCWeenieObject::SetSelectedObject @ 0x0058C2E0`: commit the changed selection and previous identities before synchronous observers, and deduplicate a same-object selection. - `CombatState.Clear` retains `ClientCombatSystem::Begin @ 0x0056A460`: session reset returns to NonCombat and clears known target health. - target-mode entry/acquisition/cancellation remains the existing `ItemHolder::UseObject @ 0x00588A80` projection. - commands remain synchronous at the existing press-time boundary; this slice adds no queue or frame of latency. ## Ownership and failure behavior - `RuntimeActionState.View` projects revisions plus selected/previous identity, combat mode, known-health count/query, and interaction mode without copying a mutable collection. - reset attempts interaction, selection, and combat suffixes even when one borrowed observer throws. - terminal disposal is failure-safe: it clears all children, detaches Runtime's internal revision subscriptions, and becomes terminal even when observers fail. - two Runtime action roots in one process remain completely isolated. - `RuntimeGameplayOwnership` now includes the action root in its combined convergence ledger. - terminal App shutdown releases UI/session borrowers before disposing the Runtime action root and then the canonical entity/object lifetime. Production source guards scan all non-Studio App sources and prove that only the Runtime owner constructs `SelectionState`, `CombatState`, or `InteractionState`. Existing Runtime dependency and assembly-load closure tests prove no App, UI, Silk.NET, OpenAL, Arch, or ImGui dependency entered the kernel. ## Automated gates All commands ran in Release: - `dotnet test tests/AcDream.Runtime.Tests/AcDream.Runtime.Tests.csproj`: 182 passed. - `dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj`: 3,779 passed / 3 fixture-generator skips. - `dotnet build AcDream.slnx -c Release`: passed. - `dotnet test AcDream.slnx -c Release --no-build --no-restore`: 8,550 passed / 5 established skips. - `git diff --check`: passed. ## Exact-binary connected gate Report: `logs/connected-world-gate-20260726-104445/report.json`. The report identifies exact source/binary commit `b298f99f913249d299796e6a71f7a9b6b283ac1a` and passes: - six capped login/outdoor/world-edge/dungeon/revisit checkpoints; - one fresh uncapped-process reconnect checkpoint; - 7/7 complete reveal/readiness checkpoints and zero invariant failures; - 245.219-second capped and 61.321-second reconnect sessions; - graceful logout and code-zero exit for both processes; - zero failures; - one expected warning covering 25 empty world-edge landblocks. The Windows session was disconnected rather than active RDP during this run, but the retained graphical route and screenshots completed. The gate is correctness/lifetime evidence, not physical-display performance evidence. ## Divergence audit This is an ownership-only port of existing retail-faithful behavior. It introduces no approximation, alternate gameplay algorithm, polling mirror, or asynchronous seam. No divergence-register row was added or retired. ## Rollback ```text git revert b298f99f913249d299796e6a71f7a9b6b283ac1a ``` Revert J5 sub-slices in reverse order. Do not revert J4 or the Slice-I flat collision cutover to mask a later J5 interaction/simulation failure. ## Next boundary J5.2 moves use/appraisal/pickup/approach transaction identity and ordered execution into Runtime. World rays, cursor/selection lighting, toasts, drag/drop visuals, and retained pending-slot drawing remain App presentation.