diff --git a/src/AcDream.Core/Physics/PhysicsDiagnostics.cs b/src/AcDream.Core/Physics/PhysicsDiagnostics.cs
index 260ed07..43a1a8d 100644
--- a/src/AcDream.Core/Physics/PhysicsDiagnostics.cs
+++ b/src/AcDream.Core/Physics/PhysicsDiagnostics.cs
@@ -408,6 +408,21 @@ public static class PhysicsDiagnostics
public static bool ProbePlacementFailEnabled { get; set; } =
Environment.GetEnvironmentVariable("ACDREAM_PROBE_PLACEMENT_FAIL") == "1";
+ ///
+ /// Phase W Stage 0 (2026-06-02): one [cell-swept] line per
+ /// call — the
+ /// transition's swept cell (sp.CurCellId/sp.CheckCellId)
+ /// vs the position-derived cell the legacy static
+ /// path used. Proves the swept
+ /// cell is stable where the static one strobes at the doorway boundary.
+ ///
+ ///
+ /// Initial state from ACDREAM_PROBE_SWEPT=1. Zero cost when off.
+ ///
+ ///
+ public static bool ProbeSweptEnabled { get; set; } =
+ Environment.GetEnvironmentVariable("ACDREAM_PROBE_SWEPT") == "1";
+
///
/// A6.P3 issue #98 step-walk investigation (2026-05-23). When true,
/// emits one [step-walk] line at selected points in the transition
diff --git a/src/AcDream.Core/Physics/PhysicsEngine.cs b/src/AcDream.Core/Physics/PhysicsEngine.cs
index 4fd40ef..33d03db 100644
--- a/src/AcDream.Core/Physics/PhysicsEngine.cs
+++ b/src/AcDream.Core/Physics/PhysicsEngine.cs
@@ -898,6 +898,15 @@ public sealed class PhysicsEngine
$"[resolve] ent=0x{movingEntityId:X8} in=({currentPos.X:F3},{currentPos.Y:F3},{currentPos.Z:F3}) cell=0x{cellId:X8} tgt=({targetPos.X:F3},{targetPos.Y:F3},{targetPos.Z:F3}) out=({probePost.X:F3},{probePost.Y:F3},{probePost.Z:F3}) cell=0x{sp.CheckCellId:X8} ok={ok} groundedIn={isOnGround} cp={probeCp} hit={probeHit} walkable={sp.HasLastWalkablePolygon}"));
}
+ // Phase W Stage 0 (2026-06-02): [cell-swept] probe — swept cell vs static-derived cell.
+ // Emits before the ResolveResult is built so it shows what BOTH paths would return.
+ // No ResolveCellId call here (it has a CellGraph.CurrCell side effect). No behavior change.
+ if (PhysicsDiagnostics.ProbeSweptEnabled)
+ {
+ Console.WriteLine(System.FormattableString.Invariant(
+ $"[cell-swept] ent=0x{movingEntityId:X8} ok={ok} inCell=0x{cellId:X8} curCell=0x{sp.CurCellId:X8} checkCell=0x{sp.CheckCellId:X8} curPos=({sp.CurPos.X:F3},{sp.CurPos.Y:F3},{sp.CurPos.Z:F3}) checkPos=({sp.CheckPos.X:F3},{sp.CheckPos.Y:F3},{sp.CheckPos.Z:F3})"));
+ }
+
ResolveResult resolveResult;
if (ok)
{
diff --git a/tests/AcDream.Core.Tests/Physics/PhysicsDiagnosticsTests.cs b/tests/AcDream.Core.Tests/Physics/PhysicsDiagnosticsTests.cs
index 8c9d45b..81ee081 100644
--- a/tests/AcDream.Core.Tests/Physics/PhysicsDiagnosticsTests.cs
+++ b/tests/AcDream.Core.Tests/Physics/PhysicsDiagnosticsTests.cs
@@ -143,6 +143,17 @@ public class PhysicsDiagnosticsTests
}
}
+ // -----------------------------------------------------------------------
+ // ProbeSweptEnabled — Phase W Stage 0 (2026-06-02): [cell-swept] diagnostic.
+ // -----------------------------------------------------------------------
+
+ [Fact]
+ public void ProbeSweptEnabled_DefaultsToFalse()
+ {
+ PhysicsDiagnostics.ProbeSweptEnabled = false;
+ Assert.False(PhysicsDiagnostics.ProbeSweptEnabled);
+ }
+
// -----------------------------------------------------------------------
// ProbeDumpGfxObjs — parallel of ProbeDumpCells (A6.P3 #98, evening v2).
// -----------------------------------------------------------------------