Implement Chunker with chunker_version = "pdf-page-v1". Honors page boundaries (no chunk crosses a page) and subdivides long pages by paragraph budget. Produces the same Chunk shape as md-heading-v1 so retrieval is uniform.
Why now / why this size
Per-medium chunkers must stay tiny and obvious. Page-aware logic is small but its chunker_version label is load-bearing for downstream embedding records.
policy_hash = blake3(canonical_json(policy)) truncated to 16 hex chars.
Behavior contract
Only operates on documents whose blocks all carry SourceSpan::Page (i.e., from kebab-parse-pdf). Other documents → return anyhow::Error("PdfPageV1Chunker only handles PDF docs").
For each page block (1 block per page after p7-1):
If text.len() (byte estimate) ≤ policy.target_tokens * 4 (proxy for tokens) → emit one chunk for the entire page.
Else → split by paragraphs (split text on \n\n or sentence-ending punctuation followed by whitespace) and group adjacent paragraphs until the running byte total approaches policy.target_tokens * 4. Apply policy.overlap_tokens * 4 bytes of trailing overlap into the next chunk's prefix.
A chunk NEVER crosses a page boundary.
Each chunk's source_spans contains exactly one SourceSpan::Page { page: i, char_start: Some(start), char_end: Some(end) } with start/end in characters within the page.
heading_path = [] (PDFs have no heading tree at v1).
block_ids = [page_block.block_id] (one block per chunk).
text = the chunk's slice of page text. If overlap is applied, the slice includes the overlap prefix from the previous chunk.
Section/heading inference from font metadata (P+).
Risks / notes
Byte-based proxy can over- or under-estimate. The chunker is intentionally crude; a proper tokenizer slot lives in P3+ and replaces this proxy across all chunkers in one PR.
Sentence-splitting uses simple regex; languages without clear sentence punctuation (e.g., Japanese) may produce uneven chunks. Document this and accept for v1.
Bumping chunker_version to pdf-page-v2 invalidates downstream embedding records for all PDFs; treat as a versioning event per §9.