handoff: split Q5's bundled 'measured' -- a label is as strong as its weakest cell

The port's authored/flow.json stamped title/on_cancel_why = 'MEASURED, HANDOFF
Q5' for a clause whose evidence cell in the source table reads 'none'. It did not
invent that: HANDOFF's Q5 row opened with one **measured** covering six clauses of
different strength, and HANDOFF is the document it authors against.

Split per clause. Measured: initial focus varies; up/down move one item per press
and wrap both ends; left/right do nothing; B on a submenu restores focus 4/4; B on
the main menu goes to the title in <= 0.4 s with no loading screen. NOT measured,
evidence cell empty: 'no auto-repeat at the durations tried', and 'B on the title
-> nothing'. Both marked do-not-stamp.

Also splits the source table's own up/down row, which bundled 'one item per press'
(indirectly but soundly evidenced by the 4-press wrap count) with 'no auto-repeat'
(nothing behind it, and the hedge was carrying the claim).

METHOD entry: the failure is in summarising, not at either endpoint. The source
table was honest and the consumer cited its source; flattening six claims into one
adjective created a provenance nothing supports. A strength label is not
distributive.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
sylph-decoder
2026-08-30 11:11:08 +00:00
parent c3b66c4b91
commit 7a63501bc1
4 changed files with 170 additions and 2 deletions

View File

