acdream/docs/research/2026-07-31-runtime-set-position-collision-reporting-handoff.md

12 KiB

Runtime SetPosition collision-report ownership handoff - 2026-07-31

Purpose and exact stopping point

This handoff records placement Slice 4B2 checkpoint 2: the isolated Runtime owner for retail SetPosition collision tracking and report-result semantics. The checkpoint intentionally stops before authored mover preparation, shared local-controller body publication, graphical/headless placement projection, collision-prefix quiescence, or any production SetPosition route cutover.

Production behavior is therefore unchanged by this checkpoint. The new owner is populated only by the dormant RuntimeSetPositionState and focused tests. AP-1 and AD-1 remain narrowed/open; AP-22 and AD-10 remain open.

Exact workspace

  • Worktree: C:\Users\erikn\.codex\worktrees\af5e\acdream
  • Branch: codex/port-claude-agents
  • Starting checkpoint: ec627c13 (docs(physics): hand off remaining divergence campaign)
  • This handoff belongs to the same behavior commit as the implementation.
  • No upstream is configured for this worktree branch.
  • Remotes:
    • origin: https://git.snakedesert.se/erik/acdream.git
    • github: git@github.com:eriknihlen/acdream.git

Continue in this worktree unless the user explicitly requests otherwise. AGENTS.md has an unrelated pre-existing content diff and must not be staged, restored, or rewritten as part of this checkpoint. Several other paths report line-ending/stat noise without a content diff; stage only the exact paths listed in the final commit.

Retail oracle

The complete readable oracle is 2026-07-31-runtime-set-position-collision-reporting.md. The named-retail anchors are:

  • CPhysicsObj::report_object_collision_end 0x00510A90
  • CPhysicsObj::report_environment_collision 0x00512FC0
  • CPhysicsObj::report_object_collision 0x00513060
  • CPhysicsObj::track_object_collision 0x00513F10
  • CPhysicsObj::report_collision_start 0x00513FD0
  • CPhysicsObj::report_collision_end 0x00514620
  • CPhysicsObj::handle_all_collisions 0x00514780
  • successful CPhysicsObj::SetPositionInternal(CTransition const*) 0x00515330
  • CPhysicsObj::leave_world 0x005155A0
  • placement failure in CPhysicsObj::SetPositionInternal 0x00515BD0

The source is docs/research/named-retail/acclient_2013_pseudo_c.txt; the struct authority is docs/research/named-retail/acclient.h.

What this checkpoint implements

RuntimeCollisionReportingState is the sole per-session owner of:

  • one environment-collision latch per exact RuntimeEntityKey;
  • one ordered object-contact table per exact owner incarnation;
  • retained peer server GUID, touch time, and ethereal-at-touch state;
  • static and ReportAsEnvironment routing;
  • asymmetric IgnoreCollisions and reciprocal ReportCollisions eligibility;
  • strict ordinary age > 1.0 and ethereal age > 0.0 expiry;
  • force-end-before-callback mutation for reentrant safety;
  • missing-peer self-only end reports without resolving a later GUID reuse;
  • exact Missile | AlignPath | PathClipped clearing on the canonical record, borrowed body, retained shadow state, and mutation version;
  • a monotonic immutable report FIFO with observer-failure isolation;
  • the retail callback-eligibility boolean used by failed placement to choose Collided versus NoValidPosition;
  • terminal ownership diagnostics and deterministic session/disposal cleanup.

Successful dormant SetPosition commits contact, water/walkable and ground edges first, runs reporting next, applies physical response once, and then refloods the shadow. An intervening Vector or Movement update suppresses only the stale physical response; it does not erase collision tracking or reports. Failed placement always supplies retail's previousContact = false and previousOnWalkable = false, reports once, applies its one response pass, and maps the report result exactly.

Hidden, teleport/withdrawal, deletion, session reset, and disposal use distinct lifetime edges. Leaving the world force-ends the departing owner's table but retains its environment latch and incoming peer records. Destruction then forgets only the departing owner state. Other owners retain exact-key contacts until their own expiry/force pass and can emit a missing-target end using the preserved server GUID. Hidden and session-clear paths force-end while the old report flags and bodies are still eligible, before state/reset teardown.

Architectural boundaries

  • Runtime owns all canonical collision-report state and report-result logic.
  • Core exposes only the exact successful SetPosition ordering seam and the retained-shadow collision identity required by Runtime.
  • App and Headless gain no report table, queue, heuristic, or production placement consumer.
  • Reports are presentation-free and keyed by exact Runtime identity.
  • Network/update callbacks may re-enter, but every later mutation revalidates current identity, body, and the relevant authority version.
  • Physical-response velocity authority is deliberately separate from report authority, matching retail's ordering without overwriting a newer vector.

Validation and independent review

The saved final diff passed:

  • combined focused Runtime collision-report and SetPosition tests: 76/76;
  • complete Runtime project: 562/562;
  • graphical/headless Runtime-physics ownership and dormancy guards: 4/4;
  • focused Core SetPosition/contact/response ordering tests: 29/29;
  • complete Core project: 4,224 passed / 1 intentional skip;
  • from-source Release solution rebuild: 0 errors and 21 pre-existing test- project nullable/analyzer warnings; this checkpoint introduces none;
  • complete Release solution: 10,309 passed / 4 intentional skips;
  • warmed steady-contact refresh: 0 managed bytes across 10,000 calls;
  • warmed immediate dormant SetPosition commit: still below the existing 2,048-byte-per-operation ceiling, with no new captured-delegate cost;
  • architecture/adversarial re-review: clean after fixing Hidden/session/delete reentrancy, stale shadow-state authority, allocation churn, and batch cost;
  • retail-conformance re-review: clean against every named address above.

