Commit Graph

4 Commits

Author SHA1 Message Date
Sylpheed port agent
15702d0d05 port: the game's clock is frame-based, ours is time-based, and 60 is finally supported
The --framerate_limit=30 run refuted the time-based reading on every
discriminating row, against its author's own expectation: modal alpha step stayed
17 where time-based predicts 34, units/second halved to 30.2, the publisher dwell
doubled to 8.450 s. Both controls passed FIRST -- the limiter demonstrably took
effect, and all 8 splash quad rects were identical, so nothing but the frame rate
differed. 255 x 1 / 15 = 17 at 28.4, 51.4 and 54.8 presents/s alike.

THE GAME ADVANCES 1 UNIT PER PRESENTED FRAME. This port advances
`time_units += delta * units_per_second`. Two different mechanisms that agree at
exactly one frame rate -- 60 Hz, the only rate the console ever asked the game to
be right at.

🔴 DO NOT MAKE THE PORT FRAME-BASED TO MATCH THE GAME, and the reason is now in
authored/timing.json so nobody "fixes" it. A time-based port reproduces a 60 Hz
console on hardware that is not 60 Hz; a frame-based one drifts on every machine
that is not -- and this port has measured ITSELF between 9.7 and 69.4 fps
depending on the renderer. Matching the game's mechanism would import a fragility
the game never had to survive, because the game only ever ran on one box.

⚠️ BUT IT SHARPENS WHAT 60 CLAIMS. If units/second IS the present rate, then
`keyframe_units_per_second = 60` is no longer "the unit is 1/60 s". It is "the
game presented these screens at 60 Hz on the console" -- a harder statement, and
checkable.

✅ And supported for the first time. Canary unlimited presents at 51-55 Hz with a
splash dwell of 4.30/4.60/4.37 s. A natively 30 Hz game would present at ~30 in
Canary too -- the framerate_limit run proves it, since forcing 30 made that same
splash take 8.45 s. It does not take 8.45 s unforced. So the game asks for ~60.

Kept as `authored`, not promoted: this is inference over three measurements
rather than a measurement of units per second. It becomes `measured` when someone
reads the console's present rate for these screens directly.

🔴 AND IT CLOSES THE CONSTANT AS A CAUSE OF FINDING 3, in the direction that
matters. Under the frame-based model the only alternative is a 30 Hz console,
which puts the plate at 236/30 = 7.87 s -- LATER than the 3.93 s shipping, not
earlier. There is NO console present rate that makes the plate arrive sooner than
this port already shows it. The human reported it late; no value of this constant
can produce that.

The method note is theirs and it is the durable part: four positions on this
number were inference over a measured quantity; this one changed an input and
watched what moved. The opportunistic comparison -- two captures that happened to
differ -- pointed exactly the wrong way, because nothing controlled what else
differed between them. One designed capture settled it against its author's
expectation.

Not settled: finding 3, still with no surviving cause; the clock origin, which
they are taking next and which every ratio and count in this account survives;
the ~1.0-1.2 menu residual; the allowance's grep trigger.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AHUQvXGyNcKonSEWsgWcX
2026-09-01 19:42:28 +00:00
Sylpheed port agent
c6b3256574 port: withdraw my "no hold" finding -- the port holds, and 60 is now positively supported
The Decoder withdrew 120 and returned to 60, which the port never left. Nothing
has to be undone. But their correction also kills last iteration's headline
finding of mine, and that matters more than the number.

🔴 WITHDRAWN: "the port has no hold" and "two errors that cancel".

I read their split -- "219 presents on screen, ~128 animating" -- as a hold
OUTSIDE the declared timeline that the port was missing. It is a split WITHIN it.
The publisher ramps 0-30, HOLDS 30-235 (205 units, 80.4 % of the screen) and
fades 235-255, and this port plays all three.

Measured rather than read. Frozen samples of the logo region:

  t=0.25 s (15 u)  0.390957   mid-ramp
  t=1.00 s (60 u)  0.405488
  t=2.00 s (120 u) 0.405488
  t=3.00 s (180 u) 0.405488
  t=3.80 s (228 u) 0.405488   identical to six decimals across 168 units
  t=4.20 s (252 u) 0.038142   in the exit fade

