diff --git a/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs b/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs
index 90df2dd..3f8297b 100644
--- a/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs
+++ b/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs
@@ -488,21 +488,68 @@ public class CellarUpTrajectoryReplayTests
/// bumping the cottage floor from BELOW.
///
///
- /// This is the actual #98 bug, NOT a step-up / AdjustOffset problem
- /// — it's a head-sphere collision against a polygon that retail
- /// doesn't have (cottage floor should be punched-through above the
- /// ramp). Whether the harness reproduces the cap pinpoints whether
- /// the cottage-cell floor polygon set is the cause.
+ /// This is the actual #98 bug, NOT a step-up / AdjustOffset problem.
+ /// Live capture's [resolve] probe pinpoints the blocking
+ /// entity: obj=0xA9B47900 — a landblock-baked static building
+ /// (the cottage GfxObj). The cottage's floor polygons live in this
+ /// GfxObj, registered as a ShadowEntry, NOT in any of the cottage's
+ /// cells. The harness's
+ /// loads cell fixtures but does NOT register the cottage GfxObj, so
+ /// the harness fails to reproduce the cap — DOCUMENTED here as the
+ /// divergence pattern.
+ ///
+ ///
+ ///
+ /// Documents-the-bug pattern: passes WHILE the harness lacks the
+ /// cottage GfxObj. When a future session adds the cottage GfxObj
+ /// (full polygon list extracted from the live [poly-dump] +
+ /// [resolve-bldg] probes), this test will start failing —
+ /// the signal to flip it from documenting-the-bug to enforcing-the-fix.
///
///
[Fact]
- public void LiveCompare_FirstCap_HeadHitsCottageFloor()
+ public void LiveCompare_FirstCap_HarnessMissesCottageFloorBecauseCottageGfxObjNotRegistered()
{
var (engine, _) = BuildEngineWithCellarFixtures();
var captured = LoadCapturedRecord(record =>
record.Result.CollisionNormalValid
&& record.Result.CollisionNormal.Z < -0.99f);
- AssertCallMatchesCapture(engine, captured);
+ Assert.NotNull(captured.BodyBefore);
+
+ var body = SeedBodyFromSnapshot(captured.BodyBefore);
+ var harnessResult = engine.ResolveWithTransition(
+ currentPos: captured.Input.CurrentPos,
+ targetPos: captured.Input.TargetPos,
+ cellId: captured.Input.CellId,
+ sphereRadius: captured.Input.SphereRadius,
+ sphereHeight: captured.Input.SphereHeight,
+ stepUpHeight: captured.Input.StepUpHeight,
+ stepDownHeight: captured.Input.StepDownHeight,
+ isOnGround: captured.Input.IsOnGround,
+ body: body,
+ moverFlags: (ObjectInfoState)captured.Input.MoverFlags,
+ movingEntityId: captured.Input.MovingEntityId);
+
+ // Live reported cn=(0,0,-1) blocking the climb at this point.
+ Assert.True(captured.Result.CollisionNormalValid,
+ "Captured record must have collisionNormalValid=true.");
+ Assert.True(captured.Result.CollisionNormal.Z < -0.99f,
+ $"Captured record must have downward collision normal; got " +
+ $"{captured.Result.CollisionNormal}.");
+
+ // Harness does NOT reproduce the live downward push because the
+ // cottage GfxObj is not registered — the blocking polygon lives
+ // in static obj 0xA9B47900, which BuildEngineWithCellarFixtures
+ // intentionally skips today (RegisterStairRampGfxObj is commented
+ // out). When the cottage GfxObj's full polygon set is added to
+ // the harness, this assertion will start to fail — flip the test
+ // to assert the live cn=(0,0,-1) round-trips at that point.
+ Assert.False(
+ harnessResult.CollisionNormalValid
+ && harnessResult.CollisionNormal.Z < -0.99f,
+ "Harness should NOT reproduce the cottage-floor cap yet — " +
+ "if it does, the cottage GfxObj has been added and this test " +
+ "needs to flip to AssertCallMatchesCapture(engine, captured).");
}
///