The final retail re-review found and closed two last ordering defects before sign-off: object collision now snapshots the mover's Missile bit before the source callback and, when that snapshot was set, unconditionally masks the current Missile | AlignPath | PathClipped bits afterward. Thus an ordinary callback-added Missile is retained when the mover was not previously a missile, but a callback which clears Missile and re-adds path bits cannot evade the pre-gated retail mask. Environment collision retains retail's post-callback current-Missile test. Successful SetPosition now publishes reports before installing the new stationary-fall counter, applies the physical response next, installs StationaryFall/Stop/Stuck transient bits after response, and only then refloods the shadow.

The host guard reads both production source trees. It proves App and Headless borrow GameRuntime.EntityObjects.Physics, declare no second collision table or return heuristic, and still contain no placement-channel consumer. No connected/live gate is required for this dormant checkpoint because no production route can populate or publish the new report owner.

Exact implementation and test paths

The behavior commit containing this handoff changes exactly these ten code and test paths:

  • src/AcDream.Core/Physics/PhysicsObjUpdate.cs
  • src/AcDream.Core/Physics/ShadowObjectRegistry.cs
  • src/AcDream.Runtime/Entities/RuntimeEntityDirectory.cs
  • src/AcDream.Runtime/Entities/RuntimeEntityObjectLifetime.cs
  • src/AcDream.Runtime/Entities/RuntimeEntityRecord.cs
  • src/AcDream.Runtime/Physics/RuntimeCollisionReportingState.cs
  • src/AcDream.Runtime/Physics/RuntimePhysicsState.cs
  • src/AcDream.Runtime/Physics/RuntimeSetPositionState.cs
  • tests/AcDream.Runtime.Tests/Physics/RuntimeCollisionReportingStateTests.cs
  • tests/AcDream.App.Tests/Runtime/RuntimePhysicsOwnershipTests.cs

The same commit synchronizes the architecture, divergence register, canonical SetPosition research, roadmap, milestones, project memory, prior campaign handoff pointer, retail-oracle note, and this detailed handoff. AGENTS.md and the pre-existing line-ending/stat-noise paths are deliberately excluded.

Remaining work - required order

1. Exact authored mover preparation

Build every SetPosition request from Setup's ordered authored spheres, exact scale/presence semantics, StepUp/StepDown heights, flags, cell-local frame and orientation, and current position/vector/state authority versions. Do not synthesize a cylinder from visual radius/height or pre-mutate canonical state.

2. Atomic local-controller/body publication

Prepare off-canonical, then perform one Runtime-validated atomic transaction which publishes the exact same body to graphical and no-window controllers. Every body writer, remote/projectile binding, SetPosition operation, clock epoch, deletion, reset and disposal path must participate. Do not resurrect the rejected snapshot/rollback lease documented in the prior handoff.

3. Presentation-only host projection

Implement graphical and headless observers over the existing dormant placement receipt channel. Withdraw removes presentation/spatial consumers while retaining Runtime identity; Place projects only the immutable committed frame; Discard retires the older revision. Host failure retries the exact FIFO head and never rolls Runtime back.

4. Collision-prefix quiescence and atomic route activation

Park SetPosition residents before retiring their collision prefix, publish the complete replacement generation, wake exact matching residents, and cut every spawn/Position/portal/projectile/drop/pickup/parent/delete route over together. Only then may AP-1 and AD-1 retire.

5. Remaining campaign slices

  • Port retail-authored object collision shape precedence and retire AP-22.
  • Remove remote terrain-normal preprojection and let the transition resolver use the retained contact plane, retiring AD-10.
  • Run the full automated and connected matrix, update all ledgers, and close the remaining physics campaign only with direct evidence.

Rollback

This checkpoint is one bisectable commit. Revert the commit containing this file to remove collision-report ownership without disturbing the earlier SetPosition residence and receipt-channel checkpoints. Do not revive the old collision-presence guess or the rejected body snapshot lease.

Because a Git commit cannot embed its own final hash, resolve the exact checkpoint and revert command without ambiguity using:

$checkpoint = git log -1 --format=%H -- `
  docs/research/2026-07-31-runtime-set-position-collision-reporting-handoff.md
git show --stat $checkpoint
git revert $checkpoint

Earlier rollback points remain:

git revert 270f5154   # dormant public placement receipt channel
git revert 4c02ac42   # Runtime SetPosition/lost-cell residence owner
git revert e84a388e   # pure Core retail SetPosition transaction

Resume procedure

  1. Continue in C:\Users\erikn\.codex\worktrees\af5e\acdream and verify git branch --show-current reports codex/port-claude-agents.
  2. Resolve the exact checkpoint with the git log command above and confirm it is the current HEAD before starting the next behavior slice.
  3. Read AGENTS.md, docs/architecture/acdream-architecture.md, this file, the collision-report oracle, the canonical SetPosition research, and the prior remaining-campaign handoff completely.
  4. Run git status --short. Preserve the unrelated AGENTS.md content diff and every documented line-ending/stat-noise path. Never stage by blanket.
  5. Begin only Exact authored mover preparation, the first remaining item above. Do not activate production routes, retire AP-1/AD-1, begin AP-22 or AD-10, or resurrect the rejected body snapshot/rollback lease.
  6. Use exact-path staging and rerun the matching focused projects, dotnet build AcDream.slnx -c Release --nologo, and dotnet test AcDream.slnx -c Release --no-build --nologo before the next reviewed checkpoint.