docs(overhaul): define S4 c3 upstream order repair

This commit is contained in:
Erik 2026-09-04 12:42:01 +02:00
parent d8c88adeb0
commit 5c9da6fc25
3 changed files with 183 additions and 10 deletions

View file

@ -105,7 +105,8 @@ The reviewed implementation is `daaeab0ba`; the complete campaign stack is
preceded production/gate-honesty PASS. Fresh campaign build, focused, shader,
allocation, graphical, and same-session stationary A/B gates pass as recorded
below and in packet §17. Three of the five additional attempts remain unused.
S4-c2 is closed; next is a fresh S4-c3 deletion contract from landed code.
S4-c2 is closed. Next is packet §18's S4-c3a upstream-order repair,
followed by a fresh S4-c3b deletion contract from the repaired landed code.
**Historical state before the final round (kept for audit; do not execute its
landing procedure):**
@ -155,11 +156,14 @@ memory 17.7 MiB. G3/G4 remain unpassed.
## 4. After chunk 2
1. **S4 chunk 3 — deletions** (packet §4): whatever of the old queue/sort/
distance residue survives, the `AlphaFlushCounts_*` Facts if a real
content-bearing gate replaces them, the two `EnvCell`/CLIP residual rows'
re-check. Write the contract from the LANDED code, not from §4's 2026-09-03
guess.
1. **S4 chunk 3 — corrected into c3a order + c3b deletions.** The fresh landed
audit found the plan's chunk-2 `CShadowPart::insertion_sort` item is missing:
production feeds the correct FIFO in registry/static-then-dynamic/particle-
tail order, not stable per-cell CYpt order. Packet §18 is c3a's binding
contract: port the upstream object/particle order first. Only after dual
review and landing does the lead write c3b to delete proven dead camera/
sort-center residue and re-check `AlphaFlushCounts_*` plus AP-238/AP-240.
Packet §4's 2026-09-03 deletion guess is explicitly not dispatchable.
2. **G3 — S4's owner gate:** the lead runs `route-g3.txt` (13 matrix shots),
`route-g3b.txt` (the capture poses; pose 15 now outdoors), `route-g3c.txt`
(Nanto ×3, 300 s waits) with `pwsh -File tools/overhaul-selfgate/run-selfgate.ps1 -Label <l> -Route <file>`

View file

@ -1176,6 +1176,175 @@ 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. Next:
write S4-c3's bounded deletion contract from the landed code, not §4's old
guess, and re-check the AP-238/AP-240/`AlphaFlushCounts_*` residuals there.
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.