# 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`](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 - complete 2026-08-01 The dormant preparation contract is implemented and independently reviewed. It binds the Runtime-owned accepted frame and exact Setup DID, preserves the ordered authored spheres and scale/step semantics, seals the returned command, and forces stale deferred residents through exact re-preparation without pre-mutating canonical state. See [`2026-08-01-runtime-set-position-authored-mover-preparation.md`](2026-08-01-runtime-set-position-authored-mover-preparation.md). ### 2. Atomic local-controller/body publication - next 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: ```powershell $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: ```powershell 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.