feat(runtime): C3c - production placement cutover: both hosts on the residence conductors (routes 1+8)

Campaign P remaining-physics-divergence, placement cutover slice C3c
(docs/plans/2026-08-02-placement-cutover.md). Both production hosts now
register every initial Create through the residence + continuation-
executor + first-entry-conductor machinery (C0-C3b):

- Graphical (route 1): RegisterEntityWithInitialResidence at Create; the
  shared RuntimeFirstEntryDriveController pumps both conductors from the
  placement-receipt flow; MaterializeProjection and RebucketLiveEntity
  are presentation-only while a residence is ACTIVE (ExecutorCompleted is
  the presentation-binding receipt); post-residence entities take the
  full legacy path including the prepare_to_enter_world clock edges.
  PlayerModeController attaches presentation to the Runtime-published
  controller; its legacy resolve/step-heights/host-construction path is
  deleted; presentation-only rollback (retail has no entry-flow rollback).
- Headless (route 8): OnSpawned registers with residence when a drive
  exists; content-less sessions keep the pre-flip direct registration;
  SynchronizeLocalPlayer/CreateController/ApplySetupStepHeights deleted;
  prepared-collision read failure is a typed AwaitingCollisionSource
  retry; far remotes outside the service window complete celless.
- RuntimeLocalPlayerMovementState.Controller setter sealed internal; all
  controller mutation flows through the publication lifecycle.

Fix slices landed within this cutover, each dual-gated:
- F1: live movement-stat/server-physics application routed through the
  Runtime ownership seam (post-logout ingest crash on the retired
  controller eliminated; RuntimeMovementSkillProjection deleted).
- F2: login activation wedge - collision-admission prefix gate factored
  out of the seal (reentrant-commit RejectedAuthority), rearm generation
  identity corrected, PlayerModeAutoEntry requires the Runtime-published
  controller (world reveal can no longer seal unmaterialized).
- F3: landblock-prefix 0-sentinel replaced by explicit absent-id guards;
  map-corner landblocks (grid row/col 0) fully legal through admission,
  park/rearm/retire, quiescence, and outdoor shadow seeds.
- F5: local-player first-entry ground contact seeded by the shared
  SpawnPlacementSettler (moved App->Core) at FinalizeActivation - the
  retail first-gravity-frame touch (enter_world 0x00516170 carries no
  seed); the legacy unconditional force-seed is overwritten by a real
  floor-found contact; airborne spawns stay airborne; outbound contact
  bit verified end-to-end. Fixes the standing-cast 'You can't do that
  while in the air!' rejections.
- R1 (dual-review round): login constraint leash armed at the committed
  placement (HandleReceivedPosition 0x00453FD0 analog); register rows
  AD-61 (settle-timing compression now covering the local player) and
  AD-42 (repointed off the deleted resolve split) in this commit;
  residence-conversion owner API; wire-landblock guards; drive-pending
  ledger in IsConverged; route attach/detach latch; executor-drain drift
  model documented + source-pinned.

Gates: Runtime 1,003, App 4,039/3 skips, Headless 79, complete solution
10,816/0 failed/4 skips (Release, -m:1); connected lifecycle/reconnect
gate PASS (logs/connected-world-gate-20260802-175401; graceful exits,
world-visible, zero airborne rejections). The nine-stop soak remains red
for the pre-existing 6b28ff99 whole-world collision-clone throughput
regression (attributed with evidence; scheduled as its own slice before
C5). Dual Opus reviews (retail-conformance + adversarial): delta PASS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-02 18:10:33 +02:00
parent 78f1eb1896
commit 529e0e9d88
68 changed files with 5977 additions and 831 deletions

View file

