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

@@ -624,3 +624,37 @@ searches produced a positive account. The bit blocks nothing: the port's screens
composite at 0.947 correlation against a capture without it. **Parked**, with the
search space narrowed and the attribution method (child order, not size) left
sound for whoever picks it up.
## The reach of the draw-capture cross-check (2026-08-29)
The orders above are read off the **live child list**; the draw captures confirm
them. That confirmation is partial, and this is how partial — counted by
[`order_crosscheck_reach.py`](../../../tools/re-capture/order_crosscheck_reach.py),
data in [`order-crosscheck-reach.txt`](../data/order-crosscheck-reach.txt):
| screen | captured frames | draws/frame | quads/frame | order length | positions the capture confirms |
|---|---|---|---|---|---|
| title (entry 4) | 3 + 2 | 8 | 12 | 24 | **7** named in [`ui-screen-runtime.md`](ui-screen-runtime.md) |
| main menu (entry 8) | 2 | 9 / 7 | 16 / 9 | 16 | ≤ the richest frame |
| splash (11/14) | 235 | — | — | 7 | within each half only |
Three things this makes explicit, none of which changes an order:
* **Count quads, not draws.** The menu's draw 9 is `indices=24`**six** quads
batched out of one texture. A per-draw count reads 9 where 16 are on screen,
and an earlier pass of this analysis "found" three quads for six declarations
that way and briefly concluded elements were missing. They were batched.
* **The title capture is stable**: 8 draws / 12 quads / 5 textures, byte-for-byte
the same census in every one of the five captured frames across two logs. So
everything it shows co-occurs, and the 7 confirmed positions are mutually
ordered by observation. The other 17 rest on the child-list read alone — which
is the ground truth here, but it is one source, not two. (The census counts 8
draws where that page names 7 confirmed elements, so the capture carried a
little more than it was read for — not chased, and not a claim either way.)
* **The menu capture is not stable**: texture `0x11C30000` is in frame 0 and gone
by frame 3. Its order is still confirmed as far as any single frame goes.
* **The splash capture cannot cross-check its middle.** Glows (f94115) and logos
(f116211) never share a frame, so no capture of this screen orders one against
the other. The static layer key does (`0xa100` < `0xa110`), which is why the
order stands — see the ❌ withdrawn section in
[`ui-prm-primitives.md`](ui-prm-primitives.md).

View File

@@ -209,19 +209,39 @@ splash renders need `--black` to match.
position 4 and `pteff00.prm` **last** — that one is the screen-transition fade.
A `.prm` paints where its screen's order says; the splash's happens to be first.
## ⚠️ And the splash's "measured paint order" is a SEQUENCE, not a depth order
## ❌ WITHDRAWN (2026-08-29, same day): "the splash's measured order is a sequence, not depth"
`measured_paint_order` returns `[0, 2, 4, 6, 1, 3, 5]` for the splash, commented
*"the full-screen `.prm`, then all three glows, then the three logos"*.
This page briefly claimed that `measured_paint_order`'s `[0, 2, 4, 6, 1, 3, 5]`
records, between its glow half and its logo half, the *temporal* order they were
seen in rather than a depth order — on the grounds that the two halves never
share a frame (0 overlap in 235, which is
[measured and still true](../data/splash-phase-timeline.txt): glows f94115,
logos f116211).
The draw capture shows the glows and the logos **never appear in the same frame**
— 0 overlapping frames in 235 ([group start time](ui-group-start-time.md)). Two
elements that never co-occur have **no observable relative depth**. What that
vector records between its glow half and its logo half is the *temporal* order
they were seen in, not a front-to-back relationship.
**The measurement was right and the conclusion was wrong**, on two independent
grounds, either of which is fatal:
🟡 This does not make the render wrong — compositing them in that order is
harmless, and the ✅ for element 0 (the `.prm` first) *is* a real depth
observation, since it co-occurs with everything. But the type of the claim
matters for a consumer: **treating the vector as depth invites compositing all
seven elements at once, which is exactly what does not reproduce the screen.**
* **Wrong source.** The vector was never read off the draw capture. It is a read
of the live screen object's **child array**
[`ui-screen-runtime.md`](ui-screen-runtime.md) records it literally as
`paint order (child slots): 0 2 4 6 1 3 5`. A child list has a definite order
whether or not any two of its children are ever drawn together, so a
co-occurrence argument cannot touch it. The capture was the *cross-check*, not
the source. That page had already stated the limit honestly for the title
build: the `kind = 0x4` instances "draw at α=0 and so never appeared in the
capture, but their placement in the list is consistent with the grouping".
* **The order is in the file anyway.** `examples/paint_order_audit` on
`GP_TITLE.pak` entry 11: `derived == measured : YES`, `inverted pairs: 0`,
**`same-layer-key ties: 0`**. The glows and the logos carry *distinct* T8aD
layer keys (`0xa100` vs `0xa110` — [key](ui-paint-order-key.md)), so the glow
half sorts before the logo half **statically**, with no capture involved. The
relationship I called unobservable is decoded.
What survives is narrower and worth keeping: **a draw capture of this screen
cannot cross-check the glow-vs-logo half of the order**, because the two halves
never co-occur. The capture validates the order *within* each half only. So the
line in [`ui-paint-order-key.md`](ui-paint-order-key.md) — "read off the live
child list, checked against a draw capture" — has that reach limit on the splash.
The order itself is not in doubt; the *capture's* power to confirm all of it is.
The ✅ above for element 0 is unaffected: it is a direct draw observation.