Workstream X: 11 papers audited across 6 layout classes,
5 verified via vision subagents. 6 real bug patterns identified
with code locations and root cause analysis.
Bug patterns:
A - _is_obviously_formal_figure_caption heuristic too aggressive
(ocr_roles.py:193)
B - Cross-column figure asset mis-assignment ignores boundaries
(ocr_figures.py:704)
C - Render frontmatter skip silently drops authors/affiliations
(ocr_render.py)
D - Two-column same-page boundary body→backmatter zone pollution
(ocr_document.py)
E - Frontmatter headings misclassified (ocr_roles.py)
F - Supplementary-only PDFs not handled
Full report: docs/superpowers/analysis/2026-07-05-layout-truth-audit-findings.md
Also: codebase-memory-mcp 0.8.1 installed and repo indexed.
- add fixture-backed replay parity for 37LK5T97, 8CCATQE3, and 5MAW65YD
- keep existing DWQQK2YB, VAMSAZMG, and PJBMGVTF gates
- update OCR project status and queue to 105-test state
- add fixture-backed parity replay for VAMSAZMG and PJBMGVTF
- keep DWQQK2YB as existing replay gate
- sync post_match render/index defaults to legacy contract
- update OCR status docs to 102-test state
3 distinct bugs found and fixed:
1. TABLE in figure regex (_FIGURE_NUMBER_PATTERN)
Removed TABLE/Table from figure regex — caused table captions to be
extracted as figure numbers and roadmapped into figure inventory.
Added unit tests (table_numeric_caption_is_not_a_figure_number,
table_appendix_caption_marker_has_no_figure_number).
2. int block_id type mismatch in cross-page lookup
CrossPageSettlementPass and PrimarySamePagePass compared block_id
with === but deduped_legends use int keys while ResourceRef stores
str. Fixed by casting both to str. Table continuation lookup
missed page filter, picking wrong page's same block_id. Added
page filter + int_block_id tests.
3. Table appendix support gaps
- Table prefix regex only accepted digits/roman, not 'TABLE A1'.
Added [A-Z]\d+ token and strip-leading-alpha in parse.
- _is_validation_first_table_candidate didn't cover figure_title
raw_label blocks with table_caption_like style. Added second
gate.
- _is_weak_explicit_table_caption only checked table_caption roles.
Extended to include validation-first candidates.
- Same-page tie-break didn't apply for weak-explicit captions.
Ported _bare_table_tie_break into vnext pass.
- figure_caption_candidate not excluded from note attachment.
- Continuation merge stripped leading duplicate table marker.
M84CTEM9 vault verification: 6/6 figures matched (3 main + 3
appendix + assets), 4/4 tables (Table 1,2 + Table A1,A2 + assets),
0 false positives, 0 figure asset leakage.
- _TABLE_PREFIX_PATTERN in ocr_roles.py, ocr_signatures.py, ocr_tables.py
now matches Table I/II/III and Table S1/S2
- _extract_table_number and _extract_marker_signature parse Roman numbers
- figure_title generic fallback checks table prefix before figure caption
- ocr_families.py adds early table-prefix guard before reference family
4AG67PBH P21: acknowledgment text absorbed as reference_item because:
'doctoral scholarships 2023.02051.BD' matched \b(?:19|20)\d{2}\.
Fixed to \b(?:19|20)\d{2}\.(?:\s|$) — year+period must be followed by whitespace or end of string.
Left column now correct: body (Acknowledgments, Conflict, Keywords, dates) in body_zone,
then [1]-[3] in reference_zone. Right column all 33 refs unaffected.
- Raise word limit 80→200 (real bio text is 90-100 words)
- Add structured_insert_candidate to Pass C role list (fixes Barbara bio miss)
- Fix page-agnostic block_id filter in ocr_figures.py (lines 4479, 4529)
- Was filtering by bare block_id, colliding same id across pages
- Changed to (page, block_id) tuples
- Add bio passes (Pass B+C) to ocr_rebuild.py pipeline
- ocr_render.py: extend consumed frontmatter roles skip from page 1 to pages <= 2,
preventing paper_title appearing twice on pre-proof papers
- ocr_document.py: add image/media block promotion in backmatter zone normalization
so raw image blocks become media_asset instead of backmatter_body; this fixes
build_figure_inventory producing 0 matched_figures. Also check seed_role in
_sanitize_reference_zone_boundary since it runs before role resolution
- scripts/dev/ocr_rebuild_paper.py: single-paper rebuild + block_trace regeneration
entry point (will be wired into CLI later)
- tests: boundary protection and completeness check tests
- DW trace regenerated with correct role distribution
- CAQ: Move correspondence detection before zone-based furniture check
(ocr_roles.py). Correspondence footnote now correctly gets
frontmatter_support instead of frontmatter_noise.
- DW: Accept raw_label=doc_title on page 2 as paper_title repeat
(ocr_structural_gate.py). Fixes title re-verification that was
held to unknown_structural.
- DW: Tag keywords block as structured_insert when abstract span
stop_reason=keywords (ocr_document.py). Uses abstract span boundary
signal instead of text matching.
- Zone fallback: Fix unassigned role resolution in ref_heading_pages
and last_body_heading_top pre-scans (ocr_document.py). Blocks with
role=unassigned now fall through to seed_role. Also populate
ref_heading_pages from first reference_item on pages without a
reference_heading.
- Updated expectations for DW (7 FAIL, down from 9) and CAQ (0 FAIL,
down from 3). All remaining DW FAILs are user-decided skips.
In post_reference_backmatter_zone, blocks with role=reference_item are
outside the verified reference range. The structural gate cannot verify
them and holds them to unknown_structural. Fix: the zone normalization
now converts ALL non-heading blocks (including reference_item) to
backmatter_body, which the gate accepts via _SAFE_PRESERVED_ROLES.
DW expectations: 18 FAIL -> 9 FAIL (fixed 8 biography blocks + 1 equal
contribution note). Remaining 9 are pre-existing known bugs.
The source-anchor override for authors matched block_id=2 on EVERY page,
not just page 1. Added page check: only accept anchored role if block is
on the same page as the source anchor. Prevents section headings,
reference items, and figure captions from being misclassified as authors.
Also updated regenerate_traces.py sys.path to use main checkout instead
of worktree, and regenerated both DW (287 blocks) and CAQ (153 blocks)
traces.
- Pass source_frontmatter_anchors to normalize_document_structure so gate
has source-backed IDs before running (fixes paper_title/authors always HELD)
- Add table_caption CANDIDATE handler (was falling through to unknown_structural)
- Author matching: handle & splitting, strip trailing labels, initial-based
matching for abbreviated names, subset match for truncated author lists
- Override frontmatter_noise preservation when seed_role is VERIFY_REQUIRED
- Accept authors role from source anchor regardless of seed_role
- Enrich source_metadata authors from formal-library.json fallback
- Heading merge: use vertical_gap <= 30px instead of sentence-end heuristic
All 280 tests pass. TSCKAVIS/DWQQK2YB/CAQNW9Q2 rebuilt and verified.
- Add paperforge_lite/ocr_diagnostics.py with tiered L1-L4 checks
- L1: token presence, L2: URL reachability, L3: API schema validation
- L4: optional live PDF round-trip test with polling
- Add 7 mocked unit tests for all levels
- Include blank.pdf test fixture