@ -109,8 +109,14 @@ internal readonly record struct RuntimeCollisionPrefixQuiescenceToken(
ulong CollisionGeneration,
ulong OperationId)
{
internal bool IsValid => LandblockPrefix != 0u
&& (LandblockPrefix & 0xFFFFu) == 0u
// C3c-F3: presence is discriminated by OperationId (allocated from a
// monotonic counter starting at 1, so a default token always carries 0)
// and CollisionGeneration (generations also start at 1) — NOT by
// LandblockPrefix != 0. Prefix 0x00000000 is the legitimate prefix of
// landblock (0,0) (id 0x0000FFFF, Dereth's map corner); the old
// prefix-based term made every real corner-landblock token read as
// invalid, wedging TryGetCurrentQuiescence and every release path.
internal bool IsValid => (LandblockPrefix & 0xFFFFu) == 0u
&& CollisionGeneration != 0UL
&& OperationId != 0UL;
}
@ -778,9 +784,14 @@ internal sealed class RuntimeSetPositionState : IDisposable
EnsureNotDisposed();
if (collisionGeneration == 0UL)
throw new ArgumentOutOfRangeException(nameof(collisionGeneration));
uint prefix = landblockId & 0xFFFF0000u;
if (prefix == 0u)
// C3c-F3: reject only the genuinely-absent landblock id (0). Prefix
// 0x00000000 is landblock (0,0) — the map corner — so a prefix == 0
// test can no longer stand in for "no landblock"; that sentinel
// collision crashed every collision publication whose streaming
// window reached the corner (connected-gate 20260802-135444).
if (landblockId == 0u)
throw new ArgumentOutOfRangeException(nameof(landblockId));
uint prefix = landblockId & 0xFFFF0000u;
if (_collisionPrefixQuiescence.TryGetValue(
prefix,
@ -1848,6 +1859,45 @@ internal sealed class RuntimeSetPositionState : IDisposable
&& operation.WakeableLostCell;
}
/// <summary>
/// C3c-F2: the identity check below is against
/// <see cref="RuntimePhysicsState.CollisionGenerationAuthority"/> — the
/// generation the collision world currently HOLDS — not against
/// <c>ExpectedCollisionGeneration</c>, which means two different things
/// at the two ends of this wait. At park time (this class's own
/// <c>TryPrepareDormantLocalActivationCommit</c>) an admission for the
/// destination landblock is in flight, so Expected == that admission's
/// generation G and the lease correctly parks against G. The wake that
/// sets <c>CollisionGenerationReady</c> is
/// <c>CommitCollisionGeneration(lb, G, ready)</c>, and the very next
/// statement in RuntimePhysicsState retires the admission
/// (AdvanceCommittedActivation) while leaving the committed generation at
/// G — from that instant Expected returns G+1, a generation that does not
/// exist and may never be begun. Comparing the parked G against Expected
/// therefore refused every login rearm forever (the connected-gate
/// DeferredCell wedge: controller never published, world never visible).
/// The committed-authority comparison keeps every staleness guarantee: a
/// superseding BeginCollisionAdmission or a CancelCollisionGeneration
/// moves the authority off G and this lease still refuses to rearm.
///
/// <para>
/// The trailing
/// <see cref="RuntimePhysicsState.IsCollisionEvaluationPrefixAdmissible"/>
/// term is the second half of the same C3c-F2 defect and is what the live
/// probe caught: the collision-generation commit reenters the host's
/// first-entry pump BEFORE its own admission is retired
/// (RuntimePhysicsState.cs:2503 commits the generation, :2552-2558 retires
/// the admission). Rearming inside that window moves the lease out of
/// AwaitingCell and the very next evaluation fails
/// <c>TrySealCollisionEvaluationAuthority</c> on the still-registered
/// admission — at which point EvaluateActivation can no longer report
/// DeferredCell (the operation is no longer AwaitingCell) and returns
/// RejectedAuthority, which is TERMINAL for the conductor. Refusing the
/// rearm until the prefix is evaluable keeps the lease parked and
/// retryable, exactly as the remote wake path already does with
/// <c>TryGetBlockingQuiescence</c> (:4069-4095).
/// </para>
/// </summary>
private bool TryRearmDeferredDormantLocalActivation(
RuntimeEntityRecord record,
PhysicsBody body,
@ -1868,8 +1918,10 @@ internal sealed class RuntimeSetPositionState : IDisposable
|| !operation.CollisionGenerationReady
|| operation.ProjectionSequence != 0UL
|| operation.CollisionGeneration != _physics
.ExpectedCollisionGeneration(operation.ExactCellId)
|| !_physics.Engine.IsSpawnCellReady(operation.ExactCellId))
.CollisionGenerationAuthority(operation.ExactCellId)
|| !_physics.Engine.IsSpawnCellReady(operation.ExactCellId)
|| !_physics.IsCollisionEvaluationPrefixAdmissible(
operation.ExactCellId))
{
return false;
}
@ -3366,14 +3418,19 @@ internal sealed class RuntimeSetPositionState : IDisposable
command);
CollisionPrefixQuiescence? quiescence =
_collisionPrefixQuiescence.GetValueOrDefault(prefix);
// C3c-F3: pass the overrides through as genuinely optional —
// `quiescence?.` yields null (absent) with no quiescence and the
// token's exact values (present, prefix 0x00000000 included)
// with one. The old `?? 0u` collapse made a corner-landblock
// quiescence indistinguishable from "no quiescence".
RuntimeSetPositionOutcome parked = ParkDeferred(
operation,
result,
publishImmediately: false,
collisionGenerationOverride:
quiescence?.Token.CollisionGeneration ?? 0UL,
quiescence?.Token.CollisionGeneration,
collisionPrefixOverride:
quiescence?.Token.LandblockPrefix ?? 0u);
quiescence?.Token.LandblockPrefix);
if (_pendingProjection.TryGetValue(
parked.Projection.Sequence,
out RuntimePlacementProjectionSnapshot staged))
@ -3929,12 +3986,22 @@ internal sealed class RuntimeSetPositionState : IDisposable
_operationPool.Clear();
}
/// <summary>
/// C3c-F3: the quiescence-override pair is nullable — null means "no
/// quiescence holds this park", a present value means "parked under that
/// quiescence's exact prefix/generation". Nullable uint is the chosen
/// has-prefix representation for the whole chain because the previous
/// 0-sentinel collided with landblock (0,0)'s legitimate prefix
/// 0x00000000: a corner-landblock quiescence override read as "absent",
/// so <see cref="Operation.CollisionQuiescenceHeld"/> derived false and
/// the parked operation skipped the QuiescenceHeld stage entirely.
/// </summary>
private RuntimeSetPositionOutcome ParkDeferred(
Operation operation,
in PhysicsSetPositionResult result,
bool publishImmediately = true,
ulong collisionGenerationOverride = 0UL,
uint collisionPrefixOverride = 0u)
ulong? collisionGenerationOverride = null,
uint? collisionPrefixOverride = null)
{
PhysicsBody body = operation.Body!;
body.Orientation = result.Orientation;
@ -3969,13 +4036,11 @@ internal sealed class RuntimeSetPositionState : IDisposable
operation.WakeableLostCell = true;
operation.EnteringWorldFromCelllessResidence = true;
ArmLostFamilyDeadlines(operation);
operation.CollisionGeneration = collisionGenerationOverride != 0UL
? collisionGenerationOverride
: _physics.ExpectedCollisionGeneration(result.CellId);
operation.CollisionPrefix = collisionPrefixOverride != 0u
? collisionPrefixOverride
: result.CellId & 0xFFFF0000u;
operation.CollisionQuiescenceHeld = collisionPrefixOverride != 0u;
operation.CollisionGeneration = collisionGenerationOverride
?? _physics.ExpectedCollisionGeneration(result.CellId);
operation.CollisionPrefix = collisionPrefixOverride
?? result.CellId & 0xFFFF0000u;
operation.CollisionQuiescenceHeld = collisionPrefixOverride.HasValue;
operation.Command = operation.Command with
{
Physics = operation.Command.Physics with