From 3e4dd3ca7216b49735802033c9fc37cfd07de3b6 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Thu, 27 Aug 2026 04:52:05 +0000 Subject: [PATCH] re: diff the legacy IDXD reader against the field table -- 17.54% wrong, with an exact predicate Answers the backlog's open "first step: diff the two readers across the disc and count disagreements", statically over every IDXD object. Of 7750 objects and 738922 named fields whose true value is numeric, legacy get_f32 is correct 39.42%, returns None (harmless) 43.04%, and returns a WRONG NUMBER 17.54% (129612 fields). The wrongness has an exact predicate: single-record objects 0 of 29822 wrong (0.00%); multi-record objects 129612 of 709100 (18.28%). The mechanism is in get_raw itself -- it flattens the pool to a token list, finds the FIRST occurrence of the key, and returns the preceding token, with no notion of records. So every record after the first inherits record 0's value: Weight truth=1.0 legacy=0.3, Points truth=10000 legacy=4000. Practical rule recorded: a get_f32 number from a single-record object is safe; from a multi-record object only the first record is. Withdrawn in the same document: my first sweep compared against "the string before THIS field's own key" and reported 65.90% -- that is not what get_raw does, so the figure is not the legacy reader's error rate. --- docs/re/BACKLOG.md | 7 ++++ docs/re/idxd-legacy-reader-diff.md | 63 ++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 docs/re/idxd-legacy-reader-diff.md diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index bb348b52..2823cc93 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -1559,6 +1559,13 @@ premise was wrong.** of `get_f32`/`get_raw` is re-checkable against ground truth but **not yet re-checked**. First step: diff the two readers across the disc and count disagreements. Also open: recover the 504 unnamed hash keys. + ✅ **(2026-08-27) DIFFED — see [idxd-legacy-reader-diff](idxd-legacy-reader-diff.md).** + Over 7 750 objects and 738 922 numerically-valued named fields, legacy + `get_f32` is correct 39.42 %, safely `None` 43.04 %, and **returns a wrong + number 17.54 %**. The error has an exact predicate: **0 of 29 822** fields wrong + in single-record objects, 18.28 % wrong in multi-record ones — because + `get_raw` finds the *first* occurrence of the key in a flat token list and has + no notion of records, so every record after the first inherits record 0's value. * ✅ **(2026-08-25) Both guest hash routines located** — `sub_82447DF0` (IDXD) and `sub_82447E70` (IXUD), transcribed instruction-for-instruction into Python and Rust; `cargo test -p sylpheed-formats --lib hash` 10/10. **IXUD SOLVED:** diff --git a/docs/re/idxd-legacy-reader-diff.md b/docs/re/idxd-legacy-reader-diff.md new file mode 100644 index 00000000..30e5c761 --- /dev/null +++ b/docs/re/idxd-legacy-reader-diff.md @@ -0,0 +1,63 @@ +# ✅ How wrong the legacy IDXD reader is — measured disc-wide + +[`BACKLOG.md`](BACKLOG.md) left this open: *"the legacy value-before-key +string-pool reader is an approximation … every number in this corpus that came +out of `get_f32`/`get_raw` is re-checkable against ground truth but not yet +re-checked. **First step: diff the two readers across the disc and count +disagreements.**"* Done, statically, over every IDXD object on the disc. + +## The answer + +**7 750 IDXD objects, 738 922 named fields whose true value is numeric:** + +| legacy `get_f32` outcome | fields | share | +|---|---|---| +| correct | 291 307 | 39.42 % | +| returns `None` — no number produced, so harmless | 318 003 | 43.04 % | +| **returns a WRONG NUMBER** | **129 612** | **17.54 %** | + +## ✅ And the wrongness has an exact predicate + +| object shape | numeric fields | wrong numbers | +|---|---|---| +| **single-record** | 29 822 | **0 — 0.00 %** | +| **multi-record** | 709 100 | 129 612 — 18.28 % | + +**The legacy reader is exactly correct on single-record objects and unsafe on +multi-record ones.** Not approximately — *zero* disagreements in 29 822 fields. + +The mechanism is in `get_raw`'s own implementation: it flattens the string pool +to a token list, finds the **first** occurrence of the key, and returns the token +before it. It has no notion of records. So in an object with N records that each +carry a `Weight`, every record's `Weight` resolves to **record 0's** value: + +``` +Weight truth=1.0 legacy=0.3 +Points truth=10000 legacy=4000 +Weight truth=3.3 legacy=0.3 +Points truth=15000 legacy=4000 +``` + +`0.3` and `4000` are record 0's values, returned for every record after it. + +## What this means for the corpus + +* A number read with `get_f32` from a **single-record** object is safe — the diff + found no counterexample in 29 822 fields. +* A number read from a **multi-record** object is safe only for the **first** + record; every later record has a ~18 % chance of being record 0's value. +* The `None` bucket (43 %) is the guard working as designed: `get_f32` rejects a + non-numeric neighbour rather than inventing a value, so a *defaulted* field + reads as absent instead of wrong. + +## ⚠️ A first pass that measured the wrong thing + +My first sweep compared the truth against *"the string immediately preceding this +field's own key in the pool"* and reported **65.90 %** disagreement. That number +is not the legacy reader's error rate, because it is not what `get_raw` does — +`get_raw` uses the **first occurrence of the key anywhere in the object**, not +this field's own key. The 65.90 % figure is withdrawn; 17.54 % is the measured +one, and the `is_definite_value` guard is why it is so much lower. + +The lesson is the same one this corpus keeps paying for: before measuring how +wrong a tool is, read what the tool actually does.