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 02b8ee99..e3f94fac 100644 --- a/docs/plans/2026-09-01-campaign-overhaul-world-solidity.md +++ b/docs/plans/2026-09-01-campaign-overhaul-world-solidity.md @@ -674,7 +674,7 @@ Update immediately when a slice changes state. Chat is not the ledger. | S1 | `acf17246`, `b681717c`, `0840d5fb`, `e2543d0e`, `8c6563ca` (+ pin test) | G1 PASS 2026-09-02 | revert newest-first; then restore `acdream.recipe7.pak` over `acdream.pak` in the dev DAT dir (the recipe-8 consumer rejects a recipe-7 pak, and vice versa) | | S2 | `059b8883`, `5a2792d6`, `707d2803`, `afbd2410`, `75ea269d`, `c94a1a40`, `f6b4584b` | G2 PASSED 2026-09-03 (owner-confirmed after the chunk-6 haze fix; terrain punch carried to S4) | revert newest-first `c94a1a40` → `059b8883`; the registry's retail product and the walk's borrowed views go together — do not revert a middle chunk alone | | S3 | chunk 2: `be9b4c1f`, `2f5373c7`, `434a7df2`; chunk 3: `4ee2866a`, `651badc2`, `e10765aa`, `896c63fe`, `74ac7aa2`; chunk 1: `02a82881`, `be81475c`, `88c70072` | G3 | chunk 3: revert newest-first `74ac7aa2` → `4ee2866a` as one unit (the per-cell terrain, the slot key, the deferred batching and the per-frame diagnostic go together); chunk 2: revert newest-first `434a7df2` → `be9b4c1f` (the counter, the leaf split and the flag deletion go together) | -| S4 | — | G3 | OPEN 2026-09-03 night. Packet `docs/research/2026-09-01-overhaul/s4-depth-alpha-packet.md`: §1 records that S3 chunk 2 already delivered S4's chunk-1 latch/gate/seal scope (the latch owner, the gated flush→stamp→clear→seal block, the counted seals); what remains of chunk 1 is small and dispatched as **S4-c1** (`s4-c1.js`, worktree `s4-c1-impl` at `6385f4411`, contract = packet §6): C0 the far-punch constant — `portal_depth.vert` carries `0.99999988` = bits `0x3F7FFFFE`, retail's is `0x3F7FFFEF` (15 ULPs nearer; the depth spec's "wrong constant" row was right; lead bit check 2026-09-03) → retail's exact bits + a source pin; C1 the ±12 local-input reject at both portal-polygon producers (Ghidra table row 0x59BCD6–0x59BD28); C2 the portal-depth color-state register row (ColorWrite off vs retail's zero-alpha blend, identical output); C3 the depth truth-table Theory, the cross-frame latch test, look-ins isolated from the root latch. Chunk 2 = the two-FIFO alpha-list cutover (packet §3); chunk 3 = deletions (packet §4). G3 is S4's owner gate; the lead's S3-state G3 pre-run (20/20 frames, in the S3 row) is the baseline to diff against. | **S4-c1 ROUND 0 = `c7ab5b6d8` (Sonnet), THREE LENSES FAIL (2026-09-03 21:00–21:20):** one BLOCKING defect seen by all three — the ±12 guard's quantifier is inverted (rejects on ANY vertex on ANY plane; retail's PDB-paired bytes at 0x59BCD6–0x59BD66 reject only when EVERY vertex lies on the SAME plane) — and the LEAD's §6 paraphrase carried the same inversion (corrected in §6; lesson saved to memory: quote the decomp predicate, never paraphrase it). The production lens's DAT scan: 2,889 portal polygons carry a ±12 vertex and 2,163 EXIT polygons lie ENTIRELY on a ±12 plane — so the guard is very likely retail's never-sealed 'panel' mechanism (the #456/#465 family), which makes the PM/PC depth-event transcript comparison against the four alphadepth captures the chunk's real gate (never run in round 0). Also: the register-test gate is vacuous (no test reads the register), the manifest comment's ULP direction is inverted. C0 (retail's exact far-punch bits, verified at the binary), C2 (AD-119) and C3 (three new truth-table/latch pins, nine mutation texts) verified. FIX ROUND 1 = S4 packet §7 (`s4-c1-fix1.js`, dispatched 21:20): the four per-plane predicates at both producers with five-case T2, the seal count order, the automated PM/PC gate over the captures (a diverging pose is tagged KnownFailure and written up, never weakened), comment truth. +| S4 | — | G3 | OPEN 2026-09-03 night. Packet `docs/research/2026-09-01-overhaul/s4-depth-alpha-packet.md`: §1 records that S3 chunk 2 already delivered S4's chunk-1 latch/gate/seal scope (the latch owner, the gated flush→stamp→clear→seal block, the counted seals); what remains of chunk 1 is small and dispatched as **S4-c1** (`s4-c1.js`, worktree `s4-c1-impl` at `6385f4411`, contract = packet §6): C0 the far-punch constant — `portal_depth.vert` carries `0.99999988` = bits `0x3F7FFFFE`, retail's is `0x3F7FFFEF` (15 ULPs nearer; the depth spec's "wrong constant" row was right; lead bit check 2026-09-03) → retail's exact bits + a source pin; C1 the ±12 local-input reject at both portal-polygon producers (Ghidra table row 0x59BCD6–0x59BD28); C2 the portal-depth color-state register row (ColorWrite off vs retail's zero-alpha blend, identical output); C3 the depth truth-table Theory, the cross-frame latch test, look-ins isolated from the root latch. Chunk 2 = the two-FIFO alpha-list cutover (packet §3); chunk 3 = deletions (packet §4). G3 is S4's owner gate; the lead's S3-state G3 pre-run (20/20 frames, in the S3 row) is the baseline to diff against. | **S4-c1 ROUND 0 = `c7ab5b6d8` (Sonnet), THREE LENSES FAIL (2026-09-03 21:00–21:20):** one BLOCKING defect seen by all three — the ±12 guard's quantifier is inverted (rejects on ANY vertex on ANY plane; retail's PDB-paired bytes at 0x59BCD6–0x59BD66 reject only when EVERY vertex lies on the SAME plane) — and the LEAD's §6 paraphrase carried the same inversion (corrected in §6; lesson saved to memory: quote the decomp predicate, never paraphrase it). The production lens's DAT scan: 2,889 portal polygons carry a ±12 vertex and 2,163 EXIT polygons lie ENTIRELY on a ±12 plane — so the guard is very likely retail's never-sealed 'panel' mechanism (the #456/#465 family), which makes the PM/PC depth-event transcript comparison against the four alphadepth captures the chunk's real gate (never run in round 0). Also: the register-test gate is vacuous (no test reads the register), the manifest comment's ULP direction is inverted. C0 (retail's exact far-punch bits, verified at the binary), C2 (AD-119) and C3 (three new truth-table/latch pins, nine mutation texts) verified. FIX ROUND 1 = S4 packet §7 (`s4-c1-fix1.js`, dispatched 21:20): the four per-plane predicates at both producers with five-case T2, the seal count order, the automated PM/PC gate over the captures (a diverging pose is tagged KnownFailure and written up, never weakened), comment truth. **S4-c2 CONTRACT DRAFTED** (packet §8, 2026-09-03 21:50): two FIFO lists of 3000, the spec §4 router as one pure function, the four flush sites (the sort-cell EXIT valve as a new walk event kind), `FlushFartherThan`/AP-34/every viewer distance deleted, and the AM/FL transcript gate over the five captures (10,556 `AM` lines, all `clip=0`; `FL` by site 13,705/309/18/23) as the proof; dispatched only after c1 lands. | S5 | — | G4 | fill | --- diff --git a/docs/research/2026-09-01-overhaul/s4-depth-alpha-packet.md b/docs/research/2026-09-01-overhaul/s4-depth-alpha-packet.md index 89d9dc2a..ba14013b 100644 --- a/docs/research/2026-09-01-overhaul/s4-depth-alpha-packet.md +++ b/docs/research/2026-09-01-overhaul/s4-depth-alpha-packet.md @@ -327,3 +327,114 @@ the oracle for that pose). `surf`/`csurf` the raw surface type and material), and `FL` lines mark every flush (terrace-edge: 3,515 `FL` lines over its frames), so the chunk-2 transcript compares per list and per flush site, not merged. + +## 8. S4-c2 contract (lead draft, 2026-09-03 night — dispatch after S4-c1 lands on the campaign branch; re-locate every owner at dispatch) + +**Scope (ONE production behavior change):** replace the single distance-sorted +`RetailAlphaQueue` with retail's two append-order lists, route every delayed +subset by the exact `DrawMesh` branch table, and flush at retail's four +normal-world sites under retail's threshold rule. No evidence infrastructure +beyond the transcript gate this chunk consumes (G-c2 below). + +**Capture profile the contract rests on (the five `*.alphadepth.log` files, +counted 2026-09-03):** 10,556 `AM` lines, every one `clip=0` (so retail's +`MultiPassAlpha` row 2 never fired live — default false, spec §3); `listSel` +0 = 6,330 lines, 1 = 4,183 (two lists, both live); `FL` lines by return +address: `005a1a0c` (DrawBlock 0.75) 13,705, `0059f310` (DrawBuilding 0f) +309, `005a4877` (PView::DrawCells 0f) 18, `00453b90` (RenderNormalMode 0f) +23; `new=1` 9,685 / `new=0` 871 (the first-for-list flag is mostly set — +most DrawMesh invocations append one subset per list). + +**Retail facts the implementer verifies at the decomp BEFORE writing (quote +the predicate, never paraphrase — `feedback_quote_decomp_predicates`):** + +1. `D3DPolyRender::AddMeshToAlphaList` @0x0059C230 — append only, two + static arrays of 3000 entries and two uint16 counts, returns false at + capacity (spec §5). Identify which `listSel` value is CLIP and which is + ALPHA from the bytes (the capture's `listSel` is the raw byte at + `@esp+0x18`), and record it in the code comment. +2. `D3DPolyRender::FlushAlphaList(threshold)` @0x0059D2E0 — the early + return fires only when BOTH counts are under `threshold × 3000`; quote + the comparison (strict `<` or `<=`) from the bytes and pin the boundary + count the bytes give (spec §5 says equality at 2250 drains); drain CLIP + fully, then ALPHA fully, in append order; reset both counts; restore the + object matrix, not the material. +3. `DrawMesh` branch table = spec §4 rows 1–5 verbatim; delay mask + `s_AlphaDelayMask` @0x00820D88 default `0x0E`; `MultiPassAlpha` + @0x0081EF96 default false; the constructed subset mask = spec §2 + (surface type bits `0x00010300` → `0x02`, `0x04` → `0x08`, `0x10` → + `0x04`, else `0x00`; OR `0x01` when the polygon's signed stippling byte + is > 0). +4. The four normal-world flush sites (spec §7) — confirm each capture + return address above lies inside the named function in + `docs/research/named-retail/symbols.json`. + +**C1 — two lists.** `RetailAlphaQueue` becomes two FIFO records, CLIP and +ALPHA, capacity 3000 each. Entry = (source, token, list, overrideClipmap, +first-for-list). NO distance field; `Submit` takes the list and the +override flag, never a viewer distance. Append at capacity returns false +and the subset is DROPPED (no immediate fallback) — pinned. Keep the +`IRetailAlphaDrawSource` protocol (`PrepareAlphaDraws` once per drain with +the tokens in list order, CLIP then ALPHA; only adjacent same-source +entries form a batch — the "never group across another entry" invariant +stays, it is what keeps compositing exact). + +**C2 — flush semantics and sites.** `Flush(threshold)` implements fact 2. +Sites: `AlphaBarrier` (DrawBuilding) → `0f`; NEW leaf event at the +sort-cell EXIT — its own `WalkFrameEventKind`, recorded after +`OnLandscapeCellTurn` (the object turn) and before the next cell's land +turn (packet §5 SETTLED) → `0.75f`; `LandscapeFlush` (PView::DrawCells) → +`0f`; pass end (RenderNormalMode) → `0f`. `FlushFartherThan` deleted; +AP-34 retired in the same commit; every `viewerDistance` argument on the +submit path and `RetailAlphaOrdering.ComputeViewerDistance` (with its +test) deleted — chunk 3's deletion list shrinks accordingly. + +**C3 — routing.** Both `WbDrawDispatcher` submit sites +(`SubmitWalkAlphaInstance`, `DeferTransparentGroups`) and +`ParticleRenderer`'s site route through ONE pure router implementing spec +§4 with these inputs: currently-drawing-sky (true only inside the `Sky` +leaf — weather emitters draw immediately there; `*.parts.log` is the +oracle for which emitters ever appear immediate), the delay mask (one +owner, default `0x0E`, no environment read), detail-surface presence (the +active detail owner from VisualMaster), `MultiPassAlpha` (one owner, +false), the spec §2 constructed mask from the DAT surface type and the +polygon's stippling, and the material's `has_alpha`. Row 1 draws never +touch a list. Truth-table test over every (mask `0x00`–`0x09`) × delay +`0x0E` × sky × detail × multipass × has_alpha cell in spec §4, each row +with a mutation text. + +**C4 — transparent EnvCell subsets** go through the same router (spec §6: +the environment detail surface makes eligible subsets immediate). + +**C5 — register.** AP-34 deleted; any row describing the distance sort +deleted; retail's non-restored material after a flush is a no-op under +Vulkan's per-batch material binding — a code comment at the drain, not a +row, unless the implementer can argue a visible effect. + +**Must NOT:** keep any distance anywhere on the alpha path; "recover" a +capacity overflow; touch S4-c1's punch/seal machinery; add flush sites +beyond the four; read an environment variable for the delay mask. + +**Tests (each with a mutation text showing the pin fails without the +change — `feedback_every_new_pin_must_be_shown_to_fail`):** FIFO beats +reversed distance in one cell; 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; the `0.75` +valve exactly at the boundary count from fact 2 (and one below it: no-op); +alternating blend modes across Vulkan batches; capacity 3000 overflow +drops the subset; the router truth table; the new event kind's ordering. + +**Gate G-c2 (the chunk's real proof):** extend S4-c1's automated alphadepth +transcript gate from PM/PC to AM/FL — per capture frame, the sequence of +(flush site, threshold) and, per flush, the drained entry count PER LIST +must match the capture's AM/FL stream; a diverging pose is tagged +KnownFailure with a written explanation, never weakened. Then the walk/ +depth/alpha suites, Release build, the validation self-gate at the S3-closed +poses diffed against the S3-closed run, and a stationary-phase soak A/B +against the S4-c1 binary (removing the sort must not regress; #463's +turn-phase rule). + +**Lenses:** one Sonnet implementer; two sequential review lenses on the +session model (retail-faithful — every predicate quoted; production — +allocation, the scratch budget, the gate's honesty); each lens returns +PASS/FAIL with file:line findings; two fix rounds maximum, then the ledger.