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.