revert #176/#177 cap raise: the uncapped light pool exposes unported per-cell reach semantics — defer to A7

The MaxGlobalLights 128->1024 fix (4d25e04d) was live-tested and made
the eviction pops stop — but with the full 366-fixture pool active,
three unported retail lighting semantics dominate the Facility Hub:

(a) lights reach THROUGH solid floors/walls: retail registers lights
    per-CELL (insert_light 0x0054d1b0) so the under-room portals'
    purple light never touches the corridor above; our flat
    sphere-overlap selection has no reach/occlusion notion — rooms
    washed magenta (user screenshot).
(b) stationary weenie fixtures ride the DYNAMIC 1/d falloff (~9x
    retail's static 1/d3 bake curve at 3m) — the #143 isDynamic
    assignment is wrong for ACE-served world fixtures.
(c) an unexplained striped z-fight-like artifact on lit floor regions
    (user screenshot; no coincident dat geometry — the coplanar-pair
    sweep came back empty; not a striped texture — all corridor
    surfaces are plain Base1Image stone).

Reverted to 128. The cap is now documented as a LOAD-BEARING STOPGAP:
it accidentally approximates per-cell reach by keeping the pool local
to the camera. The #176/#177 root cause (cap eviction popping per-cell
light sets) stays CONFIRMED and fully documented; the real fix is the
A7 dungeon-lighting arc: per-cell light registration + the static
fixture curve + the stripe hunt, THEN uncap. The desired-end-state pin
is kept as Skip with the full pointer. Register row AP-85 rewritten to
match reality; ISSUES #176/#177 back to OPEN with the complete
mechanism story.

Suites: Core 2591+3skip / App 719 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-05 23:11:18 +02:00
parent 4d25e04d83
commit d591e3bbe5
5 changed files with 169 additions and 48 deletions

View file

