port: refute the language-sprite reading of the GP_DIALOG residual

The Decoder recorded a residual as odd rather than understood, with a plausible
untested reading: GP_DIALOG has 140 entries against a 70-record table, adjacent
pairing gives identical element-name sets on only 2 of 65 pairs, and the proposed
explanation was that dialog text is baked into language-specific sprites so EN/JP
entries differ by construction. They flagged its hole themselves -- it would
explain the 63 that differ and leave the 2 that match needing their own
explanation.

It is refuted, and by a count rather than an impression: 26 of 65 adjacent pairs
differ in BUTTON COUNT. Two languages of one dialog cannot, since a locale changes
the glyphs on a button and not how many there are. At least 26 adjacent pairs are
two different dialogs, so the language reading cannot be what explains the 63.

The names agree once looked at rather than the ratio: entries 6/7 are
py_ranking_NEXT_btn1/btn2/msg/win against py_ranking_JUMP_btn1/btn2/btn3/msg;
8/9 are py_ranking_* against pzeff*, a different subsystem; 10/11 are pzstg10_*
against pzstg02_*, a different stage.

It inverts the puzzle rather than solving it. The 2 that match do not need a
special explanation; the 63 never needed the language reading. Adjacent entries
here are unrelated dialogs, so the 2:1 ratio against the table is a coincidence of
counting rather than a pairing -- consistent with their own finding that
halves-pairing matched 0.

Not claimed: that entries 0/1 and 2/3 ARE EN/JP pairs. Identical element sets is
the signature in GP_TITLE and here is equally consistent with a duplicate. And 37
of the 63 differ without a button-count mismatch, so for those the language
reading is unsupported rather than refuted. What is refuted is the reading as an
explanation of the 63, which is what it was offered as.

Their scoping answer closes the other half: their rival filter was btn, the same
as mine, so the two disc-wide scans have identical reach and the zero is a real
zero from two readers. Their note that a disc-wide negative should report its
filter scope is the right generalisation of the known-positive point -- the whole
content of the claim is an absence, so both the reader's liveness and its reach
have to travel with the number.

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-31 02:56:31 +00:00
parent 1c1ab8d57d
commit 42edffa1b5
2 changed files with 118 additions and 1 deletions

View File

