acdream/docs/research/2026-09-01-overhaul/s4-depth-alpha-packet.md

132 KiB
Raw Blame History

S4 packet — depth and alpha: what S3 already delivered, what remains (lead draft, 2026-09-03 evening)

Status: DRAFT written while the S3 post-hoc lenses ran; NOT dispatchable until the S3 review closes (plan §9 order: S3 review → G3 → S4). Every owner named below is re-located at chunk time; names, not line numbers.

Specs: oh1-depth-lifecycle.md, oh1-alpha-list-contract.md; the plan's §9 S4 section; the §7 alpha/depth captures under oh-capture/ (*.alphadepth.log, line formats in tools/walk-oracle/oh/oh-capture-alphadepth.cdb.template).

1. What S3 already delivered of S4's chunk 1

S3 chunk 2 (§8 of the S3 packet, landed be9b4c1f + 434a7df2) implemented the S4 chunk-1 scope almost whole, because the walk could not be exact without it:

S4 chunk-1 item (plan §9) State after S3 Where
one frame-persistent latch owner for portalsDrawnCount DONE — WalkFrameDriver.PortalsDrawnCount, retained across frames, never cleared by Begin/Abort/EndFrame S3 §8.2 B2
landscape → flush → stamp → clear → seal block gated exactly as retail (outside_view.view_count > 0) DONE — OnInteriorFloodDrawTurn(cells, outsideViewCount); LandscapeFlush leaf; stamp advance; clear ONLY IF count ≠ 0 (read-then-zero); seals S3 §8.2 B1/B3
WalkFrameDriver's unconditional interior clear deleted DONE S3 §8.2 B1
mid-frame stamp placed exactly (0x005a4886) DONE (AdvanceWalkPartPassStamp at the flush leaf) S3 §8.2 B1
exit seals from the exact current views and cell order, counted by the seal leaf's return value DONE — DrawExitSeals returns the submitted count; punch fans never count S3 §8.2 B2
look-ins cannot touch the root latch DONE (look-in DrawCells never increments) S3 §8.2 B2
truth-table tests over root kind / draw_landscape / outside-view count / previous-current portal count PARTIAL — the chunk-2 tests flipped the two wrong contracts (§8.3); the full truth table and the two-consecutive-frames latch test are NOT yet one theory S4-c1 below

The depth-lifecycle spec's "Current acdream correspondence" table (its rows marked missing / wrong for the counter, the gate and the test contracts) is therefore stale for those rows; the rows that still stand are the three below.

2. What remains for S4 chunk 1 (S4-c1, small)

  • Far-punch depth constant. Retail writes the far-Z punch at the exact bits 0x3F7FFFEF; portal_depth.vert uses the decimal 0.99999988. The chunk decides by TEST, not by eye: a pin that reinterprets 0.99999988f and asserts BitConverter.SingleToInt32Bits == 0x3F7FFFEF; if they differ, the shader takes the hex literal (uintBitsToFloat(0x3F7FFFEFu)) and the manifest hash is re-pinned. (1 2⁻²³ is the expected identity; prove it.)
  • The ±12 local-input reject. Ghidra arbitration (S3 packet §2, the "±12 test is an equality degenerate guard") says the check rejects a whole polygon whose local x/y equals ±12 exactly — a degenerate-input guard, not a clip rule. Port it at the punch-event producer as an equality test on the LOCAL polygon before transform, with a test that feeds one exact ±12 vertex polygon and one at ±11.999 (only the first is rejected). If the arbitration table shows the branch can never fire for a real DAT polygon, record that as the reason to skip and cite the table.
  • Seal/punch color state. Retail's portal-depth draws keep color writes ENABLED with SRCALPHA/INVSRCALPHA and source alpha 0 (a no-op blend); acdream sets ColorWrite=false. Pixel-identical by construction; the chunk adds the register row (AD-nnn: "portal-depth color path: write-mask off instead of a zero-alpha blend — identical output, different state") OR ports the exact state if the Vulkan pipeline already carries the blend attachment; the reviewer decides which is cheaper to keep honest.
  • Truth table + two-frame latch test (plan §9 S4 tests): one theory in WalkFrameDriverTests over (root kind, draw_landscape, outside-view count, previous count) → the exact event subsequence (LFLUSH, stamp, CLEAR?, SEALS?), plus the consecutive-frames case proving the latch crosses frames, plus "multiple look-ins isolated from the root".

3. S4 chunk 2 — the alpha lists (the slice's body)

Current state (verified 2026-09-03 at 7df0b94c9): RetailAlphaQueue is ONE scope-global list sorted by viewer distance at flush (SortRetailOrder in Flush / FlushFartherThan); submitters: WbDrawDispatcher (two queue.Submit sites: the packed path and the walk classify path with viewerDistance) and ParticleRenderer (one site). Barriers: IWalkFrameLeafRenderer.AlphaBarrierFlushLandscapeAlpha_alpha.Flush() at the building turn (retail DrawBuilding's FlushAlphaList(0f)), the LandscapeFlush leaf (retail PView::DrawCells's FlushAlphaList(0f) @0x005a4872), and two RetailPViewRenderer end-of-pass calls (the top-level SmartBox::RenderNormalMode flush). FlushFartherThan (the pre-punch "drain the farther content" approximation) is the AP-34 row.

Retail (spec §5§7, verified against the decomp at chunk time): two independent FIFO lists (CLIP and ALPHA) of 3000 AlphaListEntry each; AddMeshToAlphaList appends, never sorts; each DrawMesh invocation owns a first-for-this-list flag that captures material + object matrix for the list's replay; FlushAlphaList(threshold) is a no-op only when BOTH counts are below threshold × 3000, otherwise drains CLIP then ALPHA in append order, resets both, restores the object matrix, does NOT restore the material; capacity overflow = append returns false and the delayed subset is NOT drawn; DrawBlock calls FlushAlphaList(0.75) per land cell (the pressure valve — inert below 2250 entries).

Behavior change (chunk contract to be written after the S3 review):

  1. Replace the sorted single queue with two FIFO records mirroring the retail entry (source token, first-for-list material/matrix capture, overrideClipmap, list id) — no distance field, no sort.
  2. Route every submitter to the exact list by the retail DrawMesh branch table (spec §4): CLIP for the multipass clip-map delayed duplicate, ALPHA for delayed subsets; sky/detail immediate gates; material has_alpha fallback.
  3. Flush sites exactly: DrawBuilding 0f (the existing AlphaBarrier), DrawBlock 0.75 per land cell (NEW — a threshold flush at the SC turn; inert at today's counts, pinned by a capacity test), PView::DrawCells 0f (the existing LandscapeFlush), top-level 0f (the existing pass-end flush). Delete FlushFartherThan and retire AP-34.
  4. Capacity 3000 per list with the exact overflow behavior (append false, subset dropped) — pinned, not "expanded or recovered".
  5. Transparent EnvCell subsets routed to their retail list (spec §6: the environment detail surface makes eligible subsets immediate).

Tests (plan §9 S4): multiple translucent objects in one cell with reversed distance vs insertion order (FIFO wins); 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 partial flush at exactly 2250; alternating blend modes across Vulkan batches; capacity 3000 overflow drops the subset.

Gate: the alpha/depth transcripts exact against the §7 captures (*.alphadepth.logAM add-mesh, FL flush, PM portal mask lines), the walk/depth/alpha suites, Release build; then the owner's G3 (S4's owner gate per the plan) — the lead's S3-state G3 pre-run of 2026-09-03 (20/20 frames) is the baseline to diff against.

4. S4 chunk 3 — deletions

Delete the obsolete stencil/bias/skip paths and the CYpt sort once chunk 2's transcript is exact: RetailAlphaOrdering.ComputeViewerDistance and every viewerDistance argument on the submit path; any remaining FlushFartherThan consumer; the #117/#129 bias remnants the S1 hygiene already removed from portal_depth.vert (verify nothing else carries them). Register: AP-34 retired; any row describing the distance sort retired; the seal/punch color-state row from S4-c1 kept or retired per its decision.

6. S4-c1 contract (lead draft, 2026-09-03 evening — dispatch after the S3 review closes; re-locate every owner)

Retail facts (verified in the decomp / the Ghidra arbitration table of oh1-depth-lifecycle.md):

  • R1 far-Z punch: DrawPortalPolyInternal @0x0059bc90's tail writes the punch depth from the constant with bits 0x3F7FFFEF.
  • R2 the ±12 reject: 0x59BCD60x59BD28 then 0x59BD400x59BD66 compare each SOURCE vertex's LOCAL x/y against ±12 BEFORE xformStart. The QUANTIFIER (S4-c1 round-1 retail lens, 2026-09-03 night — the lead's first wording here and in T2 was inverted): retail rejects the polygon only when ALL of its local vertices lie on ONE of the four planes x=+12, x=12, y=+12, y=12 — a polygon degenerate onto a bounding plane; a polygon with merely one vertex on such a plane is drawn and counted. Four accumulating predicates, one per plane, each true only if every vertex satisfied it; return if any predicate survives (degenerate-input guard, S3 packet §2). Then 0x59BD700x59BD74: only false/true-depth SEALS increment the counter (modulo 65,536); far punches never do (already ported, S3 §8.2 B2). 0x59BDBC0x59BDBF: fewer than 3 CLIPPED vertices submit no fan (after the possible increment).
  • R3 portal-depth state: depth test ALWAYS, depth write on, no cull; color writes ENABLED with SRCALPHA/INVSRCALPHA and source alpha 0 (a no-op blend); no stencil.

