re: count the in-range fallbacks -- and the control that failed is the answer
sylpheed-port pointed out that classifying defaults "by inspection" is exactly
the method that cannot see an in-range fallback, and that correction applies to
my own sweep from an hour ago: I waved 64 sites through by reading them.
Counted instead, disc-wide over 965 builds and 24 811 keyframes:
ui_layout.rs:1681 untimed poses (would fabricate t=0): 0
ui_layout.rs:1010 pose_at queries 168 264, None (reads a=0): 0
Two zeroes, which is the result this corpus now distrusts most, so the detector
was made to prove it can see a hit: ask pose_at for a time no build declares.
The control FAILED -- 10 906 out-of-range queries, 0 None -- so the detector was
blind and the :1010 zero measured nothing.
The failure is the finding. pose_at is TOTAL: reading the source, its only None
path is an `if ks.is_empty() { return None }` guard, and disc-wide there are 0
elements with zero keyframes out of 5 453. So :1010's unwrap_or(0) is unreachable
BY CONSTRUCTION, which is stronger than "0 in this corpus" -- and it was
established by the control failing rather than by the count passing. Without the
control this corpus would have recorded a true conclusion resting on a
meaningless number.
:1681 stands differently: 0 of 24 811, and time really is Option<u32> with the
stale reader demonstrably producing None (its screen info prints a trailing -),
so the state is representable and a detector would see it. :973 is not a hazard
-- guarded two lines later by `if tmax == 0 { return false; }`, where reading is
sufficient because the guard is the proof.
METHOD gains both: a zero is worth nothing until the detector is shown able to
report non-zero; and the habit under several of this week's errors, which is
reading a PROXY for the thing when the thing itself is one command away -- a line
count for an era, a type name's spelling for its default, an ordinal for an
entry, a fallback's text for its firing rate.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
86
crates/sylpheed-formats/examples/inrange_fallback_count.rs
Normal file
86
crates/sylpheed-formats/examples/inrange_fallback_count.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
//! Do `ui_layout`'s two IN-RANGE fallbacks ever fire? Counted, disc-wide.
|
||||
//!
|
||||
//! An in-range fallback supplies a value that is legitimate, so no output can
|
||||
//! distinguish it from the real thing and inspection cannot settle it. The only
|
||||
//! question that has an answer is *how often does it fire*.
|
||||
//!
|
||||
//! ui_layout.rs:1681 kf.time.unwrap_or(0) -- 0 is a real keyframe time
|
||||
//! (pose 0's time IS 0), so a fabricated one is invisible.
|
||||
//! ui_layout.rs:1010 pose_at(t).map(|k| k.fade >> 24).unwrap_or(0) > 0
|
||||
//! -- alpha 0 is legitimate, and it makes "no pose here"
|
||||
//! read as "fully transparent", biasing an occlusion test
|
||||
//! toward NOT occluded.
|
||||
//!
|
||||
//! (ui_layout.rs:973's `unwrap_or(0)` is NOT counted: it is guarded two lines
|
||||
//! later by `if tmax == 0 { return false; }`, so 0 is handled, not assumed.)
|
||||
//!
|
||||
//! cargo run -p sylpheed-formats --example inrange_fallback_count
|
||||
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
|
||||
let mut paks: Vec<PathBuf> = std::fs::read_dir(root.join("dat")).expect("dat/")
|
||||
.filter_map(|e| e.ok().map(|e| e.path()))
|
||||
.filter(|p| p.extension().is_some_and(|x| x == "pak")).collect();
|
||||
paks.sort();
|
||||
let (mut kf, mut untimed, mut builds) = (0u64, 0u64, 0u64);
|
||||
let (mut queries, mut none_at) = (0u64, 0u64);
|
||||
for pak in &paks {
|
||||
let Ok(ar) = PakArchive::open(pak) else { continue };
|
||||
for e in ar.entries() {
|
||||
let Ok(by) = ar.read(e) else { continue };
|
||||
if !ui_layout::is_build(&by) { continue }
|
||||
let Some(b) = ui_layout::parse_build(&by) else { continue };
|
||||
builds += 1;
|
||||
// (a) :1681 -- how many poses carry no time?
|
||||
for el in &b.elements {
|
||||
for k in &el.keyframes {
|
||||
kf += 1;
|
||||
if k.time.is_none() { untimed += 1 }
|
||||
}
|
||||
}
|
||||
// (b) :1010 -- ask every element for a pose at every time that any
|
||||
// element declares, which is the set the occlusion test draws from.
|
||||
let mut times: Vec<u32> = b.elements.iter()
|
||||
.flat_map(|e| e.keyframes.iter().filter_map(|k| k.time)).collect();
|
||||
times.sort_unstable(); times.dedup();
|
||||
for el in &b.elements {
|
||||
for &t in × {
|
||||
queries += 1;
|
||||
if el.pose_at(t).is_none() { none_at += 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
print!("."); std::io::stdout().flush().ok();
|
||||
}
|
||||
println!();
|
||||
println!("{builds} builds, {kf} keyframes");
|
||||
println!(":1681 untimed poses (the fallback would fabricate t=0): {untimed}");
|
||||
println!(":1010 pose_at queries {queries}, of which None (fallback reads a=0): {none_at}");
|
||||
// NEGATIVE CONTROL. Both counters above report 0, and a zero is the result
|
||||
// this corpus has learned to distrust most -- it reads clean rather than
|
||||
// suspicious. So prove the detector CAN see a hit: ask every element for a
|
||||
// pose at a time no build declares. If pose_at is total, `none_out` is 0 too
|
||||
// and the 0 above means nothing.
|
||||
let mut out_queries = 0u64;
|
||||
let mut none_out = 0u64;
|
||||
for pak in &paks {
|
||||
let Ok(ar) = PakArchive::open(pak) else { continue };
|
||||
for e in ar.entries() {
|
||||
let Ok(by) = ar.read(e) else { continue };
|
||||
if !ui_layout::is_build(&by) { continue }
|
||||
let Some(b) = ui_layout::parse_build(&by) else { continue };
|
||||
for el in &b.elements {
|
||||
for &t in &[u32::MAX, 1_000_000u32] {
|
||||
out_queries += 1;
|
||||
if el.pose_at(t).is_none() { none_out += 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("CONTROL pose_at at an undeclared time: {out_queries} queries, {none_out} None");
|
||||
println!(" (if this is 0 the detector is blind and the 0 above is meaningless)");
|
||||
println!("--- END ---");
|
||||
}
|
||||
Reference in New Issue
Block a user