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

@@ -393,12 +393,18 @@ authored version can be deleted.
`a=255`). That is why a splash render needs `--black` rather than the default
backdrop. ⚠️ Not a general rule: the main menu's measured order puts one `.prm`
at position 4 and the other **last** (the transition fade).
⚠️ **And the splash's recorded paint order `[0,2,4,6,1,3,5]` is a temporal
sequence, not a depth order.** Its glows and logos never share a frame, so
their relative depth was never observable — the vector records the order they
were *seen in*. Element 0 (the `.prm`) is a genuine depth observation because it
co-occurs with everything. **Do not read the rest as depth and composite all
seven at once** — that is precisely what fails to reproduce the screen.
**The splash's recorded paint order `[0,2,4,6,1,3,5]` is a real depth
order** — read off the runtime child array, and independently backed by the
static layer key (glows `0xa100` sort before logos `0xa110`;
`paint_order_audit` reports derived == measured, 0 ties). A same-day claim on
this page that it was "a temporal sequence, not depth" was **withdrawn**; see
the ❌ section in the linked page for why, if you read it before the fix.
⚠️ Separately and still true — and it is an **activation** fact, not a
paint-order one: the splash's glows and logos are never on screen together
(glows f94115, logos f116211,
[timeline](../re/data/splash-phase-timeline.txt)). Compositing all seven at
once reproduces no frame of the real screen. Depth says *what covers what*;
it does not say *what is up*.
[`structures/ui-prm-primitives.md`](../re/structures/ui-prm-primitives.md)
* **Menu order is geometric.** Buttons sorted top-to-bottom by resting Y. This is

View File

@@ -826,11 +826,15 @@ agent's loop prompt, i.e. nowhere durable. See [`README.md`](README.md) for the
four-entry enumeration showed none exists, and the question closed statically.
A hypothesis that predicts an artefact can be killed by looking for the
artefact, which is often far cheaper than measuring the behaviour.
* **Two things that never co-occur have no observable relative order.** A
"measured paint order" recorded from a running game looks like depth
information throughout, but between elements that never share a frame it can
only be the sequence they were *seen in*. The splash's vector mixes both kinds
— element 0 is real depth (it co-occurs with everything), the glow/logo split
is not — and the difference matters, because reading it as depth invites
compositing every element at once. When recording an order, note which pairs
actually appeared together.
* **Check what a "measured" value was measured *from* before reasoning about
its limits.** Two things that never co-occur have no observable relative order
— true, and a real limit on any order read from a *draw capture*. I applied it
to the splash's paint order and withdrew it hours later: that vector is a read
of the runtime **child array**, which has a definite order whether or not its
children are ever drawn together, and the two halves in question also carry
distinct static layer keys. Both the provenance and an independent static field
said the order was real. The general trap is not the co-occurrence rule, it is
applying a source-specific limit to a value from a different source: the word
"measured" covers several kinds of evidence, and the page that recorded it
usually says which — `ui-screen-runtime.md` said "child slots" in as many
words. Read that line before building an argument on top of it.

View File

@@ -595,9 +595,13 @@ neighbourhood, not just the line.
glows — so whichever was active, a subset of its elements was drawn at a time.
Selective activation is reinstated on evidence.
[`ui-group-start-time.md`](structures/ui-group-start-time.md)
* "the splash's `measured_paint_order` records a front-to-back depth order" →
**mis-typed.** Its glows and logos never share a frame (0 overlap in 235), so
their relative depth was never observable — between those halves the vector
records the *temporal* order they were seen in. Element 0 (`palogo_eff0.prm`)
is a genuine depth observation, because it co-occurs with everything.
[`ui-prm-primitives.md`](structures/ui-prm-primitives.md)
* ~~"the splash's `measured_paint_order` records a front-to-back depth order" →
mis-typed; between its glow and logo halves it records only the temporal order
they were seen in."~~ → **that refutation is itself refuted (same day).** The
vector is a read of the runtime **child array** (`ui-screen-runtime.md`:
"paint order (child slots)"), not of the draw capture, so co-occurrence does
not bear on it; and the halves carry *distinct* T8aD layer keys
(`0xa100` < `0xa110`, `paint_order_audit`: 0 same-key ties), so the file orders
them regardless. The no-overlap measurement was correct; the inference from it
was not. What survives: a capture of this screen can only cross-check the order
*within* each half. [`ui-prm-primitives.md`](structures/ui-prm-primitives.md)

View File

@@ -0,0 +1,23 @@
# How much of each recorded paint order its draw capture actually cross-checked.
# 2026-08-29, tools/re-capture/order_crosscheck_reach.py
#
# The three measured_paint_order vectors are reads of the runtime CHILD ARRAY
# (ui-screen-runtime.md: "paint order (child slots)"). These captures are the
# cross-check, not the source. Quads = indices/4: a single draw can carry
# several (the menu's draw 9 has indices=24 = 6 quads), so counting draws
# under-reads what is on screen.
== docs/re/captures/title-screen-draw-order.log
frame 1: 8 draws, 12 quads, 5 textures
frame 2: 8 draws, 12 quads, 5 textures
frame 3: 8 draws, 12 quads, 5 textures
textures in EVERY captured frame: 5 of 5
== docs/re/captures/title-draw-order-with-alpha.log
frame 1: 8 draws, 12 quads, 5 textures
frame 2: 8 draws, 12 quads, 5 textures
textures in EVERY captured frame: 5 of 5
== docs/re/captures/main-menu-draw-order.log
frame 0: 9 draws, 16 quads, 5 textures
frame 3: 7 draws, 9 quads, 4 textures
textures in EVERY captured frame: 4 of 5
absent from some frame: ['11C30000']

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.