So there was never a missing hold and therefore never a pair of cancelling
errors. authored/timing.json's "the pacing was right all along" WAS right all
along, and my paragraph casting it as a possible coincidence is withdrawn there.

⚠️ The failure was not a mis-measurement. I took a two-part split from someone
else's instrument and assumed its boundary sat where my own model put it.
Presents are not units, and "animating vs holding" in presents does not decompose
the same way as "ramp vs hold" in declared units. That is a new failure shape for
this corpus and it is worth the name.

✅ AND THE DWELL FIGURES ARE NOW POSITIVE EVIDENCE, not survivors. A time-based
clock is immune to dropped frames, so a dwell in seconds is stable across runs at
different frame rates. The port's own splash dwell across a 4.0x change in its
rendering rate -- work done two iterations ago for an unrelated reason:

  17.3 fps -> 4.28 s     19.6 -> 4.26     25.0 -> 4.27     69.4 -> 4.26

a 0.5 % spread, putting 255 units at 59.6-59.9 units/s every time.

🔴 Labelled rather than counted: that shows the PORT's clock is time-based, which
it is by construction, so it is not evidence about the game's. What it does
establish is that the dwell figures I supplied are frame-rate-INDEPENDENT
measurements rather than artefacts of whatever rate a run hit -- which is the
property their argument needs of them, and it was assumed until now.

The mechanism, theirs, worth more than the number: units per PRESENT halved when
the present rate doubled (+34 at 27.2 presents/s, +17 at 51.4) while units per
SECOND did not move (54.4 vs 51.4). "2 units per frame" was never a property of
the game, only of a capture that ran at 27 fps.

🔴 And check-citations caught me again, in the entry where I was recording the
lesson about citations: I wrote their document as a `docs/re/...md` path that does
not resolve here. The check does not care about the disclaimer next to it, which
is correct. Named without a path now.

Finding 3 is OPEN AGAIN with no surviving named cause. Units-per-second is
eliminated in favour of the value already shipping; everything else died earlier.
The clock origin is untouched and every quantity in the resolved account is a
ratio or a count, so a common offset survives all of it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AHUQvXGyNcKonSEWsgWcX
2026-09-01 19:38:19 +00:00
Sylpheed port agent
c24ea3ba0e port: my falsifier was malformed, and following it through found two errors that cancel
CONCEDED. I set the falsifier as "at 120 the publisher splash runs 2.125 s against
cold boots measuring 4.30/4.60/4.37". 2.125 s is the declared ANIMATION length;
4.3 s is how long the SCREEN is up. The screen holds after the timeline ends, so
those are different quantities and the comparison would have found a contradiction
at ANY units-per-second.

The Decoder also checked the defence I handed them -- that the dwell corpus might
be emulator-contaminated -- and declined it. Their capture reproduces those boots
(publisher 4.263 s, developer 3.457 s, four runs agreeing). They could have waved
my numbers away and did not.

🔴 BUT FOLLOWING IT THROUGH FOUND SOMETHING NOBODY HAD SAID: THE PORT HAS NO HOLD.

  publisher   declared 255 units  measured 4.270 s  animation at 60 = 4.250 s
  developer   declared 210 units  measured 3.527 s  animation at 60 = 3.500 s

The port's screen time IS its animation time; the residual is +0.02 s, i.e. none.
The game, by the Decoder's counts, is on screen 219 presents and animates ~128 of
them -- about 42 % hold.

So if 120 is right, this port makes TWO ERRORS THAT CANCEL: it animates every
splash 2x too slow, and it omits the hold entirely, and the two sum to almost
exactly the right total screen time.

That is why the dwell check passes, and authored/timing.json cited that agreement
as proof -- "So the pacing was right all along and nothing changes in the code."
Conditional on 120, that sentence is a coincidence. Corrected in place.

⚠️ A passing check on a SUM cannot see two errors of opposite sign inside it.
Fourth member of today's family, after the non-inverting latch check, the
unguarded buffer assumption, and the segmentation that nearly produced a
convenient answer.

🔴 AND 120 EXPLAINS BOTH OPEN PLAY-TEST FINDINGS. 60 EXPLAINS NEITHER.

  finding 3, "the plate arrives late":
      at  60  full at 3.933 s        at 120  1.967 s
  finding 4, "the game's fade is MORE PRONOUNCED":
      at  60  build-in 0.750 s, then the screen leaves at once
      at 120  build-in 0.375 s, then the screen HOLDS ~1.7 s

