ó
    À‘´j‹  ã                  ó°  • % S r SSKJr  SSKrSSKrSSKJr  SSKJrJ	r	J
r
JrJrJrJr  SSKJrJrJr  SSKJr  SSKJr  \ " S	 S
\5      5       r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r\" SSSS9\" SSSSS9\" SSS S!S9\" S"S#S$S%S9\" S&S'S(S)S*S+9\" S,S-S.S)S/S+9\" S0S1S2S)S39\" S4S5S6S)S39\" S7S8S9S)S39\" S:S;S<S9\" S=S>S?S)S39\" S@SASBS)SCS+9\" SDSESFS)S39\" SGSHSIS)S394rSJ\SK'   \" 1 SLk5      r \" SM \ 5       5      r! " SN SO\5      r" " SP SQ\5      r#SXSR jr$ " SS ST\5      r%SYSU jr&SZSV jr'          S[SW jr(g)\ag  
TableExtractor Protocol and ExtractedTable Pydantic model.

`ExtractedTable` carries the LLM-correction outputs (title, caption,
markdown, footnotes, footnote refs and marks, units, header rows) plus the
Camelot-side provenance (page, bbox, flavor). `subtitle` is always left empty
and exists only so older artifacts still load.

The numeric content lives inside `markdown`. Where its values come from
depends on the path, and the system prompts in `quber.agents.llm_client` set
the rule for each. The deprecated camelot-llm correction may not change any
Camelot value. The set-of-mark correction takes values from Camelot's grid and
the table's text layer, and may recover rows Camelot missed from that text
layer. A table the figure stage reads off a page image (`kind` image_table)
involves no Camelot: its grid, fingerprint and `som_region` come from the page
scan.
é    )ÚannotationsN)ÚPath)ÚListÚLiteralÚOptionalÚProtocolÚSequenceÚTupleÚruntime_checkable)Ú	BaseModelÚFieldÚfield_validator)ÚClassifierResult)ÚFootnoteDefc                  ó(   • \ rS rSrSS jrSS jrSrg)ÚTableExtractoré    c              ƒ  ó   #   • g 7f©N© ©ÚselfÚsources     Ú8/home/mande/repo/quber/src/quber/core/extractors/base.pyÚextract_tablesÚTableExtractor.extract_tables"   s   é € È#ùs   ‚c                ó   • g r   r   r   s     r   Úextract_tables_syncÚ"TableExtractor.extract_tables_sync$   s   € Èó    r   N)r   r   ÚreturnzList[ExtractedTable])Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__r   r   Ú__static_attributes__r   r    r   r   r       s   † äMçLr    r   c                  ó®  • \ rS rSr% \" SSS9rS\S'   \" SSS9rS\S'   \" SS	S9rS\S
'   \" SSS9r	S\S'   \" SSS9r
S\S'   \" SS9rS\S'   \" \SS9rS\S'   \" \SS9rS\S'   \" \SS9rS\S'   \" SSS9rS\S'   \" SSS9rS \S!'   \" S"S9rS#\S$'   \" SS%S9rS&\S''   \" SS(S9rS&\S)'   \" SS*S9rS&\S+'   \" \S,S9rS-\S.'   \" \S/S9rS-\S0'   \" \S1S9rS2\S3'   \" \S4S9rS\S5'   \" S6S7S9rS8\S9'   \" S:S;S9rS<\S='   \" SS>S9rS?\S@'   \" SASASBSCSD9rSE\SF'   \" SSGS9rSH\SI'   \" SJSKS9rSL\SM'   \ " SSNSO9\!SUSP j5       5       r"\" SSQS9r#SR\SS'   STr$g)VÚExtractedTableé'   Ú a²  Deterministic address of this table: '<doc>-p<page>-t<n>', where <doc> is the source file stem, <page> the 1-indexed page, and <n> the locator's reading-order ordinal on that page. A sub-table produced by splitting a fused region appends '-s<k>'. The same document yields the same IDs on every run, so external references (a review comment, a validation report, a UI link) stay valid across runs. Empty for engines that do not set it.©ÚdefaultÚdescriptionÚstrÚtable_idzçFirst 8 hex characters of sha256 over Camelot's raw value grid. The same document yields the same fingerprint on every run; a changed value at the same table_id shows as a different fingerprint. Empty when no grid backed the table.Úcontent_fingerprintzIThe table's printed name, copied off the page; empty when none is printedÚtitlezLThe sentence that introduces the table, copied off the page; empty when noneÚcaptionz5Retained for older artifacts; new runs leave it emptyÚsubtitlez5Corrected markdown table; numeric values from Camelot©r-   ÚmarkdownzáFootnotes printed below the table, each a pair of the footnote's own marker (empty for an unmarked general note) and its text. Read off the table image by the correction agent; the image's formatting decides what is a marker.©Údefault_factoryr-   zList[FootnoteDef]Ú	footnotesu¸  Footnote reference markers carried on the table's headers or cells, read off the table image â€” a superscript or parenthetical number, letter, or symbol that points to a footnote: e.g. '1', '(1)', a letter 'a', an asterisk '*', a dagger 'â€ ' or double-dagger 'â€¡', or a section sign 'Â§'. Written as it appears. Empty if the table carries none. Survives superscripts the text layer drops; the demand-driven footnote lookup keys off this.ú	List[str]Úfootnote_refsu…  Where each footnote reference marker sits: one entry per carrying cell, addressed by row/col in the corrected markdown (header row 0). The agent QUOTES the carrying cell and a lookup resolves the quote to its cell â€” it never counts positions. An entry with row/col None is a marker whose quote matched no cell (or that was catalogued without a quote) â€” kept and flagged, never dropped.zList['LocatedMarker']Úfootnote_marksz6Scale/currency unit attribution caption; empty if noneÚunitsNzôLeading column-header rows of the corrected markdown, counted off the table image by the correction review. A stacked header counts every stacked row; 0 means the fragment starts at data. None on artifacts extracted before this capture existed.úOptional[int]Úheader_rowsz1-indexed page numberÚintÚpagez4Camelot's geometric box on the page (x1, y1, x2, y2)ú+Optional[Tuple[float, float, float, float]]ÚbboxzõSet-of-Mark vision boundary box that located this table, normalized 0..1 with the page top-left as origin (x1, y1, x2, y2). Full-precision floats, never floored or snapped to a grid cell. None for engines that do not run the Set-of-Mark locator.Ú
som_regiona	  The table's actual content extent, normalized 0..1 top-left origin (x1, y1, x2, y2). Same box as som_region but with the bottom revised down to the last tabular row, located by matching the corrected markdown's last row back to the page text layer. som_region and bbox can overrun past the grid (e.g. enclosing footnote lines printed below it); this is the authoritative end of the table. Equal to som_region when no overrun is found or the last row could not be located. None for engines without the Set-of-Mark locator.Úcontent_regionub  The Camelot cell grid with per-cell geometry, as extracted before LLM structure correction. Rows and columns align with Camelot's raw grid, not the (possibly restructured) `markdown` â€” values are preserved verbatim through correction, so the geometry can be remapped onto the corrected cells by value later. Empty when no Camelot grid backed the table.zList[List['GroundedCell']]Ú	cell_gridu²  The corrected markdown's grid with per-cell geometry â€” one GroundedCell per markdown cell, same row/col addressing (header row 0), boxes normalized 0..1 top-left. This is the complete cell-level view, fully resolved at the grounding stage: combined cells carry the box their merge's reported addresses resolved to, and every other cell its Camelot cell box via order-preserving alignment to the raw grid â€” whole-cell matches first, then fragments of glued Camelot cells by ordered span tiling within the aligned rows. box is None only where a cell's text has no home in the raw grid; those gaps are warned in the run log at extraction. Equal to cell_grid when no correction was applied.Úcorrected_grida(  Corrected cells that combine two or more source cells (a rejoined split symbol, or a flattened multi-row/spanning header), each addressed by its row/col in the corrected markdown and resolved to one Camelot cell box per reported source address plus their union. Empty when no cells were combined.zList['MergedCellBox']Úmerged_cellsu.  Text printed in the table's header area that appears in no output cell â€” usually surrounding page text the correction rightly excluded, but recorded so an omission is never silent. Each entry becomes a table-level review flag (status 'header_text_dropped'). Empty when everything printed was carried.Údropped_textÚunknownz2Camelot extraction flavor that produced this tablez'Literal['lattice', 'stream', 'unknown']ÚflavorÚ
text_tableaÇ  What this region really is, set by reconciliation against docling. text_table: a real text-layer table (the default). chart: SoM mistook a docling-classified picture (bar/line chart, etc.) for a table. image_table: a real table rendered as an image (no text layer under a docling-detected table, Camelot empty). Its content is whatever last read the image: the page-scan workflow's reading where that has run, and docling's own OCR of it where it has not.z-Literal['text_table', 'chart', 'image_table']ÚkindzSource PDF pathúOptional[str]r   g        g      Y@zSCamelot parsing_report.accuracy (0-100); how cleanly text snapped to detected cells)r,   ÚgeÚler-   ÚfloatÚcamelot_accuracyzVWhat the TableClassifier decided about this candidate; None if classifier was bypassedzOptional[ClassifierResult]Úclassifier_decisionFzJTrue if the LLM modified Camelot's raw markdown during the correction passÚboolÚllm_correctedÚbefore)Úmodec                ó”   • [        U[        5      (       a-  U Vs/ s H  n[        U[        5      (       a  SUS.OUPM!     sn$ U$ s  snf )uÛ   Artifacts extracted before footnotes carried their marker stored each
footnote as a bare string. Load those as unmarked notes â€” the text is
intact; only the marker pairing is absent â€” so old artifacts stay
readable.r*   )ÚmarkerÚtext)Ú
isinstanceÚlistr.   )ÚclsÚvÚitems      r   Úcoerce_legacy_footnote_stringsÚ-ExtractedTable.coerce_legacy_footnote_stringsÒ   sJ   € ô �aœ×ÑÙ`aÓbÒ`aÐX\´J¸tÄS×4IÑ4I˜r¨4Ò0ÈtÒSÑ`aÑbÐbØˆùò cs   š&AzIRecord of the detector/correspondence/completeness flow; None if not usedzOptional[ExtractionRecord]Úextraction_recordr   )r]   Úobjectr!   rb   )%r"   r#   r$   r%   r   r/   Ú__annotations__r0   r1   r2   r3   r5   r[   r8   r:   r;   r<   r>   r@   rB   rC   rD   rE   rF   rG   rH   rJ   rL   r   rQ   rR   rT   r   Úclassmethodr_   ra   r&   r   r    r   r(   r(   '   sÅ  ‡ ÙØð:ñ
€Hˆcó 
ñ  %Øð^ñ Ð˜ó ñ ØÐ kñ€Eˆ3ó ñ ØÐ nñ€GˆSó ñ  "Ð2iÑj€HˆcÓjÙÐ&]Ñ^€HˆcÓ^Ù#(ØðXñ$€IÐ ó ñ  %Øð$ñ
 €M�9ó 
ñ -2Øð*ñ
-€NÐ)ó 
ñ ˜rÐ/gÑh€Eˆ3ÓhÙ!&Øðñ"€K�ó ñ Ð"9Ñ:€Dˆ#Ó:Ù8=ØÐ"Xñ9€DÐ
5ó ñ ?DØðSñ?€JÐ;ó ñ CHØð_ñ
C€NÐ?ó 
ñ -2ØðQñ	-€IÐ)ó 	ñ 27ØðAñ2€NÐ.ó ñ +0Øð[ñ+€LÐ'ó ñ $Øð^ñ€L�)ó ñ 7<ØÐ'[ñ7€FÐ3ó ñ ;@Øð<ñ;€DÐ
7ó ñ "¨$Ð<MÑN€FˆMÓNñ $ØØØØiñ	Ð�eó ñ 7<ØØlñ7ÐÐ3ó ñ  ØØ`ñ€M�4ó ñ
 �[ xÑ0Øóó ó 1ðñ 5:ØØ_ñ5ÐÐ1ö r    r(   c                  ó   • \ rS rSr% Sr\" SS9rS\S'   \" SSS	9rS
\S'   \" SSS	9r	S\S'   \" SSS	9r
S\S'   \" \SS9rS\S'   \" SSS	9rS\S'   \" \SS9rS\S'   \" SSS	9rS\S '   \" SS!S	9rS\S"'   \" SS#S	9rS\S$'   \" \S%S9rS&\S''   S(rg))ÚExtractionRecordéä   uø  Outcome of the extraction attempt for one detected table.

Produced by `CamelotCorrespondenceExtractor`. Its pipeline has a vision
detector list every table visible on a page, matches each detected
table to the Camelot chunk(s) holding its data, and audits the result
for completeness against the page image.

This record captures the status of that attempt, the chunks that supplied
the data, and the audit verdict â€” including the failure case where a
table was detected by the vision detector but not extracted by Camelot
(`detected_not_extracted`); so a table the detector saw is never silently
dropped from the output.

None on `ExtractedTable` when the table came through the legacy
classifier/unifier path, which has no detector to anchor a record to.
a‡  extracted: a Camelot chunk matched the detected table and passed the completeness audit. incomplete: matched but the completeness audit found numbers in the image absent from the data, and no chunk could supply them. detected_not_extracted: the detector confirmed a table on the page but neither Camelot flavor nor the recovery pass produced it (reported explicitly, never silently dropped).r4   z<Literal['extracted', 'incomplete', 'detected_not_extracted']ÚstatusNzH1-based top-to-bottom position of the matched detected table on its pager+   r=   Údetected_ordinalr*   zTThe detector's description of this table; the content hook correspondence matched onr.   Údetected_descriptionzKWhich Camelot flavor supplied the chunk(s); None for detected_not_extractedz&Optional[Literal['lattice', 'stream']]Úmatched_flavorz>Camelot candidate_ids assembled into this table, in page orderr6   r9   Úsource_candidate_idsFz�True if a single Camelot chunk spans two or more detected tables (convergence). The chunk is kept whole and flagged, never split.rS   ÚcombinedzGDetected ordinals a combined chunk spans; empty unless combined is Truez	List[int]Úcombined_ordinalszWcompleteness audit verdict; None if the audit did not run (e.g. detected_not_extracted)zOptional[bool]Úcompleteness_completezVIf truncated, which edge was cut off (per the completeness audit); empty when completeÚcompleteness_gapz¸True if the text-layer fill step inserted one or more figures to round off an edge truncation. The inserted values are listed in filled_cells; every other cell remains Camelot-sourced.Úfilled_from_text_layerzvFigures inserted by the fill step, with their grid position and text-layer origin; empty unless filled_from_text_layerzList[FilledCell]Úfilled_cellsr   )r"   r#   r$   r%   Ú__doc__r   rh   rc   ri   rj   rk   r[   rl   rm   rn   ro   rp   rq   rr   r&   r   r    r   rf   rf   ä   s/  ‡ ññ" LQð=ñ	L€FÐHó 	ñ ',ØØ^ñ'Ð�mó ñ !&ØØjñ!Ð˜#ó ñ >CØØañ>€NÐ:ó ñ ',ØØTñ'Ð˜)ó ñ ØðOñ€Hˆdó ñ $)ØØ]ñ$Ð�yó ñ -2ØØmñ-Ð˜>ó ñ "ØØlñÐ�có ñ $)Øð'ñ$Ð˜Dó ñ &+Øð Mñ&€LÐ"ö r    rf   c                  ó¸   • \ rS rSr% Sr\" SS9rS\S'   \" SS9rS\S	'   \" S
SS9r	S\S'   \" SS9r
S\S'   \" SS9rS\S'   \" SS9rS\S'   \" SSS9rS\S'   Srg)Ú
FilledCelli1  a¦  One figure inserted into a table by the text-layer fill step.

Records that this value did NOT come from a Camelot chunk: it was read
directly from the PDF text layer at (x, y) and placed into the grid to
round off an edge truncation. Camelot remains the source for every
other cell; this keeps the amendment auditable and never blurs a
filled value with a Camelot-extracted one (the source field is always
`text_layer`).
z/The literal text-layer figure that was insertedr4   r.   ÚvaluezY0-based column index in the assembled row the value was placed in (0 is the label column)r?   Úcolumnr*   z3Label of the restored row the value was placed intor+   Ú	row_labelz,Which edge the truncated row was restored atzLiteral['top', 'bottom']Úedgez'Text-layer x of the figure (PDF points)rP   Úxz'Text-layer y of the figure (PDF points)ÚyÚ
text_layerzIAlways text_layer; distinguishes a filled cell from a Camelot-sourced onezLiteral['text_layer']r   r   N)r"   r#   r$   r%   rs   r   rv   rc   rw   rx   ry   rz   r{   r   r&   r   r    r   ru   ru   1  sŠ   ‡ ññ Ð#TÑU€Eˆ3ÓUÙØoñ€FˆCó ñ  2Ð3hÑi€IˆsÓiÙ%*Ð7eÑ%f€DÐ
"ÓfÙÐ!JÑK€A€uÓKÙÐ!JÑK€A€uÓKÙ$)ØØ_ñ%€FÐ!ö r    ru   c                  ó”   • \ rS rSr% Sr\" SS9rS\S'   \" SSS	S
9rS\S'   \" SSSS
9r	S\S'   \" SSS9r
S\S'   \" SSS9rS\S'   Srg)ÚLocatedMarkeriJ  u�  One footnote reference marker tied to the cell that carries it.

