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

245 lines
12 KiB
Markdown

# 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.