Commit Graph

1227 Commits

Author SHA1 Message Date
sylph-decoder
c364cde476 re: sweep the disc for the ordinal foot-gun -- GP_TITLE was the mildest case
Last iteration I retracted three claims because `--build 10/11` on GP_TITLE are
entries 12/15, and named the untested remainder in my own report: how much else
in the corpus used a build ordinal as an entry index. This is that sweep.

`screen --build N` indexes a predicate-filtered list, so every rejected entry
shifts every later ordinal. Disc-wide: 21 of 24 build-bearing archives diverge,
18 of them at ordinal 0 -- `--build 0` is entry 108 in each GP_MAIN_GAME_*2D,
24/26 in GP_HANGAR_ARSENAL/GP_READY_ROOM. GP_TITLE is the ONLY archive whose
first ten ordinals are the identity, which is the sole reason 207 of the
corpus's 226 build citations are safe. Second foot-gun: `--all` swaps the
predicate and renumbers 18 archives, so `--build N` and `--build N --all` are
not the same object.

The instrument failed its control first. A version using parse_build as the
predicate reported GP_TITLE as 16 builds, ordinal == entry throughout -- it
would have certified the exact bug it was built to find. The shipped version
uses the same predicates screen_builds() uses and reproduces `screen list` on
GP_TITLE exactly.

Audited all 226 citations. One real defect: a five-row table in
ui-keyframe-time-unit.md headed "declared element (build 11)" spans builds 10
and 11 -- palogo_sqex is in 10. All five placements re-verified and correct, so
the linear-ramp measurement is untouched; only the label was wrong. Fixed with a
per-row bundle column. GP_DIALOG --build 0 and GP_DEBRIEFING_PILOTLOG --build 10
re-run and reproduce.

Refutation attempted: sylpheed-port's corrected mid-ramp test rests on
ptlogo_all_eff holding a=127 from t=112 to t=246. Their quote is exact and it is
a plateau. The refutation fails; their correction stands.

METHOD already carried the rule I broke, and ui-splash-addressing already said
the splashes need --all. The failure was not missing knowledge -- it was
addressing a bundle by index without grepping for the index first.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 13:20:41 +00:00
sylph-decoder
f102cf9209 handoff+method: land the ordinal retraction where the claims live
Marks the two void splash rows in the capture-comparison data file, withdraws the
three claims in HANDOFF, and corrects the METHOD entry -- whose 'a gradient across
buckets is not a mechanism' near-miss was itself resolved by a counter-example
taken with the wrong index.

General form recorded: an index that silently means something else produces
well-formed output for the wrong object, and this project has now been bitten
twice from opposite directions with 'everything still validates' both times.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:59:58 +00:00
sylph-decoder
3356343cad re: RETRACT the splash settle windows -- --build takes an ORDINAL, not an entry
The port recomputed the publisher splash's widest keyframe-free gap as 190 units
against my 8 and said one reading must be wrong. Mine was, and the library was
never wrong -- only my invocation.

From the file: entry 10's union of times is [0,15,30,45,235,239,251,255], widest
gap 190, and settle_window() returns Some((45,235)). Entry 11 gives 145. Both
match the port exactly.

The cause is that screen render --build N takes a BUILD ORDINAL. screen list says
[10] entry 12 and [11] entry 15; the splashes are entries 10 and 11 and are not
screen builds at all, so my --build 10/11 rendered the LOADING screens. This is
the foot-gun HANDOFF already documents, which the port caught months ago in the
mirror direction.

Three retractions:

1. 'Width does not predict quality' -- withdrawn. It rested entirely on the
   splashes being width 8 while winning 75x. They are the widest of the five, so
   width and mid-ramp are perfectly confounded across every screen either of us
   has measured and the width hypothesis is NOT refuted.

2. 'My filter excluded the splashes' -- withdrawn; at 190 and 145 they were never
   near the 10-unit cutoff. The other half stands: it admitted the 10-19 bucket,
   the worst at 45.1 %.

3. The splash rows of settle-vs-rest-against-captures -- void. They scored
   loading-screen renders against splash captures. I discarded them for a railed
   gamma fit; the real reason is that they were the wrong screens, and the railing
   was that mismatch surfacing where my instrument could report it.

Surviving: the title row (ordinal 4 = entry 4) and the disc-wide censuses, which
iterate pak entries directly and never touch the ordinal path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:59:29 +00:00
sylph-decoder
ca41b81377 method: a borrowed threshold still has to be checked against the cases it decides
The under-10-units filter was documented and reasonable and wrong both ways: it
admitted the 10-19 bucket, the worst at 45.1 % mid-ramp, and excluded the two
splashes at width 8, the strongest evidence for the proposal it was serving. One
--settle invocation per screen would have shown this in seconds.

Plus the near-miss: the bucket gradient made 'narrow window means bad settle
pose' look obvious, and it is refuted by two screens inside the excluded band
that win by 75x and 33x. A gradient across buckets is not a mechanism.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:45:59 +00:00
sylph-decoder
9d32852724 re: census the settle pose's own failure mode -- and refute the obvious explanation
The port found ptmsg, the main menu's footer, at alpha 127.5 at that screen's
settle instant. Verified: build 5's window is [44,56] = 12 units and
screen render --settle already prints 'narrow -- this bundle may never settle'.

Disc-wide, elements caught mid-ramp at their screen's settle instant: 25.5 %
overall, 40.9 % on windows under 10 units, 45.1 % on 10-19, falling to 11.7 % and
15.0 % on wide ones.

The obvious reading of that table -- narrow window means the settle pose is bad --
is REFUTED by the screens that motivated the proposal, and I nearly published it.
The two splashes have an 8-unit window, narrower than the main menu's 12, and the
settle pose beats rest() there by 75x and 33x. Width does not predict quality.

The predictor is the port's own statement: the settle pose wins decisively where
rest() lands on a transient's peak, and loses slightly where rest() is already
sound and an element arrives after the window closes.

And my own rest_vs_settle filter was wrong in both directions: dropping bundles
under 10 units admitted the 10-19 bucket, the worst at 45.1 %, and excluded both
splashes at width 8 -- the strongest evidence FOR the proposal. A threshold taken
from a documented rule of thumb and applied without checking which screens it
admitted and which it threw away.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:45:33 +00:00
sylph-decoder
54254a86e1 method: correct 'cannot adjudicate against the incumbent' -- it needed a discriminator
The entry said a candidate-vs-incumbent comparison is the wrong shape of
experiment. Too strong. Two iterations later the same comparison adjudicated with
no new oracle, once a structural property was added that says which side is wrong
per disagreement -- does the chosen run contain the settle instant. Control 3072
of 3072; disagreements attributed 1036 of 1036.