@ -106,23 +106,34 @@ corridor, and (c) pops into existence on entering the room. Classic
portal-visibility miss: the stair geometry's cell is not reached by the
portal flood from the viewer's cell until the viewer crosses into it.
**Status update:** 🟡 FIX SHIPPED 2026-07-06 — pending user gate.
**Root cause (found via the probe launch):** the geometry never vanished —
its LIGHTS did. `BuildPointLightSnapshot` kept only the `MaxGlobalLights=128`
point lights nearest THE CAMERA; the Facility Hub registers 366 fixtures, so
238 were evicted per frame by camera distance. A room whose torches all
ranked past the cap rendered at bare 0.2 ambient (near-black in a dungeon =
"not visible"); approaching re-admitted them ("pops into existence"); the
eviction boundary sweeping with the camera dropped the ramp's lights
mid-descent ("disappears on the last step"). Retail's
`minimize_object_lighting` (0x0054d480) has no global camera-nearest cap.
**FIX:** cap raised to a non-biting 1024 safety valve (register row AP-85);
pin `LightManagerTests.PointSnapshot_HubScaleLightCount_ObjectSelectionIsCameraInvariant`
(RED at 128, GREEN at 1024). Investigation ledger (12 refuted mechanisms +
the probe run that discriminated):
**Status:** OPEN — root cause CONFIRMED; fix DEFERRED to the A7
dungeon-lighting arc (the cap-raise fix was live-tested and REVERTED,
see below).
**Root cause (confirmed via the probe launches):** the geometry never
vanishes — its LIGHTS do. `BuildPointLightSnapshot` keeps only the
`MaxGlobalLights=128` point lights nearest THE CAMERA; the Facility Hub
registers 366 fixtures, so 238 are evicted per frame by camera distance.
A room whose torches all rank past the cap renders at bare 0.2 ambient
(near-black in a dungeon = "not visible"); approaching re-admits them
("pops into existence"); the eviction boundary sweeping with the camera
drops the ramp's lights mid-descent ("disappears on the last step").
Retail's `minimize_object_lighting` (0x0054d480) has no global
camera-nearest cap.
**Why the fix is deferred:** raising the cap to 1024 (commit `4d25e04d`)
made the pops stop but exposed three unported retail lighting semantics
that DOMINATE the frame with the full pool active: (a) lights reach
through solid floors/walls — retail registers lights per-CELL
(`insert_light` 0x0054d1b0) so the under-room portal light never touches
the corridor above; our flat sphere-overlap has no reach notion; (b)
stationary weenie fixtures ride the DYNAMIC 1/d falloff (~9× retail's
static 1/d³ at 3 m — the #143 isDynamic misassignment for ACE-served
fixtures); (c) an unexplained striped z-fight-like artifact on lit floor
regions (user screenshot). Reverted to 128 (`AP-85` documents the
stopgap; the desired-end-state pin is Skip'd in LightManagerTests).
**A7 fix shape:** per-cell light registration (insert_light port) +
static curve for stationary fixtures + the stripe hunt, THEN uncap.
Full investigation ledger:
`docs/research/2026-07-06-176-177-render-pair-investigation.md`.
**Gate:** stairs/stair room stay visible (lit) from the corridor, through
the descent, at all approach angles.
**Acceptance:** the staircase renders whenever its room is visible through
the connecting opening, and stays rendered through the full descent.
@ -143,25 +154,28 @@ render; the physics fix landed (seam shake gone, user-gated) and the flash
REMAINS — so it is a render-side issue in its own right, correlated with
camera angle.
**Status update:** 🟡 FIX SHIPPED 2026-07-06 — pending user gate.
**Root cause (found via the probe launch):** per-cell LIGHTING pops, not a
draw failure. The probe run reproduced the flash while the ambient branch
([light] insideCell/0.2 grey — stable) and the portal flood ([pv-input] —
zero drops in 54k frames) were provably healthy — which eliminated the
last CPU-side theories and exposed the one channel the probes could not
see: per-cell 8-light SET COMPOSITION. `BuildPointLightSnapshot` kept the
128 lights nearest THE CAMERA of the Hub's 366 registered fixtures; an
in-range torch of a visible cell that ranked past the cap was evicted, so
that CELL's Gouraud lighting flipped as the camera moved — discontinuity
lines at exactly cell-seam granularity, camera-angle dependent (the chase
boom swings the camera position, re-ranking the 128), and a torch-losing
floor drops to dim blue-grey stone (the perceived purple flash). Twelve
other mechanisms refuted first — ledger in
**Status:** OPEN — root cause CONFIRMED; fix DEFERRED to the A7
dungeon-lighting arc (see #177 for the revert story — same mechanism,
same deferral).
**Root cause (confirmed via the probe launches):** per-cell LIGHTING pops,
not a draw failure. The probe run reproduced the flash while the ambient
branch ([light] — stable 0.2 grey) and the portal flood ([pv-input] —
zero drops in 54k frames) were provably healthy, which eliminated the
last CPU-side theories and left the one channel the probes cannot see:
per-cell 8-light SET COMPOSITION. The camera-capped snapshot (128 of the
Hub's 366 fixtures, nearest-to-camera) evicts in-range lights of visible
cells; the flipping unit is a CELL, so the discontinuities sit at exactly
cell-seam granularity, swing with the camera position (the chase boom),
and the dominant flipping light is the under-room PORTALS' purple —
hence purple flashes on the floor. Twelve other mechanisms were refuted
first — ledger in
`docs/research/2026-07-06-176-177-render-pair-investigation.md`.
**FIX:** `MaxGlobalLights` 128 → 1024 non-biting safety valve (AP-85);
pin `LightManagerTests.PointSnapshot_HubScaleLightCount_ObjectSelectionIsCameraInvariant`.
**Gate:** no purple/lighting flashes on floors at corridor seams from any
camera angle while running the 015E↔017A loop.
**Deferral:** the uncapped pool (live-tested `4d25e04d`, reverted)
stabilizes the pops but floods rooms with through-floor portal light
(no per-cell reach semantics), over-strong dynamic-curve fixture light,
and a striped floor artifact — the A7 arc owns the real fix (per-cell
`insert_light` registration + static fixture curve + stripe hunt, then
uncap). Register row AP-85.
**Acceptance:** no purple/placeholder flashes on dungeon floors from any
camera angle at the corridor seams.