docs(render): OVERHAUL S3 ownership packet (draft, pre-capture)

s3-walk-ownership-map.md: the decomp-verified retail table for the walk
(views, stamps, DrawCells order, DrawBuilding sequence, landscape
far-to-near interleave), the current acdream owners with the S2-era
assessment, the four bounded chunks (transcript emitter blocked on the
owner's capture; exact PView state; landcell interleave; deletions), the
two review lenses, the automated gate, and the three exact traces to ask
for at the capture session. Ledger S3 row flipped to PACKET DRAFTED /
blocked on the capture; the G2 handoff points at it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-03 01:06:16 +02:00
parent 78068b2cfe
commit 31465a0ece
3 changed files with 149 additions and 2 deletions

View file

@ -87,7 +87,9 @@ layout sweeps (`LayoutImporterMediaBearingChildSweepTests`,
1. The owner's ~1 h retail capture session (`tools/walk-oracle/oh/`, recon attach
first) — add a `CTransition` trace at `num_sphere == 0` to retire AD-117(1).
2. S3 Walk.
2. S3 Walk — the ownership packet is DRAFTED and waiting for the capture:
`docs/research/2026-09-01-overhaul/s3-walk-ownership-map.md` (§7 lists the
three exact things to capture).
Open tails carried into S5: retire the obsolete `-CollisionShadowEvery` referee in
`tools/run-connected-r6-soak.ps1`; the `[walk-membership]` line rides the #177

View file

@ -0,0 +1,145 @@
# S3 — Walk: exact PView views, leaf admission, and interleave — ownership map and chunk plan
**Status:** DRAFT packet written 2026-09-03 at the S2 closeout, BEFORE the
owner's §7 capture session. Every retail claim below is decomp-verified
(named pseudo-C + Ghidra bridge, cited by address); the capture session adds
the per-frame TRANSCRIPT the automated gate needs and may amend §3 (marked
"capture-owned"). Nothing in this packet is implemented yet.
**Plan:** `docs/plans/2026-09-01-campaign-overhaul-world-solidity.md` §9 S3.
**Binding inputs:** `oh1-retail-world-contract.md` §4§5 (view/frame order),
`oh1-built-mesh-view-contract.md` (caller order, stamps, direct answers,
binding constraints), `2026-08-30-fw-flood-pseudocode-appendix.md`, the FW
plan's verified seam map (`docs/plans/2026-08-30-campaign-fw-frame-walk.md`
§"Verified seam map"), and S2's ownership truth
(`s2-membership-ownership-map.md` §9: the registry is the only membership
source; the walk reads `GetRetailPartEntriesInCell`).
## 1. What S3 changes (behavior)
`WalkPView` owns retail's exact per-frame state — the portal-view lists, the
view/update counts, the todo order, the draw list, and the stamps — and each
content category follows its retail leaf rule. Terrain is emitted as ordered
landcell events interleaved with buildings and object lists in retail
far-to-near order. `DrawBuilding` is one semantic sequence. The "all terrain
first" simplification and every generic GPU clip rule that retail does not
have are deleted. S3 ships no evidence infrastructure beyond the one
print-only transcript emitter its own gate consumes (rule §5).
## 2. Retail truth (decomp-verified; addresses are the Sept 2013 build)
| Retail function | Address | What it decides | Verified in |
|---|---|---|---|
| `PView::InitCell` / `InsCellTodoList` | (walk root; see flood appendix) | seeds the flood from the viewer cell, orders the todo list | flood appendix |
| `PView::ClipPortals` / `AddViewToPortals` / `ConstructView` | `PView::GetClip → polyClipFinish @0x006B6D00` | builds CHILD VIEWS by polygon-clipping PORTAL polygons — the only polygon clip in the walk | built-mesh contract §"What polygon-clips?" |
| `Render::copy_view` | `0x0054dfc0` | copies the view polygon, derives edge planes (0x48 semantic fields, prune, cap 31) | built-mesh contract ledger |
| `Render::set_view` | `0x0054d0e0` | installs the view in render globals; NO scissor, NO general mesh clip | idem |
| `Render::obj_view_set` | `0x0054b9b0` | transforms the active planes/sphere through `FrameCurrent`, publishes `local_object_center/radius` | idem (side effects unrepresented — Medium row) |
| `Render::viewconeCheck` | `0x0054c250` | the ordinary sphere admission: strict-outside / inclusive-partial | `WalkVisibilityMath` pins |
| `CPhysicsPart::Draw` | `0x0050d7a0` | outer part-stamp skip (`+0xdc` vs device `+0xb0`); force bypasses; local player bypasses the inner stamp | idem |
| `RenderDeviceD3D::DrawMeshInternal` | `0x0059f360` | first admitted view stamps the non-player part and submits the WHOLE eligible mesh once; later views return | idem |
| `RenderDeviceD3D::DrawEnvCell` | `0x0059f170` | no sphere admission; cell stamp (`+0x130`) gate; whole shell once per stamp | idem |
| `RenderDeviceD3D::DrawBuilding` | `0x0059f2a0` | detail state → `FlushAlphaList(0)``CPhysicsPart::Draw(part,1)` portal-only BSP pass → flag → `Draw(part,0)` ordinary shell | idem |
| `PView::DrawCells` | `0x005a4840` | outside-view branch (sunlight, `LScape::draw`, alpha flush, device-stamp advance @`0x005a4886`, counter consume/clear, exit seals) then reverse shells (`CEnvCell::setup_view @0x0052c430` per live view + `DrawEnvCell`) then reverse object lists (`DrawObjCellForDummies`) | retail-world contract §5.2 |
| `LScape::draw_check_blocks` / `landcell_check` / `grab_visible_cells` / `draw` / `calc_draw_order` | (landscape walk) | admitted land cells in retail FAR-TO-NEAR order; per admitted cell `DrawLandCell` THEN `DrawSortCell` (building pass / look-in / shell / object turn) | retail-world contract §5.2; **capture-owned:** the exact `calc_draw_order` sequence at the four poses |
| `DrawObjCellForDummies` | (object-list path) | installs the cell's top `portal_view_type` as `PortalList`, walks the cell's shadow part list (`CShadowPart::insertion_sort` by `CYpt`) and draws each part through the view loop | built-mesh contract §"object-list path" |
Facts already PROVED and binding (do not re-derive, do not weaken):
- the built cell shell is stamped and submitted whole once after Boolean admission;
- portal polygons, not built meshes, are polygon-clipped;
- `DrawCells` draws all shells then all object lists, both in reverse
draw-list order, views ascending;
- device, cell-shell and part stamps persist with the local-player bypass;
- the "first view clips the shell" hypothesis is RETIRED.
## 3. Current acdream owners (functions, not line numbers — re-locate at chunk time)
| Retail mechanism | Current owner | Assessment (from the built-mesh comparison at `eaea8776`, re-checked against `c94a1a40` file list) | S3 action |
|---|---|---|---|
| view polygon / planes | `WalkViews` | strong match | keep; pin |
| viewcone sense | `WalkVisibilityMath` | exact | keep |
| flood + todo order | `WalkFrameDriver` (flood turns, `VisitedCells`, `OnLandscape`) | order proven for shells/objects; `_skyDrawnThisFrame` is a PROXY for retail's `outside_view.view_count != 0` | chunk 2 replaces the proxy with the real outside-view count |
| whole-mesh admission at slot 0 | `WbDrawDispatcher.WalkClassify` (`ResolveWalkLightSet`, part stamps, `RetailWholeMeshSlot`) | correct | keep; chunk 4 deletes the still-translated clip slots per category |
| part stamp identity | `(RenderProjectionId, PartIndex)` | retail identity is the `CPhysicsPart*`; S2 made per-cell membership registry-borrowed, so one logical part now reaches the classifier from EVERY cell it is in with the SAME projection id — the identity audit the contract asked for is now structurally answered; pin it | chunk 2 pin |
| cell shell once per stamp + mid-frame re-arm | `WalkFrameDriver` shell loop, `RetailPViewPassExecutor.WalkLeaf` | correct | keep; re-arm gate moves to the real outside-view count |
| building sequence | `WalkFrameDriver` building turn, `RetailFrameWalk` | matches alpha barrier → portal pass → shell | keep; pin as ONE sequence |
| terrain emission | `RetailPViewPassExecutor` landscape stage (whole-stage terrain event before building/object turns) | DIVERGES: retail is `DrawLandCell` then `DrawSortCell` PER admitted land cell, far-to-near | chunk 3 |
| landscape leaf's use of the installed outside-view list | `TerrainModernRenderer` visible cells + `WalkFrameDriver.VisitedLandscapeCellIds` | top-level ownership proven; per-leaf pixel use is an S3 audit item | chunk 3 audit (bounded: one pose) |
| generic GPU clip rules for categories retail never clips | Vulkan clip slots on look-in / straddling / building categories (`RetailPViewPassExecutor`, `UseIndoorMembershipOnlyRouting`) | retail clips only portal polygons | chunk 4 delete, with a CPU/GPU equivalence pin for any category that must keep a translated clip |
| `obj_view_set` side effects | not represented (world-space sphere vs captured planes) | mathematically aligned for affine transforms | out of S3 unless the capture shows a consumer |
| missing `SelectionSphere` fallback | "any view → whole mesh" | not a retail branch | keep as a corruption fallback, outside parity claims (register row if it survives S5) |
## 4. Chunks (bounded; one Sonnet agent each; stop on a third round)
**Chunk 1 — transcript emitter + parser + fixture import (needs §7 captures).**
One print-only flag (documented in `docs/launch-options.md` in the same
commit) emits the OH line kinds the capture templates produce
(`tools/walk-oracle/oh/*.template`: walk / parts / alpha-depth) from the
production walk; the existing FW0-style test-side parser is extended for the
new kinds; the four captured pose logs are imported as fixtures. Gate: the
emitter's lines parse with the same parser as the retail logs; NO validator,
NO canonical JSONL (rule §5, [[feedback-evidence-infrastructure-sink]]).
BLOCKED until the owner runs the capture session.
**Chunk 2 — exact PView state.** `WalkPView` (new, App/Rendering/Walk) owns:
the live view list per cell (retail `portal_view_type` lists), the
outside-view count, the view/update counts, the todo order, the draw list and
the two stamps. `_skyDrawnThisFrame` and every other proxy for
`outside_view.view_count != 0` is replaced by the real count. Per-category
leaf contract pinned: whole-once (built shell), Boolean sphere (ordinary
part), actual polygon clip (portal polygons only), repeated submission (local
player). Part identity pin: the same logical part reached from two cells
classifies once per stamp. Can start before the capture (decomp oracle);
the capture confirms.
**Chunk 3 — interleave.** Terrain becomes ordered landcell events: for each
admitted land cell in retail far-to-near order, `DrawLandCell` (that cell's
terrain range) then `DrawSortCell` (building pass 1 / look-in work / building
shell / land-cell object turn). Per-landcell terrain ranges come from the
existing terrain mesh layout (index ranges per landcell — verify
`TerrainModernRenderer` exposes them; if not, the chunk adds the range table
at bake/upload time, not a per-frame rebuild). The whole-stage terrain event
is deleted in chunk 4, not here (two-step so the pixel gate can bisect).
Gate: terrain pixels/mesh counts unchanged when no interleave is present;
dense-outdoor p50/p99 recorded before/after.
**Chunk 4 — deletions.** The whole-stage terrain event; the generic clip
rules on categories retail never clips (Vulkan clip slots removed from those
categories); any residual "first view clips the shell" code path. Gate: no
duplicate draw of a stamped part across a pan/zoom replay; membership/draw
count changes only at a retail view boundary.
## 5. Review (one Opus retail lens + one shader/perf lens at the S3 boundary)
- retail lens on every stamp/view loop branch and on the call order against
the capture transcript and the decomp;
- shader review of clip-space sign, y inversion, W plane, plane count and
scissor for the categories that KEEP a translated clip;
- performance review: the command-count increase from interleaving is
measured (dense outdoor p50/p99), not hidden by reordering.
Lead verifies every finding against the source before an edit (S2 precedent:
19 findings, 4 blocking, all real; see `s2-membership-ownership-map.md` §9).
## 6. Automated gate (S3 has no standalone owner gate; folds into G3)
- transcript equality with the §7 captures at the captured depth for all four
poses plus the FW0 still fixtures;
- tests distinguish whole-shell-once, Boolean part admission and actual
polygon clipping;
- pan/zoom replay changes membership/draw count only at a retail view boundary;
- no duplicate draw of a stamped part;
- terrain pixels/mesh counts unchanged when no interleave is present;
- self-gate route (`tools/overhaul-selfgate/`) at the three owner poses +
the four capture poses, pixel-diffed against the G2 candidate run
`logs/selfgate-20260903-010022-s2-review-fixes-3` — the per-region diff,
not the eye, is the verdict ([[feedback-deleted-fallback-carried-population]]).
## 7. Open questions for the capture session (ask for exactly these)
1. `LScape::calc_draw_order` sequence at each of the four poses (far-to-near
land cell order) — chunk 3's oracle.
2. Per-frame `outside_view.view_count` and the device-stamp advance count at
each pose — chunk 2's oracle for the re-arm gate.
3. `CTransition` at `num_sphere == 0` (a shapeless object's cell array on a
move) — retires AD-117 item 1 (S2 residual), unrelated to S3 but cheapest
to capture in the same session.