acdream/docs/research/2026-07-26-slice-j5-1-canonical-action-state.md
Erik be73bccf5a docs(runtime): close canonical action ownership
Record J5.1's exact Runtime selection, combat, and target-mode owner, its automated and connected acceptance evidence, rollback, and the J5.2 interaction-transaction boundary. Synchronize architecture, roadmap, milestones, issues, and agent handoff state.

Co-authored-by: Codex <codex@openai.com>
2026-07-26 10:54:12 +02:00

4.5 KiB

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

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.