@@ -883,7 +883,7 @@ discovered it after re-exporting. ❔ The sweeps may simply be a small term, and
| Q2 | which build is which screen state | ✅ answered | `GP_TITLE` is **8 screens shipped twice, EN/JP**: 4/7 title art, 2/3 the `PRESS Ⓐ` plate, 5/8 main menu, 6/9 `EXTRAS`, and ✅ **pak entries 0/1 and 12/15 are the LOADING screen** — two variants, plain and dressed, decoded from their `pgloading_*` element names (2026-08-29). ⚠️ **Read that in ENTRY space.** This row said "0/1 and 10/11" until 2026-08-29; that is true only of `screen list`'s ordinals, where 10→entry 12 and 11→entry 15. In entry space 10/11 are the **publisher and developer splashes** (`palogo_sqex`, `palogo_gamearts`). The port caught it; see [METHOD](../re/METHOD.md#mechanics-that-have-bitten). 🟡 which of the two is `LOADING` vs `LOADING2` is undecided; 🟡 the English member of a pair is the one in the first half of the data segment — [`ui-title-build-map.md`](../re/ui-title-build-map.md) |
| Q3 | paint order for the six screens | ✅ answered, ❔ tie-break | **decoded**: a `u16` layer key at `+0x0A` of each `T8aD` sprite header, stable-sorted with declaration index; unkeyed elements get an implied key. Confirmed on 5 measured orders + `EXTRAS` vs a capture. One residual: the **tie-break** is unknown and bites on one element of the title — [`structures/ui-paint-order-key.md`](../re/structures/ui-paint-order-key.md). ⚠️ **The key does not fully order a screen**: elements sharing a key are tied, and the tie-break is ❔ **undecodable from the bundle** — declaration table, `T8aD` header (exhaustive: every offset 0x00–0x7f at u8/u16/u32, both directions, **0** fields match the measured order against **64** for the control) and the RATC child order all give the same order the game does *not* use. ✅ **Your exposure is now measured at ZERO PIXELS (2026-08-29).** The 2 overlapping tied pairs on `EXTRAS` are `ptframe3`×`ptframe4` (the other is a `loop*` you never draw), and rendering the screen with that pair swapped changes **0 px** — because the two sprites put ink on ~3 600 pixels each and **share none of them**; the 102×132 "overlap" was a bounding-box artefact. Same on the main menu's `ptframe1`×`ptframe2`. This is blend-independent: layers that never touch the same pixel cannot be ordered wrongly. **Nothing about the tie-break can change a pixel on any of your five screens** — [`structures/ui-paint-order-derived-check.md`](../re/structures/ui-paint-order-derived-check.md) |
| Q4 | button → GamePart | ✅ answered | **measured** which screen all **5** buttons open, by pressing each one and reading the screen's own title off the framebuffer. ✅ **In the form you need it: exactly ONE main-menu button opens a `GP_TITLE` entry.** `EXTRAS` → **entry 6** (EN) / **9** (JP). The other four leave the archive: `NEW GAME` → `DIFFICULTY` → `SELECT DATA`; `LOAD GAME` → the save-slot list; `TUTORIAL` → the lesson list; `OPTIONS` → GAME/CONTROL/SOUND/SCREEN SETTINGS. None of those four is a `GP_TITLE` build — so a menu→submenu→back cycle inside this archive is `main menu ↔ EXTRAS` and nothing else. The **GamePart id is still a name match**, not a measurement, and 🔴 the "cheap way to measure it" this page used to point at is a dead route (the guest words are monotonic counters, not a screen id) — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
| Q5 | navigation semantics | ✅ answered | **measured**: initial focus varies boot to boot (2× `TUTORIAL`, 2× `NEW GAME`); ⬆⬇ one step, **wraps both ends**; ⬅➡ do nothing; Ⓑ returns to the parent **with focus restored**; Ⓑ on the main menu → title; Ⓑ on the title → nothing — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
| Q5 | navigation semantics | ✅ answered, ⚠️ **per clause** | 🔴 **This row used to open with a single `**measured**` covering six clauses of different strength, and the port's `authored/flow.json` copied that word into a `MEASURED` provenance stamp for a clause whose evidence cell reads `none`. A bundled label is exactly as strong as its weakest cell.** Split: ✅ **measured** — initial focus varies boot to boot (2× `TUTORIAL`, 2× `NEW GAME`); ⬆⬇ move **one item per press** (indirect: the 4-press wrap count only works if each press moves one) and **wrap both ends**; ⬅➡ do nothing; Ⓑ on a submenu returns to the parent **with focus restored** (4/4); Ⓑ on the main menu → **title**, ≤ 0.4 s, no loading screen (2026-08-30). 🟡 **NOT measured, evidence cell empty** — *"no auto-repeat at the durations tried"* (nothing records a **held** direction) and *"Ⓑ on the title → nothing"* (the one run that pressed there did so **during the build-in**, so its result is confounded). **Do not stamp either as MEASURED** — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
| Q6 | boot sequence + what drives it | ✅ answered | sequence **measured** end to end; the driver is **code, not data** — four search spaces closed, so the port **authors** the sequence — [`boot-config-and-gamepart-registry.md`](../re/boot-config-and-gamepart-registry.md) |
| Q7 | transitions | ✅ answered | a **fade through black**, drawn by the screen's own last-painting `.prm` quad. Fade-in ramp is **decoded** from its keyframes; the ~0.4 s fade-out is **measured** (not in the file) — [`screen-transitions.md`](../re/screen-transitions.md) |
| Q8 | menu audio bindings | ✅ answered | cue vocabulary + bank **decoded**; event binding is a **name match** (the authors' own event names). ✅ **You CAN have the SE audio** — ⚠️ an earlier version of this row said it was "undecodable from the disc"; that was **retracted** and the row was stale. Three cues are located in `Static.slb` and **decode to PCM**: d-pad move `0x1ec0` (4 packets), Ⓑ back `0x0ec0` (2), Ⓐ confirm `0x5d6c0` (6), all mono 48 kHz. The bank is a packed run of XMA waves with no delimiter, so a wave is only (offset, packet count) — and ⚠️ the file order is **not** cue-id order, so the index cannot be counted out — [`menu-audio-cues.md`](../re/menu-audio-cues.md) |

View File

@@ -1532,3 +1532,26 @@ control is what said so, which is the only reason the weaker number never got us
📌 Ask, before building a matcher: **does the artefact already state the answer?**
Screens have titles, files have magic, logs have names. A derived statistic is for
when nothing states it.
## A bundled label is exactly as strong as its weakest cell
`HANDOFF.md`'s Q5 row opened with a single **`measured`** and then listed **six**
clauses of very different strength — two of which had an evidence cell reading
`none` in the source table. The port agent's `authored/flow.json` then stamped
`title/on_cancel_why = "MEASURED, HANDOFF Q5"` for one of those two.
It did not invent that. **It read the label the summary offered**, and the summary
was the document it is told to author against.
⚠️ **The failure is in summarising, not in either endpoint.** The source table was
honest — it had the empty cells. The consumer was honest — it cited its source.
Flattening six claims into one adjective is what created a provenance that nothing
supports, and provenance is the part that gets believed later, long after anyone
would re-derive the value.
**So a summary row carries a label per clause, or it carries the weakest one.**
Never the strongest, and never one label over a list. If that makes the row ugly,
the row is telling you it is doing too much.
📌 The general shape: a strength label is **not distributive**. "These six things are
measured" is a claim about the conjunction, and a reader takes it about each element.

View File

@@ -18,7 +18,8 @@ with [`tools/re-capture/menu_focus.py`](../../tools/re-capture/menu_focus.py).
|---|---|---|
| **initial focus, main menu** | **`TUTORIAL`** — the *middle* item, not the top | 2/2 boots, the first frame after the menu appears |
| **initial focus, `EXTRAS`** | `MISSION SELECT` — the top item | [`extras-wrap.png`](captures/menu-nav/extras-wrap.png) |
| **up / down** | one item per press, no auto-repeat at the durations tried | |
| **⬆⬇ — one item per press** | one item per press | ✅ *indirect but sound*: the wrap montage's **4 presses from `EXTRAS` landing on `OPTIONS`** only counts out if each press moves exactly one |
| **⬆⬇ — no auto-repeat** | 🟡 *"no auto-repeat at the durations tried"* | **none** — and the hedge is carrying the claim. Nothing here records a *held* direction |
| **wrap at the top** | ⬆ from the first item goes to the **last** | [`wrap-montage.png`](captures/menu-nav/wrap-montage.png), panels 1→2 |
| **wrap at the bottom** | ⬇ from the last item goes to the **first** | same, panels 3→4, and 4 presses from `EXTRAS` landing on `OPTIONS` — i.e. wrapping — is what makes the count come out |
| **left / right** | **nothing**, on the main menu | cursor unmoved across one ⬅ and one ➡ |