The first checkpoint: what native parsing can actually prove

For pdf-inspector, a native result is not one yes-or-no answer. It is a bundle of observations about a page: whether the PDF exposes text or image signals, whether the characters can be decoded, whether their positions belong to the visible page, and whether the native representation appears to cover the page's meaning. This checkpoint combines those observations into a practical judgment: continue with native processing, keep a limitation visible, or escalate the page.

Four questions behind one native result

The first question is presence. Does the page contain text-showing operations that an extractor can inspect, or is its visible content mainly images and paths? The detector uses those structural signals to distinguish text-based, scanned, image-based, and mixed documents. That classification is useful because it identifies where native work is likely to pay off and where visual recovery may be needed.

Presence is only the first rung. A page can have text operators and still expose very little meaningful text. A scan may carry a small overlay, and a page with vector-outlined lettering may contain no ordinary text operation for the main words. So the second question is decoding: do the font-local codes map to the intended Unicode characters, or do they produce replacement symbols, control characters, private-use runs, punctuation soup, or other signs of a broken text layer?

The third question is placement. Even correctly decoded characters are not yet a document. They need to land in the right page frame, on the right line, and in the right relationship to neighboring items. The visible page-box contract, rotation handling, and baseline information let downstream consumers decide whether a region contains a word, whether a marker belongs to a sentence, or whether two groups of items are separate columns.

The fourth question is coverage. Did native extraction account for the page's meaningful content, or did it recover only a clean fragment? A page with a full-page scan and a small native label can pass presence and decoding while failing coverage. A page with a table drawn as paths can look complete to a person while offering too little text structure for native extraction. Coverage is the question that prevents “clean” from being mistaken for “complete.”

These questions belong together because each can invalidate a conclusion reached by the previous one. A page with no text fails at presence. A page with text but a broken CMap fails at decoding. A page with good characters but a shifted CropBox frame fails at placement for a region consumer. A page with a valid overlay but a missing image body fails at coverage. The evidence ladder is therefore ordered, but not additive in a simple score: a strong result on one rung cannot erase a failure on another.

classDiagram class PageDecision class PageClassification class PositionedEvidence class TextQuality class LayoutEvidence class OcrReason class NativeOrEscalated PageDecision --> PageClassification : begins with PageDecision --> PositionedEvidence : checks placement PageDecision --> TextQuality : checks decoding PageDecision --> LayoutEvidence : checks coverage clues PageDecision --> OcrReason : records why PageDecision --> NativeOrEscalated : selects outcome PositionedEvidence --> LayoutEvidence : supplies geometry TextQuality --> OcrReason : explains suspicion

A useful consequence follows from this model: the detector's confidence should be read as a routing clue, not as the probability that the final Markdown is correct. The current implementation uses an evenly distributed sample of up to eight pages by default, then performs additional page analysis for routing. Elsewhere in the repository, a summary table describes early-exit scanning as the default.