feat(runtime): construct remote bodies at Create per retail set_description

Cutover slice C3b: residence-route remote/creature/projectile Creates now
get their canonical PhysicsBody at Create time — retail's order, closing
the C3 flip's Finding C (production builds bodies at first motion; retail
builds them in ACCObjectMaint::CreateObject). RuntimeRemoteBodyDescription
walks set_description 0x00514F40 exactly: the motion-table gate (zero id
PASSES — verified at 0051871f/005127ca), the frame-vs-movement branch
keyed on retail's movement_buffer != 0 (an empty-buffer movement payload
takes the PLACEMENT branch and writes no autonomy — the wire-shape defect
the retail review caught), set_state, the byte-certain friction gate
(inclusive [0,1]; NaN deliberately skipped per the gates doc's sanctioned
deviation), the set_elasticity clamp with retail's unordered-to-zero NaN
routing (ACE diverges to 0.1 on that edge), the translucency gate
(!= 0.0f, original always recorded), velocity via setter, omega raw, and
ctor-defaults for absent wire fields (0.95f/0.05f/0 — the fresh-desc-per-
message flow verified at both UnPack call sites). InWorld stays false
until submission, the enter_world analog.

RuntimeRemoteFirstEntryState sequences mover-prep -> body construction ->
placement -> acknowledgement -> Execute with every C3a hardening
inherited: exactly-once stages, the shared acknowledge-stage
discriminator (extracted to RuntimeFirstEntryAcknowledgement, one body
for both conductors), typed Contention against in-flight remote-motion
binds, never-clobber body binding through the canonical writer (foreign
body fails closed — provably safe coexistence with today's
build-at-first-motion path in both directions), automatic convergence
through the retirement fan-out, and the construction receipt riding the
terminal Advance. Dormant: no production caller; C3c wires both hosts.

Reviewed: retail-conformance PASS (the construction order, both gate
boundary/NaN semantics, the motion-table and autonomy verdicts all
re-derived from the pseudo-C) + architecture/adversarial PASS after one
fix round. Runtime 982/982; complete Release solution 10,777 passed / 4
intentional skips.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-02 10:20:48 +02:00
parent d62b99509e
commit 0934a12111
6 changed files with 2083 additions and 41 deletions

View file

