port: the counter-example I kept asking for was in a file I wrote

For several iterations I said the MISSION-SELECT-versus-top-item ambiguity needed
a screen whose opening item is not its first, and that none was known. The Decoder
found one and reported it had been sitting unconnected in their corpus.

It is in mine too, and I authored it. authored/flow.json under
main_menu/buttons/ptbtn01 has read since 1defbe0 on 2026-08-29: 'MEASURED
destination (EASY/NORMAL/HARD/BACK, opening on NORMAL, then SELECT DATA)'.
DIFFICULTY opens on the second of four. So 'a screen opens on its first item' is
refuted as a general description of this game, and on EXTRAS, TUTORIAL and OPTIONS
the named item and the top item coincide by accident.

Worse than an index failing to amplify: my extras/initial_focus_why framed the
ambiguity as conditional -- 'it matters IF another screen is ever authored' -- in
the same file that already recorded such a screen. Future tense over a fact twelve
keys away. Corrected to name DIFFICULTY concretely.

MenuFlow.initial_focus's buttons[0] fallback is now documented as a repair for
broken data rather than a default, and that is measured rather than fastidious: if
a screen reaches that line silently the port shows a top-item default for a game
that does not always have one. No authored value moves -- DIFFICULTY is not a
GP_TITLE build and EXTRAS keeps ptbtn11, correct under either reading. Walk re-run
unchanged.

It does not settle the question, which is about reset rather than opening. That
needs the cursor moved inside DIFFICULTY, left and re-entered, and its forward
path crashes the guest at SELECT DATA so the run must go back rather than on.

No checker either of us has built would have caught this. Every instrument here
verifies that a claim matches a value; nothing detects that an answer already
written down is not being connected to the question it answers -- and mine had
both halves in one file.

It also makes the previous iteration's restraint look better: declining to promote
'4/4 submenus reset' to a rule was argued from the principle that a generalisation
should not pre-decide the next screen, and the next screen turns out to be one the
generalisation would have got wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
Sylpheed port agent
2026-08-31 01:37:30 +00:00
parent 7ebf5fc8c5
commit 55d30209d9
4 changed files with 78 additions and 2 deletions

View File

@@ -378,7 +378,19 @@
"measuring history -- which is precisely what made the caveat necessary while",
"persistence here was unknown.",
"",
"⚠️ WHAT IS STILL AMBIGUOUS, and it matters if another screen is ever authored:",
"⚠️ WHAT IS STILL AMBIGUOUS -- and the condition below is ALREADY MET:",
"",
"🔴 CORRECTED 2026-08-31. This read \"it matters IF another screen is ever",
"authored\" whose opening item is not its first. Such a screen exists and is",
"recorded IN THIS FILE: DIFFICULTY, under `main_menu/buttons/ptbtn01`, is",
"EASY/NORMAL/HARD/BACK and opens on NORMAL -- the SECOND of four. Measured:",
"driven with no d-pad, unchanged for 90 s, matching the committed capture at",
"r=+0.999 (Decoder, docs/re/captures/newgame-path/newgame-difficulty.png).",
"",
"So \"a screen opens on its first item\" is REFUTED as a general description of",
"this game. On EXTRAS, TUTORIAL and OPTIONS the named item and the top item",
"coincide BY ACCIDENT. A top-item rule would be wrong on DIFFICULTY.",
"",
"nobody can separate \"resets to MISSION SELECT\" from \"resets to the TOP ITEM\".",
"They coincide here -- ptbtn11 is both. The port's value is correct under either",
"reading, and the REASON is not established.",

View File