Corrected rule: a bare comparison cannot adjudicate because a disagreement is
symmetric; it becomes decisive the moment a property breaks the symmetry per
case. Reach for an oracle when no such property exists, not as the first move.

With the tell that I had one available and did not look: I recorded the residual
as 'ambiguous by construction' and moved on TWICE without asking what would make
it un-ambiguous.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:38:44 +00:00
sylph-decoder
642341b12b re: rest_plateau() picks the wrong plateau -- and it is the whole residual
rest_plateau() selects the LONGEST run of identical adjacent poses, which need
not be the run covering the screen's settle instant. rest_vs_settle left a 21.9 %
disagreement that I recorded as ambiguous by construction. It is not.

  CONTROL  exactly one plateau, covering the settle instant:
           3 072 / 3 072 agree (100.0 %)
  TEST     more than one plateau, at least one covering:
           1 622 elements, agree on 586 (36.1 %)
           of the 1 036 disagreements, rest() landed on a run NOT covering the
           settle instant: 1 036 -- all of them, no exceptions

Both poses are genuinely held in these cases -- they are plateau cases, not
transients -- so this is rest() returning a pose the screen has ALREADY LEFT by
the time it settles.

This corrects my own METHOD entry of two iterations ago, which said a candidate
cannot be adjudicated against the incumbent it replaces. Too strong. The bare
comparison cannot; the comparison plus a structural property that independently
says which side is wrong in each disagreement can. What I lacked was not an
oracle but a discriminator.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:38:18 +00:00
sylph-decoder
b37eb4a5bc handoff: settle_time() itself beats rest() on the one screen that adjudicates
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:30:23 +00:00
sylph-decoder
10f469cbed re: settle_time() itself beats rest() against the game -- on the one screen that adjudicates
Closes the gap the port named: it ran my proposal against captures 3/3 in favour,
but tested ITS OWN settled pose rather than UiBuild::settle_time().

Geometry established first, because my first attempt got it wrong: a 1280x720
render meets a 1279x675 capture by CROP, not scale -- crop rows 0..675 gives RMSE
14.07 against 68.89 resized and 79.61 for the 45-row crop. The 45-row offset
holds for a full display frame; these captures are already the game surface.

Gamma fitted per pose so neither candidate can win on the fit:

  title      settle  g=0.84  RMSE  8.17  15.28 % >8
  title      rest    g=1.04  RMSE 20.92  70.84 % >8

The two splashes DO NOT ADJUDICATE and are not counted: their gamma fit rails at
the edge of the search range, still railing when widened to 0.30..3.00, so the
photometric model is wrong for them -- and with gamma railed their margins
collapse to 1.16x and 1.06x.

title adjudicates at an interior gamma and does so decisively, 4.6x on differing
area and 2.6x on RMSE. So the IMPLEMENTATION and not merely the direction is
supported.

Absolute agreement is poor -- the port's settled title row is 0.21 % where mine
is 15.28 % -- so the ordering is what this table carries, not the values. The
port's three-screen result remains the stronger evidence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:30:07 +00:00
sylph-decoder
3aa47f77a7 method: a candidate cannot be adjudicated against the incumbent it replaces
Plus the two companions: any statistic keyed on where an element's visibility
ends is near information-free here (87.8 % end at a=0 from the screen's exit
ramp, which bit both agents within an hour), and the port's mirror -- my
threshold-free 'nothing is held on this path' criterion is correct on the
fallback path and fails outright on the plateau path, so a cleaner definition
that fails a control is worse than an ugly one that passes.

HANDOFF carries the proposal with its evidence, its failed control, and an
explicit refusal to change rest() in a crate the port pins on the strength of
something I cannot validate from my own side.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:23:10 +00:00
sylph-decoder
0c9224fbbc re: propose settle-instant posing -- and my control cannot validate it
The proposal: pose every element at the SCREEN's settle instant rather than
asking each element for its own resting pose. On the 2 249 fallback elements in
settling bundles the visible-pose rate falls 73.6 % -> 34.7 %.

But the control fails twice. Naive, over every plateau element: 46.6 %. That one
was misspecified and I caught it by asking what the number means physically --
rest() finds *a* held pose and many elements hold one during the build-in then
move on, so it answers a different question and disagreement proves nothing.
Restricted to elements HOLDING ACROSS the settle instant: 78.1 %, still not a
pass.

And the residual is ambiguous by construction: rest_plateau() picks one plateau,
so an element with two whose settle instant falls in the other will disagree --
and there pose_at(settle) is RIGHT. The control cannot separate 'the candidate is
wrong' from 'the incumbent is wrong'.

Recorded as the general point: comparing a candidate to the incumbent cannot
adjudicate when the incumbent is the thing under suspicion. It is the wrong shape
of experiment, not a tuning problem.

What does adjudicate is the oracle and it is the port's measurement, not mine --
publisher splash against a committed capture, settle-instant pose RMSE 2.17 /
0.01 % differing against --pose=rest 9.05 / 0.75 %. My numbers describe the
proposal's effect; they do not establish it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:22:44 +00:00
sylph-decoder
e988f6e090 handoff: correct the fallback number to 1457, and record the failed correction
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:13:57 +00:00
sylph-decoder
c89e4da723 re: my own 1697 audited -- and the first correction failed its control
Applying the port's physical-story rule to my own number. '1 697 fallback fires
return a visible pose' was published as if it were a defect count; it is not, since
an element that genuinely ends visible should rest visible.

The first correction split the 1 697 by whether the element's LAST keyframe is
visible: 347 correct, 1 350 transient peaks. Plausible, arithmetic fine, and
WRONG -- 12 278 of 13 991 elements (87.8 %) end at alpha 0 because a screen's exit
ramp drives everything to zero, so the split carries almost no information. The
1 350 is not published.

What survives needs no such split: the fallback runs only when no two adjacent
poses are equal, i.e. only when no pose is held, so every pose it can return is
un-held by construction -- and 1 457 of the 2 305 times it returns the element's
MAXIMUM alpha, the brightest un-held pose.