@ -64,7 +64,13 @@ public readonly record struct RuntimeEntityObjectOwnershipSnapshot(
/// <c>Advance</c>), but fully constructed/wired like every other owner
/// here, so its own ownership must converge to zero the same way.
/// </summary>
int LocalPlayerFirstEntryActiveCount = 0)
int LocalPlayerFirstEntryActiveCount = 0,
/// <summary>
/// C3b: outstanding <see cref="RuntimeRemoteFirstEntryState"/> tracked
/// keys - the remote/projectile Create-time body-construction conductor.
/// Dormant like its C3a sibling; converges to zero the same way.
/// </summary>
int RemoteFirstEntryActiveCount = 0)
{
public bool IsConverged =>
IsDisposed
@ -87,6 +93,7 @@ public readonly record struct RuntimeEntityObjectOwnershipSnapshot(
&& InitialCreateExecutorProgressCount == 0
&& PendingCompletionReceiptCount == 0
&& LocalPlayerFirstEntryActiveCount == 0
&& RemoteFirstEntryActiveCount == 0
&& StreamSubscriberCount == 0
&& PlacementStreamSubscriberCount == 0
&& PendingDispatchCount == 0
@ -176,6 +183,15 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
InitialCreateResidences,
InitialCreateExecution,
Physics);
// C3b: the remote/projectile analog of the conductor above — retail
// body construction at Create time in place of the publication
// chain. Dormant like its sibling (no production caller of Advance);
// constructed and wired identically so its ownership converges the
// same way.
RemoteFirstEntry = new RuntimeRemoteFirstEntryState(
InitialCreateResidences,
InitialCreateExecution,
Physics);
// Round 3 B3: every residence retirement path - not only the
// executor's own DiscardProgress calls - must converge the
// executor's progress AND its separately-tracked pending
@ -190,6 +206,10 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
// updated doc comment for why this is now multicast.
InitialCreateResidences.BindRetirementNotification(
key => LocalPlayerFirstEntry.Forget(key));
// C3b: the remote conductor joins the SAME multicast retirement
// fan-out, third in registration order.
InitialCreateResidences.BindRetirementNotification(
key => RemoteFirstEntry.Forget(key));
// F2: reaps the executor's completion-receipt correlation entry
// exactly when a host acknowledges the ExecutorCompleted receipt it
// correlates - mirrors the residence-retirement binding immediately
@ -245,6 +265,15 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
InitialCreateResidences,
InitialCreateExecution,
Physics);
// C3b: the remote/projectile analog of the conductor above — retail
// body construction at Create time in place of the publication
// chain. Dormant like its sibling (no production caller of Advance);
// constructed and wired identically so its ownership converges the
// same way.
RemoteFirstEntry = new RuntimeRemoteFirstEntryState(
InitialCreateResidences,
InitialCreateExecution,
Physics);
// Round 3 B3: every residence retirement path - not only the
// executor's own DiscardProgress calls - must converge the
// executor's progress AND its separately-tracked pending
@ -259,6 +288,10 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
// updated doc comment for why this is now multicast.
InitialCreateResidences.BindRetirementNotification(
key => LocalPlayerFirstEntry.Forget(key));
// C3b: the remote conductor joins the SAME multicast retirement
// fan-out, third in registration order.
InitialCreateResidences.BindRetirementNotification(
key => RemoteFirstEntry.Forget(key));
// F2: reaps the executor's completion-receipt correlation entry
// exactly when a host acknowledges the ExecutorCompleted receipt it
// correlates - mirrors the residence-retirement binding immediately
@ -314,6 +347,15 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
InitialCreateResidences,
InitialCreateExecution,
Physics);
// C3b: the remote/projectile analog of the conductor above — retail
// body construction at Create time in place of the publication
// chain. Dormant like its sibling (no production caller of Advance);
// constructed and wired identically so its ownership converges the
// same way.
RemoteFirstEntry = new RuntimeRemoteFirstEntryState(
InitialCreateResidences,
InitialCreateExecution,
Physics);
// Round 3 B3: every residence retirement path - not only the
// executor's own DiscardProgress calls - must converge the
// executor's progress AND its separately-tracked pending
@ -328,6 +370,10 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
// updated doc comment for why this is now multicast.
InitialCreateResidences.BindRetirementNotification(
key => LocalPlayerFirstEntry.Forget(key));
// C3b: the remote conductor joins the SAME multicast retirement
// fan-out, third in registration order.
InitialCreateResidences.BindRetirementNotification(
key => RemoteFirstEntry.Forget(key));
// F2: reaps the executor's completion-receipt correlation entry
// exactly when a host acknowledges the ExecutorCompleted receipt it
// correlates - mirrors the residence-retirement binding immediately
@ -353,6 +399,7 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
internal RuntimeInitialCreateContinuationExecutor InitialCreateExecution
{ get; }
internal RuntimeLocalPlayerFirstEntryState LocalPlayerFirstEntry { get; }
internal RuntimeRemoteFirstEntryState RemoteFirstEntry { get; }
public RuntimeEntityObjectOwnershipSnapshot CaptureOwnership()
{
@ -389,7 +436,8 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
InitialCreateExecution.ReplayFailureCount,
InitialCreateExecution.LastReplayFailure is not null,
InitialCreateExecution.PendingCompletionReceiptCount,
LocalPlayerFirstEntry.CaptureOwnership().ActiveCount);
LocalPlayerFirstEntry.CaptureOwnership().ActiveCount,
RemoteFirstEntry.CaptureOwnership().ActiveCount);
}
public void BindEventContext(
@ -1734,6 +1782,7 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
InitialCreateResidences.Clear();
InitialCreateExecution.DiscardAll();
LocalPlayerFirstEntry.DiscardAll();
RemoteFirstEntry.DiscardAll();
Physics.CollisionReports.LeaveWorldBatch(active);
Physics.ResetSessionPhysics();
Entities.BeginSessionClear();