Commit graph

90 commits

Author SHA1 Message Date
LLLin000
77a6e0cfec fix: heading→emitted events, backmatter→heading events, page-qualified keys
- Section/subsection headings now appear in BOTH heading_events and
  emitted_block_events (emitted_as='heading') for complete event stream
- Backmatter headings (Funding/Acknowledgments/Data Availability/Conflicts)
  now generate heading_events → appear as structure tree sections with
  their own body_units
- Page-qualified block IDs (p{page}:{block_id}) in tree own/subtree_block_ids
  and body_units block_map: eliminates ambiguous block_id collisions when
  same block_id appears on multiple pages in real OCR data
- TC-9.2 wording fix, KEYS empty guard, global unit_id uniqueness check
2026-07-06 18:19:17 +08:00
LLLin000
288829bb5b feat: PR 1 — nested structure tree + body_units correctness
- RenderOutput dataclass with heading_events/emitted_block_events tracking
- Stack-algorithm structure tree with own/subtree block IDs
- Recursive body_units builder with role helper + token cap splitting
- Schema v4: section_path_json, section_level, section_title, part_ordinal
- Phase 4/5 reorder in ocr_rebuild.py and ocr.py
- 12 new test cases for tree nesting, own_block_ids, rendered-order intervals
2026-07-06 16:42:08 +08:00
LLLin000
d8451947ad refactor: separate render artifact writes from user fulltext commit 2026-07-05 16:50:58 +08:00
LLLin000
a138100398 fix(pr1): remove has_any_author gate from affiliation/email fallback 2026-07-04 22:17:43 +08:00
LLLin000
57bb73556b feat(pr1): add frontmatter render fallback for empty metadata 2026-07-04 21:57:04 +08:00
LLLin000
964e05b305 feat: Workstream A — OCR object writeback module
- A0: extract post-inventory seam into ocr_object_writeback module
- A1: add ownership evidence contract + idempotency guard
- A2: claim side-adjacent figure text (M84CTEM9 fix)
2026-07-04 13:16:37 +08:00
LLLin000
8dba963394 fix: complete reference detection fixes — 5 problem families 2026-07-03 01:46:27 +08:00
LLLin000
9aa228d60c feat: layout robustness layer — robust banding, role-aware gating, two-column continuation
Task 1: Add robust band estimator core module (ocr_banding.py)
  - LayoutBandEstimate, UsableContentDecision dataclasses
  - collect_layout_band_candidates, estimate_layout_bands
  - choose_runtime_bands, decide_usable_content

Task 2: Expose dry-run robust band diagnostics in normalize_document_structure
  - layout_band_estimate field on DocumentStructure
  - Serialized diagnostics with legacy vs robust comparison

Task 3: Enable robust runtime band selection
  - _order_tail_blocks uses robust estimate + choose_runtime_bands
  - Falls back to legacy-safe bands when robust holds

Task 4: Make layout band gating role-aware
  - decide_usable_content replaces _is_in_usable_content
  - Strong roles (reference_heading/item/body, backmatter_heading/boundary)
    bypass band gating entirely
  - backmatter_body gated at Phase 4b after heading ownership check

Task 5: Column-aware two-column continuation reference attachment
  - _block_column(), _should_attach_reference_item_to_ref_section()
  - rejected_ref_items list replaces body_pool fallback

Verification: 202/202 tests pass, 14/14 paper rebuilds OK,
95FDVE4W reference ordering confirmed
2026-07-02 19:15:44 +08:00
LLLin000
78b9973123 fix: reference-zone ordering fixes (P0-P4)
P0: disambiguate table field keys from block_page_by_id in ocr_render.py
P1: add _is_tail_backmatter_continuation() guard, order backmatter correctly
P2: phase 4b tail nonref guard with tail_backmatter_blocks list
P3: page-continuation-marker false reference gate in ocr_families.py
P4: force reference heading before same-page refs, ref_item bypass usable gate
2026-07-02 19:06:06 +08:00
LLLin000
cb6e52eff5 fix: backmatter_body (author bios) after refs in skip_section_grouping render
Two-part fix:

1. ocr_bio.py: clear zone ('') when post_ref_bio_cleanup converts
   block to backmatter_body, so render doesn't interleave with refs
   (was reference_zone from zone inference)

2. ocr_render.py: skip_section_grouping path (no reference_heading
   on page) grouped backmatter_body/backmatter_heading into non_ref,
   placing them before the same page's refs. On mixed-column tail
   pages this put bios between [170] and [171]. Now backmatter roles
   are output after refs within each page.

Fixes 2HEUD5P9 page 26 author bios appearing before [171]-[188].
2026-06-29 14:10:50 +08:00
Research Assistant
b1fdbc30eb feat: P0 fixes (ref sort, caption insert) + P1 figure containment render hygiene
P0:
- Fix 2: _ref_number_sort_key handles [N] bracket format (ocr_render.py:481)
- Fix 4: remove figure_caption from _INSERT_CANDIDATE_ROLES (ocr_document.py:3846)
- Fix 5: filter demoted body_paragraph from figure legends (ocr_figures.py:2950)

