port: add wait:<seconds>, observe the bed's loop, and measure the seam at 3.4 s of silence

The port could not be asked to run for a stated duration -- a bare  step
is a no-op that returns at settle -- so nothing after the settle point was
observable. An 87.7 s bed on a harness whose longest menu run was 7 s.

The bed loops at 87.8 s against the track's 87.7 (r=0.947 and 0.885 on a clean
bed-only recording): loop: restart behaves exactly as authored. First
end-to-end observation of P6 looping.

The authored 'audibly wrong at the seam' is confirmed and quantified: 36
consecutive near-silent 50 ms windows, 84.40-87.80 s, about 3.4 s of silence
after a fade from RMS 2057 to 431. Recorded in authored/audio.json. It does NOT
license trimming, which would still invent a loop point.

My first wait: used create_timer and ran 39% long (30 s requested, 41.7 s wall)
because an idle scene throttles the delta it counts down on. Now polls
Time.get_ticks_msec: +4.6%. Checked before generalising: over a boot the port's
clock tracks wall clock within 4%, so animation timing is sound and the earlier
splash-dwell agreement stands.

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 23:23:35 +00:00
parent b71c35acf4
commit e5398be93b
3 changed files with 120 additions and 3 deletions

View File

@@ -5681,3 +5681,76 @@ first where I would have invented an *anomaly* rather than a defect.
Nothing in this section rests on that correlator. The finding is `stop_bed` having
no caller, which is a fact about the source.
## `wait:<seconds>`, and the bed's loop seam is 3.4 seconds of silence
The port could not be asked to **run for a stated duration**. A bare `wait`
script step is `pass` — it returns as soon as the screen settles — so nothing
happening after the settle point was observable from a harness at all. The music
bed made that concrete: an 87.7 s track whose restart nobody had watched, on a
harness whose longest menu run was under seven seconds.
`--script=wait:105` fixes that, and the first thing it found was the answer.
### The bed loops, exactly where it should
Recording the Master bus over 132 s with nothing but the menu playing — no movie,
no voice, a clean signal — the bed's `t=2…17 s` template matches twice:
| | r | pass begins |
|---|---|---|
| first pass | **0.947** | 0.0 s |
| second pass | **0.885** | **87.8 s** |
The track is **87.7 s**. So `loop: "restart"` does what `authored/audio.json`
says: replays from sample 0 at the track's end, no trimming, no loop point.
✅ First end-to-end observation of P6's looping behaviour.
### And the seam is measurably as bad as it was authored to be
`loop_why` predicted *"the listener hears the track's own fade-out and the silence
after it before the music comes back"*. Measured off the bus:
| window around the seam | RMS |
|---|---|
| −8 … −4 s | 2057 |
| −4 … −2 s | 714 |
| −2 … −0.3 s | 431 |
| +0.3 … +2 s | 2164 |
and **36 consecutive 50 ms windows below peak 300, from 84.40 s to 87.80 s** —
about **3.4 seconds of near-silence** before the music returns. That is long
enough to read as *the music stopped*, not as a loop.
The claim was right and is now a number. ⚠️ It does **not** license trimming to
the fade: that would still invent a loop point, and an invented one is
indistinguishable from a decoded one a month later. The measurement is recorded
to make the cost of the missing loop point concrete, in `authored/audio.json`.
### 🔴 My first `wait:` was wrong by 39 %, and the way it was wrong matters
It used `create_timer`, which counts down on the frame delta. In an **idle**
scene this container throttles and the delta it reports is not the time that
passed: a requested 30 s took **41.7 s** of wall clock while the port reported
30. Measured against `date` either side of the process, with a no-wait control
to subtract 1.21 s of startup.
Now polled on `Time.get_ticks_msec()`: 30 s requested, **31.38 s** wall, +4.6 %.
⚠️ **This is idle-specific and is not a general clock fault**, which I checked
before writing any of it down. Over a whole boot, where things are animating, the
port's clock tracks wall clock to **within 4 %** — 10.43 s wall against 10.82 s
reported. So the port's *animation* timing is sound and the earlier splash-dwell
agreement (4.400 s and 3.650 s against declared 255 and 210 units) **stands**; I
had briefly believed it did not.
What is genuinely unsound is `_elapsed` **while idle**: it reported 23.21 s across
30 real seconds of waiting. Every timing the port prints during animation is
fine; a timing that spans a wait is not.
📌 The reason to care: the only reason to hold a screen is to observe something on
a **real** clock — an audio loop, a timeout, an idle return. A timer that
silently ran 39 % long would have put every such observation at the wrong instant,
and the bed-loop result above would have been the first casualty. It survived only
because the seam was read off the **recording's** clock, which the bed's own known
length calibrates.