port: the loop window is measured -- ss 9.44 t 61.87 -- and near-silence tracked the error

Region [9.44, 71.31] of an 87.744 s wave: first 9.44 s an intro played once, last
16.4 s a fade never played. 61.87 replaces 61.93, 0.1 percent apart; the measured
value has the loop's own endpoints under it.

The port's near-silence count tracked the window's correctness without being
designed to: 36 frames spanning 3.4 s untrimmed, 5 with the right length over the
wrong window, 0 with the measured window. The old window kept part of the quiet
intro; the measured one excludes intro and fade both. Wrap continuity is
unchanged and still not evidence -- the silence count discriminated where the
step count could not.

Also fixes a stale why that reached the manifest for two days: corrections went
into loop_end_why and loop_start_why while loop_why, the field the exporter
concatenates, still said the loop would be audibly wrong at the seam and that no
loop-point field existed. A correction that does not reach the artifact a
consumer reads has not been made.

My first check of that fix reported the stale text still present, because the
replacement quotes the refuted sentences in order to name them.

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-30 10:17:51 +00:00
parent 500924be5c
commit 7487c136fa
2 changed files with 84 additions and 20 deletions

View File

@@ -9,7 +9,7 @@ dies, which is what this file is for.
<!-- INDEX: generated by tools/port/index-decisions -- do not hand-edit -->
138 sections. Search this before re-deriving anything.
139 sections. Search this before re-deriving anything.
* [P0 — the exporter, 2026-08-28](#p0--the-exporter-2026-08-28)
* [P1 — Godot draws the screen, 2026-08-28](#p1--godot-draws-the-screen-2026-08-28)
@@ -149,6 +149,7 @@ dies, which is what this file is for.
* [Independent confirmation of the 1.5 MB cap — the mechanism, not just the conclusion](#independent-confirmation-of-the-15-mb-cap--the-mechanism-not-just-the-conclusion)
* [The loop is a runtime field, the two readings conflict, and the port keeps what it shipped](#the-loop-is-a-runtime-field-the-two-readings-conflict-and-the-port-keeps-what-it-shipped)
* [The duration is confirmed and the window is wrong — and the start is now a visible field](#the-duration-is-confirmed-and-the-window-is-wrong--and-the-start-is-now-a-visible-field)
* [The loop window is measured — `-ss 9.44 -t 61.87` — and the near-silence count tracked the error](#the-loop-window-is-measured---ss-944--t-6187--and-the-near-silence-count-tracked-the-error)
<!-- /INDEX -->
## P0 — the exporter, 2026-08-28
@@ -7969,3 +7970,59 @@ implicitly for two days.
command carries `-ss 10 -t 61.93` and the output stays 61.930 s — a window, not a
truncation. Restored to 0.0; the export is byte-unchanged. When the start is
measured this is a one-value edit, not a code change.
## The loop window is measured — `-ss 9.44 -t 61.87` — and the near-silence count tracked the error
The region is **[9.44 s, 71.31 s]** of an 87.744 s wave: the first 9.44 s is an
intro played **once**, the last 16.4 s a fade-out **never played**. Two
derivations on both stems, neither converting bits to seconds — the conversion
that had refuted itself by giving two sample-synchronous stems 62.34 and 63.29 s.
**61.87 replaces 61.93**, 0.1 % apart. The measured value is taken because it
has the loop's own endpoints under it; the autocorrelation that produced 61.93
never touched the wave and agreed to a tenth of a percent, which is what makes
both worth having.
### The port's own near-silence count tracked the window's correctness
| window | near-silent 50 ms frames in ~127 s |
|---|---|
| no trim, `restart` at the wave's end | **36**, spanning 3.4 s |
| `[0, 61.93]` — right length, wrong window | **5**, no run ≥0.2 s |
| **`[9.44, 71.31]` — measured** | **0** |
That is a real corroboration from this side and it was not designed as one. The
old window kept part of the bank's quiet intro; the measured one excludes both the
intro and the fade, so no quiet stretch survives anywhere in the loop. The count
fell monotonically as the window got closer to right.
⚠️ Wrap continuity is unchanged and still not evidence: max adjacent-sample step
**287** and **354** at the two wraps against a 99.9th percentile of **3 812**. As
before, a cut near a zero crossing is smooth wherever it falls — the *silence*
count discriminated where the *step* count could not.
### 🔴 A stale `why` reached the manifest for two days
Correcting `loop_end_why` and `loop_start_why` left `loop_why` — **the field the
exporter concatenates into `manifest.json`** — still asserting that the loop would
be *"AUDIBLY WRONG AT THE SEAM"*, that *"no loop-point field has been identified
anywhere"*, and that trimming *"would INVENT a loop point"*. All three refuted;
all three shipped to any consumer reading the export.
**A correction that does not reach the artifact a consumer reads has not been
made.** The corrections existed, were accurate, and were in the wrong fields.
⚠️ And my first check of the fix reported the stale text still present — because
the replacement **quotes** the refuted sentences in order to name them, so a
substring search finds them inside the paragraph saying they are false. I had to
read the context to see it. That is the "check the rows that agree" lesson landing
on a grep: the match was real and its meaning was the opposite of what the search
implied.
### Why the wait for 9.44 was cheap
Their note is worth keeping: it was not that the field predicted the value, but
that `loop_end_s` alone was **asserting** a start of zero in a form no reader
could weigh or find — and that proving `10.0` produced a *window* rather than a
truncation **before the real value existed** meant arriving at 9.44 was a
one-value edit with a clean baseline behind it.