docs(plan): indoor BSP world-origin fix implementation plan
Five-task plan for Bug B slice (spec 2026-05-20). Tasks: 1. Regression test in BSPQueryTests.cs (BSPQuery API contract) 2. Apply Decompose + arg-pass at TransitionTypes.cs:1442 3. Run physics suite, confirm 8-failure baseline holds 4. Commit 5. User visual + probe-equivalence verification Bug A explicitly deferred to a future slice. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
865634f450
commit
56816fcbe4
1 changed files with 462 additions and 0 deletions
462
docs/superpowers/plans/2026-05-20-indoor-bsp-worldorigin-fix.md
Normal file
462
docs/superpowers/plans/2026-05-20-indoor-bsp-worldorigin-fix.md
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
# Indoor BSP World-Origin Fix Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Stop indoor BSP step-down + Path-4 land from writing local-space `ContactPlane`s by passing the cell's actual world rotation + world origin to `BSPQuery.FindCollisions`.
|
||||
|
||||
**Architecture:** Single-call-site mechanical fix at `TransitionTypes.cs:1442`. Decompose `cellPhysics.WorldTransform` once, pass the rotation as `localToWorld` and the translation as `worldOrigin`. Mirrors the existing correct pattern at `:1808` for object BSP queries.
|
||||
|
||||
**Tech Stack:** C# .NET 10, xUnit, `System.Numerics.Matrix4x4.Decompose`, existing `BSPQuery` / `Transition` / `CellPhysics` types.
|
||||
|
||||
**Spec:** [`docs/superpowers/specs/2026-05-20-indoor-bsp-worldorigin-fix-design.md`](../specs/2026-05-20-indoor-bsp-worldorigin-fix-design.md)
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
**Files to modify:**
|
||||
|
||||
- `src/AcDream.Core/Physics/TransitionTypes.cs` — Single call site at `:1442`. Add 8-10 lines for `Matrix4x4.Decompose` + updated arg list.
|
||||
|
||||
**Files to extend:**
|
||||
|
||||
- `tests/AcDream.Core.Tests/Physics/BSPQueryTests.cs` — Add one regression test (~50 lines including fixture builder) at the end of the file. Verifies `BSPQuery.FindCollisions` with `path.StepDown=true` + non-identity `localToWorld` + non-zero `worldOrigin` writes a world-space `ContactPlane`.
|
||||
|
||||
**No files created.** No files deleted (Bug A's `TryFindIndoorWalkablePlane` removal is a separate slice — out of scope for this plan).
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Add regression test — BSPQuery.FindCollisions Path 3 with translated cell
|
||||
|
||||
This test verifies the BSPQuery API's correctness when called with non-identity world transforms — it documents the expected behavior and guards against future regressions in `BSPQuery`. It will already pass before the fix at `:1442` (because `BSPQuery` itself is correct when called correctly), but it locks in the contract.
|
||||
|
||||
**Files:**
|
||||
- Modify: `tests/AcDream.Core.Tests/Physics/BSPQueryTests.cs` — append a new test method after the existing `FindWalkableSphere_SteepPoly_RejectedByWalkableAllowance` test (the last one in the file, around line 421).
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
Append to `tests/AcDream.Core.Tests/Physics/BSPQueryTests.cs` (after the last test method, before the closing `}` of the class):
|
||||
|
||||
```csharp
|
||||
// =========================================================================
|
||||
// FindCollisions — world-origin / world-rotation correctness (spec 2026-05-20)
|
||||
// =========================================================================
|
||||
|
||||
/// <summary>
|
||||
/// Build a single-leaf BSP with one horizontal floor polygon at the given
|
||||
/// cell-local Z. Vertex array forms a 4x4 m square centered at cell-local
|
||||
/// (0, 0).
|
||||
/// </summary>
|
||||
private static (PhysicsBSPNode root, Dictionary<ushort, ResolvedPolygon> resolved)
|
||||
BuildSingleFloorBsp(float floorZ)
|
||||
{
|
||||
var verts = new[]
|
||||
{
|
||||
new Vector3(-2f, -2f, floorZ),
|
||||
new Vector3( 2f, -2f, floorZ),
|
||||
new Vector3( 2f, 2f, floorZ),
|
||||
new Vector3(-2f, 2f, floorZ),
|
||||
};
|
||||
|
||||
var root = new PhysicsBSPNode
|
||||
{
|
||||
Type = BSPNodeType.Leaf,
|
||||
BoundingSphere = new Sphere
|
||||
{
|
||||
Origin = new Vector3(0f, 0f, floorZ),
|
||||
Radius = 3f,
|
||||
},
|
||||
};
|
||||
root.Polygons.Add(0);
|
||||
|
||||
var resolved = new Dictionary<ushort, ResolvedPolygon>
|
||||
{
|
||||
[0] = new ResolvedPolygon
|
||||
{
|
||||
Vertices = verts,
|
||||
Plane = new Plane(Vector3.UnitZ, -floorZ),
|
||||
NumPoints = 4,
|
||||
SidesType = CullMode.None,
|
||||
},
|
||||
};
|
||||
|
||||
return (root, resolved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindCollisions_StepDown_TranslatedWorldOrigin_WritesWorldSpacePlane()
|
||||
{
|
||||
// Cell is translated +94 m in world Z (i.e., the cell-local floor at
|
||||
// Z=0 sits at world Z=94). This mirrors the Holtburg cottage scenario
|
||||
// captured in launch-cp-probe.log (cell 0xA9B40150, floor world
|
||||
// Z≈94.02).
|
||||
var (root, resolved) = BuildSingleFloorBsp(floorZ: 0f);
|
||||
|
||||
var transition = new Transition();
|
||||
transition.SpherePath.WalkableAllowance = PhysicsGlobals.FloorZ;
|
||||
transition.SpherePath.WalkInterp = 1.0f;
|
||||
transition.SpherePath.StepDown = true;
|
||||
transition.SpherePath.StepDownAmt = 0.5f;
|
||||
|
||||
// Foot sphere in cell-local space: just above the floor.
|
||||
var localSphere = new Sphere
|
||||
{
|
||||
Origin = new Vector3(0f, 0f, 0.48f),
|
||||
Radius = 0.48f,
|
||||
};
|
||||
|
||||
var state = BSPQuery.FindCollisions(
|
||||
root,
|
||||
resolved,
|
||||
transition,
|
||||
localSphere,
|
||||
localSphere1: null,
|
||||
localCurrCenter: localSphere.Origin,
|
||||
localSpaceZ: Vector3.UnitZ,
|
||||
scale: 1.0f,
|
||||
localToWorld: Quaternion.Identity,
|
||||
engine: null,
|
||||
worldOrigin: new Vector3(0f, 0f, 94f));
|
||||
|
||||
// Path 3 step-down should fire and adjust the sphere onto the floor.
|
||||
Assert.Equal(TransitionState.Adjusted, state);
|
||||
|
||||
// ContactPlane must be in world space: normal stays (0,0,1) since the
|
||||
// cell rotation is identity; D = -world_floor_Z = -94.
|
||||
Assert.True(transition.CollisionInfo.ContactPlaneValid);
|
||||
Assert.Equal(1.0f, transition.CollisionInfo.ContactPlane.Normal.Z, precision: 3);
|
||||
Assert.Equal(-94.0f, transition.CollisionInfo.ContactPlane.D, precision: 2);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the test to verify it passes**
|
||||
|
||||
Run:
|
||||
```powershell
|
||||
dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj -c Debug --nologo --filter "FullyQualifiedName~FindCollisions_StepDown_TranslatedWorldOrigin"
|
||||
```
|
||||
|
||||
Expected:
|
||||
```
|
||||
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1
|
||||
```
|
||||
|
||||
If it fails, examine the assertion output. The most likely failure mode: `TransitionState.OK` instead of `Adjusted` — means the step-down didn't adjust onto the floor. Adjust `StepDownAmt` / sphere position to ensure the sphere center is within `radius` of the floor plane so `find_walkable` accepts the contact.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```powershell
|
||||
git add tests/AcDream.Core.Tests/Physics/BSPQueryTests.cs
|
||||
git commit -m "test(physics): BSPQuery.FindCollisions writes world-space plane with translated origin
|
||||
|
||||
Regression test for indoor BSP world-origin fix (Bug B). Verifies that
|
||||
BSPQuery.FindCollisions with path.StepDown=true and a non-zero
|
||||
worldOrigin parameter writes a world-space ContactPlane to
|
||||
CollisionInfo (not a cell-local-space one).
|
||||
|
||||
Passes before the call-site fix at TransitionTypes.cs:1442 because
|
||||
BSPQuery itself is correct when called with the right args — it's the
|
||||
caller that was passing the defaults. This test locks in the BSPQuery
|
||||
contract so the relationship between worldOrigin/localToWorld input and
|
||||
ContactPlane.D output cannot regress silently.
|
||||
|
||||
Spec: docs/superpowers/specs/2026-05-20-indoor-bsp-worldorigin-fix-design.md.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Apply the call-site fix
|
||||
|
||||
Decompose `cellPhysics.WorldTransform` and pass the rotation + translation to `BSPQuery.FindCollisions`. This is the actual bug fix.
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/AcDream.Core/Physics/TransitionTypes.cs:1442` — the BSP collision call inside the indoor branch of `FindEnvCollisions`. Replace the 10-arg invocation with a Decompose + 11-arg invocation including `localToWorld` + `worldOrigin`.
|
||||
|
||||
- [ ] **Step 1: Read the current call site for exact context match**
|
||||
|
||||
Read `src/AcDream.Core/Physics/TransitionTypes.cs` lines 1430-1455 to confirm the exact whitespace and surrounding code. (We need the exact `old_string` for the Edit tool.)
|
||||
|
||||
- [ ] **Step 2: Apply the edit**
|
||||
|
||||
Use Edit on `src/AcDream.Core/Physics/TransitionTypes.cs`:
|
||||
|
||||
`old_string`:
|
||||
```csharp
|
||||
// Use the full 6-path BSP dispatcher for retail-faithful collision.
|
||||
// Use pre-resolved polygons (vertices+planes computed at cache time).
|
||||
var cellState = BSPQuery.FindCollisions(
|
||||
cellPhysics.BSP.Root,
|
||||
cellPhysics.Resolved,
|
||||
this,
|
||||
localSphere,
|
||||
localSphere1,
|
||||
localCurrCenter,
|
||||
Vector3.UnitZ, // local space Z is up
|
||||
1.0f, // scale = 1.0 for cell geometry
|
||||
Quaternion.Identity,
|
||||
engine); // engine needed for Path 5 step-up
|
||||
```
|
||||
|
||||
`new_string`:
|
||||
```csharp
|
||||
// Use the full 6-path BSP dispatcher for retail-faithful collision.
|
||||
// Use pre-resolved polygons (vertices+planes computed at cache time).
|
||||
//
|
||||
// 2026-05-20 (Bug B fix): pass the cell's world rotation +
|
||||
// translation so the BSP's internal find_walkable /
|
||||
// step_sphere_down / Path-4 land write world-space ContactPlanes
|
||||
// (NOT cell-local). The prior call passed Quaternion.Identity
|
||||
// and defaulted worldOrigin = Vector3.Zero — which corrupted
|
||||
// every Path 3 + Path 4 CP write inside an indoor cell with
|
||||
// D ≈ 0 instead of D = -world_floor_Z. Mirrors the existing
|
||||
// correct pattern at the FindObjCollisions call site.
|
||||
//
|
||||
// Retail oracle: BSPTREE::find_collisions (decomp
|
||||
// acclient_2013_pseudo_c.txt:323924) calls Plane::localtoglobal
|
||||
// (:323921) before set_contact_plane. Our TransformNormal +
|
||||
// TransformVertices + BuildWorldPlane chain is the equivalent
|
||||
// — it just needs the right rotation + origin.
|
||||
Quaternion cellRotation;
|
||||
Vector3 cellOrigin;
|
||||
if (Matrix4x4.Decompose(cellPhysics.WorldTransform, out _, out cellRotation, out cellOrigin))
|
||||
{
|
||||
// Clean decompose — use the extracted rotation + translation.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Matrix has shear or other non-decomposable parts. EnvCell
|
||||
// WorldTransform is always rigid rotation + translation per
|
||||
// the dat format, so this branch should never fire. Log a
|
||||
// one-shot warning + fall back to identity rotation +
|
||||
// .Translation so we degrade to "translation-only" instead
|
||||
// of the original "both broken".
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
$"[indoor-bsp] WARN cellPhysics.WorldTransform did not decompose cleanly for cell 0x{sp.CheckCellId:X8} — falling back to identity rotation"));
|
||||
cellRotation = Quaternion.Identity;
|
||||
cellOrigin = cellPhysics.WorldTransform.Translation;
|
||||
}
|
||||
|
||||
var cellState = BSPQuery.FindCollisions(
|
||||
cellPhysics.BSP.Root,
|
||||
cellPhysics.Resolved,
|
||||
this,
|
||||
localSphere,
|
||||
localSphere1,
|
||||
localCurrCenter,
|
||||
Vector3.UnitZ, // local space Z is up
|
||||
1.0f, // scale = 1.0 for cell geometry
|
||||
cellRotation,
|
||||
engine, // engine needed for Path 5 step-up
|
||||
worldOrigin: cellOrigin);
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Build to verify the change compiles**
|
||||
|
||||
Run:
|
||||
```powershell
|
||||
dotnet build -c Debug
|
||||
```
|
||||
|
||||
Expected: `Build succeeded.` with 0 errors. Warnings unchanged from baseline (3 pre-existing xUnit warnings).
|
||||
|
||||
- [ ] **Step 4: Run the regression test (Task 1's) to verify it still passes**
|
||||
|
||||
Run:
|
||||
```powershell
|
||||
dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj -c Debug --no-build --nologo --filter "FullyQualifiedName~FindCollisions_StepDown_TranslatedWorldOrigin"
|
||||
```
|
||||
|
||||
Expected:
|
||||
```
|
||||
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1
|
||||
```
|
||||
|
||||
(The Task 1 test exercises `BSPQuery` directly; this fix is at the caller, so the test still passes.)
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Run the broader physics test suite — confirm no regressions
|
||||
|
||||
Verify the existing 8-failure baseline is unchanged (2 BSPStepUp + 6 MotionInterpreter pre-existing failures, all unrelated to this fix).
|
||||
|
||||
- [ ] **Step 1: Run all physics tests**
|
||||
|
||||
Run:
|
||||
```powershell
|
||||
dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj -c Debug --no-build --nologo --filter "FullyQualifiedName~Physics"
|
||||
```
|
||||
|
||||
Expected:
|
||||
```
|
||||
Failed! - Failed: 8, Passed: ...(at least 405), Skipped: 0, Total: ...
|
||||
```
|
||||
|
||||
The 8 failures are the documented baseline. If you see 9+ failures or different failure names, the fix introduced a regression — investigate before continuing.
|
||||
|
||||
- [ ] **Step 2: Cross-check the failures match the baseline**
|
||||
|
||||
Verify the failed test names match this set (no new failures, no new passes that were previously failing):
|
||||
|
||||
Expected failing tests:
|
||||
```
|
||||
AcDream.Core.Tests.Physics.MotionInterpreterTests.GetMaxSpeed_WalkForward_ReturnsWalkAnimSpeed
|
||||
AcDream.Core.Tests.Physics.MotionInterpreterTests.GetMaxSpeed_Idle_ReturnsZero
|
||||
AcDream.Core.Tests.Physics.MotionInterpreterTests.GetMaxSpeed_WalkBackward_ReturnsWalkAnimSpeedTimesBackwardsFactor
|
||||
AcDream.Core.Tests.Physics.MotionInterpreterTests.GetMaxSpeed_* (3 more)
|
||||
AcDream.Core.Tests.Physics.BSPStepUpTests.C3_Path6_AirborneMoverHitsSteepSlope_SetsCollide
|
||||
AcDream.Core.Tests.Physics.BSPStepUpTests.* (1 more)
|
||||
```
|
||||
|
||||
If the failing-test list has changed, stop and investigate. The fix should not affect motion-interpreter or step-up behavior.
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Commit the fix
|
||||
|
||||
- [ ] **Step 1: Stage the modified file**
|
||||
|
||||
```powershell
|
||||
git add src/AcDream.Core/Physics/TransitionTypes.cs
|
||||
git status
|
||||
```
|
||||
|
||||
Expected `git status`:
|
||||
```
|
||||
Changes to be committed:
|
||||
modified: src/AcDream.Core/Physics/TransitionTypes.cs
|
||||
```
|
||||
|
||||
(Only `TransitionTypes.cs` should be staged. If the test file appears, it was already committed in Task 1.)
|
||||
|
||||
- [ ] **Step 2: Commit with the spec's commit message**
|
||||
|
||||
```powershell
|
||||
git commit -m "fix(physics): pass cell world-transform to indoor BSP collision
|
||||
|
||||
Indoor cell BSP queries at TransitionTypes.cs:1442 were calling
|
||||
BSPQuery.FindCollisions with Quaternion.Identity + defaulted
|
||||
Vector3.Zero worldOrigin. Inside the BSP, Path 3 (step_sphere_down)
|
||||
and Path 4 (land-on-surface) use those params to build the
|
||||
world-space ContactPlane. Result: planes written with D ~ 0 instead
|
||||
of the cell's world floor Z (e.g. -94.02 for Holtburg cottages).
|
||||
320 corrupt CP writes per Holtburg session per the [cp-write] probe.
|
||||
|
||||
Fix: decompose cellPhysics.WorldTransform once at the call site,
|
||||
pass the rotation as localToWorld and the translation as
|
||||
worldOrigin. Mirrors the existing correct pattern at :1808
|
||||
(FindObjCollisions, passes obj.Rotation + obj.Position).
|
||||
|
||||
Retail oracle: BSPTREE::find_collisions (acclient_2013_pseudo_c.txt:323924)
|
||||
calls Plane::localtoglobal at :323921 before set_contact_plane.
|
||||
Our TransformNormal + TransformVertices + BuildWorldPlane chain is
|
||||
the equivalent — it just needs the right rotation + origin.
|
||||
|
||||
Spec: docs/superpowers/specs/2026-05-20-indoor-bsp-worldorigin-fix-design.md.
|
||||
Evidence: launch-cp-probe.log capture 2026-05-20, [cp-write] probe.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Verify commit landed cleanly**
|
||||
|
||||
```powershell
|
||||
git log --oneline -3
|
||||
```
|
||||
|
||||
Expected: top of log shows the fix commit, followed by the regression-test commit from Task 1, followed by `865634f docs(spec): indoor BSP world-origin / world-rotation fix (Bug B)`.
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Hand off to user for visual verification
|
||||
|
||||
The fix's acceptance test is visual + probe-equivalence. The user drives the client and confirms (a) `[cp-write] caller=BSPQuery.StepSphereDown:1123` lines now show correct world-Z D values, and (b) indoor walking visual scenarios behave better.
|
||||
|
||||
- [ ] **Step 1: Confirm graceful-logout state**
|
||||
|
||||
Before launching, check no stale acdream client is running (per CLAUDE.md's logout-before-reconnect rules). Run:
|
||||
```powershell
|
||||
Get-Process -Name AcDream.App -ErrorAction SilentlyContinue
|
||||
```
|
||||
|
||||
If a process is listed, close it gracefully first:
|
||||
```powershell
|
||||
$proc = Get-Process -Name AcDream.App -ErrorAction SilentlyContinue
|
||||
if ($proc) {
|
||||
$proc.CloseMainWindow() | Out-Null
|
||||
$proc.WaitForExit(5000) | Out-Null
|
||||
}
|
||||
Start-Sleep -Seconds 3
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Tell the user the launch command**
|
||||
|
||||
Show the user (do NOT auto-launch — user retains control here):
|
||||
|
||||
> Fix landed. Ready for visual verification. Launch with the probe flags on:
|
||||
>
|
||||
> ```powershell
|
||||
> $env:ACDREAM_DAT_DIR = "$env:USERPROFILE\Documents\Asheron's Call"
|
||||
> $env:ACDREAM_LIVE = "1"
|
||||
> $env:ACDREAM_TEST_HOST = "127.0.0.1"
|
||||
> $env:ACDREAM_TEST_PORT = "9000"
|
||||
> $env:ACDREAM_TEST_USER = "testaccount"
|
||||
> $env:ACDREAM_TEST_PASS = "testpassword"
|
||||
> $env:ACDREAM_DEVTOOLS = "1"
|
||||
> $env:ACDREAM_PROBE_INDOOR_BSP = "1"
|
||||
> $env:ACDREAM_PROBE_CONTACT_PLANE = "1"
|
||||
> dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 | Tee-Object -FilePath "launch-cp-probe-postfix.log"
|
||||
> ```
|
||||
>
|
||||
> Walk these scenarios (~30 seconds each):
|
||||
> 1. **Cottage entry** (outdoor → indoor)
|
||||
> 2. **Indoor standstill** for ~10 seconds (stationary case — may still glitch; that's Bug A, expected)
|
||||
> 3. **2nd-floor walking** (primary success criterion for Bug B)
|
||||
> 4. **Cellar descent**
|
||||
> 5. **Single-floor cottage walk** (regression check)
|
||||
>
|
||||
> Then close the window (CloseMainWindow path for graceful logout). I'll grep the new log for the `StepSphereDown:1123` lines and confirm the D values are now correct.
|
||||
|
||||
- [ ] **Step 3: Read + analyze the post-fix log**
|
||||
|
||||
After the user closes the window, run:
|
||||
|
||||
```powershell
|
||||
Get-Content launch-cp-probe-postfix.log -Encoding Unicode | Out-File launch-cp-probe-postfix.utf8.log -Encoding utf8
|
||||
```
|
||||
|
||||
Then use Bash:
|
||||
```bash
|
||||
echo "=== StepSphereDown D distribution (post-fix) ==="
|
||||
grep -E 'caller=BSPQuery\.StepSphereDown' launch-cp-probe-postfix.utf8.log | grep -oE 'D=[-0-9.]+' | sort | uniq -c | sort -rn | head -10
|
||||
echo "=== Caller distribution (compare to pre-fix) ==="
|
||||
grep -oE 'caller=[A-Za-z_.:0-9]+' launch-cp-probe-postfix.utf8.log | sort | uniq -c | sort -rn | head -10
|
||||
echo "=== indoor-walkable result distribution (should be ~same; Bug A still active) ==="
|
||||
grep -oE '\[indoor-walkable\].*result=[A-Z]+' launch-cp-probe-postfix.utf8.log | grep -oE 'result=[A-Z]+' | sort | uniq -c
|
||||
```
|
||||
|
||||
Expected:
|
||||
- StepSphereDown D values cluster around realistic floor Z values (-94.0, -94.02, etc., depending on the cell), NOT D=-0.000.
|
||||
- StepSphereDown caller count is similar to pre-fix (~320) OR much lower (the `Plane`-equality suppression in the property setter hides duplicate writes; if seed and BSP-write both produce the same world plane, only the seed shows up).
|
||||
- indoor-walkable MISS/HIT ratio still ~99% MISS (Bug A unchanged).
|
||||
|
||||
- [ ] **Step 4: Hand off to the user with the assessment**
|
||||
|
||||
Tell the user one of:
|
||||
|
||||
**On success (D values now correct):**
|
||||
> Probe-equivalence verified — StepSphereDown D values are now world-Z (e.g. -94.02), not -0.000. Bug B closed. Visual report? If 2nd-floor walking is stabler but stationary cases (cellar entry, indoor standstill) still glitch, that's Bug A — next slice. If you saw the M2-critical indoor scenarios work end-to-end, we can decide whether to ship Bug A as a follow-up phase or punt to post-M2 polish.
|
||||
|
||||
**On failure (D values still wrong):**
|
||||
> StepSphereDown D values are still wrong (showing X / -0.000 / etc.). The Decompose path either didn't fire or extracted the wrong values. Investigate: check what `cellPhysics.WorldTransform` actually looks like for the affected cells (might need a one-shot `[cell-transform]` probe).
|
||||
|
||||
---
|
||||
|
||||
## Self-review (run after writing this plan)
|
||||
|
||||
- **Spec coverage:** Plan covers the spec's Fix section (Task 2), Verification section (Task 3 + Task 5), and the call-site change (Task 2). The risk R1 (cell scale) is acknowledged in-spec but no plan task — fine, deferred. Risk R2 (Decompose returns false) handled inline in Task 2's `else` branch. Risk R3 + R4 informational; no plan task needed.
|
||||
- **Placeholder scan:** No TBD/TODO. Every code block is complete. Commands have exact expected output strings.
|
||||
- **Type consistency:** `cellRotation` (Quaternion), `cellOrigin` (Vector3), `cellPhysics.WorldTransform` (Matrix4x4) — consistent across Task 2.
|
||||
- **Test coverage:** Task 1 covers BSPQuery API regression. Visual verification (Task 5) covers the call-site fix. Acceptable per project convention for one-line mechanical fixes with probe evidence.
|
||||
- **Bug A is explicitly out of scope.** Plan acknowledges it (Task 5 step 4) and defers to a future slice.
|
||||
Loading…
Add table
Add a link
Reference in a new issue