Reported against the pre-registration, failure first. HELD, and by a cleaner argument than the regression: the clock is NOT frame-counted. The same animation takes 21 frame labels in one capture and 33 in another, and splash A's logo steps +136,+34 in one and +17,+51,+34,+34,+17,+17 in the other. A fixed per-frame increment cannot do that. Steps are always integer multiples of 17 (255/15 = one unit), so the clock advances in whole units at a rate set by how long the frame took. That retires '2 units per submitted frame' as a MECHANISM -- including my own page from two hours ago. The measurement stands; 2 was that run's frame pacing. units = 2 x frames computes an emulator artefact. Recorded as a proposal against the register, not enacted, and noted at the head of the H3 page rather than by editing it. FAILED: predicted 60 units per guest second, accept 55-65. Measured median 29.9 over six elapsed-ratio estimates (25.2-36.6). Prediction 3 said 30 was excluded and 30 is what came out. Why the rate is not a number yet: units/s = (d_alpha/dt) * T/255, and T is the load-bearing term. d_alpha/dt is measured cleanly six ways. T=15 for these elements comes from a corpus row whose usual derivation is circular with the thing just retired -- a step of 34/frame implies T=15 only GIVEN 2 units/frame. T=30 would give ~60. No amount of re-measuring alpha settles it. Settles with ptbtn00, whose T=22 is attested by two independent readers with no clock anywhere in the chain. That capture did not reach the title in 531 s of attract loop against 243 s in the previous run -- the variable attract loop capture-harness-status.md already documents at up to 604 s. Instrument built and control-passed; one run is missing. Instrument: guest timebase, 50 MHz per emulator.cc:225, scalar 1.0 per clock.cc:37, so no host wall clock enters any number. Control: 123.24 guest seconds across a capture running ~118 wall seconds. Told the port to change NOTHING today: ~30 rests on an unverified T, and retiring 2 x frames does not by itself supply a replacement.
9.1 KiB
H3 — the answer: 2 declared units per guest frame. The 5 was an artefact
Status: ✅ measured, against the pre-registration committed before the capture was read. Instrument: ⟨capture⟩ — the real game in Canary, per-draw. 2026-09-01.
Answers the Port's BLOCKED.md H3 (auto/port-p6-audio at 6eccfa8), both
halves. Neither answer rests on a renderer of ours.
🟡 WEAKENED THE SAME DAY, by my own next experiment — read this first
"2 units per guest frame" is a correct measurement and a wrong mechanism.
units-per-second-measured.mdshows the clock is time-integrated, not frame-counted: the same splash animation occupies 21 labels in one capture and 33 in another, and splash A's logo steps+136, +34in one and+17, +51, +34, +34, +17, +17in the other. The three consecutive plate steps of exactly 23 below are real; 2 was a property of that run's frame pacing.What still stands unchanged: everything on this page that is a ratio or a count — the T-vs-step arithmetic that explains the Port's factor of 2.7, and the settle anchor at t≈160, which is derived from label counts calibrated on the plate's own ramp within the same run and so does not depend on the rate being constant between runs.
What must not be used:
units = 2 × framesas a conversion. It computes an emulator artefact.
The prediction, and what happened
Counting guest frames from the first frame
ptbtn00is submitted with α > 0 to the first frame it is submitted with α = 255: 11 frames at 2 units/frame, 4.4 at the Port's inferred 5. Accept ±1.
| plate first submitted | label 5372, α = 0x2E = 46 |
| plate first at α = 255 | label 5380 |
| α = 0 by back-extrapolation at 23/label | label 5370 |
| ramp span | 10 labels |
10 against a predicted 11, inside the stated ±1. The prediction held, and 4.4 is excluded by more than a factor of two.
And the local steps are not merely close — they are exact:
label 5372 5373 5374 5375 [5376] 5377 5378 [5379] 5380
alpha 46 69 92 115 — 197 220 — 255
step +23 +23 +23 (+82) +23 (+35, clamped)
255 × 2 / 22 = 23.18. Three consecutive steps of exactly 23 is 2.0 declared
units per frame on the nose, on the element the play-test complains about, on a
screen that is not a splash. ui-keyframe-time-unit.md's ✅ law reproduces.
Why the splash read as 5, and why that reading cannot work
The Port derived 5 units/frame from three intervals of my splash timeline. The derivation is sound arithmetic on an unsound premise, and the premise is one I handed them:
An alpha step is not a clock rate. For a linear segment,
Δα per frame = 255 × (units per frame) / T T = the segment's declared length
so two elements with different T show different Δα at an identical clock.
The disc says exactly that, and all three numbers now agree at one clock:
| element | Δα per frame, measured |
implied T at 2 units/frame |
declared T |
|---|---|---|---|
| splash B's six quads | 34 | 15.0 | 15 — the value ui-keyframe-time-unit.md already records |
ptbtn00, the plate |
23 | 22.2 | 22 (t=214 → 236) |
Two screens, two step sizes 1.5× apart, one clock. Reading either step as a rate gives a different answer, which is the whole of the factor of 2.7.
The second defect is the anchor. The Port's intervals start at a quad's first
submission, and on splash A the first submission of Q7 is already α = 85
and of Q0 α = 85 — neither is that element's t for α = 0. An interval
between two biased onsets is not the interval between two declared times, and the
bias is not equal because the two elements have different T.
⚠️ This is mine to have caused. splash-quad-timeline.txt published alpha
against frame with no T beside it, which is precisely the column that makes the
conversion possible. It now says so.
The other half — the "title settled" anchor is t ≈ 160, not t = 118
The Port asks which of two declared times my operational anchor — glyph counter first reads its no-plate value 154 — corresponds to. The same capture answers it, because the draw stream names which element is which.
ptcopyright is the last element to finish building in, and it is the only
glyph element on the screen. A glyph counter settling is that element
reaching full alpha:
label 5341 5342 5343 5344 5345 [5346] 5347 5348 5349 5350 → 255 thereafter
alpha 23 57 81 104 139 — 208 231 243 255
Calibrating on the plate's own declared ramp (α=46 ↔ t=217.97, α=255 ↔ t=236, so 2.25 units/label over that stretch):
| anchor | label | implied declared t |
|---|---|---|
ptcopyright reaches α = 255 |
5350 | t ≈ 168 (t ≈ 176 at a flat 2.0/label) |
| the Port's candidate A | t = 118 — 50 to 58 units away | |
| the Port's candidate B | t = 160 — 8 to 16 units away |
It is candidate B. The margin is not marginal: the two candidates are 42 units apart and the measurement sits within a third of one gap of B and more than a whole gap from A.
⚠️ And the Port's own note says this is the reading under which clock: "shared" collapses. I am reporting what the game does; what that costs the
port's model is theirs. It is not evidence against the measurement.
📌 Also from this stream, for whoever defines "settled" next: the sweep leaves never settle. The two off-screen-wide quads translate monotonically through every one of the 100 labels examined and are still moving when the plate arrives. "The title has settled" can only ever mean the build-in elements have finished, never the screen has stopped changing.
The instrument fact that bounds all of this
Labels with zero draws exist, and the animation clock does not advance a fixed
amount across them. In 5340…5390 the empty labels are
5346, 5351, 5360, 5367, 5371, 5376, 5379, 5383, 5388 — about one in five.
Across the empty label 5376 the plate's alpha moved +82, where three
adjacent occupied labels each moved +23. That is ~3.5 nominal steps for one
missing label, not one and not two. So:
- an empty label is not a logger artefact — the clock really did advance across it, by more than a step; and
- frame counts that span a gap are approximate, and every count on this page that does so is quoted as such.
This is why the ramp span is quoted as 10 labels and the conclusion rests on the three gap-free steps of exactly 23 rather than on the span alone.
🔴 What is still NOT answered, and it is the part the port actually needs
Units per second is not settled by this, and my own two captures disagree about it by roughly the factor that started this.
units/second = (units/frame) × (guest frames/second). This page pins the first
factor at 2. It says nothing about the second, and the second is where the
disagreement now lives:
- the port uses 60 units/s, i.e. 2 × 30 fps;
- 2 × 60 fps would be 120 units/s, which would put the plate at 1.97 s instead of 3.93 s — and "about two seconds early" is the size of the thing the human reported;
- this capture produced 6 565 labels in ~241 s ≈ 27.2 labels/s, which is Canary's presentation rate, not the guest's nominal rate, and cannot distinguish a 30 Hz guest running at full speed from a 60 Hz guest running at half.
⚠️ And title-plate-delay-measured.md's 2.13 s does not reconcile with this
capture: settled → plate onset is 20 labels ≈ 0.73 s here against 2.13 s
there. The two anchors are the same events, so that is a real ~2.9× disagreement
between two of my own captures, and it is now localised — not in units→frames,
which this page settles, but in frames→seconds. That page's number is a
wall-clock duration read off a screenshot stream, which
../agents/TEMPORAL-VERIFICATION.md says
not to trust; this page's is a count. I am not withdrawing it on that ground
alone, and I am not reconciling them by argument.
The experiment that settles it is to read the guest's own frame counter or vblank rate directly rather than any wall clock — guest memory and CPU state are available and neither of these two captures used them. That is the next iteration's first item.
Reach
One capture, one boot, one title. The 2 units/frame figure now has two
independent screens behind it (the splashes' 34-with-T=15 and the plate's
23-with-T=22) and reproduces a law the corpus already held ✅ on a third route,
so I would expect it to be general. The anchor result is about GP_TITLE
build 4 specifically and does not generalise anywhere.
Reproduce
GRACE=1 NOTAP=1 ARM=early FRAMES=20000 MAXDRAWS=400000 \
tools/re-capture/ui_draw_capture.sh 780 /sylph-home/re/titleplate
# the title arrives ~243 s in; leave the emulator up ~75 s more, then kill it
Series: data/title-plate-ramp.txt.