# A6.P1 partial-ship handoff — 2026-05-21 **Status:** Infrastructure complete + scenario 1 (Holtburg inn doorway) captured end-to-end (retail + acdream paired). Scenarios 2–9 deferred to next session. **Pasteable session-start prompt at the bottom of this doc.** ## TL;DR A6.P1 ships in two milestones: 1. **Infrastructure milestone (DONE today):** `[push-back]` acdream probe (3 helpers + 3 sites + DebugVM mirror + CLAUDE.md docs), cdb probe script (v4 with PDB-verified offsets + hex-bits float output), PowerShell runner with ASCII encoding, README, capture-dir scaffolding, PDB-match verification, type dumper, hex→float decoder. 2. **Capture milestone (PARTIAL):** 1 of 9 scenarios captured. Scenarios 2–9 user-driven, deferred at user direction to avoid fatigue. **Scenario 1 already surfaces two strong M1.5 findings** (before any formal A6.P2 analysis): | Metric | Retail | acdream | Notes | |---|---:|---:|---| | dispatcher entries (find_collisions / BSPQuery.FindCollisions) | 5,818 | 295 | acdream calls dispatcher **20× less often** | | ContactPlane writes (set_contact_plane fn / per-field writes) | 18 calls | **73,304** field-writes | acdream **rewrites CP every frame/sub-step** vs retail's per-event | The CP-write blowup directly confirms the spec's hypothesis ([2026-05-21-phase-a6-indoor-physics-fidelity-design.md §1.2](../superpowers/specs/2026-05-21-phase-a6-indoor-physics-fidelity-design.md)) that `FindEnvCollisions` indoor branch resynthesizes CP per frame instead of retaining via Mechanisms A/B/C. Same family as the `TryFindIndoorWalkablePlane` workaround. ## State both altitudes (next session) > **Currently working toward: M1.5 — "Indoor world feels right."** > > **Current phase: A6 — Indoor physics fidelity (cdb-driven).** > > **Next concrete step: Capture scenarios 2–9 (paired retail + acdream > traces). Then run A6.P2 analysis on all 9 captures.** ## What shipped today (16 commits) ### Infrastructure (Tasks 1–14 from the A6.P1 plan) | Commit | What | |---|---| | `ace9e62`, `ad6c89d` | T1: `ProbePushBackEnabled` toggle + roundtrip test | | `3a173b9` | T2: `LogPushBackAdjust` helper | | `eb8a318` | T3: instrument `BSPQuery.AdjustSphereToPlane` | | `2d1f27d` | T4: `LogPushBackDispatch` helper | | `35631d1` | T5: instrument `BSPQuery.FindCollisions` | | `66ee757` | T6: `LogPushBackCellTransit` helper | | `642734d` | T7: instrument `Transition.CheckOtherCells` | | `dd95c10` | T8: DebugVM `ProbePushBack` mirror | | `e1f7efe` | T9: CLAUDE.md `ACDREAM_PROBE_PUSH_BACK` env var docs | | `7bb799b` | T10: `tools/cdb/a6-probe.cdb` v1 (broken offsets) | | `1c640eb` | T11: `tools/cdb/a6-probe-runner.ps1` (later patched to ASCII) | | `df315a9` | T12: `tools/cdb/README-a6-probe.md` | | `0e21f22`, `22e341f` | T13: PDB-match verification (audit trail) | | `260c60f` | T14: capture-dir scaffolding + findings doc stub | ### cdb script iteration (T15 dry-runs) | Commit | What | |---|---| | `d0c8c54` | v1→v2 prep: type dumper (`a6-types-dump.cdb` + runner) + ASCII runner | | `7b9b26f` | v2 cdb script: PDB-verified offsets + BP6 fix to `check_walkable` | | `1b6d49e` | v3 cdb script: `@@c++(*(float*)addr)` for floats (still produced zeros) | | `2d841cb` | v4 cdb script: hex-bits float output via `%08X` (WORKS) | ### Scen1 capture + decode tooling | Commit | What | |---|---| | `180b4a5` | scen1 retail.log captured (v4 cdb, 13,552 hits, real hex bits) | | `8ca718a` | scen1 acdream.log paired (84,130 lines, full probe distribution) | | `194ed3e` | `decode_retail_hex.py` — Python hex→float decoder + scen1 decoded log | ## Why cdb v1→v4 iteration was necessary The cdb side hit three landmines we didn't anticipate when writing the A6.P1 plan: 1. **v1: Stack-arg offsets wrong.** Plan's probe actions used arbitrary registers (`@edx`, `@edi`) to read function args. `__thiscall` puts non-this args on the stack (`[esp+N]`), not in arbitrary registers. All 12 BP5 hits printed `Nx=0 Ny=0 ...` — confirming the read addresses were wrong. **Fix:** type dumper + double-indirect via `dwo(poi(@esp+N)+offset)`. 2. **v2: BP6 symbol wrong + PowerShell UTF-16 encoding.** v1's `validate_walkable` doesn't exist in the PDB (the actual function is `CTransition::check_walkable`). PowerShell's `Tee-Object` writes UTF-16 LE by default, making logs ungreppable. **Fixes:** BP6 symbol corrected, runner switched to `Out-File -Encoding ASCII`. v2 had correct integer reads (substeps=3, insertType=0) but all `%f` floats still printed as 0.000000. 3. **v3: `%f` doesn't work with `dwo()`.** Switching to `@@c++(*(float*)addr)` to force C++ interpretation also produced 0.000000 across all float fields. cdb's `.printf %f` appears to not reliably handle our float values (possibly varargs promotion, possibly a deeper limitation). **Workaround (v4):** print all floats as 32-bit hex bits via `%08X`; Python decoder reinterprets via `struct.unpack('= 50000)` → `100000`). 6. **BP6 fires with FloorZ (0.6642) not cos85 (0.0872).** v4 confirmed this — `check_walkable` is called with `PhysicsGlobals.FloorZ` for ground verdicts. The cos85 value (0.0872) is passed in a different code path (post-set_collide wall-slide) which didn't fire during scen1 (no wall hits). Will appear when scenarios 2–9 hit walls. ## Pickup prompt for fresh session Open a new Claude Code session at this worktree's branch (`claude/strange-albattani-3fc83c`, HEAD at the latest A6.P1 commit). Then paste: --- ``` Pick up A6.P1 capture work — scenarios 2 through 9. The infrastructure shipped today (probe + cdb v4 + decoder all working). Scenario 1 captured end-to-end with paired retail + acdream traces; preliminary findings already strong (CP-write blowup confirms the M1.5 hypothesis). Read FIRST: docs/research/2026-05-21-a6-p1-partial-ship-handoff.md Then state both altitudes: Currently working toward: M1.5 — Indoor world feels right Current phase: A6.P1 — capture scenarios 2-9 Next concrete step: scenario 2 (Holtburg inn stairs) Workflow per scenario (validated by scen1): 1. Verify retail binary matches PDB: py tools/pdb-extract/check_exe_pdb.py "C:/Turbine/Asheron's Call/acclient.exe" Expect MATCH (GUID {9e847e2f-...}). 2. User launches retail, walks character to scenario start, stops. 3. .\tools\cdb\a6-probe-runner.ps1 -ScenarioTag "scenN_..." Wait for "a6-probe v4 armed:" in the log file. 4. User performs the scripted walk. 5. Wait for cdb auto-detach (50K hits) OR kill cdb (acclient dies too; relaunch needed). Hit rate ~6.5K/sec under motion. 6. User launches acdream with all 5 probe env vars + output to docs/research/2026-05-21-a6-captures/scenN_.../acdream.log 7. User walks acdream through the SAME scripted walk. 8. Close acdream gracefully. 9. py tools/cdb/decode_retail_hex.py docs/research/.../retail.log 10. Commit retail.log + retail.decoded.log + acdream.log for that scenario. Scenario list per the README at tools/cdb/README-a6-probe.md. DO NOT modify the cdb script. v4 works (verified by BP6 threshold decoding to FloorZ 0.6642 exactly). The hex-bits + Python decoder pattern is the stable approach. CLAUDE.md rules apply: - Three failed visual verifications = handoff (we hit this on the cdb script v1→v2→v3 cycle; v4 broke the streak). - No workarounds without approval (v4 hex output isn't a workaround, it's the chosen design after cdb %f proved unreliable). - Visual verification at the Holtburg Sewer is the M1.5 physics acceptance test (deferred to A6.P4 after fixes land). After all 9 captures: proceed to A6.P2 analysis per the design spec docs/superpowers/specs/2026-05-21-phase-a6-indoor-physics-fidelity-design.md §4. Note: Finding 2 (CP-write blowup) is already evidence-confirmed from scen1; A6.P2 just needs to quantify + extend across scenarios. ``` --- ## References - Design 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) - Implementation plan: [`docs/superpowers/plans/2026-05-21-phase-a6-p1-cdb-probe-spike.md`](../superpowers/plans/2026-05-21-phase-a6-p1-cdb-probe-spike.md) - cdb script: [`tools/cdb/a6-probe.cdb`](../../tools/cdb/a6-probe.cdb) (v4) - cdb runner: [`tools/cdb/a6-probe-runner.ps1`](../../tools/cdb/a6-probe-runner.ps1) - Type dumper: [`tools/cdb/a6-types-dump.cdb`](../../tools/cdb/a6-types-dump.cdb) + [`a6-types-dump.txt`](../../tools/cdb/a6-types-dump.txt) (PDB-extracted offsets) - Hex decoder: [`tools/cdb/decode_retail_hex.py`](../../tools/cdb/decode_retail_hex.py) - Scen1 retail: [`docs/research/2026-05-21-a6-captures/scen1_inn_doorway/retail.log`](2026-05-21-a6-captures/scen1_inn_doorway/retail.log) + [`retail.decoded.log`](2026-05-21-a6-captures/scen1_inn_doorway/retail.decoded.log) - Scen1 acdream: [`docs/research/2026-05-21-a6-captures/scen1_inn_doorway/acdream.log`](2026-05-21-a6-captures/scen1_inn_doorway/acdream.log) - Findings doc stub (to be filled by A6.P2): [`docs/research/2026-05-21-a6-cdb-capture-findings.md`](2026-05-21-a6-cdb-capture-findings.md)