`row`/`col` address the carrying cell in the corrected markdown (header
row 0), resolved by looking up the cell text the agent QUOTED for the
marker â€” the model never counts positions. Both None when the marker is
known to be on the table but its carrying cell is not â€” the marker is
kept and flagged for review rather than guessed onto a row.
z?The reference marker as printed: '1', '(1)', 'a', '*', a daggerr4   r.   rX   Nr   zN0-based row of the carrying cell in the corrected markdown; None when unplaced)r,   rN   r-   r=   ÚrowzQ0-based column of the carrying cell in the corrected markdown; None when unplacedÚcolÚfootnoteuS  The correction agent's judgement of what the marker points at, made from the page image: 'footnote' â€” a note printed for this table; 'section' â€” a cross-reference to a named part of the document whose content lives elsewhere. Resolution routes on this: section references resolve to a heading pointer and are never hunted as footnotes.r+   zLiteral['footnote', 'section']rL   Úcellu  'cell': the marker is carried by a grid cell at row/col. 'table': the marker is carried by the table's own title or subtitle text â€” a spanning band or title suffix â€” so it qualifies the whole table and reaches every record; row/col are None but the marker is placed, not flagged.zLiteral['cell', 'table']Úscoper   )r"   r#   r$   r%   rs   r   rX   rc   r   r€   rL   rƒ   r&   r   r    r   r~   r~   J  s‰   ‡ ññ Ð$eÑf€FˆCÓfÙØØØdñ€Cˆó ñ
 ØØØgñ€Cˆó ñ
 ,1ØðAñ	,€DÐ
