port: their corrected calibration matches the file at all six points; guard the 60 against emulator drift

Counting indices/4 lands every transition where the export's declared alpha>0
count changes, within a half-open boundary. Their quad counts (1/2 publisher,
3/6 developer) also reproduce exactly when restricted to sprite-bearing
elements -- independently confirming the layerless backdrop is absent from the
batch they log.

Refutation: their drift explains the corpus 4.1% in SIGN but overshoots in
magnitude 2.4x (predicts a 1.369 ratio, corpus shows 1.278, declared 1.214).
The drift was measured in their container and the 4.1% belongs to a different
instrument -- the same transfer I just got wrong with build 4.

Guards keyframe_units_per_second at the constant itself: 60 is the game's
logical rate, not a frame rate, and the 33% drift is not evidence about it.

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 21:36:59 +00:00
parent be643ba58a
commit 011ba1065a
2 changed files with 84 additions and 1 deletions

View File

@@ -15,7 +15,20 @@
"exact rather than a repeating decimal a reader has to recognise.",
"",
"DELETE THIS FILE when a field on the disc is found that states the unit.",
"Nothing here is on the disc."
"Nothing here is on the disc.",
"",
"🔴 DO NOT 'CORRECT' THIS AGAINST AN EMULATOR FRAME RATE. A draw-stream",
"measurement on 2026-08-29 found the presented units-per-frame rising 33 % over",
"a single boot (1.765 early, 2.357 late) and three independent readings of one",
"container's rate disagreeing with each other. That is the EMULATOR's",
"presentation pacing drifting, and no single units-per-frame figure describes a",
"run there.",
"",
"60 is a different quantity: the GAME's logical unit rate, measured off the",
"running game as HANDOFF Q1 (a declared t=30 landing on the linear value at",
"every one of seven sampled frames). The port renders at its own frame rate and",
"converts through this constant, so guest pacing cannot reach it. The two",
"numbers are not comparable and one is not evidence about the other."
],
"kind": "measured",
"source": "/reborn docs/port/HANDOFF.md Q1, docs/re/ui-keyframe-time-unit.md",

View File

@@ -5242,3 +5242,73 @@ units later than the developer's and the two are not comparable quantities.
an unexplained 4.1 % error on the same screen are more likely one problem than
two. ⚠️ It also does **not** touch the corpus comparison, which is a separate
instrument (3 cold boots, not this draw log); their 4.1 % may still be real.
## Their corrected boundaries check out against the file — all six, exactly
The Decoder found the cause of the 7.9 % I reported, and it was worse than the
anchor mismatch I proposed: **the developer splash batches six quads into one
draw and their log dumps only the first two.** While the three glows are alive
they occupy that prefix, so the three wordmarks are invisible to the log until
the glows stop at t=45. *"Developer wordmarks first drawn at frame 140"* was the
logging prefix shifting, not the game. The anchor difference I found was a
symptom; the truncation was the cause. It is also what hid `palogo_anima`.
Their fix is to count `indices / 4`, which the 8-vertex dump cap cannot touch.
Every one of the six resulting calibration points matches this export:
| splash | their transition | their t | export |
|---|---|---|---|
| publisher | 1→2 quads | 15 | `palogo_sqex` joins at **t=16** |
| publisher | 2→1 | 45 | `palogo_sqex_eff` ends **t=44** |
| publisher | last drawn | 255 | group ends **t=255** ✅ |
| developer | 3→6 quads | 15 | three wordmarks join at **t=16** |
| developer | 6→3 | 45 | three glows end **t=44** |
| developer | last drawn | 210 | group ends **t=210** ✅ |
The two 15-vs-16 rows are a half-open boundary, not a disagreement: they name the
last frame at the old count, the export names the first instant at the new one.
✅ A second thing falls out that neither of us was looking for: their quad counts
are **1 and 2** on the publisher against **3 and 6** on the developer, and a
count restricted to *sprite-bearing* elements reproduces exactly that. So
`palogo_eff0` — the layerless forced backdrop — is **not in the batch they log**,
confirmed from the file. Their instrument and this export agree on which element
is the odd one out, having disagreed about it in every earlier iteration.
### Refutation attempt — does the drift actually explain the corpus's 4.1 %?
Their four segment rates recompute exactly (1.765 / 2.165 / 2.308 / 2.357; the
developer's two agreeing to 2.1 %, the run rising 33.5 %). The explanation is that
the publisher runs in the first seconds where the rate is furthest from its later
value. Testing what that predicts for the *corpus*:
| publisher ÷ developer | ratio |
|---|---|
| declared (255 ÷ 210) | 1.214 |
| **their drift predicts** | **1.369** |
| corpus, 3 cold boots | **1.278** |
**Sign confirmed, magnitude not.** The corpus ratio does sit above declared, which
is what the drift predicts and is real evidence. But their container's drift
would inflate it by 12.8 % where the corpus shows 5.3 % — roughly 2.4× too
strong. So drift of *some* size is doing the work; drift of *their* size is not.
⚠️ And the reason to be careful here is that the move is the one I just got wrong:
the 4.1 % is a property of the **corpus**, a different instrument (3 cold boots,
elsewhere), and the drift was measured in **their container**. Transferring it is
exactly what I did carrying build 4 onto the splashes. A general warm-up is
plausible for any emulator, so this is not baseless — but it is unconfirmed for
the corpus, and the magnitude gap is the evidence that the corpus's drift is not
theirs. It cannot be closed without the corpus's own frame log.
✅ Untouched by any of it: the declared **255** and **210**, and the port's
4.400 s / 3.650 s. Neither uses their draw log.
### The guard this puts on `keyframe_units_per_second`
⚠️ *"No single units-per-frame figure describes a run"* is a statement about
**emulator presentation pacing**, and a later reader could easily take it as
grounds to revisit the port's `60`. It is not. 60 is the **game's logical unit
rate** (HANDOFF Q1, measured), the port renders at its own frame rate and
converts through it, and guest pacing cannot reach it. `authored/timing.json` now
says so at the constant itself, where someone about to change it will read it.