diff --git a/paperforge/worker/ocr_document.py b/paperforge/worker/ocr_document.py index 56ead06e..b459b7d6 100644 --- a/paperforge/worker/ocr_document.py +++ b/paperforge/worker/ocr_document.py @@ -5989,12 +5989,6 @@ def normalize_document_structure( for block in blocks: if block.get("seed_role") == "figure_caption" and not _should_keep_formal_caption_seed(block): block["role"] = "figure_caption_candidate" - if not gate_context.accepted_table_block_ids: - for block in blocks: - if block.get("seed_role") == "table_caption" and not _should_keep_formal_caption_seed(block): - block["role"] = "table_caption_candidate" - if block.get("seed_role") == "table_html": - block["role"] = "table_html_candidate" decisions = [] for block in blocks: diff --git a/paperforge/worker/ocr_roles.py b/paperforge/worker/ocr_roles.py index 48da59ea..9a195f13 100644 --- a/paperforge/worker/ocr_roles.py +++ b/paperforge/worker/ocr_roles.py @@ -1318,6 +1318,15 @@ def assign_block_role( evidence=[f"textual table (bullet list) not media_asset: {text[:60]}"], ) + + # Inline table HTML check: applies to all raw_labels, not just "text" + if text.strip().lower().startswith(" HTML is self-identifying, no verification needed } @@ -358,6 +359,16 @@ def resolve_verified_role(block: dict, context: RoleGateContext) -> VerifiedRole render_default=False, ) + if proposal == "table_html": + # Inline HTML is self-identifying — no structural verifier needed. + # The seed_role is reliable when the block text starts with
. + if str(block.get("text", "") or "").strip().lower().startswith(" HTML — self-identifying, accepted without verification"], + ) + return hold_role(seed_role, "table_html seed without inline
text") + if proposal in VERIFY_REQUIRED or seed_role in VERIFY_REQUIRED: return hold_role(seed_role, f"{proposal} requires structural verifier") source = "non_structural_seed" if current_role in {"", "unassigned"} else "non_structural_normalized_role"