At 60 the logo drifts in slowly and leaves; at 120 it snaps in and sits, which is
what "more pronounced" describes. Finding 4 is explained twice over by one
constant -- the fade is 2x slow AND the hold is missing. Every named cause for
both findings has died over the past several iterations; 120 is the first
hypothesis that accounts for either, and it accounts for both.

This is not a measurement and I am not calling it decisive. It is the one thing
the port can contribute that no capture can: what a human watching both reported.

STILL HOLDING AT 60. Reach is one boot and they are not asking me to lift it.

⚠️ The hold and the constant are COUPLED. At 60 the port must NOT gain a hold --
the animation already fills the screen time and a hold would overshoot by ~40 %.
The missing hold is a defect only if 120 is right. When it moves it is TWO
changes: the constant, and a hold measured as (screen presents - animation
presents), which must NOT be inferred from the total -- the total is exactly the
quantity that cannot distinguish the two errors.

Not settled: the constant; the clock origin; the ~1.0-1.2 menu residual.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AHUQvXGyNcKonSEWsgWcX
2026-09-01 19:32:22 +00:00
Sylpheed port agent
07da4f167f port: hold at 60 against a better 120, audit the switch, and name its falsifier first
The Decoder measures 120 units/s with a content-hash experiment carrying the
controls the withdrawn version lacked -- a static texture hashing constant (1
change in 403 samples) and movie luma not constant (102 distinct) -- against
pre-registered bands the observed 0.5739 falls inside. It is a better experiment
than either it replaces.

THE PORT HAS NOT MOVED. It is their third position on this number in one day,
reach is one boot, and they said themselves that a second independent boot before
a timeline is rewritten is the defensible call. Agreed.

⚠️ And 60 is not defended either -- its bracket was withdrawn this morning. Both
numbers are undefended. The port keeps the one it ships because switching on a
single capture is a worse failure than holding on none. That is the whole
reasoning and it is not evidence about the game.

✅ THE AUDIT THEY ASKED FOR COMES OUT CLEAN. "If seconds are baked in anywhere,
they all move." No seconds are baked into the timeline: every second this port
prints or acts on is computed as units / keyframe_units_per_second at the point of
use -- settle_time, exit_time, _overlay_quit_at, the boot log. audio.json's
loop_start_s / loop_end_s ARE seconds and correctly do NOT follow the constant;
they are positions in an audio file with no keyframe unit in them. So the switch
is one number in one file.

🔴 ONE EXCEPTION, AND IT WAS HIDING BEHIND A COMMENT ABOUT NOT DRIFTING.
tools/port/verify-dwell read black_hold_units from the authored file "so it cannot
drift again" -- and then divided by a literal 60.0. The value could not drift; the
conversion could, and would have gone silently wrong the moment the constant moved,
which is under active dispute right now. Harmless only because the hold is 0.
Fixed to read the rate from the same file it already opens.

That is the third time in this corpus a `why` has described a property the code
did not have, and the first where the comment and the defect were one line apart.

📌 AND THE FALSIFIER IS PRE-REGISTERED, BEFORE ANY SECOND BOOT, in
docs/port/units-per-second-switch-readiness.md. At 120 every declared interval
halves: the plate lands at 1.967 s, the publisher splash runs 2.125 s and the
developer 1.750 s. Three cold boots measured those splashes at 4.30/4.60/4.37 and
3.51/3.50/3.37.

So 120 and the dwell corpus cannot both be right in wall-clock seconds -- the same
collision that killed the 35 units/s proposal from the other direction, arriving
from the opposite side. Either those dwells carry the emulator's speed factor,
which would make them worth exactly as little as the 2.13 s route the Decoder has
already declined to lean on, or 120 is wrong. Naming that now is the point of
writing it before the boot rather than after.

What would move this port: a second independent boot agreeing, AND a statement on
whether the cold-boot dwell corpus survives the same speed-factor objection that
the 2.13 s route does not. The first without the second leaves a 2x contradiction
standing between two numbers the port would then hold at once.

Not settled: the constant; the clock origin, which every ratio and count above
survives untouched; the ~1.0-1.2 menu residual; the allowance's grep trigger.

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