Skip to content

Record why the 13-bit row count is right (W4) - #8

Merged
jrgutier merged 1 commit into
mainfrom
docs/pdb-row-count-interpretation
Aug 1, 2026
Merged

Record why the 13-bit row count is right (W4)#8
jrgutier merged 1 commit into
mainfrom
docs/pdb-row-count-interpretation

Conversation

@jrgutier

@jrgutier jrgutier commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Closes W4 from .omc/plans/playlist-phantom-entry-root-cause.md — and the answer is that no code change is needed. Comment only, no behaviour change.

The doubt

The reader takes a page's slot count from the 13-bit field packed at +24. crate-digger models the same bytes differently — an 8-bit count at +24 with a num_rows_large u16 at +34 taking over past 255 rows. If crate-digger were right, this reader would mis-parse every dense page, silently — and verify could never catch it, because both sides share the reader.

The plan flagged that fixtures cannot settle this: they are packed by the same assumption the parser makes. Only real bytes can. A 3,673-track export provided them.

The measurement — 997 data pages, 14 carrying 284 rows

page word & 0x1FFF byte at +24 u16 at +34
18 284 28 283
53 284 28 84
140 284 28 283
311 284 28 14
329 284 28 20
  • The 13-bit field is right. Those pages parse correctly — the library converts to 3,872 playlist entries and verifies with 0 discrepancies.
  • The byte at +24 under-reports: 28 is simply 284 & 0xFF.
  • The u16 at +34 is not a row count. It reads 283, 84, 14 and 20 across pages that all hold 284 rows, and 0x1FFF on 271 others. This repo names it transaction_row_index, which fits — 283 is the last index of 284 rows.
  • On the 983 pages holding ≤255 rows the two readings agree, which is exactly why this divergence stays invisible on small libraries.

Why this is worth a commit

Probe-before-fix is what the plan called for, and it paid: acting on the ksy alone would have "fixed" a correct parser into a broken one. The measurement is now recorded next to _decode_page_counts so the next reader doesn't re-open the question from the spec alone.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V3aF4y4GdsuJta2bfYUZ8w

The reader takes a page's slot count from the 13-bit field packed at +24.
crate-digger models the same bytes differently — an 8-bit count at +24 with a
u16 "num_rows_large" at +34 taking over past 255 rows — and if that were right
this reader would mis-parse every dense page, silently, with verify unable to
notice because both sides share the reader.

Fixtures cannot settle it: they are packed by the same assumption the parser
makes. A real 3,673-track export can, and does. Across its 997 data pages, 14
carry 284 rows:

  word & 0x1FFF = 284 on those pages, and they parse correctly — the library
  converts to 3,872 playlist entries and verifies with 0 discrepancies.

  the byte at +24 reads 28, which is just 284 & 0xFF. Alone it under-reports.

  the u16 at +34 is not a row count at all: 283, 84, 14 and 20 across pages that
  all hold 284 rows, and 0x1FFF on 271 others. This repo names that field
  transaction_row_index, which fits — 283 is the last index of 284 rows.

  on the 983 pages holding <=255 rows the two readings agree, which is why the
  divergence stays invisible on small libraries.

Comment only, no behaviour change. Written down so the next reader does not
re-open the question from the ksy alone and "fix" a correct parser.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3aF4y4GdsuJta2bfYUZ8w
@jrgutier
jrgutier merged commit 9b3e5f9 into main Aug 1, 2026
9 checks passed
@jrgutier
jrgutier deleted the docs/pdb-row-count-interpretation branch August 1, 2026 04:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant