Files
Sylpheed/docs/port/p7-gate.md
Sylpheed port agent ba3f490c67 port: P7's gate has an artifact, and the GPU kills my finding-4 candidate outright
Three things this iteration, and the middle one is the human's doing.

P7 -- GATE MET, with an artifact. The path had been wired for some time
(then_video S00A, skipped_chain, after_video -> title, and S00A.ogv in the
export) and NOBODY HAD RUN IT. A milestone is done when its artifact exists, not
when the wiring reads correctly.

Pre-registered: unskipped, S00A is 93.78 s of media, so it should end on its own
at ~94 s and hand off to title. Measured: video ended at 94.13 s -- +0.35 s,
0.4 % -- then -> title, plate raised, script complete at 96.83 s. Both
predictions held. docs/port/p7-gate.md.

And it genuinely decodes, checked because "ends at the right time" does not prove
it: 45 frames in a 2.03 s window, 244 in an 18.91 s one. Scales with the window,
sub-linearly, at the software fill ceiling -- those two runs predate the GPU. The
counts are upper bounds and the port says so itself.

Free corroboration of the fill-rate finding, from a direction it was not designed
for: the unskipped run reports main_menu at 60.3 fps for 94 s, because the screen
never changes during a movie. Same process, same container, same screen: 60.3 fps
with one full-screen video texture on top, 9.7 fps drawing the menu's five
additive full-screen quads.

 THE FINDING-4 FRAME-RATE CANDIDATE IS DEAD, tested rather than argued away.
The human activated a hardware GPU in both containers; Godot takes it with no
change on our side (NVIDIA GTX 1070 Ti, Vulkan 1.4.312, Forward+):

  publisher_logo   17.3-25.0 -> 69.4 fps
  developer_logos  16.7-22.8 -> 69.1
  title            12.7-17.2 -> 61.1
  main_menu              9.7 -> 59.6

Pre-registered that 5-7 full-screen textured quads at 720p is trivial for that
card and the fade would get its full 45 steps. At 69 fps the 45-unit build-in
gets 52 drawn steps and the companion glow's 15-unit rise gets 17 -- MORE frames
than declared units, so every declared alpha is drawn and the quantisation is
absent rather than reduced.

So every candidate for finding 4 is now dead: keyframes vindicated against the
vertex stream, companion quads drawn, blend space matching, settled pose at
0.01 %, no post-process pass, and the frame rate drawing every declared step. The
port has nothing left that is KNOWN to be wrong about the splashes -- which is a
statement about our knowledge, not about the port. The human saw something and
nothing we can measure reproduces it. The next play-test is now the
highest-value thing on this focus, and the rate line will say 60-something.

One figure did not improve: main_menu's worst gap is 117 ms on the GPU against
150 ms on llvmpipe, essentially unchanged while the mean improved 6x. A hitch
that survives a 6x fill speed-up is not fill. Likely first-frame cost, STATED AS
UNTESTED, recorded rather than chased.

check-all now asserts the display before any Godot step. Xvfb does not survive a
container restart and LEAVES ITS SOCKET BEHIND, so Godot reports "X11 Display is
not available", falls back to Wayland, fails that too, and exits non-zero -- and
every Godot-backed step would have gone red for that one reason. Cost me one run
before I noticed. Checked with xdpyinfo rather than by looking for the socket,
because the stale socket is what makes it confusing.

Also recorded from the P7 run, neither chased: Godot reports 4 leaked ObjectDB
instances at exit on that path, and the menu bed keeps playing under the movie
(already an open ask -- does the menu music duck?).

Not settled: the 117 ms menu hitch; H6's +0x04 exposure; H1 (with the Decoder);
the four red verify-screen rows; and what the human actually saw.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AHUQvXGyNcKonSEWsgWcX
2026-09-01 18:32:48 +00:00

4.2 KiB

P7 — the new-game intro plays and returns to a defined state

Status: gate met, with an artifact. Run 2026-09-01 by the Port at 4be90c2 + this commit; HANDOFF on this branch answers 9ca1eb5.

PORT-MISSION.md P7: "New-game intro video after NEW GAME | Plays, then returns to a defined state."

The path had been wired for some time — authored/flow.json gives ptbtn01 a then_video: "S00A", a skipped_chain, and after_video: {goto: "title"}, and S00A.ogv is in the export. Nobody had run it. A milestone is done when its artifact exists, not when the wiring reads correctly, and this file is the difference.

Pre-registered (R2)

--menu --script=accept with focus on NEW GAME announces the skipped DIFFICULTY, SELECT DATA chain, plays S00A, and returns to title. Unskipped, S00A is 93.78 s of media, so it should end on its own at ≈94 s and hand off.

What happened

  menu on main_menu, focus ptbtn01
script[1] accept at 1.00 s
  (NEW GAME) -> the real chain is DIFFICULTY -> SELECT DATA, then the movie.
               Neither screen is in this export.
  -> video S00A at 0.97 s (/work/export/video/S00A.ogv)
     + voice S00A
     video ended at 94.13 s
     -> title (authored: authored)
  (after the movie) -> title
  overlay press_start raised, settles at t=236
script complete after 96.83 s on title

94.13 s against 93.78 s of declared media — +0.35 s, 0.4 %. It ends on its own, at the right time, and hands off. Both predictions held.

Artifacts: s_00_start.png (main menu, NEW GAME focused) and s_01_accept.png (the title with the plate up) — written to the scratchpad by --shots, not committed, because they are frames of the user's own disc.

It genuinely decodes — checked, because "ends at the right time" does not prove it

A player that consumed 94 s of time while showing one frame would also "end at 94 s". So the frame counts, at two window lengths:

window frames shown of 2813
2.03 s 45 2 %
18.91 s 244 9 %

Frames scale with the window — it is decoding, not stalled. Sub-linearly though, 22.2 fps early against 12.9 fps over the longer window, and that is the same software fill ceiling documented in port-frame-rate.md; these two runs predate the GPU.

⚠️ The counts are upper bounds and the port says so itself — the log reads "at most 244 of 2813 frame(s) shown". It cannot see inside VideoStreamPlayer, so it reports what it can bound rather than a number it cannot support.

A free corroboration of the fill-rate finding

The unskipped run reports main_menu: 5677 frames in 94.13 s — **60.3 fps**. The screen never changes during a movie, so the rate line attributes the whole playback to it.

The same process, in the same container, on the same screen: 60.3 fps while a full-screen video texture is on top, and 9.7 fps while drawing the menu's five additive full-screen quads. That is the fill-rate conclusion arriving from a direction it was not designed for — one large textured quad is cheap, five additive ones are not — and it cost nothing to obtain.

Two things this run surfaced that are not P7

  • 🔴 4 ObjectDB instances were leaked at exit. Godot's own warning, on every run of this path. Small and at shutdown, so it costs a player nothing, but it is a real signal that something in the video/overlay teardown is not freed. Not chased, recorded.
  • 🟡 The menu bed keeps playing under the movie. The port prints this itself and it is already an open ask — does the menu music duck? — in BLOCKED.md. Left audible on purpose rather than guessed at.

What this does not claim

  • That the skipped chain is right. DIFFICULTY and SELECT DATA live in archives this milestone does not export; the port announces the skip rather than pretending the sequence is complete, which is the honest half of a gate it cannot fully reach.
  • That after_video: title is what the game does. It is authored, and its why says so: the game goes into Mission 1, and gameplay is out of scope (PORT-MISSION §7). "Returns to a defined state" is the gate; title is the state we defined.