I ran that control only because the port had just been bitten by the same exit
ramp, its census calling ptmsg -- the main menu's permanent footer -- 'a 2-unit
flash'. Without its message the 1 350 would have shipped.

METHOD gains the sharpened form: the physical-story test catches confident FALSE
claims, not just nulls. A wrong number usually still has a story, just an absurd
one. Plus the tell that its fix was right -- re-keyed on the screen's span, the
false positives fell out on their own, and a definition that stops needing
hand-maintained exceptions is usually the correct one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 12:13:46 +00:00
sylph-decoder
ef851fec92 method: say what the number means physically and see whether the story survives
From the port, and a better generalisation than mine. I had been filing my
failures under 'an external quantity caught it', which prescribes finding an
anchor; anchors are not always available. The port's title_jp error had none --
every control passed because the metric was fine and the error was which frame it
scored. What caught it was asking why rest produced that light, which exposed a
4-unit sparkle whose rest.t is its own peak.

So: state what the number means physically and see whether the story survives
contact with the data. A wrong frame yields a number with no physical story
behind it, which is detectable from the inside. It subsumes the null-as-result
cases too.

And a control does not test this: a control proves the INSTRUMENT and says
nothing about the SAMPLE.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:55:10 +00:00
sylph-decoder
ad9cd948c6 re: the port's two extra elements are PLATEAU cases -- refutation succeeds, and its point gets bigger
The port listed palogo_gamearts_eff and palogo_seta_eff among GP_TITLE's four
visible dwell-fallback fires; this census listed only palogo_sqex_eff and
palogo_anima_eff. Checked, and the census is right: gamearts_eff and seta_eff
hold a=255 at identical x, y and scale from t=15 to t=30, which is a plateau at
pair index 1, so rest_plateau() handles them and t=15 is the CORRECT answer. They
are not fallback cases.

The distinction is not cosmetic -- a plateau is a pose the element genuinely
holds, and only the dwell fallback is the unsound path.

But the refutation makes the port's underlying point STRONGER. Its rest pose for
those two really is the flash's peak, reached by the SOUND path. So 'a rest
render is not a frame to score against a capture' does not follow from the
fallback being unsound: a plateau can itself be the held peak of a transient. The
rule covers both paths, and the fallback census understates the exposure rather
than bounding it.

Also records the port's oracle number for the rule -- publisher splash against
the committed capture, timeline RMSE 2.17 / 0.01 % differing against --pose=rest
9.05 / 0.75 %, 75x the differing area.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:54:43 +00:00
sylph-decoder
28b06f9a31 handoff: rest is not a settled pose -- 1697 of 2305 fallback fires return a visible pose
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:50:25 +00:00
sylph-decoder
cae2f7596e re: the rest() fallback -- its example dissolved, the question got bigger
ui-resting-pose.md built its dwell-fallback section on GP_TITLE build 7's
ptlogo_eff3.t32, listing keyframes [46, 61, 103, -] -- the STALE PARSER's output.
Corrected they are [0, 46, 61, 103], the longest gap moves from 61->103 to 0->46,
and BOTH ends of the new longest gap are a=0. The element no longer selects a
visible pose under either indexing, and build 7 renders byte-identical under the
corrected and legacy readings (0 px differ). MISSION lists this element as the one
case a Japanese capture was needed to discriminate; it is not.

But losing an example is not closing a question, so: disc-wide census. The
fallback fires on 2 305 of 13 991 elements and returns a VISIBLE pose in 1 697 of
them -- 74 %.

GP_TITLE is 5 fires, 4 visible, and all four are on the SPLASH screens:
palogo_sqex_eff and palogo_anima_eff, each [0:a0 15:a255 30:a212 45:a0], a flash
peaking at 15 and dead by 45 where the fallback returns t=30 a=212.

Independently converged on from the other side: the port, working from the JP
capture and knowing nothing of this census, found ptlogo_back2eff1's rest.t at the
peak of its own 4-unit sparkle with six staggered across the logo, so --pose=rest
fires every sparkle at once -- a frame the game never shows.

Consequence recorded as a rule: a render posed at rest is a legitimate common
reference for comparing two DECODERS and is not a frame to score against a
capture of the game.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:50:07 +00:00
sylph-decoder
3b52240d83 handoff: the JP title at rest is captured, with its rest demonstrated
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:37:54 +00:00
sylph-decoder
279a33846e re: the Japanese title at rest -- the capture MISSION has wanted since 2026-08-29
Asked for by the port: its title_jp row drifted, localized to a 350x396 block at
(405,74) -- the logo stack -- and with no JP capture in the corpus it could say
the renderers moved apart but not which one moved.

Three earlier attempts failed to reach the interactive title in either locale.
The reason is now known and was never the locale: A at the title needs a
signed-in profile, and no run had one.

Locale set through canary's own persisted XConfig and restored afterwards,
verified back at language=1. INDEPENDENT confirmation it took: the XMA probe
logged a different voice-context set from every English run (ja 1112064 /
1150976 / 1177600 against en 1294336 / 1118208 / 1171456), so the switch reached
the guest rather than being a menu-language cosmetic.

'At rest' is demonstrated rather than assumed. Five frames ~1.5 s apart after the
plate pulse says the screen has settled: the port's ROI is byte-identical across
all of them, max |delta| 0 over 138 600 px, while the WHOLE FRAME moves 39 584 to
71 927 px -- the plate pulse and sweeps. That contrast is the control: the
instrument can see motion and the ROI still shows none.

The capture shows what the English title does not -- the katakana subtitle, and a
crystalline burst behind the wordmark, the ptlogo3a/b/c + ptlogo_back2eff* stack
that this corpus records as transparent at rest in English. Exactly the region
the port's drift is localized to.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:37:35 +00:00
sylph-decoder
8ad87012fb handoff: the fade ramp is 10 units decoded, and screen info was stale
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:22:59 +00:00
sylph-decoder
83b7316065 re: the CLI binary was STALE -- screen info's keyframe times were the old parser's
The copy of sylpheed-cli in this container was built 2026-08-29 12:38, before the
keyframe-record-layout fix. The old parser shifted every time by one slot and
could not time a group's final pose, printing a trailing '-':

  stale  pteff00.prm  4 kf  rest t=70  [12:0,0 70:0,0 80:0,0 -:0,0]
  fresh  pteff00.prm  4 kf  rest t=12  [ 0:0,0 12:0,0 70:0,0 80:0,0]

