diff --git a/docs/port/DECISIONS.md b/docs/port/DECISIONS.md index 413f6a71..13c82420 100644 --- a/docs/port/DECISIONS.md +++ b/docs/port/DECISIONS.md @@ -9,7 +9,7 @@ dies, which is what this file is for. -152 sections. Search this before re-deriving anything. +153 sections. Search this before re-deriving anything. * [P0 — the exporter, 2026-08-28](#p0--the-exporter-2026-08-28) * [P1 — Godot draws the screen, 2026-08-28](#p1--godot-draws-the-screen-2026-08-28) @@ -163,6 +163,7 @@ dies, which is what this file is for. * [The `rest()` flash defect reaches four screens I ship — and the port already survives it](#the-rest-flash-defect-reaches-four-screens-i-ship--and-the-port-already-survives-it) * [Correction: those two are the *sound* path, which makes the rule stronger](#correction-those-two-are-the-sound-path-which-makes-the-rule-stronger) * [The two loading screens are no longer black, and it was the paint order](#the-two-loading-screens-are-no-longer-black-and-it-was-the-paint-order) +* [Adjudicating the Decoder's `rest()` replacement against the game](#adjudicating-the-decoders-rest-replacement-against-the-game) ## P0 — the exporter, 2026-08-28 @@ -8884,3 +8885,59 @@ holds it past the end and the game shows it throughout; the sparkle's identical that fails a control is worse than an ugly one that passes** — and I would have adopted this on its elegance if the control pair had not already been sitting there from the earlier mistake. + +## Adjudicating the Decoder's `rest()` replacement against the game + +They proposed posing every element at the **screen's** settle instant instead of +asking each element for its own resting pose, found their own control could not +validate it — *"a candidate cannot be adjudicated against the incumbent it is +meant to replace"* — and said the oracle number is what decides. It is, and I had +only ever run it on one screen. Running it on every capture-backed screen: + +| screen | candidate (settled) | incumbent (`rest`) | | +|---|---|---|---| +| `title` | **0.21 %** | 1.82 % | candidate | +| `publisher_logo` | **0.01 %** | 0.75 % | candidate | +| `developer_logos` | **0.01 %** | 0.33 % | candidate | +| `main_menu` | 0.07 % | 0.25 % | ⚠️ **confounded** | +| `extras` | 0.19 % | 0.46 % | ⚠️ **confounded** | + +✅ Three screens adjudicate cleanly and all three favour the candidate, by 9× to +75×. The settled figures are corroborated: they match `verify-capture`'s +independently recorded numbers to the digit. + +### 🔴 Two of the five rows are not evidence, and my first table said they were + +My first run had `main_menu` at **3.29 %** for the candidate — losing to the +incumbent by 13×, the opposite direction from everything else. That had no +plausible story, which is what made me look. + +`--screen=` shoots the frame immediately: the "settled" main_menu drew **6 of 16** +elements and skipped `ptframe1`, `ptframe2` and `ptmsg` as *"transparent at t=9"*. +It was a mid-build-in frame. **The same wrong-frame error as `title_jp`, caught +before publishing this time and only because the number's direction made no +sense.** Properly posed via `--menu --script=wait`, it is 0.07 %. + +⚠️ **But that fix introduces a confound, and it is fatal to those two rows.** The +only way to pose these screens settled is `--menu`, which also draws the **focus +record**; the `rest` column is rendered by `--screen`, which draws none. This +tool's own header records that difference: main_menu without focus is 2 159 +differing pixels — **0.234 %** — against 531 with it. My incumbent figure is +0.25 %. *The entire gap on those two rows is the focus record, not the pose.* + +So they stay in the table marked confounded rather than counted. **A 5–0 result +was available by not looking.** + +### What this does and does not settle + +✅ The candidate is better on every screen where the question can be asked +cleanly, against the game rather than against the incumbent — which is the +adjudication their failed control could not provide. + +⚠️ It does **not** validate their implementation. I tested the port's settled pose, +not `UiBuild::settle_time()`; the two agree in *direction*, and whether they agree +in value is unmeasured. And three screens are three screens. + +📌 They are right not to change `rest()` on this. I pin their crate, nothing I +ship reads `rest`, and a proposal whose evidence comes entirely from the consumer +has no business landing in the dependency on that basis alone.