diff --git a/src/AcDream.Core/Physics/PhysicsDataCache.cs b/src/AcDream.Core/Physics/PhysicsDataCache.cs
index 3f89793..6fd45a4 100644
--- a/src/AcDream.Core/Physics/PhysicsDataCache.cs
+++ b/src/AcDream.Core/Physics/PhysicsDataCache.cs
@@ -168,6 +168,15 @@ public sealed class PhysicsDataCache
LocalAabbMin = aabbMin,
LocalAabbMax = aabbMax,
};
+
+ if (PhysicsDiagnostics.ProbeCellCacheEnabled)
+ {
+ var root = cellStruct.PhysicsBSP?.Root;
+ int bspRootPolyCount = root?.Polygons?.Count ?? 0;
+ bool bspRootHasChildren = root?.PosNode is not null || root?.NegNode is not null;
+ Console.WriteLine(System.FormattableString.Invariant(
+ $"[cell-cache] envCellId=0x{envCellId:X8} physicsPolyCount={cellStruct.PhysicsPolygons?.Count ?? 0} resolvedCount={resolved.Count} bspRootPolyCount={bspRootPolyCount} bspRootHasChildren={bspRootHasChildren}"));
+ }
}
///
diff --git a/src/AcDream.Core/Physics/PhysicsDiagnostics.cs b/src/AcDream.Core/Physics/PhysicsDiagnostics.cs
index bb49b20..05935e8 100644
--- a/src/AcDream.Core/Physics/PhysicsDiagnostics.cs
+++ b/src/AcDream.Core/Physics/PhysicsDiagnostics.cs
@@ -195,4 +195,30 @@ public static class PhysicsDiagnostics
///
public static bool ProbeIndoorBspEnabled { get; set; } =
Environment.GetEnvironmentVariable("ACDREAM_PROBE_INDOOR_BSP") == "1";
+
+ ///
+ /// Indoor walking Phase D follow-up (2026-05-19). When true, emits one
+ /// [cell-cache] line each time
+ /// caches a new EnvCell. Reports per-cell polygon counts and BSP root
+ /// structure so the caller can cross-reference with [indoor-bsp]
+ /// lines to distinguish between:
+ ///
+ /// - Empty data (physicsPolyCount=0 or resolvedCount=0)
+ /// — candidate (a)/(c) in the poly=n/a investigation.
+ /// - Non-zero polygon counts but bspRootPolyCount=0 at
+ /// root + tree has children — correct structure for non-leaf root,
+ /// leaves hold the poly refs; not a bug.
+ /// - Non-zero polygon counts but bspRootPolyCount=0 at
+ /// root AND root is a leaf (bspRootHasChildren=false) — BSP leaf with
+ /// zero poly refs, candidate (b)/(d).
+ ///
+ /// This diagnostic fires at most once per EnvCell (cache is no-op after
+ /// first population). It does NOT have a DebugPanel mirror yet — this is
+ /// a one-shot capture tool, not a persistent toggle. Promote to full
+ /// infrastructure after the root cause is identified.
+ ///
+ /// Initial state from ACDREAM_PROBE_CELL_CACHE=1.
+ ///
+ public static bool ProbeCellCacheEnabled { get; set; } =
+ Environment.GetEnvironmentVariable("ACDREAM_PROBE_CELL_CACHE") == "1";
}