From 8ccc3ddda45241307e12b5fd1138ce9663676bcb Mon Sep 17 00:00:00 2001 From: ReaperOfVeriod Date: Tue, 13 Oct 2026 08:18:20 +0200 Subject: [PATCH] Retract the uniformity claim everywhere it still stood, including the API docs The record-length retraction had been applied to the tests and to the section that discovered the problem, but the same claim was still standing in four other places -- including the rustdoc for has_uniform_record_length(), which is what a caller would actually read: crates/gc-formats/src/chunks.rs:206 "Measured: true for 1,509 of 1,509 chunks" docs/roadmap.md:448 "uniform record length (1,509 of 1,509)" docs/formats/core-data-regions.md a whole section titled "Every chunk has a uniform record length" All three now say 257 of 1,509, and the method's rustdoc explains WHY the old number was an artefact -- that resolve sliced at the first offset delta, so every record came out the same length by construction and the predicate was confirming the parser back to itself. That section also contained a withdrawal, and the withdrawal was wrong: "This withdraws the previous commit's variable-length type. That came from taking minlen/maxlen over all of a type's records at once, pooling across chunks; rule 3a's pooled claim, third time this session." The pooling rule fired correctly and was overruled by a measurement with no independent content. The per-chunk check that should have caught the pooled signal was itself reporting the parser's own slicing, so it agreed with the wrong answer for the same reason the original claim did. Two errors stacked: a real signal dismissed by a rule that had been right twice already, and a predicate that could not have told the difference. This is the third time this session that a test was asserting the parser's behaviour rather than the disc's, and the third time it was the only thing standing between a claim and a retraction. has_uniform_record_length is the clearest instance: a predicate named after a property of the data, returning a confident answer about the code. 245 tests, clippy clean. --- crates/gc-formats/src/chunks.rs | 17 ++++++++++++++--- docs/formats/core-data-regions.md | 27 ++++++++++++++++++++------- docs/roadmap.md | 10 ++++++---- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/crates/gc-formats/src/chunks.rs b/crates/gc-formats/src/chunks.rs index e506715..49a0c63 100644 --- a/crates/gc-formats/src/chunks.rs +++ b/crates/gc-formats/src/chunks.rs @@ -203,10 +203,21 @@ impl<'a> ResolvedChunk<'a> { /// True when every record in this chunk has the same length. /// - /// **Measured: true for 1,509 of 1,509 chunks** across all 27 levels. Record + /// **Measured: true for 257 of 1,509 chunks** across all 27 levels. Record /// length varies *between* chunks of the same type -- one type runs 76 to 104 - /// bytes -- but never within one. An earlier claim that some type had - /// variable-length records was pooling across chunks; it is withdrawn. + /// bytes -- and, on 1,252 chunks, *within* one as well. + /// + /// This method used to report 1,509 of 1,509, and that was an artefact of + /// `resolve`: it sliced every record at the chunk's first offset delta, so + /// every record came out the same length by construction, and this predicate + /// was confirming the parser back to itself. `resolve` now bounds each record + /// by its successor's offset, which is the only coherent reading -- a record + /// of the nominal stride would overlap the next one whenever the delta is + /// smaller, and an explicit offset table cannot express an overlap. + /// + /// So the earlier withdrawal, "an earlier claim that some type had + /// variable-length records was pooling across chunks", was also wrong. The + /// records are variable-length and were never anything else. pub fn has_uniform_record_length(&self) -> bool { let mut it = self.records.iter().filter(|r| !r.is_empty()); let Some(first) = it.next().map(|r| r.len()) else { diff --git a/docs/formats/core-data-regions.md b/docs/formats/core-data-regions.md index 51f5656..67bdb95 100644 --- a/docs/formats/core-data-regions.md +++ b/docs/formats/core-data-regions.md @@ -1429,15 +1429,28 @@ fits and `None` otherwise, so the 247 unexplained chunks are distinguishable from the 1,262 explained ones and nothing skips a leading byte on the strength of a rule that does not apply. -### Every chunk has a uniform record length +### RETRACTED: "every chunk has a uniform record length" -**1,509 of 1,509 chunks.** Length varies between chunks of the same type -- one -type runs 76 to 104 bytes -- but never within one chunk. +**Claimed: 1,509 of 1,509 chunks. True: 257 of 1,509.** -This **withdraws the previous commit's "variable-length type"**. That came from -taking `minlen`/`maxlen` over all of a type's records at once, pooling across -chunks; rule 3a's pooled claim, third time this session. Within any one chunk the -length is fixed. +Length varies between chunks of the same type -- one type runs 76 to 104 bytes -- +and on 1,252 chunks it varies *within* one as well. + +**Both halves of that old entry were wrong, and both were mine.** + +"Never within one chunk" was `resolve` slicing every record at the chunk's first +offset delta. Every record then came out the same length by construction, so the +predicate was confirming the parser back to itself. + +And this section's *withdrawal* of "variable-length type" was wrong too. It read +the pooled observation as a partitioning artifact -- `minlen`/`maxlen` taken across +all of a type's records at once. Rule 3a is right about pooling in general, and it +was applied to a real signal here: the type genuinely has variable-length records, +and the per-chunk check that would have caught it was itself reporting the +parser's own slicing. + +Two errors stacked. The pooling rule fired correctly and was overruled by a +measurement that had no independent content. ## The first TWO bytes encode the record's own index diff --git a/docs/roadmap.md b/docs/roadmap.md index 395e3a6..e6f6b81 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -444,10 +444,12 @@ Phase 1 hands over the extents; this phase works out what each one contains. chunks, 34,491 records.** Moby class IDs enrich at 9,493 hits against 246.1 expected with contiguous per-type arrays -- but the arrays land in a different place for each type, so no single pooled scan finds them. -- [x] **Chunk record framing is closed.** Every chunk has a **uniform record - length** (1,509 of 1,509) -- length varies *between* chunks of a type, never - within one, which withdrew an earlier "variable-length type" claim that had - been pooled across chunks. The record's leading byte is a **per-chunk phase +- [x] **Chunk record framing is closed**, but the uniformity claim in it is + **retracted**: only **257 of 1,509** chunks have a uniform record length, and + 1,252 are variable within the chunk. "1,509 of 1,509" was `resolve` slicing + at the chunk's first offset delta and the predicate confirming the parser + back to itself. An earlier withdrawal ("variable-length was a pooled + artifact") was wrong too -- the records were always variable. The record's leading byte is a **per-chunk phase counter** (`bucket_rule`, 1,262 of 1,509 chunks) and on **1,235** of them *both* leading bytes encode the record's own index in mixed radix (`index_rule`), so the leading bytes carry no per-record information.