port: P3 -- the boot title gets its PRESS (A) plate, and two of the RE agent's numbers do not agree

ScreenView now draws two builds at once, which it never had to before. It is a
second ScreenView in the same SubViewport rather than a subordinate screen
inside one: each build has its own timeline, its own textures and its own hold,
which is the entire content of the finding, and Node2D siblings already paint in
tree order. `paint_order` still means what it meant -- an ordering WITHIN a
build.

The delay is authored in flow.json on the BOOT STEP, not on the `title` screen.
What was measured is the boot title; whether the plate is there when the title
is reached again -- (B) from the menu, or after the attract movie -- is not, and
hanging it on the screen would quietly claim that it is.

REFUTATION, and it is the substance of this commit: the RE agent's authoring
instruction does not reproduce the RE agent's own measurement, and the gap is
3.97 s. The instruction is "when build 4 has settled, wait 2.13 s, composite
build 2". But build 2 has a group and this port plays groups -- ptbtn00 is alpha
0x00 at t=214, still 0x00 at t=236 while it slides 10 px up, and 0xff only at
t=238, which is 3.967 s at 60 units/s. So the plate is first VISIBLE at
settle+6.10 s, while what was measured -- the glyph counter leaving 154 -- is
visibility at settle+2.13 s. Both groups starting together puts it 0.38 s BEFORE
settle; build 2 starting at settle puts it at settle+3.97 s; landing on the
measurement needs build 2's group to start 2.51 s after build 4's, which is not
a landmark of anything.

The measurement is untouched -- it is an observation of the running game and I
have no standing to doubt it. What is refuted is the step that turns it into an
authoring rule. So the port ships the instruction, prints the discrepancy on
every boot, and files the row. Same call as the BGM sub-waves: a port that
quietly picks the number that looks right destroys the evidence, because a
corrected boot looks exactly like a correct one.

Also refuted, and it was mine: BLOCKED.md has said since P2 that "no element's
alpha reverses direction anywhere in this export, so nothing pulses". ptbtn00
reverses -- 0x00 -> 0xff -> 0x00 -- and it was in the export the whole time. The
claim had been checked against the screens P2 happened to be animating. The port
still draws no pulse, because no reading of this group yields the measured
2.24 s: the whole group is 4.47 s and from its first keyframe 0.90 s.

Gate: `--boot --capture=` writes one frame of the composited end state, instead
of the 600-PNG filmstrip that was previously the only boot artifact.
`--screen=title --overlay=press_start` raises the same composite in two seconds
for anyone who does not want to sit through 137 s of Theora.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WM5XL4HfrHuxz8RiMWdCMC
This commit is contained in:
Sylpheed port agent
2026-08-29 12:40:50 +00:00
parent 2ad839460c
commit 4f767e72f6
4 changed files with 353 additions and 7 deletions

View File

