Routes the classifier's two NO-PLACEMENT remote branches — Interpolate (contact, PlayerDistance < 96 m) and NoPositionOperation (no contact) — through a Runtime-owned seam, and fixes the two divergences they carried. Teleport, far-snap and cell-less stay on the legacy App path; 4b owns them. Route 4 was split into 4a/4b after scoping put the whole route at 1,500-2,500 lines against a ~400 budget. 4a's branches perform no SetPosition, so this slice carries no deferred-cell park, no service-window guard and no allocation exposure — which is what made the split worth doing. Divergences fixed, both previously unfiled: * D1 — the NPC airborne branch hard-snapped Body.Position/Orientation and branched on the client-tracked rmState.Airborne, never consulting the wire IsGrounded bit. Retail's MoveOrTeleport @0x00516330 returns 0 at 0x0051636D and writes nothing. Player remotes were already correct; NPCs were not. * D2 — ConstrainTo was armed before the operation, unconditionally, so it fired on the airborne no-op retail skips and anchored to the PRE-move position. Retail arms it at 0x00454272, only when MoveOrTeleport returns nonzero, anchored to &arg2->m_position read live, i.e. post-move. AP-87 and TS-44 were carried deliberately, not delegated away. AP-87's three conditions — including firstUp, which one round silently dropped — are preserved as an explicit acdream policy layer applied AFTER the classifier commits to Interpolate; the two previously separate player/NPC copies are now one. TS-44 stays an NPC-only caller gate; extending sticky suppression to player remotes has no retail basis and no live evidence, so it was declined rather than absorbed. Landing is explicitly carved out of 4a's ownership on both arms. A landing packet classifies Interpolate, so an ordering slip would ENQUEUE a body that must PLANT and a creature knocked off a ledge would glide down over a packet interval. The carve-out is a named entry point returning AirborneSnap/SteadyStateInterpolate/ Legacy precisely so the PRECEDENCE is observable and testable rather than implied by statement order — that is how the slip happened once and was caught. The player/NPC asymmetry on landing is real and NOT resolved here: retail draws no such distinction, but converging them is a behaviour decision needing its own evidence. Filed into the 4b plan. Register: AP-135 filed for the two bookkeeping writes the airborne branch deliberately retains (rmState.CellId, LastServerPos/Time) — not retail's model, but load-bearing for our catch-up sweep and staleness timer, and verified not to be a canonical cell commit for ordinary remotes. AP-87 and TS-44 rewritten to describe the code. Honest remainder: App still owns branch selection, the airborne return, the cell write, the entity write and the shadow publish, and headless satisfies "both hosts drive the identical entry point" only vacuously since it returns early for remotes. That is written into the 4b bullet rather than left implicit. Cost: 364 non-comment production lines, 91% of the ~400 budget — the split did isolate the cheap half, but not by much. Do not carry "well under" into 4b's scoping. Gates: complete Release solution 10,938 passed / 4 skipped / 0 failed (pre-4a baseline 10,909). Four review rounds; the first three each introduced a new behavioural defect while fixing another, and each left a comment asserting behaviour that no longer matched — the final round's precedence matrix was traced cell-by-cell against HEAD with only the D1-intended difference. App tests call production entry points against a real WorldEntity and real classifier output, closing route 2's #292 gap rather than repeating it. Connected acceptance NOT run — needs a live second character. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
13 KiB
C4 route 4a — dual review findings, and a contract correction (2026-08-03)
Both mandated reviews returned FAIL. Nothing is committed. This supersedes the 4a contract where they disagree, and corrects an error in that contract that caused one of the findings.
Reviews: retail-conformance (Opus) and adversarial/architecture (Opus), run independently against the same uncommitted diff. Suite was green at 10,917/4/0, which again proves nothing.
Verified correct — do not churn
- The Runtime seam
RuntimeRemoteSteadyStatePosition.csitself: pure, stateless, correctly decomp-anchored, genuinely well tested. Both reviewers passed it standalone. - Retail truth re-verified independently:
MoveOrTeleport@0x00516330arg4 == 0->return 0writing nothing;player_distance < 96f->InterpolateTo;ConstrainTo@0x00454272 only insideif (MoveOrTeleport(...) != 0), anchored post-move. - AP-87's two headline conditions survive with identical semantics and no bypass path.
skipGenericPositionWriteIS derived purely from classification (the staged- cutover discriminator condition is met).- Per-entity currency on the callee is sound; the caller re-validates
IsCurrentPositionAuthoritybetween classify and apply. - Budget respected: ~343 production lines against ~400.
R0 — CRITICAL, and it is a defect in ALREADY-COMMITTED route 2
AcceptedPhysicsTimestamps.PreviousTeleport is always 0 on the live Position
path. InboundPhysicsStateController.cs:636 calls Current(gate, teleportAdvanced: ...) and omits the previousTeleport argument, which
defaults to 0 (:1119). The ONLY site that populates it is :926-941, the
deferred initial-create path — which is why the continuation executor is correct
and every newer consumer is not. Verified first-hand.
Two live consequences:
(a) Route 2, at HEAD, silently drops force corrections.
LiveEntityNetworkUpdateController.cs:1199 and
RuntimeLiveEntitySessionController.cs:268 feed the always-zero value into the
route-2 drive, where ValidAcceptedAuthority (classifier :524-525) requires
Previous == Accepted for ForcePosition. For any local player whose
TELEPORT_TS is nonzero — i.e. anyone who has portalled or recalled this session
— the authority is rejected and the correction is dropped. The user's @pklite
acceptance was genuine but narrow: that character had not teleported, so the
stamp was still 0.
(b) Route 4a misclassifies every previously-teleported remote.
TeleportAdvanced becomes IsNewer(0, T), true for any T in [1, 0x7FFF],
so the classifier returns SetPosition — a disposition 4a does not own — and
(per R3) the entity falls into the far-snap arm and hard-snaps on EVERY packet
at 5-10 Hz. That is worse than the pre-4a behaviour it replaced, and it is
exactly the per-packet stepping the connected gate screens for. Reachable the
first time an observed character portals or recalls, permanently thereafter.
Fix at the source: capture previousTeleport = gate.TeleportTimestamp
BEFORE TryAcceptPositionEvent mutates it, and pass it into Current — the
shape :926 already uses. Then audit every consumer.
Commit this separately and first. It is a shipped-code defect independent of 4a, and it needs its own bisectable commit and its own issue.
R1 — HIGH — my contract was wrong: the rebucket must NOT be deleted
The 4a contract listed RebucketLiveEntity among the generic-tail writes to
delete, and said the result "must reach the render entity through the existing
placement-projection sink instead." That instruction was copied from route 2
and does not transfer. Route 2 performs a placement and therefore has a
committed receipt to project. 4a's two branches perform NO placement, so there
is no receipt and nothing substitutes for the bucket transaction. The
implementer followed the contract precisely; the contract was wrong.
skipGenericPositionWrite currently also gates
_liveEntities.RebucketLiveEntity (:1400), which is the ONLY site that moves
an ordinary moving remote's spatial bucket (the nine other call sites are
player, projectile, teleport, hydration, materialization, equipped-child and
rescue paths; the per-tick DR writers deliberately do not rebucket — see
LiveEntityRuntime.cs:856-858). So for every grounded remote inside 96 m none
of these runs again: the GPU draw bucket, IsSpatiallyVisible +
RefreshPresentation, CommitRebucket (the canonical FullCellId), the
prepare_to_enter_world clock rebase, and PublishProjectionVisibilityChanged.
Failure: a creature chasing you across a landblock boundary keeps its body and
collision shadow but leaves its draw bucket behind, is frustum-culled, and goes
invisible-but-solid — the #184 class AP-87 exists to prevent, through a
different door. Secondary: the stale FullCellId feeds back as the classifier's
own CommittedCellId and as the ConstraintDistance cell key.
Required: keep the rebucket running for both 4a classifications. Delete only
the three render-pose writes. Also note R12 below: the per-UP rebucket doubles
as the pending-bucket promotion recovery (GpuWorldState.cs:1113-1126, the
2026-07-03 invisible-player fix) — the cell-change-gated canonical commit does
not cover it.
R2 — HIGH — the App acceptance tests are tautologies
LiveEntityNetworkRemoteSteadyStateIntegrationTests.cs:75-86 recomputes
skipGenericPositionWrite in the test body, asserts it true, then places the
mutation inside if (!skipGenericPositionWrite) — a branch the preceding assert
proves unreachable. The second test writes the tail sync itself and then asserts
its own arithmetic. Both pass unchanged with the production file reverted to
HEAD, and the fixture supplies a correct Previous/Accepted teleport pair
that production never produces, so the suite is structurally incapable of
catching R0(b).
This is #292 again, in a WEAKER form than route 2's: a source-text pin at least fails when the source changes; this never observes production at all. The contract's acceptance bullet said "behavioural, not a source-text pin… do not repeat it."
Required: a test that fails if the generic tail double-writes a remote. If
LiveEntityNetworkUpdateController genuinely cannot be constructed, then extract
the decision+mutation into something that CAN be tested and have production call
it — do not simulate production in the test body.
R3 — HIGH — "not Interpolate" is treated as "far", mis-owning five dispositions
Player :1723-1740, NPC :1867-1888 use if (Interpolate) … else <far snap>.
The else also swallows SetPosition (cell-less half — remotePlacementRequired
covers only the teleport half), RejectedAuthority, RejectedData, and null.
So a wire quaternion failing validation, or a cell-less remote, now hard-snaps
every packet where the legacy code did distance-based routing — a behaviour
change to branches contract item 7 forbids touching. ClassifyRemoteAcceptedPosition's
own doc comment (:47-50) claims null leaves the legacy path "completely
unchanged"; that is false.
Required: test explicitly for the two dispositions 4a owns. Everything else falls through to untouched legacy routing. One classification, one owner.
R4 — HIGH — the NPC airborne branch still writes cell, render entity and shadow
Contract item 5 says the airborne branch writes NOTHING. The player arm complies
(:1624-1628 returns). The NPC arm only skips the snap and falls through to
rmState.CellId = p.LandblockId (:1931 — which commits the canonical cell via
RemoteMotion.cs:169-177 and can rebucket), LastServerPos/Time,
RemoteServerControlledVelocityCycle.Apply (an animation decision from an
airborne packet), the entity.SetPosition/ParentCellId/Rotation tail
(:1976-1978), and LiveEntityShadowPublisher.TryPublishRemote (:1979).
Worse than before because the body no longer moves: previously body, cell, entity and shadow all agreed; now the body stays put while the cell jumps to the server's and the shadow publishes against a cell that need not contain it.
(Contract-precision note: :1616 writes rmState.CellId before the PLAYER
return too. That is pre-existing free-fall bookkeeping the contract's "not the
cell" wording did not intend to forbid — decide deliberately and record it,
rather than leaving the contract and the code silently disagreeing.)
R5 — MEDIUM — ConstrainTo lost on the player-remote landing packet
The deleted unconditional arm sat before if (IsPlayerGuid(...)), so it ran for
the landing transition. The new arm at :1747-1752 is after the landing block's
return at :1710. A landing UP is a grounded near correction where retail's
MoveOrTeleport returns nonzero, so retail DOES arm the leash. Behaviour loss
on a path 4a was to leave alone. Also: when the route is null or Rejected*,
ConstrainAfterRouting is false so the leash never re-arms, yet the else arm
still hard-snaps — a hard move with a stale anchor.
R6 — MEDIUM — AP-87 and TS-44 changed silently; both register rows now misdescribe the code
AP-87: the NPC variant's third condition firstUpNpc
(LastServerPosTime <= 0) was dropped with no replacement, and the updated row
still describes it as a "belt hint". Low blast radius (a UP-created
RemoteMotion is seeded so bodyToTarget == 0), but the contract demanded the
choice be stated, and the original code carried an explicit comment about why
LastServerPosTime is unreliable.
TS-44: the sticky check moved inside ApplyInterpolate, which BOTH kinds
call, so it now suppresses player-remote near corrections that previously had no
sticky check at all (the old snapSuppressedByStick gate was structurally
unreachable for players). Player remotes are stickable
(LiveEntityMotionRuntimeController.cs:144-145, :342-352). The updated row
still says "NPC UpdatePosition enqueue is suppressed" and calls the App gate an
"NPC-only caller gate" — both now false. The player arm is also internally
inconsistent: near is suppressed, far is not.
Required: decide each deliberately, and make the rows true.
R7 — MEDIUM — contract items 1 and 2 are not met; this is a helper extraction, not an ownership transfer
The Runtime "owner" is two stateless statics. App still owns request assembly
(ClassifyRemoteAcceptedPosition is private to the App controller), branch
selection, the airborne early return, the cell write, the entity write, and the
shadow publish. No second host can reuse any of it. The headless claim is
factually true (RuntimeLiveEntitySessionController.cs:212-216 returns early
for remotes, so nothing diverges) but it satisfies item 2 by redefinition.
Note Runtime ALREADY builds this exact request in
RuntimeInitialCreateContinuationExecutor.ApplyPositionAction:1907-1945. The
new App builder is a third copy of the same construction — which is precisely
how R0 and R8 diverged from it. Prefer sharing that builder over maintaining a
third copy.
R8 — MEDIUM-LOW — the request builder fabricates Vector3.Zero, violating a documented invariant
:75-77 uses _playerController?.Position ?? Vector3.Zero. GameRuntime.cs:288-290
states the rule for this exact field: a null controller "must yield null, never a
fabricated Vector3.Zero that would misclassify every remote entity as
implausibly far." RuntimeInitialCreateContinuationExecutor.ResolveInputs:510-521
honours it. The new builder does the opposite.
R9 — LOW-MEDIUM — the new generation plumbing is decorative
RuntimeEntityObjectLifetime.CurrentGeneration() and LiveEntityRuntime.Generation
return the lifetime's CURRENT generation, not the classified record's. The
classifier only tests Generation.Value != 0, never compares it — so the token
cannot detect a generation change, and the currency it claims to add is supplied
entirely by the surrounding IsCurrentPositionAuthority checks. Two new public
members for a non-zero placeholder. Also _generation is assigned in
BindEventContext but never cleared in Dispose, unlike its siblings.
Either make it load-bearing or drop it.
R10 — LOW — residue
- R11:
ApplyInterpolate's return value is discarded at both call sites, and the NPC caller still wraps it in its ownif (!snapSuppressedByStick)— duplicating the check that moved into the seam. - R12: the deleted per-UP rebucket also lost the pending-bucket promotion
recovery (
GpuWorldState.cs:1113-1126, the 2026-07-03 invisible-player fix). Covered by fixing R1, but note it explicitly. - R13: HTML entity escapes leaked into plain
//comments (>=96 m) at:1718,:1735,:1864,:1883. - R14:
preSnapPos(:1394) assigned, never read, with a comment describing behaviour that no longer exists.
R15 — live-gate addition, not a code defect
D1 makes ACE's wire IsGrounded newly load-bearing for NPC remotes. ACE emits it
from TransientState & OnWalkable (PositionPack.cs:73), while acdream's NPC
free-fall is gated on the client-tracked rmState.Airborne, set only by
0xF74E VectorUpdate or !Body.OnWalkable — never from the wire bit. A creature
ACE reports as not-in-contact while the client believes it grounded now receives
NO correction where the legacy routing pulled it.
Add to the connected gate: push a monster off a ledge / pull one down a cliff.
Gate
Complete Release suite, not a subset. Pre-4a baseline is 10,909/4/0. R2 means the current green number is not evidence for the thing it claims to test.