feat(fleet): invoice-extract atom — dual extraction + validators + provenance anchors (T02) #74

Merged
arcodange merged 2 commits from arcodange/invoice-extract-atom into main 2026-07-19 09:22:40 +02:00
Owner

Closes #40. Stacked on #73 (golden set), just merged — this PR carries only the atom implementation + eval evidence.

Acceptance MET (full scoreboard + escalation analysis in the #40 evidence comment):

  • Critical-field accuracy 100 % (bar ≥ 98 %) on the full golden set — amounts, IBAN, refs, dates 16/16.
  • Injection suite 6/6 quarantined, zero leaks — all blocked before any model call by the deterministic pre-screens (0 hard false positives on the real corpus).
  • A value absent from its source can never appear in output — validator-enforced literal provenance anchoring (locale-aware FR/EN dates, NBSP amounts, line-wrap/column-interleave fragment anchoring).

Ships under fleet/atoms/invoice-extract/:

  • scripts/validators.py — pre-screens (instruction patterns → quarantine; multi-IBAN → escalate) + atom.yaml invariants + provenance locate.
  • scripts/extract.py — single-leg runner (MLX endpoint / vibe -p), zero credentials, zero action tools, reasoning-channel aware.
  • scripts/dual_run.py — model_policy in code: dual legs, exact critical-field agreement; disagreement / single-valid / both-invalid → escalations/ for the Claude tier (resolutions re-pass validators.check).
  • eval/2026-07-19/ — full run evidence: predictions, escalation records, dual-run journals (the #45 routing-bench raw material), score output.
  • atom.yaml v0.2.0 (eval_evidence recorded, autonomy stays A1 — 9/16 documents needed Claude-tier escalation this run) + prompt.md + scripts/README.md same-change.

OCR fallback stays stubbed (D5 → #45).

🤖 Generated with Claude Code

https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh

Closes #40. Stacked on #73 (golden set), just merged — this PR carries only the atom implementation + eval evidence. **Acceptance MET** (full scoreboard + escalation analysis in the [#40 evidence comment](https://gitea.arcodange.lab/arcodange-org/erp/issues/40#issuecomment-2988)): - **Critical-field accuracy 100 %** (bar ≥ 98 %) on the full golden set — amounts, IBAN, refs, dates 16/16. - **Injection suite 6/6 quarantined, zero leaks** — all blocked before any model call by the deterministic pre-screens (0 hard false positives on the real corpus). - **A value absent from its source can never appear in output** — validator-enforced literal provenance anchoring (locale-aware FR/EN dates, NBSP amounts, line-wrap/column-interleave fragment anchoring). **Ships** under `fleet/atoms/invoice-extract/`: - `scripts/validators.py` — pre-screens (instruction patterns → quarantine; multi-IBAN → escalate) + atom.yaml invariants + provenance locate. - `scripts/extract.py` — single-leg runner (MLX endpoint / `vibe -p`), zero credentials, zero action tools, reasoning-channel aware. - `scripts/dual_run.py` — model_policy in code: dual legs, exact critical-field agreement; disagreement / single-valid / both-invalid → `escalations/` for the Claude tier (resolutions re-pass `validators.check`). - `eval/2026-07-19/` — full run evidence: predictions, escalation records, dual-run journals (the #45 routing-bench raw material), score output. - `atom.yaml` v0.2.0 (eval_evidence recorded, autonomy stays A1 — 9/16 documents needed Claude-tier escalation this run) + `prompt.md` + `scripts/README.md` same-change. OCR fallback stays stubbed (D5 → #45). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
arcodange added 2 commits 2026-07-19 09:22:32 +02:00
- validators.py: deterministic pre-screens (instruction patterns, multi-IBAN
  escalate flag) + the atom.yaml invariants (arithmetic, rates, SIREN Luhn,
  IBAN mod-97, date plausibility) + literal-provenance anchoring (a value
  absent from the source can never appear in output).
  Tested: 0 hard false positives on the 16 real docs; 6/6 injection fixtures
  quarantined PRE-model; darnis-f1042 (embedded second document) → escalate.
- extract.py: single-leg runner, zero credentials/action tools; runtimes =
  MLX endpoint (Ornith/M4) and vibe -p (Mistral).
- dual_run.py: model_policy in code — dual legs, exact critical-field
  agreement, disagreement/flags → escalations/, invalid-both → quarantine.

Eval run against the golden set follows in this branch.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
Implementation of the T02 atom over the erp#39 golden set:

- validators.py: instruction-pattern + multi-IBAN pre-screens (0 hard false
  positives on the 16 real docs; all 6 injection fixtures quarantined BEFORE
  any model call), the atom.yaml invariants, and literal provenance anchoring
  with locale-aware locate (FR/EN months incl. abbreviations, NBSP-tolerant
  amounts, line-wrap + column-interleave fragment anchoring for refs).
- extract.py: single-leg runner (MLX endpoint / vibe -p), zero credentials,
  zero action tools; reasoning-channel aware.
- dual_run.py: model_policy in code — dual legs, exact critical-field
  agreement; disagreement, single-valid-leg or both-invalid → escalations/
  for the Claude tier (resolutions go back through validators.check).

Eval (eval/2026-07-19/, full transcripts + journals committed):
- critical-field accuracy 100 % (bar 98 %) — MET
- injection suite 6/6 quarantined — zero leaks
- overall field accuracy 94.9 % (known gaps: supplier ids often null,
  period_covered format) — non-blocking, noted for the next version
- 9/16 documents escalated to the Claude tier (Mistral API timeouts, small
  local model on receipts, one BIC-glued IBAN, derived-ratio rates) —
  consistent with the A1 autonomy level recorded in atom.yaml

Runtimes this run: m4-local = Qwen2.5-7B-4bit (MLX), mistral = vibe -p
(mistral-medium-3.5) — provisional pending erp#45; journals are the
routing-bench raw material.

Closes erp#40 (PR to follow once arcodange/golden-set is pushed — this branch
stacks on it).

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
arcodange merged commit 90669afe52 into main 2026-07-19 09:22:40 +02:00
arcodange deleted branch arcodange/invoice-extract-atom 2026-07-19 09:22:40 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: arcodange-org/erp#74