From 13fc7d83498f479d3f662570f2350eeb08874e16 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 2 Sep 2026 17:50:25 +0200 Subject: [PATCH] docs(render): rescope Campaign OVERHAUL to five production slices v2 replaces the twelve-stage plan. OH1's evidence-grammar stage is parked on quarantine/oh1-evidence-grammar-2026-09-02; the committed research contracts stay binding. Stage mapping: OH2 -> S1, OH3 -> S2, OH4+OH5 -> S3, OH6+OH7 -> S4, OH8-OH11 -> S5. Adds the working model (lead in the loop, bounded chunks, time-box), the single retail capture session before S3, and per-slice minimal evidence products. Carries the InitCell inflag prose correction in the flood appendix and marks the T3 handoff superseded. Co-Authored-By: Claude Fable 5.1 --- ...-09-01-campaign-overhaul-world-solidity.md | 1984 +++++------------ ...2026-08-30-fw-flood-pseudocode-appendix.md | 73 +- .../2026-09-02-campaign-overhaul-handoff.md | 464 ++++ 3 files changed, 1077 insertions(+), 1444 deletions(-) create mode 100644 docs/research/2026-09-01-overhaul/2026-09-02-campaign-overhaul-handoff.md diff --git a/docs/plans/2026-09-01-campaign-overhaul-world-solidity.md b/docs/plans/2026-09-01-campaign-overhaul-world-solidity.md index bcf3fd74..066ca939 100644 --- a/docs/plans/2026-09-01-campaign-overhaul-world-solidity.md +++ b/docs/plans/2026-09-01-campaign-overhaul-world-solidity.md @@ -1,31 +1,30 @@ # Campaign OVERHAUL — retail world construction and render solidity -**Status:** READY TO EXECUTE (plan requested by owner 2026-09-01; -implementation has not started). +**Status:** ACTIVE — **v2 rescope 2026-09-02.** Five production slices replace +the twelve-stage v1 plan. S1 is the current slice. See §13 for the ledger and +§15 for what v2 changed and why. **Campaign code:** `OH`. **Worktree (binding):** `C:\Users\erikn\source\repos\acdream\.claude\worktrees\peaceful-blackburn-5333f0` -**Branch (binding):** `claude/campaign-w-retail-frame-walk`. +**Branch (binding):** `claude/campaign-w-retail-frame-walk`. This is the +long-lived renderer integration branch. It carries all of Campaign FW (101 +commits over `origin/main` at `e102fb36`). **Nothing merges to `main` until +the final gate passes**; `origin/main` is merged INTO this branch at every +slice boundary so it never drifts. -**Plan-start HEAD:** `e8808602` (`fix(render): restore landscape objects and -walk alpha order`), 27 commits ahead of the remote when this plan was written. +**v2 base:** `5d907ae9` (`docs(render): define OH1 retail world contract`), +tree clean. The uncommitted OH1/T3 evidence grammar (~32K lines) is parked +verbatim on `quarantine/oh1-evidence-grammar-2026-09-02` (see its +`QUARANTINE-README.md`). Do not merge that branch. -**Known accepted historical anchor:** `b8befded` (`checkpoint: preserve -user-gated FW closeout fixes`). This is a rollback reference, not permission to -discard the work after it. - -**Dirty-tree rule:** the worktree already contains a large, valuable set of -uncommitted rendering, geometry, physics-shadow, lighting, diagnostics, test, -and prepared-package changes. Nothing may reset, overwrite, clean, stash-pop, -or wholesale replace that state. OH0 must classify and preserve it before the -first behavioral edit. - -**Predecessor evidence:** Campaign FW and the cathedral review corpus remain -authoritative evidence, but Campaign OVERHAUL supersedes FW as the execution -ledger for world-construction and world-render solidity work. +**Recovery anchors:** `b3b7d922` is the checkpoint that committed the +pre-overhaul investigation candidates, including the Facility Hub stair fix +(recipe 7 authored drawing sphere, static render-shadow membership, per-part +stamps). `b8befded` is the user-gated FW closeout. Both are history, not +permission to discard later work. No history rewrite, ever. **One-sentence goal:** recreate retail's single coherent world-cell graph and its exact per-frame world walk up to a narrow Vulkan translation boundary, so @@ -37,69 +36,64 @@ suppression, guessed tolerances, or corrective overdraw. ## 1. Why this campaign exists -Campaign FW successfully replaced the legacy production visibility product -with a retail-derived frame walk, fixed the original cathedral through-wall -actor defect, restored outdoor particles, and corrected several object and -terrain lifetime regressions. It did **not** make the complete world pipeline -retail-identical. - -The current client still reconstructs relationships that retail owns directly: +Campaign FW replaced the legacy visibility product with a retail-derived frame +walk and fixed several defects. It did not make the world pipeline +retail-identical. The client still reconstructs relationships retail owns +directly: - prepared cell meshes are separate from portal topology; - building shells are separate from building portal ownership; - render projections are separate from physics `CELLARRAY` membership; -- static visual membership is rebuilt from visual bounds; +- static visual membership is rebuilt from visual bounds in an App-owned model + that competes with the physics registry; - terrain is submitted as a complete slice before per-cell object turns; - alpha uses a modern scope-global queue rather than retail's exact cell/list ownership; -- the interior depth clear is emitted unconditionally even though the retail - decomp establishes an outside-view block and a previous-frame - `portalsDrawnCount` latch; -- CellStruct face selection still uses the registered AP-234 `NoPos` proxy - rather than the surface-type decision retail actually makes; -- some accepted object parts are duplicated through Vulkan clip slots, a - translation whose exact correspondence to the built-mesh retail leaf has not - been proved for every content category. +- the interior depth clear is unconditional although retail latches it on the + previous frame's `portalsDrawnCount`; +- CellStruct face selection uses the AP-234 `NoPos` proxy rather than the + surface-type decision retail makes; +- some accepted object parts are duplicated through Vulkan clip slots without + proof that retail clips them. -These differences explain why local fixes oscillate between opposite failure -modes: prevent one leak and walls disappear; restore a wall and a portal-view -artifact returns; cull one cell and a valid stair or ramp vanishes. The campaign -therefore changes the unit of work from "fix this visible triangle" to "port -and prove this retail-owned world invariant." +These explain why local fixes oscillate between opposite failure modes. The +precedent is physics: incremental collision patching never converged; the +faithful retail port did. The renderer gets the same treatment. + +Owner-observed symptom family: cathedral walls/wall-textured triangles over +floating stairs; stair slabs appearing/disappearing by camera angle; the +cathedral exterior ramp absent; textures bleeding through opaque surfaces; the +local character chopped at cathedral and Facility Hub seams; remote actors and +particles through walls; waterfalls vanishing by angle; outdoor groups +disappearing after small turns; landscape draw-range regressions; spell +effects lingering. --- ## 2. Definition of success -Campaign OVERHAUL is complete only when all of the following are true. - 1. One authoritative, generation-scoped cell graph supplies portal topology, building ownership, drawable CellStruct identity, and render/physics cross-cell part membership. No production consumer rebuilds a competing answer. 2. CellStruct mesh extraction selects sides and subsets from the same authored data retail uses, including exact surface-type handling. AP-234 is retired. -3. The per-frame transcript matches retail for the same root and camera pose: - landscape visits, portal views, building calls, cell order, object-list - turns, frame-stamp boundaries, depth events, and alpha flushes. +3. The per-frame transcript matches retail's captured transcript for the same + root and camera pose at the depth the capture records: landscape/building + order, portal views, cell order, object-list turns, shell/part draws, + depth events, alpha inserts and flushes. 4. Every leaf category has a proven retail contract: EnvCell shell, building shell, landblock static, indoor static, dynamic object, particle, terrain, - punch, seal, and transparent subset. + punch, seal, transparent subset. 5. Vulkan receives an ordered list of already-decided retail draw operations. - Vulkan may encode and batch adjacent compatible work, but it does not decide - visibility, ownership, ordering, clipping, or depth-phase membership. -6. Scene-specific suppression, shell lifts, bias values, fallback floods, - corrective redraws, and behavior-changing diagnostic flags do not remain in - production. -7. The owner acceptance matrix passes in the cathedral, Facility Hub, Nanto, - Tusker Island, Holtburg, ordinary dungeons, and ordinary outdoor terrain. -8. The complete Release suite, installed-DAT conformance lane, connected - lifecycle route, R6 route, and performance checkpoint pass on the exact - owner-gated binary. -9. Architecture, inventory, divergence register, launch options, campaign - memory, and milestone ledgers describe the code that actually ships. No - document may claim a conditional clear while production emits an - unconditional one, or claim exact cell extraction while AP-234 remains. + It may batch adjacent compatible work; it decides nothing. +6. No scene-specific suppression, shell lift, bias, fallback flood, corrective + redraw, or behavior-changing diagnostic flag remains in production. +7. The owner acceptance matrix (§10) passes. +8. The complete Release suite, installed-DAT lane, connected lifecycle route, + R6 route, and performance checkpoint pass on the exact gated binary. +9. Architecture, inventory, divergence register, launch options, memory, and + milestone ledgers describe the code that ships. "Looks fixed at one camera angle" is never a completion condition. @@ -107,1263 +101,488 @@ Campaign OVERHAUL is complete only when all of the following are true. ## 3. Scope and non-goals -### In scope +**In scope:** CellStruct/EnvCell geometry construction; the canonical +cell/building/portal/part-membership graph; static and dynamic cross-cell +render membership; retail `PView` view ownership and leaf contracts; landscape, +building, cell-shell, object, particle, depth, and alpha ordering; portal punch +and exit-seal lifecycle; retail landscape `in_view` and its particle/light/ +shadow consumers; material behavior needed for solid composition (AP-232 +residual); minimal per-slice instrumentation; deletion of superseded +reconstruction and diagnostic apparatus; docs and regression coverage. -- CellStruct/EnvCell render-geometry construction. -- The canonical cell/building/portal/part-membership graph. -- Static and dynamic cross-cell render membership. -- Retail `PView` portal-view ownership and draw-leaf contracts. -- Landscape, building, cell-shell, object, particle, depth, and alpha ordering. -- Portal punch and exit-seal lifecycle/state. -- Retail landscape `in_view` production and its particle/light/shadow - consumers. -- Material behavior necessary for solid world composition, including the - transparent-detail AP-232 residual. -- Exact instrumentation and retail/acdream transcript comparison. -- Deletion of the superseded reconstruction and diagnostic apparatus. -- Documentation and regression coverage for the finished pipeline. - -### Explicitly out of scope - -- Replacing Vulkan with retail's graphics API. -- Recreating C++ pointer layouts, allocator behavior, or COM objects. -- Changing the asynchronous streaming strategy, publication budgets, reveal - radii, prepared-package mmap model, or GPU resource lifetime—except for a - schema/version migration strictly required by exact prepared geometry. -- Increasing draw distance or hiding defects with additional residency. -- A general lighting redesign. Lighting must remain stable through the - overhaul; independent lighting findings enter only if they prove a - world-ownership or draw-order dependency. -- Physics behavior not required to produce exact cell/part membership. -- New graphics features, visual enhancements, or non-retail occlusion systems. -- Removing the user-requested Extended particle-range option. The Retail - option must be exact; a deliberate user-selected range multiplier remains a - documented preference rather than being confused with visibility parity. +**Out of scope:** replacing Vulkan; recreating C++ pointer layouts; changing +streaming strategy, budgets, reveal radii, the mmap package model, or GPU +resource lifetime except the S1 recipe bump; increasing draw distance; a +lighting redesign; physics not required for exact membership; new graphics +features; removing the user-requested Extended particle-range option. --- ## 4. Binding engineering rules 1. **Retail makes every world decision.** Modern code may represent a result - differently, but may not invent an additional visibility, membership, + differently but may not invent an additional visibility, membership, ordering, clipping, or depth decision. -2. **Evidence before code.** Every behavioral slice begins with a written - retail contract containing named functions, addresses, inputs, state writes, - branch senses, call order, and observable output. No implementation starts - from a screenshot theory. -3. **Named retail first.** Search - `docs/research/named-retail/acclient_2013_pseudo_c.txt` and `acclient.h` - before fresh decompilation. -4. **Ghidra arbitrates branch sense.** Binary Ninja pseudo-C is a navigation - aid. Any condition whose polarity affects admission, clipping, depth, - ordering, or lifetime must be cross-checked in Ghidra before implementation. -5. **DAT identity is exact.** Aggregate owner IDs do not identify rendered - content. A trace must reach landblock/static/server owner → Setup → part → - GfxObj → polygon/surface before assigning a visual carrier. -6. **No symptom-site fixes.** A cell ID, building ID, GfxObj ID, camera pose, - cathedral-only branch, extra shell draw, or suppression flag may be used for - diagnosis only. It cannot ship as behavior. -7. **No silent drop.** During a slice, every rejected cell/view/part/mesh must - have a diagnostic reason available. Production diagnostics are removed or - made strictly print-only at slice close. +2. **A slice ships a production behavior change or it is not a slice.** + Evidence tooling is built inside the slice that consumes it, to the depth + that slice needs, never as its own stage. +3. **Evidence before code, contract already written.** The OH1 research + contracts (§6) and the retail capture (§7) are the evidence. No slice + starts from a screenshot theory; no slice builds a new evidence language. +4. **Named retail first; Ghidra arbitrates branch sense.** Any condition whose + polarity affects admission, clipping, depth, ordering, or lifetime is + cross-checked in Ghidra (`patchmem`, port 8081) before implementation. +5. **DAT identity is exact.** A trace reaches owner → Setup → part → GfxObj → + polygon/surface before assigning a visual carrier. Aggregate owner IDs do + not identify content. +6. **No symptom-site fixes.** Cell/building/GfxObj IDs and camera poses are + for diagnosis only. +7. **No silent drop.** Every rejected cell/view/part/mesh has a diagnostic + reason available during a slice; production diagnostics are removed or made + print-only at slice close. 8. **No competing production owner.** A cutover slice deletes the route it - replaces. A temporary comparator may live within one slice but cannot cross - the slice boundary as a second authority. -9. **Whole-mechanism fixes.** Do not change a downstream draw call when retail - owns the decision upstream in graph construction, portal traversal, shadow - registration, or stage ordering. -10. **Build before launch.** Every launched candidate is a green Release build - produced from a recorded commit/worktree state. `dotnet run` without a - successful build is forbidden. -11. **Exact binary for gates.** The commit/hash, package schema, environment - flags, and log path are recorded before every owner gate. -12. **Client process safety.** Never kill the client. Use graceful in-client - closure only when the owner has authorized control; otherwise wait for the - owner to close it. -13. **Preserve unrelated work.** No destructive git command, broad checkout, - reset, or clean. Every rollback is a normal revert of a named campaign - commit or a return to a recorded checkpoint. -14. **Register discipline.** A newly discovered deliberate deviation is filed - in the same commit. A retired deviation is removed in the same commit as - the exact port and its tests. -15. **Docs are tested truth.** If the architecture text and production code - disagree, the slice is not closed until one is corrected with evidence. + replaces within the slice. +9. **Whole-mechanism fixes.** Never patch a downstream draw when retail owns the + decision upstream. +10. **Build before launch; exact binary for gates.** Commit hash, package + recipe, flags, and log path are recorded before every owner gate. +11. **Client process safety.** Never kill the client. +12. **Preserve unrelated work.** No `reset --hard`, `checkout --`, `clean`, or + bare `stash`. Rollback is a normal revert of a named commit. +13. **Register discipline.** Deviations filed/retired in the same commit. +14. **Docs are tested truth.** Architecture text and code agree at slice close. +15. **Time-box.** A chunk that needs a third fix round stops and goes to the + user with its evidence. No agent decides it needs more infrastructure. --- -## 5. The required Plan → Implement → Review loop +## 5. Working model -Every numbered slice follows the same state machine: +The v1 failure was one agent given the whole campaign for eighteen hours. v2 +keeps the lead in the loop at every chunk. -```text -PLANNED - → EVIDENCE COMPLETE - → IMPLEMENTED - → REVIEWED (architecture + retail fidelity) - → FINDINGS FIXED - → NARROW RE-REVIEW - → AUTOMATED GATE GREEN - → OWNER GATE, only when assigned - → CLOSED + rollback recorded -``` +| Role | Who | Does | Never | +|---|---|---|---| +| Lead / architect | the main session (Fable) | writes each chunk contract (files, retail functions + addresses, acceptance tests); dispatches one bounded chunk; verifies every claim against source; runs gates; commits; merges main in at slice boundaries | hands off "complete the slice" | +| Implementer | Sonnet, one dispatch per chunk | one file cluster + its tests; build and test green is the return condition; returns a diff summary and open questions | commits; adds evidence infrastructure; starts a third fix round; touches files outside its contract | +| Retail reviewer | Opus, one pass per slice on the production port | checks each ported branch against the named decomp with addresses; findings as file:line + decomp citation | reviews tooling | +| Architecture reviewer | Opus, only at the two cutover slices (S2, S5) | one owner per fact; layering; lifetime; performance shape | | +| Adversarial verify | Workflow fan-out, review stage only | three skeptics per finding try to refute it; a finding survives with two of three | | -### 5.1 Plan packet required before implementation - -Each slice receives a short research packet under -`docs/research/2026-09-01-overhaul/` containing: - -- the exact question being answered; -- named retail functions and addresses; -- struct fields and offsets used; -- caller/callee order; -- all branch senses that change behavior; -- retail state before and after the call; -- current acdream source locations; -- a retail-vs-acdream difference table; -- the smallest production ownership change that closes the difference; -- tests that fail before and pass after; -- performance/allocation risk; -- rollback boundary; -- whether an owner gate is required and why automation cannot settle it. - -No packet may say "probably," "roughly," or "retail-shaped" at the behavior -being implemented. Unresolved facts block only that sub-slice; they do not -license an approximation. - -### 5.2 Implementation discipline - -- Implement one retail invariant at a time. -- Keep the diff local to the named ownership boundary. -- Add the deterministic failing test or comparator before changing production - behavior whenever practicable. -- Preserve retail ordering even if it temporarily produces more draw calls. - Adjacent-run batching is a later, separately reviewed optimization. -- Do not mix diagnostic experiments with the final implementation commit. -- Remove the replaced production route and its tests in the cutover commit. -- Build focused projects after every meaningful edit; build the full solution - before review. - -### 5.3 Two mandatory review lenses - -**Architecture review** asks: - -- Is there exactly one owner for this fact? -- Did a render cache or projection become a second world model? -- Do graphical and physics consumers borrow the same generation/identity? -- Are publication and teardown atomic at the existing boundary? -- Is fallback behavior explicit, bounded, and retail-supported? -- Did the change leak App/Vulkan types into Core/Content/Runtime? -- Can a retry, cancellation, recenter, or late upload create mixed generations? - -**Retail-fidelity review** asks: - -- Is every behavioral branch tied to a named retail function? -- Were ambiguous conditions Ghidra-arbitrated? -- Are list order, iteration direction, stamps, latches, and flush sites exact? -- Are built-mesh and non-built-mesh retail branches distinguished? -- Are polygon sides and Surface types interpreted from the correct owner? -- Does the implementation preserve retail quirks rather than normalize them? -- Does the test assert the retail mechanism, not merely the desired screenshot? - -Review findings are recorded as Blocker/Major/Minor. Blocker and Major findings -must be fixed before the slice gate. The changed surface receives a narrow -re-review; a review is not closed by author explanation alone. - -### 5.4 Commit shape - -Prefer this sequence for each slice: - -1. `docs(render): define OHx retail contract` — evidence packet and fixtures. -2. `fix(render): port OHx ` or - `refactor(render): cut over OHx ` — behavior and focused tests. -3. `docs(render): close OHx review` — review disposition, measured gates, - register/doc reconciliation. - -A very small slice may combine 1 and 2, but the evidence must still predate the -behavioral decision in the diff history. Every closed slice records its commit -and `git revert ` anchor in this file. +Chunk contracts state explicit stop conditions: build red after two attempts → +return; contract ambiguity → return with the question; any need for a third +round → return. Coupled files go to one agent serially against a pinned +contract; only genuinely independent chunks run in parallel worktrees. +Agents write incremental output to disk; a silent agent is stopped and +inspected, not waited on. --- -## 6. Evidence hierarchy and oracle products +## 6. Evidence hierarchy and products -When sources disagree, use this order: +When sources disagree, in this order: -1. Installed retail binary behavior captured at named functions. +1. Live retail binary behavior captured at named functions (§7). 2. Named retail PDB/header identity and Ghidra-arbitrated decompilation. 3. Byte-exact installed DAT structure and geometry. -4. Existing retail cdb/oracle traces in - `docs/research/2026-08-30-fw-walk-oracle/posed/`. +4. Existing FW0 cdb traces in `docs/research/2026-08-30-fw-walk-oracle/`. 5. Deterministic acdream replay of the same input. -6. Render/API captures for confirming submitted geometry and state. +6. Render/API captures. 7. acdream diagnostic logs. -8. Visual observation, used to discover symptoms and accept final pixels—not - to infer object identity or branch logic. +8. Visual observation — to discover symptoms and accept final pixels, never to + infer identity or branch logic. -### 6.1 Canonical frame transcript +**Research contracts already written (committed at `5d907ae9`, binding):** +`oh1-retail-world-contract.md`, `oh1-construction-landscape-contract.md`, +`oh1-built-mesh-view-contract.md`, `oh1-alpha-list-contract.md`, +`oh1-depth-lifecycle.md`, `oh2-cellstruct-surface-contract.md`, and the +corrected `2026-08-30-fw-flood-pseudocode-appendix.md`. The retail facts the +v1 T3 reviews established are carried in +`2026-09-02-campaign-overhaul-handoff.md` §5.3 and are binding inputs to S3/S4. -OH1 defines a versioned, line-oriented transcript. At minimum it records: +**Evidence products, minimal by design:** -- frame number, frame stamp, previous/current `portalsDrawnCount`; -- camera pose, resolved camera root, player cell, outdoor/interior root kind; -- PView identity (`root` versus building look-in), `draw_landscape`, and - outside-view count; -- each portal-view polygon after every clip, including exact ordered vertices; -- todo insertion/pop order and cell draw-list append order; -- landscape landcell order and `in_view` result; -- building entry, degrade gate, look-in portal pass, alpha barrier, punch, and - shell draw; -- EnvCell shell draw stamp and mesh identity; -- object-list cell turn and every admitted part, with membership source; -- particle owner turn and degradation decision; -- alpha enqueue list, insertion key, queue identity, and flush site; -- full-depth clear, far-Z punch, and true-depth seal state; -- exact final draw-leaf sequence. - -Retail and acdream use the same semantic schema. Pointer values, Vulkan handles, -and allocation addresses are excluded from equality. - -### 6.2 Canonical geometry manifest - -For every audited CellStruct polygon: - -```text -cellStructId -polygonIndex -sides_type / CullMode -NoPos / NoNeg -positiveSurfaceId / negativeSurfaceId -positiveSurface.Type / negativeSurface.Type -selected side(s) -subset classification -emitted/skipped reason -vertex IDs and final winding -``` - -The manifest is required for cathedral cells `0xF4180100`, `0101`, `0104`, -`0106`, `0107`, `0112`, `0113`, and `0114`, plus the Facility Hub stair cells -around `0x8A02015E/015F`. Installed-DAT catalog tests sample additional ordinary -dungeons so the solution cannot overfit those two buildings. - -### 6.3 Canonical part-membership manifest - -For each static/dynamic object part: - -```text -owner identity and owner kind -Setup ID / part index / GfxObj ID -root transform and part transform -retail drawing sphere and/or part bounds -resident cell -every crossed shadow cell, in retail insertion order -parent/child inheritance source -render membership -physics membership -fallback reason, if any -``` - -The production invariant is that one canonical registration transaction -produces retail's typed outputs: per-part render-shadow cells and object-level -physics `CELLARRAY`/broadphase cells. Those outputs may differ where retail's -algorithms differ, but no consumer may recalculate either one independently. - ---- - -## 7. Target architecture - -The final design keeps modern immutable storage but restores retail ownership. -Names below are descriptive; OH1 may refine names without weakening the -contract. - -```text -Prepared DAT assets - ├─ exact CellStruct mesh/subset records - ├─ exact portal/topology records - ├─ exact building shell/portal ownership - └─ exact Setup/GfxObj part records - │ - ▼ -WorldCellGraphSnapshot (one generation, one authority) - ├─ CellNode[] - │ ├─ drawable shell identity - │ ├─ ordered portals/neighbours - │ ├─ owning building - │ ├─ ordered static part shadows - │ └─ ordered dynamic part shadows - ├─ BuildingNode[] - ├─ PartRenderShadowMembership[] - ├─ ObjectPhysicsCellMembership[] - └─ exact stable indices/identities - │ - ├─────────────► physics adapter (borrowed) - ├─────────────► render preparation adapter (borrowed) - └─────────────► RetailFrameWalk (borrowed topology) - │ - ▼ - Retail semantic draw transcript - │ - ▼ - Vulkan encoder / adjacent batching -``` - -### Required properties - -- Core/shared records are BCL-only and contain no Vulkan handles. -- Mesh payloads remain Content/App resources referenced by stable IDs/ranges. -- The existing generation/publication transaction remains the publication - boundary; this campaign does not invent a second streamer. -- A complete graph snapshot becomes visible atomically. -- Render and physics adapters never mutate canonical topology/membership. -- Dynamic membership updates replace one object's membership transactionally - and preserve exact object incarnation/generation identity. -- Child objects inherit the retail root object's `CELLARRAY` through one - canonical rule. -- The walk owns temporary per-frame portal views, todo lists, draw lists, - stamps, and latches. These are not persisted in render projections. -- The Vulkan encoder receives clip/depth/order data but cannot enlarge the - visible set or reorder across a semantic boundary. - ---- - -## 8. Stage overview and owner-gate budget - -| Stage | Purpose | Owner gate | +| Product | Form | Used by | |---|---|---| -| OH0 | Preserve/classify the current state and establish baseline evidence | No | -| OH1 | Define the exact retail world contract and upgrade the oracle | Only if a missing retail capture requires owner action | -| OH2 | Exact CellStruct geometry and prepared-package representation | **Gate G1** after automated world-geometry checks | -| OH3 | One canonical cell graph and exact part-shadow membership | Fold into G1 if no second launch is needed; otherwise a short G1b | -| OH4 | Exact PView views and leaf admission/clipping contracts | No standalone owner gate | -| OH5 | Exact landscape/building/cell/object interleave | No standalone owner gate | -| OH6 | Exact depth epoch, clear latch, punches, seals, and frame stamps | **Gate G2** for opaque-world solidity | -| OH7 | Exact alpha ownership, ordering, and flushes | No standalone owner gate | -| OH8 | Exact landscape `in_view` and particle/light/shadow consumers | **Gate G3** together with OH7/OH9 | -| OH9 | Building/material/degrade leaf fidelity required for composition | Fold into G3 | -| OH10 | Delete duplicate owners, fallbacks, experiments, and stale claims | No | -| OH11 | Full regression, performance, connected routes, docs, final acceptance | **Gate G4** final matrix | +| Geometry conformance | installed-DAT scans + synthetic fixtures + a two-run SHA-256 over the emitted CellStruct subset records | S1 | +| Membership conformance | typed expected cell lists per fixture object + installed-DAT comparator between the canonical graph and the old builders (comparator lives and dies inside S2) | S2 | +| Frame transcript | the FW0 line format (`F/P/LS/BLD/DI/DC`) extended with the OH line kinds the capture scripts emit; parsed by the existing test-side `WalkOracleTrace` parser, extended in place; acdream emits the same lines behind ONE print-only flag inside the slice that needs it | S3, S4 | +| Framebuffer equivalence | offscreen fixture renders compared to the retail formula | S5 | -The owner should normally see four builds during the campaign, not one build per -code slice. A new owner gate is added only when the automated oracle cannot -settle a real visual/feel question or a prior gate exposes a regression. +Pointer values, Vulkan handles, and allocation addresses are excluded from +equality. No canonical JSONL, no semantic validator: structure is checked in +the parser, semantics in the port and in the compare against retail. --- -## 9. Detailed stages +## 7. Retail capture session (owner action, before S3) -### OH0 — safety baseline and dirty-tree classification +The one owner action in the campaign apart from gates. Scripts live in +`tools/walk-oracle/oh/` (recon, three capture templates, runner, README). -**Goal:** make the current state recoverable and comprehensible before any -overhaul behavior changes. +| Pose | Root | Why | +|---|---|---| +| holtburg-doorway-still | interior `a9b4013f` | the flap scene; three consecutive look-in punches of one cell | +| terrace-edge | outdoor | the #456 pose; far building drawn and depth-covered | +| cathedral-arrival | interior `f4180106` | interior root, landscape through the exit view, culled roster | +| foundry-deep | interior `a9b40176` | deep chain with `ov=1`; landscape and 12 buildings drawn from the basement | -#### Plan +Per pose, three short attaches in order, each auto-detaching after its frame +budget: **walk** (cell granularity: FW0 lines plus `DrawEnvCell` and object-cell +turns, 5 frames), **parts** (`CPhysicsPart::Draw` candidates and +`DrawMeshInternal` actual draws with GfxObj ids, 3 frames), **alpha/depth** +(`AddMeshToAlphaList`, `FlushAlphaList` with site, depth-clear latch and +`portalsDrawnCount`, 5 frames). Still poses repeat bit-for-bit per frame +(FW0 finding 6), so few frames suffice and the ACE-timeout risk from +per-hit `.printf` stays bounded. Budget: one hour. -1. Record HEAD, upstream, status, staged/unstaged/untracked files, submodules, - package schema, shader manifest hash, and installed-DAT identity. -2. Classify every current dirty file into: - - accepted prior fix; - - current cathedral/facility investigation; - - exact retail depth-state port; - - diagnostic-only apparatus; - - tests for one of those changes; - - unrelated/user-owned change. -3. Record the runtime flags that change behavior, especially every - `ACDREAM_PROBE_CATHEDRAL_*` switch, and prove they are unset in normal - launch state. -4. Build the current state in Release and run the focused walk/geometry/depth - tests. Record failures honestly; do not edit production to make OH0 green. -5. Write `docs/research/2026-09-01-overhaul/oh0-baseline.md` with the complete - inventory and the exact recovery procedure. -6. Create a normal checkpoint commit containing only classified campaign work - after confirming no unrelated user change is swept into it. If unrelated - changes cannot be separated safely, leave them dirty and record hashes; - never force a checkpoint by overwriting them. +Procedure: recon attach first (no breakpoints; `dt`/`x` dumps verify every +offset the templates assume); PDB pairing check before every attach; `qd` only +at top level after the terminal-hit fall-through. Logs land in +`docs/research/-oh-walk-oracle/` and become S3/S4 fixtures. -#### Implement - -OH0 changes documentation, evidence tooling, and checkpoint history only. It -does not change draw behavior. - -#### Review - -- Confirm every pre-existing dirty file is accounted for. -- Confirm the accepted `b8befded` anchor and current HEAD are both recorded. -- Confirm no behavioral probe is silently enabled by a default. -- Confirm the checkpoint can be reverted without reverting user-owned work. - -#### Automated gate - -- Release solution build result recorded. -- Focused walk/depth/geometry test results recorded. -- `git diff --check` clean for new OH files. -- Recovery recipe reviewed from a fresh `git status` snapshot. - -#### Owner gate - -None. OH0 should not consume owner time. - -#### Exit artifacts - -- `oh0-baseline.md` -- first entry in the execution ledger -- checkpoint/recovery anchor +If a static fact is later found unrecoverable from these captures, request one +more exact capture with pose, action, duration, and expected trace. Never an +open-ended "run around and report". --- -### OH1 — retail world contract and oracle completion +## 8. Target architecture (unchanged from v1) -**Goal:** replace prose such as "retail-shaped" with an executable contract for -world construction and every frame leaf. +```text +DAT + prepared package + └─ S1 CellStruct subset construction (surface-index owned, recipe 8) +World-cell graph (generation-scoped, S2) + ├─ portal topology, building ownership, drawable cell identity + ├─ static part-shadow membership (init_static_objects/AddPartsShadow) + └─ dynamic/child membership (add_shadows_to_cells, one transaction) +Frame walk (per frame, S3) + ├─ LScape::draw order → DrawBuilding sequence → look-ins + ├─ PView views/todo/draw-list/stamps → DrawCells two-pass + └─ leaf admission per category (whole-once / Boolean sphere / real clip) +Depth + alpha (S4) + ├─ portalsDrawnCount latch, conditional clear, punches, seals, mid-frame stamp + └─ retail alpha lists, per-cell insertion, FIFO flush sites, 0.75 valve +Consumers (S5) + └─ landcell in_view → particles/lights/shadows; material/degrade policy +Vulkan encoder: ordered immutable stream; merges adjacent compatible runs only +``` -#### Plan - -Produce focused, Ghidra-arbitrated notes for these symbol families: - -1. **Construction/ownership** - - `CEnvCell::init_static_objects` - - `CPhysicsObj::calc_cross_cells_static` - - `CPartArray::AddPartsShadow` - - `CPhysicsObj::add_shadows_to_cells` - - child-list propagation and cell removal counterparts -2. **Portal traversal** - - `PView::InitCell` - - `PView::InsCellTodoList` - - `PView::ClipPortals` - - `PView::AddViewToPortals` - - `PView::ConstructView` - - `Render::copy_view`, `Render::set_view`, `Render::obj_view_set` - - `Render::viewconeCheck` -3. **Landscape/building order** - - `LScape::draw_check_blocks` - - `LScape::landcell_check` - - `LScape::grab_visible_cells` - - `LScape::draw` - - `RenderDeviceD3D::DrawBuilding` -4. **Cell/object leaves** - - `PView::DrawCells` - - `RenderDeviceD3D::DrawEnvCell` - - `RenderDeviceD3D::DrawObjCellForDummies` - - `CPhysicsPart::Draw` and its built/non-built branches -5. **Geometry/material/alpha** - - `D3DPolyRender::ConstructMesh` - - `D3DPolyRender::DrawMesh` - - `D3DPolyRender::AddMeshToAlphaList` - - `D3DPolyRender::FlushAlphaList` - - `CShadowPart::insertion_sort` -6. **Depth lifecycle** - - the complete `PView::DrawCells` outside-view block; - - the source, reset, and previous-frame consumption of - `portalsDrawnCount`; - - the mid-frame frame-stamp increment; - - far-Z portal punches and true-depth exit seals. - -The result must explicitly answer: - -- Which built meshes are submitted whole after a Boolean sphere test? -- Which geometry is actually polygon-clipped by the installed portal view? -- Does a surviving object view cause multiple built-mesh draws or only repeated - admission tests before a draw stamp suppresses duplicates? -- Which frame stamp applies to landscape look-ins versus the interior root? -- Which list owns transparent EnvCell subsets? -- What exactly increments `portalsDrawnCount`, and when is it cleared? -- What is the exact relationship between cell traversal order and part-shadow - insertion order? - -#### Implement - -1. Define the canonical transcript schema and serializers in test/tooling code. -2. Extend retail capture templates only for missing fields. -3. Add acdream transcript emission behind one print/file diagnostic that does - not alter behavior. -4. Convert the existing posed FW oracle into semantic fixtures consumable by - equality tests. -5. Add geometry and membership manifest generation to `A8CellAudit` or a - narrowly named successor tool; do not add DAT parsing to App. - -#### Review - -- Retail review verifies every transcript field is observable at the cited - retail site. -- Architecture review verifies tooling does not become a second production - visibility owner. -- A fixture review verifies pointers/addresses are normalized while ordering, - float bits, IDs, and branch outcomes remain exact. - -#### Automated gate - -- Existing posed traces parse without loss. -- Round-trip transcript serialization is byte-stable. -- Synthetic ordering/latch fixtures detect deliberate one-event mutations. -- Installed-DAT manifests are deterministic across two runs. -- No production draw result changes. - -#### Owner gate - -Only if a retail capture lacks a fact that cannot be recovered statically. The -request must name the exact location, pose, action, capture duration, and -expected output; no open-ended "run around and report" gate. - -#### Exit artifacts - -- `oh1-retail-world-contract.md` -- versioned transcript schema -- versioned geometry/membership manifest schema -- retail/acdream replay fixtures +Required properties: render and physics adapters never mutate canonical +topology/membership; dynamic updates replace one object's membership +transactionally with exact incarnation identity; children inherit the root's +`CELLARRAY` by one rule; the walk owns per-frame views/todo/draw lists/stamps/ +latches and never persists them in projections; the encoder cannot enlarge the +visible set or reorder across a semantic boundary. --- -### OH2 — exact CellStruct geometry and subset construction - -**Goal:** retire AP-234 and make cell-wall geometry a byte/data-derived fact. - -#### Plan - -1. Trace `DrawEnvCell → DrawMesh(arg4=1)` and - `ConstructMesh` through Surface lookup and subset creation. -2. Pin the meaning of `sides_type`, `NoPos`, `NoNeg`, positive/negative - surface IDs, untextured surfaces, clip maps, and reversed winding. -3. Produce before-state manifests for all canonical cathedral and Facility Hub - cells and a statistically useful installed-DAT sample. -4. Identify every prepared-package record affected by adding exact surface - identity/type to the extraction decision. -5. Define package version/migration behavior before changing the codec. - -#### Implement - -1. Thread the real positive/negative `Surface.Type` into - `PrepareCellStructMeshData` before emit/skip selection. -2. Apply retail's exact side/subset rule; remove the `NoPos` approximation and - its explanatory exception. -3. Preserve original polygon/vertex order and float bits. -4. Update the prepared payload schema and strict codec if necessary. -5. Update bake equivalence, migration catalog, launcher package validation, and - corruption tests together. -6. Rebuild only the required prepared package through the supported bake flow; - never patch the package by hand. -7. Delete AP-234 in the same behavior commit. - -#### Tests - -- Unit matrices for all `sides_type × NoPos × NoNeg × Surface.Type` - combinations. -- Positive/negative side winding and material identity tests. -- CellStruct manifest goldens for canonical scenes. -- Installed-DAT comparison over all available CellStruct records, reporting - every changed polygon and why. -- Prepared-package encode/decode/corruption/version tests. -- Render-batch tests proving an untextured subset is skipped and a textured - `NoPos` edge case follows retail rather than the old proxy. - -#### Review - -- Retail reviewer checks the exact subset decision against the decomp. -- Data reviewer checks no ordinary GfxObj rule was accidentally applied to - CellStructs or vice versa. -- Architecture reviewer checks the Surface lookup remains in Content/bake, - not a render-thread DAT read. - -#### Automated gate - -- Content, Bake, Launcher.Core, and focused App suites green in Release. -- Installed-DAT manifest produces no unexplained difference. -- Full solution Release build green. -- No per-frame allocation or DAT lookup added. - -#### Owner gate G1a — geometry integrity - -One exact build, normal settings, all behavior-changing probes unset: - -- cathedral exterior ramp and all floating stair slabs; -- cathedral walls at the known `0x104/0106` and `0x107/0112` seams; -- Facility Hub bottom/top stairs and doorway walls; -- two ordinary dungeons with solid-color and textured cell surfaces; -- Holtburg/Nanto building shells. - -Pass means no missing/new wall faces, no invisible ramp/slab, and no gross -material substitution. Camera-dependent occlusion is not adjudicated until -OH6. - -#### Rollback - -One normal revert of the OH2 behavior/schema commit plus restoration of the -previous prepared package version through the supported launcher migration. - ---- - -### OH3 — canonical world-cell graph and exact part-shadow membership - -**Goal:** one graph owns the relationships retail stores on `CEnvCell`, -`CBuildingObj`, `CPhysicsObj`, `CPartArray`, and `CShadowPart`. - -#### OH3a — graph contract and read-only construction - -**Plan:** map every existing source of cell topology, building ownership, -static membership, dynamic membership, and child inheritance. Define stable -keys and generation lifetime. - -**Implement:** build `WorldCellGraphSnapshot` alongside existing owners from -the same accepted publication input. It is initially read-only and diagnostic; -no consumer changes behavior. - -**Review:** reject any field that is a renderer cache rather than world truth; -verify Core/shared layering and atomic lifetime. - -**Gate:** exhaustive equality between graph topology and source publication; -zero production pixel change. - -#### OH3b — static `AddPartsShadow` parity - -**Plan:** port exact part bounds/shape, cell-crossing, insertion order, and -removal rules for indoor statics, building parts, landblock statics, scenery, -and non-colliding decorations. - -**Implement:** populate one ordered membership vector per visual part. Retain -the old render index as a comparator only inside OH3b. Cut render lookup to the -canonical membership after exact comparison is green. - -**Tests:** cathedral ramp/stairs/walls, Facility stairs, a large outdoor object -crossing a 24 m cell edge, a landblock-edge object, a non-colliding decoration, -and a multi-part Setup whose individual parts cross different cells. - -**Delete:** the superseded visual-AABB index builder and duplicate cell buckets -after cutover. - -#### OH3c — dynamic and child membership parity - -**Plan:** port `add_shadows_to_cells`, removal, movement update, and child-list -inheritance as one transaction tied to exact runtime entity incarnation. - -**Implement:** one dynamic registration transaction produces the distinct -retail render-shadow and physics-cell outputs, and the corresponding adapters -borrow those typed results. Visual-only effects use a separately named, -retail-supported owner rule rather than silently falling back to root position. - -**Tests:** local player, remote player, NPC, projectile, spell worldobject, -equipped child, contained child, crossing an indoor portal, crossing outdoors, -and teardown/reconnect. - -#### OH3d — consumer cutover and deletion - -Cut the following consumers to the canonical graph in one controlled series: - -1. indoor static render lookup; -2. outdoor static render lookup; -3. dynamic render lookup; -4. physics broadphase projection; -5. particle owner-cell lookup; -6. point-light owner-cell lookup; -7. directional-shadow caster reachability. - -After every consumer agrees, delete duplicate dictionaries, origin-cell -fallbacks for prepared content, and independent render membership builders. - -#### Review - -- Architecture: exactly one membership authority; retry/recenter/reset safe. -- Retail: crossed cells and insertion order match `AddPartsShadow` family. -- Lifecycle: no stale incarnation or old generation can retain membership. -- Performance: no per-frame graph rebuild; updates are proportional to changed - objects. - -#### Automated gate - -- Exact membership comparator reports zero mismatch across the installed-DAT - canonical routes. -- Render-shadow and physics-cell projections each match their typed expected - output from the same canonical registration transaction; any intentional - difference between the two is explicit and fixture-covered. -- Cancellation, generation replacement, landblock retirement, reconnect, and - child detach converge to zero retained rows. -- Full Release solution and connected headless lifecycle route green. - -#### Owner gate G1b — membership stability - -Use G1a's same binary if practical; otherwise launch once after OH3d: - -- stand on and move around cathedral floating stairs/ramp; -- move/rotate at Facility Hub stairs; -- circle dense Tusker groups while turning the camera; -- observe remote player and NPC across the cathedral wall cells; -- cast and complete several spells, confirming no lingering visual owners. - -Pass means static geometry never disappears merely because its origin cell or -camera-facing cell changes, dynamics do not vanish at membership transitions, -and retired effects leave no render rows. - ---- - -### OH4 — exact PView state and draw-leaf contract - -**Goal:** prove and port what each installed portal view does to each content -category. This stage resolves the current GPU clip-slot uncertainty. - -#### Plan - -For EnvCell shells, building shells, indoor statics, outdoor statics, dynamic -objects, and particles, record separately: - -- number of `portal_view` iterations; -- `viewconeCheck` inputs/result; -- draw-stamp read/write; -- `Render::set_view`/`obj_view_set` calls; -- built versus immediate polygon path; -- whether the final mesh is whole, CPU clipped, or later raster clipped; -- whether multiple surviving views cause multiple submissions; -- which view remains installed at the draw call. - -The already-proved EnvCell rule is binding: the built cell shell is stamped and -submitted whole once. The old "first view clips the shell" hypothesis is -retired and may not return without contradictory binary evidence. - -#### Implement - -1. Make `WalkPView` own the exact mutable per-frame state retail owns: - portal-view lists, view/update counts, todo ordering, draw list, and stamps. -2. Retain exact screen/homogeneous portal polygons as the semantic view. -3. Apply the retail leaf contract per content category: - - whole mesh once where retail does so; - - Boolean drawing-sphere admission where retail does so; - - exact polygon clipping only where retail does so; - - repeated submission only where retail does so. -4. Remove Vulkan clip slots from any category for which they add clipping not - present in retail. -5. Where a retail polygon clip genuinely must reach Vulkan, translate the - already-decided clipped polygon/planes exactly once and pin conventions with - CPU/GPU equivalence tests. -6. Delete comments/tests asserting the disproved generic rule that every - accepted cell/static/dynamic mesh must render through the same clip slot. - -#### Review - -- One table row per content category with a retail call chain. -- Ghidra verification of every stamp/view loop branch. -- Shader review of clip-space sign, y inversion, W plane, max plane count, and - scissor interaction for the remaining translated categories. -- Ensure clip slots cannot become a second admission mechanism. - -#### Automated gate - -- Retail/acdream leaf transcript equality for posed cathedral frames. -- Tests distinguish whole-shell once, Boolean part admission, and actual - polygon clipping. -- Camera pan/zoom replay does not change membership or draw count except at the - same retail view boundary. -- No unexplained duplicate draw of a stamped part. - -#### Owner gate - -Deferred to G2 after frame ordering and depth lifecycle are exact. Testing OH4 -alone would produce ambiguous pixels and waste an owner round. - ---- - -### OH5 — exact landscape, building, cell, and object interleave - -**Goal:** make the frame event sequence equal to retail rather than drawing -terrain as a preliminary block. - -#### Plan - -1. Recover the exact `LScape::draw`/`grab_visible_cells` iteration direction, - sorting keys, and per-landcell call order. -2. Define the exact relationship between: - - terrain cell draw; - - building draw; - - landcell object list; - - building look-in flood; - - outdoor statics and particles; - - pre-clear alpha drain; - - interior root cell-shell/object-list passes. -3. Record all degrade gates and their location relative to alpha barriers. -4. Design terrain draw ranges that allow per-landcell turns without changing - terrain geometry or texture blending. - -#### Implement - -1. Replace `DrawTerrainSlice` as a whole-stage event with ordered landcell - terrain events. -2. Give `TerrainModernRenderer` stable per-landcell ranges/commands. -3. Emit terrain, buildings, and object lists in retail far-to-near order. -4. Reproduce `DrawBuilding` as one semantic sequence: - degrade gate → full alpha barrier → portal/look-in work → punch → own shell. -5. Preserve the separate interior `DrawCells` two-pass order: all shells in - reverse draw-list order, then all object lists in reverse draw-list order. -6. Permit Vulkan to merge only adjacent compatible terrain/draw commands with - no intervening semantic event. -7. Remove the source comment and implementation that acknowledge "all terrain - first" simplification. - -#### Tests - -- Synthetic three-landcell scene with buildings/objects between terrain - cells; exact event-string golden. -- Equal-distance tie ordering. -- Building with and without drawable degrade slot. -- Look-in building embedded between two outdoor cells. -- Interior root with landscape views and without them. -- Outdoor root with no interior clear. -- Renderer command-buffer test proving an alpha/depth boundary prevents an - otherwise legal adjacent merge. - -#### Review - -- Retail call-order audit against trace and decomp. -- Performance review ensures command count increase is measured, not hidden by - reordering. -- Architecture review ensures terrain does not acquire a competing visibility - list. - -#### Automated gate - -- Frame transcript order exact for all posed fixtures. -- Terrain pixels/mesh counts unchanged when no building/object interleave is - present. -- Dense outdoor CPU/GPU p50/p99 captured as an informational checkpoint; no - optimization is permitted to alter order. - -#### Owner gate - -Deferred to G2. - ---- - -### OH6 — exact depth epoch, clear latch, portal punches, seals, and stamps - -**Goal:** reproduce retail's complete depth lifecycle, not merely the punch -pipeline state. - -#### Plan - -1. Reconstruct the full `PView::DrawCells` control flow around - `outside_view.view_count`, the landscape block, alpha flush, frame-stamp - increment, conditional clear, and exit seals. -2. Identify the sole producers/reset sites of `portalsDrawnCount` and prove - whether the clear consumes the previous frame's value before or after reset. -3. Confirm look-in PViews (`draw_landscape=0`) never execute the root landscape - clear/seal block. -4. Confirm which 0xFFFF portals are sealed, their iteration order, installed - view, polygon orientation, and true-depth draw. -5. Retain the already-ported exact Vulkan state: - depth test ALWAYS, depth write ON, color write OFF, no stencil; far-Z for - punch, true clip-space depth for seal. - -#### Implement - -1. Add one explicit frame-persistent latch owner corresponding to retail's - `portalsDrawnCount`; no renderer-local heuristic. -2. Gate the complete landscape→flush→stamp→clear→seal block exactly as retail. -3. Remove `WalkFrameDriver`'s unconditional interior clear. -4. Place the mid-frame stamp transition exactly; allow straddling parts to draw - in both retail scopes when retail re-arms them. -5. Generate exit seals from the exact current walk views and retail cell order. -6. Ensure building look-ins cannot advance or consume the root latch. -7. Delete obsolete stencil/bias tests and any diagnostic skip path once the - causal assertions are covered. - -#### Tests - -- Truth table over root kind, `draw_landscape`, outside-view count, - previous/current portal count, and expected clear/seal/stamp events. -- Two consecutive frames proving the latch is genuinely cross-frame. -- Multiple building look-ins proving isolation from the root PView. -- Coincident cathedral exits at y≈24, y=48, and y=72. -- Recording GPU tests for exact punch/seal pipeline and draw count. -- Negative tests: outdoor root never clears interior depth; zero-view interior - root does not execute a fabricated landscape block. - -#### Review - -- Retail reviewer traces every state write from producer to next-frame - consumer. -- GPU reviewer checks pipeline state and clip-depth calculation only after the - scheduling transcript is exact. -- Architecture reviewer checks the latch has one frame owner and deterministic - reset on session/world generation changes. - -#### Automated gate - -- Exact depth-event transcript equality for posed fixtures. -- Focused walk/depth suites green. -- Full Release build and hermetic App suite green. -- Cathedral replay contains no behavior-changing probe. - -#### Owner gate G2 — opaque-world solidity - -The owner receives one exact binary with a short prescribed route: - -1. Cathedral `0xF4180106 ↔ 0xF4180104`: move both directions, zoom, rotate; - player remains whole and walls remain opaque. -2. Cathedral `0xF4180107 ↔ 0xF4180112` floating stairs: ascend/descend, pan, - zoom, stand at top and bottom; no wall-textured beam, missing slab, exterior - terrain bleed, or chopped player. -3. Cathedral exterior ramp: visible from all meaningful exterior angles. -4. Remote player parked at `0xF4180112`: hidden from `0x104`, `0x101`, and - outdoors wherever retail has no sightline; visible only through valid - openings. -5. Facility Hub stairs at `0x8A02015E/015F`: stairs and player remain whole at - bottom, side, ascent, top, and all retail zoom extents. -6. Tusker/Nanto/Holtburg: rotate in place; terrain, buildings, and opaque - objects remain stable. - -Any failure reopens the owning OH4/OH5/OH6 slice based on transcript evidence. -No new camera-specific suppression is allowed. - ---- - -### OH7 — exact alpha lists, per-cell order, and flush boundaries - -**Goal:** retire AP-34 by reproducing retail's alpha ownership and order. - -#### Plan - -1. Map the two retail alpha lists, their owners, insertion sites, insertion - keys, equal-key behavior, and flush/reset lifecycle. -2. Recover `CShadowPart::insertion_sort` exactly, including direction and ties. -3. Pin every full flush: - - `DrawBuilding(... FlushAlphaList(0f))`; - - `DrawCells` pre-clear; - - final normal-mode flush. -4. Pin `DrawBlock`'s 0.75 pressure-valve semantics and prove it does not become - a global distance sort. -5. Determine the queue ownership of transparent EnvCell shell subsets. - -#### Implement - -1. Replace the scope-global CYpt sort with explicit retail queue/list records. -2. Enqueue transparent parts at their cell/object turn after retail per-cell - insertion ordering. -3. Route transparent EnvCell subsets through the correct queue/flush behavior. -4. Preserve FIFO at flush; do not sort the finished list globally. -5. Preserve blend-mode boundaries without reordering entries. Adjacent - compatible entries may batch only if their FIFO positions remain adjacent. -6. Implement the 0.75 pressure valve exactly. -7. Retire AP-34 in the behavior commit. - -#### Tests - -- Multiple translucent objects in one cell with reversed distance/insertion - orders. -- Equal CYpt stable tie. -- Two cells whose global distance sort would disagree with retail traversal. -- Particle, translucent object, and transparent EnvCell overlap. -- DrawBuilding 0f full flush. -- Pre-clear flush and final flush. -- 0.75 partial flush/pressure valve. -- Alternating blend modes prove order retention across Vulkan batches. - -#### Review - -- Retail list/order review from insertion to flush. -- Vulkan review for blend/depth state without semantic reorder. -- Allocation review: queue storage is retained/reused, with no per-entry boxes. - -#### Automated gate - -- Alpha transcript exact on synthetic and posed fixtures. -- AP-34 deleted. -- Particle/mesh shared-alpha tests green. -- Dense particle field performance captured. - -#### Owner gate - -Fold into G3 after OH8/OH9 so particles, `in_view`, and material combine are -tested together. - ---- - -### OH8 — exact landscape `in_view` and visibility consumers - -**Goal:** make terrain visibility, outdoor particle updating, light admission, -and shadow reachability consume retail state instead of a modern approximation. - -#### Plan - -1. Port and fixture `LScape::draw_check_blocks`, `landcell_check`, - `get_clip_height`, and `block_check` from named retail/Ghidra. -2. Establish exact grid pitch, interval math, corner order, view union, - previous-frame stamping, and outside/inside enum meanings. -3. Pin `CLandCell::IsInView` previous-frame behavior and - `CEnvCell::IsInView`'s constant `PARTIALLY_INSIDE` behavior. -4. Map the update-time and draw-time particle gates separately. -5. Define the complete visibility answer as typed products, not one ambiguous - set: visited EnvCells, in-view landscape cells, drawable object parts, and - particle-update cells. - -#### Implement - -1. Produce the exact retail landcell `in_view` set during the landscape walk. -2. Replace frustum/AABB reconstruction for retail `IsInView` consumers. -3. Feed exact state to particle update/degrade, point-light snapshots, and - directional-shadow selection. -4. Keep EnvCell preparation scoped to visited EnvCells; do not union unrelated - outdoor cells into shell preparation. -5. Preserve the explicit user-selectable Extended particle range after the - exact retail visibility gate. Retail mode applies no multiplier. -6. Retire or narrow AP-117 based on the exact port. - -#### Tests - -- Landcell boundary grazing and multiple portal-view union. -- Previous-frame `CLandCell::IsInView` timing. -- Constant interior EnvCell particle cell test plus distance gate. -- Nanto waterfalls turning at `0xE43D001E`. -- Cathedral waterfall owner range `0xCF418000..13`. -- Tusker scenery/creature visibility while rotating. -- Point light and shadow consumer equality with canonical typed sets. - -#### Review - -- Retail math and one-frame timing review. -- Consumer audit proves no remaining frustum/AABB visibility reconstruction. -- Settings review isolates Extended range as a deliberate post-retail option. - -#### Automated gate - -- Installed-DAT terrain visibility comparisons green. -- Particles/lights/shadows report no independent cell-set decisions. -- Full Core/App focused suites green. - ---- - -### OH9 — building/material/degrade leaf fidelity - -**Goal:** close remaining composition differences that can look like missing or -bleeding world geometry even when traversal is correct. - -#### Plan - -1. Audit `DrawBuilding` degrade selection and no-geometry behavior. -2. Audit building/EnvCell detail texture setup and transparent subset combine. -3. Resolve AP-232 by pinning retail's single fixed-function stage result, - including output alpha. -4. Confirm cull mode, negative-side rendering, clip-map discard, fog, depth - write, and blend state per world subset class. -5. Separate material defects from lighting differences; this stage changes - lighting only when named retail material state requires it. - -#### Implement - -1. Make building degrade selection and complete body gate exact. -2. Reproduce retail's single-result detail combine for translucent subsets, - either in one Vulkan shader path or a mathematically proven equivalent that - produces the same framebuffer result. -3. Preserve exact opaque detail behavior. -4. Normalize world subset state through one audited policy table so building, - EnvCell, and ordinary GfxObj paths cannot silently disagree. -5. Retire AP-232 when pixel-equivalence tests cover translucent detail. - -#### Tests - -- Opaque, clip-map, alpha, inverse-alpha, additive, luminous, and detail-bearing - world subsets. -- Translucent detail over dark and bright backgrounds. -- Building degrade slot absent/present. -- Positive/negative side and cull-state matrix. -- Fogged transparent detail identity. - -#### Review - -- Retail material-stage review. -- Shader algebra review with framebuffer-equivalence fixtures. -- Pipeline-state review for depth/cull/blend consistency. - -#### Automated gate - -- AP-232 deleted. -- Offscreen framebuffer tests match the retail formula. -- World material suites and full Release build green. - -#### Owner gate G3 — transparency, particles, and material composition - -One combined route: - -- cathedral waterfalls, lake mist, torches, floating stairs, walls, exterior - ramp, lifestone/portal effects, and remote actors; -- Nanto waterfalls while rotating at the recorded position; -- Holtburg lifestone behind houses and NPCs; -- Tusker spell casting, projectile completion, corpses, dense creatures, and - scenery; -- Facility Hub point lights and transparent/magenta-lit surfaces at multiple - zoom levels; -- at least one ordinary dungeon with transparent/detail-bearing material. - -Pass means correct occlusion, no lingering effects, no particle disappearance, -no transparency exchange across cells, and no camera-dependent material bleed. - ---- - -### OH10 — delete reconstruction residue and enforce the architecture - -**Goal:** ensure the exact path is the only path that can ship. - -#### Plan - -Inventory every class/field/flag made obsolete by OH2–OH9. Search by type, -constructor, interface, environment variable, log prefix, test name, and docs. - -#### Implement - -Delete or retire: - -- competing cell/part membership dictionaries; -- origin-cell and visual-AABB fallbacks for prepared world content; -- generic per-view GPU clip rules disproved by OH4; -- whole-stage terrain events superseded by per-landcell interleave; -- unconditional clear code and stale comments; -- scope-global alpha ordering superseded by retail queues; -- behavior-changing cathedral skip flags and carrier-discriminator code; -- obsolete shell lift, bias, stencil, corrective redraw, or suppression tests; -- `PortalVisibilityBuilder` research code if no test/research owner still needs - it; otherwise move it out of production assemblies and mark it non-authority; -- stale launch-option rows and retired diagnostics; -- architecture claims contradicted by the final code. - -Add architectural guards: - -- production call graph has one `WalkPView`/world-cell graph owner; -- renderer cannot query DAT directly; -- consumers cannot construct independent visibility sets; -- Vulkan submitter cannot sort across semantic event boundaries; -- no production reference to behavior-changing OH diagnostic symbols; -- divergence rows retired in their owning commits. - -#### Review - -- Dead-code/call-graph review. -- Architecture dependency review. -- Retail review of every deletion to ensure no real mechanism was mistaken for - patch apparatus. -- Documentation consistency review. - -#### Automated gate - -- `rg` guards and dependency tests green. -- No OH behavior-changing probe remains. -- Full Release build and hermetic suites green. -- `git diff --check` clean. - -#### Owner gate - -None; pixels must be unchanged from the accepted G3 binary. If cleanup changes -pixels, it is a failed deletion and the owning slice reopens. - ---- - -### OH11 — performance, regression, final owner acceptance, and closeout - -**Goal:** prove the exact architecture survives ordinary play and becomes the -documented shipping state. - -#### Automated closeout - -1. Full Release solution build. -2. Focused suites: - - App Walk/PView/frame-driver/depth/alpha/render tests; - - Content CellStruct/Surface/prepared-package tests; - - Core cell-transit/shadow/membership tests; - - Runtime lifetime/placement tests touched by shared membership; - - Launcher package migration tests. -3. Hermetic solution lane: - `Lane!=InstalledDat&Lane!=Linux&Lane!=Manual&Lane!=Timing&Lane!=Live&Lane!=PreparedPackage`. -4. Supported installed-DAT lane, with unsupported/known exclusions listed - rather than hidden. -5. Two clean deterministic geometry and membership manifest runs with equal - hashes. -6. Retail/acdream frame transcript equality over all canonical fixtures. -7. Capped and uncapped lifecycle/reconnect routes. -8. R6 nine-stop route. -9. Portal-in and portal-out presentation route, including long destination - preparation. -10. Graceful shutdown with zero retained graph/membership/alpha rows. - -#### Performance checkpoint - -Measure the exact final candidate in Release: - -- dense Arwic capped and uncapped; -- Tusker dense-creature scene; -- cathedral interior/floating stairs; -- Facility Hub interior; -- CPU/GPU p50 and p99, FPS, draw/dispatch counts, managed allocation/frame, - working/private memory, graph/membership retained bytes, and alpha queue high - water. - -Correctness comes first, but a regression greater than 20% against the recorded -pre-OH baseline triggers an explicit optimization slice before final gate. -Optimization may merge adjacent compatible commands or reuse storage; it may -not reorder, cull, or weaken the retail transcript. Every optimization must -pass transcript equality before performance is remeasured. - -#### Owner gate G4 — final acceptance matrix - -The final user gate repeats G1–G3 on one clean exact binary and adds ordinary -travel: - -- cathedral complete route and two-client wall occlusion; -- Facility Hub stair circuit; -- Nanto waterfalls and town buildings; -- Tusker Island combat/casting/camera rotation; -- Holtburg town/building/lifestone route; -- at least two ordinary dungeons selected without code changes; -- portal to/from each world type; -- zoom/pan/rotation at seams; -- ten minutes of free movement looking for spontaneous terrain/object loss. - -The owner verdict is recorded per row as PASS/FAIL with location and symptom. -A failure reopens the responsible slice. The final binary is not rebuilt after -owner acceptance except for documentation-only changes; if code or shader bytes -change, the affected gate repeats. - -#### Documentation closeout - -- Update `docs/architecture/acdream-architecture.md` with the actual canonical - graph and frame pipeline. -- Update `docs/architecture/worldbuilder-inventory.md` with the exact boundary: - asset extraction/preparation only, never world visibility ownership. -- Reconcile `docs/architecture/retail-divergence-register.md`. -- Update `docs/launch-options.md` after probe deletion. -- Close/supersede the relevant FW ledger sections without deleting history. -- Update roadmap, milestones, and `project_frame_walk_campaign.md` or its - successor memory with current truth at the top. -- Record final commits, package version, test counts, connected artifacts, - performance numbers, user verdict, and reverts. - -#### Campaign close condition - -Only after G4 passes and docs match code does Status change to -`CLOSED — USER ACCEPTED`. +## 9. The five slices + +Each slice: plan packet (already written or one short note) → implementation +in bounded chunks → retail review (+ architecture review at S2/S5) → fix → +automated gate → owner gate where listed → ledger update → merge `origin/main` +in. + +### S1 — Geometry: exact CellStruct construction (was OH2) + +**Spec:** `oh2-cellstruct-surface-contract.md`, sections 3, 8, 9, 10, 12 are +the implementation contract verbatim. Retail anchors: `CEnvCell::UnPack` +`0x0052D470`, `CPolygon::UnPack` `0x00538650`, `copyVert` `0x0059C080`, +`D3DPolyRender::ConstructMesh` `0x0059DFA0`, `D3DPolyRender::DrawMesh` +`0x0059D4A0`, `RenderDeviceD3D::DrawEnvCell` `0x0059F170`. + +**Behavior change:** side candidates come only from `sides_type`; `NoPos`/ +`NoNeg` mean UV absence only; subsets are owned and ordered by source surface +index; built-EnvCell admission is `(Surface.Type & 6) != 0` after surface +resolution; authored `sides_type` is not GPU cull. AP-234 retired. + +**Chunks:** +1. Core side-candidate descriptor (pure, allocation-free) + `MeshExtractor. + PrepareCellStructMeshData` rewrite against it + §10.1/§10.2 tests. +2. Prepared subset record fields (source surface index, raw type, retail mask, + fixed cell-shell cull) + `ObjectMeshDataSerializer` round-trip + + `PakFormat.CurrentBakeToolVersion = 8`, launcher recipe 8, `7 → 8` + FullRebuild step + §10.5 tests. Container format stays 2, with a test + saying so. +3. `CellMesh.Build` routed through the same descriptor or its render role + deleted; full installed-DAT scan with every admission delta explained by + `Surface.Type & 6`; two-run deterministic hash; §10.3 canonical pins + (`0xF4180104`: eight `ST_DOUBLE` clip-map polygons, 44 drawable side + calls); AP-234 row deleted with addresses; inventory/architecture text. + +**Review:** retail lens on the descriptor, mask, winding, and admission; data +lens that no ordinary-GfxObj rule leaked into cells or vice versa; Surface +lookup stays in Content/bake. + +**Automated gate:** Content, Bake, Core, Launcher.Core, focused App suites +green in Release; installed-DAT scan reports zero unexplained deltas; full +solution build green; no per-frame allocation or DAT lookup added. + +**Package:** rebuild the dev pak (`Documents\Asheron's Call\acdream.pak`) to +recipe 8 through the supported bake flow; keep the recipe-7 file beside it as +`acdream.recipe7.pak`. Note the launcher-installed pak under +`%LOCALAPPDATA%\acdream\pak` is still recipe 6; it is not the gate binary's +pak. + +**Owner gate G1 — geometry integrity.** One exact build: cathedral exterior +ramp and every floating stair slab; cathedral walls at the `0x104/0106` and +`0x107/0112` seams; Facility Hub bottom/top stairs and doorway walls; two +ordinary dungeons with solid-color and textured surfaces; Holtburg/Nanto +shells. Pass = no missing/new wall faces, no invisible ramp/slab, no gross +material substitution. Camera-dependent occlusion is not adjudicated here. + +**Rollback:** revert the S1 behavior/schema commits; restore +`acdream.recipe7.pak`. + +### S2 — World graph: one membership owner (was OH3) + +**Spec:** `oh1-construction-landscape-contract.md` §construction/ownership; +retail: `CEnvCell::init_static_objects`, `CPhysicsObj::calc_cross_cells_static`, +`CPartArray::AddPartsShadow`, `CPhysicsObj::add_shadows_to_cells`, +`find_bbox_cell_list`, child-list propagation and removal counterparts. +Starting point: the `b3b7d922` candidates (`WalkProductionWorldData` render +index, `ShadowShapeBuilder.FromStaticRenderParts`, +`ShadowObjectRegistry.ComputeStaticRenderCells`, the Facility stair pin +`FacilityStairAssembly_RegisterAcross015FTo015EWithoutCollisionRows`). They +use retail's mechanism in the wrong owner; S2 moves them, it does not delete +the mechanism. + +**Behavior change:** one generation-scoped `WorldCellGraphSnapshot` owns +portal topology, building ownership, drawable cell identity, and typed +per-part render-shadow plus object-level physics `CELLARRAY` outputs from one +registration transaction. Every consumer borrows it; the App-owned render +index, visual-AABB fallbacks, origin-cell fallbacks, and duplicate cell buckets +are deleted. + +**Chunks:** +1. Read-only graph snapshot beside existing owners from the same accepted + publication; equality test against source publication; zero pixel change. +2. Static `AddPartsShadow` parity: ordered membership vector per visual part; + old index retained as comparator only inside this chunk; cut render lookup + after the installed-DAT comparator is zero-mismatch. Fixtures: cathedral + ramp/stairs/walls, Facility stairs, a 24 m cell-edge crosser, a + landblock-edge object, a non-colliding decoration, a multi-part Setup whose + parts cross different cells. +3. Dynamic/child parity: `add_shadows_to_cells`, removal, movement update, + child inheritance as one transaction keyed by exact incarnation. Fixtures: + local/remote player, NPC, projectile, spell world object, equipped child, + contained child, indoor portal crossing, outdoor crossing, teardown/ + reconnect. +4. Consumer cutover in order: indoor static render lookup, outdoor static + render lookup, dynamic render lookup, physics broadphase projection, + particle owner-cell lookup, point-light owner-cell lookup, directional-shadow + reachability. Delete the superseded builders. + +**Review:** architecture (one authority; retry/recenter/reset safe; no +per-frame rebuild) and retail (crossed cells and insertion order match the +`AddPartsShadow` family; `CellTransit` prune change affects collision too and +is reviewed as such). + +**Automated gate:** comparator zero mismatch on installed-DAT canonical routes; +render-shadow and physics projections each match typed expectations from the +same transaction; cancellation, generation replacement, landblock retirement, +reconnect, child detach converge to zero rows; full Release solution and +connected headless lifecycle route green. + +**Owner gate G2 — membership stability.** Cathedral floating stairs/ramp; +move/rotate at Facility Hub stairs; circle dense Tusker groups while turning; +remote player and NPC across cathedral wall cells; cast several spells. Pass = +static geometry never vanishes because its origin or camera-facing cell +changes; dynamics do not vanish at transitions; retired effects leave no rows. + +### S3 — Walk: exact PView views, leaf admission, and interleave (was OH4 + OH5) + +**Spec:** `oh1-built-mesh-view-contract.md`, `oh1-retail-world-contract.md`, +the flood appendix, handoff §5.3 facts, and the §7 capture fixtures. +Retail: `PView::InitCell`, `InsCellTodoList`, `ClipPortals`, +`AddViewToPortals`, `ConstructView`, `DrawCells`, `Render::copy_view`, +`set_view`, `obj_view_set`, `viewconeCheck`; `LScape::draw_check_blocks`, +`landcell_check`, `grab_visible_cells`, `draw`, `calc_draw_order`; +`RenderDeviceD3D::DrawBuilding`, `DrawEnvCell`, `DrawObjCellForDummies`, +`CShadowPart::insertion_sort`, `CPhysicsPart::Draw`, `DrawMesh`, +`DrawMeshInternal`. + +**Binding already-proved facts:** 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. + +**Behavior change:** `WalkPView` owns retail's exact per-frame state +(portal-view lists, view/update counts, todo order, draw list, stamps); each +content category follows its retail leaf rule (whole-once / Boolean sphere / +actual polygon clip / repeated submission) and Vulkan clip slots are removed +from categories where retail does not clip; terrain is emitted as ordered +landcell events interleaved with buildings and object lists in retail +far-to-near order; `DrawBuilding` is one semantic sequence (degrade gate → full +alpha barrier → look-in work → punch → own shell); the "all terrain first" +simplification is deleted. + +**Chunks:** (1) transcript emitter for the OH line kinds behind one print-only +flag + parser extension + fixture import of the §7 logs; (2) exact PView +state and per-category leaf contract with CPU/GPU equivalence pins for any +category that still translates a clip to Vulkan; (3) landscape/building/cell/ +object interleave with per-landcell terrain ranges; (4) delete disproved +generic clip rules and the whole-stage terrain event. + +**Review:** retail lens on every stamp/view loop branch (Ghidra) and on the +call order against capture and decomp; shader review of clip-space sign, y +inversion, W plane, plane count, scissor for remaining translated categories; +performance review that command count increase is measured, not hidden by +reordering. + +**Automated gate:** 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; dense-outdoor p50/p99 recorded. + +**Owner gate:** none standalone; folds into G3. + +### S4 — Depth and alpha: latch, punches, seals, stamps, lists, flushes (was OH6 + OH7) + +**Spec:** `oh1-depth-lifecycle.md`, `oh1-alpha-list-contract.md`, the §7 +alpha/depth captures. Retail: the complete `PView::DrawCells` outside-view +block, `portalsDrawnCount` producer/reset/consumer, the mid-frame stamp +increment (`@0x005A4886`), far-Z punches, true-depth exit seals; +`D3DPolyRender::AddMeshToAlphaList`, `FlushAlphaList`, +`CShadowPart::insertion_sort`, `DrawBlock`'s 0.75 pressure valve. + +**Behavior change:** one frame-persistent latch owner for `portalsDrawnCount`; +the landscape → flush → stamp → clear → seal block gated exactly as retail; +`WalkFrameDriver`'s unconditional interior clear deleted; the mid-frame stamp +placed exactly so straddling parts draw in both retail scopes; exit seals from +the exact current views and cell order; look-ins cannot touch the root latch. +The scope-global CYpt sort is replaced by explicit retail list records with +per-cell insertion order, FIFO flush, exact full-flush sites, and the 0.75 +valve; transparent EnvCell subsets routed to their retail list. AP-34 retired. +Vulkan keeps the already-ported state: depth ALWAYS, write ON, color OFF, no +stencil; far-Z punch, true clip-space seal. + +**Chunks:** (1) latch owner + conditional block + seal generation + truth-table +tests; (2) alpha list records + insertion sort + flush sites + valve + +ordering tests; (3) delete obsolete stencil/bias/skip paths and the CYpt sort. + +**Tests:** truth table over root kind, `draw_landscape`, outside-view count, +previous/current portal count → clear/seal/stamp events; two consecutive +frames proving the latch is cross-frame; multiple look-ins isolated from the +root; coincident cathedral exits at y≈24/48/72; outdoor root never clears +interior depth; multiple translucent objects in one cell with reversed +distance/insertion orders; equal-key stable tie; two cells where a global sort +disagrees with traversal; particle/object/transparent-cell overlap; +`DrawBuilding 0f` flush; pre-clear and final flush; 0.75 partial flush; +alternating blend modes across Vulkan batches. + +**Review:** retail lens tracing every state write from producer to next-frame +consumer, and every list from insertion to flush; GPU lens on pipeline state +after the transcript is exact; architecture lens that the latch has one frame +owner and resets on generation change. + +**Automated gate:** depth-event and alpha transcripts exact against §7 +captures; focused walk/depth/alpha suites and full Release build green; AP-34 +deleted; no behavior-changing probe in the cathedral replay. + +**Owner gate G3 — opaque solidity and transparency.** Cathedral +`0xF4180106 ↔ 0xF4180104` both directions with zoom/rotate; floating stairs +`0xF4180107 ↔ 0xF4180112` ascend/descend/pan/zoom; exterior ramp from all +angles; remote player at `0xF4180112` seen only through valid openings from +`0x104`, `0x101`, outdoors; Facility Hub stairs at all zoom extents; cathedral +waterfalls, mist, torches, lifestone/portal effects; Tusker/Nanto/Holtburg +rotate in place. Pass = player whole, walls opaque, no wall-textured beam or +missing slab, no terrain bleed, correct transparency order, no effect through +walls. + +### S5 — Consumers, material, cleanup, closeout (was OH8 + OH9 + OH10 + OH11) + +**Spec:** `oh1-construction-landscape-contract.md` §landscape; retail +`LScape::draw_check_blocks`, `landcell_check`, `get_clip_height`, +`block_check`, `CLandCell::IsInView` (previous-frame), `CEnvCell::IsInView` +(constant `PARTIALLY_INSIDE`); `DrawBuilding` degrade selection; the +fixed-function material stage for translucent detail (AP-232). + +**Behavior change:** the landscape walk produces the exact retail landcell +`in_view` set; frustum/AABB reconstruction is replaced for every `IsInView` +consumer (particle update/degrade, point-light snapshots, directional-shadow +selection); the Extended particle range remains a deliberate post-retail +option, Retail mode applies no multiplier; AP-117 retired or narrowed. Building +degrade selection and complete-body gate exact; translucent detail combine +reproduces retail's single stage result with framebuffer-equivalence +fixtures; one audited world-subset state policy table; AP-232 retired. Then +delete every obsolete owner, fallback, flag, probe, and stale claim, add the +architectural guards, and run the full closeout. + +**Cleanup inventory (delete or retire):** competing membership dictionaries; +origin-cell and visual-AABB fallbacks; disproved generic per-view clip rules; +whole-stage terrain events; unconditional clear code; scope-global alpha +ordering; `ACDREAM_PROBE_CATHEDRAL_*` skip flags and the carrier-discriminator +code; `ACDREAM_PROBE_FACILITY_STAIRS` and `WbDrawDispatcher.FacilityStairProbe` +with its call sites in `RetailPViewRenderer`, `WalkPView`, +`WalkProductionWorldData`, `WalkStaticStreamPopulator`, +`WbDrawDispatcher.OrderedStream/WalkClassify`; obsolete shell-lift, bias, +stencil, corrective-redraw, suppression tests; `PortalVisibilityBuilder` +research code out of production; stale launch-option rows; architecture +claims contradicted by code. Guards: one `WalkPView`/graph owner in the +production call graph; renderer cannot query DAT; consumers cannot construct +independent visibility sets; the submitter cannot sort across semantic +boundaries; no production reference to OH diagnostic symbols. + +**Automated closeout:** full Release build; focused App/Content/Core/Runtime/ +Launcher suites; hermetic lane +`Lane!=InstalledDat&Lane!=Linux&Lane!=Manual&Lane!=Timing&Lane!=Live&Lane!=PreparedPackage`; +installed-DAT lane with exclusions listed; two deterministic geometry/ +membership runs with equal hashes; transcript equality over all fixtures; +capped/uncapped lifecycle/reconnect routes; R6 nine-stop; portal in/out with +long destination prep; graceful shutdown with zero retained rows. + +**Performance checkpoint:** dense Arwic capped/uncapped, Tusker dense scene, +cathedral floating stairs, Facility Hub; CPU/GPU p50/p99, FPS, draw counts, +allocation/frame, memory, retained graph/membership bytes, alpha high water. A +regression over 20% against the recorded pre-OH baseline triggers an explicit +optimization slice (merge adjacent runs, reuse storage; never reorder, cull, +or weaken the transcript). + +**Owner gate G4 — final matrix.** Repeats G1–G3 on one clean binary and adds: +two-client cathedral wall occlusion; Facility Hub stair circuit; Nanto +waterfalls and town; Tusker combat/casting/rotation; Holtburg town/building/ +lifestone; two ordinary dungeons chosen without code changes; portal to/from +each world type; zoom/pan/rotate at seams; ten minutes of free movement. Per +row PASS/FAIL with location and symptom. The final binary is not rebuilt after +acceptance except for documentation-only changes. + +**Documentation closeout:** architecture doc (actual graph and pipeline), +inventory (asset extraction only, never visibility ownership), divergence +register reconciliation, launch options after probe deletion, FW ledger +superseded not deleted, roadmap/milestones, campaign memory. Then merge to +`main`. Status changes to `CLOSED — USER ACCEPTED` only after G4 and docs match +code. --- ## 10. Canonical scene and symptom matrix -| Scene | Fixed coordinates/state | Required invariant | Primary stages | +| Scene | Fixed coordinates/state | Required invariant | Slices | |---|---|---|---| -| Cathedral south transition | `0xF4180106 [37.181568 46.790077 169.804993]` ↔ `0xF4180104 [37.310383 48.895710 169.804993]` | Player and walls remain whole; no wand/body depth inversion | OH4–OH6 | -| Cathedral wall actor | Observer `0x104`, `0x101`, outdoors; remote in `0xF4180112 [36.299465 18.594580 169.804993]` | Actor visible only through a retail-valid sightline | OH3–OH6 | -| Cathedral floating stairs | `0xF4180107 [38.311169 24.270454 177.423584]` ↔ `0xF4180112 [38.333950 23.704699 177.868729]` | Every slab stable; no moving wall-textured triangles/rays | OH2–OH6 | -| Cathedral exterior ramp | Stand directly on the formerly invisible ramp | Exact authored shell/member always renders | OH2–OH5 | -| Facility Hub stairs | `0x8A02015E [60.971485 -42.752495 -4.121752]`, `0x8A02015F [58.815380 -49.425373 -0.857726]` | Stairs/player stable at bottom, side, ascent, top, zoom | OH2–OH6 | -| Nanto waterfalls | `0xE43D001E [93.826614 126.522484 120.005005]` | Falls do not vanish while rotating; houses occlude effects/NPCs | OH7–OH9 | -| Tusker Island | Owner's dense combat route | Terrain/scenery/actors stable; completed spell objects retire | OH3, OH5, OH8 | -| Holtburg | Town route | Buildings intact; particles/lifestone obey opaque depth | OH5–OH9 | -| Ordinary dungeons | At least two selected before code changes | No cathedral-specific overfit; stairs/walls/portals stable | All | +| Cathedral south transition | `0xF4180106 [37.181568 46.790077 169.804993]` ↔ `0xF4180104 [37.310383 48.895710 169.804993]` | Player and walls whole; no wand/body depth inversion | S3–S4 | +| Cathedral wall actor | Observer `0x104`, `0x101`, outdoors; remote in `0xF4180112 [36.299465 18.594580 169.804993]` | Actor visible only through a retail-valid sightline | S2–S4 | +| Cathedral floating stairs | `0xF4180107 [38.311169 24.270454 177.423584]` ↔ `0xF4180112 [38.333950 23.704699 177.868729]` | Every slab stable; no moving wall-textured triangles | S1–S4 | +| Cathedral exterior ramp | Stand on the formerly invisible ramp | Authored shell/member always renders | S1–S3 | +| Facility Hub stairs | `0x8A02015E [60.971485 -42.752495 -4.121752]`, `0x8A02015F [58.815380 -49.425373 -0.857726]` | Stairs/player stable at bottom, side, ascent, top, zoom | S1–S4 | +| Nanto waterfalls | `0xE43D001E [93.826614 126.522484 120.005005]` | Falls do not vanish while rotating; houses occlude | S4–S5 | +| Tusker Island | Owner's dense combat route | Terrain/scenery/actors stable; spell objects retire | S2, S3, S5 | +| Holtburg | Town route | Buildings intact; particles/lifestone obey depth | S3–S5 | +| Ordinary dungeons | Two, chosen before code changes | No cathedral overfit; stairs/walls/portals stable | all | -The matrix is append-only during the campaign. New symptoms receive a row and -are assigned to an existing invariant before any fix is attempted. +Append-only; a new symptom gets a row and an existing invariant before any fix. --- ## 11. Test and command policy -### Standard build - ```powershell dotnet build AcDream.slnx -c Release -``` - -### Focused project families - -```powershell dotnet test tests\AcDream.Content.Tests\AcDream.Content.Tests.csproj -c Release --no-build dotnet test tests\AcDream.Core.Tests\AcDream.Core.Tests.csproj -c Release --no-build dotnet test tests\AcDream.Runtime.Tests\AcDream.Runtime.Tests.csproj -c Release --no-build @@ -1371,206 +590,105 @@ dotnet test tests\AcDream.App.Tests\AcDream.App.Tests.csproj -c Release --no-bui dotnet test tests\AcDream.Launcher.Core.Tests\AcDream.Launcher.Core.Tests.csproj -c Release --no-build ``` -Use focused `--filter` expressions during implementation, but a stage cannot -close on focused tests alone. Record exact commands and counts in the ledger. +Focused `--filter` runs are for iteration; a slice closes on the full families +above plus the hermetic lane. Record exact commands and counts in §13. -### Launch discipline - -Normal owner-gate launch, from the binding worktree after a green Release build: - -```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" -dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Release -``` - -All behavior-changing probes remain unset for acceptance. A trace gate lists -its print-only flags explicitly. Never reuse an old running client after a -rebuild; record the launched binary hash and process start time. +**Launch discipline:** every launched candidate is a green Release build from a +recorded commit; all behavior-changing probes unset; the owner is told the +exact commit, recipe, and log path; the owner closes the client. --- ## 12. Instrumentation lifecycle -Every new probe is declared in the owning research packet before code: - -- question it answers; -- exact emission site; -- fields and identity chain; -- print-only versus behavior-changing; -- expected maximum volume; -- environment flag; -- deletion stage. - -Rules: - -- Prefer deterministic file transcripts to console tail interpretation. -- Print only on state change or bounded frame windows unless a capture - explicitly requires every event. -- Never use aggregate owner IDs as geometry identity. -- Behavior-changing probes may exist only inside the active investigation and - must be visibly announced at startup. -- A behavior-changing probe can identify a mechanism; it cannot become the - mechanism. -- OH10 removes all Campaign OVERHAUL behavior-changing probes. +- One print-only transcript flag for the frame walk, introduced in S3 chunk 1, + documented in `docs/launch-options.md` in the same commit, output-only, + never read by any draw decision. +- Slice-local comparators (S2 old-vs-new membership) live and die inside the + slice. +- Existing `ACDREAM_PROBE_CATHEDRAL_*` / `ACDREAM_PROBE_FACILITY_STAIRS` flags + stay unset and untouched until S5 deletes them. +- No agent adds a probe outside its chunk contract. --- -## 13. Rollback and recovery policy +## 13. Execution ledger -1. No history rewrite. -2. Every closed behavior slice records a normal `git revert` anchor. -3. Schema migrations record both code revert and package restoration steps. -4. A failed owner gate reverts only the candidate slice if the cause is known; - otherwise preserve logs/artifacts and return to the latest accepted campaign - checkpoint. -5. Never revert the entire dirty starting tree to `b8befded`; that commit is a - historical baseline, not a substitute for OH0 classification. -6. Failed experiments are either reverted immediately or committed on an - explicitly quarantined branch. They do not remain mixed into the next - candidate. -7. The owner must always be told which exact client binary is running. +Update immediately when a slice changes state. Chat is not the ledger. + +| Slice | Status | Spec | Implementation | Reviews | Automated gate | Owner gate | Notes | +|---|---|---|---|---|---|---|---| +| v1 OH0 | CLOSED | `oh0-baseline.md` | `b3b7d922` | read-only classification | Release build green; 319 focused / 1 skip | n/a | historical; candidates it committed are S1/S2 seeds | +| v1 OH1 | SUPERSEDED | research contracts committed at `5cd4fd2c`/`5d907ae9` (kept, binding) | T0–T3 evidence grammar parked on `quarantine/oh1-evidence-grammar-2026-09-02` | reviews found the grammar a false oracle three times | n/a | n/a | see §15 | +| S1 Geometry | IN PROGRESS | `oh2-cellstruct-surface-contract.md` | — | — | — | G1 | recipe 7 → 8 | +| Capture | PENDING | §7 + `tools/walk-oracle/oh/README.md` | scripts drafted; recon owed | — | offsets verified by recon | owner session ~1 h | before S3 | +| S2 World graph | PLANNED | `oh1-construction-landscape-contract.md` | — | — | — | G2 | seeds in `b3b7d922` | +| S3 Walk | PLANNED | built-mesh/world contracts + captures | — | — | — | folded into G3 | | +| S4 Depth + alpha | PLANNED | depth/alpha contracts + captures | — | — | — | G3 | retires AP-34 | +| S5 Consumers + closeout | PLANNED | landscape contract; AP-232 | — | — | — | G4 | retires AP-117/AP-232; deletes probes | ### Rollback ledger -| Slice | Implementation commit(s) | Last accepted gate | Revert command/notes | +| Slice | Commits | Last accepted gate | Revert | |---|---|---|---| -| Starting history | `b8befded`, `4808d4d1`, `4683ac6f`, `e8808602` | FW/Tusker gates recorded in predecessor plan | Historical anchors only; OH0 classifies dirty successor work | -| OH0 | `b3b7d922` | n/a | Recovery checkpoint only; `git revert b3b7d922` removes the preserved investigation state. This commit is not a retail/visual acceptance claim. | -| OH1 | — | n/a | Fill during execution | -| OH2 | — | G1a | Fill during execution | -| OH3 | — | G1b | Fill during execution | -| OH4 | — | G2 combined | Fill during execution | -| OH5 | — | G2 combined | Fill during execution | -| OH6 | — | G2 | Fill during execution | -| OH7 | — | G3 combined | Fill during execution | -| OH8 | — | G3 combined | Fill during execution | -| OH9 | — | G3 | Fill during execution | -| OH10 | — | pixels unchanged | Fill during execution | -| OH11 | — | G4 | Fill during execution | +| FW closeout | `b8befded`, `4808d4d1`, `4683ac6f`, `e8808602` | FW/Tusker gates | historical anchors only | +| v1 OH0 | `b3b7d922` | n/a | `git revert b3b7d922` removes the investigation candidates including the Facility stair fix; not a visual claim | +| S1 | — | G1 | fill during execution; restore `acdream.recipe7.pak` | +| S2 | — | G2 | fill | +| S3 | — | G3 | fill | +| S4 | — | G3 | fill | +| S5 | — | G4 | fill | --- -## 14. Risk register +## 14. Risk register (condensed) -### R1 — rebuilding retail's object graph as a second scene graph - -**Risk:** `WorldCellGraphSnapshot` becomes a mirror that can drift from Runtime -or publication state. - -**Control:** graph records own only canonical topology/membership facts; mesh -and entity state remain borrowed by stable identity. Atomic generation tests and -consumer deletion are part of OH3, not deferred cleanup. - -### R2 — over-porting mutable C++ mechanics - -**Risk:** copying retail pointer/list implementation creates unnecessary -allocation and lifetime hazards. - -**Control:** port observable ordering, ownership, stamps, and state transitions; -represent them with retained arrays/indexes. Equality is judged by semantic -transcript, not pointer layout. - -### R3 — Vulkan batching changes semantic order - -**Risk:** performance optimization regroups cells/materials after the exact -walk is built. - -**Control:** ordered stream is immutable; only adjacent compatible runs merge. -Tests deliberately place merge-compatible draws around alpha/depth boundaries. - -### R4 — prepared-package schema churn - -**Risk:** exact CellStruct surface data invalidates existing packages or creates -launcher/client skew. - -**Control:** OH2 owns one explicit version bump, strict rejection/migration, -rollback, corruption tests, and launcher coverage. - -### R5 — retail oracle incompleteness - -**Risk:** an unobserved built-mesh branch causes another confident but wrong -generic clipping rule. - -**Control:** OH1 explicitly separates each leaf category and blocks OH4 until -the built/non-built behavior is settled. No approximation is allowed to bridge -the gap. - -### R6 — scene overfitting - -**Risk:** cathedral IDs leak into production logic or tests validate only one -DAT structure. - -**Control:** production guards reject scene IDs; installed-DAT sampling and -ordinary-dungeon gates are mandatory. - -### R7 — performance collapse from per-cell commands - -**Risk:** exact interleave increases draw calls and CPU overhead. - -**Control:** correctness-first transcript; then adjacent-run merging and -retained storage only. The 20% stop rule requires an explicit optimization -slice, never a semantic shortcut. - -### R8 — stale documentation drives the next wrong fix - -**Risk:** architecture/plan claims remain inconsistent with code. - -**Control:** OH10 includes grep/document consistency checks; OH11 cannot close -until the architecture description is reviewed against production call sites. - -### R9 — too many owner gates - -**Risk:** implementation degenerates into repeated manual trial-and-error. - -**Control:** four planned gate builds only. Every build arrives after evidence, -implementation, two-lens review, fixes, and automated gates. +- **R1 second scene graph.** Graph records own only topology/membership facts; + mesh/entity state is borrowed. Consumer deletion is inside S2. +- **R2 over-porting C++ mechanics.** Port observable ordering, ownership, + stamps, and transitions into retained arrays; equality by transcript. +- **R3 Vulkan reorders.** Immutable stream; only adjacent compatible runs + merge; tests place merge-compatible draws around alpha/depth boundaries. +- **R4 package churn.** S1 owns one recipe bump with strict rejection, + migration, rollback, corruption tests, launcher coverage. +- **R5 oracle incompleteness.** The §7 capture is the answer key; a missing + fact gets one exact additional capture, never an approximation. +- **R6 scene overfitting.** Production guards reject scene IDs; installed-DAT + sampling and ordinary-dungeon gates are mandatory. +- **R7 per-cell command cost.** Correctness-first; the 20% rule triggers an + explicit optimization slice. +- **R8 stale docs.** S5 cannot close until architecture text is checked + against production call sites. +- **R9 evidence sink (new).** Rule 2 and rule 15. A slice with no production + change after its first chunk is a red flag, not progress. --- -## 15. Execution ledger +## 15. v2 rescope record (2026-09-02) -Update this table immediately when a slice changes state. Do not keep the real -status only in chat. +**What happened.** v1's OH1 ("upgrade the oracle first") ran unsupervised for +eighteen hours and produced ~32K lines of uncommitted canonical-JSONL +evidence grammar plus 142 tests, three review rounds each finding the grammar +encoded wrong retail semantics, and zero production change. The grammar +re-encoded PView inside a validator, making it a second port that needed the +same retail review; it also validated "strong" evidence that neither the +retail captures nor the acdream recorder produced. The one unlocking item, +extending the cdb capture templates, was never started. -| Slice | Status | Evidence packet | Implementation | Reviews | Automated gate | Owner gate | Notes | -|---|---|---|---|---|---|---|---| -| OH0 | CLOSED | `docs/research/2026-09-01-overhaul/oh0-baseline.md` | `b3b7d922` recovery checkpoint | Read-only dirty-tree classification; every path accounted for | Release build green; focused gates 319 passed / 1 skipped; OH docs pass `git diff --check` | n/a | No production behavior changed by OH0; no unrelated semantic files found; candidate state is explicitly unaccepted | -| OH1 | IN PROGRESS | `oh1-retail-world-contract.md` plus construction, built-view, alpha-list, and depth packets | strict Core schema/codec and output-only App recorder in review | retail synthesis re-review passed after two blockers were corrected; final alpha/tooling review active | Core codec focused gate green before schema-expansion review | not required so far | No production draw decision may change; legacy FW semantic importer and recorder equivalence gate remain | -| OH2 | PLANNED | — | — | — | — | G1a | Retire AP-234 | -| OH3a | PLANNED | — | — | — | — | folded | Read-only canonical graph | -| OH3b | PLANNED | — | — | — | — | folded | Static membership | -| OH3c | PLANNED | — | — | — | — | folded | Dynamic/child membership | -| OH3d | PLANNED | — | — | — | — | G1b if needed | Consumer cutover/deletion | -| OH4 | PLANNED | — | — | — | — | folded into G2 | Per-leaf portal-view contract | -| OH5 | PLANNED | — | — | — | — | folded into G2 | Full landscape interleave | -| OH6 | PLANNED | — | — | — | — | G2 | Exact depth lifecycle | -| OH7 | PLANNED | — | — | — | — | folded into G3 | Retire AP-34 | -| OH8 | PLANNED | — | — | — | — | folded into G3 | Retire/narrow AP-117 | -| OH9 | PLANNED | — | — | — | — | G3 | Retire AP-232 | -| OH10 | PLANNED | — | — | — | — | n/a | Deletions and guards | -| OH11 | PLANNED | — | — | — | — | G4 | Final closeout | +**What v2 keeps.** All committed research contracts; the FW0 capture corpus +and its proven line-format + parser + replay pattern (which reached 9/10 +conformant fixtures in FW1); the `b3b7d922` candidates as S1/S2 seeds; the +retail facts the T3 reviews established (handoff §5.3). ---- +**What v2 parks.** The evidence grammar, recorder hooks, importer, manifest +command, and their docs, verbatim, on +`quarantine/oh1-evidence-grammar-2026-09-02`. -## 16. First execution actions +**Stage mapping.** OH2 → S1; OH3a–d → S2; OH4 + OH5 → S3; OH6 + OH7 → S4; +OH8–OH11 → S5. Owner gates: G1 after S1, G2 after S2, G3 after S4, G4 final. -When the owner says to begin execution, do exactly this: +**Process changes.** Rules 2 and 15; the §5 working model; the §7 single +capture session; evidence products limited to what each slice consumes. -1. Start OH0; do not edit rendering behavior. -2. Produce the dirty-tree classification and recovery anchor. -3. Build and record the current baseline. -4. Start OH1's retail contract with the two facts most likely to invalidate - current code: - - object built-mesh behavior under `set_view`/`obj_view_set`; - - complete `portalsDrawnCount` producer/consumer/reset lifecycle. -5. In parallel only after OH0 safety is complete, prepare OH2's CellStruct - surface manifest; it is independent of frame scheduling. -6. Review the OH1/OH2 evidence before the first behavior change. -7. Implement OH2, review it, fix findings, and run G1a. - -No new cathedral visual discriminator is the first action of this campaign. +**Memory:** `claude-memory/feedback_evidence_infrastructure_sink.md`; +`claude-memory/project_overhaul_campaign.md` is the START HERE. diff --git a/docs/research/2026-08-30-fw-flood-pseudocode-appendix.md b/docs/research/2026-08-30-fw-flood-pseudocode-appendix.md index a6e65879..b6968026 100644 --- a/docs/research/2026-08-30-fw-flood-pseudocode-appendix.md +++ b/docs/research/2026-08-30-fw-flood-pseudocode-appendix.md @@ -6,7 +6,18 @@ Second read round: the interior-flood and view-support functions. Same method as ### PView::InitCell @0x005a4b70 -**Summary:** Initializes the cell's TOP portal_view slot (portal_view.data[num_view-1]) for the flood: stamps view_timestamp = master_timestamp, clears cell_view_done, grows the per-portal portal_info array to num_portals, classifies every portal as in-view (inflag) or rejected via a cell-local viewpoint-vs-portal-plane side test, computes max_indist = max SQUARED viewpoint distance to any in-view portal vertex, and marks every rejected portal seen=1 so the flood never traverses it. The entry portal (real index; 0xffff sentinel never matches) is forced inflag=1 + seen=1 instead of side-tested. +**Corrected summary (2026-09-02, x87 branch re-arbitrated):** Initializes the +cell's TOP portal_view slot (`portal_view.data[num_view-1]`) for the flood: +stamps `view_timestamp = master_timestamp`, clears `cell_view_done`, grows the +per-portal `portal_info` array to `num_portals`, and classifies every portal by +the cell-local viewpoint/plane side test. The names are deceptive: +`ClipPortals` considers exactly `seen != 0 && inflag != 1`, so `inflag == 0` +is the traversable candidate state and `inflag == 1` is excluded. The entered- +through portal is forced to `inflag=1, seen=1` and is therefore excluded as the +backlink. `max_indist` is the maximum SQUARED viewpoint distance over the +`inflag == 1` portal vertices—the excluded/incoming/back-facing set—not the +traversable set. The earlier prose labels in this report inverted this meaning; +the assignments themselves were correct. ```c int PView::InitCell(CEnvCell* cell, uint16 entry_portal_idx) // Ghidra: returns int; BN said void @@ -21,12 +32,12 @@ int PView::InitCell(CEnvCell* cell, uint16 entry_portal_idx) // Ghidra: returns DArray::grow(&slot->portal, cell->num_portals); // exact-size; NEW entries UNINITIALIZED float max_d2 = 0.0f; - int any_rejected = /*UNINITIALIZED stack dword — see gotchas*/; + int any_candidate = /*UNINITIALIZED stack dword — see gotchas*/; for (i = 0; i < cell->num_portals; i++) { // CCellPortal stride 0x18 CPolygon* poly = cell->portals[i].portal; if (i == entry_portal_idx && slot->portal.data[i].inflag == 0) { - // entered-through portal: forced visible + consumed (0xffff seed sentinel never hits this) + // entered-through backlink: forced excluded + consumed (0xffff seed sentinel never hits this) slot->portal.data[i].inflag = 1; slot->portal.data[i].seen = 1; } else { @@ -36,10 +47,10 @@ int PView::InitCell(CEnvCell* cell, uint16 entry_portal_idx) // Ghidra: returns int side; // 0=POSITIVE, 1=NEGATIVE if (d > F_EPSILON) side = 0; // F_EPSILON = 0.000199999995f else if (d < -F_EPSILON) side = 1; - else { slot->portal.data[i].inflag = 0; any_rejected = 1; goto vertex_scan; } // IN_PLANE: always reject + else { slot->portal.data[i].inflag = 0; any_candidate = 1; goto vertex_scan; } // IN_PLANE: traversable candidate if (side != cell->portals[i].portal_side) - slot->portal.data[i].inflag = 1; // viewer on the see-through side - else { slot->portal.data[i].inflag = 0; any_rejected = 1; } // viewer on the portal's own side + slot->portal.data[i].inflag = 1; // excluded by ClipPortals + else { slot->portal.data[i].inflag = 0; any_candidate = 1; } // traversable candidate } vertex_scan: if (slot->portal.data[i].inflag == 1 && poly->num_pts > 0) // num_pts = byte @ +0xe @@ -48,14 +59,14 @@ vertex_scan: if (max_d2 < d2) max_d2 = d2; } } - slot->max_indist = max_d2; // max squared distance to any in-view portal vertex + slot->max_indist = max_d2; // max squared distance over inflag==1 (excluded) portal vertices - if (any_rejected != 0 && slot->view_count > 0) + if (any_candidate != 0 && slot->view_count > 0) for (v = 0; v < slot->view_count; v++) { Render::set_view(&slot->view, v); // installs global active view; the check below does NOT read it for (j = 0; j < cell->num_portals; j++) if (portal[j].inflag == 0 && portal[j].seen == 0) - portal[j].seen = 1; // rejected portals become 'consumed': flood never walks them + portal[j].seen = 1; // makes inflag==0 portals eligible for ClipPortals } slot->update_count = slot->view_count; @@ -64,7 +75,29 @@ vertex_scan: } ``` -**Gotchas:** BN body @0x005a4b70 is UNUSABLE: it scrambled the x87 side-test control flow AND elided the squared-distance math (showed only the z subtraction). This model is Ghidra-verified (127.0.0.1:8081). Confirmed semantics: side==portal_side rejects, IN_PLANE (|d|<=0.000199999995f) always rejects — matches the FW doc's sidedness table. Real retail quirks: (1) any_rejected (local_4) is NEVER initialized — if no portal is rejected it reads stack garbage; the effect is benign (the fixup inner body no-ops when nothing was rejected; only side effect is redundant set_view churn), so a port should init it to 0 with identical observable behavior. (2) The entry-portal branch is guarded by the STALE inflag (inflag==0) — on a freshly grown portal array inflag is heap garbage (DArray::grow does NOT zero new entries); the caller (AddViewToPortals) presumably establishes it — verify that contract when porting FW3. (3) set_view inside the fixup loop installs each view globally but nothing in the loop consults it, and the LAST view stays installed on exit — both decompilers agree; purpose unclear (possibly vestigial). (4) positionPush(3, cell->pos) means the plane test and max_indist run in CELL-LOCAL coordinates. (5) 0xffff sentinel: ushort zero-extended vs uint loop index — never matches, so the seed cell side-tests every portal. (6) max_indist is a SQUARED distance — todo-list keys fed from it are squared; comparisons stay consistent. Ghidra return type is int (0 = early-out on view_count==0, 1 = did work); BN said void __stdcall. +**Gotchas:** BN body @0x005a4b70 is UNUSABLE: it scrambled the x87 +side-test control flow AND elided the squared-distance math (showed only the z +subtraction). The x87 branch was re-arbitrated against retail bytes +`005A4C48..005A4C9D` on 2026-09-02. Confirmed semantics: +`side==portal_side` and IN_PLANE (`|d|<=0.000199999995f`) produce +`inflag=0`, which is the traversable candidate state because `ClipPortals` +later requires `seen!=0 && inflag!=1`; side mismatch produces the excluded +`inflag=1` state. Real retail quirks: (1) `any_candidate` (`local_4`) is NEVER +initialized—if no candidate exists it reads stack garbage; the effect is +benign because the fixup inner body no-ops, leaving only redundant `set_view` +churn, so a port may initialize it to zero with identical observable behavior. +(2) The entry-portal branch is guarded by stale `inflag`; it forces the +entered-through backlink to the excluded/seen state. On a freshly grown portal +array `inflag` is heap garbage (`DArray::grow` does not zero new entries), so +the caller contract remains significant. (3) `set_view` inside the fixup loop +installs each view globally but nothing in the loop consults it, and the LAST +view stays installed on exit. (4) `positionPush(3, cell->pos)` means the plane +test and `max_indist` run in CELL-LOCAL coordinates. (5) The `0xffff` seed +sentinel never matches, so the seed cell side-tests every portal. (6) +`max_indist` is a SQUARED distance over `inflag==1` portal vertices; todo-list +comparisons stay internally consistent even though that set is excluded from +traversal. Ghidra return type is int (0 = early-out on `view_count==0`, 1 = +did work); BN said void `__stdcall`. ### PView::InsCellTodoList @0x005a4f50 @@ -147,7 +180,25 @@ void CEnvCell::curr_view_push() **Gotchas:** VERIFIES the earlier read: num_view++ with 0x48-byte lazy slot alloc + counter resets — with precision: exactly view_count/update_count/view_timestamp are reset on EVERY push (fresh or recycled); cell_view_done and max_indist are NOT reset here and stay stale (heap garbage on a brand-new slot) until PView::InitCell writes them — InitCell always runs before they are consumed, but a port must preserve that ordering or zero them harmlessly. The single-slot null after grow is sound only because this DArray grow(n) sets sizeOf to EXACTLY n (verified @0x005a45d0: copies old, sizeOf=arg; blocksize unused by grow; grow with arg<=sizeOf delegates to shrink) — no hidden capacity slack, so no garbage slots. portal_view_type layout confirmed in acclient.h: {DArray portal @0; view_type view @0x10 (vertex_count_total, poly@0x14, vertex@0x24); max_indist @0x34; view_count @0x38; cell_view_done @0x3c; view_timestamp @0x40; update_count @0x44}; DArray = {data, blocksize, next_available, sizeOf}. -**Report notes:** All four bodies cross-checked against live Ghidra MCP (http://127.0.0.1:8081, patchmem.gpr) — mandatory here, because BN got two of them materially wrong: (1) InsCellTodoList's insertion comparison was polarity-INVERTED in BN (would have modeled a farthest-first pop); Ghidra's strict `dist < prev->dist` break gives a descending-from-index-0 list whose END-pop is NEAREST-first, which is what makes the draw list come out near->far and DrawCells' end-first walk far-to-near — consistent with FW doc section 5. (2) InitCell's BN body scrambled the plane-side branches and elided the dx^2+dy^2+dz^2 accumulation entirely (showed a bare z subtraction). Ghidra-confirmed model: side 0/1 vs portal_side rejects on equality, IN_PLANE always rejects (matches the doc's section 7 sidedness table), max_indist = max SQUARED cell-local distance to in-view portal vertices, and rejected portals get seen=1 in a fixup pass whose per-view set_view calls are side-effect-only. Two genuine retail quirks worth register-awareness if ported observably: InitCell's any_rejected flag is an uninitialized stack read (benign in effect), and the entry-portal force-visible branch keys off STALE inflag whose state is a caller contract (read PView::AddViewToPortals before relying on it in FW3). Struct authorities verified in acclient.h: portal_info {seen, inflag}; portal_view_type (0x48 bytes, field offsets in the curr_view_push gotchas); PView {outside_view, draw_landscape, outdoor_portal_list, cell_draw_list, cell_draw_num, cell_todo_list, cell_todo_num, lscape}; CellListType nodes are 8-byte {CEnvCell* cell, float dist}; CPolygon {vertices@0, num_pts byte@0xe, plane@0x20}. Sources: docs/research/named-retail/acclient_2013_pseudo_c.txt lines 311378-311393, 432896-433045, 433183-433243, 433279-433320; DArray grow/shrink @0x005a45d0 region; struct defs in docs/research/named-retail/acclient.h (portal_info @32458, portal_view_type @32346, view_type @32338, PView @45934, CPolygon @31855). +**Report notes (corrected 2026-09-02):** All four bodies were +cross-checked against the live Ghidra project; the load-bearing branches were +then re-arbitrated against the retail bytes because the earlier prose assigned +the intuitive but wrong meaning to `inflag`. (1) `InsCellTodoList` uses strict +`dist < prev->dist` as its break, giving a list descending from index zero and +nearest-first END pops, with FIFO ties. (2) `InitCell` writes `inflag=0` for +`side==portal_side` and IN_PLANE, then its fixup writes `seen=1`; those rows +are precisely the candidates later admitted by `ClipPortals`'s +`seen!=0 && inflag!=1` gate. Side mismatch and the entered-through backlink +use `inflag=1` and are excluded. `max_indist` is the maximum squared +cell-local distance over the `inflag==1` portal vertices, not over the +traversable candidates. Two genuine retail quirks remain relevant: +`local_4` is an uninitialized stack read, and the entry-portal branch keys off +stale `inflag` state established by the caller/allocation history. Struct +authorities remain `portal_info {seen,inflag}`, `portal_view_type` (0x48 +bytes), `PView`, `CellListType {cell,float dist}`, and `CPolygon`. Sources: +named-retail lines 311378-311393, 432896-433045, 433183-433243, and +433279-433320; retail bytes `005A4C48..005A4C9D`; DArray grow/shrink near +`0x005A45D0`; and the named retail header definitions. ## Report 2 - Flood propagation (ClipPortals / AddViewToPortals) diff --git a/docs/research/2026-09-01-overhaul/2026-09-02-campaign-overhaul-handoff.md b/docs/research/2026-09-01-overhaul/2026-09-02-campaign-overhaul-handoff.md new file mode 100644 index 00000000..8a157b5d --- /dev/null +++ b/docs/research/2026-09-01-overhaul/2026-09-02-campaign-overhaul-handoff.md @@ -0,0 +1,464 @@ +> **SUPERSEDED 2026-09-02 (same day) by the v2 rescope.** This handoff describes the v1 OH1/T3 freeze. Its section 8 dirty-tree map is WRONG: the dirty App rendering files were T2 recorder hooks, not pre-overhaul behavior candidates (those were already committed in `b3b7d922`). The T3 grammar it describes is parked on `quarantine/oh1-evidence-grammar-2026-09-02`. Section 5.3 (retail truths bound by T3) remains a binding input to S3/S4. Current plan: `docs/plans/2026-09-01-campaign-overhaul-world-solidity.md` §15. + +# Campaign OVERHAUL handoff — OH1/T3 freeze + +**Frozen:** 2026-09-02 (Europe/Stockholm) + +**Campaign state:** active; not complete + +**Current slice:** OH1, transcript task T3 + +**T3 state:** third implementation/fix round is locally green, but independent +closure review is still required + +**Production rendering claim:** none. OH1 is evidence/contract work and must not +change draw decisions. + +This is the durable handoff for a new model. It records the exact checkout, +history, dirty-state constraints, campaign ledger, current automated evidence, +review findings, and the next safe actions. Do not reconstruct state from chat +summaries when this file and the campaign ledger disagree with them. + +## 1. Exact checkout and recovery boundary + +Work only in this existing worktree: + +```text +C:\Users\erikn\source\repos\acdream\.claude\worktrees\peaceful-blackburn-5333f0 +``` + +Repository state at the freeze: + +| Field | Value | +|---|---| +| Branch | `claude/campaign-w-retail-frame-walk` | +| HEAD | `5d907ae9ad9462347eb697c39ae3ffac136a40bc` | +| Upstream | `origin/claude/campaign-w-retail-frame-walk` | +| Upstream relation | ahead 32, behind 0 at the freeze | +| Staged paths | 0 | +| Latest commit | `5d907ae9 docs(render): define OH1 retail world contract` | +| Recovery checkpoint | `b3b7d922 checkpoint(render): preserve pre-overhaul investigation state` | + +Recent history: + +```text +5d907ae9 docs(render): define OH1 retail world contract +5cd4fd2c docs(render): define OH2 CellStruct contract +eaea8776 docs(render): clean OH0 baseline formatting +fba07e77 docs(render): establish Campaign OVERHAUL baseline +b3b7d922 checkpoint(render): preserve pre-overhaul investigation state +e8808602 fix(render): restore landscape objects and walk alpha order +4683ac6f docs(render): record Campaign FW closeout gates +4808d4d1 refactor(render): remove Campaign FW probes +``` + +The current T3 work is deliberately **uncommitted**. Do not reset, clean, +checkout, or wholesale copy another tree over this checkout. The dirty tree +contains both intentionally preserved pre-overhaul investigation candidates and +new OH1 evidence tooling. Follow the recovery procedure in `oh0-baseline.md`. +In particular: + +1. Never use `git reset --hard`, `git checkout --`, or `git clean` here. +2. Do not treat every dirty App rendering file as OH1 work. +3. To inspect an older state, use a separate detached/read-only worktree. +4. To recover through history, revert OH commits in reverse order and stop at + `b3b7d922`; do not rewrite history. +5. Before staging, inspect each path and exclude line-ending/blank-line noise. + +## 2. Goal and campaign scope + +The active goal is: + +> Complete Campaign OVERHAUL — retail world construction and render solidity — +> in this worktree by executing every Plan → Implement → Review slice, using +> deterministic retail evidence, independent review, automated gates, and only +> the necessary owner visual gates, until the campaign is user-accepted and +> closed. + +The campaign exists because locally plausible fixes repeatedly traded one world +artifact for another. The accumulated owner-observed symptom family includes: + +- Cathedral opaque walls or wall-textured triangles covering floating stairs; +- floating stair slabs appearing/disappearing with camera angle or cell seam; +- the cathedral exterior ramp being entirely absent despite supporting the + player physically; +- wall, terrain, or building textures bleeding through other opaque surfaces; +- the local character being chopped at cathedral and Facility Hub cell seams, + including a missing head/body sections and equipment drawing through it; +- remote players/NPCs and particle systems appearing through opaque walls; +- waterfalls disappearing by camera angle, or shining through buildings; +- outdoor terrain/scenery/object groups disappearing after small camera turns; +- landscape draw range regressions; and +- spell effect world objects lingering after their authored lifetime. + +Some preserved dirty-tree candidates improved individual symptoms, but they are +explicitly **unaccepted** and are not a retail-parity baseline. The overhaul is +meant to replace approximation-by-symptom with one executable retail contract +covering authored geometry, cell membership, PView traversal, leaf admission, +draw order, depth, alpha, and downstream consumers. + +## 3. Mandatory read order and active ledgers + +Read these before editing: + +1. `AGENTS.md` in the repository root. +2. `docs/architecture/acdream-architecture.md` — architecture authority. +3. `docs/architecture/worldbuilder-inventory.md` — mandatory before any + rendering or DAT algorithm is reimplemented. +4. `docs/plans/2026-09-01-campaign-overhaul-world-solidity.md` — the campaign + plan and primary execution ledger. +5. `docs/research/2026-09-01-overhaul/oh0-baseline.md` — exact dirty-state + classification, hashes, baseline gates, and recovery procedure. +6. `docs/research/2026-09-01-overhaul/oh1-retail-world-contract.md`. +7. The four supporting OH1 evidence packets: + - `oh1-construction-landscape-contract.md` + - `oh1-built-mesh-view-contract.md` + - `oh1-alpha-list-contract.md` + - `oh1-depth-lifecycle.md` +8. `docs/research/2026-09-01-overhaul/oh1-world-evidence-tooling.md` — the + active OH1 tooling/status ledger. +9. `docs/research/2026-09-01-overhaul/oh2-cellstruct-surface-contract.md` — + completed OH2 design, not authorization to skip unfinished OH1 work. +10. `docs/research/2026-08-30-fw-flood-pseudocode-appendix.md` — corrected + PView/flood pseudocode and signedness/branch details. + +Historical cathedral context remains useful after the overhaul plan and OH0 +classification have been read: + +- `docs/research/2026-08-30-cathedral-handover.md` +- `docs/research/2026-08-30-cathedral-synthesis.md` +- `docs/research/2026-08-30-fw-walk-oracle/posed/` + +Retail source authority: + +- `docs/research/named-retail/acclient_2013_pseudo_c.txt` +- `docs/research/named-retail/acclient.h` +- `docs/research/decompiled/` only as the older address-range fallback. + +Grep the named retail decomp by `class::method` before decompiling anything +fresh. When Binary Ninja or recovered pseudo-C leaves a branch sense ambiguous, +use the existing Ghidra arbitration workflow; do not choose the branch that +merely makes current tests green. Content identity must be traced to the DAT, +not inferred from aggregate owner IDs. + +The campaign plan contains three important ledgers: + +- stage/owner-gate table around lines 434–445; +- checkpoint ledger around lines 1461–1473; and +- execution ledger around lines 1561–1575. + +The execution ledger is authoritative over the plan header's older +`READY TO EXECUTE` wording. + +## 4. Campaign progress at the freeze + +| Scope | State | Durable result | What remains | +|---|---|---|---| +| OH0 | **CLOSED** | Dirty tree classified; recovery checkpoint `b3b7d922`; baseline and source/package hashes recorded | Nothing unless the checkout must be recovered | +| OH1 research contract | **CLOSED/COMMITTED** | Main and four supporting retail contracts at `5d907ae9` | Keep synchronized with executable evidence | +| OH1 T0–T2 | **CLOSED** | Canonical schema/codec/hash/coverage foundations, strong frame/call grammar, narrow FW0 importer, and output-only App recorder foundations | Preserve their strict capability boundary | +| OH1 T3 | **IMPLEMENTED, GREEN, REVIEW OPEN** | Source-closed PView, installed-view, DrawCells, shell/object-leaf, and persistent-stamp grammar; third fix round frozen uncommitted | Finish the missing adversarial surface and independent retail/architecture closure review | +| OH1 T4–T8 | **PENDING** | No closure claim | Complete landscape/building order, alpha/material, depth lifecycle, recorder/fixture integration, aggregate gates, and OH1 closeout as defined by the plan | +| OH2 design | **CLOSED/COMMITTED** | Exact CellStruct surface/subset contract at `5cd4fd2c` | Production implementation, package migration, deterministic installed-DAT manifest, review, and G1 are not started | +| OH2 implementation | **PLANNED/BLOCKED ON OH1** | None | Start only after OH1's executable contract is review-closed | +| OH3 | **PLANNED** | Canonical cell graph/exact part-shadow membership | Entire slice | +| OH4 | **PLANNED** | Exact PView views and leaf admission/clipping | Entire slice | +| OH5 | **PLANNED** | Exact landscape/building/cell/object interleave | Entire slice | +| OH6 | **PLANNED** | Exact depth epoch, clear latch, punches, seals, stamps | Entire slice plus owner gate G2 | +| OH7 | **PLANNED** | Exact alpha ownership/order/flushes | Entire slice | +| OH8 | **PLANNED** | Exact landscape `in_view` and particle/light/shadow consumers | Entire slice | +| OH9 | **PLANNED** | Building/material/degrade leaf fidelity | Entire slice | +| OH10 | **PLANNED** | Delete duplicate owners/fallbacks/experiments/stale claims | Entire slice | +| OH11 | **PLANNED** | Full regression, performance, connected routes, docs, final acceptance | Entire slice plus final owner gate G4 | + +OH2 did not disappear: its **design** was produced in parallel and committed. +Its implementation is intentionally waiting because implementing geometry before +the complete OH1 oracle is review-closed would repeat the campaign's central +failure mode: a green test encoding the wrong retail behavior. + +## 5. Current T3 implementation + +### 5.1 Purpose and boundary + +T3 does not render anything. It defines a strict, canonical JSONL evidence +language in `AcDream.Core.Diagnostics.WorldEvidence` and validators that reject +semantic traces that cannot be a retail PView/DrawCells execution. The schema is +currently unshipped version 4. Do not add a compatibility path for an older +in-progress v4 shape; finish this version atomically unless persisted external +artifacts are discovered. + +The third fix round changed only: + +- `src/AcDream.Core/Diagnostics/WorldEvidence/WorldEvidenceModels.cs` +- `src/AcDream.Core/Diagnostics/WorldEvidence/WorldEvidenceJsonl.Vocabulary.cs` +- `src/AcDream.Core/Diagnostics/WorldEvidence/WorldEvidenceJsonl.TranscriptShapes.cs` +- `src/AcDream.Core/Diagnostics/WorldEvidence/WorldEvidenceJsonl.cs` +- `src/AcDream.Core/Diagnostics/WorldEvidence/WorldEvidenceJsonl.PViewGrammar.cs` +- `tests/AcDream.Core.Tests/Diagnostics/WorldEvidence/WorldEvidenceJsonlTests.cs` +- `tests/AcDream.Core.Tests/Diagnostics/WorldEvidence/WorldEvidenceT3Tests.cs` + +The wider uncommitted OH1 evidence scope also includes: + +- `src/AcDream.Core/Diagnostics/WorldEvidence/` +- `src/AcDream.App/Rendering/Walk/Diagnostics/` +- `tests/AcDream.Core.Tests/Diagnostics/WorldEvidence/` +- `tests/AcDream.App.Tests/Rendering/Walk/LegacyWalkOracleImporter.cs` +- `tests/AcDream.App.Tests/Rendering/Walk/LegacyWalkOracleImporterTests.cs` +- `tests/AcDream.App.Tests/Rendering/Walk/WorldFrameTranscriptRecorderTests.cs` +- `tools/A8CellAudit/GeometryManifestCommand.cs` +- `docs/research/2026-09-01-overhaul/oh1-world-evidence-tooling.md` + +### 5.2 What round three closed + +The third round closed these previously falsifiable gaps: + +- route-stage truthfulness; +- distinct source/destination/outside/temporary ViewSet ownership; +- exact previous/current installed-view identity; +- caller-owned restore after `OtherPortalClip`; +- `CellView`/`AddView` state replay and exact append/count ledgers; +- `SetOtherSeen` ordering after branch, recursion, and watermark; +- stronger exact call-body, direct-parent, and grouping validation; +- actual failed-tail-pop evidence for `NullTail`; +- persistent global device, cell-shell, and typed-part stamp ledgers; +- reject-then-accept and all-reject stamp cases; +- global `Render::PortalList` bindings for `ClipPortals` and object-cell turns; +- exact `Render::copy_view(newmethod=1)` algorithm replay rather than checking + only caller-supplied output bytes; and +- deletion of stale `PortalVisit`/legacy `PartAdmit` vocabulary. + +This round exists because earlier green versions were independently shown to +be false oracles. Review caught inverted portal-flag and sidedness meanings, +conflated `do_clip`/side state, restore ownership assigned to the wrong +function, conflated view containers, incomplete call/cardinality ledgers, +self-fulfilling `copy_view` tests, and wrong draw-call ownership. Do not close +T3 merely because 153 tests pass. + +### 5.3 Retail truths already bound by T3 + +These are not optional interpretations: + +- `portal_info` has raw signed `seen` and `inflag`; a clip candidate is + `seen != 0 && inflag != 1`. +- Retail sidedness is `POSITIVE = 0`, `NEGATIVE = 1`. +- `InitCell` treats `inflag = 0` as a candidate and `inflag = 1` as excluded/ + backlink; `max_indist` is computed from final `inflag == 1` vertices. +- Todo storage is farthest at the front and nearest at the tail; tail pop is + nearest-first; equal keys preserve FIFO order. +- `ClipPortals` is two-pass: pass one resolves/liveness globally. If any portal + is live, pass two evaluates every source view against every flag candidate, + including unresolved candidates. +- `OtherPortalClip` resets one function-static temporary view set each epoch. + Its first copy may reject. Its far clip always uses `do_clip = 1`; the far + side is derived separately as + `far.portal_side == POSITIVE ? NEGATIVE : POSITIVE`. +- `ClipPortals`, not `OtherPortalClip`, restores the source view after the + helper returns, including rejection and far-zero paths. +- Source CellView, destination CellView, PView outside view, and the one static + reciprocal temporary view are separate containers. +- `AddToCell` installs every newly appended view unconditionally. +- `SetOtherSeen` occurs only after the completed branch/recursion/watermark. +- `FixCellList` always calls `AdjustCellPlace` and then `AdjustCellView`; the + list move itself remains conditional. +- `DrawCells` draws shells first and objects second, in reverse cell order; + views are ascending. A null `drawing_bsp` skips only that cell's shell. +- The object chain is + `DrawObjCellForDummies → insertion_sort → DrawObjCell → DrawPartCell →` + `CShadowPart::Draw → CPhysicsPart::Draw → DrawMesh`. +- Built EnvCell shells and built parts submit whole after Boolean admission; + portal polygons, not arbitrary built meshes, are polygon-clipped. +- Device, cell-shell, and part stamps persist. The first ordinary accepted + view stamps/draws and later views suppress; force/local-player paths bypass + the ordinary inner stamp behavior. + +## 6. Automated state at handoff + +All results below are from the frozen uncommitted tree. + +| Gate | Result | Provenance | +|---|---|---| +| T3 focused cases | **54/54 passed** | Final third-round agent run | +| Core WorldEvidence aggregate | **153/153 passed** | Final third-round agent run | +| Core Release build | **PASS, 0 warnings / 0 errors** | Final third-round agent run | +| App legacy importer + recorder compatibility | **46/46 passed** | Handoff verification run after the Core freeze | +| Complete solution Release build | **PASS, 0 warnings / 0 errors** | Handoff verification run after the Core freeze | +| Trailing whitespace | **clean** | Final third-round agent run | +| Dead T3 vocabulary grep | **clean** | Only the intentional test asserting `PartAdmit` is absent remains | + +The complete solution **test suite was not rerun** after the third T3 round. +No tests are known red. The older OH0 baseline (319 focused passes / 1 skip) +and the tooling note's pre-T2 counts are historical provenance, not current OH1 +closure evidence. + +Reproduction commands from the worktree root: + +```powershell +dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj -c Release --no-restore --filter "FullyQualifiedName~Diagnostics.WorldEvidence.WorldEvidenceJsonlTests" + +dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Release --no-restore --filter "FullyQualifiedName~WorldFrameTranscriptRecorderTests|FullyQualifiedName~LegacyWalkOracleImporterTests" + +dotnet build AcDream.slnx -c Release --no-restore --nologo + +git diff --check +``` + +## 7. Known open T3 review surface + +T3 is not review-closed until these are either implemented and tested or +explicitly disproved as required by the retail sources: + +1. Add a dedicated same-typed-part-across-two-cells persistent-stamp fixture. +2. Add an outside-`DrawCells` `PortalListBind` positive/completeness fixture. +3. Add explicit `copy_view` adversarials for every numerical boundary: + - exactly one pixel and just over one pixel; + - every wrap-prune branch; + - the 32-plane cap; + - negative zero; + - second append/pool reset; and + - normalization epsilon. +4. Decide under retail and architecture review whether call boundaries require + a typed `PViewCallContext`. Exact identities currently come from owned + semantic rows. Do not add the type merely for aesthetics, and do not reject + it merely to avoid a schema edit. +5. Decide whether `NullTail`'s current + `TailPopAttempted = true` + `TailPointerPresent = false` is sufficiently + exact, or whether retail evidence requires a standalone nullable-pop event. +6. Run a fresh independent retail-faithfulness review and a separate + architecture/false-oracle review. The reviewer must try coordinated + omissions/relabels, not only single-field mutations. + +No owner/client gate is needed for T3 unless static retail sources genuinely +lack one fact. If an owner capture becomes necessary, request one exact pose, +action, duration, and expected trace. Do not ask the owner to explore visually. + +## 8. Dirty-tree map + +At the freeze, `git status --short` reports no staged files. The principal +groups are: + +### Preserved pre-overhaul behavior candidates — do not attribute to T3 + +- App composition/rendering changes in `FrameRootComposition`, + `ParticleRenderer`, `RetailAlphaQueue`, `RetailPViewPassExecutor*`, + `RetailPViewRenderer`, `OrderedDrawStream`, `WalkFrameDriver`, + `WalkStaticStreamPopulator`, `WbDrawDispatcher*`, and + `WorldSceneRenderer`; +- associated App walk/alpha/PView/runtime-option tests; +- `docs/launch-options.md`; and +- A8 audit project/lock-file changes. + +Their detailed semantic classification and risk level are in +`oh0-baseline.md`. They include geometry recipe, lighting, depth-state, +exit-seal, membership, built-mesh, part-stamp, shell-stamp, and diagnostic +candidates. None is accepted simply because it remains in the tree. + +### OH1 evidence work + +- Core `Diagnostics/WorldEvidence` models, codec, grammar, and tests; +- App transcript recorder and narrow legacy oracle importer/tests; +- the synthetic A8 geometry-manifest command boundary; +- launch-option documentation for output-only evidence; and +- the active tooling note and corrected flood appendix. + +### Known non-semantic noise to exclude from narrow commits + +The following were classified as CRLF-only in OH0: + +- `src/AcDream.App/Rendering/Scene/RenderProjectionRecordFactory.cs` +- `src/AcDream.App/Rendering/Scene/RenderSceneContracts.cs` +- `src/AcDream.Core/Physics/ShadowPartBox.cs` +- `src/AcDream.Core/World/MeshRef.cs` +- `src/AcDream.Core/World/WorldEntity.cs` + +`src/AcDream.App/Streaming/LandblockBuildFactory.cs` was blank-line-only. +Recheck with `git diff --ignore-space-at-eol -- ` before assuming any of +these has gained semantic content. + +## 9. Next safe execution sequence + +1. Confirm `HEAD`, branch, and `git status --short`; do not clean the tree. +2. Read the documents in section 3, especially OH0 and the active tooling note. +3. Review the seven round-three T3 files as one closed grammar change. +4. Implement the bounded adversarial fixtures in section 7 without changing + production rendering or loosening the canonical schema. +5. Run the 153-test WorldEvidence aggregate, the 46-test App compatibility + gate, `git diff --check`, and the complete Release solution build. +6. Obtain independent retail-faithfulness and architecture/false-oracle + reviews. Fix findings and rerun the same gates. +7. Update `oh1-world-evidence-tooling.md` and the campaign execution ledger. +8. Stage only the reviewed T3/OH1 paths. Preserve the OH0-classified App + behavior candidates and line-ending noise. Commit T3 only after review + closure; record the commit in the checkpoint ledger. +9. Complete OH1 T4–T8 from the plan: landscape/building interleave, + alpha/material evidence, depth lifecycle, recorder/fixture integration, + and final no-production-change gates/reviews. +10. Mark OH1 closed only when all planned evidence families are executable and + the narrow FW0 importer is still truthfully narrow. +11. Then begin OH2 implementation from the already committed CellStruct + contract. OH2 owns the production descriptor, package version/migration, + installed-DAT manifest generation, two-run determinism gate, review, and G1. + +Do not jump directly to cathedral symptom fixes. The first production behavior +change belongs to OH2 after OH1 closes. Preserve the campaign's Plan → +Implement → Review rhythm and combine owner gates according to the stage table; +do not launch a client after every code edit. + +## 10. Copy-paste prompt for the next model + +```text +Take over Campaign OVERHAUL in the EXISTING worktree: +C:\Users\erikn\source\repos\acdream\.claude\worktrees\peaceful-blackburn-5333f0 + +Branch: claude/campaign-w-retail-frame-walk +Frozen HEAD: 5d907ae9ad9462347eb697c39ae3ffac136a40bc + +Do not use the main checkout. Do not create or copy another worktree over this +one. The tree is intentionally dirty and has no staged files. Never run reset +--hard, checkout --, or clean. The recovery anchor is b3b7d922. + +First read, in order: +1. AGENTS.md +2. docs/architecture/acdream-architecture.md +3. docs/architecture/worldbuilder-inventory.md +4. docs/research/2026-09-01-overhaul/2026-09-02-campaign-overhaul-handoff.md +5. docs/plans/2026-09-01-campaign-overhaul-world-solidity.md +6. docs/research/2026-09-01-overhaul/oh0-baseline.md +7. docs/research/2026-09-01-overhaul/oh1-retail-world-contract.md +8. all four supporting OH1 contract packets +9. docs/research/2026-09-01-overhaul/oh1-world-evidence-tooling.md +10. docs/research/2026-09-01-overhaul/oh2-cellstruct-surface-contract.md +11. docs/research/2026-08-30-fw-flood-pseudocode-appendix.md + +Current truth: OH0 is closed. OH1 research and T0-T2 are closed. OH1/T3's third +implementation round is uncommitted and locally green (54/54 T3, 153/153 Core +WorldEvidence, 46/46 App importer/recorder, complete Release build 0 warnings/ +errors), but T3 is NOT independently review-closed. OH1/T4-T8 and every +production slice OH2-OH11 remain pending. OH2 design exists at 5cd4fd2c, but +OH2 implementation must not start until OH1 closes. + +Your first work is to inspect—not rewrite—the frozen T3 grammar and close the +explicit review gaps listed in handoff section 7: same-part-across-two-cells +stamps, outside-DrawCells PortalListBind, all copy_view numerical adversarials, +and evidence-based decisions on PViewCallContext and NullTail representation. +Then run independent retail-faithfulness and architecture/false-oracle reviews, +fix findings, rerun the recorded gates, update both ledgers, and commit only the +narrow reviewed T3 scope. + +The named retail pseudo-C and retail headers are the behavior oracle. Grep by +class::method first. Use Ghidra to arbitrate ambiguous branch sense. Do not +invent an approximation and do not make production draw decisions in OH1. +Do not infer render content from aggregate owner IDs; trace identities to DAT. + +No owner/client gate is currently needed. If a static fact genuinely cannot be +recovered, ask for one precise capture with an exact pose/action/duration and +expected trace. The user normally closes a running client; never kill it unless +the user explicitly authorizes control. +``` + +## 11. Handoff stop condition + +At this freeze all previous subagents are complete and no agent should be +assumed to be editing the tree. The next model owns the next mutation. Before +changing anything, compare live `git status` and `git diff` with this document; +newer filesystem state always needs explicit classification rather than being +silently folded into T3.