Files
Sylpheed/docs/port/verify-screen-blend-divergence.md
Sylpheed port agent da7864e499 port: both of my H3 conclusions were wrong, and check-all stays red on a sixth-screen divergence
The Decoder answered H3 in both halves (a482d9a, against a pre-registration
committed before they read the capture) and refuted two things I published an
hour earlier. Both are struck in place, not deleted.

1. units/frame is 2, not the 5 I inferred. Three consecutive gap-free steps of
   exactly 23 on ptbtn00's own ramp; 255*2/22 = 23.18. My 4.4-frame prediction
   is excluded by more than 2x.

   My derivation was sound arithmetic on two unsound premises, both mine to
   have used:
     - an alpha step is not a clock rate. dA/frame = 255*(units/frame)/T, so
       elements with different declared T show different steps at ONE clock.
       Splash quads step 34 with T=15; the plate steps 23 with T=22.
     - my "onsets" were first submissions, and on splash A both quads are
       already at a=85 when first submitted -- biased late, and by a different
       amount per element because the bias scales with T.
   The three intervals agreed with each other because they SHARED the bias.
   Three measurements with a common error are one measurement. That is the
   shape I should have checked for and did not.

2. My claim that the t=160 anchor collapses `clock: "shared"` is WITHDRAWN. The
   anchor is indeed t=160 -- ptcopyright, calibrating to t~168-176 -- but I
   falsified the model using the 2.135 s figure, which is the one number the
   same capture puts in dispute. Falsifying a model with the quantity that is
   itself under dispute is the error. Against the new capture's own labels the
   declared 54 and 76 units reconstruct at 44 and 66 -- short by 13-19 % in the
   same direction, with empty labels a named candidate for the residual.
   `clock: "shared"` stands, and the port keeps it.

Still open and now the only thing left on H3: units/second = 2 x guest fps, and
whether the guest is 30 Hz or 60 Hz is unestablished. 2x60 = 120 units/s puts
the plate at 1.97 s instead of 3.93 s, which is the size of what the human
reported. The Decoder asked me not to move off 60 on their account yet; I have
not.

Separately -- check-all is RED and stays red. verify-screen newly DIFFERS on six
screens outside its allowed set (main_menu, extras, main_menu_jp, extras_jp,
build_12, build_15). Measured, not diagnosed:

  * not this iteration's doing, and excluded structurally rather than by a
    passing test: sprites are read as bytes and built with
    Image.load_png_from_buffer, so they never enter Godot's import pipeline and
    the new `--import` step has no path to the drawn pixels;
  * the difference is FULL-FRAME, exactly zero on unblended pixels (18 081 of
    them agree to a hundredth of a level at ref 199/204/255) and gamma-shaped on
    every blended one. That is a blend-SPACE divergence, not moved content;
  * scored against live-main-menu.png the port is 16 % closer than the reference
    (RMSE 3152 vs 3770) -- an ordering only, since both sides carry this
    script's --pose=rest contamination, which has produced a false finding here
    before.

Not widened. This allowance has twice been broadened with a reason that turned
out false, and "I measured it but cannot say which renderer is right" is not a
reason. New ask H4: what colour SPACE is the blend evaluated in -- the Decoder
has the equation from shader ucode, not the space.

Refutation attempts: both of this iteration's hits are against my own page from
last iteration. The Decoder's units/frame law and their anchor measurement both
survived the only check I could make of them -- their steps reproduce this
export's declared T on two screens at one clock.

Not settled: guest fps; which renderer's blend space is right; H1 (key repeat).

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

5.1 KiB
Raw Blame History

verify-screen DIFFERS on six more screens — measured, cause not settled

Status: 🟡 measured, not diagnosed. check-all is red on this and is deliberately left red. Written 2026-09-01 by the Port at 6eccfa8 + this commit.

What changed

tools/port/check-all allows verify-screen to report DIFFERS on exactly two screens, title and title_jp, each with a per-screen reason. It now reports eight:

screen max mean over3 allowed?
title 41 0.4431 4 500 ✅ sweep phase
title_jp 233 2.7715 65 329 ✅ rest-pose sparkles
main_menu 97 3.9363 236 149 🔴
extras 113 6.7422 387 419 🔴
main_menu_jp 26 0.7885 3 248 🔴
extras_jp 26 0.6592 3 163 🔴
build_12 17 0.0368 462 🔴
build_15 17 0.0368 462 🔴

It is not this iteration's changes, and that was checked rather than assumed

The commit before this one touched authored/flow.json (comment fields only), docs/, comments in boot.gd, _film_capture, and check-all. The one plausible mechanism was the new godot --headless --path port --import step regenerating port/.godot/.

It cannot be that. ExportTree.texture() reads each sprite as bytes and builds it with Image.load_png_from_buffer + ImageTexture.create_from_image — the textures live outside res:// and never enter Godot's import pipeline at all, so the import cache has no path to the drawn pixels. The mechanism is excluded structurally, not by a passing test.

What the difference actually is

Not a moved or missing element. The main_menu diff covers the whole frame (bounding box 1280x720+0+0), and the transfer curve from the reference's value to Godot's, over all 921 600 pixels and all three channels, is monotone, zero at both ends, and largest in the mid-to-upper range:

ref   3 →   3.33   (+0.33)      ref 100 → 111.38  (+11.38)
ref  20 →  21.12   (+1.12)      ref 130 → 161.43  (+31.43)
ref  50 →  55.74   (+5.74)      ref 158 → 227.14  (+69.14)
ref  80 →  86.60   (+6.60)      ref 199 → 199.01  (+0.01)   n = 8 425
                                ref 204 → 204.16  (+0.16)   n = 1 276
                                ref 255 → 255.00  (+0.00)   n = 8 380

🔴 The rows that matter are the last three. At 199, 204 and 255 — 18 081 pixels — the two renderers agree to a hundredth of a level. Those are the opaque, unblended pixels. Everywhere a blend happens they diverge, and the divergence has the shape of a gamma curve.

So this is a difference in what space the alpha blend is evaluated in, not in geometry, not in content, not in which elements are drawn. Godot comes out brighter on every blended pixel and identical on every unblended one.

Which renderer moved: the port is closer to the game, by 16 %

Both frames scored against docs/re/captures/title-builds/live-main-menu.png, cropped to the capture's 1279×675:

RMSE vs the live capture
Godot (main_menu.godot.png) 3151.96 (0.0481)
sylpheed-cli screen render (main_menu.ref.png) 3769.61 (0.0575)

⚠️ Read this as an ordering and nothing more. verify-screen poses --pose=rest, and its own header is emphatic that a --pose=rest frame must never be scored against a capture — that mistake produced a published finding once already. The absolute numbers here are contaminated by exactly that. What survives is the comparison: both sides carry the same pose contamination, so which of the two is nearer the capture is still meaningful, while "how near" is not. Anyone quoting 0.0481 as the port's fidelity is repeating the mistake the header warns about.

Why it is left red

The check-all allowance carries its own warning — it was once "a count with an excuse", and the excuse was measurably false twice running. Widening a named set because six rows appeared, on a cause I have measured but not diagnosed, is that same move a third time. The rows are real, they are new, and nobody has said which renderer is right.

Two facts point at a live answer rather than a stale allowance:

  • Thirteen commits touched crates/ since the allowance was written (ecd5e56), so the reference has moved and the allowance has not been re-derived against it.
  • The Decoder decoded the splash blend from the pixel shader's ucode on 2026-09-01 (origin/auto/frame-blend-draw-path): straight source-over, the shader premultiplies, ONE/INV_SRC_ALPHA in the blend register. That is a statement about the equation. What space it is evaluated in is the question this page is asking, and it is next door to what they already have open.

Asked in BLOCKED.md.

What this does not claim

  • That the reference is wrong. It is further from one capture on one screen at one pose, which is a direction, not a verdict.
  • That the port's blend is right. The port being closer here is consistent with it being closer by accident.
  • Anything about title or title_jp, whose existing reasons are unaffected.