@@ -0,0 +1,71 @@
//! Test the Decoder's UNTESTED reading of a residual they recorded as odd.
//!
//! `GP_DIALOG` holds 140 entries against a 70-record dialog table — a 2:1 ratio
//! that would make the id→entry join an ordering question. It does not hold:
//! adjacent pairing gives identical element-name sets on **2 of 65** pairs,
//! halves pairing on **0**. In `GP_TITLE` a language pair shares its element set
//! exactly, so identical sets are the signature there and almost nothing matches
//! here.
//!
//! The residual: the only two adjacent pairs that DO match are entries `0/1` and
//! `2/3` — and `2/3` is the DIFFICULTY build. Their plausible reading is that
//! dialog text is baked into language-specific sprites, so EN/JP entries differ
//! by construction. ⚠️ **They flagged it as untested and did not assert it**, and
//! it has a hole they named themselves: it would explain the 63 that differ and
//! leave the 2 that match needing their own explanation.
//!
//! This prints what the differences actually look like, so the reading is judged
//! against the names rather than accepted as plausible.
use sylpheed_formats::{pak, ratc, ui_layout};
use std::collections::BTreeSet;
fn main() {
let root = std::env::var("SYLPHEED_DISC").unwrap_or_else(|_| "/disc".into());
let ar = pak::PakArchive::open(format!("{root}/dat/GP_DIALOG.pak")).expect("GP_DIALOG.pak");
let sets: Vec<Option<BTreeSet<String>>> = ar.entries().iter().map(|e| {
let by = ar.read(e).ok()?;
if !ratc::is_ratc(&by) { return None }
let b = ui_layout::parse_build(&by)?;
Some(b.elements.iter().map(|el| el.name.clone()).collect())
}).collect();
let (mut same, mut diff, mut pairs) = (0usize, 0usize, 0usize);
let mut shown = 0;
for i in (0..sets.len().saturating_sub(1)).step_by(2) {
let (Some(a), Some(b)) = (&sets[i], &sets[i + 1]) else { continue };
pairs += 1;
if a == b {
same += 1;
println!(" entries {i:>3}/{:<3} IDENTICAL sets, {} element(s)", i + 1, a.len());
continue;
}
diff += 1;
if shown < 3 {
shown += 1;
let only_a: Vec<_> = a.difference(b).cloned().collect();
let only_b: Vec<_> = b.difference(a).cloned().collect();
println!(" entries {i:>3}/{:<3} differ: {} only-in-first, {} only-in-second",
i + 1, only_a.len(), only_b.len());
println!(" first : {:?}", &only_a[..only_a.len().min(4)]);
println!(" second : {:?}", &only_b[..only_b.len().min(4)]);
}
}
// 🔴 THE DECISIVE DETAIL, not the impressionistic one. Two languages of one
// dialog cannot differ in BUTTON COUNT. If adjacent entries do, they are
// different dialogs and the whole adjacent-pairing premise is wrong -- which
// is a stronger statement than "the language reading is untested".
let btns = |s: &Option<BTreeSet<String>>| -> usize {
s.as_ref().map_or(0, |x| x.iter().filter(|n| n.contains("btn")).count())
};
let mut mismatched = 0;
for i in (0..sets.len().saturating_sub(1)).step_by(2) {
if sets[i].is_none() || sets[i + 1].is_none() { continue }
if btns(&sets[i]) != btns(&sets[i + 1]) { mismatched += 1 }
}
println!("\n adjacent pairs whose BUTTON COUNTS differ: {mismatched}");
println!(" A language pair cannot. Every one of these is two different dialogs.");
println!("\n {pairs} adjacent pair(s): {same} identical, {diff} differing");
println!(" Their reading -- text baked into language-specific sprites -- predicts");
println!(" the differing names look SYSTEMATIC (a locale suffix, a parallel set).");
println!(" Judge it against the names above rather than against its plausibility.");
}

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 -->
288 sections. Search this before re-deriving anything.
289 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)
@@ -299,6 +299,7 @@ dies, which is what this file is for.
* [DIFFICULTY is a dialog, and the count-match it weakens was one I had recorded](#difficulty-is-a-dialog-and-the-count-match-it-weakens-was-one-i-had-recorded)
* [Their note about instruments applies to me more than to them](#their-note-about-instruments-applies-to-me-more-than-to-them)
* [The reach I recorded as theirs closed, and re-running it with a broader filter held](#the-reach-i-recorded-as-theirs-closed-and-re-running-it-with-a-broader-filter-held)
* [Refuted: their language-sprite reading of the `GP_DIALOG` residual](#refuted-their-language-sprite-reading-of-the-gp_dialog-residual)
<!-- /INDEX -->
## P0 — the exporter, 2026-08-28
@@ -14437,3 +14438,48 @@ agreed."*
produced the scan.** Agreement would have ended it; so would a challenge to the
whole claim. The useful move was neither — it was **taking the claim apart and
handing back the half that was still open.**
## Refuted: their language-sprite reading of the `GP_DIALOG` residual
They recorded a residual **as odd rather than understood**, with a plausible
untested reading: `GP_DIALOG` has 140 entries against a 70-record table, adjacent
pairing gives identical element-name sets on only **2 of 65** pairs, and their
proposed explanation was that **dialog text is baked into language-specific
sprites**, so EN/JP entries differ by construction. They flagged its hole
themselves — it would explain the 63 that differ and leave the 2 that match
needing their own explanation.
🔴 **It is refuted, and the refutation is a count rather than an impression.**
**26 of 65 adjacent pairs differ in BUTTON COUNT.** Two languages of one dialog
cannot: a locale changes the glyphs on a button, not how many there are. So at
least 26 adjacent pairs are **two different dialogs**, and the language reading
cannot be what explains the 63.
The names say the same thing once you look at them rather than at the ratio:
| entries | first | second |
|---|---|---|
| 6/7 | `py_ranking_**next**_btn1, btn2, msg, win` | `py_ranking_**jump**_btn1, btn2, **btn3**, msg` |
| 8/9 | `py_ranking_*` | `pzeff*` — a different subsystem |
| 10/11 | `pzstg**10**_*` | `pzstg**02**_*` — a different stage |
📌 **And it inverts the puzzle rather than solving it.** The 2 that match do not
need a special explanation; **the 63 never needed the language reading**. Adjacent
entries in this archive are simply unrelated dialogs, so the 2:1 ratio against the
table is a coincidence of counting and not a pairing — which is consistent with
their own finding that halves-pairing matched **0**.
⚠️ **What I am not claiming.** That entries `0/1` and `2/3` *are* EN/JP pairs is
**not** established by this scan. Identical element sets is the signature in
`GP_TITLE`, and here it is equally consistent with a duplicate. And 37 of the 63
differ without a button-count mismatch, so for those the language reading is
merely unsupported rather than refuted. **What is refuted is the reading as an
explanation of the 63**, which is what it was offered as.
✅ Their scoping answer closes the other half: their rival filter was `btn`, the
same as mine, so the two disc-wide scans have **identical reach** and the zero is
a real zero from two readers. Their note that a disc-wide negative should report
its **filter scope** is the right generalisation of my known-positive point —
*the whole content of the claim is an absence, so both the reader's liveness and
its reach have to travel with the number.*