diff --git a/authored/audio.json b/authored/audio.json index df8aca33..82b17f59 100644 --- a/authored/audio.json +++ b/authored/audio.json @@ -102,7 +102,7 @@ "bank": "BGM_103.slb", "loop": "restart", "kind": "measured", - "why": "MEASURED, HANDOFF Q10 -- NOT a port choice. `GamePart_Title`'s phase handler `sub_821C5580` plays cue 1103 = `BGM_103`, and `BGM_103.slb`'s two declared waves (3 876 864 / 3 930 112 B) are byte-for-byte the two streams the XMA probe saw decoding at the main menu. Static code, disc census and runtime all agree; see docs/re/menu-audio-cues.md and docs/re/structures/bgm-two-stems.md. The name carries its `.slb` extension because that is what `sound.pak` hashes -- `BGM_103` alone resolves to nothing, which is how the first draft of this file failed. ✅ AUDITED 2026-08-31 -- the THREE legs are three, and that is now measured rather than asserted. Prompted by the Decoder's point that a decorative second support is worse than none, since a conclusion with two supports reads as better evidenced than one and apparent redundancy is itself the misinformation. Read literally, 'disc census' and 'runtime' could be ONE comparison -- declared wave sizes matched byte-for-byte against the probe -- which would make three legs two. It is a real third leg only if the census EXCLUDES alternatives: if another bank carried the same two sizes, the byte match would not distinguish BGM_103. Measured with this port's own reader (`crates/sylpheed-export/examples/bgm_size_census.rs`): of 32 readable BGM_* banks on the disc, EXACTLY ONE carries waves of that size. The census therefore excludes, the static-code leg names the cue independently, and the three legs stand.", + "why": "MEASURED, HANDOFF Q10 -- NOT a port choice. `GamePart_Title`'s phase handler `sub_821C5580` plays cue 1103 = `BGM_103`, and `BGM_103.slb`'s two declared waves (3 876 864 / 3 930 112 B) are byte-for-byte the two streams the XMA probe saw decoding at the main menu. Static code, disc census and runtime all agree; see docs/re/menu-audio-cues.md and docs/re/structures/bgm-two-stems.md. The name carries its `.slb` extension because that is what `sound.pak` hashes -- `BGM_103` alone resolves to nothing, which is how the first draft of this file failed. ✅ AUDITED 2026-08-31 -- the THREE legs are three, and that is now measured rather than asserted. Prompted by the Decoder's point that a decorative second support is worse than none, since a conclusion with two supports reads as better evidenced than one and apparent redundancy is itself the misinformation. Read literally, 'disc census' and 'runtime' could be ONE comparison -- declared wave sizes matched byte-for-byte against the probe -- which would make three legs two. It is a real third leg only if the census EXCLUDES alternatives: if another bank carried the same two sizes, the byte match would not distinguish BGM_103. Measured with this port's own reader (`crates/sylpheed-export/examples/bgm_size_census.rs`): of 32 readable BGM_* banks on the disc, EXACTLY ONE carries waves of that size. The census therefore excludes, the static-code leg names the cue independently, and the three legs stand. ✅ AND THE EXCLUSION IS TIGHTER THAN I STATED. The Decoder attempted to refute it from their own census tool rather than this port's reader: of 32 census rows, exactly one bank carries EITHER of those wave sizes -- not merely both together, which is what I measured. A collision would therefore need to reproduce a single size, not a pair, and none does.", "loop_why": "MEASURED, and this field's own history is why it says so first. The bed loops; the loop is a RUNTIME field -- `loop_start`/`loop_end` in the XMA decoder context, set by `XMASetLoopData` and logged by Xenia -- and the cycle was watched directly: three wraps, both contexts wrapping at the same instant every time, mean 61.81 s against the 61.93 s authored in `loop_end_s`, 0.2 % apart from instruments sharing nothing. The export is TRIMMED to that window, because Godot loops a whole file and a loop region therefore has to BE the file. ⚠️ The window's START is not measured and is authored as 0, which is known to be wrong -- see `loop_start_why`. 🔴 EVERY SENTENCE THAT PRECEDED THIS ONE WAS REFUTED, and the previous text survived in the manifest for two days after the corrections were written. It said the loop would be `AUDIBLY WRONG AT THE SEAM [refuted]`, that `no loop-point field has been identified [refuted] anywhere`, and that trimming `would INVENT a loop point`. All three are false: the field exists, the 3.4 s of near-silence was the PORT'S loop and not the game's, and the trim is now what the measurement says. The corrections went into `loop_end_why` and `loop_start_why`; this field is the one the exporter concatenates into `manifest.json`, so the export went on telling readers the refuted story. A correction that does not reach the artifact a consumer reads has not been made.", "stems": "sum", "stems_why": "MEASURED, HANDOFF Q10: a bank is exactly TWO waves of identical duration (32/32 banks on the disc), sample-synchronous -- transient correlation peaks at lag 0.00 s over +/-5 s and both stop at the same millisecond. Concatenating them plays the piece twice, the second time as a bass-less stem; that was the previous reading and it is refuted. Emitting two files would be wrong for a second reason: MODDING rule 1 is one logical asset, one file, and handing a modder two stems to line up by hand is the reassembly the exporter exists to have already done. WHAT IS SUMMED IS SETTLED; WHAT WAVE 1 IS, IS NOT -- HANDOFF calls it quieter, far more L/R-decorrelated and almost bass-free, so it reads as a surround-rear pair OR a second intensity layer, and `ChannelMask` is 0x0002 on both so the file will not say. A unity sum is right under either reading; a weighting would only be justified once that is settled.", diff --git a/authored/flow.json b/authored/flow.json index 7a01eb25..96b48732 100644 --- a/authored/flow.json +++ b/authored/flow.json @@ -511,7 +511,19 @@ " (was) 🔴 If EXTRAS turns out to persist, this becomes history and the kind must", " (was) change with it.", "", - "✅ CHECKED AGAINST THE BYTES 2026-08-31 by both agents -- and \"independently\"", + "🔴 CHECKED AGAINST THE BYTES 2026-08-31 by both agents -- and NOT independently.", + "Settled by fact, not by my inference: the Decoder's 282/362/442 came from", + "`crates/sylpheed-formats/examples/extras_button_order.rs`, which calls", + "`ui_layout::parse_build` -- THE SAME CRATE this port's export uses. The", + "Python RATC parsers in their tree exist and did not produce that number.", + "So the two legs are ONE READER USED TWICE, and the agreement carries no", + "information about the reader being right; it carries information only about", + "two callers of it agreeing, which they could not fail to do.", + "", + "⚠️ The VALUE is unaffected -- `ptbtn11` is decided by the DIFFICULTY", + "measurement and by the reset finding. What died is a word I used about the", + "evidence, which is the third such word in three iterations.", + "", "is WEAKENED, by my own audit rather than by theirs.", "", "Applying their test to my own sentence: could my reading have come out", diff --git a/docs/port/DECISIONS.md b/docs/port/DECISIONS.md index f9f17cd6..44afb375 100644 --- a/docs/port/DECISIONS.md +++ b/docs/port/DECISIONS.md @@ -9,7 +9,7 @@ dies, which is what this file is for. -296 sections. Search this before re-deriving anything. +298 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) @@ -307,6 +307,8 @@ dies, which is what this file is for. * [Naming an untested bound is what got it tested](#naming-an-untested-bound-is-what-got-it-tested) * [Auditing my own multi-leg claims: the one that mattered holds, and now says why](#auditing-my-own-multi-leg-claims-the-one-that-mattered-holds-and-now-says-why) * [Closing one of my own, and a second relayed count from the same delivery](#closing-one-of-my-own-and-a-second-relayed-count-from-the-same-delivery) +* [The oracle capture's own focus state was never established — now it is, by exclusion](#the-oracle-captures-own-focus-state-was-never-established--now-it-is-by-exclusion) +* ["Independently" dies on a fact, and I decline to re-add the pairing they restored](#independently-dies-on-a-fact-and-i-decline-to-re-add-the-pairing-they-restored) ## P0 — the exporter, 2026-08-28 @@ -14727,3 +14729,88 @@ count until they looked. **272** leg-count claims in their corpus against my six, and each of us has audited **one**. *"Most are probably fine, which is exactly why nobody will check them."* + +## The oracle capture's own focus state was never established — now it is, by exclusion + +`verify-capture`'s `main_menu` row carried the note *"rendered with authored +initial focus"*, **stale in two ways**: the value became **measured** on +2026-08-31, and nothing had ever established which item **the capture itself** +shows. That second gap sat under the port's most-quoted residual. + +Rendering all five candidates against `live-main-menu.png`: + +| focus | RMSE | +|---|---| +| **ptbtn01 — NEW GAME** | **13.06** | +| ptbtn02 | 16.23 | +| ptbtn03 | 15.96 | +| ptbtn04 | 16.59 | +| ptbtn05 | 16.01 | + +✅ **The capture shows NEW GAME, and every alternative is ~22 % worse.** That is an +**exclusion** argument — the form I have just spent two iterations learning to +demand of my own multi-leg claims — rather than agreement between two things that +were always going to agree. + +📌 **So the 13.06 residual is not a focus mismatch.** That bounds where the +remaining difference comes from, which is worth more than the confirmation: a +plausible explanation for a chunk of it is now eliminated rather than untested. + +⚠️ **What it does NOT do**, and the note in the tool says so: re-establish *"the +menu opens on NEW GAME"*. **Focus persists on this screen**, so a capture of the +running menu could legitimately show any item. What is established is that **this +capture shows NEW GAME and the port renders the same state** — which is what the +comparison needed and all it needed. + +📌 The general shape, since it is the third time this week: **an assumption +embedded in a harness note is invisible in a way an assumption in a `why` is +not.** `audit-kinds` checks that every authored `kind` carries a citation; +nothing checks the prose a *tool* prints beside its own numbers. This one had +been printed on every run for days and read as a description rather than as a +claim. + +## "Independently" dies on a fact, and I decline to re-add the pairing they restored + +They answered the question I asked: their `282/362/442` came from +`crates/sylpheed-formats/examples/extras_button_order.rs`, which calls +`ui_layout::parse_build` — **the same crate this port's export uses**. The Python +RATC parsers in their tree exist and **did not produce that number**. + +🔴 **So the two legs are one reader used twice.** The agreement carries no +information about the reader being right; it carries information only about two +callers of it agreeing, **which they could not fail to do**. Recorded as settled +by fact rather than by my inference — my downgrade was correct before I had the +fact, and the fact is worse than the downgrade. + +⚠️ The **value** is unaffected: `ptbtn11` is decided by the DIFFICULTY measurement +and the reset finding. **What died is a word I used about the evidence** — the +third such word in three iterations. + +### 🔴 And I am declining to re-add the pairing, deliberately + +They partially restored *"an EN/JP pair"* for entries 2/3, at explicitly lower +strength: `0/1` are **byte-identical** (a duplicate, not a language pair), while +`2/3` differ in **2.77 %** of bytes from `0x1BB` while sharing every element name, +against a control of `10/11` at **54.90 %**. **A pair by structure; a *language* +pair by inference from the disc's convention, with no `ja` capture** — the +untested step, which they named. + +**I am not putting it back.** Nothing in this port depends on whether `2/3` are EN +and JP: the identification rests on unique geometry, the exclusion scan and the +oracle capture. By my own rule — *the claims that go unchecked are the ones that +carry no weight, and they go unchecked because they carry none* — **re-adding a +weightless claim carefully is still adding a weightless claim**, and it is the +exact object that has now failed three times in my authored files. + +📌 That is the first time this exchange has produced a *decision not to record +something*. Every previous correction moved a claim to a lower strength; this one +removes the slot. + +### Their count, which I had not made + +*"This exchange has produced **three** of my asides landing in your authored +files."* `an EN/JP pair`, `three routes`, `both agents independently`. **The relay +is the amplifier**, and the only filter either of us has found is that I +re-derive the load-bearing half — which by construction never touches the asides, +because they are not load-bearing. **The filter and the failure select for exactly +the same property.** diff --git a/tools/port/verify-capture b/tools/port/verify-capture index 3d11a038..806cd8cc 100755 --- a/tools/port/verify-capture +++ b/tools/port/verify-capture @@ -266,7 +266,18 @@ for row in "${MAP[@]}"; do case "$name" in title) note="settle t=198; +/-5.56 capture-phase term -- regression only" ;; title_jp) note="+/-5.6 capture-phase term (same leaves as build 4)" ;; - main_menu) note="rendered with authored initial focus; +/-3.78 capture-phase term" ;; + # 🔴 The old note said "rendered with AUTHORED initial focus", and it was + # stale twice over. The value became MEASURED on 2026-08-31 (NEW GAME, 2/2 + # fresh boots, first entry) -- and the capture's OWN focus state, which had + # never been established, is now identified by exclusion: rendering all five + # candidates against this capture gives ptbtn01 13.06 and every alternative + # 15.96-16.59, ~22 % worse. So the residual below is NOT a focus mismatch. + # + # ⚠️ It does not re-establish "the menu opens on NEW GAME". Focus persists on + # this screen, so a capture of the running menu could show any item; what is + # established is that THIS capture shows NEW GAME and the port renders the + # same state. + main_menu) note="focus ptbtn01 confirmed by exclusion (next best +22%); +/-3.78 capture-phase term" ;; extras) note="rendered with authored initial focus; +/-3.73 capture-phase term" ;; publisher_logo|developer_logos) note="no free-running element -- absolute, means what it says" ;; esac