docs: withdraw yesterday's "paint order is a sequence" -- wrong source

Last iteration I claimed the splash's measured_paint_order [0,2,4,6,1,3,5]
records, between its glow and logo halves, the temporal order they were
seen in rather than depth -- because the halves never share a frame.

The no-overlap measurement is right (glows f94-115, logos f116-211). The
inference is wrong, on two independent grounds:

  * Wrong source. That vector is not a read of the draw capture. It is a
    read of the live screen object's CHILD ARRAY -- ui-screen-runtime.md
    records it literally as "paint order (child slots)". A child list has
    a definite order whether or not its children are ever drawn together,
    so co-occurrence does not bear on it. The capture was the CHECK.
  * The order is in the file anyway. paint_order_audit on GP_TITLE entry
    11: derived == measured, 0 inverted pairs, 0 same-layer-key ties. The
    glows and logos carry distinct T8aD keys (0xa100 < 0xa110), so the
    file orders the halves statically, no capture involved.

I asked the question that started this iteration -- do the title and menu
orders have the same problem -- and the answer is that none of the three
does, for the same reason.

What survives is narrower and now recorded with numbers: how much of each
order its capture actually cross-checks. The title capture is stable (8
draws / 12 quads / 5 textures, identical in all five captured frames
across two logs) and confirms 7 of 24 positions; the menu capture is not
(texture 0x11C30000 present in frame 0, gone by frame 3); the splash
capture cannot cross-check its middle at all.

A counting trap worth the tool: count QUADS, not draws. The menu's draw 9
is indices=24 -- six quads batched from one texture. Counting draws reads
9 where 16 are on screen, and an earlier pass of this analysis briefly
"found" three quads for six declarations that way and concluded elements
were missing. They were batched.

METHOD: check what a "measured" value was measured FROM before reasoning
about its limits. The co-occurrence rule is real, and it is specific to
orders read from draw captures.
This commit is contained in:
Sylpheed RE agent
2026-08-29 05:19:44 +00:00
parent 2532c056be
commit 7a4e4333f4
7 changed files with 171 additions and 33 deletions

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env python3
"""How much of a recorded paint order did its draw capture actually cross-check?
The three `measured_paint_order` vectors in ui_layout.rs are reads of the live
screen object's CHILD ARRAY (ui-screen-runtime.md: "paint order (child slots)").
The draw captures are the cross-check, not the source -- so they bound how much
of each vector was independently confirmed, nothing more.
An element that is never drawn in the captured window (alpha 0, or its phase
never ran) contributes no confirmation. This counts what each capture could see:
draws, quads (indices/4 -- batched draws carry several), and distinct textures
per frame, plus which textures fail to appear in every frame.
"""
import re
import sys
import collections
def census(path):
frame, per, draws, tex = 0, collections.Counter(), collections.Counter(), collections.defaultdict(set)
for ln in open(path):
if ln.startswith('--- frame'):
frame = int(re.search(r'frame (\d+)', ln).group(1))
continue
m = re.match(r'\s*(\d+) prim=(\d+) indices=(\d+)', ln)
if not m or int(m.group(2)) != 13:
continue
per[frame] += int(m.group(3)) // 4
draws[frame] += 1
t = re.search(r'base=0x([0-9A-F]+)', ln)
tex[frame].add(t.group(1) if t else 'untextured')
return per, draws, tex
for path in sys.argv[1:]:
print(f'== {path}')
per, draws, tex = census(path)
if not per:
print(' no prim=13 draws')
continue
for f in sorted(per):
print(f' frame {f}: {draws[f]} draws, {per[f]} quads, {len(tex[f])} textures')
sets = [tex[f] for f in sorted(tex)]
common, allt = set.intersection(*sets), set.union(*sets)
print(f' textures in EVERY captured frame: {len(common)} of {len(allt)}')
if allt - common:
print(f' absent from some frame: {sorted(allt - common)}')