15-task TDD plan covering the three pieces of A6.P1:
Phase A — Build the [push-back] acdream probe (Tasks 1-9):
toggle + 3 helpers + 3 emission sites in BSPQuery/Transition,
DebugVM mirror, CLAUDE.md env-var docs.
Phase B — Build the cdb infrastructure (Tasks 10-12):
7-BP cdb script, PowerShell runner, README.
Phase C — Execute 9 captures + findings stub (Tasks 13-15):
PDB-match verify, capture dir + findings stub, scenario captures.
API surface verified against current code: ResolvedPolygon has no
Id property (probe omits poly attribution; cross-ref via time-
adjacent [push-back-cell] line). CheckOtherCells locals are
sp.CheckCellId + cellId + result (verified at TransitionTypes.cs
lines 1418-1473). SpherePath has Collide/InsertType/WalkInterp,
ObjectInfo has State (verified).
Spec: docs/superpowers/specs/2026-05-21-phase-a6-indoor-physics-fidelity-design.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
49 KiB
Phase A6.P1 — cdb Probe Spike 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: Build the [push-back] acdream probe + the 7-breakpoint cdb script, then capture paired retail vs acdream traces at 9 indoor scenarios so A6.P2 can quantify the BSP collision response divergence.
Architecture: Three layers — (1) a new ProbePushBackEnabled toggle in PhysicsDiagnostics with 3 helper methods + 3 emission sites in BSPQuery / Transition; (2) a cdb breakpoint script + PowerShell wrapper that attaches to live retail; (3) a per-scenario capture protocol producing {retail,acdream}.log pairs.
Tech Stack: C# / .NET 10, xUnit, Console.WriteLine for probe emission (existing pattern), cdb.exe (Windows debugger), PowerShell.
Spec: docs/superpowers/specs/2026-05-21-phase-a6-indoor-physics-fidelity-design.md.
File Structure
Files to create:
tools/cdb/a6-probe.cdb— cdb breakpoint script (~80 lines)tools/cdb/a6-probe-runner.ps1— PowerShell wrapper to attach cdb (~40 lines)tools/cdb/README-a6-probe.md— usage documentation (~60 lines)docs/research/2026-05-21-a6-captures/.gitkeep— directory markerdocs/research/2026-05-21-a6-captures/scenN-<scenario>/{retail,acdream}.log— capture pairs (filed by Task 15)docs/research/2026-05-21-a6-cdb-capture-findings.md— findings doc stub (Task 14)
Files to modify:
src/AcDream.Core/Physics/PhysicsDiagnostics.cs— addProbePushBackEnabledtoggle + 3 helperssrc/AcDream.Core/Physics/BSPQuery.cs— 2 emission sites (lines 332, 1550)src/AcDream.Core/Physics/TransitionTypes.cs— 1 emission site inCheckOtherCells(line ~1472)src/AcDream.UI.Abstractions/Panels/Debug/DebugVM.cs— addProbePushBackmirrortests/AcDream.Core.Tests/Physics/PhysicsDiagnosticsTests.cs— add toggle roundtrip testCLAUDE.md— addACDREAM_PROBE_PUSH_BACK=1to "Diagnostic env vars" section
Phase A — Build the [push-back] probe (TDD)
Task 1: Add ProbePushBackEnabled toggle to PhysicsDiagnostics
Files:
-
Modify:
src/AcDream.Core/Physics/PhysicsDiagnostics.cs(append afterProbeWalkMissEnabledat line ~277) -
Test:
tests/AcDream.Core.Tests/Physics/PhysicsDiagnosticsTests.cs -
Step 1: Write the failing test
Append to tests/AcDream.Core.Tests/Physics/PhysicsDiagnosticsTests.cs (before the final closing } of the class):
// -----------------------------------------------------------------------
// ProbePushBackEnabled — flag gates the [push-back] emission path.
// A6.P1 (2026-05-21).
// -----------------------------------------------------------------------
[Fact]
public void ProbePushBack_StaticApi_Roundtrip()
{
bool initial = PhysicsDiagnostics.ProbePushBackEnabled;
try
{
PhysicsDiagnostics.ProbePushBackEnabled = true;
Assert.True(PhysicsDiagnostics.ProbePushBackEnabled);
PhysicsDiagnostics.ProbePushBackEnabled = false;
Assert.False(PhysicsDiagnostics.ProbePushBackEnabled);
}
finally
{
PhysicsDiagnostics.ProbePushBackEnabled = initial;
}
}
- Step 2: Run test to verify it fails
Run: dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj --filter FullyQualifiedName~ProbePushBack_StaticApi_Roundtrip --no-build
Expected: COMPILE ERROR — 'PhysicsDiagnostics' does not contain a definition for 'ProbePushBackEnabled'.
- Step 3: Implement the toggle
Append to src/AcDream.Core/Physics/PhysicsDiagnostics.cs immediately before the LogCpBoolWrite method (around line 279):
/// <summary>
/// Phase A6.P1 cdb probe spike (2026-05-21). When true, every BSP
/// collision response site emits a structured <c>[push-back]</c> line:
/// input/output sphere center, plane geometry, push-back delta, walk
/// interp, and the dispatcher's selected path. Direct comparison to
/// retail's cdb breakpoint set documented at
/// <c>tools/cdb/a6-probe.cdb</c>.
///
/// <para>
/// Three emission sites: <see cref="BSPQuery.AdjustSphereToPlane"/>
/// (the suspected over-correction site), <see cref="BSPQuery.FindCollisions"/>
/// (the 6-path dispatcher), and <see cref="Transition.CheckOtherCells"/>
/// (multi-cell BSP iteration outcomes). All three are zero-cost when
/// off — checked via early-out at each site.
/// </para>
///
/// <para>
/// Initial state from <c>ACDREAM_PROBE_PUSH_BACK=1</c>.
/// Runtime-toggleable via DebugVM mirror.
/// </para>
///
/// <para>
/// Spec: <c>docs/superpowers/specs/2026-05-21-phase-a6-indoor-physics-fidelity-design.md</c>.
/// </para>
/// </summary>
public static bool ProbePushBackEnabled { get; set; } =
Environment.GetEnvironmentVariable("ACDREAM_PROBE_PUSH_BACK") == "1";
- Step 4: Run test to verify it passes
Run: dotnet build src/AcDream.Core/AcDream.Core.csproj -c Debug --nologo && dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj --filter FullyQualifiedName~ProbePushBack_StaticApi_Roundtrip --no-build
Expected: PASS.
- Step 5: Commit
git add src/AcDream.Core/Physics/PhysicsDiagnostics.cs tests/AcDream.Core.Tests/Physics/PhysicsDiagnosticsTests.cs
git commit -m "$(cat <<'EOF'
feat(physics): A6.P1 — add ProbePushBackEnabled toggle
New PhysicsDiagnostics flag gates the [push-back] probe shipping
in subsequent tasks. Env-var ACDREAM_PROBE_PUSH_BACK=1 + DebugVM
mirror, matching the existing probe-toggle pattern.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 2: Add LogPushBackAdjust helper method
Files:
-
Modify:
src/AcDream.Core/Physics/PhysicsDiagnostics.cs -
Step 1: Add the helper method
Append immediately after the ProbePushBackEnabled property (just added) in src/AcDream.Core/Physics/PhysicsDiagnostics.cs:
/// <summary>
/// A6.P1 emission helper for the <c>AdjustSphereToPlane</c> site.
/// One line per call: input sphere center, plane geometry, push-back
/// delta, walk-interp before/after, and whether the adjust applied.
/// Direct paired comparison to retail's cdb breakpoint on
/// <c>CPolygon::adjust_sphere_to_plane</c>.
///
/// <para>
/// Caller MUST guard with <c>if (!ProbePushBackEnabled) return;</c>
/// before computing the delta arguments — this method assumes the
/// caller paid that price already.
/// </para>
/// </summary>
public static void LogPushBackAdjust(
Vector3 inputCenter,
Vector3 outputCenter,
Plane plane,
float radius,
float walkInterpBefore,
float walkInterpAfter,
float dpPos,
float dpMove,
float iDist,
bool applied)
{
var delta = outputCenter - inputCenter;
float deltaMag = delta.Length();
Console.WriteLine(System.FormattableString.Invariant(
$"[push-back] site=adjust_sphere " +
$"in=({inputCenter.X:F4},{inputCenter.Y:F4},{inputCenter.Z:F4}) " +
$"out=({outputCenter.X:F4},{outputCenter.Y:F4},{outputCenter.Z:F4}) " +
$"delta=({delta.X:F4},{delta.Y:F4},{delta.Z:F4}) deltaMag={deltaMag:F4} " +
$"n=({plane.Normal.X:F4},{plane.Normal.Y:F4},{plane.Normal.Z:F4}) d={plane.D:F4} " +
$"r={radius:F4} winterp={walkInterpBefore:F4}->{walkInterpAfter:F4} " +
$"dpPos={dpPos:F4} dpMove={dpMove:F4} iDist={iDist:F4} applied={applied}"));
}
// Note: cellId/polyId omitted — ResolvedPolygon has no Id property and
// AdjustSphereToPlane is called from inside BSP traversal without cell
// attribution. Cross-reference with [push-back-cell] (same trace, time-
// adjacent) for cell attribution; polyId pursued only if A6.P2 needs it
// (would require plumbing the ushort dict-key through BSP traversal).
- Step 2: Verify it compiles
Run: dotnet build src/AcDream.Core/AcDream.Core.csproj -c Debug --nologo
Expected: BUILD SUCCEEDED with 0 errors.
- Step 3: Commit
git add src/AcDream.Core/Physics/PhysicsDiagnostics.cs
git commit -m "$(cat <<'EOF'
feat(physics): A6.P1 — add LogPushBackAdjust helper
One-line per-call emission helper for the AdjustSphereToPlane
instrumentation site. Direct field-for-field paired comparison to
retail's CPolygon::adjust_sphere_to_plane breakpoint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 3: Wire LogPushBackAdjust into BSPQuery.AdjustSphereToPlane
Files:
-
Modify:
src/AcDream.Core/Physics/BSPQuery.cs:332-362(theAdjustSphereToPlanemethod body) -
Step 1: Read the current method body
Read src/AcDream.Core/Physics/BSPQuery.cs lines 320-365 to confirm the current shape — AdjustSphereToPlane returns bool, modifies validPos.Center and path.WalkInterp in-place.
- Step 2: Replace the method body with the instrumented version
Replace the body of AdjustSphereToPlane in src/AcDream.Core/Physics/BSPQuery.cs (lines 332-362) with:
private static bool AdjustSphereToPlane(
ResolvedPolygon poly,
SpherePath path,
CollisionSphere validPos,
Vector3 movement)
{
// A6.P1: snapshot inputs for the [push-back] probe (cheap copy of
// Vector3 + 2 floats). Only the LogPushBackAdjust call below pays
// the Console.WriteLine cost, and only when the probe is on.
var inputCenter = validPos.Center;
float walkInterpBefore = path.WalkInterp;
float dpPos = Vector3.Dot(validPos.Center, poly.Plane.Normal) + poly.Plane.D;
float dpMove = Vector3.Dot(movement, poly.Plane.Normal);
float dist;
if (dpMove <= PhysicsGlobals.EPSILON)
{
if (dpMove >= -PhysicsGlobals.EPSILON)
{
if (PhysicsDiagnostics.ProbePushBackEnabled)
{
PhysicsDiagnostics.LogPushBackAdjust(
inputCenter, validPos.Center, poly.Plane, validPos.Radius,
walkInterpBefore, path.WalkInterp,
dpPos, dpMove, 0f,
applied: false);
}
return false;
}
dist = dpPos - validPos.Radius;
}
else
{
dist = -validPos.Radius - dpPos;
}
float iDist = dist / dpMove;
float interp = (1f - iDist) * path.WalkInterp;
if (interp >= path.WalkInterp || interp < -0.5f)
{
if (PhysicsDiagnostics.ProbePushBackEnabled)
{
PhysicsDiagnostics.LogPushBackAdjust(
inputCenter, validPos.Center, poly.Plane, validPos.Radius,
walkInterpBefore, path.WalkInterp,
dpPos, dpMove, iDist,
applied: false);
}
return false;
}
validPos.Center -= movement * iDist;
path.WalkInterp = interp;
if (PhysicsDiagnostics.ProbePushBackEnabled)
{
PhysicsDiagnostics.LogPushBackAdjust(
inputCenter, validPos.Center, poly.Plane, validPos.Radius,
walkInterpBefore, path.WalkInterp,
dpPos, dpMove, iDist,
applied: true);
}
return true;
}
Note: Cell + poly attribution intentionally omitted — ResolvedPolygon
has no Id property and AdjustSphereToPlane is private inside BSP
traversal without cell scope. A6.P2 cross-references with the time-adjacent
[push-back-cell] line for cell attribution. If polyId becomes
necessary, A6.P3 plumbs the dictionary key through (mechanical change).
- Step 3: Verify build is green
Run: dotnet build src/AcDream.Core/AcDream.Core.csproj -c Debug --nologo
Expected: BUILD SUCCEEDED with 0 errors. The probe is now wired but inactive unless ACDREAM_PROBE_PUSH_BACK=1.
- Step 4: Quick smoke run to confirm the probe emits
Set the env var and run any test that calls AdjustSphereToPlane (existing BSPQuery tests touch this path):
$env:ACDREAM_PROBE_PUSH_BACK = "1"
dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj --filter "FullyQualifiedName~BSPQuery" --no-build --logger "console;verbosity=detailed" 2>&1 | Select-String "\[push-back\]" | Select-Object -First 3
Remove-Item Env:\ACDREAM_PROBE_PUSH_BACK
Expected: at least 1 [push-back] site=adjust_sphere ... line in the output. If zero lines, the probe didn't fire — investigate.
- Step 5: Commit
git add src/AcDream.Core/Physics/BSPQuery.cs
git commit -m "$(cat <<'EOF'
feat(physics): A6.P1 — instrument AdjustSphereToPlane with [push-back]
Wires the LogPushBackAdjust helper into all three return paths
of AdjustSphereToPlane (early-return on no-movement, early-return
on interp out-of-window, and the applied path). Probe is gated by
ProbePushBackEnabled so it's zero-cost when off.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 4: Add LogPushBackDispatch helper method
Files:
-
Modify:
src/AcDream.Core/Physics/PhysicsDiagnostics.cs -
Step 1: Add the helper method
Append immediately after the LogPushBackAdjust method (just added) in src/AcDream.Core/Physics/PhysicsDiagnostics.cs:
/// <summary>
/// A6.P1 emission helper for the <c>FindCollisions</c> dispatcher
/// site. One line per call: input sphere center, movement vector,
/// path-selection state flags (collide / insertType / objState),
/// walk-interp at entry, and the return state. Direct paired
/// comparison to retail's cdb breakpoint on
/// <c>BSPTREE::find_collisions</c>.
///
/// <para>
/// Caller MUST guard with <c>if (!ProbePushBackEnabled) return;</c>
/// before calling.
/// </para>
/// </summary>
public static void LogPushBackDispatch(
Vector3 sphereCenter,
Vector3 movement,
bool collide,
int insertType,
int objState,
float walkInterpEntry,
int returnState)
{
Console.WriteLine(System.FormattableString.Invariant(
$"[push-back-disp] site=dispatch " +
$"center=({sphereCenter.X:F4},{sphereCenter.Y:F4},{sphereCenter.Z:F4}) " +
$"mvmt=({movement.X:F4},{movement.Y:F4},{movement.Z:F4}) " +
$"collide={collide} insertType={insertType} objState=0x{objState:X} " +
$"winterp={walkInterpEntry:F4} return={returnState}"));
}
- Step 2: Verify it compiles
Run: dotnet build src/AcDream.Core/AcDream.Core.csproj -c Debug --nologo
Expected: BUILD SUCCEEDED.
- Step 3: Commit
git add src/AcDream.Core/Physics/PhysicsDiagnostics.cs
git commit -m "$(cat <<'EOF'
feat(physics): A6.P1 — add LogPushBackDispatch helper
One-line per-call emission helper for the FindCollisions dispatcher
instrumentation site. Captures path-selection state (collide flag,
insertType, objState) + walk-interp + return state for direct
comparison to retail's BSPTREE::find_collisions breakpoint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 5: Wire LogPushBackDispatch into BSPQuery.FindCollisions (modern overload only)
Files:
- Modify:
src/AcDream.Core/Physics/BSPQuery.cs:1550-1576(the modernFindCollisionsoverload entry)
Note: The legacy overload at :1895 delegates to the modern overload — instrumenting only the modern one covers all dispatches.
- Step 1: Locate the dispatcher's entry block
Read src/AcDream.Core/Physics/BSPQuery.cs lines 1550-1580 to confirm the entry shape (we want to emit AFTER the path/collisions/obj locals are computed but BEFORE the actual dispatch begins).
- Step 2: Insert the probe emission after
movementis computed
After line 1576 (var movement = sphere0.Center - localCurrCenter;) and BEFORE the next significant statement in BSPQuery.cs's FindCollisions, add:
// A6.P1: snapshot dispatcher entry for the [push-back-disp] probe.
// Emitted before path selection so the captured state reflects
// the inputs the dispatcher routes on. Return value is captured
// by wrapping the actual dispatch — see end of method.
if (PhysicsDiagnostics.ProbePushBackEnabled)
{
PhysicsDiagnostics.LogPushBackDispatch(
sphereCenter: sphere0.Center,
movement: movement,
collide: path.Collide,
insertType: (int)path.InsertType,
objState: (int)obj.State,
walkInterpEntry: path.WalkInterp,
returnState: -1); // Sentinel; full return state captured separately.
}
Note: The returnState=-1 sentinel marks "entry log" — A6.P2 analysis can pair entry/exit by call order in the trace. If a per-call exit log is needed, A6.P1.5 adds a wrapping try/finally; for now entry-only suffices since the dispatcher's path can be inferred from subsequent [push-back] adjust-sphere lines and the eventual return.
- Step 3: Verify build is green
Run: dotnet build src/AcDream.Core/AcDream.Core.csproj -c Debug --nologo
Expected: BUILD SUCCEEDED.
- Step 4: Quick smoke run
$env:ACDREAM_PROBE_PUSH_BACK = "1"
dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj --filter "FullyQualifiedName~FindCollisions" --no-build --logger "console;verbosity=detailed" 2>&1 | Select-String "\[push-back-disp\]" | Select-Object -First 3
Remove-Item Env:\ACDREAM_PROBE_PUSH_BACK
Expected: at least 1 [push-back-disp] site=dispatch ... line.
- Step 5: Commit
git add src/AcDream.Core/Physics/BSPQuery.cs
git commit -m "$(cat <<'EOF'
feat(physics): A6.P1 — instrument FindCollisions with [push-back-disp]
Wires LogPushBackDispatch into the modern FindCollisions overload
at the entry block (after path/collisions/obj locals + movement
computed). Legacy overload delegates to modern, so single
instrumentation site covers all dispatches.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 6: Add LogPushBackCellTransit helper method
Files:
-
Modify:
src/AcDream.Core/Physics/PhysicsDiagnostics.cs -
Step 1: Add the helper method
Append immediately after LogPushBackDispatch in src/AcDream.Core/Physics/PhysicsDiagnostics.cs:
/// <summary>
/// A6.P1 emission helper for the <c>CheckOtherCells</c> multi-cell
/// BSP iteration site. One line per off-cell hit: from-cell, to-cell,
/// BSP result (Ok / Adjusted / Slid / Collided), and the iteration
/// outcome. Direct paired comparison to retail's
/// <c>CTransition::check_other_cells</c> loop at decomp line
/// 272717. Augments the existing A4 multi-cell BSP instrumentation
/// with explicit per-iteration outcome telemetry.
///
/// <para>
/// Caller MUST guard with <c>if (!ProbePushBackEnabled) return;</c>
/// before calling.
/// </para>
/// </summary>
public static void LogPushBackCellTransit(
uint primaryCellId,
uint otherCellId,
int bspResult,
bool halted)
{
Console.WriteLine(System.FormattableString.Invariant(
$"[push-back-cell] site=other_cell " +
$"primary=0x{primaryCellId:X8} other=0x{otherCellId:X8} " +
$"bspResult={bspResult} halted={halted}"));
}
- Step 2: Verify it compiles
Run: dotnet build src/AcDream.Core/AcDream.Core.csproj -c Debug --nologo
Expected: BUILD SUCCEEDED.
- Step 3: Commit
git add src/AcDream.Core/Physics/PhysicsDiagnostics.cs
git commit -m "$(cat <<'EOF'
feat(physics): A6.P1 — add LogPushBackCellTransit helper
One-line per-iteration emission helper for the CheckOtherCells
multi-cell BSP loop. Captures primary/other cell ids, BSP result,
and halted flag for direct comparison to retail's
CTransition::check_other_cells loop.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 7: Wire LogPushBackCellTransit into Transition.CheckOtherCells
Files:
-
Modify:
src/AcDream.Core/Physics/TransitionTypes.cs:1404-1480(theCheckOtherCellsloop) -
Step 1: Locate the insertion point
In src/AcDream.Core/Physics/TransitionTypes.cs, find the line block at
~1466-1473:
if (PhysicsDiagnostics.ProbeIndoorBspEnabled)
{
Console.WriteLine(System.FormattableString.Invariant(
$"[other-cells] primary=0x{sp.CheckCellId:X8} iter=0x{cellId:X8} result={result}"));
}
if (ApplyOtherCellResult(result, out var halted))
return halted;
We add the new [push-back-cell] emission AFTER the existing [other-cells]
block and BEFORE the ApplyOtherCellResult call.
- Step 2: Insert the new emission
In src/AcDream.Core/Physics/TransitionTypes.cs, modify the line block at
~1466-1473 by inserting a new if block between the existing
[other-cells] probe and the ApplyOtherCellResult call. The locals in
scope at this point are sp.CheckCellId (the primary), cellId (the
loop variable for the candidate cell), and result (the BSP query
return state). After the edit it reads:
if (PhysicsDiagnostics.ProbeIndoorBspEnabled)
{
Console.WriteLine(System.FormattableString.Invariant(
$"[other-cells] primary=0x{sp.CheckCellId:X8} iter=0x{cellId:X8} result={result}"));
}
if (PhysicsDiagnostics.ProbePushBackEnabled)
{
PhysicsDiagnostics.LogPushBackCellTransit(
primaryCellId: sp.CheckCellId,
otherCellId: cellId,
bspResult: (int)result,
halted: false); // Sentinel; A6.P2 infers halt by checking if the iter ended here.
}
if (ApplyOtherCellResult(result, out var halted))
return halted;
- Step 3: Verify build is green
Run: dotnet build src/AcDream.Core/AcDream.Core.csproj -c Debug --nologo
Expected: BUILD SUCCEEDED with 0 errors.
- Step 4: Quick smoke run
$env:ACDREAM_PROBE_PUSH_BACK = "1"
dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj --filter "FullyQualifiedName~CheckOtherCells" --no-build --logger "console;verbosity=detailed" 2>&1 | Select-String "\[push-back-cell\]" | Select-Object -First 3
Remove-Item Env:\ACDREAM_PROBE_PUSH_BACK
Expected: at least 1 [push-back-cell] site=other_cell ... line.
- Step 5: Commit
git add src/AcDream.Core/Physics/TransitionTypes.cs
git commit -m "$(cat <<'EOF'
feat(physics): A6.P1 — instrument CheckOtherCells with [push-back-cell]
Wires LogPushBackCellTransit into the multi-cell BSP iteration loop
just before ApplyOtherCellResult halts. Captures primary/other
cell ids + BSP result for direct comparison to retail's
CTransition::check_other_cells loop (already ported as A4).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 8: Add ProbePushBack mirror to DebugVM
Files:
-
Modify:
src/AcDream.UI.Abstractions/Panels/Debug/DebugVM.cs(append afterProbeIndoorBspat line ~360) -
Step 1: Add the mirror property
After the ProbeIndoorBsp property in src/AcDream.UI.Abstractions/Panels/Debug/DebugVM.cs (closing } around line 360), insert:
/// <summary>
/// Phase A6.P1 cdb probe spike (2026-05-21). Runtime mirror of
/// <c>PhysicsDiagnostics.ProbePushBackEnabled</c> (env var
/// <c>ACDREAM_PROBE_PUSH_BACK</c>). Toggling here flips the three
/// <c>[push-back]</c> emission sites live — no relaunch required.
/// </summary>
public bool ProbePushBack
{
get => PhysicsDiagnostics.ProbePushBackEnabled;
set => PhysicsDiagnostics.ProbePushBackEnabled = value;
}
- Step 2: Verify build is green
Run: dotnet build src/AcDream.UI.Abstractions/AcDream.UI.Abstractions.csproj -c Debug --nologo
Expected: BUILD SUCCEEDED.
- Step 3: Commit
git add src/AcDream.UI.Abstractions/Panels/Debug/DebugVM.cs
git commit -m "$(cat <<'EOF'
feat(ui): A6.P1 — add ProbePushBack mirror to DebugVM
Runtime checkbox mirror for ProbePushBackEnabled. Toggling in
DebugPanel (under ACDREAM_DEVTOOLS=1) flips all three [push-back]
emission sites live without relaunch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 9: Update CLAUDE.md "Diagnostic env vars" section
Files:
-
Modify:
CLAUDE.md("Diagnostic env vars" subsection) -
Step 1: Locate the section
Run: grep -n "ACDREAM_PROBE_RESOLVE\|Diagnostic env vars" CLAUDE.md | head -5
Identify the line where the existing ACDREAM_PROBE_* env var documentation ends.
- Step 2: Add the new env var entry
Append the new entry immediately after the existing ACDREAM_PROBE_WALK_MISS entry (look for the [walk-miss] documentation line). Add:
- `ACDREAM_PROBE_PUSH_BACK=1` — A6.P1 cdb probe spike (2026-05-21).
Emits three line types per physics tick: `[push-back]` (per
`BSPQuery.AdjustSphereToPlane` call), `[push-back-disp]` (per
`BSPQuery.FindCollisions` dispatch), `[push-back-cell]` (per
`Transition.CheckOtherCells` off-cell hit). Heavy under motion
(~100–500 lines/sec). Pair with retail's cdb breakpoint set at
`tools/cdb/a6-probe.cdb` for the A6.P1 capture protocol.
Runtime-toggleable via the DebugPanel "Diagnostics" section.
- Step 3: Commit
git add CLAUDE.md
git commit -m "$(cat <<'EOF'
docs(CLAUDE): A6.P1 — document ACDREAM_PROBE_PUSH_BACK env var
Adds the new probe to the Diagnostic env vars list with hit-rate
estimate and cross-reference to the cdb probe script.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Phase B — Build the cdb script + infrastructure
Task 10: Write tools/cdb/a6-probe.cdb
Files:
-
Create:
tools/cdb/a6-probe.cdb -
Step 1: Verify the parent directory exists
ls tools/ 2>&1; mkdir -p tools/cdb
- Step 2: Write the cdb script
Create tools/cdb/a6-probe.cdb:
$$
$$ Phase A6.P1 cdb probe spike — 2026-05-21
$$
$$ 7 breakpoints on retail's BSP collision response sites. Each BP fires
$$ a non-blocking action (printf + gc), incrementing a per-BP counter.
$$ Auto-detaches via 'qd' after 50,000 total hits to avoid retail lag.
$$
$$ Symbol lookup convention per CLAUDE.md "Retail debugger toolchain":
$$ - snake_case for BSPTREE, CTransition, OBJECTINFO, COLLISIONINFO, SPHEREPATH
$$ - PascalCase for CPhysicsObj
$$ - Always 'x' first to confirm the actual name
$$
.logopen /t a6-probe-${ARG_LOG_TAG}.log
.sympath C:\Users\erikn\source\repos\acdream\refs
.symopt+ 0x40
.reload /f acclient.exe
$$ Counters: $t0 = total hits, $t1..$t7 = per-BP hits
r $t0 = 0
r $t1 = 0
r $t2 = 0
r $t3 = 0
r $t4 = 0
r $t5 = 0
r $t6 = 0
r $t7 = 0
$$ BP1: CTransition::transitional_insert
bp acclient!CTransition::transitional_insert "r $t1 = @$t1 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP1] transitional_insert hit#%d eax_2=%d insertType=%d\\n\", @$t1, poi(@ecx+0x18), poi(@ecx+0x1c); .if (@$t0 >= 50000) { qd } .else { gc }"
$$ BP2: CTransition::step_up
bp acclient!CTransition::step_up "r $t2 = @$t2 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP2] step_up hit#%d walkable_allowance=%f\\n\", @$t2, poi(@ecx+0x60); .if (@$t0 >= 50000) { qd } .else { gc }"
$$ BP3: SPHEREPATH::set_collide
bp acclient!SPHEREPATH::set_collide "r $t3 = @$t3 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP3] set_collide hit#%d normalZ=%f\\n\", @$t3, dwo(@edx+0x8); .if (@$t0 >= 50000) { qd } .else { gc }"
$$ BP4: BSPTREE::find_collisions
bp acclient!BSPTREE::find_collisions "r $t4 = @$t4 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP4] find_collisions hit#%d collide=%d insertType=%d\\n\", @$t4, poi(@ecx+0x40), poi(@ecx+0x1c); .if (@$t0 >= 50000) { qd } .else { gc }"
$$ BP5: CPolygon::adjust_sphere_to_plane (the over-correction suspect)
bp acclient!CPolygon::adjust_sphere_to_plane "r $t5 = @$t5 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP5] adjust_sphere hit#%d Nx=%f Ny=%f Nz=%f d=%f cx=%f cy=%f cz=%f r=%f winterp=%f\\n\", @$t5, dwo(@ecx+0x0), dwo(@ecx+0x4), dwo(@ecx+0x8), dwo(@ecx+0xc), dwo(@edx+0x0), dwo(@edx+0x4), dwo(@edx+0x8), dwo(@edx+0xc), dwo(@edi+0x40); .if (@$t0 >= 50000) { qd } .else { gc }"
$$ BP6: CTransition::validate_walkable
bp acclient!CTransition::validate_walkable "r $t6 = @$t6 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP6] validate_walkable hit#%d arg2=%f\\n\", @$t6, dwo(@esp+0x4); .if (@$t0 >= 50000) { qd } .else { gc }"
$$ BP7: COLLISIONINFO::set_contact_plane
bp acclient!COLLISIONINFO::set_contact_plane "r $t7 = @$t7 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP7] set_contact_plane hit#%d isWater=%d\\n\", @$t7, dwo(@esp+0x8); .if (@$t0 >= 50000) { qd } .else { gc }"
.printf \"a6-probe armed: BPs 1-7 set, threshold=50000 total hits, qd on threshold\\n\"
$$ Continue execution
g
Note: The ${ARG_LOG_TAG} placeholder is substituted by the PowerShell runner (Task 11) per scenario. The field offsets (+0x18, +0x1c, etc.) are based on the named-retail struct layouts in docs/research/named-retail/acclient.h; if a BP fires with garbage values, verify the offset against the struct definition.
- Step 3: Commit
git add tools/cdb/a6-probe.cdb
git commit -m "$(cat <<'EOF'
feat(cdb): A6.P1 — 7-BP probe script for retail BSP collision response
Sets non-blocking breakpoints on transitional_insert, step_up,
set_collide, find_collisions, adjust_sphere_to_plane,
validate_walkable, set_contact_plane. Each BP increments a counter
and emits a single printf line. Auto-detach via qd at 50K total
hits to avoid retail lag (CLAUDE.md gotcha — high BP rates trigger
ACE timeout).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 11: Write tools/cdb/a6-probe-runner.ps1
Files:
-
Create:
tools/cdb/a6-probe-runner.ps1 -
Step 1: Write the wrapper
Create tools/cdb/a6-probe-runner.ps1:
# Phase A6.P1 cdb probe runner — 2026-05-21
#
# Attaches cdb to a live retail acclient.exe with the a6-probe.cdb script.
# Per-scenario usage:
# .\tools\cdb\a6-probe-runner.ps1 -ScenarioTag "scen1_inn_doorway"
#
# Prerequisites (verify before invoking):
# 1. Retail acclient.exe v11.4186 running and in-world (matches refs/acclient.pdb).
# Verify with: py tools\pdb-extract\check_exe_pdb.py "C:\Turbine\Asheron's Call\acclient.exe"
# 2. ACE running locally on 127.0.0.1:9000.
# 3. Retail character at the scenario start position.
#
# Output:
# docs\research\2026-05-21-a6-captures\<ScenarioTag>\retail.log
param(
[Parameter(Mandatory=$true)]
[string]$ScenarioTag
)
$cdbExe = "C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe"
if (-not (Test-Path $cdbExe)) {
Write-Error "cdb.exe not found at $cdbExe. Install Microsoft Store WinDbg (~50 MB)."
exit 1
}
$scriptPath = Join-Path $PSScriptRoot "a6-probe.cdb"
if (-not (Test-Path $scriptPath)) {
Write-Error "a6-probe.cdb not found at $scriptPath."
exit 1
}
$captureDir = Join-Path $PSScriptRoot "..\..\docs\research\2026-05-21-a6-captures\$ScenarioTag"
if (-not (Test-Path $captureDir)) {
New-Item -ItemType Directory -Path $captureDir | Out-Null
}
$logPath = Join-Path $captureDir "retail.log"
# Patch the .cdb script with the scenario-tagged log path (in-place substitution).
$scriptContent = Get-Content $scriptPath -Raw
$patchedScript = $scriptContent -replace '\$\{ARG_LOG_TAG\}', $ScenarioTag
$tempScript = Join-Path $env:TEMP "a6-probe-$ScenarioTag.cdb"
Set-Content -Path $tempScript -Value $patchedScript -Encoding ASCII
Write-Host "Attaching cdb to acclient.exe with scenario tag '$ScenarioTag'..."
Write-Host "Log: $logPath"
Write-Host "(cdb auto-detaches at 50K total hits; or press Ctrl-Break to interrupt.)"
& $cdbExe -pn acclient.exe -cf $tempScript 2>&1 | Tee-Object -FilePath $logPath
Remove-Item $tempScript -ErrorAction SilentlyContinue
Write-Host ""
Write-Host "Capture complete. Log saved to $logPath"
- Step 2: Commit
git add tools/cdb/a6-probe-runner.ps1
git commit -m "$(cat <<'EOF'
feat(cdb): A6.P1 — PowerShell runner for a6-probe.cdb
Wrapper that attaches cdb to a live retail acclient.exe with a
scenario-tagged log path. Per-scenario invocation:
.\tools\cdb\a6-probe-runner.ps1 -ScenarioTag "scen1_inn_doorway"
Output: docs\research\2026-05-21-a6-captures\<ScenarioTag>\retail.log
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 12: Write tools/cdb/README-a6-probe.md
Files:
-
Create:
tools/cdb/README-a6-probe.md -
Step 1: Write the README
Create tools/cdb/README-a6-probe.md:
# A6.P1 cdb probe — usage
Phase A6.P1 cdb probe spike (2026-05-21). Captures retail's per-tick BSP
collision response state for paired comparison against acdream.
## Files
- `a6-probe.cdb` — the 7-breakpoint cdb script (see comments inside).
- `a6-probe-runner.ps1` — PowerShell wrapper that attaches cdb to live retail.
## Prerequisites
1. **Retail binary matches our PDB.** Verify with:
```powershell
py tools\pdb-extract\check_exe_pdb.py "C:\Turbine\Asheron's Call\acclient.exe"
Expected: === MATCH: this exe pairs with our acclient.pdb ===
-
cdb installed. Microsoft Store WinDbg installs cdb at
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe. 32-bit required for acclient.exe. -
Retail running and in-world. Launch retail, log into your character, navigate to the scenario start point.
-
ACE running locally on 127.0.0.1:9000.
Usage
For each of the 9 A6.P1 scenarios:
# 1. Position retail character at scenario start (e.g., outside Holtburg inn).
# 2. Launch the probe with a scenario tag:
.\tools\cdb\a6-probe-runner.ps1 -ScenarioTag "scen1_inn_doorway"
# 3. cdb attaches; "a6-probe armed: BPs 1-7 set" appears in console.
# 4. In the retail client window, perform the scripted walk for this scenario.
# 5. cdb auto-detaches at 50K total hits (cleanly via qd; retail keeps running).
# 6. Log filed at docs\research\2026-05-21-a6-captures\scen1_inn_doorway\retail.log
The 9 scenarios
Per the A6 design spec, in capture order:
| # | Tag | Walk script |
|---|---|---|
| 1 | scen1_inn_doorway |
Walk forward through door, stop just inside |
| 2 | scen2_inn_stairs |
Walk up 4 steps, stop on landing |
| 3 | scen3_inn_2nd_floor |
Walk forward 3 m, sidestep 1 m, walk back |
| 4 | scen4_cottage_cellar |
Walk to cellar opening, descend 2 steps |
| 5 | scen5_sewer_entry |
Walk into portal, then walk 2 m forward inside |
| 6 | scen6_sewer_first_stair |
Walk down full stair flight |
| 7 | scen7_sewer_inter_room |
Walk through portal, stop 1 m past |
| 8 | scen8_sewer_chamber |
Walk in, traverse center, walk out other side |
| 9 | scen9_sewer_corridor |
Walk full length end-to-end |
Pairing with acdream
For each scenario, run acdream IN PARALLEL with the same scripted walk:
$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_PUSH_BACK = "1"
$env:ACDREAM_PROBE_INDOOR_BSP = "1"
$env:ACDREAM_PROBE_CELL = "1"
$env:ACDREAM_PROBE_CELL_CACHE = "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 "docs\research\2026-05-21-a6-captures\scen1_inn_doorway\acdream.log"
The [push-back], [push-back-disp], [push-back-cell] lines in
acdream.log pair with the [BP1]..[BP7] lines in retail.log via
scenario tag.
Known watchouts
Per CLAUDE.md:
- High BP hit rates cause retail lag. 50K threshold is the calibrated ceiling that keeps retail responsive without triggering ACE timeout.
qd(quit detached) is forbidden in BP actions per CLAUDE.md cdb watchout. The a6-probe.cdb script putsqdONLY in the threshold branch, NOT directly in a BP action's primary command list. Verify this is preserved if editing.- Killing cdb kills retail.
qddetaches cleanly;Stop-Processdoes not. If you must interrupt mid-capture, press Ctrl-Break in the cdb console. - acclient.exe is 32-bit + uses thiscall.
thisis inecx. Struct field offsets in the script come fromdocs/research/named-retail/acclient.h.
- [ ] **Step 2: Commit**
```bash
git add tools/cdb/README-a6-probe.md
git commit -m "$(cat <<'EOF'
docs(cdb): A6.P1 — README for the cdb probe + runner
Documents prerequisites (PDB match, cdb install, retail+ACE
running), per-scenario invocation, the 9-scenario tag table, and
the parallel acdream capture command. Includes the CLAUDE.md cdb
watchouts inline so probe operators don't have to chase them.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Phase C — Execute 9 captures + file findings stub
Task 13: Verify retail binary matches PDB
Files: None modified — verification step.
- Step 1: Run the PDB matcher
py tools\pdb-extract\check_exe_pdb.py "C:\Turbine\Asheron's Call\acclient.exe"
Expected: === MATCH: this exe pairs with our acclient.pdb ===
If MISMATCH: stop. Investigate which retail build is installed; either re-install the matching build or update refs/acclient.pdb to match. Don't proceed with captures using a mismatched PDB — symbol resolution will fail and all BP actions will dump garbage.
- Step 2: Document the result in the capture directory
After confirming MATCH, capture the verification output to file. This is the audit trail for the capture session:
mkdir -p docs\research\2026-05-21-a6-captures
py tools\pdb-extract\check_exe_pdb.py "C:\Turbine\Asheron's Call\acclient.exe" > docs\research\2026-05-21-a6-captures\pdb-match-verification.txt 2>&1
- Step 3: Commit the verification artifact
git add docs/research/2026-05-21-a6-captures/pdb-match-verification.txt
git commit -m "$(cat <<'EOF'
docs(research): A6.P1 — record retail-PDB match verification
Audit trail for the A6.P1 capture session: confirms the live retail
acclient.exe matches refs/acclient.pdb before any BP-driven
captures fire.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 14: Create capture directory structure + findings doc stub
Files:
-
Create:
docs/research/2026-05-21-a6-captures/scen{1..9}_<name>/.gitkeep(9 stub dirs) -
Create:
docs/research/2026-05-21-a6-cdb-capture-findings.md(findings doc stub) -
Step 1: Create the per-scenario directory stubs
$scenarios = @(
"scen1_inn_doorway",
"scen2_inn_stairs",
"scen3_inn_2nd_floor",
"scen4_cottage_cellar",
"scen5_sewer_entry",
"scen6_sewer_first_stair",
"scen7_sewer_inter_room",
"scen8_sewer_chamber",
"scen9_sewer_corridor"
)
foreach ($s in $scenarios) {
$dir = "docs\research\2026-05-21-a6-captures\$s"
if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir | Out-Null }
New-Item -ItemType File -Path "$dir\.gitkeep" -Force | Out-Null
}
- Step 2: Create the findings doc stub
Create docs/research/2026-05-21-a6-cdb-capture-findings.md:
# A6.P1 cdb capture findings — 2026-05-21
**Status:** STUB — captures in progress. Tables filled by A6.P2 analysis.
**Spec:** [`docs/superpowers/specs/2026-05-21-phase-a6-indoor-physics-fidelity-design.md`](../superpowers/specs/2026-05-21-phase-a6-indoor-physics-fidelity-design.md).
**PDB match verification:** [`pdb-match-verification.txt`](2026-05-21-a6-captures/pdb-match-verification.txt).
## Capture inventory
| Scenario | Tag | Retail log | acdream log | Status |
|---|---|---|---|---|
| 1 | scen1_inn_doorway | [retail.log](2026-05-21-a6-captures/scen1_inn_doorway/retail.log) | [acdream.log](2026-05-21-a6-captures/scen1_inn_doorway/acdream.log) | pending |
| 2 | scen2_inn_stairs | [retail.log](2026-05-21-a6-captures/scen2_inn_stairs/retail.log) | [acdream.log](2026-05-21-a6-captures/scen2_inn_stairs/acdream.log) | pending |
| 3 | scen3_inn_2nd_floor | [retail.log](2026-05-21-a6-captures/scen3_inn_2nd_floor/retail.log) | [acdream.log](2026-05-21-a6-captures/scen3_inn_2nd_floor/acdream.log) | pending |
| 4 | scen4_cottage_cellar | [retail.log](2026-05-21-a6-captures/scen4_cottage_cellar/retail.log) | [acdream.log](2026-05-21-a6-captures/scen4_cottage_cellar/acdream.log) | pending |
| 5 | scen5_sewer_entry | [retail.log](2026-05-21-a6-captures/scen5_sewer_entry/retail.log) | [acdream.log](2026-05-21-a6-captures/scen5_sewer_entry/acdream.log) | pending |
| 6 | scen6_sewer_first_stair | [retail.log](2026-05-21-a6-captures/scen6_sewer_first_stair/retail.log) | [acdream.log](2026-05-21-a6-captures/scen6_sewer_first_stair/acdream.log) | pending |
| 7 | scen7_sewer_inter_room | [retail.log](2026-05-21-a6-captures/scen7_sewer_inter_room/retail.log) | [acdream.log](2026-05-21-a6-captures/scen7_sewer_inter_room/acdream.log) | pending |
| 8 | scen8_sewer_chamber | [retail.log](2026-05-21-a6-captures/scen8_sewer_chamber/retail.log) | [acdream.log](2026-05-21-a6-captures/scen8_sewer_chamber/acdream.log) | pending |
| 9 | scen9_sewer_corridor | [retail.log](2026-05-21-a6-captures/scen9_sewer_corridor/retail.log) | [acdream.log](2026-05-21-a6-captures/scen9_sewer_corridor/acdream.log) | pending |
## Analysis tables (filled by A6.P2)
### Table 1 — Per-site push-back delta
*Placeholder — filled by A6.P2 analysis. Rows = (site × scenario) cross-product.
Delta computed as `‖output_center − input_center‖` per call. Bug candidate
threshold: ratio > 3× retail.*
| Site | Scenario | Retail mean delta (mm) | Retail p99 (mm) | acdream mean (mm) | acdream p99 (mm) | Ratio |
|---|---|---|---|---|---|---|
### Table 2 — Path-frequency diff
*Placeholder — filled by A6.P2 analysis. Paths labeled 1-7 per the
find_collisions dispatcher.*
| Scenario | Path | Retail count | acdream count | Diff % |
|---|---|---|---|---|
### Table 3 — ContactPlane lifecycle diff
*Placeholder — filled by A6.P2 analysis.*
| Scenario | Retail CP writes/sec | acdream CP writes/sec | Retail CP-restore-from-LKCP/sec | acdream CP-restore/sec |
|---|---|---|---|---|
### Table 4 — Sub-step state mutations
*Placeholder — filled by A6.P2 analysis. Fields: cell_array_valid,
hits_interior_cell, walk_interp, walkable, collide.*
| Scenario | Field | Retail mutations/sec | acdream mutations/sec |
|---|---|---|---|
## Per-scenario narrative (filled by A6.P2)
### Scenario 1 — Inn doorway entry
*Placeholder.*
### Scenario 2 — Inn stairs ascent
*Placeholder.*
*(etc. — 3 through 9)*
## Findings (filled by A6.P2)
*Numbered bug candidates. Each entry contains: title, retail decomp
anchor (line in acclient_2013_pseudo_c.txt), our suspect code site
(file + line), divergence quantified, proposed fix sketch, scenarios
affected.*
- Step 3: Commit the stub structure
git add docs/research/2026-05-21-a6-captures/ docs/research/2026-05-21-a6-cdb-capture-findings.md
git commit -m "$(cat <<'EOF'
docs(research): A6.P1 — capture directory structure + findings stub
Creates the 9 per-scenario capture directories (gitkeep stubs) and
the findings doc stub at docs/research/2026-05-21-a6-cdb-capture-findings.md.
A6.P1 fills the capture log slots; A6.P2 fills the analysis tables
and findings section.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Task 15: Execute the 9 capture scenarios (USER-DRIVEN)
Files:
- Modify (filled by capture runs):
docs/research/2026-05-21-a6-captures/scen{1..9}_<name>/{retail,acdream}.log - Modify:
docs/research/2026-05-21-a6-cdb-capture-findings.md(update "Status" column frompending→captured)
Operator role: This task is USER-DRIVEN — the user runs retail + acdream clients, executes the scripted walks, and confirms each scenario's capture pair is filed. Each scenario is ~5 min of user time at the keyboard. Captures can be split across days; each scenario's pair is self-contained.
For EACH of the 9 scenarios:
- Step 1: Position retail at scenario start
Open retail client, navigate to the scenario start position. For scenario 1: outside the Holtburg inn front door, facing the doorway. Stop. (Don't move while the cdb attaches.)
- Step 2: Attach cdb with the scenario tag
.\tools\cdb\a6-probe-runner.ps1 -ScenarioTag "<scenN_name>"
Wait for a6-probe armed: BPs 1-7 set, threshold=50000 total hits, qd on threshold
in the cdb console.
- Step 3: Launch acdream with all probes enabled
In a SEPARATE PowerShell window:
$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_PUSH_BACK = "1"
$env:ACDREAM_PROBE_INDOOR_BSP = "1"
$env:ACDREAM_PROBE_CELL = "1"
$env:ACDREAM_PROBE_CELL_CACHE = "1"
$env:ACDREAM_PROBE_CONTACT_PLANE = "1"
dotnet build -c Debug
dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 |
Tee-Object -FilePath "docs\research\2026-05-21-a6-captures\<scenN_name>\acdream.log"
Navigate +Acdream to the same scenario start position. Stop.
- Step 4: Perform the scripted walk in BOTH clients
Per the README table:
| Scenario | Walk script |
|---|---|
| 1 inn doorway | Walk forward through door, stop just inside |
| 2 inn stairs | Walk up 4 steps, stop on landing |
| 3 inn 2nd floor | Walk forward 3 m, sidestep 1 m, walk back |
| 4 cottage cellar | Walk to cellar opening, descend 2 steps |
| 5 sewer entry | Walk into portal, then walk 2 m forward inside |
| 6 sewer first stair | Walk down full stair flight |
| 7 sewer inter-room | Walk through portal, stop 1 m past |
| 8 sewer chamber | Walk in, traverse center, walk out other side |
| 9 sewer corridor | Walk full length end-to-end |
Perform the SAME walk in retail and in acdream. cdb fires BPs; acdream
emits [push-back] lines.
- Step 5: Teardown
cdb auto-detaches at 50K hits. If it doesn't fire within ~30 sec of the walk completing, press Ctrl-Break in the cdb console.
Close acdream by gracefully closing the window (NOT Stop-Process, per CLAUDE.md logout-before-reconnect rules).
- Step 6: Verify capture files are non-empty
$dir = "docs\research\2026-05-21-a6-captures\<scenN_name>"
Get-Item "$dir\retail.log", "$dir\acdream.log" | Format-Table Name, Length
Expected: both files > 1 KB. If retail.log is < 1 KB, BPs didn't fire —
investigate (probably PDB load failed or retail wasn't in-world).
If acdream.log doesn't contain [push-back] lines, the env var didn't
take effect — re-launch.
- Step 7: Mark scenario captured + commit
Update docs/research/2026-05-21-a6-cdb-capture-findings.md: change
the scenario's row "Status" from pending to captured.
git add docs/research/2026-05-21-a6-captures/<scenN_name>/ docs/research/2026-05-21-a6-cdb-capture-findings.md
git commit -m "$(cat <<'EOF'
capture(research): A6.P1 — scenario <N> <name>
Paired retail + acdream traces filed at
docs/research/2026-05-21-a6-captures/<scenN_name>/.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
Repeat steps 1–7 for all 9 scenarios. Total user time: ~45 min (5 min per scenario) + ~30 min capture-setup overhead = ~75 min single session. Splittable across days; each scenario's commit is self-contained.
A6.P1 acceptance
Phase A6.P1 is complete when:
- All 9 scenarios have
{retail,acdream}.logpairs filed underdocs/research/2026-05-21-a6-captures/scenN_<name>/. - Each log pair is non-empty (retail > 1 KB, acdream > 1 KB).
- Each scenario's row in
docs/research/2026-05-21-a6-cdb-capture-findings.mdshows Status =captured. pdb-match-verification.txtis filed as audit trail.- The
[push-back],[push-back-disp],[push-back-cell]probes ship on main (Tasks 1–9 committed). dotnet buildgreen,dotnet testbaseline unchanged (no test regressions from the probe instrumentation — probe is zero-cost when off).
A6.P2 takes the captures + findings doc stub and produces the quantitative analysis tables + bug candidates list.