@@ -83,7 +83,11 @@ git log -1 --format=%h -- docs/port/HANDOFF.md # newer than 9ca1eb5? re-reconc
| P5 — Ⓑ on the main menu | **is Ⓑ what returns to the title, or the idle timer?** | Q5 | 🟡 stated in HANDOFF, no capture behind it. The title self-returns after ~810 s idle, so one unrecorded observation cannot separate them. `authored/flow.json` implements it and marks it *authored — likely but UNPROVEN*. **Not blocking** — P5 shipped with it — but it is the only navigation rule on that screen with nothing under it. Settled by one run that presses Ⓑ well inside the idle window, timestamped. |
| P6 BGM — the sub-wave count | **is a music bank's LEADING REGION a stem, or a decoder artefact?** | Q10 | 🔴 **HANDOFF and the decoders disagree, and P6 ships the disagreement.** `media::sound_bank_riffs("BGM_103.slb")` returns **three** sub-waves; HANDOFF Q10's census says a music bank is *"exactly two waves of identical duration (32/32 banks on the disc)"*. The third comes from `slb.rs:380` `to_xma_riffs`, whose hybrid branch emits a leading headerless packet region ahead of the `RIFF` waves — and `docs/re/REFUTED.md` already records that region as what makes `BGM_106``BGM_109` *"break the two-wave rule"*. Derived at HANDOFF `9ca1eb5`. **The exporter sums all three and writes a manifest warning**, because choosing which sub-wave to drop is a decoding question and MISSION §2 forbids this exporter answering one. So the menu currently plays a sum of three things where the census predicts two. What settles it: whether that leading region carries music. Raised with the Decoder 2026-08-29. |
| P3/P5 — the title plate | ~~does the idle title show `PRESS Ⓐ`~~ | Q2 | **answered 2026-08-29, NOT ON `main` YET, and it is the expensive answer.** Pointer from the Decoder, unverified by me at the time of writing: branch `auto/no-disc-and-menu-captures` at **`fb536df`**, `docs/re/title-plate-delay-measured.md`, per-frame traces in `docs/re/data/plate-timing-run{1,2}.tsv`. It confirms the 🔴 row below: `ScreenView` **does** have to draw two builds at once, and `--boot`'s plate-free end state is wrong. ⚠️ The Decoder flags a wrong way to read the number — time it from the frame build 4 *stops animating*, not from the frame it first appears; the two runs differ by half a second on the latter and 6 ms on the former. **Read the file, not this row.** Not taken at P6; this is the next iteration's work. |
| P3 — the plate's ONSET | **does the plate become visible 2.13 s after settle, or does its GROUP START then?** | Q2 | 🔴 **new, and it is a disagreement between two of the Decoder's own numbers.** `docs/re/title-plate-delay-measured.md` (`auto/no-disc-and-menu-captures` at `fb536df`, **not on `main`**) measures the plate *becoming visible* at settle + **2.13 s**, and instructs the port to *"wait 2.13 s, composite build 2"*. Those are 3.97 s apart, because build 2 has a group of its own and the port plays it: `press_start`'s `ptbtn00` is alpha `0x00` at t=214, `0x00` at t=236 (it slides y 560→550 invisible), `0xff` at t=238 — **3.967 s** from group start to full alpha at 60 u/s. Neither landmark reconciles them: both groups starting together puts full alpha 0.38 s *before* build 4 settles (`title` settles at t=261 = 4.350 s); build 2 starting at settle puts it at settle + 3.97 s. Landing on settle + 2.13 s needs build 2's group to start 2.51 s after build 4's, which is neither. **The port ships the instruction, not its own arithmetic**, prints the discrepancy on every boot, and is not choosing. First thing to check, and it is about the instrument rather than the game: is *"title settled"* (the glyph counter first reading 154) the same instant as the port's last-element settle? Raised 2026-08-29. |
| ~~P3/P5 — the title plate~~ | ~~does the idle title show `PRESS Ⓐ`~~ | Q2 | ✅ **answered and TAKEN at this iteration.** `auto/no-disc-and-menu-captures` at `fb536df`, `docs/re/title-plate-delay-measured.md`, traces in `docs/re/data/plate-timing-run{1,2}.tsv`. It is the third case: build 4 alone, then the plate composited over it. ⚠️ The delay is timed from where build 4 **stops animating**, not from where it first appears — measured the other way the two runs differ by 0.48 s against 6 ms. `ScreenView` now draws two builds at once, as a second `ScreenView` in the same `SubViewport` rather than a subordinate screen inside one. The onset question above is what is left. |
| P3 — the plate's PULSE | **what period does the plate pulse at, and which group boundary repeats?** | Q2 | ❔ **open, and the port draws no pulse.** The same finding measures the running plate pulsing continuously — peak/trough intervals 2.12 / 2.19 / 2.34 / 2.31 s, mean **2.24 s**. `press_start`'s group encodes exactly one cycle (`0x00``0xff` at t=238244 → `0x00` untimed), and **no reading of it produces 2.24 s**: the whole group is 268 units = 4.47 s, and from its first keyframe 54 units = 0.90 s. So repeating the group would be inventing a period. The port holds the plate at its settle (t=238, alpha `0xff`), which is what it does on every other screen and what the static oracle capture `live-title-press-a.png` shows. What settles it: which instant the group restarts from. |
| P5 focus ring — implementation | ~~the ring's spin period~~ | Q1 | ✅ answered (2.177 s, `4fa3099`) and **still not implemented** — the port draws 0°, a pose the corpus says the game never shows. Not blocked on anybody; it is queued behind P3's plate this iteration. |
## Answered since this file was last written — no longer blocking
@@ -236,9 +240,7 @@ right for an entry animation (the main menu settles at t=80, 1.33 s) and is
proven on the screen P2 gates. The **title** runs to t=269 — 4.48 s — and there
the port's settled pose and the decoders' `rest` disagree badly (max 142/255).
What is known: no element's alpha reverses direction anywhere in this export, so
nothing pulses, which removes the obvious reason to expect a loop without
disproving one. What would settle it: **a capture of build 4 alone**. The one
🔴 **REFUTED 2026-08-29, by the port, against its own export.** This paragraph said: *"no element's alpha reverses direction anywhere in this export, so nothing pulses, which removes the obvious reason to expect a loop without disproving one."* `press_start`'s `ptbtn00` reverses: `fade_argb` is `0x00ffffff` at t=214 and t=236, `0xffffffff` at t=238 and t=244, and `0x00ffffff` again on the final untimed keyframe. It was in the export the whole time and the claim was never checked against it — it was checked against the screens P2 happened to be looking at. The reason to expect a loop is back, and the running game pulses this exact element. What would settle it: **a capture of build 4 alone**. The one
live title capture composites the `PRESS Ⓐ` plate (build 2) over it, so it
cannot be diffed against the title by itself.