(ó 	ñ ',ØðNñ'€EÐ#ö r    r~   c                  óT   • \ rS rSr% SrS\S'   S\S'   S\S'   SrS\S	'   S
rS\S'   Srg)Ú
CellStatusit  as  One entry of the cell-status reference: the machine code a corrected
cell carries and the human framing a front end shows for it. `inspect`
marks the codes a consumer surfaces to the user when the table is used.
`cases` names the residue-catalog cases the code covers (the catalog is
docs/CELL_STATUS_CASES.pdf), so a status always points back to a
demonstrated example.
r.   ÚcodeÚlabelr-   FrS   Úinspectr*   Úcasesr   N)	r"   r#   r$   r%   rs   rc   rˆ   r‰   r&   r   r    r   r…   r…   t  s,   ‡ ñð ƒIØƒJØÓØ€GˆTÓØ€Eˆ3†Or    r…   Ú
reconciledzMatches the page.z]The cell's text tied back to a printed source and carries that source's measured coordinates.)r†   r‡   r-   Úheader_printed_unlocatedz?This header is printed on the page. We could not measure where.uµ   Header or band text is printed on the page, but its coordinates could not be measured. The text is correct; only the geometry is missing. Expected behavior â€” a pass, not a defect.Ú1)r†   r‡   r-   r‰   Úlabel_printed_unlocatedzBThis row label is printed on the page. We could not measure where.u    A row label is printed on the page, usually wrapped across printed lines, but its coordinates could not be measured. Expected behavior â€” a pass, not a defect.z2 and 3Úsingle_characterzNA one-character cell, such as a bare "$". Not matched to a position by design.uº   One-character text (a bare '$'), excluded from location matching by design: a bare symbol or digit would anchor inside any unrelated number. Working as designed â€” a pass, not a defect.Ú7Útotal_label_addedz@The page prints no label on the totals row, so we wrote "Total".uµ   The totals row is printed with no label; the extraction wrote 'Total'. Flagged for user review because the author could have intended something else â€” a review item, NOT a defect.TÚ5)r†   r‡   r-   rˆ   r‰   Úheader_label_addedz;The page prints no header over this column, so we named it.uè   The table is printed with no header over this column; the extraction wrote a generic column name ('Item', 'Description'). Flagged for user review because the author could have intended something else â€” a review item, NOT a defect.Ú6Ú
unverifiedzUThis value is on the page, but our check of it did not complete. Worth a manual look.uØ   The condition could not be confirmed: the text has no printed source and is not an authorized conventional label, or the inspector could not tell from the image. An open question for user review â€” not yet a defect.)r†   r‡   r-   rˆ   ÚdefectzGThe page shows something different from what we recorded. See the note.u  The inspector positively observed the page showing something OTHER than what the extraction recorded â€” a different word printed at an added label's position, or a structure the condition misdescribes. A confirmed defect; the evidence names what the page shows.Úfootnote_unresolvedzQThis cell has a footnote marker, and we could not find the footnote it refers to.uÃ  A marker is printed on a table cell or a figure's label and no tier found the note it points at â€” not the pairs the correction agent read off the image, not the reading-order scan, not the demand-driven lookup. The element states a figure the document qualifies somewhere, and the qualification is missing: read alone it looks unqualified, which is indistinguishable from a clean reading. An element-level flag naming the marker, not an output cell.Úfootnote_unreferencedz1A footnote on this page that no marker points to.un  A note printed for a table or figure that no marker on it names. Currently judged within one element type, so a note a table claims can still read as unreferenced by a figure on the same page and the reverse â€” which is why it is catalogued but not surfaced. Becomes meaningful once every reader's claims are pooled and the leftovers reported once for the document.Úfootnote_marker_unplacedz<This table has a footnote marker we could not tie to a cell.aY  The correction agent read this footnote reference marker off the table image but could not tie it to a carrying cell, or the position it reported failed validation. The marker is real; only its cell is unknown, so its footnote can be attached at table level but not to a specific row. A table-level flag: it names the marker, not an output cell.Úheader_text_droppedz?The page prints header text here that we left out of the table.a  Text printed in the table's header area appears in no output cell. Usually surrounding page text (a heading, a note) that the extraction correctly excluded from the table, but surfaced so an omission is never silent. A table-level flag: it names the missing text, not an output cell.Ú4Úvalue_misreadz>The page prints a different figure here. Check which is right.a  A chart value where the page fragment at the value's position states a different number than the reading. One of the two is wrong and the position pins exactly where to look, so the value never passes silently. A figure-value flag: it names the value and carries the fragment's box.Úvalue_unreconciledzFRead from the chart once, without a second check. Worth a manual look.a%  A chart value present in one reading with no counterpart in the other. The note states the direction: a scan-only value the local read did not corroborate, or a locally read value the scan omitted. Either way the value stands unverified and is surfaced rather than passed. A figure-value flag.zTuple[CellStatus, ...]ÚCELL_STATUS_REFERENCE>   r^   Útotalr-   c              #  ó8   #   • U  H  oR                   v •  M     g 7fr   )r†   ©Ú.0Úss     r   Ú	<genexpr>r£   /  s   é € ÐEÒ/D¨!ŸvžvÒ/Dùs   ‚c                  ó¢   • \ rS rSr% Sr\" SS9rS\S'   \" SSS	9rS
\S'   \" SSS	9r	S\S'   \" SSS	9r
S\S'   \" S5      \SS j5       5       rSrg)ÚGroundedCelli2  uJ  One Camelot cell paired with its geometry.

