diag #181: root-cause chain complete - flapping cell 0x0181, wall-press excitation, and the REAL defect: camera-flood-scoped light application

Issue181VisFlapReplayTests: headless flood replay at the live parked pose names cell 0x8A020181 - +-0.5mm eye perturbations flip its admission (at yaw15/pitch-20 for every direction). Issue181CameraParkStabilityTests: the camera loop parks BIT-EXACT with static inputs (0.00um over 2000 frames) - the live ~1mm/frame wander is the wall-press equilibrium (sought steps a*gap ~4mm into the wall per frame, the clip lands within adjust_to_plane's parametric 0.02 window; player physics bit-frozen per [resolve]). That wobble is retail-class. The defect is OURS: the A7 adaptation scopes light application to the camera flood's per-frame admission, so a sliver cell flapping flips whole lit regions; retail computes light reach once at registration (Render::add_static_light -> CObjCell::add_lights), camera-independent. Fix direction: registration-time per-light reach sets via the portal graph (pseudocode docs/research/2026-07-06-a7-per-cell-lighting-pseudocode.md). ISSUES #181 updated with the full chain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-06 21:04:34 +02:00
parent d9a4ca2355
commit 864e4d9e75
3 changed files with 233 additions and 7 deletions

View file

@ -73,14 +73,35 @@ WHILE the #180 camera strobe was live, so none of them cleanly cleared the rende
— and CLIP_DEBUG=1 forced gl_ClipDistance slots only; the AABB-scissor degrade sibling
may never have been disabled.
**Next step:** replay the flood headlessly (PortalVisibilityBuilder + LoadEnvCell
fixtures) at eye=(49.15,38.62,3.98) ± a micron/mm grid; identify the flapping cell
and the exact threshold (#129/#130 NDC floor-ceil class, or AP-19's PortalSideEpsilon);
fix the root — either the threshold's correctness or the eye-noise divergence
(retail-faithful candidates only, no hysteresis band-aids).
**ROOT CAUSE CHAIN (completed 2026-07-06 night, all headless/live-probed):**
1. The flapping cell is **0x8A020181** (`Issue181VisFlapReplayTests`: ±0.5 mm eye
perturbation flips its admission across several gazes — at yaw 15/pitch 20 it flips
for EVERY perturbation direction).
2. The excitation is the WALL-PRESS wobble, not µm noise: at the parked spot the camera
is pressed into a wall (`[resolve]` hit=yes n=(0,1,0) every frame; the player physics
position is BIT-FROZEN — in=tgt=out). The sought steps α·gap ≈ 4 mm into the wall per
frame and the sweep clips it back with `adjust_to_plane`'s parametric 0.02 termination
window (retail's own constant) → the published eye slides ~1 mm/frame along the wall.
`Issue181CameraParkStabilityTests`: with static inputs and no wall the camera parks
BIT-EXACT — the loop is healthy; a wall-press wobble of this scale is retail-class.
3. **The AMPLIFIER is ours and is the actual defect: the A7 adaptation scopes light
APPLICATION to the camera flood's per-frame admission** (light registration
`cellId:` scoping). Retail computes a light's reach through the portal graph ONCE at
registration (`Render::add_static_light``CObjCell::add_lights`), camera-
independent — a sliver cell flapping costs retail a few pixels; it costs us whole lit
regions (the washed-region strobe).
**Acceptance:** parked camera in the washed spot → vis count constant across 10k+
frames; frame-pair pixel diffs show no region-shaped changes; the user sees no flicker.
**The fix:** replace camera-flood light scoping with retail's registration-time light
reach sets (per-light cell-set walk from the light's own cell through the portal graph;
decomp pseudocode already on disk:
`docs/research/2026-07-06-a7-per-cell-lighting-pseudocode.md`). The wall-press wobble
and the binary knife-edge admission then match retail's visible behavior (sub-pixel
consequences). No hysteresis/damping band-aids on the flood.
**Acceptance:** parked pressed camera in the washed spot → lit regions steady (the
`[flap]` vis 31↔32 flap may legitimately persist at sub-pixel visual cost); frame-pair
pixel diffs show no region-shaped changes; the user sees no flicker; #176 re-gate
(steady purple wedge) passes.
---