acdream/docs/research/2026-08-04-c4-route-3-retail-review.md
Erik e0f96a55bf fix(physics): C4 route 3 — portal placement authority (local player)
Removes a duplicate placement authority for local-player portal arrival.
Portalling worked before this change and works after it — this is not a
bug fix, EXCEPT that it found and fixed one dead-code production bug.

THE PRODUCTION BUG: TryExecuteCanonicalPortalPlacement re-read the
accepted destination at Place time, but TryBeginPortalReveal already
consumes that slot at Aim time — so the arm was 100% dead code and every
real portal Place refused with host-token-unavailable. Found only
because we refused to accept 7 skipped tests instead of chasing the
count to zero.

RETAIL IS THE GENERIC PATH FOR THE THIRD ROUTE RUNNING:
SmartBox::TeleportPlayer @0x00453910 = SetPositionSimple(dest, 1) with
flags 0x1012, followed by PlayerPositionUpdated.

BOTH INVERSIONS, WITH THEIR ANCHORS: unlike route 2, the leash IS armed
here (ConstrainTo @0x0045418A) and velocity is zeroed
(set_velocity @0x004541B4); unlike route 4b-3, the local teleport_hook
runs AFTER placement (@0x004538AE).

THE THREE-ROUND DEFECT CHAIN, HONESTLY:
- Round 1 released the player at the pre-teleport position while the
  anim stream marched on — the contract wrongly assumed Place re-fires
  (process rule 1's third occurrence this campaign).
- Round 2's fix inferred commit from a global PendingCount, which three
  non-committing paths also clear — making the SAME bug complete
  cleanly and silently. Strictly worse than round 1: round 1 at least
  tripped portal-complete-before-materialized.
- Round 3 latches the commit where it actually happens
  (ReconcileAndAcknowledgePortal), keyed on reveal generation and
  teleport sequence, via TryConsumePortalCommit. Two of the three
  required regression tests landed and are sabotage-verified on both
  hosts (ParkedPlace_ForgottenByOrdinaryMergeDoesNotLatchAsCommitted /
  HeadlessPortalPrepareDestinationForgottenByOrdinaryMergeDoesNotLatchAsCommitted).
  The third (force-arm-takes-the-slot) was judged unnecessary on review:
  with the inference gone, PendingCount is only a "don't ask yet" guard
  at both gates, so a force operation occupying or vacating the slot no
  longer changes an input the commit decision reads — the case collapses
  into what the landed test already discriminates.

THE B2/P3 RESOLUTION: both round-2 reviews were right about different
branches of the same synchronous call. RuntimePlacementProjectionSubscription
.OnPlacement acknowledges the FIFO head only when TryApply returns true;
a Place whose portal authority went stale (transit ended/superseded
while parked) used to return false, wedging every later entity's
placement receipt behind it forever. Both sinks
(RuntimePlacementPresentationSink, HeadlessRuntimePlacementProjectionSink)
now acknowledge-and-ignore a stale-authority Place instead of refusing
it. The regression test (RuntimePlacementPresentationSinkTests
.PortalPlace_StaleTransitHostOrSequenceIsAcknowledgedAndIgnored) had
been asserting the old, wrong `false` behaviour; it now asserts and
sabotage-verifies the fix.

Also lands: AP-144 (register discipline — the portal movement-event
send reuses the stricter UsePositionFromServer gate where retail's
SendMovementEvent is the looser autonomy_level != 0 test, diverging
only at level 1, currently unreachable), AP-145 + issue #318 (the
local-player collision-shadow presentation write bypasses its own
publisher's ShadowObjects write via a direct cache .Set(), self-healing
only once dedup diverges — filed, not fixed, pending a composition
test), AD-42 deleted (its last citation retired by the canonical portal
arm), AD-2 updated (the wait-cue's trigger predicate now covers a
second cause), and two documentation corrections: the enter_world
misattribution (both call sites are in SmartBox::HandleCreateObject,
only one in the player branch — portal arrival is TeleportPlayer, not
enter_world) and the stale "local player never reaches this path"
comment on the generic-remote-render-pose write.