P1:
- figure containment render-hygiene pass after table inventory writeback
- 6 helpers: _cluster_bboxes_by_proximity, _is_contained,
  _highly_overlaps_any_matched_region, _figure_region_bbox,
  _matched_asset_keys, tag_figure_contained_text
- Wire call site in postprocess_ocr_result() (ocr.py:1891)

Infra:
- Sync workspace fulltext after rebuild (asset_index.py)
- Fix UnboundLocalError on index-refresh (sync_service.py)
- Add missing frontmatter fields to field registry (field_registry.yaml)
- 283 + 19 = 302 tests passing
2026-06-27 22:56:22 +08:00
Research Assistant
fd877f4504 fix: blue sidebar box not rendered as callout
Three issues fixed:
1. score_structured_insert: _in_visual_container weight 0.3->0.45
   (evidence-driven admission is now reliable)
2. score_structured_insert: add sidebar_header_phrase check (+0.2)
   for 'available with this article' etc.
3. _container_text set to block text (was True bool)
4. Normalize newlines in text before keyword matching
5. Safeguard renderer for non-string _container_text
6. Bump span_visual_container_version to force backfill re-run
2026-06-26 23:13:25 +08:00
Research Assistant
faa70545eb fix: resolve figure_id collisions via name mutation
When two figures share the same figure_id (e.g. supplementary
"Figure S.1" and main "Figure 1" both mapped to "figure_001"),
the second occurrence is renamed with an "s" prefix:
  figure_001 -> figure_s001, figure_ss001, etc.

This avoids file overwrite in ocr_objects.py and ensures both
body and supplementary figures appear at their correct positions
in the rendered fulltext.

Changes:
- _resolve_figure_id_collisions() in ocr_figures.py
- figure_id passthrough in ocr_figure_reader.py (reader + normalize)
- _reader_figure_embed_target prefers explicit figure_id
- 11 unit tests covering single/triple/multi collisions, mixed buckets,
  empty IDs, realistic body+supplementary layout
2026-06-26 18:36:04 +08:00
Research Assistant
943e5995cb fix: ownership skip also matches str(block_id) for int/string alias 2026-06-25 23:08:07 +08:00
Research Assistant
b4152abe10 A2: check table ownership (consumed_table_block_keys) before _SKIPPED_BODY_ROLES in render loop
Moves the block_id fetch and consumed_table_block_keys check before
_SKIPPED_BODY_ROLES so table note removal is a contract-based decision
(ownership) not a role-based accident (footnote role).

Part of table ownership contract refactor.
2026-06-25 22:27:35 +08:00
Research Assistant
72b0bf4a31 A2: per-block page for consumed_table_block_keys
Build block->page map from structured_blocks so cross-page note
blocks get their real page instead of table['page'].
2026-06-25 22:26:05 +08:00
Research Assistant
87d3e8cae2 test: add regression tests for footnote skip, caption fallback, bare table N matching 2026-06-25 17:23:49 +08:00
Research Assistant
c661669ec8 fix: skip footnote in body, propagate bare table caption pre-candidates, downgrade caption fallback to note 2026-06-25 17:18:52 +08:00
Research Assistant
38d665e34e fix: heading level from font size, bold font face, and case style 2026-06-25 16:49:18 +08:00
Research Assistant
692c200a12 fix: sort reference items by parsed number in tail reordering 2026-06-23 20:01:41 +08:00
Research Assistant
410151ea8e fix: reuse rebuild metadata and object extraction work 2026-06-22 22:15:25 +08:00
Research Assistant
ba68910cf3 fix(ocr): dedup backfill text in rebuild + exclude footer from table notes
- Add rebuild raw-block dedup: strip pdf_text_layer_fallback blocks
  whose 5-gram overlap with same-page body exceeds 80%
- Propagate _text_source / _ocr_raw_status / _ocr_raw_error_type to
  structured blocks for downstream debugging
- Add render-level dedup: skip body_paragraph if _text_source marks
  it as backfill with >=80% overlap vs emitted page text
- Exclude noise/page_footer/page_header/frontmatter_noise roles from
  table note candidate detection
2026-06-22 17:28:06 +08:00
Research Assistant
6522dc9aef docs: update PROJECT-MANAGEMENT with 2HEUD5P9 rebuild findings 2026-06-22 02:50:37 +08:00
Research Assistant
db69961c7c feat: convert body-zone footnotes with distinct font to callout 2026-06-22 01:51:10 +08:00
Research Assistant
924fcfd54f fix: footnote blocks emit after refs; frontmatter_noise renders on backmatter pages; visual heading grading; figure inner-text crop exclusion 2026-06-22 00:46:54 +08:00
Research Assistant
7e88e223bc fix: remove backmatter bold override for pre-reference headings — use visual heading level instead 2026-06-22 00:22:49 +08:00
Research Assistant
64e99367c9 fix: consumed_table_block_keys use (page, id) tuples; exempt numbered headings from bogus_heading length check 2026-06-22 00:09:23 +08:00
Research Assistant
b1081e3db3 feat: visual heading grading — font_size cluster + bold/regular for L3/L4; fix number pattern for 3D-prefix headings 2026-06-21 23:42:15 +08:00
Research Assistant
0e0a8463af fix: clean table projection and health heading semantics 2026-06-19 23:50:12 +08:00
Research Assistant
765cdf91f2 fix: carry owned table notes through rebuild outputs 2026-06-19 23:34:01 +08:00
Research Assistant
7fde6236a2 fix: skip backmatter section grouping on pages without ref heading
On two-column tail pages with reference items but no explicit reference
heading (e.g. K7R8PEKW page 16), forced backmatter section grouping
overrides the natural column-sorted reading order.

