diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 06db8811..0e0b1be8 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -23,6 +23,43 @@ There is no fourth kind. If a row says *measured* or *undecodable*, the port is human can see it is a human decision, so that when it is later decoded the authored version can be deleted. +## 🟡 2026-08-30 — the black gap tracks the OUTGOING screen. Direction and button are ruled out. + +Your `black_hold_units` is escalated because four gaps gave no rule. A fifth +transition orders them. [`data/fade-four-transitions.txt`](../re/data/fade-four-transitions.txt). + +| transition | black gap | outgoing screen | +|---|---|---| +| menu → title (Ⓑ) | **0** | menu | +| menu → EXTRAS (Ⓐ) | **1** | menu | +| EXTRAS → menu (Ⓑ) | **2** | EXTRAS | +| title → menu (Ⓐ) ×3 | **3, 3, 3** | title | + +📌 **The gap is a property of the screen being LEFT.** Two transitions leaving the +menu give 0 and 1; the one leaving `EXTRAS` gives 2; the three leaving the title +give 3 every time. + +* **Direction is ruled out** — `EXTRAS → menu` (2) and `menu → EXTRAS` (1) are the + same pair both ways and differ. +* **Button is ruled out** — Ⓑ gives 0 and 2, Ⓐ gives 1 and 3. +* **Incoming screen is ruled out** — an incoming menu takes 3 (from the title) and + 2 (from `EXTRAS`). + +🔴 **It is still not a rule, and I would not author from it.** Three outgoing +screens with one value each (bar the title's three) means "each outgoing screen has +its own gap" merely restates the data — a rule would *predict*. And nothing +declared does: the outgoing screen's own closing ramp is 5, 5, 5, 4 frames against +gaps of 0/1, 2, 3, which if anything inverts, on three points. + +📌 **What it changes for you:** a *uniform* `black_hold_units` is now positively +excluded rather than merely unsupported — the value differs by outgoing screen +across a 0–3 frame range. If you ever key it, key it on the screen being left, and +only once someone has measured more than one value per screen. + +⚠️ Reach: five transitions, all `GP_TITLE`, three of the five being the same pair. +The one-frame gap on `menu → EXTRAS` is one *logged* empty frame with two +neighbours absent from the capture, so it is 1 measured with an upward uncertainty. + ## ✅ 2026-08-30 — the sweep leaves: what is settled, and what is not Closing a long thread so its conclusions are reachable here rather than only in diff --git a/docs/re/data/fade-four-transitions.txt b/docs/re/data/fade-four-transitions.txt index 4d502420..d29716c0 100644 --- a/docs/re/data/fade-four-transitions.txt +++ b/docs/re/data/fade-four-transitions.txt @@ -133,3 +133,43 @@ frame untextured full-screen textured (distinct) draws tex # 🟡 STILL OPEN: menu -> EXTRAS, the reverse of the pair measured at a 2-frame # gap. The instrument is fixed (WHERE=menu2extras now reaches its branch) and the # run has not been taken. + +################################################################################ +# FIFTH TRANSITION: menu -> EXTRAS via (A). 2026-08-30. +# The reverse of the pair already measured at a 2-frame gap, taken to test whether +# the black gap is a property of the screen PAIR or of the DIRECTION. +# +# Navigation verified both ways before arming: extras margin 11.23, back on the +# menu margin 11.60, against the discriminator's 9.9-11.7 control band. And the +# run announced its effective configuration -- "branch taken = menu2extras: back +# on the MENU with focus restored -> press (A)" -- which is the guard added after +# the previous run silently took the wrong branch. +# +# frames 42-46 outgoing quad 51, 102, 153, [45 absent], 255 -- 5 frames, +# matching build 5's declared close of 10 units = 5 frames +# frame 49 EMPTY: 3 draws, 0 textured +# frames 51+ EXTRAS building +# +# ⚠️ Frames 48 and 50 carry no `--- frame` header at all, so the gap is ONE logged +# empty frame with two unlogged neighbours. Quoted as 1, not silently rounded to 3. +# +################################################################################ +# ALL FIVE, ORDERED BY OUTGOING SCREEN -- which is the first thing that orders them +# +# transition black gap outgoing outgoing close (disc) +# menu -> title (B) 0 menu (build 5) 10 units = 5 frames +# menu -> EXTRAS (A) 1 menu (build 5) 10 units = 5 frames +# EXTRAS -> menu (B) 2 EXTRAS (build 6) 10 units = 5 frames +# title -> menu (A) x3 3, 3, 3 title (build 4) 8 units = 4 frames +# +# 🟡 THE GAP TRACKS THE OUTGOING SCREEN, not the direction and not the button: the +# two transitions leaving the MENU give 0 and 1, the one leaving EXTRAS gives 2, +# and the three leaving the TITLE give 3 every time. Direction is ruled out -- +# EXTRAS->menu (2) and menu->EXTRAS (1) are the same pair in both directions and +# differ; button is ruled out -- (B) gives 0 and 2, (A) gives 1 and 3. +# +# 🔴 BUT THAT IS NOT YET A RULE. With three outgoing screens and one value each +# (bar the title's three), "each outgoing screen has its own gap" only restates +# the data; a rule would PREDICT. And nothing declared does: the outgoing close is +# 5, 5, 5, 4 frames against gaps 0/1, 2, 3 -- if anything inverted, on three +# points. Recorded as a narrowing of WHERE to look, not as a rule. diff --git a/tools/re-capture/fade_decompose.sh b/tools/re-capture/fade_decompose.sh index fa63f37e..5a257bc5 100755 --- a/tools/re-capture/fade_decompose.sh +++ b/tools/re-capture/fade_decompose.sh @@ -67,6 +67,7 @@ done WHERE="${WHERE:-menu}" if [ "$WHERE" = "menu" ]; then + BRANCH="menu: (A) on the boot title -> arm on the MENU -> press (B)" # 2. one (A) on the boot title -> main menu; we arm THERE and press (B). python3 "$SD/pad.py" tap A 0.5 for _ in 1 2 3 4 5 6; do @@ -76,6 +77,7 @@ if [ "$WHERE" = "menu" ]; then [ "$s" = "menu" ] || { echo "NO MENU (screen=$s)"; exit 2; } BTN=B elif [ "$WHERE" = "extras" ] || [ "$WHERE" = "menu2extras" ]; then + BRANCH="extras-family: navigate to EXTRAS" python3 "$SD/pad.py" tap A 0.5 for _ in 1 2 3 4 5 6; do sleep 4; s="$(screen)"; echo " after A: $s" @@ -116,10 +118,13 @@ elif [ "$WHERE" = "extras" ] || [ "$WHERE" = "menu2extras" ]; then shot "$OUT/back-on-menu.png" echo " back on menu: $(python3 "$SD/which_title_screen.py" "$OUT/back-on-menu.png")" BTN=A + BRANCH="menu2extras: back on the MENU with focus restored -> press (A)" else BTN=B + BRANCH="extras: arm on EXTRAS -> press (B)" fi else + BRANCH="title: arm on the BOOT TITLE -> press (A)" # arm on the title itself and press (A): the incoming screen is then build 5, # whose declared fade-in is 12 units where build 4's is 16. BTN=A @@ -129,6 +134,19 @@ shot "$OUT/armed-on-$WHERE.png" # 3. arm the capture, dismiss the menu bar F10 opened, then press (B). # Everything between F10 and (B) is spent inside the capture window, so keep # it short: the window is FRAMES submitted frames, not seconds. +# ── EFFECTIVE CONFIGURATION ────────────────────────────────────────────────── +# Printed from the variables actually in force, NOT from $WHERE. A three-part +# patch once left a branch condition unapplied, so WHERE=menu2extras silently ran +# the `title` branch and produced a well-formed capture of a different transition. +# The data looked fine; only the ABSENCE of this branch's log lines gave it away. +# So: every run states what it is really about to do. +echo "── EFFECTIVE CONFIG ──────────────────────────────" +echo " requested WHERE = ${WHERE}" +echo " branch taken = ${BRANCH:-}" +echo " button to press = ${BTN}" +echo " arming on = $(screen)" +echo "──────────────────────────────────────────────────" +[ -n "${BRANCH:-}" ] || { echo "REFUSING: no branch announced itself"; exit 5; } xdotool windowactivate --sync "$win"; sleep 1 xdotool key F10; sleep 0.6 xdotool mousemove 900 400 click 1; sleep 0.6