@@ -147,6 +147,12 @@ HANDOFF.
| ~~P1P7 — the keyframe record layout~~ | ~~adopt the corrected pose/time pairing~~ | — | ✅ **ADOPTED 2026-08-29 by pinning `formats-pin-2026-08-29c`.** This row was wrong twice: it said the change *"cannot be taken yet"* and that it *"reaches the port only when that branch lands on `main`"*. **It arrives when the tag is pinned**, which is what MISSION §2's tagging rule exists for. ⚠️ And the knob I tested first, `SYLPHEED_KF_TIME_SHIFT`, is a **retired partial fix** that left pose 0 untimed — the real correction is the tagged crate's default, with the old reading behind `SYLPHEED_KF_TIME_LEGACY=1`. **The blast radius was far smaller than this row predicted**: under the correction *every pose is timed* (866 keyframes, 0 untimed), so `pose_at`'s synthetic-exit branch became dead code rather than wrong code and nothing needed re-deriving. Oracle: `publisher_logo` 1.00 %→**0.75 %**, `developer_logos` 0.39 %→**0.33 %**, `extras`' differing region collapsing from 736×525 to **398×295 at the sweep position**. 🔴 Open cost: `sylpheed-cli` builds from the workspace crate, so `verify-screen` compares two decoder eras until the tag reaches `main`. Revert to the path dependency then. |
| ~~P7 / naming — the four unnamed builds~~ | ~~which locale and variant is each of entries 0, 1, 12, 15?~~ | — | ✅ **answered 2026-08-29** (`docs/re/ui-title-build-map.md`): all four are the loading screen, two variants — plain (7 elements) and dressed (10) — decoded from their own `pgloading_*` element names. ⚠️ **Not adopted as names yet, for two reasons the RE agent gave and one the port found.** Theirs: the executable names exactly two, and *which* bundle takes which name is 🟡 undecided, so `LOADING`/`LOADING2` must not go in an asset path; and locale is 🟡 — the English member of a pair is the one in the first half of `GP_TITLE.p00`, 8/8 structurally but only 3/3 where a capture can check, and the three pairs that matter are the three no capture can check. Mine: **the message gives the bundles as "0/1 and 10/11", which is the `is_build` ordinal, and `authored/screen_names.json` is keyed by PAK ENTRY** — in entry space 10 and 11 are `palogo_sqex` and `palogo_gamearts`, the splashes. See the refutation section in `DECISIONS.md`. |
## Half-answered, 2026-08-31 — derived from HANDOFF (today's `DIFFICULTY` delivery)
| Milestone | Needs | HANDOFF | State |
|---|---|---|---|
| P5 — "resets to the named item" vs "resets to the top item" | **move the cursor in `DIFFICULTY`, leave, re-enter** | today | 🟡 **HALF ANSWERED, and the half that landed was in my own file.** *"A screen opens on its first item"* is **refuted**: `DIFFICULTY` is EASY/NORMAL/HARD/BACK and opens on **NORMAL, the second of four** — measured, no d-pad, unchanged 90 s, r=+0.999 against the committed capture. 🔴 `authored/flow.json` has recorded *"opening on NORMAL"* since `eef45ec` (2026-08-29) — **I wrote the counter-example I then spent iterations asking for**, and framed the ambiguity as conditional in the same file. ❔ Still open is the **reset** half, which needs the cursor moved inside `DIFFICULTY` and the screen re-entered; its forward path crashes the guest at `SELECT DATA`, so the run must go back rather than on. ⚠️ No authored value moves — `DIFFICULTY` is not a `GP_TITLE` build; `EXTRAS` keeps `ptbtn11`, correct under either reading. |
## Open on my own tooling, 2026-08-31 — derived from HANDOFF `d38adcf`
| Milestone | Needs | HANDOFF | State |

View File

