Skip to content

v0.0.9 — Audit Pass

Choose a tag to compare

@sebastienrousseau sebastienrousseau released this 11 Jun 23:07
· 88 commits to main since this release
v0.0.9
1b54034

Audit pass. Addresses the three Critical findings and all eight quick wins from the deep audit, adds a hybrid trust & correctness slice, an examples/docs regression suite, and an LLM-accuracy eval harness. Drains all open Dependabot version-bump PRs and resolves all open security alerts. 818 tests, 100% line+branch coverage enforced in CI, full ubuntu/macOS/Windows matrix on Python 3.10–3.14.

New features

1. Page provenance for every extracted row

result = smart_ingest("statement.pdf")
for tx in result.transactions:
    print(tx.amount, tx.description, "page", tx.source_page)

extract_text_pages() keeps per-page text instead of one joined blob, and smart_ingest attributes each text-LLM row back to the page containing its description; vision rows inherit the page from their bounding box. Untraceable rows stay None — an honest signal, never a guess. Surfaced in the ingest CSV (source_page column) and the review UI.

2. Cross-statement continuity check

from bankstatementparser.hybrid import scan_and_ingest

batch = scan_and_ingest("statements/2026/")
if batch.continuity and batch.continuity.breaks:
    for b in batch.continuity.breaks:
        print(f"{b.previous_label} closed at {b.previous_closing}, "
              f"{b.next_label} opened at {b.next_opening} (gap {b.gap})")

The closing balance of statement N must equal the opening of N+1 — the Golden Rule extended across a folder of monthly statements. A missing month, duplicated export, or hallucinated balance shows up as a ContinuityBreak.

3. Confidence-driven review: --review-below

bankstatementparser --type review --input result.json --review-below 0.8

Per-row extraction confidence is now acted on, not just displayed: low-confidence rows are routed into the interactive review walk even when statement-level verification passed. Review mode also re-runs the Golden Rule after every accept/edit/delete and appends a reverify audit entry — no more stale verdicts.

4. French & Spanish CSV headers on the deterministic path

Date opération, Libellé, Montant, Solde, Devise, Fecha, Concepto, Importe, Saldo, Divisa, … now parse deterministically — no LLM fallthrough. Header normalization folds accents (NFKD), so Débit/Crédit/Référence resolve through the existing English synonyms.

5. LLM-accuracy eval harness (CI, non-blocking)

python scripts/run_llm_eval.py --mock              # harness self-check
python scripts/run_llm_eval.py --model ollama/llama3 --min-f1 0.9

A pure scoring module (bankstatementparser.hybrid.evaluation) compares extractions against ground-truth cases and produces deterministic precision/recall/F1 plus per-field accuracies. CI blocks on the mock self-check; the real-model eval runs non-blocking, gated on the BSP_EVAL_MODEL repo variable. Every prompt or model tweak is no longer a silent gamble.

6. Examples & docs regression suite

Every shipped example script (including the shell walkthroughs) runs end-to-end as a subprocess in CI, and every fenced code block in README/FAQ/docs is executed against repository fixtures or import-verified. It immediately caught a real bug: --type camt console output crashed on real statements — fixed.

Breaking changes

Per SemVer, anything may change while the version is 0.y.z. Migration notes for each item are in the CHANGELOG.

  • Pain001Parser.get_summary() raises Pain001ParseError instead of returning an error dict; the error key is gone from SummaryRecord.
  • Garbled or missing amounts raise instead of silently becoming 0.0Decimal end-to-end for all money fields.
  • openpyxl moved to the new [excel] extra; CAMT streaming no longer defaults transaction currency to "".

Correctness & security

  • REST API safety floor: upload size cap, suffix allow-list, generic 422 with UUID correlation id.
  • value_date is no longer silently copied from booking_date by the LLM extractor.
  • CAMT recovery-mode parsing is opt-in; the strict lxml default rejects entity-expansion attacks at parse time.
  • Vision rows correctly labelled source_method="vision"; multi-currency statements no longer report a false DISCREPANCY.
  • All 20 open Dependabot version-bump PRs drained, all 18 security alerts resolved.

Install

pip install bankstatementparser==0.0.9
pip install 'bankstatementparser[hybrid-vision]'   # LLM + vision extras

Full changelog: v0.0.8...v0.0.9