Campaign OVERHAUL S3 chunk 1 (docs/research/2026-09-01-overhaul/s3-walk-ownership-map.md
§11): the transcript-kinds/fixtures/print-only-emitter half of the walk work,
built AFTER chunk 3 landed LC/SC (the per-land-cell interleave).
B1 — the emitter (print-only, never gates admission/depth/order):
- ACDREAM_DUMP_WALK_TRANSCRIPT=1 is read once into RuntimeOptions.DumpWalkTranscript
(rule 4) and handed to RenderingDiagnostics.DumpWalkTranscriptEnabled (rule 5,
a settable static, not a second env read) once at GameWindow construction — the
deep walk call sites have no reachable RuntimeOptions reference.
- WalkTranscriptDump (new) prints the OH line kinds — F/P/LS/LC/SC/BLD/DI/DC/EC/OC —
to Console at the exact points retail's cdb breakpoints sit
(tools/walk-oracle/oh/oh-capture-walk.cdb.template), gated internally so every
method bails out before any string work when the flag is off.
- Every call site lives in WalkFrameDriver.cs, at the point the driver already
processes that turn: Collect (F/P, after BeginFrame), Emit's DI/LS/DC/BLD cases,
OnLandCellTurn/OnLandscapeCellTurn (LC/SC, at LOD resolution via the new
WalkTranscriptDump.LodCellId helper, before the 8x8-bucket expansion), and the
EmitFloodTurns/EmitCellContentsTurn loops (EC/OC — both UNCONDITIONAL per flood
visit, matching the OH captures' always-equal EC/OC counts; retail's own
DrawEnvCell stamp dedupe sits past the breakpoint, inside the function).
- DC's "pv=" field encodes interior(0)/outdoor(1) as an 8-hex-digit 0/1 so it
satisfies the same pv=[0-9a-f]{8} regex real captures use; derived from
_currentDcStage at the DC event (CellStatic = interior pview, else outdoor).
- The frame-root pose (origin, quaternion) is a reasonable orthonormal basis built
from the walk's own CyPlane.Normal forward vector and WalkLandscape's own
ViewerWorldOriginX/Y block origin — self-consistent for the round-trip parser,
not a byte-exact reproduction of retail's Frame (B4's diff never compares P).
B2 — WalkOracleTrace learns EC/OC event kinds (LC/SC already existed from chunk 3).
New WalkOraclePartsTrace.cs holds two small read-only parsers for the parts log
(PD/DM) and the alpha-depth log (AM/FL/PM/PC) — records only, no validator, no
canonical JSONL, no new tool.
B3 — fixtures: the five OH walk captures join WalkOracleTraceTests.AllFixtures
(now (root, name) pairs — FW0's own root plus the OH capture directory) for
parse + complete-frame pins. The four kit poses join WalkTraceConformanceTests'
still-fixture coverage as NEW rows (the OH cathedral-arrival root is f4180108,
not FW0's f4180106): terrace-edge/cathedral-arrival extend the existing theory
(now (root, fixture) parameterized); holtburg-doorway-still and foundry-deep get
dedicated tests mirroring their FW0 siblings' own structure. Finding: the OH
foundry-deep capture's own retail transcript draws 12 real town buildings through
its exit chain (unlike the FW0 capture, which apparently reached none at that
pose) — the FW0 test's stub 1x1 landscape undershoots it (first divergence:
nothing after "LS" vs retail's real BLD content); fixed by building the full
landscape/building world via WalkLandscapeDatBuilder.Build, matching the shared
theory's own approach, not by skipping or weakening the row.
WalkTraceReplayContext.Signature(WalkOracleFrame) now filters to the DI/DC/BLD/LS
kinds (LC/SC/EC/OC never had a WalkEvent analogue in RetailFrameWalk's own
four-kind vocabulary) instead of mapping them to a "?" placeholder, so the still-
fixture comparison stays apples-to-apples on both sides.
B4 — WalkTranscriptSignatureDiff (test-side only, no runner/tool): diffs two
transcripts (raw lines or parsed frames) at the full DI/DC/BLD/LS/LC/SC/EC/OC
level, reporting the first divergent event and position per frame. Proven over a
synthetic self-vs-self-minus-one-event pair (SignatureDiff_ReportsTheExactRemovedEvent).
Tests: T1 (flag off) is split into a unit-level zero-allocation/zero-output check
on WalkTranscriptDump itself (the walk's pre-existing allocation, e.g.
RetailFrameWalk.EmitDrawCells's per-call array, is untouched by this chunk and not
independently zero-alloc) and an integration-level Collect() check; both assert via
WalkOracleTrace.Parse returning zero frames rather than raw string equality, which
is robust to unrelated Console.WriteLine noise from other test classes running in
parallel (a real, observed hazard — WalkFrameDriverTests joins
CameraDiagnosticsCollection for the same reason CornerFloodReplayTests/
Issue181WallPressEquilibriumTests already do, issue #251). T2 proves the
emitter/parser round trip on a synthetic interior frame. T3's InstalledDat rows all
pass. T4: LaunchOptionsDocumentationTests green with the ACDREAM_DUMP_WALK_TRANSCRIPT
row (both directions).
Gates: hermetic lane 6,814/0 (was 6,795 baseline + new tests), three consecutive
clean runs; InstalledDat lane 245/3 known-failures (the two pre-existing #383
layout tests + TowerAscent) unchanged from baseline.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Ports RenderDeviceD3D::DrawBlock @0x005a17c0's real per-cell order:
loop 1 (@0x005a1876) prepares shadow lists; loop 2 (@0x005a197d)
DrawLandCell(cell) @0x005a19c0 fires ONLY when the cell is in view,
STRICTLY BEFORE DrawSortCell(cell) @0x005a19e6, which fires whenever
alwaysDrawObjects (retail default 1 @0x00820ed4) or the cell is in
view. RetailFrameWalk.DrawLandscape now emits sink.OnLandCellTurn(
landblockId, side, cellIndex) at that exact point, per admitted cell,
before the existing DrawBuilding + OnLandscapeCellTurn (the
DrawSortCell half). WalkFrameDriver records one LandCell frame event
per turn and deletes the whole-stage TerrainSlice(0) emission and the
DrawTerrainSlice leaf outright — drawing all terrain before every
building let a nearer building's far-Z punch survive under farther
terrain drawn afterward, the doorway-behind-a-hill fragment bug from
the owner's G2 Holtburg screenshot; this chunk removes it by ORDER
alone, with no depth-compare change (S4's punch z-func question is
untouched, per the contract).
Index-run arithmetic (S3 §9.1 R3): the terrain mesh is cell-major
(LandblockMesh.Build: cy outer, cx inner, 6 indices/cell, 384/land-
block). A retail LOD cell (side n, LOD coords X,Y) covers cx in
[X*8/n,(X+1)*8/n), cy in [Y*8/n,(Y+1)*8/n) — one contiguous run per
covered cy row: side 8 -> one run of 6, side 4 -> two runs of 12,
side 2 -> four runs of 24; side 1's single coarse cell covers every
row contiguously so its 8 per-row runs collapse into ONE run of all
384 indices. TerrainModernRenderer.AppendCellIndexRuns (pure, no GPU,
no baked table) and DrawLandCellRuns (resolves the landblock's slot,
builds one DrawElementsIndirectCommand per run, reuses the existing
DrawRhi bind-and-submit path) implement this; TerrainModernRenderer
.Draw(...) is untouched and keeps serving non-walk callers (directional-
shadow receivers, the flat terrain path).
Order-preserving batching (S3 §9.2 B2): WalkFrameDriver.Replay merges
consecutive same-landblock LandCell events with no intervening event
into ONE DrawLandCellBatch leaf call; any other event splits the
batch. In production this rarely fires because retail's own
DrawSortCell (AlwaysDrawObjects=true) always interposes an object-
list turn between one cell's LandCell event and the next's — see
perfNote in the task report for the resulting command-count increase.
Deleted as dead: the _walkTerrainInViewLandcells field and
SetWalkTerrainInViewLandcells setter on RetailPViewPassExecutor (fed
only DrawWalkTerrainSlice's inViewLandcells filter, which no longer
exists — the walk's own per-cell CellInView admission is now the
sole terrain-visibility authority) and its two call sites in
RetailPViewRenderer.DrawWalkDrivenStatics.
Weather placement (S3 §9.1 R5): confirmed unchanged. GameSky's
weather pass (RenderWeather, gated on is_player_outside) already
runs after every LandCell event for both root kinds — for an
outdoor root, DrawLandscapeDynamicsPhase is called directly after
driver.Replay() completes (which processes the whole per-cell
_events list first); for an interior root with ov>0, it fires via
the LandscapeFlush leaf (RetailPViewRenderer.FlushWalkLandscape ->
_walkPreClearDynamics), and OnInteriorFloodDrawTurn only emits
LandscapeFlush AFTER DrawLandscape's per-cell loop has fully run
and recorded every LandCell event ahead of it in the same _events
list Replay walks in order. No code change needed; verified by
reading the call sites.
Tests: WalkEvents/RetailFrameWalk/WalkFrameDriver's existing pins
updated (every "TERRAIN:0" expectation deleted, matching the deleted
event); new coverage for T1 (WalkLandCellOrderTests — LandWalkOrder +
WalkLandscape.CalcDrawOrder + WalkLandscapeAssembler
.SideCellCountForRing reproduce both cathedral captures' frame-2
LC/SC sequences byte-for-byte, 533/698 arrival and 531/757 leak, cross-
verified against the retail ring-to-LOD table), T2 (a synthetic two-
block landscape with a real WalkVisibilityMath-driven out-of-view
column, proving LC-before-building/statics, far-to-near, no-LC-but-
keeps-SC for the excluded cells, and no TerrainSlice event of any
kind), T3 (TerrainLandCellIndexRunsTests — the index-run arithmetic
for every side/cell, disjoint and exhaustive over the 384-index
landblock), T4 (batching merge/split), and the RetailPViewPassExecutor
CompiledCallGraph pin retargeted at DrawWalkLandCellBatch /
DrawLandCellRuns. WalkOracleTrace gains LC/SC event kinds and a
Load(root, name) overload for the OH capture directory — the one
parser change this chunk needs, no validator, no other infrastructure.
App hermetic lane: 6,786/6,786 (6,765 baseline + 21 new). InstalledDat
lane: 241 passed, 3 accepted failures (2 pre-existing #383 layout
fixture-drift tests, 1 TowerAscent Status=KnownFailure) — unchanged
from baseline. Core terrain tests: 116/116 (Core untouched by this
chunk).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
WalkOracleTrace decodes the P lines of the pose-stamped capture round
(raw IEEE-754 dwords from Render::viewer_pos @0x0081ef00: camera cell,
world origin, the four Frame quaternion components in storage order)
into WalkOraclePose on each frame. Poseless FW0 fixtures parse as
before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
WalkOracleTrace parses the FW0 retail traces (frames of LS/BLD/DI/DC
events, truncated detach frame dropped) and loads fixtures from the
research directory. Nineteen tests pin the load-bearing shapes: the far
building drawn every terrace-edge frame, the cathedral roster cull, the
stable doorway root, the one-frame walkout handover, camera-cell rooting
(porch-cam), the foundry landscape drop, and bit-identical stationary
frames. FW1 conformance builds on these.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>