# C4 route 3 — retail-conformance review, round 2 (delta) — 2026-08-05 **Verdict: FAIL — but a near miss.** All three round-1 MAJOR retail findings (R1, R3, R8) are genuinely fixed, and the R1 fix is the right shape for the right retail reason. What blocks is small and cheap: one unsound "the park committed" inference that reopens R1's failure mode on a narrow path (**N1**), one approximation shipped with a code comment instead of the register row the project's binding rule requires (**R7**), and one transient condition converted into a fatal exception on the headless endurance path (**N3**). **R4/A5 (the presentation suite) explicitly does NOT block** — see §D. That call changed from round 1 because the A10 correction is true: I verified the canonical Place receipt, not the suffix, is the render entity's mover, and both halves of that path already have tests. Scope: delta against my round-1 report (`2026-08-04-c4-route-3-retail-review.md`). Same working tree, HEAD `cd3129e9`, uncommitted. Review only. --- ## §A — round-1 findings: disposition | # | round-1 finding | round-2 status | |---|---|---| | R1 | `Place` one-shot; no re-attempt driver; reveal completes with an unplaced body | **FIXED** — §B, and the fix is retail-correct | | R2 | headless discards the arm's status, acks a materialization that never happened | **FIXED** — §B.3 | | R3 | probe's `leash` field can never read `armed` | **FIXED** — `Constraint?.IsConstrained` at `RuntimeAcceptedPositionDriveController.cs:838` | | R4 | App presentation suite missing; assertions weakened | **PARTIALLY closed, does not block** — §D | | R5 | headless dual-host parity untested | **FIXED** — `HeadlessPortalPrepareDestinationParksThenCommitsOnCollisionGenerationWake` | | R6 | `enter_world` caller-sweep correction mis-stated the retail record | **FIXED and independently re-verified** — §C.4 | | R7 | retail's movement refresh is autonomy-gated; acdream's was not | **PARTIALLY fixed — BLOCKS on register discipline** — §C.3 | | R8 | probe fired only on commit; refusals invisible under the pinned env var | **MOSTLY fixed** — two App-side causes remain invisible, §E.2 | | R9 | stale "TryBeginPortal (below)" | **FIXED** (`:751` now reads "above") | | R10 | `AD-131` does not exist | **FIXED** → `AP-131` | | R11 | probe hardcoded `autorunCancelled: true` | **FIXED** — reads `CancelAutoRun()`'s bool | --- ## §B — the R1 fix: correct, and correct for the right retail reason `LocalPlayerTeleportController.cs:527` ```csharp bool placementReady = dataReady && TryAdvancePortalCommit(sequence); ... var (_, events) = _presentation.Tick(deltaSeconds, placementReady); ``` Inverting the readiness feed instead of touching the sequencer is the right call, for a reason worth recording: **it is retail's own shape.** Retail holds the player in portal space on `CellManager::blocking_for_cells` and `SmartBox::UseTime` @0x00455410 runs only `CheckPrefetchStatus` until the destination is usable — the hold lives in the *readiness predicate*, not in the animation. Feeding the sequencer "the canonical commit has already happened" rather than "the data is ready" reproduces that hold without changing a single sequencer timing (stop condition 2 respected). `TeleportAnimSequencer.cs` is untouched — confirmed by `git diff`. ### B.1 — arrival ORDER is preserved; Inversion B intact Verified by tracing the single tick on which the commit succeeds: 1. `TryAdvancePortalCommit` → `TryExecuteAcceptedPortalArrival` → `TryPrepareAndSubmitAuthoredPlacement` → **canonical body commit** (`CommitCanonical`, retail `SetPositionSimple` @0x005162B0). 2. `ReconcileAndAcknowledgePortal` → `CommitCanonicalTeleportFrame` (UnStick @0x00514EEE / UnConstrain @0x00514F02 / re-arm @0x0045418A, velocity zero @0x004541B4, StopCompletely) — **after** the placement. 3. `CancelAutoRun()` + movement refresh — the `PlayerTeleported` @0x006B32B0 port, **after** the hook tail. 4. Only then does the sequencer see `worldReady=true`, emit `Place`, and run the presentation suffix (`NotifyTeleported`, camera reset, reconcile) and `ObserveMaterialized`. Retail: `SetPositionSimple` @0x00453924 → `PlayerPositionUpdated` @0x00453932 → `teleport_hook` @0x004538AE → `PlayerTeleported` @0x004538B3 → `set_viewer` @0x004538D5. **Same order.** Inversion B (local hook AFTER placement) holds; the gating did not move it. Two sub-order deltas versus retail, both traced and both **unobservable** — stated so a future reader does not re-derive them: - Retail's `ConstrainTo` @0x0045418A and `set_velocity` @0x004541B4 run in `HandleReceivedPosition` *after* `PlayerPositionUpdated` returns, i.e. after `SendMovementEvent` and `set_viewer`. acdream runs both inside `CommitCanonicalTeleportFrame`, before them. Nothing reads the leash between those points, and `MoveToStatePack` @0x006B4720 packs `InqRawMotionState` + `m_position` + contact + longjump + timestamps — **no velocity** — so the outbound bytes are identical either way. - `NotifyTeleported()` (teleport_hook's TargetManager teardown) now runs in the presentation suffix, i.e. after `PlayerTeleported`, where retail runs the whole hook before it. Purely local; no interaction with the outbound send. ### B.2 — the refusal path is now genuinely held, and tested with teeth `RefusedPlace_HoldsTheStreamAndConvergesOnlyAfterContentionClears` (App.Tests) forces a real Runtime `Contention` by taking the entity's placement token, drives **100 ticks at 0.1 s** — 10 s, roughly 3× the tunnel's own 2–5 s timing, well past where the pre-fix code fired `FireLoginComplete` — and asserts the positive facts: body unmoved, `IsActive`, `Snapshot.Completed == false`, `LoginCompleteCount == 0`. It then releases the competing operation and asserts the very next tick commits at the offered destination. That is a real discriminator, not a negative-only assertion, and it directly kills R1. A permanent refusal now holds in the tunnel showing retail's centered wait cue (`_holdSeconds` accumulates on `!placementReady`) until supersession or session reset — which is exactly what contract D-T5 pinned and §4 item 4 requires. ### B.3 — headless `PrepareDestination` now throws if no drive is wired, gates the attempt on `_collision.IsReady(destination.CellId)`, and returns `IsCollisionReady: committed`; `RuntimeLiveEntitySessionController.TryAdvancePortalCompletion` returns early on `!IsCollisionReady`, retried by `PumpPortalCompletion` from `HeadlessSessionHost.Tick`. The materialization ack can no longer precede a placement. R2 closed. ### B.4 — P3 (no wedgeable portal receipt) is now ESTABLISHED Neither review had closed this. `RuntimePlacementProjectionSubscription.OnPlacement` (`:122-150`) calls `_sink.TryApply(in head)` **synchronously on publish**, so a portal-carrying Place receipt is applied and acknowledged inside the commit call, while the transit is still active and `IsCurrentPlacementAuthority` still holds. This matters most on headless, where `TryAdvancePortalCompletion` runs `Complete` + `EndTeleport` synchronously right after the commit and the FIFO is only republished at the end of the same `Tick` — had delivery been deferred, that receipt would have failed the portal gate forever and wedged the placement FIFO for every entity. It does not. **P3 satisfied on both hosts.** --- ## §C — retail verification of the round-2 changes ### C.1 — A4: the route fields carry retail semantics (with one granularity defect) Verified in `RuntimeAuthoritativePositionRouteClassifier.cs:164-171`: - `ConstrainAfterRouting => ConstrainPhase is AfterPositionOperation` — **correct and discriminating.** It separates the three real retail cases: force (`None`, early return @0x0045409D), local teleport (`After`, `ConstrainTo` @0x0045418A), local non-teleport (`Before`, `ConstrainTo` @0x004541EC). The sabotage the contract's §8 item 11 demanded can now fail as designed. - `ZeroVelocity` — read directly; retail `set_velocity` @0x004541B4. **N4 (LOW) — `RunsTeleportHook` gates too much.** `RuntimeAcceptedPositionDriveController.cs:795-801` uses `route.RunsTeleportHook` (`TeleportHookPhase is not None`) to gate the **entire** `CommitCanonicalTeleportFrame` call. But that method does far more than retail's `teleport_hook` @0x00514ED0 (CancelMoveTo, UnStick, StopInterpolating, UnConstrain, TargetManager, report_collision_end): it also resets the render-lerp anchors, publishes `UpdateCellId`, runs StopCompletely, resets the input edges, and resets the object clock — none of which retail conditions on the hook. Retail's `SetPositionInternal` @0x00515330 does the frame/cell work unconditionally. Today the portal route always sets the phase, so there is no live effect; but a future `TeleportHookPhase.None` would silently skip the render-root cell publish — the doorway-FLAP class. Gate only the `UnStick`/`UnConstrain`/re-arm block on the hook phase. `RunsTeleportHook` also collapses `Before` and `After` into one boolean. Harmless here because the call site is unconditionally post-commit, but it means the field cannot express Inversion B by itself. ### C.2 — the "sequence" plumbing `TryExecuteCanonicalPortalPlacementCore` now takes the authority's `TeleportSequence` from `_pendingDestination` and `Debug.Assert`s it equals the transit's `ActiveTeleportSequence`. Sound: the two can only diverge through a bug, and `RuntimeWorldTransitState.OfferTeleportDestination:495-503` accepts **exactly one** destination per active sequence (`if (_destinationAccepted) return false;`), so the Aim-time snapshot is unique per sequence by construction. (This also disposes of a hazard I went looking for: a second destination cannot supersede within a sequence, and a new sequence routes through `OnTeleportStarted` → `ResetTransit`, which clears `_placementCommitted`/`_awaitingDeferredWake` at `:932`.) ### C.3 — R7: the autonomy gate — **the approximation is real and needs its register row (BLOCKING)** The retail reading is now exactly right, and I verified both halves: - `CommandInterpreter::UsePositionFromServer` @0x006B3B40 (pseudo-C `:699506-699510`) is literally `return this->autonomy_level != 2`. acdream's `RuntimeCharacterState.UsePositionFromServer` (`:122`) is `AutonomyLevel != FullAutonomyLevel(2)` — **an exact port.** - `CommandInterpreter::SendMovementEvent` @0x006B4680 gates on `this->autonomy_level != 0` (@0x006B46BB, pseudo-C `:700283`). So `!UsePositionFromServer` sends at level 2 only; retail sends at levels 1 **and** 2. The implementer's characterisation is accurate, and the divergence is currently unreachable — `TrySetAutonomyLevel` has **zero production callers** (only `RuntimeCharacterStateTests`), so `AutonomyLevel` is always 2 and the two gates agree. Retail's own default is 2 (`command_line_autonomy_level = 0x2`, pseudo-C `:1088429`). That is precisely what an approximation is: correct today, wrong the day someone wires level 1. CLAUDE.md's register rule is binding and admits no implementer discretion — *"Any commit that introduces a deviation (an adaptation, an approximation, a stopgap, a 'retail does X but we…') adds its register row IN THE SAME COMMIT. … A deviation found without a row is a bug twice over."* The shipped disposition is a code comment at `RuntimeAcceptedPositionDriveController.cs:812-824` saying *"not register-worthy on its own (no user-visible#-labeled symptom yet)"*. A symptom is not the threshold; a deviation is. Either thread the raw `AutonomyLevel` through (the exact port, and the constructor already takes two optional funcs so the marginal cost is one more) or add the row. A comment is not the register. ### C.4 — R6: the corrected `enter_world` banner is now accurate Re-verified independently against the pseudo-C, not merely re-read: - `:93797` @0x004550EC and `:93824` @0x00455095 both sit inside **`SmartBox::HandleCreateObject` @0x00454C80**. ✓ - `CObjectMaint::CreateObject` is invoked at @0x00454FD8 *inside* that function — a callee, not the enclosing scope. ✓ - @0x004550EC is in the `if (arg3 != this->player_id)` **non-player** branch; only @0x00455095 follows `SmartBox::init_player` + `CellManager::ChangePosition` in the player branch. ✓ - The load-bearing negative still holds: the `Position*` overload @0x00516310 has exactly those two callers and the `int` overload @0x00516170 is reached only from @0x00516327 — `enter_world` is not on the portal path. The banner now states all four facts correctly. This citation is safe for future sessions to cite. --- ## §D — R4/A5: still open, and it does NOT block. Here is why the call changed. Round 1 rated this MAJOR on the premise (taken from contract §3.4) that the sink *"writes no pose"*, making the suffix the render entity's only mover. **That premise was wrong, and the A10 correction is right.** I verified `LiveEntityRuntime.TryApplyRuntimePlacementPlace` (`LiveEntityRuntime.cs:1386-1420`): a `Place` receipt calls `entity.SetPosition(projection.WorldPosition)`, sets `entity.Rotation`, sets `entity.ParentCellId = token.ExactCellId`, and calls `_spatial.RebucketLiveEntity` — `commitPose` defaults true and is passed `false` only for `WithdrawalRestored` (`:1364-1372`). The canonical receipt IS the mover; the suffix's writes are redundant repeats, exactly as the rewritten class comment now says. The comment is verified true. With that established, the coverage picture is materially different from round 1: - the sink's Place-receipt render-entity reframe + rebucket — **covered** (`RuntimePlacementPresentationSinkTests.Place_ReframesAndRebucketsExactSidecarWithoutMutatingRuntimePhysics`); - the sink's **portal gate discriminating** — **covered** (`PortalPlace_RequiresExactCurrentTransitHostAndSequence`, which drives a valid authority and a mismatched sequence); - the suffix's own entity write + destination bucket ordering — **covered** (the two `ConcretePlacement_*` tests, adapted to the new signature against a real `LiveEntityRuntime`/`WorldEntity`/`GpuWorldState`); - the **canonical body** pose and cell after an App-driven portal commit — **now covered**: the four weakened assertions were restored against `harness.Movement.Controller.Position`/`.CellId`, including A6's superseded-destination discriminator, and the App harness now runs a real Runtime rather than a fake placement. What remains uncovered is narrower than "the presentation suite was not built": no single test composes teleport-controller → canonical commit → real sink → suffix; the **local-player collision shadow** after a portal commit (#312's own layer) is unasserted; the T8 overwrite ordering is unasserted; and the refused-Place test asserts body/LoginComplete/IsActive but not the render entity. That is a genuine gap and it is #312-adjacent, so it must be recorded and closed in C5 — the implementer flagged it explicitly rather than claiming closure, which is the right behaviour. But it is no longer a "nothing asserts the only mover" hole, and it does not block this slice. --- ## §E — new findings ### N1 — MEDIUM — `PendingCount == 0` does not mean "the portal committed"; R1's failure mode survives on a narrow path `LocalPlayerTeleportController.cs:653-657` ```csharp if (_awaitingDeferredWake) { if (_acceptedPositionDrive.PendingCount != 0) return false; _awaitingDeferredWake = false; _placementCommitted = true; // ← inference return true; } ``` and identically `HeadlessSessionWorldProjection.cs:818` (`committed = _acceptedPositionDrive.PendingCount == 0;`). `PendingCount` is `_pending is null ? 0 : 1` (`RuntimeAcceptedPositionDriveController.cs:330`) — a shared, arm-agnostic counter. Three `Advance` paths clear a **portal** pending, and only one of them commits: | `Advance` site | commits? | logs? | |---|---|---| | `:918` completed-wake, authority current | yes → `ReconcileAndAcknowledgePortal` | yes | | `:918` completed-wake, authority stale | body committed by `RetryDeferred`, **suffix skipped** | `AbandonedAtWake` | | `:973` **watch died** — "most likely a subsequent accepted Position's merge-time Forget" | **no** | **no line at all** | | `:1020` `!IsPlacementCurrent` on the prepare-retry | **no** | **no line at all** | On the last two the caller latches `_placementCommitted = true` for a placement that never happened: the sequencer is released, `Place` fires, `ObserveMaterialized` acks a materialization that did not occur, and the player is revealed at the **origin**. That is exactly R1's shape, re-entered through the deferred door. Reachability is genuinely low — both hosts now gate the attempt behind collision readiness (`_worldReveal.Evaluate(...).IsReady` graphically, `_collision.IsReady(...)` headless), so a park is rare — and the Runtime-layer test `PortalDeferredCell_WakeAbandonsInsteadOfReconcilingWhenAuthorityWentStale` proves at least one non-committing convergence exists (`Assert.Equal(0, drive.PendingCount)` with no reconcile). Nothing tests the caller's inference against it. The fix is small: have the drive report a portal-specific terminal outcome (it already distinguishes them well enough to log `AbandonedAtWake`) instead of the caller inferring commit from a shared counter. Also give the two silent branches a probe line — under D-T8 they are portal-arrival attempts that ended. ### N2 — LOW/MEDIUM — headless `IsUnhydratable` is now hardcoded false `HeadlessSessionWorldProjection.cs:874` reports `IsUnhydratable: false` unconditionally, where it previously reported `!ready`. The old value was itself a conflation (not-yet-resident ≠ unhydratable), so this is not a regression in meaning — but headless can now never report an unhydratable destination, so a genuinely unhydratable claim spins in `PumpPortalCompletion` forever instead of taking AD-2's stated "loud unhydratable-placement path". Either derive the real predicate or state in the method's doc that headless does not model it. ### N3 — MEDIUM — a transient headless condition is now fatal `HeadlessSessionWorldProjection.cs:854` throws `InvalidOperationException` on the `default:` arm, which covers **`NotApplicable`** as well as `Rejected`. `NotApplicable` is returned by `TryExecuteAcceptedPortalArrival` for `record.PhysicsBody is null` and for an active initial-Create residence (`RuntimeAcceptedPositionDriveController.cs:243-251`) — hydration-race conditions, not "the reveal is stale". The exception message asserts a diagnosis ("the reveal itself is stale or the local player has no canonical body, neither recoverable by waiting") that is true for `Rejected` and not established for `NotApplicable`. Refusing to fake success is right; converting a possibly-transient condition into a process-killing throw on the host that must survive K4's 30-session / two-hour endurance profile is the wrong end of that trade. Split the arm: throw on `Rejected`, treat `NotApplicable` as a retryable wait with a bounded attempt budget (or a loud log plus `IsCollisionReady: false`). ### N4 — LOW — `RunsTeleportHook` over-gates the frame commit (§C.1) ### N5 — LOW — the plan-doc correction contradicts itself `docs/plans/2026-08-02-placement-cutover.md` now opens *"This line was accurate for both halves at the time it was written"*, explains that route 3 added the consumer and producer together, and then closes with *"'Zero producing call sites; the adapter does not exist' was accurate only for the producer half"* — which contradicts the opening sentence. The substance is right (the type, `IsValid`, `Pending.Portal`, the sinks' gates and `BeginAcceptedPlacementCore`'s gate pre-dated route 3; the arm did not); the paragraph needs one pass so a future reader can cite it. --- ## §E.2 — R8 residual `LogPortalArrivalAttempt` now fires on every Runtime-side exit under the gate's own `ACDREAM_PROBE_LOCAL_TELEPORT`, and a live `Contention` refusal was observed — R8's substance is closed and **§9's gate is now passable as specified**: `leash=armed` reads from `ConstraintManager.IsConstrained`, which `ConstrainTo` @0x00556240 sets unconditionally, so a committed arrival prints `armed`. Two App-side refusal causes still never reach Runtime and therefore emit no `[local-tp]` line: `cause=stale-reveal` (`LocalPlayerTeleportController.cs:666`, the `CanPlacePortalDestination` preflight) and `cause=host-token-unavailable` (`:737`). Both log through `PhysicsDiagnostics.LogTeleport`, gated by the *different* `ACDREAM_PROBE_TELEPORT`. Under the pinned gate environment these are invisible. Either route them through `LogLocalTeleportArrival` or add `ACDREAM_PROBE_TELEPORT=1` to §9's environment line. --- ## §F — gate evidence - **Release build**: green, 0 warnings / 0 errors. - **`AcDream.Runtime.Tests`**: 1,164 passed / 0 failed / **0 skipped**. - **`AcDream.Headless.Tests`**: 85 passed / 0 failed / **0 skipped**. - **`LocalPlayerTeleportControllerTests`**: 21 passed / 0 failed / **0 skipped**. - No `Skip` attribute in any touched test file. No test weakened: the four round-1 weakenings were restored with stronger targets (the real canonical body rather than the deleted fake's captured argument), and three genuinely new discriminators were added (`RefusedPlace_…`, `PortalCommitted_UnderServerControlSendsNoMovementEvent`, `PortalDeferredCell_WakeAbandonsInsteadOfReconcilingWhenAuthorityWentStale`, plus the headless park test). - Per process rule 3, none of this is evidence of correctness — it is evidence that nothing regressed while the above holes remain. --- ## §G — what must land to pass 1. **N1** — stop inferring commit from `PendingCount`; report a portal-specific terminal outcome, and log the two silent non-committing `Advance` branches. 2. **R7** — add the AD register row for the autonomy approximation, or thread the raw `AutonomyLevel` through and make it exact. Binding project rule; not an implementer judgment call. 3. **N3** — do not throw on `NotApplicable`; split it from `Rejected`. Cheap follow-ups, non-blocking: N2, N4 (gate only the UnStick/UnConstrain/ re-arm block on `RunsTeleportHook`), N5, and R8's two App-side causes. Record as a dated, named C5 item: R4/A5's residual — the end-to-end composition test, the local-player collision shadow after a portal commit, and the T8 overwrite ordering.