diag(physics): probe whether Runtime's world frame and App's origin ever disagree

#283 step 1: prove or disprove reachability before restructuring ownership.

Runtime rebases its world frame the instant an accepted Position carries
TeleportAdvanced (RuntimePhysicsState.ObserveLocalWorldFrame). App's
LiveWorldOriginState rebases only once StreamingOriginRecenterCoordinator
.Advance observes IsOriginRecenterRetirementComplete - many frames later,
after the old window has fully retired. Between those two edges the owners can
disagree by the source-to-destination landblock delta, and anything converted
in the gap lands a multiple of 192 m from the geometry App is building. Same
failure family as the zero-offset bug 670f307c fixed, with a wrong origin
rather than a missing one.

Reasoning has already closed most of the window: the recenter detaches EVERY
resident landblock before adopting the new origin, so old-origin collision is
retired first. What remains is the narrow gap between Runtime's flip and App's
BeginOriginRecenter, while old-origin geometry is still resident. Whether that
is ever actually hit is an empirical question, and the campaign rule is that a
restructure needs evidence, not a hypothesis.

ACDREAM_PROBE_WORLD_FRAME=1 emits one [world-frame] line per DISAGREEMENT at
DatLiveEntityProjectionMaterializer's landblock->world conversion - the exact
App-side counterpart of Runtime's TryGetWorldFrameOffset, and the site that
already holds both owners, so no new dependency is introduced. Silence across
a portal run is the evidence that #283 is unreachable and can close as a
permanent invariant instead of an ownership move.

Measurement only: the probe never gates placement, and the flag lives in
PhysicsDiagnostics with the rest of the ACDREAM_PROBE_* family per the
diagnostic-owner rule rather than as a scattered env read.

Complete Release solution: 10,836 passed / 4 skipped / 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-03 14:21:46 +02:00
parent 0c14c4029c
commit 898ff18b26
3 changed files with 67 additions and 0 deletions

View file

@ -163,6 +163,8 @@ internal sealed class DatLiveEntityProjectionMaterializer
CreateObject.ServerPosition position = canonicalSpawn.Position.Value;
int lbX = (int)((position.LandblockId >> 24) & 0xFFu);
int lbY = (int)((position.LandblockId >> 16) & 0xFFu);
if (AcDream.Core.Physics.PhysicsDiagnostics.ProbeWorldFrameEnabled)
ProbeWorldFrameAgreement(position.LandblockId);
var worldOrigin = new Vector3(
(lbX - _origin.CenterX) * 192f,
(lbY - _origin.CenterY) * 192f,
@ -1185,4 +1187,38 @@ internal sealed class DatLiveEntityProjectionMaterializer
}
return nullSlots >= 8;
}
/// <summary>
/// #283 reachability probe. This method is the App-side counterpart of
/// Runtime's <c>TryGetWorldFrameOffset</c>: both convert a
/// landblock-local network origin into the streamed world frame, and both
/// must use the SAME centre landblock or the entity lands a multiple of
/// 192 m from the geometry around it.
///
/// Runtime rebases on the accepted teleport Position; App's
/// <c>LiveWorldOriginState</c> rebases only after old-window retirement
/// completes. Emits one line per DISAGREEMENT — silence across a portal
/// run is the evidence that the window is unreachable in practice, and
/// that #283 can be closed as a permanent invariant rather than an
/// ownership restructure. Measurement only; it never gates placement.
/// </summary>
private void ProbeWorldFrameAgreement(uint landblockId)
{
uint runtimeCenter = _runtime.Physics.WorldFrameCenterLandblockId;
if (runtimeCenter == 0u || !_origin.IsKnown)
return;
int runtimeCenterX = (int)((runtimeCenter >> 24) & 0xFFu);
int runtimeCenterY = (int)((runtimeCenter >> 16) & 0xFFu);
if (runtimeCenterX == _origin.CenterX
&& runtimeCenterY == _origin.CenterY)
{
return;
}
float deltaX = (runtimeCenterX - _origin.CenterX) * 192f;
float deltaY = (runtimeCenterY - _origin.CenterY) * 192f;
Console.WriteLine(System.FormattableString.Invariant(
$"[world-frame] DISAGREE runtime=({runtimeCenterX},{runtimeCenterY}) app=({_origin.CenterX},{_origin.CenterY}) offsetDelta=({deltaX:F0}m,{deltaY:F0}m) projecting=0x{landblockId:X8}"));
}
}

View file

@ -61,6 +61,27 @@ public static class PhysicsDiagnostics
public static bool ProbeCellEnabled { get; set; } =
Environment.GetEnvironmentVariable("ACDREAM_PROBE_CELL") == "1";
/// <summary>
/// #283 reachability probe (2026-08-03). Runtime rebases its world frame
/// the instant an accepted Position carries TeleportAdvanced, while App's
/// <c>LiveWorldOriginState</c> rebases only once
/// <c>StreamingOriginRecenterCoordinator</c> observes old-window
/// retirement completion — many frames later. Between those edges the two
/// owners can disagree by the source-to-destination landblock delta, and
/// anything converted in that gap lands a multiple of 192 m from the
/// geometry App is building.
///
/// <para>When true, every projected placement compares Runtime's frame
/// centre against App's origin centre and emits one
/// <c>[world-frame]</c> line per DISAGREEMENT only — silence means the
/// window is never observed. This exists to prove or disprove
/// reachability before any ownership is restructured; it is a
/// measurement, never a gate. Initial state from
/// <c>ACDREAM_PROBE_WORLD_FRAME=1</c>.</para>
/// </summary>
public static bool ProbeWorldFrameEnabled { get; set; } =
Environment.GetEnvironmentVariable("ACDREAM_PROBE_WORLD_FRAME") == "1";
/// <summary>
/// Stuck-cast/missing-attack investigation (2026-07-30). When true,
/// every REMOTE ground-contact edge (HitGround / LeaveGround — each of

View file

@ -546,6 +546,16 @@ public sealed class RuntimePhysicsState : IDisposable
}
}
/// <summary>
/// #283: the landblock Runtime currently treats as world-frame (0,0), or
/// 0 before the local-player Create publishes one. Read-only and
/// diagnostic — App compares it against its own
/// <c>LiveWorldOriginState</c> centre to detect the teleport-window
/// disagreement described on
/// <c>PhysicsDiagnostics.ProbeWorldFrameEnabled</c>.
/// </summary>
internal uint WorldFrameCenterLandblockId => _worldFrameCenterLandblockId;
/// <summary>
/// #284: records that this session's local-player Create was accepted,
/// independently of whether it carried a usable landblock. The frame is