Doc Processor
Reads invoice PDFs, checks that the numbers add up, and writes clean rows to Google Sheets. Anything that doesn't reconcile is quarantined and flagged on Telegram instead of written.
Built and verified · recorded run, offline test suite, and full source below.
The problem
Somebody retyping invoices into a spreadsheet makes one mistake in maybe fifty rows, and nobody finds it until month-end. The goal is not extraction for its own sake but extraction with checks loud enough that a bad row gets caught the day it arrives.
Pipeline architecture
Each PDF goes through text extraction, then a structured-output pass that maps the fields to a fixed schema. Rows are validated against range and arithmetic checks before anything is written. Valid rows append to a Sheet; failures are quarantined with the source page attached and a Telegram message explaining what didn't add up.
Recorded run
Recorded live in a real terminal: the offline test suite, then ./scripts/demo.sh — four clean invoices processed, and the deliberately broken fifth quarantined with the failing math shown.


Key decisions
Validation before writing, every time
A row only reaches the Sheet after its totals reconcile and its fields pass range checks. Extraction confidence is never taken on faith.
Sample documents ship with the repo
Five synthetic sample PDFs with expected outputs let anyone verify the accuracy claims with one command, instead of trusting a screenshot.
Alerts instead of dashboards
Anomalies arrive as a Telegram message the moment they happen. The dashboard is for reviewing history, not for finding out that something broke.
Guardrails
- Originals are never modified; every output is a new file.
- Sample documents are synthetic, so no real data ever enters the repo.
- Every extracted row links back to its source page.
Verification
Targets cutting manual entry time on the sample documents. Verified: 100% field accuracy on the four clean samples (116/116 fields), the deliberately broken fifth quarantined by the math checks, every written row traceable to its source page.