@@ -9,7 +9,7 @@ dies, which is what this file is for.
<!-- INDEX: generated by tools/port/index-decisions -- do not hand-edit -->
269 sections. Search this before re-deriving anything.
270 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)
@@ -280,6 +280,7 @@ dies, which is what this file is for.
* [The register check had no executable control, and an empty register passed forever](#the-register-check-had-no-executable-control-and-an-empty-register-passed-forever)
* [Two harness gaps closed, and one of them was mine done by hand](#two-harness-gaps-closed-and-one-of-them-was-mine-done-by-hand)
* [All four submenus reset, and I am not promoting it to a rule](#all-four-submenus-reset-and-i-am-not-promoting-it-to-a-rule)
* [🔴 The counter-example I kept asking for was in a file I wrote](#the-counter-example-i-kept-asking-for-was-in-a-file-i-wrote)
<!-- /INDEX -->
## P0 — the exporter, 2026-08-28
@@ -13744,3 +13745,49 @@ selection and 01 is still first. **NEW GAME is untested.**
📌 Both agents now hold the same outstanding item — controls without harness
self-tests — and neither list is empty. Mine is down to
`verify-transcode-fidelity`.
## 🔴 The counter-example I kept asking for was in a file I wrote
For several iterations I have said the MISSION-SELECT-versus-top-item ambiguity
would be decided by *"a screen whose opening item is not its first"*, and that no
such screen was known. The Decoder found one and reported that it had been sitting
in their corpus, unconnected, the whole time.
**It is in mine too, and I authored it.** `authored/flow.json`, under
`main_menu/buttons/ptbtn01`, has read since **2026-08-29** (`eef45ec`):
> *"MEASURED destination (EASY/NORMAL/HARD/BACK, **opening on NORMAL**, then
> SELECT DATA)"*
**DIFFICULTY opens on the second of four items.** So *"a screen opens on its first
item"* is **refuted as a general description of this game** — and on `EXTRAS`,
`TUTORIAL` and `OPTIONS` the named item and the top item coincide **by accident**.
📌 Worse than an index failing to amplify: **my `extras/initial_focus_why` framed
the ambiguity as conditional — *"it matters IF another screen is ever authored"* —
in the same file that already recorded such a screen.** Future tense over a fact
twelve keys away. Corrected to name DIFFICULTY concretely.
### What it changes in the port, and what it does not
* ✅ `MenuFlow.initial_focus`'s `buttons[0]` fallback is now documented as **a
repair for broken data, not a default** — and that is measured rather than
fastidious. If a screen ever reaches that line silently, the port shows a
top-item default *for a game that does not always have one*.
* ⚠️ **No authored value moves.** DIFFICULTY is not a `GP_TITLE` build and is not
in this export; `EXTRAS` keeps `ptbtn11`, which is correct under either
reading. Walk re-run to confirm: unchanged.
* ❔ **It still does not settle my question**, which is about *reset*, not
*opening*. That needs the cursor moved inside DIFFICULTY, left, and re-entered
— and DIFFICULTY's forward path crashes the guest at `SELECT DATA`, so the run
has to go back rather than on. Theirs to run.
📌 **And no checker either of us has built would have caught this.** Every
instrument in this project verifies that a *claim* matches a *value*. Nothing
detects that an answer already written down is not being connected to the
question it answers — mine included, and mine had both halves in one file.
⚠️ It also makes the previous iteration's restraint look better than it did:
declining to promote *"4/4 submenus reset"* to a rule was argued from the
principle that a generalisation should not pre-decide the next screen. **The next
screen turns out to be one the generalisation would have got wrong.**

View File

@@ -65,6 +65,17 @@ func focus() -> String:
## the first button rather than to nothing, and SAY SO: a menu that opens with
## no focus looks like a rendering bug, and this is the one place that mistake
## would hide.
##
## 🔴 THE FALLBACK IS A REPAIR, NOT A DEFAULT, and since 2026-08-31 that is
## measured rather than fastidious. `DIFFICULTY` -- EASY/NORMAL/HARD/BACK --
## opens on **NORMAL, the second of four**, so "a screen opens on its first item"
## is refuted as a description of this game. On `EXTRAS`, `TUTORIAL` and
## `OPTIONS` the named item and the top item coincide by accident.
##
## So `buttons[0]` here is what to draw when the DATA IS BROKEN, and it warns
## precisely because it is not a claim about the game. If a screen ever reaches
## this line silently, the port will be showing a top-item default for a game
## that does not always have one.
func initial_focus(name: String, buttons: Array) -> String:
if buttons.is_empty():
return ""