The 2026-06-08 AM "physics rest micro-jitter" diagnosis is refuted with primary
evidence (door-recheck 216K standstill records: 0 position re-snaps; player
byte-stable during the flap). Two adversarial verification sub-agents confirmed:
- Retail roots the render at the camera viewer_cell (swept from the player via
SmartBox::update_viewer 0x453ce0; DrawInside(viewer_cell) 0x453aa0) and toggles
DrawInside / LScape::draw -- so acdream's eye-cell rooting + inside/outside
toggle are RETAIL-FAITHFUL. The locked-design "root at player cell" is wrong.
- The flap is render membership instability, eye-motion-driven: the visible-cell
set oscillates (8<->3) as the eye sweeps monotonically. Root = the
re-enqueue-on-growth DRIFT (PortalVisibilityBuilder.cs:322, MaxReprocessPerCell
=16) re-clipping each grown cell every round -> sub-cm eye jitter flips membership.
Fix (spec, not yet implemented): verbatim port of retail's enqueue-once flood
(ConstructView + AddViewToPortals): enqueue once on first discovery, clip each
cell's portals once, union late growth in place (AddToCell) + draw-reorder
(FixCellList), never re-enqueue. Kills the drift; rooting/camera/seal untouched.
This commit lands VERIFIED GROUNDWORK + design only:
- spec: docs/superpowers/specs/2026-06-08-portal-flood-enqueue-once-port-design.md
- findings: docs/research/2026-06-08-flap-physics-diagnosis-REFUTED-its-render-membership.md
- [pv-input] probe gains rawPlayer + yaw (disambiguates the varying input)
- 4 GREEN physics rest-stability tests (prove rest is bit-stable -> flap not physics)
- apparatus: launch-flap-capture.ps1, analyze_flap_live.py, find_burst.py
- captured fixtures: tests/.../Fixtures/flap-doorway/0xA9B4017{0..5}.json
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
44 lines
1.7 KiB
Python
44 lines
1.7 KiB
Python
import sys, re, math
|
|
from collections import Counter
|
|
|
|
pat = re.compile(
|
|
r'outRoot=(\w) flood=(\d+) eye=\(([^)]+)\) player=\(([^)]+)\) '
|
|
r'rawPlayer=\(([^)]+)\) yaw=([-\d.]+)')
|
|
rows = []
|
|
for l in sys.stdin:
|
|
m = pat.search(l)
|
|
if not m:
|
|
continue
|
|
rows.append((
|
|
m.group(1), int(m.group(2)),
|
|
tuple(float(x) for x in m.group(3).split(',')), # eye
|
|
tuple(float(x) for x in m.group(4).split(',')), # player (RenderPosition)
|
|
tuple(float(x) for x in m.group(5).split(',')), # rawPlayer (physics body)
|
|
float(m.group(6)))) # yaw
|
|
print("parsed pv-input rows:", len(rows))
|
|
if not rows:
|
|
raise SystemExit
|
|
|
|
print("flood histogram (outRoot,flood)->count:", dict(Counter((r[0], r[1]) for r in rows)))
|
|
|
|
def rng(idx):
|
|
return [max(r[idx][k] for r in rows) - min(r[idx][k] for r in rows) for k in range(3)]
|
|
print(f"eye range over window (m): {[round(v,6) for v in rng(2)]}")
|
|
print(f"render-pos range over window (m): {[round(v,6) for v in rng(3)]}")
|
|
print(f"raw-phys range over window (m): {[round(v,6) for v in rng(4)]}")
|
|
print(f"yaw range over window (rad): {round(max(r[5] for r in rows)-min(r[5] for r in rows),6)}")
|
|
|
|
flips = 0
|
|
samples = []
|
|
for i in range(1, len(rows)):
|
|
a, b = rows[i-1], rows[i]
|
|
if a[1] == b[1]:
|
|
continue
|
|
flips += 1
|
|
ed = math.dist(a[2], b[2]); pd = math.dist(a[3], b[3])
|
|
rd = math.dist(a[4], b[4]); yd = abs(b[5]-a[5])
|
|
if len(samples) < 18:
|
|
samples.append(f"{b[0]} {a[1]}->{b[1]:<2} eye={ed*1000:7.3f}mm rend={pd*1e6:8.1f}um raw={rd*1e6:8.1f}um yaw={yd*1000:8.4f}mrad")
|
|
print(f"flood flips in window: {flips}")
|
|
for s in samples:
|
|
print(" ", s)
|