`text` is the cell value (immutable through the pipeline). `box` is the
cell's box normalized 0..1 with the page top-left as origin â€” the same
frame as `som_region` and `MergedCellBox`, so every box the table carries
reads in ONE frame â€” or None when no Camelot box backs the cell.
zCell value from Camelot's gridr4   r.   rY   NzOCell box (x1, y1, x2, y2) normalized 0..1, top-left origin; None if unavailabler+   rA   Úboxuÿ   Why the cell does or does not carry a box; set on corrected-grid cells only. One of the codes in CELL_STATUS_REFERENCE â€” see that registry (and the set_of_mark README) for each code's meaning and whether a consumer should surface it for user inspection.rM   rh   z¨Inspection evidence for a flagged cell: the status inspector's one-line account of what the table image shows at this position. None when the cell needed no inspection.Únotec                ó@   • Ub  U[         ;  a  [        SU< S35      eU$ )Nzunknown cell status z&; register it in CELL_STATUS_REFERENCE)Ú_CELL_STATUS_CODESÚ
ValueError)r\   r]   s     r   Ústatus_is_a_registered_codeÚ(GroundedCell.status_is_a_registered_codeS  s,   € ð ‰=˜QÔ&8Ó8ÜÐ3°A±5Ð8^Ð_Ó`Ð`Øˆr    r   )r]   rM   r!   rM   )r"   r#   r$   r%   rs   r   rY   rc   r¦   rh   r§   r   rd   r«   r&   r   r    r   r¥   r¥   2  sˆ   ‡ ññ Ð"BÑC€Dˆ#ÓCÙ7<ØØeñ8€CÐ	4ó ñ "Øð.ñ€FˆMó ñ  Øð)ñ€Dˆ-ó ñ �XÓØóó ó ór    r¥   c                  óˆ   • \ rS rSr% SrS\S'   S\S'   SrS\S	'   S
rS\S'   SrS\S'   Sr	S\S'   S\S'   S\S'   Sr
S\S'   Srg)ÚCellFlagi[  u,  One item a run surfaces for review â€” the error-check record.