- _reorder_tail_run: add skip_section_grouping param. When set, emit
  blocks in column-sorted order with reference items grouped at end,
  bypassing the backmatter/body section grouping logic entirely.
- _order_tail_blocks: detect pages with ref items + no ref heading and
  pass skip_section_grouping=True.
- _normalize_backmatter_roles_after_boundary: remove forced conversion
  of body_paragraph to backmatter_body inside backmatter region (body
  paragraphs attach naturally via _find_owning_heading in Phase 1).
2026-06-17 01:31:38 +08:00
Research Assistant
8636a2cf89 fix: restore K7 abstract + Introduction paragraph 2026-06-16 21:33:03 +08:00
Research Assistant
644309473b fix: review findings — page1_candidates variable bug, page2 doc_title gate, same-page table pre-ref emission
- ocr_document.py: page1_candidates filter now uses b.get('block_id')
- ocr_structural_gate.py: page 2 doc_title requires source anchor to accept
- ocr_render.py: emit matched figures/tables before ## References to fix
  same-page table-after-refs ordering (A8E7SRVS Table 10)
2026-06-14 23:17:54 +08:00
Research Assistant
a4634aeb20 fix(ocr-render): apply normalize_ocr_math_text to structured_insert _container_text 2026-06-14 22:19:15 +08:00
Research Assistant
80b91f73fd fix(ocr): merge Box N / Key insights content boxes into structured_insert callout
Add _merge_box_content() post-processing to normalize_document_structure:
detects structured_insert blocks whose text starts with Box N or Key
insights, then consumes following body-like blocks as box content.
Consumed blocks get role=noise + render_default=False to suppress
double-rendering. Column-crossing boxes (common in multi-column
layouts) are handled by removing the x-overlap heuristic.
2026-06-14 22:16:57 +08:00
Research Assistant
ae01067240 fix: suppress Box 1 structured_insert leak, recover table inventory from table_caption_candidate
- ocr_render.py: structured_insert respects render_default (fixes Box 1 endnote
  leaking as > [!NOTE] callout). Add table_caption_candidate to skipped roles.
- ocr_tables.py: build_table_inventory now collects table_caption_candidate
  blocks as captions (was silently skipping them)
2026-06-14 21:28:52 +08:00
Research Assistant
7cf7ce0f1f fix: restore blank line after title heading 2026-06-14 21:04:25 +08:00
Research Assistant
056f7eaac2 style(ocr-render): wrap metadata in [info] callout, remove blank line after title 2026-06-14 21:04:09 +08:00
Research Assistant
7f83affeea fix(ocr-render): remove internal reader_status labels from markdown output
EXACT_MATCH, LEGEND_ONLY, ASSET_GROUP_ONLY are internal status
signals and should not leak into user-facing rendered fulltext.
2026-06-14 20:56:37 +08:00
Research Assistant
5fc9554c66 fix(ocr): protect figure/image blocks from backmatter normalization, fix duplicate title, and add unified rebuild entry point
- 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
2026-06-14 18:47:50 +08:00
Research Assistant
f1d617bc7f fix: restore abstract fallback and reader status visibility 2026-06-14 12:31:12 +08:00
Research Assistant
7fedab0e5c fix: exclude bullet-prefixed highlight text from abstract rendering 2026-06-13 21:44:16 +08:00
Research Assistant
56c549fec1 fix: remove blockquote prefix from abstract, fix backmatter_start detection 2026-06-13 21:40:03 +08:00
Research Assistant
050f9f32ee fix: suppress reader figure cards when embed covers them, add tail veto in infer_zones 2026-06-13 21:19:49 +08:00
Research Assistant
0d7579a03d fix: remove internal status labels from reader figure card output 2026-06-13 21:12:04 +08:00
Research Assistant
2eb6c1439b fix: enforce single-consumption closure in final structured renderer 2026-06-13 17:04:40 +08:00
Research Assistant
7b8ed4be0e fix: close OCR v2 real-paper structural, object, and render gaps 2026-06-12 17:41:57 +08:00
Research Assistant
e4d050c298 fix: close OCR v2 real-paper structural and object gaps 2026-06-12 17:24:57 +08:00
Research Assistant
669c3bfe07 fix: repair OCR renderer object emit and tail heading suppression 2026-06-12 16:52:32 +08:00
Research Assistant
d9f76917e9 style: ruff format after OCR role gate implementation 2026-06-12 15:11:33 +08:00