Current acdream (at d0c981212):

  • portal_depth.vert:53 clipPos.z = clipPos.w * 0.99999988; — the decimal literal is 1 2⁻²³ = bits 0x3F7FFFFE; retail's constant 0x3F7FFFEF is 0.99999898672… — FIFTEEN ULPs nearer the camera (lead's bit check, 2026-09-03: SingleToInt32Bits(0.99999988f) == 0x3F7FFFFE). The depth spec's "wrong constant" row is right. C0 below fixes it; T1 pins it.
  • No ±12 reject anywhere on the punch/seal producers (WalkFrameDriver.OnPunchGeometry @ the walk's punch event; RetailPViewRenderer.DrawWalkExitPortalMasks); the clipped-count <3 gate exists as the vertices.Length < 3 early return in DrawWalkPunchFan.
  • PortalDepthMaskRenderer.Rhi.cs: GpuCompareOp.Always, depth write on, Blend = GpuBlendMode.None, ColorWrite = false — pixel-identical to R3 (a zero-alpha blend changes no color), state-different.

Behavior change (small):

  • C0 the far-punch constant: portal_depth.vert takes retail's exact bits (uintBitsToFloat(0x3F7FFFEFu), comment citing DrawPortalPolyInternal @0x0059bc90's tail), the SPIR-V is recompiled and VulkanShaderManifestTests re-pinned. Visible effect: the far punch lands 15 ULPs nearer than before — at 24-bit depth that is the difference between "at the far plane" and "one step in front of it", which is exactly the retail relationship the seals (true depth) and the interior repaint rely on; any capture pose whose PM lines show mode=1 punches is the regression check.
  • C1 the ±12 local-input reject ported at the producer that owns the LOCAL polygon (the walk's punch-event producer for punch fans; the exit-seal enumeration for seals — both read the dat portal polygon in cell-local space before the world transform), as retail's four per-plane predicates: the polygon is dropped only when EVERY source vertex lies on the same one of x=+12, x=12, y=+12, y=12 (exact equality), BEFORE any counter increment (order: reject → transform → clip → count). A polygon with one vertex on a bound is NOT rejected. If the table shows the bound can never be hit by an authored portal polygon, the port still lands (it is retail's code) with the test proving the reject fires on a synthetic all-on-one- plane polygon and NOT on a one-vertex-on-the-plane polygon.
  • C2 no state change for R3: add register row "portal-depth color path: ColorWrite=false instead of retail's zero-alpha SRCALPHA/INVSRCALPHA blend — identical output, different pipeline state" (an AD row, with the citation), unless the reviewer prefers the exact blend attachment; the lead's default is the row (zero-risk, honest).
  • C3 the truth-table theory and the two-frame latch test (§2 above).

Tests: T1 reads portal_depth.vert's punch line and asserts the literal it carries has bits 0x3F7FFFEF (a source pin — it FAILS at d0c981212, where the line reads 0.99999988 = 0x3F7FFFFE; MUTATION: any other literal); T2 ±12 reject (corrected 2026-09-03 night — the lead's first wording inverted retail's quantifier): a synthetic local polygon with EVERY vertex at x = 12 exactly (degenerate onto the plane) → no punch event and no seal, counter unchanged; the same polygon with ONE vertex at x = 12 and the rest inside → punched/sealed and counted; every vertex at x = 11.999 → punched/sealed; T3 the truth table (root kind × draw_landscape × outside-view count × previous count) → the exact event subsequence; T4 two consecutive frames prove the latch crosses frames (frame 1 seals N>0 → frame 2 clears; frame 1 seals 0 → frame 2 does not clear); T5 multiple look-ins never touch the root latch. Mutation checks for every new pin, texts inline in the commit body.

Gates: build 0 warnings; hermetic green; InstalledDat the four known; depth-event transcript unchanged at the four capture poses (the PM/PC lines of the alpha-depth captures — S4-c1 changes no event unless a ±12 polygon exists in a captured pose, in which case the transcript is the proof); the lead's four-pose self-gate with validation on (zero errors).

7. S4-c1 fix round 1 (lead, 2026-09-03 night — after the three-lens review of c7ab5b6d8; round 1 of the two the plan allows)

Verdicts. Retail lens FAIL, production lens FAIL, build lens FAIL (the same blocking quantifier; plus: the commit body's "register tests 52/52" gate is vacuous — no test in the repository reads the divergence register, so a register row is checked only by a human read; §7's gates say so and drop that filter from the claimed evidence). The BLOCKING finding is one defect seen by all three: C1's quantifier is inverted — the port rejects a polygon when ANY vertex lies on ANY ±12 plane; retail (PDB-paired bytes at VA 0x59BCD60x59BCE5: fld/fcomp 12.0/fnstsw/test ah,0x44/jnp over xor bl,bl — four accumulating per-plane flags) rejects only when EVERY vertex lies on the SAME plane. The lead's §6 paraphrase carried the same inversion and is already corrected (§6 R2/C1/T2). Consequences the lenses proved: the T2 pins lock the wrong rule in; the guard's doc claims authored polygons "essentially never" hit the bound, but the production lens's DAT scan found 2,889 portal polygons with a ±12 vertex and 2,163 EXIT polygons lying ENTIRELY on a ±12 plane; and the §6 depth-event transcript gate (PM/PC lines) was neither run nor automated — the one check that would have shown the effect on real data. Minor: the manifest re-pin comment has the ULP direction inverted and points at the wrong test class.

Why this matters beyond the round. If 2,163 exit polygons lie entirely on a bounding plane, retail never punches or seals THOSE portals — which is the "never-drawn portal polygon = panel" family the PV campaign named (#456) and very likely the mechanism behind retail's own cathedral seam leak (#465's "hole"). Porting the guard correctly therefore changes acdream's seal/punch set at many poses toward retail's; the captured PM/PC lines are the only proof that the change lands exactly, so F3 builds that comparison as this slice's own gate (S4's automated gate already requires "depth-event transcripts exact against the §7 captures").

F1 (BLOCKING) — port the quantifier retail has. Replace IsRejectedByPortalPolygonBoundaryGuard's any-vertex test with four per-plane predicates (x=+12, x=12, y=+12, y=12), each initially true and cleared by the first vertex NOT on that plane; reject iff any predicate survives all vertices (exact float equality, LOCAL coordinates, before any transform), at both producers (WalkFrameDriver.OnPunchGeometry's punch path and RetailPViewPassExecutor's seal enumeration). Rewrite the doc comment with the DAT counts (recompute them with a scratch scan over the installed DAT and cite the numbers in the commit body — the "essentially never" sentence is deleted). T2 becomes: every vertex at x=12 → rejected; one vertex at x=12, the rest inside → kept, punched/sealed, counted; every vertex at x=11.999 → kept; every vertex at y=12 → rejected; vertices split across x=12 and y=12 (none on one common plane) → kept. MUTATION: restore the any-vertex form → the "one vertex" and "split planes" cases fail; delete the guard → the all-on-plane cases fail. Rewrite the existing T2 tests and WalkFrameDriverTests.OnPunchGeometry_RejectsWholePolygonOn… to these semantics (the names say what they pin).

F2 — count order at the seal path. Retail: guard → transform → clip → count; the fan is skipped when the CLIPPED count is under 3, AFTER the counter increment (0x59BDBC0x59BDBF). RetailPViewPassExecutor's seal loop drops sub-3-vertex LOCAL polygons before the guard and before counting. Port retail's order (authored polygons always have ≥3 vertices, so this changes no real frame — pin it with a synthetic 2-vertex polygon: counted, not drawn) and note the register row AD-119's neighbour if a comment there describes the old order.

F3 — the depth-event transcript gate, automated. Parse the four oh-capture/*.alphadepth.log fixtures' PM poly=<ptr> mode=<0|1> counterBefore=<hex> and PC ov=<n> counter=<hex> fc=<0|1> lines per frame (the oh-capture-alpha-depth.cdb.template documents them) into per-frame sequences of (mode, counterBefore) and (ov, counter, fc); replay each pose's frame 2 through RetailFrameWalk/WalkFrameDriver with a recording leaf (the existing WalkTraceReplayContext + DAT builder; punch fans = mode 1 events, exit seals = mode 0 events; the driver's PortalsDrawnCount before each event = counterBefore; the interior turn's ov/count/forceClear = PC) and compare the sequences exactly. Pointers are not compared. Expect: with F1 correct, the four poses match; if a pose does not, the test prints both sequences and is tagged Status=KnownFailure with the divergence written into this section — never weakened. The oracle-side parser lives beside WalkOracleTrace (a WalkAlphaDepthTrace), the comparison beside WalkTraceConformanceTests. This is the slice's own gate, not extra infrastructure.

F4 — comment truth. VulkanShaderManifestTests.cs:80-81: 0x3F7FFFFE is FARTHER from the camera (larger z/w), and T1 is PortalDepthVert_FarPunchConstant_MatchesRetailExactBits in that same file, not in WalkVisibilityMathTests.

F5 — commit message: every mutation text verbatim (F1's four, F2's one, F3's "swap one PM mode" mutation), the DAT scan numbers and the scan method, the per-pose PM/PC match/mismatch table, Co-Authored-By last.

Gates: build 0 warnings; hermetic fully green; InstalledDat exactly the four known plus, if F3 finds a divergence, that row tagged KnownFailure and written up here; the shader and register test classes green; the lead's four-pose validation self-gate afterwards (zero validation errors; the cathedral floating-stairs frame diffed against the S3-closed gate — a changed seal set is EXPECTED to change the exterior-slab region if retail's panel family is what the guard reproduces; the owner's retail screenshot is the oracle for that pose).

5. Open questions to settle before dispatch

  • SETTLED (2026-09-03): the walk's SC turn is IWalkEventSink.OnSortCellTurn in WalkFrameDriver (today a transcript print at DrawSortCell ENTRY, fired from RetailFrameWalk.DrawLandscape); the 0.75 valve is retail's DrawBlock call AFTER DrawSortCell returns, so chunk 2 adds one leaf method at the sort-cell EXIT (a WalkFrameEventKind of its own, ordered after the cell's object turn) — not a print-site change.
  • PARTLY SETTLED (2026-09-03): ParticleRenderer submits every deferred particle draw (billboard and mesh kinds alike) to the single queue with a viewer distance (queue.Submit(_alphaSource, token, sqrt(DistanceSq))). In retail a particle is a DrawMesh like any other subset, so its list is decided by the §4 branch table on the emitter's subset mask and material (rows 3/4 → ALPHA under the default 0x0E delay mask; row 1 immediate while m_currentlyDrawingSky is set — the weather emitters). Chunk 2 routes particles through the same branch table, not a particle-specific rule; the parts capture (*.parts.log, PD/DM lines) is the oracle for which emitters ever appear as immediate draws.
  • SETTLED (2026-09-03): the alphadepth captures' AM lines carry the list selector (AM mesh=… surf=… csurf=… new=… clip=… listSel=…listSel is the list, new the first-for-list flag, clip the clip-map duplicate, 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 15 verbatim; delay mask s_AlphaDelayMask @0x00820D88 default 0x0E; MultiPassAlpha @0x0081EF96 default false; the constructed subset mask = spec §2 (surface type bits 0x000103000x02, 0x040x08, 0x100x04, 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 0x000x09) × 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.

9. S4-c1 fix round 2 (lead, 2026-09-03 23:05 — the LAST round; a third stops the chunk and writes it up)

Round 1 (2bd353234) verdicts: retail-faithful lens PASS, production lens PASS, gate-honesty lens FAIL. All findings converge on the transcript gate's terrace-edge row plus one pin gap. Fix these, nothing else:

R2-1 (blocking, gate honesty). The terrace-edge KnownFailure write-up (test doc comment and commit body) claims "the PC sequence matches exactly"; it does not — PC diverges in the same counter field (expected [(0,2,0),(0,2,0)], actual [(0,0,0),(0,0,0)]), and the PM assert throws before the PC assert runs, so the test never printed both sequences as §7 F3 required. Resolution: R2-2 below removes the divergence; whatever remains must be asserted so that BOTH sequences are always compared and printed together (collect both diffs, one assertion message), and every written claim about a sequence must be one the test actually evaluated.

R2-2 (major, both PASS lenses). The terrace-edge divergence is a harness initial-condition choice: retail's portalsDrawnCount (wo(008719b4)) is a persistent session value that the capture's FIRST PC/PM line already carries (cathedral 0, foundry 1, holtburg 2, terrace 2, cathedral-stair-arch 8). Seed WalkFrameDriver.PortalsDrawnCount from the fixture's first observed counter before the ONE replay pass (the field is settable from the test assembly), delete the two-pass "priming" replay, and re-run all poses. Expected: terrace-edge turns green with NO KnownFailure tag; every other pose stays exact by the same arithmetic the passing poses already prove. If any pose still diverges after seeding, it keeps a KnownFailure tag AND its divergence is written into THIS section (not only into a doc comment) with both sequences quoted.

R2-3 (major, retail lens). T2's five cases do not discriminate "every vertex lies on SOME plane" (per-vertex OR, AND across vertices) from retail's "every vertex lies on the SAME plane", and real DAT content exists where they disagree. Add the discriminating case to T2 and to the punch pin: a polygon whose every vertex is on a ±12 plane but not all on the same one, e.g. [(12,0,3), (0,12,3), (12,5,3)] — ADMITTED by retail's four per-plane accumulators (no accumulator survives: x+12 is cleared by vertex 2, y+12 by vertex 1). Mutation text: implementing the per-vertex-OR form rejects it (assert flips).

R2-4 (sixth pose). The campaign branch now carries docs/research/2026-09-01-overhaul/oh-capture/cathedral-stair-arch.walk.log + .alphadepth.log (commit 4f12cd06b on claude/campaign-w-retail-frame-walk; also .pmverts.log at 3a6aa7eef) — the #464 artifact pose, root 0xF4180114, seven outside views, sixteen building punches (twelve rejected by the guard on local y=12.000) and eight seals with counterBefore 0..7, steady-state counter 8. Cherry-pick those two capture commits into the impl worktree (git cherry-pick 4f12cd06b 3a6aa7eef; if either conflicts on README.md, keep both rows) and add AlphaDepthTranscript_CathedralStairArch_MatchesRetailFrame2 as a sixth Fact. The lead already ran it against 2bd353234 with the capture copied in: PASS (the seed value 8 comes from the fixture under R2-2).

R2-5 (comment truth, minor ×4). (a) RetailPViewPassExecutor.DrawPortalDepthWrite's summary still describes the retired ">=3 vertices" enumeration and DrawExitPortalMask's summary still promises the counter "always matches what reached the GPU" — both false after F2; fix the text. (b) The F2 pin's doc comment names a mutation that would NOT fail (moving submitted++ after DrawDepthFan is unobservable — void return, no throw); say so, keep only the mutation that fails (restoring the <3 pre-filter). (c) WalkVisibilityMath's doc comment states DAT-scan figures as exact facts that an independent scan does not fully reproduce; state each figure WITH its counting rule (what is counted, over which id range, how unresolvable polygons are treated) or keep only the figures both scans agree on (2,889 any-vertex / 2,163 all-on-one-plane / 100 % exits / 0 interior). (d) The commit body must not cite "register tests 52/52" as evidence — no test reads the register; register truth is the human read (no row changes; AD-119 unchanged).

Not in scope: anything under src/ beyond R2-5(a)'s comments; the seal path's test-side reproduction (accepted as-is under F3's "recording leaf" wording); the lead's punch-geometry scratch dump (stays in s4-c1-gate, never committed).

Gates (all reproduced by the lenses, none claimed vacuously): Release build 0 warnings; hermetic lane green; InstalledDat lane with ONLY the pre-existing #383 ×2, TowerAscent, #458 KnownFailure failures (terrace-edge must no longer be among them); all six transcript Facts green; the shader classes green. One commit on top of 2bd353234 in s4-c1-impl.

Lenses (sequential, session model, narrowed to the round-2 diff): retail-faithful (R2-3's predicate and R2-2's seeding argued from the bytes/decomp — the counter's persistence across frames at PView::DrawCells and the reset site), gate-honesty (every sentence in the commit body and every test doc comment is something the tests evaluate; both sequences compared together), production (no allocation/behavior change outside the test project except R2-5(a) comments).

10. S4-c2 landing (Sonnet implementer, 2026-09-04) — gate G-c2 result and open scope

C1/C2/C3/C5 landed as specified. RetailAlphaQueue is retail's own two FIFO lists (RetailAlphaEntry, capacity 3000 each, TryAppend returns false and drops the subset at capacity, Flush(site, threshold) implements the exact Ghidra-verified no-op predicate — if (clipCount < threshold*3000 && alphaCount < threshold*3000) return; — and drains CLIP fully then ALPHA fully, only adjacent same-source runs batched). RetailAlphaMeshRouter ports DrawMesh's five-row branch table and ConstructMesh's mask formula as pure functions, independently verified against a fresh 2026-09-04 Ghidra decompile of both functions plus AddMeshToAlphaList and FlushAlphaList (not just the packet's own researched spec — see the commit body for the exact quoted predicates). WbDrawDispatcher's two submit sites and ParticleRenderer's one route through the router with a shared SubmitToAlphaQueue/inline equivalent; S4-c2 fix round 1 correction (M1, blocking): the claim that "rows 1/2/4/5 are provably unreachable there" was WRONG for the particle site, which the round's own retail-faithful review lens caught as a production crash. WbDrawDispatcher's sites genuinely never reach a mask other than 0x02 (IsOpaque pre-filters both Opaque and ClipMap upstream, so row 3 always fires there — this part of the claim holds). But ParticleRenderer.TryAppendMeshDraws applies NO such pre-filter: a mesh-particle batch's TranslucencyKind.Opaque classification (mask 0x00) is a real, reachable input, hitting row 5 (Immediate) — and the throw-on-non- Append guard fired in the render loop. The fix round deleted both throws, implemented rows 1/5's immediate draw at the particle site (reusing the non-deferring DrawOrdered code, no new renderer), and derived materialHasAlpha for row 4 from CMaterial::CheckAlphaValues @0x005396a0/SetTranslucencySimple @0x005396f0's retail rule — a particle's current interpolated alpha (already carried in ColorArgb's top byte) stands in for retail's live per-instance material alpha. FlushFartherThan, RetailAlphaOrdering.ComputeViewerDistance, and every viewerDistance argument on the submit path are deleted. A NEW WalkFrameEventKind.SortCellExit / IWalkEventSink.OnSortCellExit / IWalkFrameLeafRenderer.FlushSortCellExit fires once per admitted land-block cell, immediately after that cell's OnLandscapeCellTurn and before the next cell's OnLandCellTurn — pinned by a dedicated two-block far/near ordering test in RetailFrameWalkTests.cs, mutation-checked (reordering the two calls in RetailFrameWalk.cs makes the pin fail with "SCX must immediately follow its own cell's SC").

C4 (EnvCell) — SUPERSEDED, S4-c2 fix round 1 (M6, 2026-09-04). This landing's original claim (EnvCell "deliberately NOT done," needing "a genuinely new deferred-replay abstraction") was WRONG in the same round's own two-lens review: EnvCellRenderer.RenderTransparentOrdered already replayed a cell's transparent batch on demand, so no new abstraction was needed. The fix round wired it: RetailPViewPassExecutor.SubmitOrDrawTransparentCellShell routes every real transparent subset through the SAME RetailAlphaMeshRouter table every other alpha submitter uses. Fix round 2 retains TextureBatchData.RetailSurfaceMask on each ObjectRenderBatch: canonical 0x08 reaches CLIP, 0x02 reaches ALPHA, and a mixed cell appends at most one filtered replay token per (cell,list); detail-active eligible subsets remain immediate at the cell turn. AP-34's residuals are now filed as AP-238 (EnvCell — narrowed to the per-cell-vs-per-subset token GRANULARITY only, not "never through the shared queue") and AP-239 (the mask-reconstruction gap, formerly filed as the colliding id "AP-237" — see A2/M8c below); a THIRD residual, AP-240, was filed this round for M2's separate finding: ordinary clip-mapped GfxObj/scenery/building content never reaches the CLIP list at all (WbDrawDispatcher.IsOpaque filters it out upstream). CLIP nevertheless has two genuine production feeder families: clip-mapped mesh particles and exact-mask EnvCell subsets. AP-239's own cited example (cloud GfxObj 0x01004C35) was DISPROVEN this round (M7) — its surface's alpha-family bits win in both retail's real priority and acdream's reconstruction, so it never actually diverges; a 2026-09-04 DAT scan found 27 real instances instead (e.g. surface 0x08000015 on GfxObj 0x010001EC). These residuals do not change the affected subset's blend mode, but overlap-dependent compositing order can be visibly different; AP-238/AP-240 state the concrete overlap.

Gate G-c2 result, all six poses, real InstalledDat run (RunAlphaFlushTranscriptGate, WalkTraceConformanceTests.AlphaDepthTranscript.cs): the flush SITE+THRESHOLD sequence matches the capture EXACTLY for all six poses — same count and order of DrawBuilding(0f)/LandscapeFlush(0f)/ RenderNormalMode(0f) calls, and (confirming the packet's own capture-profile prediction) zero SortCellExit(0.75f) drains in any of the six captures' frame 2 — every real per-land-cell valve call stayed under the 2250-entry no-op threshold at these scene complexities, exactly matching this gate's own zero-content replay. The drained-count-per-list dimension diverges on every 0f flush for every pose — this hermetic replay (EmptyAlphaDepthWorldData, the same zero-content design the PM/PC gate it extends already uses) submits no real GfxObj/particle content, so every observed count is (0,0) where retail's capture shows real volume. Full quoted sequences (site, threshold, clip, alpha), expected vs. actual, per pose:

  • cathedral-arrival: expected [(DrawBuilding,0,108,40), (DrawBuilding,0,3,0), (DrawBuilding,0,28,7), (DrawBuilding,0,7,5), (DrawBuilding,0,70,24), (DrawBuilding,0,13,0), (DrawBuilding,0,0,0), (DrawBuilding,0,0,4), (DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (DrawBuilding,0,34,7), (DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (LandscapeFlush,0,0,0), (RenderNormalMode,0,0,0)]; actual: same 16-entry SITE sequence, every count (0,0).
  • cathedral-leak: expected [(DrawBuilding,0,108,40), (DrawBuilding,0,3,0), (DrawBuilding,0,28,7), (DrawBuilding,0,7,5), (DrawBuilding,0,70,24), (DrawBuilding,0,13,0), (DrawBuilding,0,0,0), (DrawBuilding,0,0,4), (DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (DrawBuilding,0,34,9), (DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (LandscapeFlush,0,0,0), (RenderNormalMode,0,0,0)]; actual: same 16-entry SITE sequence, every count (0,0).
  • cathedral-stair-arch: expected [(DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (DrawBuilding,0,47,30), (DrawBuilding,0,21,0), (DrawBuilding,0,2,0), (DrawBuilding,0,34,27), (DrawBuilding,0,43,1), (DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (DrawBuilding,0,2,4), (LandscapeFlush,0,0,0), (RenderNormalMode,0,32,6)]; actual: same 13-entry SITE sequence, every count (0,0).
  • foundry-deep: expected [(DrawBuilding,0,1,0), (DrawBuilding,0,0,0)×11, (LandscapeFlush,0,0,0), (RenderNormalMode,0,18,7)] (12 DrawBuilding entries total — S4-c2 fix round 1 correction, A5: the landing note originally said "×10", undercounting by one against its own stated 12-entry total; 1+11=12); actual: same 14-entry SITE sequence, every count (0,0).
  • holtburg-doorway-still: expected [(DrawBuilding,0,12,0), (DrawBuilding,0,23,6), (DrawBuilding,0,0,0), (DrawBuilding,0,15,0), (DrawBuilding,0,0,0), (DrawBuilding,0,0,0), (DrawBuilding,0,0,1), (DrawBuilding,0,0,0)×6, (LandscapeFlush,0,0,0), (RenderNormalMode,0,33,0)] (13 DrawBuilding entries total — S4-c2 fix round 1 correction, A5: the landing note originally said "×5", undercounting by one against its own stated 13-entry total; 7+6=13); actual: same 15-entry SITE sequence, every count (0,0).
  • terrace-edge: expected [(DrawBuilding,0,158,452), (DrawBuilding,0,22,204), (DrawBuilding,0,0,0)×3, (DrawBuilding,0,22,523), (DrawBuilding,0,13,7), (DrawBuilding,0,14,5), (DrawBuilding,0,0,0)×3, (DrawBuilding,0,11,0), (DrawBuilding,0,0,0), (DrawBuilding,0,13,12), (RenderNormalMode,0,56,0)] (14 DrawBuilding entries, no LandscapeFlush — this pose never runs a qualifying interior turn, matching its own PM/PC KnownFailure history); actual: same 15-entry SITE sequence, every count (0,0).

All six AlphaFlushCounts_* Facts are tagged [Trait("Status", "KnownFailure")]; the paired AlphaFlushSites_* Facts are live and pass. The count Facts remain KnownFailure for exactly this reason, never weakened (the real comparison runs and genuinely fails on the count dimension; the site dimension is asserted unconditionally in the same method and genuinely passes). Root cause is a HARNESS scope limit shared with the pre-existing PM/PC gate, not a routing defect: closing it for real would mean feeding WalkFrameDriver genuine per-pose GfxObj/particle content from the installed DAT (the production WalkProductionWorldData path, not EmptyAlphaDepthWorldData) — a materially larger apparatus than this chunk's bounded scope, flagged here for a future chunk rather than attempted.

§11 result (fix round 1, Sonnet implementer, 2026-09-04): all items M1M8/A1A8 from the campaign branch's §11 landed in one commit on top of this landing. M1 (blocking) deleted both unreachable-branch throws and implemented the particle site's real rows 1/4/5; M3 wired building-detail Row 1 into SubmitToAlphaQueue with a new single-instance immediate-draw path (DrawImmediateAlphaInstance/Rhi), removing the drain's own detail branch (M3c) since detail-eligible content no longer reaches it; M6 wired EnvCell's whole transparent shell into the SAME router/queue as one ALPHA token per cell when detail was off, disproving this section's own "needs a new deferred-replay abstraction" claim above; that round's false homogeneous-0x02 premise and whole-cell replay were then corrected by the exact-mask/list-filtered §12 implementation; A1 deleted a mislabelled outdoor-root LandscapeFlush call retail never makes there (its content now joins the pass-end RenderNormalMode drain like retail's own outdoor root); M5 split the six former AlphaFlushTranscript_* Facts into live AlphaFlushSites_* (unconditional pass) and AlphaFlushCounts_* (KnownFailure, three honest reasons instead of one) and added a live boundary pin through WalkFrameDriver.Replay's own SortCellExit arm; M4 deleted the unread IsFirstForList field (retail's per-DrawMesh, per-list value genuinely varies: 9,685 new=1, 871 new=0; acdream has no one-to-one retained producer or Vulkan consumer); M2/A2/M8c retired AP-34 (restored as ~~AP-34~~, not left deleted), renumbered the colliding AP-236/AP-237 to AP-238/AP-239, and filed AP-240 for the CLIP-list-for-ordinary-content gap M2 found; M7 disproved AP-239's cloud citation and replaced it with a real scanned instance; A4 fixed ApplyScratchRetention's source-count argument; A7 renamed/redocumented the mesh-router truth-table oracle honestly. See the fix-round commit body for every mutation check's actual failing-assertion text and the real gate output lines.

§12 result (fix round 2 plus the owner-authorized post-stop repair, 2026-09-04): the owner-authorized repair supersedes the earlier §12 result's EnvCell exactness, scratch-bound, and allocation claims. The repaired real leaf path now excludes deferred non-additive transparent subsets from the opaque pass, classifies retained ClipMap presence with (mask & 0x08) != 0 (including legal positive-stipple mask 0x09), and keeps canonical row 3 at OverrideClipmap=false. Its CLIP base pipeline is the paired-retail ONE/INVSRCALPHA, alpha test GREATER_EQUAL, reference 100/255 for a paletted texture or 200/255 for DDS/non-paletted, with depth test/write on and alpha-to-coverage off. Both fragment shaders recognize only those two named references (within 1e-6 for GLSL constant folding); arbitrary 0.5 falls back to the ordinary 0.05 empty-fragment cutoff. Exact uParamB=1 remains mesh_detail.vert's pre-existing building-category sentinel and also uses 0.05, so the new reference does not erase building detail. Detail- active ClipMap replay retains the selected cutoff and a depth-writing clip base before the detail contribution. ALPHA remains straight-alpha with depth write off and the two subsets do not cross-feed.

Rejected EnvCell reservations now roll back the tail cell id while keeping the source registered for exactly one flush/end/abort reset. Storm coverage uses two sources, 3,000 accepted tokens, and 9,000 rejected attempts; rejected pending count returns to zero, retained capacity stays at or below 4,096 (the bounded geometric backing for the 3,000-list limit), and rejected payload is never prepared or drawn. The allocation claims now execute the real whole- leaf route scan, DrawCellShell, list-filtered replay and EnvCellRenderer.SubmitRhi, and the real private particle DrawImmediateParticleSubmissionRhi, against a preallocated RHI with call recording disabled. Both report 0 managed bytes per warmed iteration. This replaces the prior static/delegate-only evidence.

The exact state is backed by D3DPolyRender::SetSurface @0x0059c4d0 and the paired executable: @0x0059c72a selects blend ids 2/6 (ONE/INVSRCALPHA), globals 0x00820d8c and 0x00820d90 contain 0x64 and 0xc8, @0x0059c821 calls SetAlphaTestEnable, @0x0059c838 calls SetAlphaTestFunction with function 7 (GREATER_EQUAL), and @0x0059c866 passes depth-write byte 1. No Content model, serializer, or package-format file changed. AP-238 and AP-240 now state only the repaired production truth; the remaining AP-238 divergence is token granularity, while ordinary Wb ClipMap A2C remains AP-240 and is unchanged.

Real clean-state return matrix:

  • Release solution build: Build succeeded, 0 Warning(s), 0 Error(s).
  • Hermetic lane: every project green, 16,735 passed / 0 skipped / 0 failed across 14 assemblies; App 6,882/6,882.
  • InstalledDat: exactly Passed: 255, Failed: 10, Skipped: 1, Total: 266. The failures are only TowerAscent_StaircaseStaysConeVisible_EveryStep, MainGameUiAndChatInput_MediaBearingChildrenNowBuildAsRealWidgets (#383), EveryAuthoredInvisibleWidget_StartsHiddenAcrossAllLayouts (#383), Oh_doorway_still_first_frame_diff (#458), and the six AlphaFlushCounts_*; every AlphaFlushSites_* passes.
  • Checked-in SPIR-V was rebuilt with tools/compile-shaders.ps1: 24/24; shader descriptor/manifest/pack validator filter: 32/32.
  • Focused queue/router/walk/driver/particle/Wb/EnvCell/PView production filter: 239/239. The explicit real production allocation filter is 2/2, and both pins assert 0 B.
  • Register read: AP-238, AP-239, AP-240, AD-120, and ~~AP-34~~ each have exactly one physical row; active physical rows remain AP=159 and AD=92.
  • git diff --check: PASS.

Evidence-history disclosure: the first hermetic invocation was stopped after App exposed two stale test oracles introduced by this repair: the old mesh_modern.frag.spv SHA (expected b702b644862aca31ce1fb0677adc5872b39c4ea87f595a89363b44d10f2cc50e, actual e094a966f7653a79a57d1c208f36d3100a8dcb20891584e6c74b4697e95c1950) and the old five-blend cardinality (expected 5, actual 6). Both assertions were corrected to the exact new shader/state contract, then the complete lane above ran once without an internal retry. The same evidence directory was mistakenly reused, so script startup replaced that first invocation's TRX/log; the exact failures remain recorded here rather than being presented as a clean first attempt. The observed Core.Net PIDs belonged to those two separate script invocations, not a project retry: Core.Net passed 1,077 in the stopped invocation and again in the clean invocation. The first InstalledDat command also omitted ACDREAM_RUN_INSTALLED_DAT_TESTS=1 and was invalid evidence (161 pass / 8 fail / 97 skip); the documented environment produced the 255/10/1 result above. A narrower exploratory focused filter hit the pre-existing global Console.Out capture race once (218 passed / 1 failed, OutdoorRoot_TranscriptFlagOn_PrintsLandscapeThenLandCellThenSortCellThenBuilding_InOrder, "LS must precede LC"); that Fact passed isolated 1/1 and in the broader 239/239 focused run above. A direct unfiltered WalkTraceConformanceTests probe also produced its seven documented InstalledDat failures and is not the focused clean lane.

Actual owner-repair mutation failures (each production mutation was applied, run to the named first failure, and exactly reversed before the final gates):

  1. Restoring the opaque predicate to !IsAdditive fails WholeLeaf_MixedCellDrawsOpaqueAtTurnThenClipAndAlphaAtDrain first at draw count: expected 1, actual 3.
  2. Selecting _alphaPipeline for CLIP fails WholeLeaf_ClipDrainBindsExactStateAndTextureClassReference first at the bind sequence: expected [envcell-clip], actual [envcell-alpha].
  3. Disabling CLIP depth write fails that same production Theory first at Assert.True(clipPipeline.Depth.Write): expected true, actual false.
  4. Swapping the palette/DDS references fails the DDS row first: expected 0.784313738, actual 0.392156869 (and the palette row reports the inverse).
  5. Mutating mesh_modern.frag from < to <= (strict GREATER) fails ClipShaders_UseGreaterEqualForThePerRangeReference first at the preceding Assert.Contains("if (color.a < alphaCutoff) discard;"): the required < source spelling is absent after the mutation. The later Assert.DoesNotContain is not the first failure.
  6. Restoring row-3 OverrideClipmap=true fails the real-interface clip Theory first at Assert.False: expected false, actual true.
  7. Deleting failed-append rollback fails all flush/end/abort rejection-storm rows at the first bounded pending-count assertion: expected 0, actual 9,000.
  8. Selecting _transparentDetailPipeline for a ClipMap detail contribution fails the leaf detail pin's bind sequence: expected second bind envcell-retail-detail-clip, actual envcell-retail-detail-alpha.
  9. Resetting detail ParamB to zero fails the same detail pin first at the second pushed reference: expected 0.784313738, actual 0.
  10. Classifying CLIP with exact mask equality excludes legal mask 0x09 and fails WholeLeaf_PositiveStippleClipMaskUsesClipPipelineAndDdsReference: expected envcell-clip, actual envcell-alpha.
  11. Mapping the new blend to SRC_ALPHA/INVSRCALPHA fails AllRetailBlendModesAreRepresentable: expected (One, OneMinusSrcAlpha), actual (SrcAlpha, OneMinusSrcAlpha).
  12. Restoring mesh_detail.vert's former uParamB > 0.5 category predicate fails ClipShaders_UseGreaterEqualForThePerRangeReference first because vDetailCategory = uParamB == 1.0 is absent; the DDS reference must remain EnvCell rather than masquerading as the building sentinel.
  13. Treating every positive detail uParamB as a cutoff fails the same source pin first because isRetailClipReference(uParamB) ? uParamB : 0.05 is absent; this is the negative proof that exact building sentinel 1 is not a cutoff.
  14. Adding arbitrary 0.5 as an accepted reference to either mesh_modern.frag or mesh_detail.frag fails that source pin first at Assert.DoesNotContain("value - 0.5"); both shader mutations were run and reversed independently.

No graphical client was launched. G3/G4 remain unpassed pending the campaign branch's fresh build, reviews, and owner-visible graphical/soak gates.

13. S4-c2 final-round result — STOPPED UNLANDED (2026-09-04)

Stop rule fired. Final-fix implementation c4cbc1d0d (directly on cc8e5677a, worktree s4-c2-impl) passed its implementer matrix, but BOTH sequential §12 lenses found code/test/register changes that would require a third fix round. Section 12 explicitly bars that round. None of 048d5b12f, cc8e5677a, or c4cbc1d0d was cherry-picked to the campaign branch; the branch's latest renderer code remains S4-c1 766f9e749.

13.1 Retail-faithful lens — FAIL

Paired executable/PDB was re-confirmed ({9e847e2f-777c-4bd9-886c-22256bb87f32}, age 1). The particle row-5 fix and exact EnvCell ConstructMesh mask/list selection are correct. The following are not:

  1. BLOCKING — a deferred EnvCell subset already draws at the cell turn. WalkProductionLeafRenderer.DrawCellShell calls DrawOpaqueCellShells before SubmitOrDrawTransparentCellShell. EnvCellRenderer's opaque pass does not exclude a non-additive IsTransparent batch, so canonical pure ClipMap F4180104 / surface 08000BFF is drawn immediately before its CLIP token is appended, then drawn again at the drain. Retail row 3 only appends. The new production fixture starts at dispatch and never executes this preceding opaque-shell call.
  2. MAJOR — CLIP/detail-immediate surface state is wrong. All non-additive EnvCell transparent ranges bind _alphaPipeline (StraightAlpha, depth-write off). Retail's pure ClipMap replay uses ONE/INVSRCALPHA, alpha test, and depth-write on (SetSurface 0x0059c6e40x0059c806; SetDepthBufferMode call 0x0059c866). Detail-active row 1 uses that same retail base state before its detail combine. The port also hardcodes overrideClipmap:true although the router's ordinary mask-0x08 row has false; replay ignores the flag. Tests assert draw counts, not bound pipeline/blend/depth/override state, and construct mask-0x08 as AlphaBlend, so the wrong state stays green.
  3. MAJOR — register/result claims are false. AP-238's “token granularity only” statement omits premature/double draw and surface-state divergence; AP-240's EnvCell “CLIP feeder” is only queue bookkeeping while the visible subset has already drawn. The implementation's §12 result repeats those claims.
  4. MINOR truth: the mesh-particle pipeline summary still says it shares the billboard depth bracket despite the opaque depth-write exception; an EnvCell test comment cites a nonexistent Assert.Empty(log).

The lens reproduced 46/46 relevant queue/particle/EnvCell/PView tests and 42/42 particle/EnvCell renderer tests. Green tests do not contradict the findings because they omit the preceding opaque pass and pipeline state.

13.2 Production/gate-honesty lens — FAIL

The second lens independently confirmed both rendering blockers and added:

  1. MAJOR — source scratch is not queue-bounded. Each fixed-list EnvCellAlphaDrawSource retains pending/prepared/draw List<uint> buffers. Payload is reserved before queue admission; after 3,000 entries TryAppend rejects, but the source continues growing and Reset only clears capacity. The queue's scratch budget/capacity therefore does not bound retained source memory under rejection pressure.
  2. MAJOR — allocation evidence is vacuous for the claimed paths. The two 0-B tests feed route flags directly into static dispatch with no-op sinks; they do not run the production EnvCell scan/filter/RHI path, and the particle test does not run DrawImmediateParticleSubmissionRhi.
  3. R2-3's rejected-first-use cleanup itself is correct for flush/end/abort; M1, M3, and A1 have material production pins; allowed scope and git diff --check pass.

This lens reproduced Release 0 warnings/errors, 81/81 focused production tests, and 32/32 shader tests. Its official hermetic no-retry run was 16,727 pass / 1 pre-existing Console.Out capture-race failure; isolated App rerun passed 6,875/6,875. InstalledDat was unavailable in that lens because the opt-in DAT environment was not configured. The implementer's clean-state evidence remains: hermetic 16,728/16,728; InstalledDat 255 pass / 10 expected fail / 1 skip; shaders 32/32; corrected focused 211/211. Those counts prove the tested behavior only; they do not repair the missing discriminators.

13.3 Disposition

  • s4-c2-impl remains clean, detached at unlanded c4cbc1d0d for evidence.
  • No code fix, cherry-pick, graphical client, validation self-gate, or stationary A/B was performed after the stop. The user-required graphical gate is deliberately inapplicable to unlanded code.
  • A technically complete next attempt would need to fix pass membership, carry exact clip/override state into an EnvCell clip/depth-writing pipeline, bound source-owned payload under rejection, add end-to-end walk-leaf plus pipeline-state/allocation discriminators, and rewrite AP-238/AP-240/result truth. That is a THIRD fix round and is NOT authorized by this campaign chunk. Resume only by an explicit owner decision that changes the process; otherwise S4-c2 is stopped and G3/G4 remain unpassed.

14. S4-c2 owner-authorized repair after the stop (2026-09-04)

Authority and base. The owner replied “Ok do fix it” after receiving the §13 stop explanation. That explicitly authorizes the otherwise-forbidden third fix round for this chunk only. It does not weaken plan §5's general two-round rule. Work from clean evidence commit c4cbc1d0d in s4-c2-impl; the campaign branch remains at stop record dc971ea2b with S4-c1 766f9e749 as its latest renderer until both review lenses pass. This exception is one bounded repair: any new code/test/register finding after its reviews stops again and returns to the owner; there is no implicit fourth round.

The lead re-read docs/architecture/worldbuilder-inventory.md before writing this contract and re-verified the surface state in the named retail decomp and the paired executable/PDB. D3DPolyRender::SetSurface @0x0059c4d0 does the following for a pure Base1ClipMap surface when overrideClipmap == 0:

  • @0x0059c724..0x0059c743 selects BLEND_ONE/BLEND_INVSRCALPHA, enables alpha test, and leaves alpha blending enabled;
  • @0x0059c73c..0x0059c75d selects alpha-test reference 100 for a paletted texture and 200 for a DDS/non-paletted texture; @0x0059c821..0x0059c838 uses GREATER_EQUAL;
  • @0x0059c7b7..0x0059c806 and the SetDepthBufferMode call @0x0059c866 keep depth test and depth write enabled for this state.

The existing prepared payload already preserves everything needed without a Content/package change: RetailSurfaceMask identifies the CLIP subset and TextureKey.PaletteId distinguishes the 100/255 versus 200/255 reference. RetailAlphaMeshRouter.Route is also decisive here: this EnvCell call site hardcodes multiPassAlpha:false, so ordinary mask 0x08 is row 3, CLIP, OverrideClipmap=false. The current hardcoded true is not an approximation.

14.1 F3-1 — a deferred EnvCell subset is absent from the opaque turn

Correct both pass-filter loops in EnvCellRenderer.RenderModernMDIInternal. WbRenderPass.Opaque admits only non-additive, non-transparent batches; WbRenderPass.Transparent admits the transparent/additive batches selected by the exact route filter. Do not change SinglePass behavior. Consequently, WalkProductionLeafRenderer.DrawCellShell may call DrawOpaqueCellShells before transparent dispatch, but canonical F4180104 / surface 08000BFF must produce no draw there, append one CLIP token, and draw exactly once at the next real queue drain.

The required production pin calls the real leaf's DrawCellShell, not the static dispatcher in isolation. It records the complete sequence through the preceding opaque call, submission, and queue drain. Mutating either pass-filter loop back to the current predicate must first fail the “no pre-drain ClipMap draw” assertion. Keep a mixed opaque + 0x08 + 0x02 cell in the fixture so the opaque subset still draws once at the turn while CLIP and ALPHA do not.

14.2 F3-2 — exact CLIP state and exact row-3 override

Add the backend blend spelling for ONE/ONE_MINUS_SRC_ALPHA (normally named premultiplied/source-over) and map it explicitly in the Vulkan blend table. Add an EnvCell CLIP pipeline using the existing mesh_modern shader and world mesh layout: that blend, depth test ON, depth write ON, retail world compare, clockwise front face with the existing per-range cull override, alpha-to- coverage OFF. Do not add a shader.

Extend the existing shader/pass-state input just enough to express retail's CLIP test: GREATER_EQUAL 100/255 when TextureKey.PaletteId != 0, otherwise GREATER_EQUAL 200/255. Preserve ordinary opaque/alpha/additive behavior. Because one MDI run cannot carry two alpha references or two base states, range grouping must include the CLIP-vs-ALPHA/additive state and the applicable reference; it must not infer state from IsTransparent alone. Detail-active row-1 replay uses the same CLIP base state before the already-established detail combine and applies the same alpha reference. Do not route a pure ClipMap subset through _alphaPipeline or _transparentDetailPipeline's no-depth base state.

Queue submission for the ordinary mask-0x08 EnvCell token carries overrideClipmap:false, exactly as the router decision says. Either retain the decision/flag in the EnvCell token or make the row-3-only invariant explicit and pinned; do not hardcode true, and do not add a generic flag that replay ignores.

Production RHI pins inspect actual GpuRecordedPipelineBind calls and the created pipeline descriptions, not only MDI counts. They prove:

  • CLIP drain: the CLIP pipeline immediately precedes its draw; blend factors are ONE/ONE_MINUS_SRC_ALPHA; depth test/write are true; A2C is false; the paletted and DDS thresholds are 100/255 and 200/255;
  • ALPHA drain remains StraightAlpha with depth write off; mixed CLIP/ALPHA replay does not cross-feed subsets;
  • detail ON draws at the leaf turn, queues nothing, and a pure ClipMap base draw still uses CLIP/depth-writing state before its detail contribution;
  • the recorded queue entry for canonical row 3 has OverrideClipmap=false.

Mutations selecting _alphaPipeline for CLIP, disabling CLIP depth write, swapping either alpha reference, using strict GREATER instead of GREATER_EQUAL, or restoring overrideClipmap:true must each fail a named assertion. Recompile the checked-in SPIR-V and run the shader contract/manifest lane if shader source changes.

14.3 F3-3 — rejected payload cannot grow source scratch

Keep the queue rule from §12.4: a rejected first-use source is registered and reset exactly once, and overflow drops rather than drawing immediately. Change the EnvCell reservation API so a failed TryAppend rolls back the just- reserved cell id (or equivalently never retains it after rejection). Accepted token indices remain stable. Pending, prepared, and draw scratch may retain warmed capacity, but each is bounded by the 3,000-entry list limit; repeated rejection cannot grow count or retained capacity beyond the one bounded geometric allocation needed for that limit.

Pins use two sources and more than one full list's worth of rejected attempts. They assert the rejected source participates in flush/end/abort cleanup, never prepares/draws, its pending count returns to zero, and its retained capacity is bounded after the rejection storm. Restoring reserve-without-rollback must fail on the first bounded-count/capacity assertion.

14.4 F3-4 — production-path allocation evidence, not delegate exercises

Delete or relabel the two vacuous 0-B claims. The replacement EnvCell warmed measurement must execute the real route scan, the real leaf submission, the real list-filtered replay, and EnvCellRenderer.SubmitRhi. The particle measurement must execute DrawImmediateParticleSubmissionRhi. Instrumentation objects from RecordingGpuDevice are not production allocations; use a preallocated/no-recording test RHI if necessary, but do not replace the production method with a no-op delegate. After warm-up, the changed hot paths must report 0 managed bytes per iteration. If production itself allocates, fix the production path rather than weakening or rewording the assertion.

14.5 F3-5 — truth, scope, gates, and return

Correct the stale particle depth-bracket summary and the nonexistent Assert.Empty(log) comment. Rewrite AP-238, AP-240, and the §12 result so they state only what the repaired production path and tests prove. Any remaining modern translation (including an alpha-reference or detail-combine mismatch) gets a divergence-register row in the same implementation commit; do not bury it in prose. No new row is needed for an exact port.

Allowed files: src/AcDream.App/**, tests/AcDream.App.Tests/**, docs/architecture/retail-divergence-register.md, and this packet. The prepared Content model/serializer and recipe-8 package format do not change; the existing TextureKey.PaletteId is the required source fact. One lead-made implementation commit on top of c4cbc1d0d; the implementer returns a clean diff and evidence but does not commit.

Must not: reintroduce viewer distance or another flush site; change the two-list FIFO/strict-less valve; change ordinary Wb ClipMap A2C (AP-240); add particle A2C; add a shader; recover overflow with an immediate draw; run a graphical client from the implementation or review worktree; touch S4-c1's punch/seal behavior.

Automated return matrix: Release solution build with zero warnings/errors; hermetic lane wholly green; InstalledDat exactly the expected known-failure set from §12 unless a named, evidenced count changes; shader classes and SPIR-V manifest green; focused queue/router/walk/particle/Wb/EnvCell/PView suite; the new whole-leaf, pipeline-state, rejection-storm, and real production allocation pins; register identity/count checks; git diff --check. The commit body names every mutation and its actual first failing assertion.

Sequential reviews: first retail-faithful against ConstructMesh/DrawMesh/SetSurface and the paired executable, then production/gate-honesty against pass membership, range grouping, bounds, allocation, mutations, scope, register, and gate output. The lead verifies every finding. Only dual PASS authorizes landing the complete S4-c2 stack, followed by a fresh campaign Release build and the graphical/soak gates. G3/G4 remain unpassed until those later gates; nothing merges to main before G4.

15. Owner-authorized repair review stop (2026-09-04)

The owner-authorized implementation is clean and unlanded at a094bf2b77c3061288185f069fa0b5e494ee8540 in s4-c2-impl, on top of c4cbc1d0d / cc8e5677a / 048d5b12f. The lead independently rebuilt the Release solution with zero warnings/errors, reproduced the two real 0-B allocation pins, recompiled 24/24 shader pairs, checked the three final SPIR-V hashes, inspected the 14-assembly 16,735/16,735 hermetic evidence, and re-verified SetSurface against both the named pseudo-C and paired executable. No graphical client was launched.

The first sequential retail lens found the repaired behavior retail-faithful: whole-leaf opaque exclusion, 0x08/0x09 CLIP grouping, row-3 overrideClipmap=false, blend ids 2/6 (ONE/INVSRCALPHA), references 100/200, inclusive GREATER_EQUAL, depth write, exact shader-reference versus building-sentinel separation, detail CLIP state, ALPHA isolation, rollback/reset, particle row 5, AP-238, and AP-240 all passed. Its focused checks passed 60/60 and 88/88. It nevertheless returned FAIL because §14 requires every evidence/prose claim to be exact and permits no repair after a review finding:

  1. MAJOR — commit evidence: a094bf2b7 summarizes “14 negative mutations restored” instead of naming every mutation and actual first failing assertion as §14.5 requires. The packet has the list, but the binding requirement says the commit body must carry it.
  2. MAJOR — mutation truth: §12 mutation 5 says the <<= mutation first fails Assert.DoesNotContain; the test actually executes and fails the preceding Assert.Contains("if (color.a < alphaCutoff) discard;") first.
  3. MINOR — address prose: §12 attributes function 7 / GREATER_EQUAL to 0x0059c821; that call is SetAlphaTestEnable. The function call is at 0x0059c838, as the implementation commit body correctly records.
  4. MINOR — stale source prose: mesh_detail.vert still says EnvCell always sets and ignores uParamB=0; CLIP now passes and consumes 100/255 or 200/255. EnvCellRenderer.Rhi.cs still says the filtered opaque detail replay includes ClipMap, which the repaired pass filter excludes. ParticleRenderer.Rhi.cs still says five pipelines although it creates six.
  5. MINOR — stale test prose: RetailAlphaMeshRouterTests.cs says ClipMap never reaches MaskFromTranslucencyKind from production; mesh particles do at ParticleRenderer.cs, consistent with AP-240.

Because the retail lens failed, the production/gate lens was not started. Correcting the commit metadata, packet, source comments, and test comment would be a post-review fourth repair. §14 explicitly grants no implicit fourth round, so the implementation remains unlanded, the campaign renderer remains S4-c1 766f9e749, and G3/G4 remain unpassed. Resume only by another explicit owner process decision.

16. Owner-authorized evidence/prose repair budget (2026-09-04)

The owner replied: “Ok but fix those and finish these. You can try 5 more times.” This explicitly authorizes up to five additional bounded implementation-plus-sequential-review attempts for S4-c2. It does not weaken the retail/binary verification, dual-review, landing, graphical-gate, ledger, or no-merge-before-G4 rules. Attempt 1/5 starts from clean unlanded a094bf2b77c3061288185f069fa0b5e494ee8540; the campaign branch remains on S4-c1 until a complete attempt receives retail PASS followed by production/ gate PASS.

16.1 Attempt 1/5 contract — evidence and comment truth only

Make exactly the retail lens's §15 corrections; no renderer behavior, shader instruction, SPIR-V, test assertion, register row, package model, or gate is weakened or changed:

  1. In the §12 result, attribute SetAlphaTestEnable to 0x0059c821 and SetAlphaTestFunction(GREATER_EQUAL) to 0x0059c838.
  2. Correct mutation 5's actual first failure: after < becomes <=, the preceding Assert.Contains("if (color.a < alphaCutoff) discard;") fails because the required source spelling is absent. Do not claim the later Assert.DoesNotContain is first.
  3. Update mesh_detail.vert: exact uParamB=1 selects the building/object category; EnvCell zero and CLIP 100/255 or 200/255 select the bound environment category, and the fragment shader consumes the CLIP values.
  4. Update EnvCellRenderer.Rhi.cs: the opaque environment-detail replay is for the already-filtered opaque shell commands; transparent ClipMap is excluded and takes its immediate/delayed CLIP path with its own detail contribution.
  5. Update ParticleRenderer.Rhi.cs from “five pipelines” to the exact six.
  6. Update RetailAlphaMeshRouterTests.cs: ordinary Wb reconstruction still owns AP-239, while mesh particles genuinely call MaskFromTranslucencyKind; do not claim production never calls it.
  7. The lead amends the unlanded implementation commit so its body names all fourteen owner-repair mutations and each actual first failing assertion, using the corrected mutation-5 ordering above. The implementation agent returns an uncommitted diff and does not amend or commit.

Allowed implementation files are only the four source/test files named above plus this packet (five files total). git diff --check, Release build, the exact focused source/comment and behavioral tests, shader/manifest tests, and the two real 0-B allocation pins must remain green. The unchanged 16,735/16,735 hermetic and 255/10/1 InstalledDat evidence may be reused only if the diff remains prose-only; otherwise rerun the affected complete lane. No graphical client runs from an implementation/review worktree.

Review attempt 1 sequentially: retail/evidence lens first, then production/ gate lens only on PASS. A finding consumes attempt 1 and returns to the lead, who writes the next bounded contract against that exact finding; up to four further attempts remain. Dual PASS authorizes landing the full S4-c2 stack, fresh campaign Release/hermetic/InstalledDat gates, then the graphical and stationary-soak gates. G3/G4 remain unpassed until those steps finish.

16.2 Attempt 1/5 result; attempt 2/5 contract

Attempt 1's five-file prose diff is correct and remains uncommitted on clean base a094bf2b7. Release passed with zero warnings/errors, the affected tests passed 37/37, both real allocation pins passed 2/2, and git diff --check passed. The shader lane correctly failed 31/32: CommittedSpirvIsNotStaleAgainstItsGlslSource reports that mesh_detail.vert's source hash changed after its required comment correction. The attempt-1 contract allowed the GLSL comment but forbade the mechanically required manifest/SPIR-V refresh. The implementer stopped without weakening the freshness test or touching either artifact. This contract conflict consumes attempt 1; four attempts remain.

Attempt 2/5 retains the exact five-file diff from §16.1 and permits only the mechanical shader-artifact closure:

  1. Run tools/compile-shaders.ps1 once from s4-c2-impl.
  2. Permit changes only to src/AcDream.App/Rendering/Shaders/spv/shaders.manifest.json and, if the deterministic compiler rewrites it, the paired mesh_detail.vert.spv. No other shader source or SPIR-V may change.
  3. Verify the vertex shader's executable instructions are unchanged: if the SPIR-V bytes change, compare/disassemble the before/after modules and prove the difference is non-semantic metadata only; otherwise stop instead of accepting a shader behavior change.
  4. Run Release build, the complete shader/manifest lane (32/32), the 37 affected tests, both real allocation pins, git diff --check, and a strict changed-file audit. The unchanged hermetic/InstalledDat evidence remains reusable because the diff is prose plus deterministic shader metadata.

The implementation agent still returns an uncommitted diff. The lead verifies the artifact closure and amends the unlanded implementation commit with all fourteen mutation names/first failures. Then review attempt 2 sequentially, retail/evidence first and production/gate second. A finding consumes attempt 2; three further attempts remain.

17. Attempt 2 landing result (2026-09-04)

Attempt 2 retained the five evidence/comment fixes from §16.1 and refreshed only src/AcDream.App/Rendering/Shaders/spv/shaders.manifest.json after the one permitted compiler run. mesh_detail.vert.spv remained byte-identical: SHA-256 5346247ab7d606046943e19b28888c814e08dc6cb27cd9750096ac055457eb57, Git blob 5ae4f2379167f739f297d2f00189901e29d5e412. The lead amended the implementation evidence to name all fourteen mutations and their actual first assertions; final reviewed implementation commit: daaeab0ba.

The sequential retail/evidence lens PASSED first. It independently confirmed the paired PDB/executable GUID {9e847e2f-777c-4bd9-886c-22256bb87f32} age 1 and the required bytes: blend IDs 2/6 at 0x0059C72A/0x0059C72F, alpha-test enable at 0x0059C821, GREATER_EQUAL at 0x0059C838, and depth-write at 0x0059C866. Whole-leaf exclusion, 0x08/0x09 CLIP, row-3 override false, references/sentinel/detail/ALPHA/rollback/particles/register all passed. The production/gate-honesty lens then PASSED: real production reachability, pipeline state, bounded 3000/4096 scratch, production 0-B pins, register truth, and all fourteen mutations passed. Its fresh gates were Release 0W/0E, shader 32/32, affected 37/37, allocation 2/2, production focused 239/239.

The stack landed on the campaign branch in order: 89f1e2676 (048d5b12f), 9ccb61a8e (cc8e5677a), 0aa166aa0 (c4cbc1d0d), and 252886e84 (daaeab0ba). All 43 non-packet files at the campaign tip are byte-identical to the reviewed implementation stack.

Fresh campaign gates:

  • Release build: PASS, zero warnings/errors.
  • Shader/manifest 32/32; attempt-2 affected 37/37; real allocation 2/2 at 0 B; focused production 239/239.
  • Official no-retry 14-assembly hermetic artifact %TEMP%\acdream-s4-c2-campaign-252886e84: 16,734 pass / 1 fail / 0 skip. The sole failure is the unchanged global Console.Out capture race in WalkFrameDriverTests.Collect_WeatherTurnFiredMatchesThePrintedOcLineExactly; the exact theory passed 2/2 isolated. The isolated pass does not rewrite the original lane verdict.
  • InstalledDat with explicit installed DAT path: 255 pass / 10 documented fail / 1 skip. The failures are TowerAscent, two #383 sweeps, #458, and six AlphaFlushCounts_*; every AlphaFlushSites_* row passed.

Validation-on graphical evidence is provisional until owner review:

  • logs/selfgate-20260904-115818-s4c2-landed-route: 00-login.png, 01-cathedral-stairs.png, 02-facility-stairs.png, 03-holtburg-house.png, 04-holtburg-terrain-leak.png — PASS. Facility's left-panel crop matches the S4-c1 control; only ordinary time/weather drift.
  • logs/selfgate-20260904-120025-s4c2-landed-g3b: 13-capture-terrace-edge.png, 14-capture-cathedral-arrival.png, 15-capture-holtburg-doorway.png, 16-capture-foundry-deep.png — PASS. Pose 15 is the intentional #468 outdoor replacement and the camera is close to the translucent self body; owner review remains explicit.

The first tip soak logs/connected-r6-soak-20260904-120607.report.json failed before its first sample on known #462 and then reproduced known #461 during abort/logout; keep it as a failed attempt. The retry logs/connected-r6-soak-20260904-120756.report.json passed 9/9 with exit 0 and graceful teardown. The clean S4-c1 control at 9ba8f013e, report s4-c1-impl/logs/connected-r6-soak-20260904-121735.report.json, also passed 9/9 in the same session. Stationary tip-minus-control averages: CPU p95 0.01 ms, GPU p95 +0.16 ms, allocation p50 +1.2 KiB, update p95 0.12 ms, working set 24.6 MiB, private memory 17.7 MiB. Per-destination CPU p95 was within ±0.1 ms, GPU p95 within 0.0+0.4 ms; only Caul/Sawato allocation p50 rose materially (+5.6/+5.8 KiB).

S4-c2 is LANDED and closed. Attempt 1/5 was consumed by the contract conflict; attempt 2/5 passed; three attempts remain unused. G3/G4 remain unpassed. A fresh landed-source audit then found that the upstream per-cell CYpt order was still missing. Execute §18's bounded S4-c3a repair first; only afterward write S4-c3b's deletion contract from the repaired code and re-check the AP-238/AP-240/AlphaFlushCounts_* residuals there.

18. S4-c3a contract — restore retail's per-cell pre-append order (lead, 2026-09-04)

18.1 Why §4's deletion guess is not dispatchable yet

The landed S4-c2 queue is an exact two-list FIFO, but the fresh source audit found that its upstream production order is not yet retail's. This is a missed item from the plan's S4 chunk-2 phrase “alpha list records + insertion sort,” not new scope:

  • named retail RenderDeviceD3D::DrawObjCellForDummies @0x005A0760 calls UpdateObjCell, then calls CShadowPart::insertion_sort at 0x005A0786 when num_shadow_parts > 1, before DrawObjCell;
  • outdoor RenderDeviceD3D::DrawBlock @0x005A17C0 performs the same update and sort at 0x005A18A3 for every visible land cell before its draw loop;
  • UpdateObjCell @0x005A0690 updates each owning physics object's viewer distance, and CShadowPart::insertion_sort @0x006B5130 is stable and orders descending CPhysicsPart::CYpt (far to near); equal CYpt retains the pre-sort shadow-list order;
  • CPhysicsObj::add_particle_shadow_to_cell @0x00514A70 calls CPartArray::AddPartsShadow, so scene-particle parts participate in that same per-cell list rather than forming an unconditional cell-tail block.

Production currently reads ShadowObjectRegistry.GetRetailPartEntriesInCell in registration order, collapses adjacent part rows to one entity record in WalkProductionWorldData.ResolveCellView, classifies static then dynamic records separately, and emits CellParticles after both. The only surviving sort in DeferTransparentGroups is by retained submission ordinal; it reconstructs an already-grouped append sequence and never computes CYpt. Therefore §4 must not delete LocalSortCenter yet. First make the upstream cell order real; c3b then deletes facts and parameters proven dead.

18.2 C1 — one bounded per-cell stable CYpt order

For each normal-world outdoor or interior/look-in object-list cell turn:

  1. compute every eligible object part's CYpt key from its authored GfxObj SortCenter transformed by that part's current model and the current world viewpoint; squared distance is acceptable as the nonnegative monotonic key, but do not replace the authored sort center with the entity origin;
  2. stable-sort far to near within that one cell turn only; all surface subsets of one part retain authored subset order;
  3. combine static and dynamic object records before the sort—the retail cell has one shadow_part_list, not two independently sorted lists;
  4. never sort across cells, building turns, landscape/clear/seal barriers, or frame scopes. The two RetailAlphaQueue lists remain unsorted FIFO lists.

Opaque/cutout commands may still be emitted through the ordered draw stream and delayed subsets through the alpha submission list, but both projections must derive from the same stable part order. A cell with no particles still submits its sorted object alpha range. A building shell is not an ordinary cell shadow part and keeps its existing DrawBuilding alpha mark/detail rule.

18.3 C2 — merge scene-particle alpha at the same cell turn

The existing cell particle event must prepare (not prematurely submit) that cell's scene-particle draw records, expose each record's already-computed authored CYpt/distance key, and merge them far-to-near with the cell's delayed object subset records before either source appends to RetailAlphaQueue. Particle subsets sharing one part key remain in authored/submission order. The merge is stable and allocation-free after warm-up. It must preserve every S4-c2 router outcome: billboard ALPHA, mesh CLIP/ALPHA, row-5 immediate opaque state, capacity drop, and source-owned rollback. An earlier building barrier must still be unable to see a later cell's staged content.

Retail's one physical shadow-list insertion ordinal across object and particle registrations is not represented by one acdream owner today. For an exactly equal cross-source CYpt tie, keep a deterministic stable source order and file AP-242 in this implementation commit; do not invent an “exact” common ordinal. Also file AP-241 for the narrower remaining full-list difference: row-5 immediate particle draws and ordinary opaque/cutout object draws still use separate Vulkan submission channels, so their relative coplanar depth winner is not a literal replay of one interleaved CShadowPart::draw loop. These rows disclose only the unported consequence after C1/C2, not the delayed alpha order C1/C2 now make exact. Increment the register header count and add identity/count pins in the same commit.

18.4 C3 — deletion/truth boundary for c3a

  • Keep ObjectRenderData.SortCenter, CachedBatch.LocalSortCenter, WalkClassifiedBatch.LocalSortCenter, and the per-instance/part equivalent needed by C1. c3b deletes only fields proven unused after the exact order is live; do not erase the evidence first.
  • Remove a cameraWorldPosition parameter only when the replacement CYpt key is retained on the staged record and a signature/source pin proves no alpha submit API silently recomputes or ignores it. No _ = cameraWorldPosition tombstone survives c3b.
  • Keep AlphaSubmissionOrderComparer: it restores original submission ordinal after material grouping and is not the deleted scope-global distance sort. Keep building-degrade ViewerDistanceTo, portal-BFS distance, opaque/private-viewport SortDistance, and the immediate off-screen ParticleSubmissionOrdering.Sort; none is the world-alpha queue sort.
  • Update WbDrawDispatcher, ParticleRenderer, GroupKey, WalkStaticStreamPopulator, worldbuilder-inventory.md, and acdream-architecture.md prose so world alpha is described as per-cell CYpt order feeding two FIFO lists—not one scope-global far-to-near queue.

AlphaFlushCounts_* remains KnownFailure in c3a. Correct its three reasons: (1) the replay world is content-empty; (2) AP-238 coalesces EnvCell to one (cell,list) token; (3) AP-239/AP-240 alter CLIP-vs-ALPHA membership for the named ordinary-Wb cases. Delete the six rows only in a later chunk that first supplies a real content-bearing production replay. The broad stale claim “acdream appends one entry per instance while retail appends per subset” is false for the ordinary Wb/particle paths and must be removed. AP-238/AP-239/ AP-240 stay active and truthful.

18.5 Required tests and mutations

Use real production seams, not a surrogate list sorter:

  1. one cell with near-first/far-second translucent object parts appends far first; reversing the comparator fails;
  2. equal-CYpt object parts retain input order; replacing the stable algorithm with an unstable/tie-reversing one fails;
  3. static and dynamic parts interleave by CYpt instead of forming two blocks;
  4. a multipart entity preserves per-part order and authored subset order;
  5. particle/object delayed records with reversed distances merge into the same far-to-near pre-append sequence; restoring the old particle-tail event fails;
  6. two cells whose distances disagree globally remain cell-major; a global sort mutation fails;
  7. the real queue still drains CLIP then ALPHA FIFO, and the four flush sites, 0.75 valve, building barrier, EnvCell CLIP state, row-5 immediate particle state, rollback, and 3000-entry drop tests remain green;
  8. the production combined-order hot path reports 0 managed bytes per warmed iteration; the pin must call the actual driver/particle/dispatcher merge;
  9. source/signature pins distinguish retained CYpt data from deleted dead camera threading, and documentation/register pins fail on the old “scope-global distance-sorted queue” wording or missing AP-241/AP-242.

The commit body names every mutation and its actual first failing assertion. No new pin is accepted without its observed failing text.

18.6 Scope, gates, and review

Allowed production files: the existing normal-world alpha participants under src/AcDream.App/Rendering/{Walk,Wb}/, ParticleRenderer.cs and .Rhi.cs, plus the minimum shared alpha record needed for the merge. Tests may change only under tests/AcDream.App.Tests/Rendering/ and the directly affected Core dispatcher tests. Documentation changes are limited to this packet, worldbuilder-inventory.md, acdream-architecture.md, and retail-divergence-register.md.

Must not: sort inside RetailAlphaQueue; merge CLIP and ALPHA; change any S4-c2 mask/pipeline/reference/depth decision; move a flush/barrier; sort across cells; change building degrade, private/sealed viewport ordering, portal BFS, prepared package formats, render-scene ownership, or shadow/collision registration; add allocations to the warmed path; run a graphical client from the implementation/review worktree.

Automated return: git diff --check; Release solution build 0W/0E; focused per-cell/order/queue/particle/Wb/walk/EnvCell/PView tests; real 0-B pin; shader/manifest lane; full hermetic lane; InstalledDat with exactly the documented global set plus the six retained AlphaFlushCounts_*, no new failure. The implementer commits one bounded change on a clean scratch worktree and returns the commit, changed-file list, gate output, and mutation ledger.

Sequential reviews: (1) retail lens checks the named decomp and paired binary at 0x005A0690, 0x005A0786, 0x005A18A3, and 0x006B5130..0x006B519D, per-cell scope, comparator direction/stability, part/subset grouping, particle reachability, and every retained deviation; (2) production/gate-honesty lens checks real event reachability, barrier isolation, two-list FIFO preservation, allocation/bounds/rollback, mutations, register count, allowed files, and every gate claim. A failed lens gets one bounded fix contract; a third fix round stops and is written up. Dual PASS lands c3a; the lead then writes c3b's deletion-only contract from that code.

18.7 Implementation result (scratch implementation, 2026-09-04)

The bounded c3a implementation now builds one combined registry view for each ordinary outdoor/interior object-cell turn, transforms each GfxObj's authored SortCenter, applies a stable descending per-cell insertion sort, and derives both opaque/cutout commands and delayed object records from that same order. The real particle leaf prepares but does not expose delayed records; the cell event merges their retained keys with the object's range before either source appends to the unchanged CLIP/ALPHA FIFO lists. Row-5 immediate routing, capacity-drop/source rollback, barriers, and building-shell ownership are unchanged. Exact equal object/particle keys use the disclosed object-first tie.

The paired-binary correction is recorded as AP-243: retail's UpdateObjCell greater-than-50 m branch at 0x005A06B7..0x005A0720 gives all parts one cell CYpt/heading through CPhysicsObj::UpdateViewerDistance and therefore retains insertion order, while this bounded port always uses the more exact per-part authored center. AP-241/AP-242 record the two other narrow residuals. The active AP header and physical table are pinned at 162 rows, with exactly one row for each AP-241/AP-242/AP-243.

Lead-approved process-scope clarification: the real-path integration also changes exactly src/AcDream.App/Rendering/RetailPViewPassExecutor.WalkLeaf.cs and src/AcDream.App/Rendering/RetailPViewPassExecutor.cs. The literal {Walk,Wb}/ production-file list omitted the existing leaf adapter and the thin PrepareCellParticleAlpha forwarder required to reach the expressly allowed ParticleRenderer; relocating that bridge would create an artificial seam. These two files contain only the interface adaptation and forwarder—no router, queue, mask, pipeline, reference, depth, or flush behavior. The lead approved this minimum real-path reachability delta before commit. It is a contract-scope clarification, not a retail behavior deviation, so it files no additional AP row.

Clean-state return matrix (no graphical client was launched):

  • Initial solution --no-restore build was invalid setup evidence: 42 projects lacked project.assets.json (NETSDK1004). One solution restore followed; the official Release solution build then succeeded with 0 warnings and 0 errors.
  • Shader descriptor/manifest/SPIR-V validation: 32/32. No shader source, checked-in SPIR-V, manifest, Content model, serializer, or package format changed.
  • Focused queue/router/particle/Wb/walk/EnvCell/PView production filter: 210/210. The three real warmed routes (EnvCell whole-leaf SubmitRhi, immediate mesh particle RHI, and the new driver/particle/dispatcher merge) pass 3/3 and each asserts 0 managed bytes.
  • Official one-shot 14-assembly hermetic gate: 16,743 passed / 0 skipped / 0 failed. Evidence: %TEMP%/acdream-s4-c3a-impl-20260904-2015.
  • InstalledDat with explicit C:\Turbine\Asheron's Call: 385 passed / 10 failed / 1 skipped. The failures are exactly TowerAscent, the two #383 layout sweeps, #458 Oh_doorway_still_first_frame_diff, and the six retained AlphaFlushCounts_*; all six paired AlphaFlushSites_* pass. Evidence: %TEMP%/acdream-s4-c3a-installed-20260904-2017.
  • git diff --check: pass.

Observed mutation first failures (every mutation was reversed with a patch before the return matrix):

  1. Reverse the CYpt comparator: PopulateCellObjects_UsesAuthoredSortCenterAndStableFarToNearOrder expected [202,101], actual [101,202] at the first sequence assertion.
  2. Move equal keys left (>=): PopulateCellObjects_EqualCyptRetainsEntityPartAndSubsetOrder expected [11,12,21,22], actual [22,21,12,11].
  3. Restore static/dynamic blocks: PopulateCellObjects_InterleavesStaticAndDynamicOpaquePartsByCypt expected [2,3,1], actual [3,1,2].
  4. Replace authored SortCenter with entity translation: the authored-center test first expected [202,101], actual [101,202].
  5. Restore the old object-then-particle tail: CellTurn_RealParticlePreparationMergesWithObjectAlphaByCypt expected source order [Wb,Particle,Wb,Particle], actual [Wb,Wb,Particle,Particle] at position 1.
  6. Sort all staged objects scope-globally before replay: SeparateCellTurnsRemainCellMajorWhenLaterCellIsFarther first expected model X 5, actual 50.
  7. Restore a dead optional camera parameter on SubmitWalkAlphaInstance: WorldAlphaCyptContract_RetainsTheKeyWithoutDeadCameraSubmitThreading first expected parameter count 2, actual 3.
  8. Reinsert “distance-sorts one shared queue” into the inventory: WorldAlphaCyptDocumentationAndRegister_PinPerCellTruthAndThreeResiduals first failed Assert.DoesNotContain on that exact phrase.
  9. Rename AP-241 away: that same truth pin first failed the earlier AP-table- boundary Assert.True because rowIndex=-1; the later Assert.Single was not reached.
  10. Allocate one object in the real cell-merge path: ProductionCellObjectParticleMerge_WarmedPathAllocatesZeroBytes first expected 0, actual 3,072 managed bytes.

19. S4-c3a fix round 1 — authored particle CYpt and bounded preparation (lead, 2026-09-04)

The first retail-faithfulness lens returned FAIL on candidate 44e2bc227ba74d10074cfe985eee094e10b7f438. Ordinary object parts are correct, but the billboard/mode-25 particle path orders by its rendered quad center. That center is the vertex-AABB-derived ParticleGfxInfo.CenterOffset after viewer-facing adjustment, not the GfxObj's authored sort_center. Retail does not use the rendered center for CYpt: CPhysicsPart::UpdateViewerDistance @ 0x0050E030 reads the current GfxObj's sort_center at offsets +0x7C/+0x80/+0x84, scales it, passes it with the part Position to Position::get_offset, computes the length, and writes CYpt. The paired bytes at 0x0050E036..0x0050E0AE confirm that named-decomp sequence. The same lens also found the stale statement that static records are never re-sorted downstream.

The lead's pre-production audit found two coupled safety holes in the new prepared-particle seam. _preparedCellAlphaScratch is a new retained list but is absent from the alpha scratch accounting/retention bound. More importantly, PrepareForCellAlpha reserves _deferredAlpha payload tokens before the driver reaches the queue visibility edge. An exception from a later immediate duplicate can strand unregistered source payload; ordinary capacity rejection retains payload for entries that can never draw. These contradict §18.3's source-owned rollback requirement. They are included in this same bounded round rather than deferred to a predictable production-lens failure.

19.1 F1 — one authored particle sort point, separate from its draw center

Retain GfxObj.SortCenter explicitly in ParticleGfxInfo. Populate it directly in AuthoredParticleGfxInfo; synthetic texture-only/default billboards, which have no GfxObj, use zero. Do not derive it from vertex bounds and do not replace or alter the visual CenterOffset.

For every billboard/mode-25 particle, compute the CYpt point before any viewer-facing draw-frame adjustment:

particle.Position + Transform(authoredSortCenter * particle.Size, ParticleOrientation).

Use the squared viewer distance from that point for ParticleInstance and ParticleSubmission. The rendered quad position/axes remain byte-for-byte the existing CenterOffset/facing result. The full-mesh path already applies the equivalent ObjectRenderData.SortCenter through its model; keep the two paths semantically identical and do not add a second sort.

Add a real GfxObj-backed billboard test whose authored SortCenter is distinct from both its particle origin and vertex AABB center, with non-unit size and a non-identity orientation. Drive the actual cell particle preparation and driver merge against ordinary object alpha. It must prove that the authored point determines the cross-source order while the captured billboard draw center remains the existing visual center. Required mutations: using rendered pos, using the AABB center, dropping size, or dropping orientation must each fail a named first assertion.

19.2 F2 — reserve only at the queue visibility edge and roll back rejection

A prepared particle record retains only the information needed to reconstruct its source payload when Append is called; preparation must not mutate _deferredAlpha. At Append, reserve one tail token, call RetailAlphaQueue.TryAppend, and roll back that exact tail token when the append returns false or throws. A rejected first-use source must remain registered by the queue and receive one flush/end/abort reset, but it owns no rejected payload and never prepares or draws it. Accepted token indices remain stable. An exception from a later row-5 or clip-immediate draw during preparation must leave the source payload count unchanged.

Bound _preparedCellAlphaScratch by the physical two-list limit: retain no more than the first 3,000 delayed candidates for CLIP and the first 3,000 for ALPHA. Later candidates for a list cannot be admitted even in an otherwise empty frame, so dropping only their prepared records is behavior-equivalent; their immediate duplicate, if any, still executes. Include this list in an explicit retained-byte/capacity diagnostic or an equivalent dedicated bound. After a rejection storm its count is zero at reset/next preparation and its retained capacity is no greater than the bounded geometric backing required for 6,000 records (8,192 with List<T> growth). Do not change either queue's 3,000-entry capacity, FIFO append order, source registration, CLIP-then-ALPHA drain, router decisions, or row-5 immediate state.

Pins cover: more than 3,000 candidates for each list; accepted/rejected token counts; no rejected prepare/draw; flush, end, and abort cleanup; an injected immediate-draw exception after at least one delayed candidate; bounded count, capacity, and retained bytes; and the real warmed driver/particle/dispatcher merge at 0 managed bytes. Mutations restoring eager reservation, omitting false/exception rollback, or removing the per-list preparation cap must fail at their first named count/capacity assertion.

19.3 F3 — prose and register truth

Correct WalkFrameDriver.cs's WalkFrameStaticRecords comment: records retain authored traversal/registration order until the ordinary-cell populator builds the combined static/dynamic part list and performs the retail per-cell CYpt sort. They are not final stream order. After F1, AP-241's positive authored- part-order claim becomes true; AP-241/AP-242/AP-243 otherwise remain unchanged, unique, inside the AP table, and the active physical count remains 162. No new deviation is introduced by this exact repair.

19.4 Scope, return, and review order

Production edits are limited to ParticleRenderer.cs, ParticleSubmissionOrdering.cs, and the comment-only correction in Walk/WalkFrameDriver.cs. Tests may change only ParticleRendererRouteTests.cs and Walk/WalkFrameDriverTests.cs; this packet records the result. If the implementer proves one additional existing test helper is the minimum real-path fixture seam, the lead must approve and record it before commit. No router, queue, pipeline, shader, manifest, Content model, serializer, package format, building-shell, EnvCell, or PView behavior changes.

Return one fix commit on top of 44e2bc227b: git diff --check; Release 0W/0E; the focused particle/driver/queue/order/bounds suite; the real 0-B pin; shader contract lane; and a mutation ledger naming each actual first failure. No graphical launch. The retail lens re-reviews F1, the paired bytes, F3, and the unchanged S4-c2 behavior first. Only a retail PASS unlocks the sequential production/gate-honesty lens over the entire c3a stack, with special attention to F2. A failed re-review gets the one remaining bounded fix round; a further finding after that would require a third round and stops the chunk.

19.5 Fix-round-1 implementation result (Sonnet, 2026-09-04)

IMPLEMENTED — RETAIL RE-REVIEW REQUIRED. This fix commit retains the GfxObj-authored SortCenter separately from the rendered AABB-derived CenterOffset. Billboard/mode-25 CYpt now uses the authored point after the particle's scale and orientation, while the captured draw center remains the existing visual center. The prepared-cell seam now reserves source payload only from Append, rolls back the exact tail once on either a false return or an exception, retains at most the first 3,000 CLIP and 3,000 ALPHA candidates, and accounts for the bounded scratch list in its retained-byte diagnostic. The row-2 immediate duplicate remains independent of delayed retention. The static-record comment now describes the later ordinary-cell combined CYpt sort.

The lead separately authorized one plan-ledger edit so the S4-c3a row records candidate 44e2bc227b's retail FAIL and this §19 fix result. That file is ledger currency only; it does not widen production scope. AP-241/AP-242/AP-243, the active physical count of 162, both retail queues and their capacities, router decisions, FIFO order, CLIP-then-ALPHA drain, row-5 immediate state, pipelines, shaders, manifest, Content model, serializer, package format, building shells, EnvCells, and PView behavior remain unchanged.

Automated return:

  • dotnet build AcDream.slnx -c Release --no-restore --nologo — PASS, 0 warnings / 0 errors.
  • focused ParticleRendererRouteTests|WalkFrameDriverTests|RetailAlphaQueueTests|RetailParticleGeometryClassifierTests lane — PASS, 95/95, 0 skipped.
  • WorldAlphaCyptDocumentationAndRegister_PinPerCellTruthAndThreeResiduals — PASS, 1/1; all three residual rows remain unique inside the AP section and the physical count remains 162.
  • real warmed ProductionCellObjectParticleMerge_WarmedPathAllocatesZeroBytes|ProductionImmediateMesh_WarmedDrawImmediateParticleSubmissionRhiDoesNotAllocate lane — PASS, 2/2; both production-path pins observed 0 managed bytes.
  • VulkanShaderDescriptorContractTests|VulkanShaderManifestTests|RenderPackSpirvValidatorTests — PASS, 32/32, 0 skipped.
  • official one-shot 14-assembly hermetic gate — PASS, 16,751 passed / 0 skipped / 0 failed. Evidence: %TEMP%/acdream-s4-c3a-fix1-20260904-2215.
  • InstalledDat with explicit C:\Turbine\Asheron's Call and the documented ordinary set plus TowerAscent, #458 Oh_doorway_still_first_frame_diff, and the six retained AlphaFlushCounts_* — 385 passed / 10 expected failed / 1 skipped. The failures are exactly TowerAscent, the two #383 layout sweeps, #458, and the six count rows; no new failure appeared. Evidence: %TEMP%/acdream-s4-c3a-fix1-installed-inclusive-20260904-2222.
  • git diff --check — PASS (only the repository's LF-to-CRLF working-copy notices).

Mutation ledger (each mutation was applied alone, its named test was run once, and the production source was restored before the next mutation):

  1. Use rendered pos for billboard CYpt: CellTurn_GfxObjBillboardUsesScaledOrientedAuthoredSortCenterButKeepsVisualCenter first failed its distance assertion, expected 40, actual 116.
  2. Use the AABB-derived CenterOffset: the same test first failed its distance assertion, expected 40, actual 116.
  3. Drop particle size from authored SortCenter: the same test first failed its distance assertion, expected 40, actual 65.
  4. Drop particle orientation from authored SortCenter: the same test first failed its distance assertion, expected 40, actual 160.
  5. Restore eager source-payload reservation during preparation: PreparedCellAlpha_ImmediateExceptionAfterDelayedCandidateDoesNotReservePayload first failed Assert.Empty; the collection contained one DeferredParticleDraw.
  6. Omit rollback after TryAppend returns false: PreparedCellAlpha_AcceptsStableTokenAndRollsBackRejectedTailOnAbort first failed Assert.Single; the collection contained two payloads.
  7. Omit rollback after TryAppend throws: PreparedCellAlpha_AppendExceptionRollsBackExactTailToken first failed Assert.Empty; the collection contained one payload.
  8. Remove the two per-list preparation caps: PreparedCellAlpha_CapsBothListsAndRejectStormRetainsNoPayloadOrUnboundedScratch first failed the prepared-count assertion, expected 6000, actual 6002.

Before the return matrix, fixture construction exposed and corrected two test-only setup issues: missing DatReaderWriter.Lib/Types imports plus a nonexistent vector comparer caused the first compile attempt to fail, and xUnit2013 rejected two count-shaped assertions. Neither failure reached a production positive assertion. The first InstalledDat invocation used the release guide's ordinary Status!=KnownFailure filter and honestly returned 385 passed / 2 expected failed / 1 skipped; that was incomplete §18.6 evidence because it excluded TowerAscent, #458, and the six count rows. It was not retried or rewritten: the separate inclusive artifact above is the required documented-set gate. No graphical client was launched.

20. S4-c3a fix round 2 — retain authored metadata without a surface (lead, 2026-09-04; LAST ROUND)

The §19 retail re-review returned FAIL on candidate eea5793d2. The exact authored-center formula, the paired-byte argument, all installed September 2013 content, and every original c3a invariant passed. One universal contract edge did not: after ReadParticleGfxInfo successfully decodes a real GfxObj, ResolveParticleGfxInfo replaces the complete result with ParticleGfxInfo.Default whenever SurfaceId == 0. That discards the real GfxObj's SortCenter, axes, bounds-derived visual center, and degrade mode. Retail CPhysicsPart::UpdateViewerDistance @ 0x0050E030 reads GfxObj sort_center independently of surface/material presence. Packet §19.1 also explicitly permits a zero authored center only for synthetic/default billboards with no GfxObj. The existing production-path fixture supplied a synthetic in-memory Surface and therefore did not exercise the bad branch.

The lens scanned the installed domain: 2,051 emitter records reference 360 distinct GfxObjs and every one has a nonzero first Surface DID. That lowers current installed exposure to zero but does not make the implementation or its universal claim correct. The same lens found one evidence-only wording error: the in-memory NoopDatReaderWriter fixture is GfxObj-backed and drives the real production path, but is not “real DAT-backed.”

20.1 F1 — decoded GfxObj metadata survives SurfaceId == 0

When a real GfxObj decodes successfully, preserve its complete ParticleGfxInfo regardless of Surface presence. Acquire a texture slot only when SurfaceId != 0; otherwise return the decoded record unchanged with its unassigned slot. A missing/unreadable GfxObj or a descriptor with no GfxObj may still use ParticleGfxInfo.Default. Do not synthesize a surface, change procedural/untextured draw behavior, alter material/additive routing, or special-case installed DIDs.

Extend the existing production-path GfxObj-backed CYpt fixture with a no-surface row (or a separate equally real-path row): nonzero authored SortCenter; vertex AABB center different from it; non-unit size and nonidentity orientation; no Surface entry/DID. It must prove the same authored distance and object/particle merge order while retaining the existing untextured visual fallback. Restoring SurfaceId == 0 ? ParticleGfxInfo.Default : ... must first fail a named authored-distance or cross-source-order assertion. Correct the fixture comment to “production-path GfxObj-backed synthetic DAT records”; do not call it installed or real DAT-backed.

20.2 Final-round production audit before return

This is c3a's second and last fix round. Before commit, re-read every §19 F2 path rather than relying only on the existing green tests: preparation must hold no source payload; Append must reserve once; false and exception paths must roll back the same tail exactly once; a rejected first-use source must remain registered for reset; accepted tokens must remain stable; the first 3,000 candidates per list must be the only retained candidates; later row-2 immediate duplicates must still draw; flush/end/abort and next-preparation cleanup must converge; the retained capacity and byte diagnostics must remain bounded; the real warmed merge must remain 0 B. If that source audit exposes any defect, fix and pin it inside this same round and record it explicitly in the result—there is no later repair round.

20.3 Scope and return

Production edits are limited to ParticleRenderer.cs. Test edits are limited to Walk/WalkFrameDriverTests.cs; this packet and the S4-c3a plan-ledger row record the result. No other file changes without lead approval. AP-241/242/243, queue/router/pipeline/shader/manifest/package behavior, and all installed content remain unchanged.

Return one fix commit on top of eea5793d2: targeted no-surface positive and mutation; the complete §19 95-test focused lane; AP boundary/count pin; both real 0-B pins; shader/manifest lane; Release 0W/0E; git diff --check; honest changed-file list and source-audit statement. The retail lens re-reviews the no-surface branch and evidence wording first. Only PASS unlocks the sequential production/gate-honesty lens over the complete c3a stack. Any further code, test, register, or evidence correction would be a third fix round: stop the chunk and write it up; do not land or graphically gate it.

20.4 Final-fix implementation result (Sonnet, 2026-09-04)

IMPLEMENTED — FINAL RETAIL REVIEW REQUIRED. A successfully decoded GfxObj now retains its complete ParticleGfxInfo when SurfaceId == 0; texture acquisition alone remains conditional on a nonzero Surface DID. Missing or unreadable GfxObjs and descriptors without a GfxObj retain the existing Default behavior. The production-path synthetic GfxObj test supplies no Surface DID or entry, a nonzero authored center distinct from its vertex-AABB center, size 2, and a nonidentity orientation. It proves authored distance² 40, ordinary-object-then-particle merge order against distance² 49, the unchanged visual center (10,4,0), and an unassigned texture slot. The evidence comment now calls both fixtures “production-path GfxObj-backed synthetic DAT records,” not real or installed DATs.

Required §20.2 final-round source audit found no additional defect:

  • PrepareForCellAlpha clears and rebuilds only reconstruction records; it does not add source payload to _deferredAlpha.
  • PreparedParticleAlphaSubmission.Append calls ReservePreparedDispatchDeferredParticle exactly once at the visibility edge, then calls TryAppend once.
  • A false return rolls back that exact tail once outside the try; an exception rolls it back once in the catch and rethrows. The rollback method rejects any non-tail token, so an accepted earlier token cannot be renumbered or removed.
  • RetailAlphaQueue.TryAppend registers the source before its capacity return. A rejected first-use source therefore still participates in the next flush/end/abort reset while owning no rejected payload. Accepted token indices remain stable.
  • Independent retained counters admit only the first 3,000 CLIP and first 3,000 ALPHA candidates from the already stable particle order. The row-2 immediate action is computed independently of retention, so candidate 3,001 still draws immediately.
  • Flush, EndFrame, and AbortFrame reset _deferredAlpha, prepared RHI count, and _preparedCellAlphaScratch; the next preparation also clears the scratch before any early return or rebuild. The immediate-exception path holds no source payload and converges on that next preparation/abort.
  • The prepared list can retain at most 6,000 records and therefore at most the 8,192-slot List<T> geometric backing pinned by the diagnostic. Its bytes remain included in RetainedAlphaScratchBytes.
  • The real warmed driver/particle/dispatcher merge and the immediate-particle RHI path both still measure zero managed bytes.

Mutation ledger: restoring candidate eea5793d2's SurfaceId == 0 ? ParticleGfxInfo.Default : ... ternary made CellTurn_GfxObjBillboardWithoutSurfaceRetainsAuthoredSortCenterAndUntexturedFallback first fail its authored-distance assertion: expected 40, actual 100. The mutation was restored before the return matrix.

Automated return:

  • targeted no-surface production path — PASS, 1/1 after mutation restore;
  • unchanged §19 focused baseline (excluding the separately executed new target) — PASS, 95/95, 0 skipped;
  • AP-241/AP-242/AP-243 boundary/count pin — PASS, 1/1;
  • real production allocation pins — PASS, 2/2, both asserting 0 B;
  • shader/manifest/SPIR-V lane — PASS, 32/32;
  • Release solution build — PASS, 0 warnings / 0 errors;
  • git diff --check — PASS (only the repository's LF-to-CRLF working-copy notices).

Only ParticleRenderer.cs, WalkFrameDriverTests.cs, this packet, and the S4-c3a plan-ledger row changed. AP rows, queue/router/pipeline/shader/manifest/ package behavior, and installed content remain unchanged. No graphical client was launched.

21. Owner-authorized evidence-only exception (2026-09-04)

The owner explicitly authorized one correction beyond the five-attempt/ third-round stop: fix the sole false mutation-first-failure sentence and run a narrow confirmation. This does not reopen renderer implementation or any other evidence claim.

The exact correction is §18.7 mutation 9. Renaming AP-241 makes register.IndexOf("| AP-241 |") return -1; the first failure is the AP-table boundary Assert.True in WorldAlphaCyptDocumentationAndRegister_PinPerCellTruthAndThreeResiduals, not the later Assert.Single. Replace only that statement. The correction commit body must explicitly supersede the same false mutation-9 sentence in initial candidate commit 44e2bc227b; do not rewrite that historical commit.

Allowed files: this packet and the S4-c3a plan-ledger row only. No production, test, register, handoff, architecture, inventory, shader, manifest, or package file changes. The narrow gate is:

  1. temporarily rename the AP-241 table row, run only WorldAlphaCyptDocumentationAndRegister_PinPerCellTruthAndThreeResiduals, and record the actual first failure/message;
  2. restore the row exactly, rerun the same test and require 1/1 PASS;
  3. git diff --check and exact changed-file inspection;
  4. one narrow independent gate-honesty re-review of this exception diff only.

No full renderer rerun is required: the final retail and production lenses already found no other correction-worthy item and the correction cannot affect compiled source or tests. A narrow PASS unlocks landing the already-reviewed c3a stack; a narrow FAIL returns to STOPPED UNLANDED.

21.1 Evidence-exception implementation result (Sonnet, 2026-09-04)

CORRECTED — NARROW REVIEW PENDING. Temporarily renaming the AP-241 row and running only WorldAlphaCyptDocumentationAndRegister_PinPerCellTruthAndThreeResiduals first failed the boundary assertion at line 329 with the actual message: AP-241 row must be inside the AP table before the TS section; rowIndex=-1, AP=[275116,751256). The later Assert.Single was not reached. The register row was restored exactly and the same isolated test then passed 1/1. git diff --check passed, and exact inspection found only this packet and the S4-c3a plan-ledger row changed. No production, test, register, shader, manifest, or package file remains modified; no graphical client was launched. This text supersedes only §18.7 mutation 9 and the corresponding historical claim in candidate 44e2bc227b; it changes no other c3a evidence.

21.2 Narrow review and campaign landing result (2026-09-04)

PASS — LANDED. The independent narrow gate-honesty re-review found no blocking, major, or minor issue. It reproduced an in-memory AP-241 rename and the exact first boundary failure (rowIndex=-1, AP range [275116,751256)), confirmed that the later Assert.Single was not reached, then confirmed the restored isolated pin at 1/1. The AP-register Git blob is byte-identical at the exception base, correction commit, and clean scratch worktree: bf8758705a17b9415888b1a437e673826b6777e2. The exception diff is exactly this packet plus the plan row; git diff --check passed. Commit 9cfddf301 explicitly supersedes the false sentence in historical 44e2bc227b without rewriting it.

The reviewed scratch stack landed on the campaign branch as:

  1. a86ec73ec (44e2bc227b) — stable authored per-cell object/particle order;
  2. 8e0c6fb14 (b6bf6c131) — bounded fix-round-1 contract;
  3. 01674bcc7 (eea5793d2) — authored particle CYpt preparation and bounds;
  4. 8bd75ba31 (14397b14c) — bounded final fix contract;
  5. b6b015604 (359061b82) — surfaceless Gfx metadata preservation;
  6. 316193043 (255194e90) — owner-authorized narrow exception contract;
  7. 67c76026e (9cfddf301) — corrected mutation evidence.

The stop commit 06b986622 remains immediately before that stack as the truthful historical record of the then-binding rule. The owner exception, narrow PASS, and this landing supersede its operational disposition; history was not rewritten.

Fresh campaign verification after integration: Release solution build PASS, 0 warnings / 0 errors; focused particle/driver/queue/classifier lane 96/96; targeted no-surface path 1/1; AP boundary/count pin 1/1; both real production allocation pins 2/2 at 0 B; shader/manifest/SPIR-V lane 32/32; git diff --check clean. The campaign src/tests tree is byte-identical to reviewed scratch commit 9cfddf301. No graphical client was launched. c3b is now unlocked; G3 remains locked until the deletion-only c3b chunk lands.

22. S4-c3b contract — delete the superseded alpha-order sidecars (lead, 2026-09-04)

22.1 Retail and landed-code boundary

This chunk changes no retail-visible renderer behavior. Named retail D3DPolyRender::AddMeshToAlphaList @0x0059C230 accepts mesh/subset/surface and list-state flags but no camera or distance argument; it appends into one of two fixed arrays. FlushAlphaList @0x0059D2E0 replays those arrays by index. Retail's only relevant distance step is earlier and per cell: CShadowPart::insertion_sort @0x006B5130..0x006B519D, before the resulting parts call DrawMesh. The paired bytes and the named pseudo-C agree on those facts; §§1721 contain the earlier byte/review record.

Landed c3a now owns the needed key on WalkClassifiedBatch.LocalSortCenter/SortDistanceSq and on the prepared particle record before the two FIFO lists see it. A separate classic grouped dispatcher sidecar survives only as dead storage and diagnostic hash input: CachedBatch.LocalSortCenter, InstanceGroup.LocalSortCenters, and their append/cache plumbing. Two additional tombstones pass a camera position into DeferTransparentGroups and BuildTransparentSubmissionDigest, then discard it. None feeds a draw, route, list choice, queue record, flush, or barrier.

22.2 D1 — remove the dead grouped sort-center sidecar

Delete CachedBatch.LocalSortCenter and InstanceGroup.LocalSortCenters, including constructor arguments, cache-hit delegate/plumbing, append parameters, per-frame clear/release calls, and the unused field in AddSubmissionInstance's diagnostic digest. The resulting classic grouped path retains matrices, exact submission ordinal, clip slot, lights, indoor/detail/opacity/selection state, and every material key.

This deletion must not touch these live retail keys:

  • ObjectRenderData.SortCenter;
  • WalkClassifiedBatch.LocalSortCenter and SortDistanceSq;
  • WalkStaticStreamPopulator's transformed authored-center calculation and stable descending per-cell insertion sort;
  • ParticleRenderer's authored GfxObj sort center, prepared distance, and object/particle merge;
  • building-degrade ViewerDistanceTo, opaque InstanceGroup.SortDistance, portal-flood distance, private-viewport sorting, or off-screen particle ordering.

The CurrentRenderDispatcherSubmission digest deliberately stops hashing the deleted non-rendered sidecar. That is diagnostic cleanup, not a world-render change; submission order and every rendered field remain hashed.

22.3 D2 — remove the dead alpha camera-parameter chain

Remove cameraWorldPosition from DeferTransparentGroups, BuildTransparentSubmissionDigest, CreateDispatcherSubmission, ObserveCurrentDispatcherSubmission, and ObserveClassifiedDispatcherSubmission, plus all callers/tests. No _ = cameraWorldPosition tombstone may remain.

Keep the camera output from BeginEntityDispatch, the camera argument to PartitionInstanceGroups, InstanceGroup.SortDistance, and CompareOpaqueSubmissionOrder: that is the still-live opaque/private grouped path and is outside the alpha deletion.

22.4 D3 — truth cleanup and explicit non-changes

The six AlphaFlushCounts_* rows remain evaluated KnownFailures. Their exact three reasons are: (1) the replay world is content-empty; (2) AP-238 coalesces EnvCell work to one (cell,list) token; (3) AP-239/AP-240 alter list membership for the named ordinary-Wb cases. Remove any surviving broad “per instance versus per subset” explanation; ordinary Wb and particle paths otherwise append per real subset. The live AlphaFlushSites_* rows remain.

Static deletion verification must find no executable RetailAlphaOrdering, FlushFartherThan, alpha-submit viewerDistance, portal punch depth bias, #129 eye-span cap, or stencil-mark pass. Do not delete generic RHI stencil support, change PortalDepthMaskRenderer, touch shaders/SPIR-V, or change AD-119/AP-238/AP-239/AP-240/AP-241/AP-242/AP-243. The historical mutation comments that quote the deleted old API may remain when clearly past tense.

22.5 Required tests and mutation evidence

Extend the existing production-facing tests, not a surrogate implementation:

  1. reflection/source shape proves CachedBatch and InstanceGroup have no LocalSortCenter(s) sidecar while WalkClassifiedBatch still has LocalSortCenter and SortDistanceSq;
  2. reflection/source shape proves the five D2 methods have no dead camera parameter and neither tombstone remains, while PartitionInstanceGroups still accepts and uses its camera position for opaque SortDistance;
  3. existing cache-hit composition, transparent submission-order digest, group-clear, per-cell object order, particle merge, queue, allocation, and shader/state pins remain green;
  4. a source-truth pin keeps the three AlphaFlushCounts_* reasons and rejects the false broad explanation;
  5. a deletion pin rejects any production resurrection of RetailAlphaOrdering, FlushFartherThan, or an alpha-submit viewerDistance, without rejecting unrelated building/opaque/portal distance owners.

Every new pin gets a real sabotage. At minimum, record the actual first failure after independently restoring: (a) InstanceGroup.LocalSortCenters; (b) CachedBatch.LocalSortCenter; (c) the discarded camera parameter/tombstone on DeferTransparentGroups; (d) the discarded camera parameter on the transparent digest; (e) the false broad count explanation; and (f) one deleted alpha-order symbol. Restore each mutation exactly before the clean return.

22.6 Scope, gates, and review

Allowed production files: src/AcDream.App/Rendering/Wb/CachedBatch.cs, WbDrawDispatcher.cs, and comment-only cleanup in WbDrawDispatcher.WalkClassify.cs. Tests may change only tests/AcDream.App.Tests/Rendering/Wb/InstanceGroupClearTests.cs, tests/AcDream.App.Tests/Rendering/Walk/WalkStaticStreamPopulatorTests.cs, and the directly affected existing rendering test file if compile fallout requires it. Documentation is limited to this packet, docs/architecture/worldbuilder-inventory.md, and docs/architecture/acdream-architecture.md. No register edit is expected; if source truth disproves that, stop and return the fact instead of silently changing scope.

Must not change queue/router/pipeline/list membership, capacity, flush/barrier, particle preparation, per-cell sort/merge, package/content/RHI/shader state, or graphical behavior. No client launch from the implementation/review worktree.

Automated return: git diff --check; Release solution 0W/0E; focused Wb group/cache/digest + walk per-cell/order + queue/particle/router suite; both real production 0-B pins; shader/manifest/SPIR-V 32/32; hermetic lane; and InstalledDat with exactly the documented global set plus the six retained AlphaFlushCounts_*, no new failure. The implementer commits one bounded change on a clean worktree and returns exact files, counts, and mutation-first- failure text.

Sequential reviews: first, retail/deletion fidelity verifies the named decomp and paired bytes, that only pre-append per-cell CYpt survives, and that every live distance owner above was preserved. Second, production/gate honesty checks call reachability, diagnostic-digest consequences, cache/reset/storage lifecycle, allocation, allowed scope, every mutation claim, and all gate counts. A failed lens gets one bounded fix contract; a third fix round stops and is written up. Dual PASS lands c3b and unlocks G3.

22.7 S4-c3b implementation result (implementer, 2026-09-04)

PASS for the bounded implementation return. The classic grouped dispatcher no longer carries CachedBatch.LocalSortCenter or InstanceGroup.LocalSortCenters; their constructor/cache-hit/append/reset/ release and diagnostic-hash plumbing is gone. The discarded alpha camera parameter is also absent from DeferTransparentGroups, BuildTransparentSubmissionDigest, CreateDispatcherSubmission, ObserveCurrentDispatcherSubmission, and ObserveClassifiedDispatcherSubmission, with no camera tombstone remaining. The diagnostic transparent digest therefore hashes only rendered state plus the live submission ordinal, as intended.

Production-facing reflection/source pins prove the deletion and retain the separate live owners: WalkClassifiedBatch.LocalSortCenter/ SortDistanceSq, the transformed authored-center per-cell stable descending sort, and PartitionInstanceGroups(cameraWorldPosition) feeding opaque InstanceGroup.SortDistance. Existing cache-hit matrix composition, transparent submission-order digest, group lifecycle, walk/particle merge, queue/router, allocation, and shader/state tests remain green. The AlphaFlushCounts_* source-truth pin keeps exactly the content-empty replay, AP-238 (cell,list) coalescing, and AP-239/AP-240 list-membership reasons and explicitly preserves the fact that the former broad “per instance versus per subset” explanation was false. Static production truth rejects resurrection of RetailAlphaOrdering, FlushFartherThan, alpha-submit viewerDistance, or a discarded camera tombstone.

Automated return:

  • The first dotnet build AcDream.slnx -c Release --no-restore invocation did not reach compilation because the fresh worktree had no obj/project.assets.json files (NETSDK1004, 57 projects). One dotnet restore AcDream.slnx populated those assets; the Release rerun then passed with 0 warnings / 0 errors. This was dependency preparation, not a product retry.
  • focused App InstanceGroupClearTests|WalkStaticStreamPopulatorTests|ParticleRendererRouteTests|WalkFrameDriverTests|RetailAlphaQueueTests|RetailParticleGeometryClassifierTests — PASS, 132/132; focused Core WbDrawDispatcherBucketingTests|EntityClassificationCacheTests — PASS, 29/29 (161/161 aggregate);
  • the four new deletion/truth pins — PASS, 4/4 after every mutation restore;
  • real warmed ProductionCellObjectParticleMerge_WarmedPathAllocatesZeroBytes|ProductionImmediateMesh_WarmedDrawImmediateParticleSubmissionRhiDoesNotAllocate — PASS, 2/2, both observing 0 managed bytes;
  • VulkanShaderDescriptorContractTests|VulkanShaderManifestTests|RenderPackSpirvValidatorTests — PASS, 32/32; no shader, SPIR-V, manifest, RHI, or pipeline file changed;
  • official no-retry 14-assembly hermetic gate — PASS, 16,755 passed / 0 skipped / 0 failed; evidence artifacts/s4-c3b-hermetic-20260904;
  • InstalledDat with explicit C:\Turbine\Asheron's Call, inclusive of the retained KnownFailures — 385 passed / 10 expected failed / 1 skipped. The failures were exactly TowerAscent, the two #383 layout sweeps, Oh_doorway_still_first_frame_diff (#458), and the six AlphaFlushCounts_*; the skip remained Sweep_the_lookin_gate_decodes_against_the_street_fixture. No new failure appeared; evidence artifacts/s4-c3b-installed-inclusive-20260904.

Mutation ledger (each mutation was applied alone and restored by patch before the next; the restored pin set passed 4/4):

  1. Restoring InstanceGroup.LocalSortCenters first failed ClassicGroupedShapes_DeleteDeadSortCenterSidecarsButRetainWalkCyptKey at its second Assert.Null: expected null; actual List<Vector3> LocalSortCenters.
  2. Restoring CachedBatch.LocalSortCenter first failed the same pin at its first Assert.Null: expected null; actual Vector3 LocalSortCenter.
  3. Restoring the DeferTransparentGroups(Vector3, Matrix4x4) parameter and tombstone first failed AlphaSubmissionShapes_DeleteDeadCameraChainButRetainOpaqueCameraDistance: Assert.Equal expected [Matrix4x4], actual [Vector3, Matrix4x4].
  4. Restoring cameraWorldPosition on BuildTransparentSubmissionDigest first failed the same pin's next Assert.DoesNotContain: the parameter collection contained Vector3 cameraWorldPosition at position 1.
  5. Replacing the exact three-reason prose with a false broad fourth reason first failed AlphaFlushCountKnownFailure_StatesOnlyTheThreeExactReasons at Assert.Contains: the required former broad "per instance versus per subset" explanation was false. substring was absent.
  6. Restoring an executable RetailAlphaOrdering symbol first failed ClassicGroupedAlphaSourceTruth_DeletesDeadOrderingChainAndPreservesLiveOwners at Assert.DoesNotContain: substring RetailAlphaOrdering was found.

The implementation changes only the three allowed production files, the two named App test files, the one directly affected Core rendering test file, and this result. AD-119 and AP-238 through AP-243, queue/router/list membership, capacities, barriers, particles, per-cell ordering, building/private/portal distances, shaders/RHI, package/content, and graphical behavior are unchanged. No graphical client was launched.

23. S4-c3b gate-provenance fix contract (2026-09-04)

The production/gate-honesty lens found no code, test, renderer, scope, or gate defect. It found one evidence-provenance omission in §22.7: both official gate artifact sets were captured on the restored, uncommitted c3b implementation tree before the implementation commit, so their embedded identity names parent a0523e605 and WorktreeDirty=true rather than tip 4eca2a4f. The dirty-file inventory also names WalkTraceConformanceTests.AlphaDepthTranscript.cs, although that file is byte-identical at base and tip and is absent from the final diff.

Make one packet-only correction to §22.7. State the artifact timing and identity explicitly; state that the transcript entry was transient mutation-worktree dirtiness, not an active mutation during either official gate; and ground that statement in the hermetic TRX passing AlphaFlushCountKnownFailure_StatesOnlyTheThreeExactReasons plus the exact base/tip/current blob identity. Do not change production, tests, register, architecture, inventory, handoff, plan, memory, or artifact files, and do not rerun either full gate or launch a client.

Narrow verification: verify both cited summaries contain parent a0523e605/WorktreeDirty=true; verify both SHA manifests; verify the transcript blob is identical at base, tip, and current worktree; verify the hermetic TRX records the source-truth pin PASS; run git diff --check. Commit the packet-only correction and return the exact evidence. The lead then performs one narrow gate-honesty re-review; no additional retail review is required because retail and renderer behavior are untouched.