feat: text-layer grounding (extractor authority, guard rescue tier, verifier oracle + hi-DPI crops)
- backend/text_layer.py: PyMuPDF text-layer extraction, fuzzy evidence
bbox matching, 300-DPI crop rendering, coverage-gap signal
- extractor (classic + agent): TEXT LAYER block appended at call sites;
grounding guard gains text-layer rescue tier (grounding=text_layer stamp)
- verifier: {text_layer} oracle excerpt + evidence-located hi-DPI crops
replacing full-page images (fallback preserved, I2 guard intact)
- coverage gaps: text-bearing pages with zero extraction -> failed-scope
gap findings (agent) / log-only (classic)
- config knobs: TEXT_LAYER_ENABLED/MIN_CHARS/MAX_CHARS, VERIFY_TEXT_MAX_CHARS,
VERIFY_HI_DPI_CROPS, VERIFY_CROP_DPI, VERIFY_CROP_MARGIN_PTS
- tests: 22 new (text_layer unit, grounding/render, runner-level flow)
Spec: docs/superpowers/specs/2026-08-12-text-layer-grounding-design.md
This commit is contained in:
@@ -6,7 +6,7 @@ from typing import Dict
|
||||
from backend import config
|
||||
from backend.agents.base import AgentResult, AgentScope, AgentUsage, failure
|
||||
from backend.llm import call_json
|
||||
from backend.pipeline.extractor import _normalize_sheet
|
||||
from backend.pipeline.extractor import _normalize_sheet, _text_layer_block
|
||||
from backend.pipeline.sheet_index import _index_input
|
||||
from backend.prompts import (
|
||||
EXTRACTOR_SYSTEM_PROMPT,
|
||||
@@ -65,7 +65,7 @@ class SheetExtractorAgent:
|
||||
page = scope.payload["page"]
|
||||
instruction = EXTRACTOR_USER_INSTRUCTION.replace(
|
||||
"{sheet_hint}", str(scope.payload.get("sheet_hint") or "")
|
||||
)
|
||||
) + _text_layer_block(page)
|
||||
parsed = _wrap_bare_list(self._call(instruction, page),
|
||||
page["page_number"])
|
||||
if not isinstance(parsed, dict):
|
||||
@@ -79,7 +79,8 @@ class SheetExtractorAgent:
|
||||
)
|
||||
if not isinstance(parsed, dict):
|
||||
raise ValueError("no structured extraction returned")
|
||||
sheet = _normalize_sheet(parsed, page["page_number"])
|
||||
sheet = _normalize_sheet(parsed, page["page_number"],
|
||||
page_text=page.get("text_layer"))
|
||||
return AgentResult(scope_id=scope.scope_id, artifacts=[sheet])
|
||||
except Exception as exc:
|
||||
return failure(scope, exc)
|
||||
|
||||
Reference in New Issue
Block a user