diag(phys): A6.P3 #98 — [step-walk-adjust] probe inside AdjustOffset

Adds one log line per AdjustOffset call (gated by ACDREAM_PROBE_STEP_WALK)
naming the branch taken (no-cp / no-cp-slide / slide-degenerate /
slide-crease / into-plane / away-plane, optionally +safety-push) plus
zGain = output.Z - input.Z.

No math or control-flow changes — pure observability so the next capture
can disambiguate the three failure-mode hypotheses for the cellar-ramp
climb cap. Re-reading the existing capture (a6-issue98-negpoly-...log)
showed the sphere DOES climb 90.00 -> 92.79 (2.79 m gain), then caps,
contradicting the divergence comparison's "no altitude gain" framing.
The real question is what stops the climb at world Z ~= 92.79 with the
cottage floor still 1.21 m higher. Existing [step-walk] probes wrap
AdjustOffset; this new probe reveals which branch the projection takes.

Fix plan with the four-branch decision tree at
docs/superpowers/plans/2026-05-23-a6-p3-issue98-cellar-up-fix.md.

Test baseline maintained: 1167 + 8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-23 16:16:42 +02:00
parent 67005e21f1
commit 8a232a3e6e
3 changed files with 562 additions and 0 deletions

View file

@ -674,6 +674,49 @@ public static class PhysicsDiagnostics
string.IsNullOrEmpty(detail) ? string.Empty : " " + detail));
}
/// <summary>
/// A6.P3 issue #98 (2026-05-23) — focused probe INSIDE
/// <see cref="Transition.AdjustOffset"/> revealing which branch was
/// taken and the per-call Z gain. Pair with <c>[step-walk]
/// site=after-adjust</c> at the call site to triangulate where the
/// projection ends up. Caller MUST guard with
/// <c>if (!ProbeStepWalkEnabled) return;</c> before calling.
/// </summary>
public static void LogStepWalkAdjust(
string branch,
Vector3 input,
Vector3 output,
Plane? contactPlane,
bool slidingValid,
Vector3 slidingNormal,
float collisionAngle,
float walkInterp)
{
var culture = System.Globalization.CultureInfo.InvariantCulture;
string cpDesc = contactPlane is { } cp
? string.Format(culture,
"n=({0:F4},{1:F4},{2:F4}) d={3:F4}",
cp.Normal.X, cp.Normal.Y, cp.Normal.Z, cp.D)
: "n/a";
string slideDesc = slidingValid
? string.Format(culture,
"({0:F4},{1:F4},{2:F4})",
slidingNormal.X, slidingNormal.Y, slidingNormal.Z)
: "n/a";
Console.WriteLine(string.Format(culture,
"[step-walk-adjust] branch={0} input=({1:F4},{2:F4},{3:F4}) " +
"output=({4:F4},{5:F4},{6:F4}) zGain={7:F4} " +
"cp={8} slide={9} colAngle={10:F4} winterp={11:F4}",
branch,
input.X, input.Y, input.Z,
output.X, output.Y, output.Z,
output.Z - input.Z,
cpDesc, slideDesc, collisionAngle, walkInterp));
}
private static string FormatVector(bool valid, Vector3 value)
{
if (!valid)

View file

@ -2639,6 +2639,9 @@ public sealed class Transition
Vector3 result = offset;
bool checkSlide = false;
// A6.P3 #98 (2026-05-23): branch token for the [step-walk-adjust]
// probe. Tracks which exit path the projection takes.
string branch = "init";
// Check if we should apply sliding.
float slidingAngle = Vector3.Dot(result, ci.SlidingNormal);
@ -2654,7 +2657,24 @@ public sealed class Transition
if (!ci.ContactPlaneValid)
{
if (checkSlide)
{
result -= ci.SlidingNormal * slidingAngle;
branch = "no-cp-slide";
}
else
{
branch = "no-cp";
}
if (PhysicsDiagnostics.ProbeStepWalkEnabled)
PhysicsDiagnostics.LogStepWalkAdjust(
branch, offset, result,
contactPlane: null,
slidingValid: ci.SlidingNormalValid,
slidingNormal: ci.SlidingNormal,
collisionAngle: 0f,
walkInterp: sp.WalkInterp);
return result;
}
@ -2667,23 +2687,29 @@ public sealed class Transition
// Project movement along the crease between contact and slide planes.
float slideLen = slideOffset.Length();
if (slideLen < PhysicsGlobals.EPSILON)
{
result = Vector3.Zero;
branch = "slide-degenerate";
}
else
{
slideOffset /= slideLen;
result = Vector3.Dot(slideOffset, result) * slideOffset;
branch = "slide-crease";
}
}
else if (collisionAngle <= 0f)
{
// Moving into the contact plane: remove component into the plane.
result -= ci.ContactPlane.Normal * collisionAngle;
branch = "into-plane";
}
else
{
// Moving away from contact plane: snap to plane surface.
// SnapToPlane: remove any component that would violate the plane.
result -= ci.ContactPlane.Normal * collisionAngle;
branch = "away-plane";
}
// Safety check: ensure the sphere stays above the contact plane.
@ -2731,10 +2757,22 @@ public sealed class Transition
if (radius > MathF.Abs(zDist))
{
sp.AddOffsetToCheckPos(new Vector3(0f, 0f, zDist));
// A6.P3 #98 (2026-05-23): annotate the branch so the
// probe shows the safety push fired.
branch += "+safety-push";
}
}
}
if (PhysicsDiagnostics.ProbeStepWalkEnabled)
PhysicsDiagnostics.LogStepWalkAdjust(
branch, offset, result,
contactPlane: ci.ContactPlane,
slidingValid: ci.SlidingNormalValid,
slidingNormal: ci.SlidingNormal,
collisionAngle: collisionAngle,
walkInterp: sp.WalkInterp);
return result;
}