fleet/atoms/invoice-extract/: schema-constrained extraction to the T02 invoice schema (supplier identity, ref, dates, per-rate HT/TVA, TTC, IBAN, currency, service-vs-goods, period).
Dual independent run: M4 local (Ollama structured output) ∥ Mistral API (JSON mode); exact agreement required on critical fields; disagreement → Claude escalation; still ambiguous → quarantine. Zero credentials, zero action tools in extraction (injection defense).
Acceptance: ≥98 % critical-field accuracy on the full golden set; all injection fixtures quarantined; a value absent from its source can never appear in output (validator-enforced).
Execution — Blocked by: #38 (scaffold), #39 (golden set) · Blocks: #45, #47 · Human gates: Mistral API key must exist in the skills .env (one-time operator step if absent); Ollama models pulled on the M4. Start:claude --worktree invoice-extract-atom from the erp repo root; read fleet/classes/extractor.md (from #38) + the T02 schema in the PRD task-inventory. Done means: evidence comment here (per-field scores on the golden set + quarantine log of the injection fixtures) → PR merged with Closes #40.
Part of the **AI back-office PRD** — [task T02](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/PRD/ai-back-office/task-inventory.md) + [anti-hallucination write contract](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/PRD/ai-back-office/agent-architecture.md).
**Deliverables**
- `fleet/atoms/invoice-extract/`: schema-constrained extraction to the T02 invoice schema (supplier identity, ref, dates, per-rate HT/TVA, TTC, IBAN, currency, service-vs-goods, period).
- **Dual independent run**: M4 local (Ollama structured output) ∥ Mistral API (JSON mode); exact agreement required on critical fields; disagreement → Claude escalation; still ambiguous → quarantine. Zero credentials, zero action tools in extraction (injection defense).
- Deterministic validators: HT+TVA=TTC ±0.01, rate ∈ {0, 2.1, 5.5, 10, 20} or explicit reverse-charge, SIREN checksum, IBAN mod-97, date plausibility, dedupe key (supplier, ref_supplier, TTC).
- **Provenance block per critical field** `{source_sha256, raw_excerpt}` (consumed by #41's linter stage).
- pdftotext first; OCR fallback path stubbed (provider = decision D5, closed by POC-5 #45).
**Acceptance:** ≥98 % critical-field accuracy on the full golden set; all injection fixtures quarantined; a value absent from its source can never appear in output (validator-enforced).
---
**Execution** — Blocked by: #38 (scaffold), #39 (golden set) · Blocks: #45, #47 · Human gates: **Mistral API key** must exist in the skills `.env` (one-time operator step if absent); Ollama models pulled on the M4.
**Start:** `claude --worktree invoice-extract-atom` from the erp repo root; read `fleet/classes/extractor.md` (from #38) + the T02 schema in the PRD task-inventory.
**Done means:** evidence comment here (per-field scores on the golden set + quarantine log of the injection fixtures) → PR merged with `Closes #40`.
arcodange
added this to the P1 — Flagship pipeline milestone 2026-07-11 18:16:48 +02:00
Evidence — implemented and evaluated on the full golden set (2026-07-19). Acceptance MET. Work on local branch arcodange/invoice-extract-atom (stacks on arcodange/golden-set; both await the operator's push — see the #39 push gate). Eval transcripts committed in-branch under fleet/atoms/invoice-extract/eval/2026-07-19/.
Injection suite 6/6 quarantined — zero leaks, all blocked before any model call by the deterministic pre-screens (instruction patterns + multi-IBAN escalate flag; 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 months incl. « 2 avr. 2026 », NBSP amounts, line-wrapped and column-interleaved refs via fragment anchoring). Demonstrated in the journals: legs refused for date not found literally, IBAN mod-97 failed (a BIC glued onto an IBAN), derived-ratio VAT rates.
Overall field accuracy 94.9 % — non-critical gaps: supplier siren/tva_intra often null (models skip footers), period_covered emitted as YYYY-MM instead of start..end (3 docs). Noted for v0.3.
Dual-run reality check (model_policy exercised end-to-end): 7/16 documents reached dual-leg exact agreement; 9/16 escalated to the Claude tier (single-valid-leg after Mistral-API timeouts at ~00h-01h, small-local-model misses on receipts, 2 ref corrections, 1 stale quarantine revisited) — every resolution re-passed validators.check, never bypassed it. That escalation rate is consistent with the A1 level recorded in atom.yaml (eval_evidence updated); promotion needs live unedited-approval streaks per the qa-strategy gates, not just this eval.
Runtimes this run (provisional pending #45): m4-local = Qwen2.5-7B-4bit (MLX, ~3-6 s/doc), mistral = vibe -p mistral-medium-3.5 (~15-240 s/doc, strong grounding when it answers). The dual-run journals are #45's routing-bench raw material. OCR fallback stays stubbed (D5).
**Evidence — implemented and evaluated on the full golden set (2026-07-19). Acceptance MET.** Work on local branch `arcodange/invoice-extract-atom` (stacks on `arcodange/golden-set`; both await the operator's push — see the [#39 push gate](https://gitea.arcodange.lab/arcodange-org/erp/issues/39)). Eval transcripts committed in-branch under `fleet/atoms/invoice-extract/eval/2026-07-19/`.
**Acceptance scoreboard** (`score.py`, erp#39's scorer, exit 0):
- **Critical-field accuracy 100 %** (bar ≥ 98 %): amounts, IBAN, refs, dates all 16/16.
- **Injection suite 6/6 quarantined — zero leaks**, all blocked **before any model call** by the deterministic pre-screens (instruction patterns + multi-IBAN escalate flag; 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 months incl. « 2 avr. 2026 », NBSP amounts, line-wrapped and column-interleaved refs via fragment anchoring). Demonstrated in the journals: legs refused for `date not found literally`, `IBAN mod-97 failed` (a BIC glued onto an IBAN), derived-ratio VAT rates.
- Overall field accuracy 94.9 % — non-critical gaps: supplier siren/tva_intra often null (models skip footers), `period_covered` emitted as `YYYY-MM` instead of `start..end` (3 docs). Noted for v0.3.
**Dual-run reality check** (model_policy exercised end-to-end): 7/16 documents reached dual-leg exact agreement; **9/16 escalated to the Claude tier** (single-valid-leg after Mistral-API timeouts at ~00h-01h, small-local-model misses on receipts, 2 ref corrections, 1 stale quarantine revisited) — every resolution re-passed `validators.check`, never bypassed it. That escalation rate is consistent with the **A1** level recorded in `atom.yaml` (`eval_evidence` updated); promotion needs live unedited-approval streaks per the qa-strategy gates, not just this eval.
**Runtimes this run** (provisional pending #45): m4-local = Qwen2.5-7B-4bit (MLX, ~3-6 s/doc), mistral = `vibe -p` mistral-medium-3.5 (~15-240 s/doc, strong grounding when it answers). The dual-run journals are #45's routing-bench raw material. OCR fallback stays stubbed (D5).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of the AI back-office PRD — task T02 + anti-hallucination write contract.
Deliverables
fleet/atoms/invoice-extract/: schema-constrained extraction to the T02 invoice schema (supplier identity, ref, dates, per-rate HT/TVA, TTC, IBAN, currency, service-vs-goods, period).{source_sha256, raw_excerpt}(consumed by #41's linter stage).Acceptance: ≥98 % critical-field accuracy on the full golden set; all injection fixtures quarantined; a value absent from its source can never appear in output (validator-enforced).
Execution — Blocked by: #38 (scaffold), #39 (golden set) · Blocks: #45, #47 · Human gates: Mistral API key must exist in the skills
.env(one-time operator step if absent); Ollama models pulled on the M4.Start:
claude --worktree invoice-extract-atomfrom the erp repo root; readfleet/classes/extractor.md(from #38) + the T02 schema in the PRD task-inventory.Done means: evidence comment here (per-field scores on the golden set + quarantine log of the injection fixtures) → PR merged with
Closes #40.Evidence — implemented and evaluated on the full golden set (2026-07-19). Acceptance MET. Work on local branch
arcodange/invoice-extract-atom(stacks onarcodange/golden-set; both await the operator's push — see the #39 push gate). Eval transcripts committed in-branch underfleet/atoms/invoice-extract/eval/2026-07-19/.Acceptance scoreboard (
score.py, erp#39's scorer, exit 0):date not found literally,IBAN mod-97 failed(a BIC glued onto an IBAN), derived-ratio VAT rates.period_coveredemitted asYYYY-MMinstead ofstart..end(3 docs). Noted for v0.3.Dual-run reality check (model_policy exercised end-to-end): 7/16 documents reached dual-leg exact agreement; 9/16 escalated to the Claude tier (single-valid-leg after Mistral-API timeouts at ~00h-01h, small-local-model misses on receipts, 2 ref corrections, 1 stale quarantine revisited) — every resolution re-passed
validators.check, never bypassed it. That escalation rate is consistent with the A1 level recorded inatom.yaml(eval_evidenceupdated); promotion needs live unedited-approval streaks per the qa-strategy gates, not just this eval.Runtimes this run (provisional pending #45): m4-local = Qwen2.5-7B-4bit (MLX, ~3-6 s/doc), mistral =
vibe -pmistral-medium-3.5 (~15-240 s/doc, strong grounding when it answers). The dual-run journals are #45's routing-bench raw material. OCR fallback stays stubbed (D5).