View File

@@ -1591,3 +1591,162 @@ dispatch on the extension, so a temp name must preserve it.**
The second is the more dangerous shape, and it is the one this project has
already warned itself about: a confident line of output pointing at nothing. The
rename's return is now checked and the failure is loud.
## P3, reopened — the boot title was missing the `PRESS Ⓐ` plate, 2026-08-29
P3 passed its gate with a boot that ended on build 4 alone. `BLOCKED.md` carried
that as 🔴 from the start: both states were captured, so the art was never the
question — the *sequence* was, and it is behavioural, so the port had no oracle
for it.
It is answered. `docs/re/title-plate-delay-measured.md`
(`auto/no-disc-and-menu-captures` at `fb536df`, **not on `main`** at the time of
writing) measures two independent boots: the title presents **without** the
plate, and the plate arrives **2.13 s** later, the two runs agreeing to 6 ms.
### Two builds at once, as two `ScreenView`s
`ScreenView` draws one screen. The obvious change was to teach it about a
subordinate overlay screen; the change made was to put a **second `ScreenView`
in the same `SubViewport`**, after the first.
That is what "two builds at once" actually is. Each build has its own timeline,
its own textures and its own hold — the plate's group runs independently of the
title's, which is the entire content of the finding — and Node2D siblings already
paint in tree order. The alternative would have put an `if overlay` in every
method that walks elements, and would have expressed the same information less
directly. The export's `paint_order` still means what it always meant: an
ordering *within* a build.
### The delay is timed from where build 4 stops animating
Not from where the title first appears. This is the finding rather than a detail:
measured from first-draw the two oracle runs differ by **0.48 s**, because the
build-in itself ran 1.64 s and 2.13 s and the emulator's frame pacing during an
animation is not the game's clock. Measured from settle they differ by 6 ms.
So `_boot_done` — the moment the sequencer already had for "this screen has
reached its hold" — is the landmark, and the overlay is due `after_settle_seconds`
later. A number taken from the wrong instant here looks exactly like a
measurement.
### The overlay is attached to the BOOT STEP, not to the `title` screen
What was measured is the boot title. Whether the plate is there when the title is
reached *again* — by Ⓑ from the main menu, or after the attract movie — is not
measured, and hanging the overlay on the screen would quietly claim that it is.
So it lives on the boot step in `authored/flow.json`, and `_drop_overlay` takes
it away with the screen it belongs to. `BLOCKED.md` carries the gap.
### Refutation — the RE agent's instruction contradicts the RE agent's measurement
**The claim under test**, quoted from the finding's *"What the port should
author"*: draw build 4, *"when build 4 has settled, wait **2.13 s**, composite
build 2 over it"*.
**It does not reproduce the measurement it came from**, and the gap is 3.97 s.
Build 2 is not a static plate: it has a group, and this port plays groups.
`press_start` has one element, `ptbtn00`, and its `fade_argb` reads
```
t=214 0x00ffffff pos (383, 560) invisible
t=236 0x00ffffff pos (383, 550) still invisible, having slid 10 px up
t=238 0xffffffff full alpha
t=244 0xffffffff holds
— 0x00ffffff the exit, untimed
```
At the measured 60 units/s that is **3.967 s** from the group's start to full
alpha. Compose the instruction with the group and the plate is first *visible* at
settle + 2.13 + 3.97 = **settle + 6.10 s**. What was measured — the glyph counter
leaving its no-plate value of 154 — is the plate becoming visible at **settle +
2.13 s**.
Neither obvious reconciliation works:
| reading | plate visible at | measured |
|---|---|---|
| both groups start together | 3.97 s (build 4 settles at **4.350 s**) — i.e. 0.38 s *before* settle | settle + 2.13 s |
| build 2's group starts at settle | settle + 3.97 s | settle + 2.13 s |
| build 2's group starts at settle + 2.13 s (the instruction) | settle + 6.10 s | settle + 2.13 s |
To land on the measurement, build 2's group has to start **2.51 s** after build
4's, which is not a landmark of anything.
**Verdict: the instruction is refuted as written; the measurement is untouched.**
The measurement is an observation of the running game and this port has no
standing to doubt it. What is refuted is the step that turns it into an
authoring rule, and that step is an interpretation.
**So the port ships the instruction, not its own arithmetic**, prints the
discrepancy on every boot, and files the row. This is the same call as the BGM
sub-waves and for the same reason: reconciling two of the RE agent's numbers is
a decoding question, and a port that quietly picks the one that looks right
destroys the evidence — a corrected boot looks exactly like a correct one.
The first thing to check is about the instrument rather than the game: is *"title
settled"*, the glyph counter first reading 154, the same instant as the port's
last-element settle (t=261, 4.350 s into the group)? If that landmark is earlier,
the gap closes with nothing else moving.
### Refuting the port's own claim: things in this export DO pulse
`BLOCKED.md` has carried this since P2, under the port's own raised question
about whether groups loop:
> no element's alpha reverses direction anywhere in this export, so nothing
> pulses, which removes the obvious reason to expect a loop without disproving
> one.
**`ptbtn00` reverses.** `0x00``0xff``0x00`, in the table above, in the
export, the whole time. The claim was never checked against `press_start`; it was
checked against the screens P2 happened to be animating. The RE agent has now
measured the running game pulsing this exact element at a mean 2.24 s.
So the reason to expect a loop is back — and the port still does not draw one,
because **no reading of this group produces 2.24 s**: the whole group is 268
units = 4.47 s, and from its first keyframe 54 units = 0.90 s. The plate is drawn
arriving and then holding at its settle (t=238, alpha `0xff`), which is what
every other screen does and what the static oracle capture
`live-title-press-a.png` shows. Which instant a repeat restarts from is filed,
not guessed.
### `--boot --capture=` — one frame instead of six hundred
The boot had no artifact of its own except `--film`, a PNG every 0.25 s for the
whole 156 s run, to answer one question: is the plate on top of the title at the
end. `--capture` was a `--screen`-only flag taken in `_ready`, which for a boot
run is 150 s too early. It is now deferred to the end of the sequence when
`--boot` is given.
### P3 gate — the boot ends on two builds
```
godot --path port -- --boot --capture=…/p3-plate.png
→ boot sequence complete after 155.86 s, holding on title
overlay press_start due at 157.99 s (+2.13 s after settle)
overlay press_start raised at 158.00 s, 1 element(s), settles at t=238
⚠ plate raised at settle+2.13 s but its own group reaches full alpha 3.97 s
later, so it is first VISIBLE at settle+6.10 s -- the measurement is
settle+2.13 s.
boot ends on title + press_start at 161.99 s
drew 16: ptbase2, ptloop01, …, ptcopyright
overlay press_start at t = 261.00 units, drew 1: ptbtn00
```
The PNG shows the title logo with **`PRESS Ⓐ BUTTON`** under it — build 4 and
build 2 in one frame, which this port had never drawn.
Two things the run made obvious and that are now fixed:
* **The capture reported only the base build's elements.** The first composited
capture printed `drew 16` and no mention of the plate, which reads as though
the overlay had not drawn at all. The overlay gets its own line; folding its
elements into the first list would have reported a screen that does not exist.
* **`--screen=<a> --overlay=<b>`** raises the same composite immediately, by the
same code path, with no delay. It exists because the only other way to see two
builds was a 156 s boot of which 137 s is the intro movie — and under Xvfb's
software Theora decode that is several minutes to answer "is the plate on top
of the title". It applies **no** delay: the delay is a measurement and lives in
`authored/flow.json`. The boot-mode narration is suppressed there, because a
log line that describes a sequence it is not running is worse than no log line.