Carries full document identity (source, page, table) alongside the item,
so a flag can be traced to its table without reverse attribution from
page numbers. `status` is a registered inspect code; `note` is the
status inspector's one-line account of what the page image shows. Most
flags point at an output cell; a table-level flag (status `header_text_dropped`,
printed text that reached no output cell) has no cell to point at, so
`row` and `col` are None and `text` holds the missing text.
r.   r   r?   r@   NrM   r/   r*   r1   r=   r   r€   rY   rh   r§   r   )r"   r#   r$   r%   rs   rc   r/   r1   r   r€   r§   r&   r   r    r   r®   r®   [  sN   ‡ ñ	ð ƒKØ
ƒIØ"€HˆmÓ"Ø€Eˆ3ƒOØ€CˆÓØ€CˆÓØ
ƒIØƒKØ€Dˆ-Ör    r®   c                óæ  • [        S [         5       5      n/ nU  GHÑ  n[        UR                  =(       d    / 5       H¬  u  pE[        U5       H˜  u  pgUR                  U;   d  M  UR                  [        UR                  =(       d    SUR                  UR                  UR                  =(       d    SUUUR                  UR                  =(       d    SUR                  S9	5        Mš     M®     UR                   HZ  nUR                  [        UR                  =(       d    SUR                  UR                  UR                  =(       d    SUSS95        M\     UR                   H…  n	U	R                  b  M  U	R                   S:w  d  M$  UR                  [        UR                  =(       d    SUR                  UR                  UR                  =(       d    SU	R"                  SS95        M‡     GMÔ     U$ )uÞ   Every corrected cell whose status is registered for inspection, plus
each table's dropped printed text and each footnote marker not tied to a
cell, with document identity attached â€” the run's review queue, ready to
emit.c              3  ó^   #   • U  H#  oR                   (       d  M  UR                  v •  M%     g 7fr   )rˆ   r†   r    s     r   r£   Úcell_flags.<locals>.<genexpr>w  s   é € ÐQÒ.C¨ÇyÅy›f˜aŸfžfÒ.Cùs   ‚-š-r*   )	r   r@   r/   r1   r   r€   rY   rh   r§   r™   )r   r@   r/   r1   rY   rh   Útabler˜   )Ú	frozensetr�   Ú	enumeraterF   rh   Úappendr®   r   r@   r/   r1   rY   r§   rH   r;   r   rƒ   rX   )
ÚtablesÚinspect_codesÚoutÚtÚrr   Úcr‚   ÚfragmentÚmarks
             r   Ú
cell_flagsr¾   r  ss  € ô
 ÑQÕ.CÓQÓQ€MØ€CÜˆÜ × 0Ñ 0× 6°BÖ7‰FˆAÜ$ Sž>‘�Ø—;‘; -Õ/Ø—J‘JÜ Ø#$§8¡8§>¨rØ!"§¡Ø%&§Z¡ZØ"#§'¡'§-¨RØ !Ø !Ø!%§¡Ø#'§;¡;×#4°"Ø!%§¡ñ
öó *ñ 8ð  ŸœˆHØ�J‰JÜØŸ8™8Ÿ> rØŸ™ØŸZ™ZØŸ'™'Ÿ- RØ!Ø0ñö	ñ 'ð ×$Ô$ˆDØ�x‰xÓ D§J¡J°'Õ$9Ø—
‘
ÜØ Ÿx™xŸ~¨2ØŸV™VØ!"§¡ØŸg™gŸm¨Ø!Ÿ[™[Ø9ñö	ô %ñ9 ðP €Jr    c                  óØ   • \ rS rSr% Sr\" SS9rS\S'   \" SSS	9rS
\S'   \" SSS	9r	S
\S'   \" \
SS9rS\S'   \" \
SS9rS\S'   \" \
SS9rS\S'   \" SSS9rS\S'   \" SSS9rS\S'   S rg)!ÚMergedCellBoxi¤  u  A corrected cell built by combining two or more source cells, resolved to
per-source-cell boxes plus their union.

The correction agent reads the Camelot grid inside a printed spreadsheet
coordinate frame and reports each merge's source cells by ADDRESS
(`source_cells`, e.g. ['B2', 'B3']); `source_boxes` holds one box per
address, in the same order â€” the named cell's Camelot-measured box, or None
where the address could not be resolved (bad label, blank cell, or text
that does not appear in the result). `box` is the union of the located
boxes, a coarse envelope over the whole combined cell. All boxes are
normalized 0..1 with the page top-left as origin â€” the same frame as
`som_region`. Every box is Camelot's own measurement; the model only ever
repeats printed labels.
z?The combined cell text, as it appears in the corrected markdownr4   r.   Úresultr   uÉ   0-based row of this cell in the corrected markdown table (header row is 0) â€” the exact address of the cell, since result text alone repeats (e.g. an identical total in the Basic and Diluted EPS rows))rN   r-   r?   r   z;0-based column of this cell in the corrected markdown tabler€   z)The source cell values that were combinedr6   r9   Úsourcesz™The printed coordinate of each combined Camelot cell as the agent read it off the coordinate frame (e.g. ['B2', 'B3']); resolves into cell_grid by lookupÚsource_cellsz\One box per source_cells entry (same order), normalized 0..1 top-left; None where unresolvedz1List[Optional[Tuple[float, float, float, float]]]Úsource_boxesNziUnion of the located source boxes (x1, y1, x2, y2) normalized 0..1, top-left origin; None if none locatedr+   rA   r¦   Únonezºcell_address: every reported source address resolved and text-validated; partial: some resolved (the union box under-covers the combined cell); none: no address reported or none resolvedz*Literal['cell_address', 'partial', 'none']Úgrounded_byr   )r"   r#   r$   r%   rs   r   rÁ   rc   r   r€   r[   rÂ   rÃ   rÄ   r¦   rÆ   r&   r   r    r   rÀ   rÀ   ¤  sÆ   ‡ ññ Ð$eÑf€FˆCÓfÙØð*ñ€Cˆó ñ ˜Ð'dÑe€CˆÓeÙ¨tÐAlÑm€GˆYÓmÙ#ØðVñ€L�)ó ñ GLØØrñG€LÐCó ñ 8=ØØñ8€CÐ	4ó ñ ?DØð(ñ?€KÐ;ö r    rÀ   c                ó<   • [        U 5      R                   SU SU 3$ )zåThe deterministic table ID: '<doc>-p<page>-t<ordinal>'.

Built purely from the table's position, so the same document yields the
same IDs on every run. A split sub-table appends '-s<k>' to its parent's
address at the split site.
z-pz-t)r   Ústem)r   r@   Úordinals      r   Útable_addressrÊ   Ø  s&   € ô �6‹l×ÑÐ   4 &¨¨7¨)Ð4Ð4r    c                ó¤   • U (       d  g[         R                  " [        R                  " U 5      R	                  5       5      R                  5       SS $ )z9First 8 hex characters of sha256 over the raw value grid.r*   Né   )ÚhashlibÚsha256ÚjsonÚdumpsÚencodeÚ	hexdigest)Úcellss    r   Úgrid_fingerprintrÔ   â  s9   € æØÜ�>Š>œ$Ÿ*š* UÓ+×2Ñ2Ó4Ó5×?Ñ?ÓAÀ"À1ÐEÐEr    c                ó*  ^^• SUU4S jjn/ n[        U 5       Hp  u  pgU(       a  U[        U5      :  a  X   O/ nUR                  [        U5       V	V
s/ s H'  u  pš[        X¤" U	[        U5      :  a  X‰   OS5      S9PM)     sn
n	5        Mr     U$ s  sn
n	f )aÚ  Pair a Camelot cell grid with its per-cell geometry into GroundedCells.

`cell_boxes` arrive in Camelot's frame (PDF points, bottom-left origin) and
are converted here to normalized 0..1 top-left, so the grid serializes in
the same frame as every other box on the table. Shaped exactly like
`cells`. Any position `cell_boxes` does not cover (or a None `cell_boxes`)
yields a cell with no box, so the result is safe to build from a candidate
whose geometry was not captured.
c                ó^   >• U b  TS::  d  TS::  a  g U u  pp4UT-  TU-
  T-  UT-  TU-
  T-  4$ )Nr   r   )r¦   Úx1Úy1Úx2Úy2Úpage_hÚpage_ws        €€r   ÚnormÚgrounded_grid.<locals>.normù  sJ   ø€ Ø‰;˜& A›+¨°1«ØØ‰ˆ�Ø�V‘˜f r™k¨VÑ3°R¸&±[À6ÈBÁ;ÐRXÑBXÐYÐYr    N)rY   r¦   )r¦   rA   r!   rA   )r´   Úlenrµ   r¥   )rÓ   Ú
cell_boxesrÜ   rÛ   rÝ   ÚgridÚir   Úbox_rowÚjÚtxts     ``       r   Úgrounded_gridræ   é  s”   ù€ ÷ Zð Zð &(€DÜ˜EÖ"‰ˆÞ#-°!´c¸*³oÓ2E�*’-È2ˆØ�‰ô (¨œnôâ,‘F�Aô  #¨4¸aÄ#ÀgÃ,Ó>N°²
ÐTXÓ+YÔZÙ,òö	
ñ #ð €Kùós   Á.B)r¶   zSequence['ExtractedTable']r!   zList[CellFlag])r   z
str | Pathr@   r?   rÉ   r?   r!   r.   )rÓ   úList[List[str]]r!   r.   )
rÓ   rç   rà   zAOptional[List[List[Optional[Tuple[float, float, float, float]]]]]rÜ   rP   rÛ   rP   r!   zList[List[GroundedCell]]))rs   Ú
__future__r   rÍ   rÏ   Úpathlibr   Útypingr   r   r   r   r	   r
   r   Úpydanticr   r   r   Úquber.agents.classifierr   Úquber.agents.llm_clientr   r   r(   rf   ru   r~   r…   r�   rc   r³   ÚAUTHORIZED_LABELSr©   r¥   r®   r¾   rÀ   rÊ   rÔ   ræ   r   r    r   Ú<module>rï      s™  ðòõ$ #ã Û Ý ß X× XÑ Xç 6Ñ 6å 4Ý /ð ôM�Xó Mó ðMôz�Yô zôzJ�yô JôZ�ô ô2'�Iô 'ôT�ô ñ* ØØ!àkñ	ñ Ø'ØOðCð ñ	ñ Ø&ØRð1ð ñ	ñ ØØ^ðDð ñ	ñ Ø ØPðGð Øñ
ñ Ø!ØKð>ð
 Øññ ØØeðð
 ñ
ñ ØØWðJð
 ñ
ñ Ø"Øað:ð ññ Ø$ØAð.ñ	ñ Ø'ØLð.ð ññ Ø"ØOð(ð Øññ ØØNð.ð ññ Ø!ØVð7ð ñðg_1Ð Ð-ó _ñJ Ò>Ó?Ð áÑEÑ/DÓEÓEÐ ô&�9ô &ôRˆyô ô./ôd1�Iô 1ôh5ôFðØðàQðð ðð ð	ð
 õr    