port: which-focus -- a focus detector for the Decoder, with the control wired in

S00A is blocked on knowing which button a screenshot has focused.
`newgame_path.sh` assumed NEW GAME at boot, drove on it, and landed in a tutorial
mission -- HANDOFF Q5 measured focus as UNSTABLE across boots. Counting presses
cannot substitute: up from the first item wraps to the last, so no fixed number
of presses lands on a known item from an unknown start.

The Decoder's own attempt, a per-row brightness statistic, FAILED the control --
it picked NEW GAME on the capture whose filename says OPTIONS. The
render-difference method passes it, so this packages it as a script.

IT RUNS THE CONTROL ON EVERY INVOCATION, not once when it was written, and
refuses to report anything if the control fails.

  live-main-menu-options-focused  KNOWN ANSWER      OPTIONS         4.7x
  live-main-menu                  the question      NEW GAME       11.4x
  live-extras                     KNOWN from corpus MISSION SELECT  4.2x
  live-title-press-a              no menu at all    refuses         1.0x

The extras row is a second known answer I did not plant -- authored/flow.json
already records "MEASURED: EXTRAS opens focused on MISSION SELECT
(live-extras.png)" -- and the tool reaches it independently. The title row is the
negative control.

AND THE REFUSAL NOW CARRIES A NON-ZERO EXIT CODE. The first version printed "do
not act on this" and exited 0, so a caller scripting it -- which is the entire
point -- would have read a refusal as an answer. Same defect as a checker
claiming a check it skipped, and the fifth instance of that shape this session.

What it is not: it identifies focus in ONE FRAME and says nothing about what
selects focus. Q5's instability stands.

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-29 17:29:48 +00:00
parent 4e249d9d63
commit 28d90449e6
2 changed files with 159 additions and 0 deletions

View File

@@ -3804,3 +3804,54 @@ Re-deriving the transfer curve on the correctly-posed pair gives 1.20 / 1.26 /
So the focus-state contamination it flagged really did not move the trend. Its
reproduction stands as a second opinion after all, and that is now a measurement
rather than a hope.
## `tools/port/which-focus` — the Decoder asked for a detector, and it carries its own control
`S00A` is blocked on knowing which button a screenshot has focused.
`newgame_path.sh` assumed NEW GAME is focused at boot, drove on that assumption,
and landed in a **tutorial mission** — because HANDOFF Q5 measured focus as
*unstable across boots*. And counting presses cannot substitute: ⬆ from the first
item wraps to the last, so no fixed number of presses lands on a known item from
an unknown start.
The Decoder's own attempt — a per-row brightness statistic — **failed the
control**, picking NEW GAME on the capture whose filename says OPTIONS. The
render-difference method passes it, so it is now a script that agent can run.
### It runs the control on every invocation, not once when it was written
```
control -- live-main-menu-options-focused.png (answer is in the filename):
OPTIONS 1285 <- picked
EXTRAS 6073
...
-> OPTIONS, margin 4.7x CONTROL PASSED
```
If that fails, the tool **refuses to report a result at all**. A control that
does not execute is not a control, and this one cannot be skipped.
### Three checks, and one of them independently reproduces a corpus measurement
| input | verdict | margin |
|---|---|---|
| `live-main-menu-options-focused` — **known answer** | OPTIONS | 4.7× |
| `live-main-menu` — the question | **NEW GAME** | 11.4× |
| `live-extras` — **known from the corpus** | MISSION SELECT | 4.2× |
| `live-title-press-a` — **no menu at all** | *refuses* | 1.0× |
The `extras` row is a second known answer I did not plant: `authored/flow.json`
already records *"MEASURED: EXTRAS opens focused on MISSION SELECT
(live-extras.png)"*, and the tool reaches it independently.
The title row is the negative control. A frame with no menu in it gives a margin
of 1.0× and the tool says *"this frame does not decide it. Do not act on this."*
⚠️ **And that refusal now carries a non-zero exit code.** The first version
printed the warning and exited 0 — so a caller scripting it, which is the entire
point, would have read a refusal as an answer. That is the same defect as a
checker claiming a check it skipped, and it is the fifth instance of that shape
between the two of us this session.
**What it is not:** it identifies focus in *one frame*. It says nothing about
what *selects* focus; Q5's instability stands.