docs(render): S3 chunk 1 fix round 2 — one weather OC per frame (pinned), literal EC/OC comparison, cost/wording items

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-03 11:52:36 +02:00
parent 05ebe2c805
commit 9b55d78a28

View file

@ -895,6 +895,73 @@ worktree on top of `079483bb6`; round 1 of the two the plan allows.
- Gates unchanged (§11.3); the InstalledDat lane must still show only the
three known failures; the new still-fixture rows must still reproduce.
### 11.6 Chunk 1 fix round 2 (lead, 2026-09-03 — the LAST round the plan allows; after the three-lens re-review of `36be6b598`)
Round 1 closed G1G7 and G10's LC/SC half with documented mutation checks,
and delivered the milestone (three of four kit poses reproduce exactly at
the eight-kind level; the fourth is #458, a walk finding, not chunk 1's).
The re-review FAILED on the weather `OC` and on what the EC/OC comparison
actually compares. Every item below is lead-verified.
- **H1 — one weather `OC` per frame, at the one weather draw (blocking).**
The print sits inside `DrawLandscapeSliceLate`, which the renderer calls
ONCE PER OUTSIDE-VIEW SLICE (`RetailPViewRenderer`'s "GameSky's weather
pass still runs through each active landscape view" loop), so an interior
root with the player outdoors prints 24 `OC` lines where retail prints
one. Retail draws the weather ONCE: `GameSky::Draw(sky, 1)` @0x00506ff0
`if (LScape::weather_enabled) DrawObjCellForDummies(after_sky_cell)`
@0x005070da, after `LScape::draw`'s blocks (@0x00506396). Fix: move the
weather draw (`_sky.RenderWeather(...)`) AND the `OC` print out of the
per-slice method into ONE call after the slice loop (a new
`RetailPViewPassExecutor.DrawWeatherOnce(frame)`, gated exactly as today
on `RenderSky && RenderWeather && playerOutside`), unclipped, no scissor —
chunk 4 later deletes the slice loop's remaining scissor/clip apparatus.
The `OC` id: retail sets the after-sky cell's DID from the position the
sky is updated with each frame (`after_sky_cell->SetDID(arg2->objcell_id)`
@0x00506dde), and every capture's `OC` equals the frame's `P` cell — so
print the SAME cell id the frame-root `P` line prints (the camera/viewer
cell), not the player's cell; say so in the comment. PIN: a test that
drives the executor's weather path with the flag on for (a) an outdoor
root and (b) an interior root with two exit-view slices, asserting EXACTLY
ONE `OC <viewer cell>` line per frame and none when the player is inside.
MUTATION: delete the print → the pin fails (quote it).
- **H2 — G9's second comment site (blocking as reported).** `WalkFrameDriver`'s
EC print comment still claims "EC and OC counts are always exactly equal";
replace with the real proof (`holtburg-doorway-still.walk.log:1126,1131,
1134,1137` — `EC a9b40100` four times in one frame across four look-in
`DC` turns; terrace-edge has 12 EC / 16 OC because of the weather `OC`).
- **H3 — compare retail's LITERAL EC/OC (minor → required).** The oracle
side of `Signature8` drops the captured `EC`/`OC` events and derives them
from the `DC` lists, so both sides derive and the EC/OC half can never
fail. Fix: the ORACLE side keeps its captured `EC`/`OC` events verbatim
(excluding only the trailing weather `OC` — the last event of an outdoor
frame when its id equals the `P` cell); the REPLAY side derives EC/OC from
the driver's real two reverse loops (the existing derivation), with the
same non-look-in deferral on both sides (close the `pendingRootCells`
asymmetry the note found). The four kit rows must still reproduce (three
exactly; #458's row stays `KnownFailure` at its documented position — if
the literal EC/OC comparison moves that first divergence EARLIER, record
the new position in #458's row comment). MUTATION: reverse the replay
derivation (OC before EC) → the cathedral-arrival row fails on an EC/OC
token (quote it).
- **H4 — the SC hook's flag-off cost (minor).** `OnSortCellTurn` runs
`RequireOpenFrame` and two range validations before reading the flag.
Read the flag FIRST and return; the remaining flag-off cost is one
interface call per land cell (state that in the hook's doc and in H5).
- **H5 — launch-options wording (minor).** Flag on: measured ≈1,2001,400
lines per outdoor frame (terrace-edge 1,384; cathedral-arrival 1,269;
doorway 1,187) — write the measured range, not "600800". Flag off: one
bool read per print site plus one interface call per land cell for the
`SC` hook, nothing else.
- **H6 — #458 citation (note).** The `KnownFailure` row's comment cites
`docs/ISSUES.md #458` and the divergence position; the InstalledDat lane's
known-failure set is now FOUR (two #383 layouts, TowerAscent, #458) — the
build lens compares against that set.
- Gates: §11.3 unchanged; hermetic fully green; InstalledDat exactly the four
known failures. If this round does not close every item, chunk 1 STOPS and
is written up (plan rule §5) with the emitter kept as-is and the open items
carried to the S3 review round.
### 11.4 Out of scope
Any validator, canonical format, or dashboard; any behavior change; any