Skip to main content

Page-denominated document extraction run ledger

Project description

PageLedger — the tallied page

Record, route, and review document extraction — one page at a time.

You OCR'd three thousand archive pages last spring. Which engine did page 341 go through, what did the run cost, which pages were too noisy to trust, and did anyone ever review them? PageLedger is a run ledger for document extraction that keeps those answers on disk: you bring the engine (Tesseract, Docling, Marker, a cloud VLM), it routes pages, enforces page/token/dollar budgets, and writes the evidence as plain files you can grep, cite, and reproduce. No service, no database.

It grew out of a Soviet census digitization project, where "the model returned JSON" was the beginning of the work, not the end. It is built for people with the same problem: digital humanities labs, archives, historians, and anyone who has to defend their methodology months later.

Install

pip install pageledger

Quickstart

OCR a scanned PDF. No config file needed; pdf_ocr uses your locally installed Tesseract and poppler (pageledger doctor checks for both and lists your installed OCR languages):

pageledger run scan.pdf --adapter pdf_ocr --out runs/first
pageledger inspect-run runs/first

runs/first/ now holds the extracted text plus the ledger: a manifest, per-page provenance, quality warnings, word-level OCR confidence, cost evidence, and a review queue. Weak pages are already listed in an executable rerun plan, so escalating just those pages to a stronger engine is one command, and comparing the two runs is another:

pageledger rerun runs/first --config stronger.yml --out runs/second
pageledger compare-runs runs/first runs/second

Other first moves:

pageledger run report.pdf --adapter pdf_text --out runs/text   # born-digital PDF (pip install "pageledger[pdf]")
pageledger run scan.pdf --adapter pdf_ocr --out runs/sample --pages "1-10"   # sample before committing
pageledger run scan.pdf --config pageledger.yml --out runs/tuned --dry-run   # inspect routing, spend nothing
pageledger inspect-run runs/first --csv > pages.csv            # triage in a spreadsheet

Non-English documents: set lang and dpi in the config (pageledger init-config --adapter pdf_ocr writes one with both knobs visible). See docs/multilingual-ocr.md for a worked Cyrillic example, including what the signals catch on an 1850 scan.

How a run works

flowchart TD
    A["inputs (text / PDF)"] --> B["paginate<br/>(form-feed or PDF pages)"]
    B --> C["route pages<br/>route-map.yml"]
    C --> D{"budget preflight<br/>max_pages"}
    D -- over cap --> X["refuse: nothing written"]
    D -- ok --> E["extract page via adapter<br/>(retry + backoff)"]
    E --> F["quality signals<br/>quality.jsonl"]
    E --> G["provenance.jsonl<br/>+ cost.json (cost_basis)"]
    E --> H{"budget mid-run<br/>pages / tokens / USD"}
    H -- over cap --> Y["halt: manifest status=failed,<br/>partial artifacts consistent"]
    H -- ok --> E
    F -- warnings --> I["review queue<br/>audit.json / audit.md"]
    I --> J["rerun-manifest.yml"]
    J -- "pageledger rerun<br/>(stronger adapter)" --> E
    G --> K["pageledger compare-runs<br/>(parent vs rerun)"]

Every box on the right is a plain file in the run directory.

What's in the box

  • Three built-in adapters (text, pdf_text, pdf_ocr) and a thin protocol for wrapping anything else, from OCRmyPDF to a cloud VLM.
  • Quality signals per page: shape heuristics, Tesseract word confidence with a low_confidence warning, and pre-1918 Russian orthography detection that tells a historian why the OCR degraded.
  • Budgets denominated in pages, the one unit every backend shares, with tokens and dollars on top when they exist.
  • Cost records that name their basis, so a derived estimate is never mistaken for provider-billed spend.
  • Page-scoped reruns with lineage, cross-run diffs, CSV export, and a doctor command for environment diagnostics.
  • JSON Schemas for every artifact, enforced in CI, and an AGENTS.md so AI coding agents can operate the tool and validate their own output.

The alpha routes every page to one configured action; automatic page classification, schema alignment, and audit grading are documented design targets, not shipped features. The full honest-scope list is in docs/capabilities-and-limits.md.

Tested on

Real documents, with walkthroughs: a 107-page declassified JFK-files scan (free Tesseract pass, then a free local-LLM cleanup tier, then a paid cloud VLM on the pages that needed it), a modern 259-page Russian report, and an 1850 military-statistical review in pre-reform orthography that the quality signals flagged page by page. Synthetic stress runs cover 5,000 pages at ~2,100 pages/sec. Details in docs/capabilities-and-limits.md.

Documentation

docs/cli.md All six commands, flags, and config keys
docs/artifacts.md What each file in a run directory answers
docs/capabilities-and-limits.md What works, what you supply, what is design
docs/ocr-options.md Choosing local, cloud, or hybrid extraction
docs/multilingual-ocr.md Non-English and historical documents
docs/examples/jfk-scanned-archive.md Worked example: scan → flags → rerun → compare
docs/adapter-protocol.md Wrapping your own OCR/VLM engine
docs/design.md Why pages, design principles, and what comes next
docs/comparison.md Positioning against the 2026 extraction ecosystem
schemas/ JSON Schemas, the machine-readable artifact contract

Citing

Software citation lives in CITATION.cff. PageLedger keeps software and source-data citations separate; dataset_citation in the config records the latter into every manifest.

MIT license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pageledger-0.1.2.tar.gz (92.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pageledger-0.1.2-py3-none-any.whl (37.5 kB view details)

Uploaded Python 3

File details

Details for the file pageledger-0.1.2.tar.gz.

File metadata

  • Download URL: pageledger-0.1.2.tar.gz
  • Upload date:
  • Size: 92.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pageledger-0.1.2.tar.gz
Algorithm Hash digest
SHA256 4da51f6fb5765857026e67d7ff993344cf59bf548051d607997113ce5fc816cb
MD5 a7e8c22a44606cb962a3d54520411113
BLAKE2b-256 72fb03778e832d45f112596ffecc23b1a89774116d5751712358db84d48df4da

See more details on using hashes here.

Provenance

The following attestation bundles were made for pageledger-0.1.2.tar.gz:

Publisher: publish.yml on peterbussch/pageledger

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pageledger-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: pageledger-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 37.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pageledger-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 908cafda17428f0a48a8706c3efbf14320439a29c822481aa2adb9d6f365d200
MD5 33414b35c7e222417be46ffa6cac58a8
BLAKE2b-256 dc7953d4bf268e6338b5c96dabd6cd0cfef1108a8fdd44255a9d415ad877fc3a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pageledger-0.1.2-py3-none-any.whl:

Publisher: publish.yml on peterbussch/pageledger

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page