retro: the Decoder side, and the integrity check it forced
The human asked both agents for a critical retro; it reached me relayed through
sylpheed-port, and I am treating it as a message rather than as their word while
staying paused on RE iterations.
Worst failure first: I READ the refutation that mattered and routed around it
instead of auditing it. REFUTED.md killed the blend bit with our own renderer as
its instrument, and I quoted the 'a claim resting on our renderer is a claim
about our renderer' rule at the port in the same session while not applying it to
my own register.
Underneath it is the sharper one: I twice accepted render-derived labels for a
disc-side question. My 'no field separates them' negative was tested against a
partition that was wrong in six places, all six of which the oracle later called
additive.
Also recorded: the silent vertex truncation, a coverage claim written rather than
computed and wrong by four, a batching generalisation refuted by the log it was
written from, and navigation whose fix was worse than the bug.
Two additions to the port's list of shared costs: neither of us has ever given a
negative a positive control, so 'absent' and 'my search does not work' are
indistinguishable in every undecodable page I have written; and we keep
attributing a three-way residual to whichever leg we happen to be looking at.
Their eight proposals attacked one by one -- P2 sharpened into a
re-classification rather than bookkeeping, P5 pushed back on ('suppression
localises disagreement; only the oracle labels it'), the rest agreed with
amendments.
And the check the retro forced: my rival sweep covered the T8aD header and not
the 60-byte declaration entry, whose earlier hunt used the corrupted labels. Swept
properly, 16 of the 35 measured elements have no declaration entry at all and 0
declaration bits separate the other 19. The decode is not underdetermined -- run
because it could have gone the other way.
The PROTOCOL delta is presented, not applied.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
@@ -62,6 +62,7 @@ const MEASURED: &[(usize, &str, bool)] = &[
|
||||
];
|
||||
|
||||
fn main() {
|
||||
if std::env::args().any(|a| a == "decl") { decl_rivals(); return }
|
||||
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
|
||||
let ar = PakArchive::open(root.join("dat/GP_TITLE.pak")).expect("GP_TITLE");
|
||||
let mut hdr: BTreeMap<(usize, String), u32> = BTreeMap::new();
|
||||
@@ -150,3 +151,70 @@ fn main() {
|
||||
println!(" -> the sample does NOT single out a field; {} candidates tie.", rivals.len());
|
||||
}
|
||||
}
|
||||
|
||||
// ── An integrity check the published decode did NOT do ──────────────────────
|
||||
// The rival sweep above covers the 48-byte T8aD header. It does NOT cover the
|
||||
// 60-byte DECLARATION entry, and the earlier declaration hunt was run with
|
||||
// labels taken from the port's RENDER -- which put pteff10, pteff12, pteff20 and
|
||||
// pteff21..23 on the alpha-over side, where the oracle says all six are
|
||||
// additive. So the declaration has never been swept with correct labels, and if
|
||||
// one of its words also partitions the 35 without error, "the field is the T8aD
|
||||
// bit" is underdetermined.
|
||||
//
|
||||
// Run as: cargo run -p sylpheed-formats --example blend_vs_t8ad_bit -- decl
|
||||
#[allow(dead_code)]
|
||||
fn decl_rivals() {
|
||||
use std::collections::BTreeMap;
|
||||
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
|
||||
let ar = PakArchive::open(root.join("dat/GP_TITLE.pak")).expect("GP_TITLE");
|
||||
const AT: usize = 0x20;
|
||||
const STRIDE: usize = 60;
|
||||
let mut decl: BTreeMap<(usize, String), Vec<u32>> = BTreeMap::new();
|
||||
for e in [2usize, 4, 5, 6] {
|
||||
let Ok(by) = ar.read(&ar.entries()[e]) else { continue };
|
||||
if by.len() < 0x18 { continue }
|
||||
let count = u32::from_be_bytes([by[0x14], by[0x15], by[0x16], by[0x17]]) as usize;
|
||||
for i in 0..count {
|
||||
let at = AT + i * STRIDE;
|
||||
if at + STRIDE > by.len() { break }
|
||||
let end = by[at..at + 12].iter().position(|&c| c == 0).unwrap_or(12);
|
||||
let name = String::from_utf8_lossy(&by[at..at + end]).to_string();
|
||||
decl.insert((e, name), (0..15)
|
||||
.map(|k| u32::from_be_bytes([by[at+k*4], by[at+k*4+1], by[at+k*4+2], by[at+k*4+3]]))
|
||||
.collect());
|
||||
}
|
||||
}
|
||||
let mut missing: Vec<String> = Vec::new();
|
||||
for &(e, n, _) in MEASURED {
|
||||
if !decl.contains_key(&(e, n.to_string())) {
|
||||
missing.push(format!("entry {e} {n}"));
|
||||
}
|
||||
}
|
||||
println!("\n=== DECLARATION-ENTRY RIVAL SWEEP ===");
|
||||
println!("measured elements with NO declaration entry of their own: {} of {}",
|
||||
missing.len(), MEASURED.len());
|
||||
for m in &missing { println!(" {m}"); }
|
||||
if !missing.is_empty() {
|
||||
println!(" -> no declaration field can select the blend for these, because they");
|
||||
println!(" have no declaration entry. The header is the only per-sprite home.");
|
||||
}
|
||||
let labelled: Vec<&(usize, &str, bool)> = MEASURED.iter()
|
||||
.filter(|(e, n, _)| decl.contains_key(&(*e, n.to_string()))).collect();
|
||||
let mut rivals = 0;
|
||||
for w in 0..15 {
|
||||
for bit in 0..32 {
|
||||
let (mut ok, mut s, mut c) = (true, false, false);
|
||||
for &&(e, n, additive) in &labelled {
|
||||
let on = (decl[&(e, n.to_string())][w] >> bit) & 1 == 1;
|
||||
if on { s = true } else { c = true }
|
||||
if on != additive { ok = false; break }
|
||||
}
|
||||
if ok && s && c {
|
||||
println!(" RIVAL: declaration +0x{:02X} bit {bit}", w * 4);
|
||||
rivals += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("declaration bits that separate the {} labellable elements: {rivals}",
|
||||
labelled.len());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user