Suite: 11,090 passed / 4 skipped / 0 failed. No new skips, nothing
weakened.

STILL OWED: the connected two-client gate, with
ACDREAM_PROBE_LOCAL_TELEPORT=1, scored only if [local-tp] lines
actually appear in the capture — and explicitly NOT scored as covering
issue #318 (no composition test yet asserts PhysicsEngine.ShadowObjects
directly).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 03:57:37 +02:00

515 lines
26 KiB
Markdown

# C4 route 3 — retail-conformance review (2026-08-04)
**Verdict: FAIL.**
Reviewer scope: the uncommitted working-tree diff at HEAD `cd3129e9`
(`git diff HEAD` + untracked), branch
`claude/acdream-physics-divergence-5aa784`. Review only — no edits made.
The retail *reading* in this slice is excellent. Every §1 claim in the
pinned contract reproduces line-for-line in
`docs/research/named-retail/acclient_2013_pseudo_c.txt` (§A below), both
inversions are implemented in the right direction, the D-T3 duty map is
complete, and the implementer's P1 finding on TransientState is not just
correct — it retires a real pre-existing divergence.
The slice fails on **what happens when the placement does not commit**.
`TeleportAnimEvent.Place` is one-shot, so every non-`Committed` outcome
silently skips the placement, the presentation suffix, and the
materialization acknowledgement while the animation stream marches on to
reveal the world and fire LoginComplete anyway. The headless host has the
same hole with the extra property that it *asserts a materialization that
did not happen*. Neither is covered by a test, because the App-layer
presentation suite the contract made mandatory (§8 items 8/9/10, closing
route 2's B2 gap) was not written — the existing App assertions were
weakened instead. And the one probe field the connected gate keys on
(`leash=armed`) can never be true as coded.
---
## Findings
### R1 — MAJOR — `TeleportAnimEvent.Place` is one-shot; there is no re-attempt driver, and the reveal completes anyway
`src/AcDream.Core/World/TeleportAnimSequencer.cs:136-141`
```csharp
case TeleportAnimState.Tunnel:
if (worldReady)
{
evts.Add(TeleportAnimEvent.Place);
Advance(TeleportAnimState.TunnelContinue, enterTunnel: false);
```
The state advances in the **same tick** the event is emitted. `Place`
never fires again for that reveal.
`src/AcDream.App/Streaming/LocalPlayerTeleportController.cs:505-522`
```csharp
case TeleportAnimEvent.Place:
if (!_worldReveal.CanPlacePortalDestination(...)) return;
if (!TryExecuteCanonicalPortalPlacement(sequence)) return; // :513
...
_placement.Place(_pendingRotation); // :517
...
_worldReveal.ObserveMaterialized(...); // :520
```
`TryExecuteCanonicalPortalPlacement` returns `true` **only** on
`RuntimeAcceptedPositionExecutionStatus.Committed`
(`LocalPlayerTeleportController.cs:597-598`). Every other status —
`Contention`, `Rejected`, `NotApplicable`, and notably `DeferredCell`
returns `false` and the `Tick` returns.
Consequences, all reachable:
- `_placement.Place` never runs → no `entity.SetPosition` /
`ParentCellId` / `RebucketLiveEntity`, no `NotifyTeleported()`, no
camera reset, no `_spatial.Reconcile()`.
- `_worldReveal.ObserveMaterialized` never runs →
`RuntimeWorldTransitState.AcknowledgePortalMaterialized` never fires →
`Materialized` stays false.
- The **next** tick still advances the sequencer:
`TunnelContinue``TunnelFadeOut``PlayExitSound`
(`RevealWorldViewport`) → `WorldFadeIn``FireLoginComplete`
(`_mode.EnterWorld()` + `SendLoginComplete()` + `_worldReveal.Complete()`
+ `ResetTransit`).
- `RuntimeWorldTransitState.Complete` then trips
`FailInvariant("portal-complete-before-materialized")`
(`RuntimeWorldTransitState.cs:701-706`) and returns `false`;
`WorldRevealCoordinator.Complete()` (`:268-276`) **discards** that
`false`. `ResetTransit(clearSession:false)` then calls
`_transit.EndTeleport()` + `_worldReveal.Cancel()`, so the ledger
converges — but the reveal is recorded cancelled, not completed, with
one invariant failure logged.
User-visible outcome on `Contention`/`Rejected`: the player is revealed
into the destination world **standing at the origin position**, with
LoginComplete sent. On `DeferredCell`: the body commits later at the
collision-generation wake (`Advance``ReconcileAndAcknowledgePortal`),
but the presentation suffix, camera reset, rebucket, and materialization
ack are gone forever.
This is exactly what contract §4 items 4 and 5 forbid ("a refused
placement must NOT … must not advance the anim-event stream's terminal
events"; "never a half-state", "never a silent wedge in portal space")
and it is the D-T5/P4 obligation the contract flagged in advance: *"if
the Place anim event is one-shot, the re-attempt must be driven by the
same Tick predicate that produced it, and THAT mechanism must be stated
in the commit."* It is one-shot, and no mechanism was added.
The comment shipped in its place is false. `LocalPlayerTeleportController.cs:566-572`:
> "On any refusal this returns `false` without mutating anything — the
> D-T5 refusal shape: … the transit's own cancellation/supersession
> machinery is the authority on what happens next."
The transit is not the authority on what happens next. The animation
sequencer is, and it does not wait.
**Correct behaviour:** either re-drive the Place edge from the same
`ready`-gated Tick predicate until it commits (holding the sequencer in
`Tunnel` — which is what retail's `blocking_for_cells` hold is), or
cancel the reveal explicitly on refusal so the player is never revealed
without a committed placement. Retail has no third option: it places
unconditionally and immediately (`SmartBox::TeleportPlayer` @0x00453910)
and only the *simulation* waits on prefetch.
---
### R2 — MAJOR — headless discards the arm's status and acknowledges a materialization that did not happen
`src/AcDream.Headless/Hosting/HeadlessSessionWorldProjection.cs:775`
```csharp
_ = _acceptedPositionDrive.TryExecuteAcceptedPortalArrival(
destination,
authority);
```
The status is dropped on the floor. `PrepareDestination` then
unconditionally returns a ready readiness report, and
`RuntimeLiveEntitySessionController.TryCompletePortal` continues its
fully-synchronous suffix: `AcknowledgeDestinationReadiness`
`AcknowledgePortalMaterialized``SimulationReleaseProjected`
`Complete``SendGameAction(LoginComplete)``EndTeleport`.
So on any refusal or park, the headless host **fires
`AcknowledgePortalMaterialized` for a placement that never committed** —
contract §4 item 5 and D-T5 rows 1/2 both state in terms that the
materialization ack must fire only from the committed outcome. The bot
reports a completed teleport while standing where it started, with no
log line of any kind (see R8).
Retail contradiction is indirect but real: retail's
`SmartBox::PlayerPositionUpdated` @0x00453870 clears
`waiting_for_teleport` **inside the same call that performed
`SetPositionSimple`** (@0x00453924@0x0045389A). The "wait is over"
edge is downstream of the placement in retail; here it can precede a
placement that never occurred.
---
### R3 — MAJOR — the D-T8 probe's `leash` field can never read `armed`; the connected gate as pinned is unpassable
`src/AcDream.Runtime/Session/RuntimeAcceptedPositionDriveController.cs:694`
```csharp
leashArmed: controller.PositionManager?.IsFullyConstrained() ?? false,
```
Retail `ConstraintManager::IsFullyConstrained` @0x005560D0 is
`constraint_distance_max * 0.9 < constraint_pos_offset` — "has strained
past 90 % of the leash", the predicate `jump_is_allowed` reads. It is not
"is the leash armed". The acdream port says so explicitly
(`src/AcDream.Core/Physics/Motion/ConstraintManager.cs:79-89`).
Retail `ConstraintManager::ConstrainTo` @0x00556240 (pseudo-C
:353528-353537) ends with
`constraint_pos_offset = Position::distance(anchor, physics_obj->m_position)`;
acdream mirrors it at `ConstraintManager.cs:65-71`. Because
`RearmConstraintLeashAtCurrentPosition`
(`PlayerMovementController.cs:1836-1845`) anchors at the body's **own**
`CellPosition`, that distance is 0. `max * 0.9 < 0` is false.
Therefore every committed portal arrival prints `leash=unarmed`. The
contract's §9 pass criterion — *"Pass requires ALL of … `leash=armed`"*
cannot be met, and a future reader hitting `leash=unarmed` would chase a
phantom missing leash (the exact 4b-3 A1 defect class the contract
warned about, inverted).
The correct observable is `ConstraintManager.IsConstrained`, which the
Runtime test itself uses
(`RuntimeAcceptedPositionDriveControllerTests`,
`Assert.True(controller.PositionManager.Constraint!.IsConstrained)`).
`PositionManager` does not currently surface it; it needs to.
---
### R4 — MAJOR — the mandatory App-layer presentation suite is missing, and the existing App assertions were weakened
`tests/AcDream.App.Tests/Streaming/LocalPlayerTeleportControllerTests.cs`
gained **zero** new `[Fact]`s. All five new tests in the diff are in
`tests/AcDream.Runtime.Tests/Session/RuntimeAcceptedPositionDriveControllerTests.cs`.
What changed in the App file is assertion *strength*, downward:
```diff
- Assert.Equal(new Vector3(7f, 8f, 9f), harness.Placement.Position);
+ Assert.True(harness.Placement.Called);
```
(and the same substitution at eight further sites). The interface change
makes the literal old assertion impossible, which is fine — but the
contract required the replacement coverage and named it as load-bearing:
- §8 item 8: "after a committed portal placement through the REAL sink +
suffix, the render `WorldEntity` position/rotation/`ParentCellId` equal
the resolved body, the draw bucket moved, the local-player shadow
agrees, and the sink's Place receipt was consumed with a VALID portal
authority … **route 2's B2 coverage gap … becomes load-bearing here and
MUST close**."
- §8 item 9: the T8 overwrite ordering (wire pose then resolved pose).
- §8 item 10: refused Place edge presentation.
None exist. Since `RuntimePlacementPresentationSink.TryPublishPlace`
writes no pose (contract §3.4, re-confirmed), the suffix in
`LocalPlayerTeleportPlacement.Place` is now the render entity's **only**
mover — and nothing asserts it moves the entity to the resolved pose.
Combined with R1 (where that suffix is skipped entirely on refusal), this
is the #312 shape verbatim: process rule 4, "tests must assert the layer
that broke."
---
### R5 — MAJOR — headless dual-host parity (§8 item 6, D-T6) has no coverage, self-declared open
`tests/AcDream.Headless.Tests/HeadlessSessionHostTests.cs:413-422`
(added in this diff):
> "no accepted-position drive controller is wired into this fixture's
> projection … so the canonical portal arm this method now calls is a
> no-op here by construction (`_acceptedPositionDrive` is null) … a
> headless-host-specific committed-portal test is an open item, not
> attempted here given this session's time budget."
D2 (`ResynchronizeLocalPlayerForPortalArrival`, ~40 non-comment lines and
AD-42's last citation) was deleted and its replacement has **zero**
headless test coverage. D-T6 pinned this: *"dual-host parity is a test
obligation, not an aspiration."* The honest disclosure is appreciated and
does not change the finding.
Related, and unremarked in the diff: the deleted method also performed
`controller.LocalEntityId = record.LocalEntityId ?? 0u`. Verified safe —
`RuntimeLocalPlayerPhysicsPublicationState.cs:214` sets it at publication
and the entity key is stable across a portal — but the drop deserves a
line in the commit message.
---
### R6 — MEDIUM — the `enter_world` caller-sweep correction mis-states the retail record it is correcting
`docs/research/2026-07-16-portal-completion-pseudocode.md` §2.1 banner:
> "a caller sweep … shows both `CPhysicsObj::enter_world` call sites
> living inside `CObjectMaint::CreateObject`'s player branch
> (`SmartBox::init_player` + `CellManager::ChangePosition` immediately
> precede it)"
Verified independently. The two call sites are pseudo-C :93797
(@0x004550EC) and :93824 (@0x00455095). Both live inside
**`SmartBox::HandleCreateObject` @0x00454C80**, not
`CObjectMaint::CreateObject` — the latter is merely a *callee* at
@0x00454FD8 inside that same function. And they are **not both in the
player branch**: @0x004550EC is in the `if (arg3 != this->player_id)`
NON-player branch (`PhysicsDesc::get_position``enter_world(var_bc, …)`
for a newly created remote object); only @0x00455095 sits in the player
branch after `init_player` + `ChangePosition`.
The load-bearing NEGATIVE is **CONFIRMED**: the `Position*` overload
@0x00516310 has exactly those two callers, the `int` overload @0x00516170
is reached only from @0x00516327, and neither is on the portal path.
`SmartBox::TeleportPlayer``SetPositionSimple` is correct.
But this banner is explicitly a correction to the retail record that
future sessions will cite, and it is wrong in two of its three factual
clauses. Same defect class as "a register row asserting behaviour the
code does not have," applied to a research doc — the exact reason the
contract ordered the correction in-slice.
---
### R7 — MEDIUM — retail's post-teleport movement refresh is autonomy-gated; acdream's is not
Contract open question (c), answered.
`CommandInterpreter::SendMovementEvent` @0x006B4680 (pseudo-C
:700274-700313):
```
if ((player != 0 && this->smartbox != 0) && CPhysicsObj::InqRawMotionState(player) != 0)
if (this->autonomy_level != 0)
MoveToStatePack::MoveToStatePack(...)
SendMoveToStateEvent(...)
```
Two gates: a non-null raw motion state, and **`autonomy_level != 0`**.
Under server control retail sends nothing.
`RuntimeAcceptedPositionDriveController.cs:678-681` calls
`_localPlayerOutbound.TrySendMovement(...)` unconditionally;
`LocalPlayerOutboundController.TrySendMovement:187-229` gates only on a
resolvable outbound position. The controller already holds
`UsePositionFromServer` (retail's `UsePositionFromServer()`), and
`_usePositionFromServer` is already a field on this very class — the
autonomy fact is in scope.
Everything else about the port checks out: the message family is
`MoveToState` (retail packs `InqRawMotionState` into `MoveToStatePack`),
the contact byte is `Contact && OnWalkable` in both, exactly one is sent,
and no `AutonomousPosition` goes out (retail's teleport branch returns
before `SendPositionEvent` — verified at @0x004541C0). Order is right:
`CommitCanonicalTeleportFrame` (hook tail) → `CancelAutoRun`
movement send, matching @0x004538AE@0x004538B3 → tail-jump.
Either add the autonomy gate or file the delta as a register row.
---
### R8 — MEDIUM — D-T8 emits one line per *committed* arrival, not per attempt; refusals are invisible under the pinned gate environment
`PhysicsDiagnostics.LogLocalTeleportArrival` is called from exactly one
site, `ReconcileAndAcknowledgePortal`
(`RuntimeAcceptedPositionDriveController.cs:687-696`), reached only on
`CommittedHostAcknowledgementPending`. Its `placementStatus` argument is
the literal `"Committed"`.
The graphical refusal path logs via `PhysicsDiagnostics.LogTeleport`
(`LocalPlayerTeleportController.cs:582-583`, `:598-599`), which is gated
by **`ACDREAM_PROBE_TELEPORT`** (`PhysicsDiagnostics.cs:1160-1161`) — a
different env var from the `ACDREAM_PROBE_LOCAL_TELEPORT` the gate pins.
The headless refusal path logs nothing at all (R2).
Net: with the contract's pinned gate environment, a refusal produces zero
output on either host. D-T8 specified "One line per portal-arrival
attempt: cause … placement status", and §9 requires "zero
`Refused`/`Contention` lines in ordinary play" — unobservable as built.
Given R1, an unobserved refusal is precisely the failure that would ship.
---
### R9 — LOW — stale directional reference in a comment added by this diff
`src/AcDream.App/Streaming/LocalPlayerTeleportController.cs:775`:
"TryBeginPortal (below) drives …". `_worldReveal.TryBeginPortal` is
called **above** this comment, at `:741`, in the same method. Process
rule 6.
### R10 — LOW — `AD-131` does not exist
`src/AcDream.App/Physics/LiveEntityNetworkUpdateController.cs:2292`
cites "AD-2/AD-131/#275". The AD section has 48 rows. The row is
**AP-131** (`docs/architecture/retail-divergence-register.md:283`), which
is what the contract itself says. Introduced by this diff, in the very
comment the slice rewrote to fix a stale comment.
### R11 — LOW — the probe asserts more than it observes
`RuntimeAcceptedPositionDriveController.cs:693-695` hardcodes
`hookTailRan: true` and `autorunCancelled: true`.
`RuntimeLocalPlayerMovementState.CancelAutoRun():226-234` returns `false`
when autorun was already off (correctly mirroring retail's
`SetAutoRun` @0x006B4850, which acts only on a state *change* at
@0x006B4871). The field reports the action ran, not the state changed —
report the returned bool.
---
## §A — retail claims verified independently (do not re-derive)
All against `docs/research/named-retail/acclient_2013_pseudo_c.txt`.
| claim | where | result |
|---|---|---|
| `SmartBox::TeleportPlayer` @0x00453910 = `SetPositionSimple(player, dest, 1)` @0x00453924 + `PlayerPositionUpdated(this, 1, FLT_MAX)` @0x00453932, nothing else | :92514-92523 | **CONFIRMED** — the generic path, route 2's exact primitive, third route running |
| `PlayerPositionUpdated` teleport arm order: `position_update_complete=0` @0x00453890, `waiting_for_teleport=0` @0x0045389A, `has_been_teleported=0` @0x004538A4, `teleport_hook` @0x004538AE, `cmdinterp->PlayerTeleported()` @0x004538B3, `set_viewer` @0x004538D5, `LScape::update_viewpoint` @0x004538E2, `CellManager::ChangePosition` @0x00453903 | :92469-92509 | **CONFIRMED**, exactly the contract's order |
| `CommandInterpreter::PlayerTeleported` @0x006B32B0 = `SetAutoRun(0,1)` + tail-jump `SendMovementEvent` | :699036-699041 | **CONFIRMED**. New: `SetAutoRun` @0x006B4850 only acts when `(arg2==0) != (auto_run==0)` (@0x006B4871) — acdream's `CancelAutoRun` early-return matches |
| **Inversion A** — local TELEPORT branch @0x0045415F: `TeleportPlayer(&var_48)` @0x00454168`ConstrainTo(arg2, &var_48, start, max)` @0x0045418A`set_velocity(player, {0,0,0}, 1)` @0x004541B4 → return | :93013-93023 | **CONFIRMED**, including the WIRE-destination anchor |
| FORCE_POSITION branch returns @0x0045409D before every `ConstrainTo` | :92925-92933 | **CONFIRMED** — route 2's no-re-arm rule intact and correctly left force-scoped |
| **Inversion B** — the local hook runs AFTER the placement (from `PlayerPositionUpdated`), opposite to the remote arm's @0x005163EF | :92497 vs 4b-3's citation | **CONFIRMED** |
| `enter_world` is NOT on the portal path | :93797, :93824 | **NEGATIVE CONFIRMED** — but the attribution in the new correction banner is wrong; see R6 |
| **P1 (TransientState not re-seeded)** — retail `CPhysicsObj::SetPositionInternal(CTransition*)` @0x00515330 derives Contact from `collision_info.contact_plane_valid` @0x00515430, WaterContact from `contact_plane_is_water` @0x00515453, OnWalkable from `set_on_walkable(contact_plane.N.z vs floor_z)` @0x00515467-0x0051548E, Sliding from `sliding_normal_valid` @0x005154E1. **No unconditional `Contact\|OnWalkable` seed anywhere.** | :283484-283519 | **THE FINDING IS CORRECT AND IS A FIDELITY GAIN.** `PhysicsObjUpdate.CommitSetPositionContactPrefix` (`src/AcDream.Core/Physics/PhysicsObjUpdate.cs:154-176`) is that exact port, and runs inside the canonical commit (`RuntimeSetPositionState.cs:5038`). The old `SetPositionCore` seed (`PlayerMovementController.cs:1859-1862`) was the divergence; dropping it is right. The `Active` argument also holds — `PlayerMovementController.cs:2069` and `:2449` re-set it every frame. |
| `ConstraintManager::ConstrainTo` @0x00556240 initializes `constraint_pos_offset = distance(anchor, m_position)` | :353528-353537 | **CONFIRMED** — acdream matches; also the basis for R3 |
| `CommandInterpreter::SendMovementEvent` @0x006B4680 is autonomy-gated | :700274-700313 | **CONFIRMED** — see R7 |
## §B — implementation facts verified correct
- **D-T3 duty map (P1) is complete.** All nine `SetPositionCore` duties
land in `CommitCanonicalTeleportFrame`
(`PlayerMovementController.cs:1993-2041`) or the canonical commit, in
`SetPositionCore`'s own order (StopCompletely → input/mouse resets →
UnStick/UnConstrain/re-arm → edge resets → clock reset). Nothing
silently dropped except the TransientState seed, which is correct
(§A).
- **Inversions implemented in the right directions.** The portal arm
consumes the classifier's dormant LocalPlayer-teleport branch
(`RuntimeAuthoritativePositionRouteClassifier.cs:336-356`) unchanged;
`ConstrainPhase.AfterPositionOperation` + `ZeroVelocity: true` +
`SendPositionImmediately: false` + `TeleportHookPhase.AfterPositionOperation`
all flow through. The hook tail runs only from the committed receipt.
- **The force arm is untouched.** The only route-2 edits are one
force-scoping doc sentence (`:133-137`) and a non-`required`
`Portal { get; init; }` on `Pending` that defaults empty. Zero route-2
test expectation changes — §4 item 8's tripwire is clean.
- **The synthetic `priorTeleport = accepted - 1`** in
`ClassifyPortalArrival` is sound: `TeleportAdvanced` reads only the
boolean `PhysicsTimestampGate.IsNewer(prev, accepted)`, the branch's
resulting route does not depend on the previous stamp's magnitude, and
wrap is safe at `accepted == 0`.
- **AD-42 deleted** (row gone, header 49 → 48 rows), **AD-2 amended in
place** with the deferred-place timing, the T8 tolerated-overwrite
note, and the leash-anchor nuance. Plan gap-line correction present.
Register rules satisfied.
- **Release build green.** Focused
`RuntimeAcceptedPositionDriveControllerTests`: 22 passed / 0 failed /
**0 skipped**. No `Skip` attribute remains in any of the four touched
test files, and no Runtime test was weakened — the five new ones are
strong (the happy path pre-arms the leash at a *stale* anchor so a
missing re-arm fails the `ConstraintPos` assertion; the refusal tests
assert positive "nothing moved, transit still active, no packets"
facts).
## §C — the production bug fix: correct, complete, no stale-destination hazard
Verified. `RuntimeWorldTransitState.TryBeginPortalReveal:159-182` sets
`_hasAcceptedDestination = false` and `_acceptedDestination = default`
the instant it claims the generation, and
`TryGetAcceptedTeleportDestination:522-527` returns
`_teleportActive && _hasAcceptedDestination`. So the pre-fix Place-time
re-read was **guaranteed** to fail — the canonical portal arm was 100 %
dead code, refusing with `cause=host-token-unavailable` before ever
reaching Runtime. The diagnosis is right and this was a real production
bug, not a fixture artifact.
The fix is the right lifetime:
- `_pendingDestination` is written in `AimDestination:781-784`, in the
same statement block as `_pendingCell`/`_pendingRotation`, only after
`TryBeginPortal` succeeded (`:741-748`) — so the four Aim-time
snapshots are mutually consistent by construction.
- **Cancellation:** `ResetTransit:801-804` clears all four; every
cancellation path funnels through it.
- **Supersession:** a second accepted destination re-enters
`TryAimAcceptedDestination``AimDestination`
`WorldRevealCoordinator.TryBeginPortal``WithdrawHostForReplacement`
+ a **new** generation, overwriting all four snapshots together. A
superseded destination cannot survive.
- **Staleness at Place:** three independent gates still validate —
`CanPlacePortalDestination(_pendingRevealGeneration, sequence, _pendingCell)`
(`:507-511`), the idempotent
`TryRegisterHostProjection` re-derivation (generation ==
`_snapshot.Generation`, cell == `_snapshot.DestinationCell`,
`!Cancelled`, `!Completed``RuntimeWorldTransitState.cs:189-227`),
and `BeginAcceptedPlacementCore`'s own
`portal.Projection.DestinationCell == acceptedPosition.LandblockId`
against the **latest merged** snapshot
(`RuntimeSetPositionState.cs:1528-1534`).
The re-read was protecting nothing. `WorldRevealCoordinator.BeginHostLifetime`
throws if the Aim-time registration fails, so the Place-time
re-derivation is genuinely idempotent and can never mint a second host
projection in production.
## §D — contract open questions, answered
**(b) leash anchor — keep the resolved anchor as shipped.** Retail's
`constraint_pos` is write-only (never read by `adjust_offset`, confirmed
in the port's own doc at `ConstraintManager.cs:41-44` and against ACE);
the only downstream consumer of `ConstrainTo`'s inputs is
`constraint_pos_offset = distance(anchor, m_position)`, which is the
placement adjustment (centimetres) in retail and exactly 0 in acdream.
Both are orders of magnitude inside the `0.9 * max` band, so no behaviour
in the leash's brake taper can distinguish them. The AD-2 note is the
right disposition; do **not** switch anchors.
**(c) `SendMovementEvent` shape — see R7.** Message family, contact
derivation, count, and ordering are all correct; the missing
`autonomy_level` gate is the one delta.
## §E — errors in the contract itself
1. **§4 item 3 / D-T5's re-attempt reasoning is the proximate cause of
R1.** D-T5 offered "the anim event re-fires while `ready` holds" as
the leading case and demoted the one-shot case to a parenthetical
verify-and-state. It is one-shot. The contract should have read the
sequencer before writing the row and pinned the driver. This is
process rule 1 ("the contract causes the defect") recurring for the
third documented time.
2. **§9's `leash=armed` criterion is unachievable** with any
`IsFullyConstrained`-shaped observable; the contract should have named
`ConstraintManager.IsConstrained`. See R3.
3. **§3.5 overstates the change:** "`AcknowledgePortalMaterialized` fires
from the committed placement receipt instead of rubber-stamping after
a host mutation." As built it still fires from the host Place edge,
merely gated on a committed status. Substantively equivalent on the
commit path; wording should be corrected so a future reader does not
look for a receipt-driven ack that does not exist.
4. **§1's `enter_world` row** carries the same wrong caller attribution
the banner does (R6) — it says "its local-player caller is the initial
login path only (@0x00455095)", which is right about that site but
silently drops the *other* site @0x004550EC and mis-names the
enclosing function in the derived correction.
## What must land before this can pass
1. A re-attempt (or explicit-cancel) mechanism for a non-`Committed`
Place edge, with the driver named and tested — R1.
2. Headless must consume the arm's status and must not acknowledge a
materialization for a placement that did not commit — R2.
3. Fix the probe's `leash` observable (and emit a line per *attempt*,
under the gate's own env var) — R3, R8.
4. Write the App-layer presentation suite (§8 items 8/9/10) closing route
2's B2 gap, plus one headless committed-portal test — R4, R5.
5. Correct the `enter_world` caller-sweep banner — R6.
6. Gate the movement refresh on autonomy, or file the register row — R7.
7. Comment/citation cleanups — R9, R10, R11.