Both outputs are well-formed and neither announces its age.

That refutes the premise of screen-transitions.md's 2026-08-29 section, which
argued from 'there is exactly one untimed keyframe, and every element has it'.
There is no untimed keyframe, so the question it answered -- is 0.4 s the missing
duration of that keyframe -- has lost its subject. The ratio test in the same
section is untouched.

And it decodes the number the port asked about: pteff00.prm's final ramp is
70 -> 80 = 10 units, about 0.167 s, not the ~24 this page authored. I tried to
refute the port's 10 against the bytes and could not.

So the measured ~0.4 s is NOT the ramp alone -- 24 units measured against 10
decoded. That the remaining ~14 units are exactly the black hold is arithmetic
that fits (0.233 s, inside this corpus's own 0.17-0.23 s plateau) and is NOT a
measurement; the decomposition stays open.

CONTAINER-NOTES gains the trap. Renders are byte-identical across the two
binaries (max per-channel difference 0 on GP_TUTORIAL build 0), so element
identity, pivots, keyframe counts and screen render output are unaffected -- it
is the times that move.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:22:43 +00:00
sylph-decoder
951b9a4c80 handoff: Q5's two weak clauses are measured -- both stampable now
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:18:42 +00:00
sylph-decoder
1eee838f30 re: three empty evidence cells filled in one run -- auto-repeat, B on a settled title, plate redraw
1. NO AUTO-REPEAT. A 2.0 s held DOWN moves the cursor exactly once. The counter
   passes its control first: a single 0.12 s tap gives exactly 1 spike and the
   hold gives 1, with the move spike at 0.0202-0.0220 against a 0.0003-0.0038
   noise floor. The port had flagged that the hedge 'at the durations tried' was
   carrying the claim, and it was -- nothing recorded a HELD direction.

2. B ON THE SETTLED TITLE DOES NOTHING. Twenty seconds after a
   delivery-confirmed B the screen is still the title with PRESS (A) BUTTON up,
   read off a capture that names itself. This is the run the previous attempt
   could not be: it waited for the plate pulse, the title's own settled
   signature, instead of pressing during the build-in.

3. THE PLATE IS RE-DRAWN after B from the menu -- pressed at 351.2 s, pulse
   detected at 358.5 s. That was the other unevidenced half of the B-on-menu row.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:18:18 +00:00
sylph-decoder
7a63501bc1 handoff: split Q5's bundled 'measured' -- a label is as strong as its weakest cell
The port's authored/flow.json stamped title/on_cancel_why = 'MEASURED, HANDOFF
Q5' for a clause whose evidence cell in the source table reads 'none'. It did not
invent that: HANDOFF's Q5 row opened with one **measured** covering six clauses of
different strength, and HANDOFF is the document it authors against.

Split per clause. Measured: initial focus varies; up/down move one item per press
and wrap both ends; left/right do nothing; B on a submenu restores focus 4/4; B on
the main menu goes to the title in <= 0.4 s with no loading screen. NOT measured,
evidence cell empty: 'no auto-repeat at the durations tried', and 'B on the title
-> nothing'. Both marked do-not-stamp.

Also splits the source table's own up/down row, which bundled 'one item per press'
(indirectly but soundly evidenced by the 4-press wrap count) with 'no auto-repeat'
(nothing behind it, and the hedge was carrying the claim).

METHOD entry: the failure is in summarising, not at either endpoint. The source
table was honest and the consumer cited its source; flattening six claims into one
adjective created a provenance nothing supports. A strength label is not
distributive.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:11:08 +00:00
sylph-decoder
c3b66c4b91 handoff: on_cancel from the main menu is measured
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:06:32 +00:00
sylph-decoder
78cb1d4e9b re: B on the main menu goes to the TITLE -- measured, filling an empty evidence cell
menu-navigation-semantics.md had this row at yellow with an EMPTY evidence cell,
and it is what the port still authors as on_cancel.

Delivery-confirmed via [RE-INPUT] (B is kXInputPadB = 0x5801), change detected
rather than timed. B delivered at 331.2 s; the glyph leaves 327 by 331.6 and
73.5 % of pixels differ. Both captures name themselves: PROJECT SYLPHEED with the
(C)2006,2007 SQUARE ENIX line.

Three things measured:
  * B on the main menu goes to the title;
  * latency <= 0.4 s at a 4 Hz sample rate, where the corpus previously had this
    as 'not measured (a backlogged probe void)';
  * NO loading screen in between -- the disc carries four pgloading_* bundles and
    none appears on this path.

What the run CANNOT say, recorded in the table rather than glossed: 'B on the
title -> nothing' is still unevidenced. The second B was delivered during the
title's build-in, so the glyph 0 -> 154 change after it is the build-in
completing, not a response. A run that answers that row must wait for the title
to settle before pressing.

The 're-draws PRESS A after a beat' half of the first row is also still
unevidenced -- the run ended with the plate absent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 11:06:18 +00:00
sylph-decoder
dc0b84c87f handoff+index: a .tbm draws, and screen render omits it silently
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:53:57 +00:00
sylph-decoder
ddc2a8e36b re: a .tbm DRAWS -- the TUTORIAL screen captured, and the 'inert' reading refuted
Closes the open second reading in ui-forced-backdrop.md: that a .tbm contributes
no pixels, leaving 24 of its 62 deciding verdicts harmless rather than correct.

The TUTORIAL screen was reached and captured. It carries a full-screen blue
circuit/hex background. GP_TUTORIAL build 0's element 0 is pubase.tbm with pivot
(640,360) -- 1280x720, the only full-screen TEXTURED element in the bundle; the
one other full-screen element is pueff00.prm, an untextured primitive the colour
census puts at pure black. Our render of the same build is the identical layout
on pure black, 6.0-6.4 % inked against the game's 99.7 %. The only difference is
the background and the only thing it can be is the .tbm.

So the 24 .tbm verdicts are correct rather than harmless, and they are
load-bearing in the full sense. Reach: one .tbm observed; the class question is
settled, the ten other families are not individually seen.

Also: screen render is wrong on every screen carrying a .tbm -- it drops the
background silently, with no diagnostic.

And the identification is worth its own METHOD entry. Two statistical identifiers
were built. Masked correlation FAILED its control, picking EXTRAS over the known
main menu by 0.004 because the shared background dominates. A high-passed variant
PASSED by 1.28x, which is not a margin that licenses identifying an unknown, so it
was not used. The screen says TUTORIAL across the top. Ask whether the artefact
already states the answer before building a matcher.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:53:34 +00:00
sylph-decoder
77e54e95a5 re: a submenu is REACHED -- and correlation cannot identify it
Third attempt at the .tbm question. All three fixes from the previous page were
applied and all three were needed: hold A for 0.5 s, confirm delivery from
[RE-INPUT] rather than from the pad, and detect the screen change instead of
timing it. Title at 288.6 s, both presses delivered on attempt 1, submenu at
303.4 s with 87.1 % of pixels changed.

The capture is 99.7 % inked and uniform top to bottom -- a full-screen
background. Our renderer gives 1.9-3.0 % for all 19 GP_SAVE_LOAD builds,
6.0-6.4 % for GP_TUTORIAL, 78.4 % for GP_SYSTEM 0/1. So two of the three
archives render essentially nothing where the game draws a full screen.

But WHICH screen was captured is not established, and the reason is worth more
than the run: correlation cannot discriminate when the candidate renders are
near-blank. All 19 GP_SAVE_LOAD builds score -0.004..-0.010 -- a ranking with no
information. A matching statistic is useless against a hypothesis that predicts
an empty image, which is exactly the hypothesis under test.

Focus could not be read either: the two labelled menu captures fit at 2.52 and
2.48 mean absolute difference, 1.6 % apart. That is a SECOND statistic failing on
the focus problem after the per-row brightness one, so it is an open item rather
than an oversight.

Kept regardless: the game surface sits at y=45 in the 1280x720 display frame,
fitting the committed 1279x675 captures to 2.5 mean absolute difference. That is
the alignment the earlier cross-geometry comparison got wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:49:48 +00:00
sylph-decoder
ac1b76ee39 re: run 'grep the corpus for the claim' on this corpus -- four still standing
Applying my own METHOD entry one iteration after writing it found four refuted
statements still asserted unmarked where a reader lands:

  * envelope correlation 'has no resolving power' -- in three places including
    HANDOFF. The port controlled the same estimator on a single track and got
    r=1.0000 at zero offset; the saturation needs CONCURRENT streams sharing
    timing. I agreed to this in a message and never landed it.
  * '8 of 10 three-chunk regions' -- still asserted in HANDOFF in a different
    section from its own correction.
  * 'r9 is a wild pointer, never a guest address' -- still asserted inside the
    kept-for-the-record section.
  * the ALSA channel permutation, stated without scope, when a later capture
    measured the identity and labelling from it put the silent channel on the
    wrong name.

All four marked in place, striking the sentence and pointing forward.

Two lessons added: a 'kept for the record' section still asserts, so labelling
the heading is not enough; and naming a refuted claim keeps it greppable, so the
audit returns its own corrections as hits and every hit needs reading.

The first item is the one worth admitting: I acknowledged that correction in a
message, wrote the entry about corrections that never land, and then did not land
my own for a full iteration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:35:27 +00:00
sylph-decoder
e882900f85 method: 'it did nothing' and 'it never happened' look identical from outside
An A press produced no screen change; the obvious reading was that the button did
nothing. The log said the press was never delivered -- two file-pad vk=5800 lines
across the whole run is ONE press -- because it was issued 0.8 s after a screen
appeared, while the guest was loading and not polling.

The pad driver reports what it emitted, so a script checking its own output sees
success either way. Confirm the receiving side.

Generalised: when an action produces no observable effect, the first hypothesis
is that the action did not occur, not that it had no effect. The corpus has paid
for this twice -- here, and in the sign-in swallow where thousands of delivered
keystrokes were discarded inside the emulator and looked exactly like a dead pad.

Companion to the control entries: a control proves the instrument reads
correctly; a delivery check proves the experiment happened at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:31:12 +00:00
sylph-decoder
bbc167425f re: the .tbm submenu is not reached -- and the second tap was never delivered
Two runs, neither answering whether a .tbm draws pixels.

Run 1 TIMED the title->menu transition and was still on the title 8 s later
(glyph 714, the plate's pulse trough), so the second tap did the transition and
the 'submenu' capture is the menu. Void.

Run 2 DETECTED the menu instead -- glyph 327, matching live-main-menu.png
exactly -- tapped 0.8 s later, and 12 s after that was still on the menu. The
log says why: 2 file-pad vk=5800 lines, i.e. ONE press, and one RE-INPUT
delivery. The second tap was never delivered, with zero swallow lines so it is
not the sign-in path. A 0.12 s press issued while the guest is still loading a
screen is missed outright.

So 'the press did nothing' and 'there was no press' look identical from the
screen, and only the log separates them.

Worth more than the run: this is the third time in one iteration that timing was
used where detection was required -- the title->menu wait, the menu->submenu
wait, and the press itself. Each fix is the same substitution, and each was
written only after the timed version had produced a confident wrong answer.

Also records that no focus detector is needed for this question, since every
main-menu destination except EXTRAS carries a .tbm decider.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:30:49 +00:00
sylph-decoder
12159be61f re: land the loop-point correction where the claim actually lives
The port found its exporter still shipping 'no loop-point field has been
identified anywhere' in the field manifest.json concatenates, days after the
correction existed in other fields. Auditing this corpus the same way found the
same failure here: the refuted sentence was still standing untouched in
bgm-two-stems.md -- where anyone looking up BGM behaviour arrives -- and in
HANDOFF.md, the one page the port is told to read. My correction had gone into a
NEW page only.

Both fixed in place, each naming the refutation rather than quietly deleting the
old claim, and each carrying the measured window [9.44, 71.31] s at 61.87 s.

METHOD entry: writing a correction down is not landing it. Grep the corpus for
the CLAIM, not for the file you were working in. Plus the port's trap in doing
that audit -- a replacement that quotes the refuted sentence in order to name it
will match a substring search from inside the paragraph saying it is false.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:20:04 +00:00
sylph-decoder
e1f2a7f714 re: the menu loop starts at 9.44 s -- measured, and the fix was scheduling
Tailing the log from BEFORE the music starts cut the unsampled backlog from 616
samples spanning offsets 32..2,559,033 to 125 spanning 32..515,239, so the first
pass is sampled like any later cycle. Offsets below loop_start play exactly once,
which is why the previous run could not measure them.

Wraps at 96.46 / 158.33 / 220.21 s, gaps 61.87 / 61.87, both contexts together.

Two derivations, neither converting bits to seconds:
  (a) time to read_offset crossing loop_start, plus a 1.33 s head correction at a
      rate measured on 748 timestamped samples of that same stretch
  (b) first pass (offset 32 -> loop_end) minus the cycle
Both give 9.44 s on both contexts -- four numbers, one value.

So the loop region is [9.44, 71.31] s of an 87.744 s wave, cycling every 61.87 s.
The first 9.44 s is an intro played once; the last 16.4 s, the fade-out
bgm-two-stems.md documents, is never played at all.

The decoder reads ahead of playback, but both endpoints are read_offset events so
the lead cancels in the difference. One boot, one bank.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:13:14 +00:00
sylph-decoder
10df64e7d0 method: a control easier than the measurement bounds nothing
My locator validated on slices cut from the wave itself -- found exactly, control
passed perfectly -- and the measurement was still ten seconds wrong, because
matching an exact copy is a different problem from matching a real capture and
music with repeated sections is where a locator aliases. Its clean +5.00 s
stepping showed self-consistency, which is also what an aliased lock looks like.

Paired with the port's mirror image the same day: an awk that read 0 for every
span produced a perfectly structured result agreeing with the hypothesis under
test, and its tell was that the CONFIRMING rows were impossible too.

Both point the same way: the tell is in the rows that agree with you. Checking
the disconfirming half harder is the intuitive discipline and it is the wrong
half.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:04:18 +00:00
sylph-decoder
d949a2216f re: the menu loop WATCHED -- three wraps, 61.81 s, and my placement is refuted
Settles the conflict by timing the loop instead of converting it. A tailing probe
stamps read_offset with the wall clock as each log line arrives, so the period
needs no bits-to-time step -- the step already shown to be invalid.

Three wraps, each exactly loop_end -> loop_start, and BOTH CONTEXTS WRAP AT THE
SAME INSTANT all three times. That is the property two stems of one performance
must have and the one the linear conversion could not deliver (62.34 vs 63.29 s
would drift a second per cycle).

Cycle 61.56 and 62.06 s, mean 61.81, against the audio autocorrelation's 61.93 --
0.2 % apart from instruments sharing nothing.

Linearity refuted a second time and internally: the fitted rate over 10..60 s is
341 394 bits/s while the cycle covers 22 034 741 bits in 61.81 s = 356 491
bits/s, 4.4 % apart inside one stream.

My own audio locator's PLACEMENT is refuted. loop_start at 3.6 M bits is 11.6 %
of the stream by any reading, ~10.1 s at the cycle's own mean rate, against the
0.25 s that page reported -- for the reason already suspected, that its control
matched slices cut from the wave itself and never tested the aliasing the real
problem has. The length was right and the span was wrong.

Still not measured: loop_start in seconds. Offsets below it play exactly once and
this trace stamped that whole stretch at t=0.002, swallowing the log backlog in
one read, because it started after the music. The fix is to start the trace
before tapping into the menu -- one line, not done.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:03:52 +00:00
sylph-decoder
cf6be709ab re: the loop IS a runtime XMA field -- and reading it contradicts my audio measurement
No Canary patch was needed: UpdateLoopStatus already logs loop_start/loop_end,
they just need the Apu category (--log_mask=13 --log_level=3).

Decoded, from the menu, 8734 records all after BGM_103's contexts appear:
  ctx0 (wave 3876864)  loop_start 3605682  loop_end 25640423  loop_count 255
  ctx1 (wave 3930112)  loop_start 3539158  loop_end 26216351  loop_count 255
The movie's three ADV streams log NO loop records -- they do not loop.

Semantics visible in the trajectory: read_offset runs from 32 upward and 20 % of
samples sit below loop_start, so the stream plays from the beginning and
loop_start is where it returns AFTER loop_end. No wrap was observed -- the 45 s
hold ended with read_offset at 17 M against a loop_end of 25.6 M.

Two registered predictions REFUTED. loop_start is not ~0 but 11.6 % in. And a
linear bits-to-seconds conversion is invalid: it gives 62.34 s and 63.29 s for
two stems that must play sample-synchronously, which is impossible, so the data
refutes the assumption on its own.

That leaves a conflict I am not resolving: the field implies a cycle of roughly
[10 s, 72 s]; my audio tracking reported offsets 0.25..57.18 s. Recorded as
contested, with the likely weak link named as mine -- that locator's control used
slices cut from the wave itself, exact copies, which is an easier problem than
matching a real capture, and a control easier than the measurement does not bound
its error.

The port is told to change nothing: its trimmed 61.93 s loop is verified in its
own output, and the length survives better than the placement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 09:52:13 +00:00
sylph-decoder
5f386111ad re: count the voice-region population properly -- 25 three-chunk, and 17 of them were broken
Pays the debt from the truncated audit. The census prints population, coverage
and skips in the same output, and ends with an explicit END line, so a cut-short
run cannot be read as a complete one.

  POPULATION 104 movies; COVERAGE 95 resolved, 9 unresolved, 0 unreadable
  70 one-chunk regions, 25 three-chunk regions

The port's 25 was right; my '8 of 10' was not a count.

Cross-referenced against the fix's own sweep, which also ran to completion
(78 + 17 + 9 = 104): all 17 changed regions are three-chunk, none is one-chunk,
and 8 three-chunk regions were never affected -- which the 1.5 MB cap predicts,
since a region only trips the filter if its span exceeds it.

So 'the defect is specific to the multichannel regions' survives with complete
populations on both sides, while 'all three-chunk regions were broken' does not.
The original 8-of-10 was wrong in its denominator and coincidentally shares a
digit with the 8 that are unaffected, which is the kind of resemblance that
carries a dead number into a later document.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 09:46:08 +00:00
sylph-decoder
45a21f0d33 method: a sound instrument, a correct number, and the wrong sentence around it
Named by the port after hitting it twice in a fortnight -- a real 3.4 s seam
written up as the cost of a missing loop point when our own loop produced it, and
a real r=0.998 correlation written up as a duplicate when it was a
start-truncated simultaneous stream.

Distinct from everything else in this file, which is about broken or misspecified
instruments. Controls test whether a measurement is faithful and say nothing
about the clause that follows it. The defences that work are naming the
alternative explanation so it can be rejected, and noticing when a measurement
taken in OUR output is being used to make a claim about THE GAME.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 09:40:39 +00:00
sylph-decoder
fa832fad1e re: the menu BGM loops at 61.93 s, and the game never reaches the fade
240 s parked on the main menu, reached by using the XMA probe log as the screen
oracle instead of video -- the route the previous iteration wrote down. Menu in
26.8 s against never-in-378 s for the video rig, guest at 0.92x, capture at
0.08 % silence against the recipe page's own best of 0.31 %. BGM_103's contexts
verify the screen and no ADV context appears afterwards, so the attract loop
never took over.

Three results, two instruments.

NO SEAM: zero runs >= 0.3 s below median-18 dB in 232 s. The port's 3.4 s
near-silence is a property of its authored loop, not of the game.

NOT THE WAVE LENGTH: autocorrelation r at 87.750 s is -0.009 on four independent
windows; the top lag is 61.909 s with a 2x harmonic. Estimator controls recover
87.750 and 60.000 exactly.

61.93 s, INDEPENDENTLY: locating 30 s slices of the capture inside the decoded
summed waves shows playback advancing exactly +5.00 s per 5 s and wrapping at
61.93, from three wraps. Control: slices cut from the wave itself at 10/45/70 s
are found at 10.00/45.00/70.00. Two points mis-lock where the slice straddles a
wrap and they carry the two lowest scores in the table.

Offsets span 0.25..57.18 s of an 87.744 s wave, so the loop is [~0, 61.93) and
the final ~25.8 s is never played -- exactly where bgm-two-stems.md found the
fade-out and trailing silence. The game loops before the fade, which is why
there is no seam.

Also corrects my own '8 of 10 three-chunk regions start mid-stream'. The port
counts 25 three-chunk regions; it is right that both numbers cannot describe the
same set. My audit run was CUT SHORT -- the committed file ends mid-list with no
summary line -- so that was a ratio over an unknown fraction of the population,
and the claim that the defect is specific to multichannel regions is now
unsupported. The ADV verification and the fix's own sweep are unaffected; that
sweep ran to completion and printed its totals.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 09:34:42 +00:00
sylph-decoder
57035a700b handoff: the menu BGM loop is attempted and not captured; the route left
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 09:22:01 +00:00
sylph-decoder
4ce639c63d re: the menu BGM loop is NOT captured -- and the rig that cannot take it
Recorded per 'do not improvise around a blocker'. The question is what the game
does at BGM_103's loop seam, where the corpus has 'not a seamless loop, no
loop-point field found, so the menu loop is authored' and the port measures a
3.4 s near-silent seam.

Audio needs the ALSA tee; detecting the title needs video, so --gpu=null was
unavailable. Measured twice: the guest runs at ~0.20x real time (76.5 s of audio
in 378 s of wall clock) and the title is not reached in 300 s even after tapping
A to skip the movie, with the tee's slave ending in a broken pipe and Xenia in
underrun recovery. Not a crash -- rss 701 MB with 9.5 GB free, and the 'Killed'
line is this harness's own cleanup.

REFUTED along the way: CONTAINER-NOTES says --gpu=null runs here die at ~70 s.
The intro-audio capture ran 148.02 s under --gpu=null and ended on its probe's
timer with the emulator alive and the whole ADV movie decoded. More than twice
the quoted lifetime. That note had been the reason not to use --gpu=null for
anything long, which is exactly what a clean audio capture needs.

The route left, written down rather than attempted: use the XMA probe log as the
screen oracle instead of video. Sitting on the main menu decodes exactly BGM_103's
two waves, so their byte_sizes appearing IS the menu -- which is better
provenance for an audio question than a screenshot anyway.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 09:21:47 +00:00
sylph-decoder
3392982e58 method: over-warning is what makes the next real warning unreadable
From the port, after two rounds of its 'known incomplete' banner firing wrongly
-- once with a message true only for ADV, once claiming a gap over 93.694 s of
exact zeroes. Both errors were in the cautious direction, which feels like the
safe mistake and therefore goes unexamined longer than a false all-clear would;
the cost is deferred onto the one occasion the warning is true. A warning needs
the same scrutiny as an assertion, starting with what it keys on.

Also records S00A's kept count moving 1 -> 2 after the voice-region fix, on an
asset the fix was not derived from and with the prediction preceding the
observation -- at the strength it actually has. A different ASSET is evidence
about generality; a different IMPLEMENTATION is what would make it independent,
and only one of those was present.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 09:11:10 +00:00
sylph-decoder
dbb12036c1 method: an internal check cannot catch a bug that makes the input smaller
The voice-region truncation survived every test because there was nothing to
catch: the region parsed, the chunks decoded, the durations were self-consistent.
A missing third of a stream is smaller VALID output, and no check written against
our own output distinguishes that from correct output. What caught it was a
number from outside -- the running decoder's byte_sizes not fitting the region.

So: prefer at least one test per decoder pinned to something we did not produce,
and say so in the test, because the obvious maintenance of such a test is to
re-baseline it against current output, which deletes the only thing it was for.

Plus the port's corollary: it was checkable only because the identifier happened
to be a byte count. Index a handed-over result by a quantity the recipient can
test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 08:56:14 +00:00
sylph-decoder
3dbfa320ae formats: drop the 1.5 MB cap that truncated 17 voice regions' first stream
The cause, and the fix, with a disc-wide check.

resolve_movie_voice_region picks start = the predecessor cue's trailer, then
filtered it with 'end - s < 1_500_000' -- 'only within one bank'. ADV's
predecessor sits 3 618 816 B before end, so the filter rejected it and start fell
back to anchor, which is a TOC offset and not a stream boundary. That explains
the shape of the defect exactly: it strikes regions larger than 1.5 MB, which is
why the three-stream multichannel regions are hit and single-stream ones never
are. 17 of 95 resolving movies took the fallback.

ADV's predecessor trailer at 433 425 776 plus 17 040 B of descriptor and padding
is 433 442 816 -- the -238-packet start measured against the decoder, to the byte.

Dropping the cap: unchanged 78, fixed cleanly 17, changed in any other way ZERO.
In all 17 the only difference is a larger first chunk with every later chunk
byte-identical, which is what a corrected start looks like and what pulling in a
neighbouring asset does not.

Regression test pinned to the RUNNING DECODER's byte_sizes rather than to this
crate's own output. That is the point of it: every internal check passed happily
while a third of a stream was missing, so only an external number could have
caught this class of bug.

sylpheed-formats: 136 tests pass, 0 fail (the one still running at commit time is
an unrelated long mesh test).

Exact clips for the other 16 are not independently verified -- the sweep is
strong but ADV is the only one with a decoder measurement behind it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
formats-pin-2026-08-30
2026-08-30 08:55:47 +00:00
sylph-decoder
fb6095ae3a handoff: tell the port its refusal found a decoder defect, and what is safe to use
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 08:41:38 +00:00
sylph-decoder
3e8235ddbd re: resolve_movie_voice_region starts INSIDE the first stream, 8 of 10 multichannel regions
Found because the port refused to apply my stream assignment and did the
arithmetic instead: the running decoder's three ADV contexts sum to 3 584 000 B
against a resolved region of 3 114 352 -- 15 % too small to hold them. Two spans,
one wrong, and it was the disc side.

The gap is 238 packets exactly (487 424 B), which is what a start offset looks
like; ctx0 declares 632 packets and the resolver's leading chunk has 394.

Verified against the decoder's own byte_sizes, which cannot be fitted to: at
-238 packets to_xma_riffs yields [1294336, 1118208, 1171456], all three exactly.
It is a real boundary and not the end of a sweep -- at -300 the previous asset's
chunks appear while the three ADV sizes stay stable.

Disc-wide: 24 of 24 single-chunk regions start at a boundary; 8 of 10 three-chunk
regions start mid-stream. The defect is specific to the multichannel case.

The audit's per-movie number is an UPPER BOUND, not the clip -- its stopping rule
is the chunk count changing, and to_xma_riffs absorbs a few packets of the
previous asset first (243 reported for ADV against a true 238). Only ADV has
external ground truth.

Consequence: in those 8 movies the leading chunk is a truncated first stream, not
a spurious artefact, and anything measured on it was measured on a fragment --
including this corpus's own chunk-0 level, though the assignment survives because
its ratio test was chosen to be immune to the clipping.

The resolver is NOT patched. Why the predecessor cue's trailer lands 238 packets
into the next asset is unanswered, and a fix guessed from one movie would be
worse than a documented defect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 08:41:22 +00:00
sylph-decoder
8c71520ab8 re: which ADV stream sits where -- settled by level, not by waveform
Completes ask #4. The three chunks were dumped from the resolved voice region
and decoded; the assignment is ctx0 -> FL/FR, ctx1 -> FC with LFE silent,
ctx2 -> BL/BR.

Two instruments failed first and both look like results, so both are recorded.
Envelope correlation with a per-pair lag search returns 0.86-0.95 for EVERY
chunk against EVERY channel, because all six residual channels share the
dialogue's activity timing -- that is an instrument with no resolving power, not
a finding. Sample-level correlation returns about zero, because the chunks do
not start with the movie and the XMA decode's framing offset is unknown.

Level settles it under the same 0.600 gain the bed uses: each stream lands
within 0.5 dB of exactly one residual pair and misses the others by 4-6 dB. The
ratio test is immune to chunk 0 being a clipped tail of ctx0 -- chunk0 - chunk2
is +5.88 dB against FL - BL at +6.18 dB, agreeing to 0.30 dB, where a swap would
be wrong by 11.76 dB.

Structural confirmation: chunk 1 is the only chunk with a digitally silent
channel and LFE is the only output channel with an empty residual (-115.73
dBFS), one to one; and the internal L/R correlations track the residual pairs'
(0.932 vs 0.918, 0.962 vs 0.929).

Worth having on its own: the same 0.600 scales both the movie bed and the voice,
so it is one mixer gain rather than two.

Reach: levels, not waveforms; one boot, one movie; and whether 0.600 is a fixed
constant or a volume setting is still unknown.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 08:32:14 +00:00
sylph-decoder
59f5bf1b59 method: a rule learned from a burn generalises by resemblance, not by mechanism
From the port agent. This file already carries two divisor bugs of the same
shape -- a silent input in a divisor attenuating real signal -- and the lesson
taken from them was 'be suspicious of dividing by N'. Applied to the intro's
three streams it produced a unity sum that the port's own checker rejected at
+2.62 dBFS.

The precedent did not transfer because a BGM bank's two waves are stems of one
signal while the intro's three streams are positions in a field, whose downmix
weights sum to one whatever the assignment. Nothing in 'several streams, one
output' distinguishes those.

The general point: a rule extracted from a burn is indexed by what the burn
looked like rather than by why it happened, so it fires on the next thing with
the same silhouette while feeling well-earned. State the mechanism a past lesson
turned on and check that mechanism is present.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 08:29:01 +00:00
sylph-decoder
232ae0fa9c re: ask #4 answered -- the intro is a 5.1 WMAPro bed at 0.600 plus three streams
ADV.wmv carries ONE audio stream and it is wmapro 5.1, not XMA. Any framing of
the intro's audio as only 'which of three voice streams to ship' was missing the
bed.

Aligned the 148 s capture against that track (envelope r 0.769 against a median
of -0.001, refined to +224 samples, r 0.900) and solved
capture = g x movie + residual per channel.

The gain is 0.600 on every channel -- a uniform -4.44 dB, a mixer setting rather
than a fit artefact. LFE reproduces to -115.73 dBFS, 72 dB down, which is what
rules out codec difference as the explanation for the other residuals. FC is the
exception: the movie explains NOTHING of it (-0.09 dB), and the movie's own FC is
91.6 % silent.

The residual is three signals, not one: a front pair (r 0.918), a rear pair
(r 0.929), and a centre whose partner LFE is empty. The FC residual spans 34 dB
across 100 ms frames -- bursty, not steady noise.

That CONFIRMS the corpus's 5.1 reading, which voice-three-streams-are-concurrent
recorded as not established, and it confirms the specific detail it offered: that
the mono-in-stereo stream is 'a centre paired with a silent LFE'. Measured from
the output with no access to the stream contents.

Also corrects my own census page: it labelled channels with the ALSA permutation
[0,1,4,5,2,3] from the recipe page, which does NOT apply to this capture. The
6x6 matrix was computed assuming no order, every row's max falls on a distinct
movie channel, and the answer is the identity -- so the census's 'BR is 82 %
silent' was really LFE, reconciling with the movie's own 80.64 % silent LFE.

Reach: one boot, one movie; which XMA context is front/centre/rear is not
determined, only that the residual occupies those positions; and whether 0.600 is
a fixed constant or a volume setting is unknown.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 08:19:03 +00:00