fix(email-ingest): extraction testable et pinnée au golden set + adc-008 #83

Merged
arcodange merged 1 commits from arcodange/prod-apply into main 2026-08-13 10:48:00 +02:00
Owner

L'extraction de champs vivait dans un heredoc à l'intérieur d'email-inspect.sh : impossible à exécuter isolément, donc jamais mesurée, donc fausse sans que personne puisse le voir. Sur la facture Darnis F1048 elle renvoyait le numéro de TVA d'Arcodange comme référence de facture, et aucune date.

Ce qui lande

  • extract_fields.py — l'extraction sort du shell et devient un module.
  • test_extract.py — régression contre les 16 factures hand-vérifiées de fleet/golden/invoice-extract/. Score par champ, et une valeur fausse pèse plus qu'une valeur absente : un humain recopie ce qui s'affiche.
Champ Avant Après
Référence 62,5 % · 1 fausse 75 % · 0 fausse
Date 62,5 % · 2 fausses 75 % · 0 fausse
Total HT 68,8 % 75 % · 0 fausse
Total TTC 81,2 % · 1 fausse 93,8 % · 0 fausse

Valeurs fausses : 4 → 0.

Cinq bugs réels, dont trois invisibles sans test

  • est U+00BA (ordinal masculin), pas le signe degré. La classe [°o] le rate, le motif principal échoue, et le repli attrape le premier jeton ref-shaped du document — très souvent un numéro de TVA.
  • Le filtre anti-TVA rejetait FR73261832, qui est la vraie référence OVH : un numéro FR fait exactement 11 caractères après le préfixe.
  • « Montant total (HT) » était lu comme un TTC.
  • Une référence coupée par la colonne (06-01-26- / payment-366753) était renvoyée amputée : le recollage doit précéder le scan, sinon la queue seule est trouvée en premier.
  • Un \b après ne peut jamais matcher en fin de ligne (€ n'est pas un caractère de mot) — la TVA n'était jamais extraite.

adc-008 — date d'enregistrement d'une facture fournisseur

Directive opérateur formalisée : une facture fournisseur s'enregistre à sa date, même future, tant que l'exercice (année civile) ne bascule pas. Le document fait foi ; altérer sa date ferait diverger l'écriture de sa pièce justificative (CGI art. 289 VII). Registre validé : 8 règles, 8 ADC, 0 erreur.

Scope corrigé

1232 (factures fournisseur) ajouté à prod-write — oubli initial, révélé par un 403 en production sur F1048. Le pipeline s'est arrêté sans rien écrire, ce qui est le comportement voulu.

Appliqué en production via le pipeline gated : FAF2026014 (Darnis F1048), 218,50 HT + 43,70 TVA = 262,20 TTC, validée, non réglée.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh

L'extraction de champs vivait dans un **heredoc à l'intérieur d'`email-inspect.sh`** : impossible à exécuter isolément, donc jamais mesurée, donc fausse sans que personne puisse le voir. Sur la facture Darnis F1048 elle renvoyait **le numéro de TVA d'Arcodange comme référence de facture**, et aucune date. ## Ce qui lande - **`extract_fields.py`** — l'extraction sort du shell et devient un module. - **`test_extract.py`** — régression contre les **16 factures hand-vérifiées** de `fleet/golden/invoice-extract/`. Score par champ, et une valeur **fausse** pèse plus qu'une valeur absente : un humain recopie ce qui s'affiche. | Champ | Avant | Après | |---|---|---| | Référence | 62,5 % · 1 fausse | **75 % · 0 fausse** | | Date | 62,5 % · 2 fausses | **75 % · 0 fausse** | | Total HT | 68,8 % | **75 % · 0 fausse** | | Total TTC | 81,2 % · 1 fausse | **93,8 % · 0 fausse** | **Valeurs fausses : 4 → 0.** ## Cinq bugs réels, dont trois invisibles sans test - **`Nº` est U+00BA** (ordinal masculin), pas le signe degré. La classe `[°o]` le rate, le motif principal échoue, et le repli attrape le premier jeton ref-shaped du document — très souvent un numéro de TVA. - Le filtre anti-TVA rejetait **`FR73261832`**, qui est la vraie référence OVH : un numéro FR fait exactement 11 caractères après le préfixe. - « Montant total (HT) » était lu comme un **TTC**. - Une référence coupée par la colonne (`06-01-26-` / `payment-366753`) était renvoyée **amputée** : le recollage doit précéder le scan, sinon la queue seule est trouvée en premier. - Un **`\b` après `€`** ne peut jamais matcher en fin de ligne (€ n'est pas un caractère de mot) — la TVA n'était jamais extraite. ## adc-008 — date d'enregistrement d'une facture fournisseur Directive opérateur formalisée : une facture fournisseur s'enregistre **à sa date**, même future, **tant que l'exercice (année civile) ne bascule pas**. Le document fait foi ; altérer sa date ferait diverger l'écriture de sa pièce justificative (CGI art. 289 VII). Registre validé : 8 règles, 8 ADC, 0 erreur. ## Scope corrigé `1232` (factures fournisseur) ajouté à `prod-write` — oubli initial, révélé par un **403 en production** sur F1048. Le pipeline s'est arrêté **sans rien écrire**, ce qui est le comportement voulu. Appliqué en production via le pipeline gated : **`FAF2026014`** (Darnis F1048), 218,50 HT + 43,70 TVA = 262,20 TTC, validée, non réglée. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
arcodange added 1 commit 2026-08-13 10:47:50 +02:00
L'extraction de champs vivait dans un heredoc à l'intérieur d'email-inspect.sh :
impossible à exécuter isolément, donc jamais mesurée, donc fausse sans que
personne puisse le voir. Sur la facture Darnis F1048 elle renvoyait le numéro de
TVA d'Arcodange comme référence de facture, et aucune date.

- extract_fields.py : l'extraction sort du shell et devient un module.
- test_extract.py : régression contre les 16 factures hand-vérifiées de
  fleet/golden/invoice-extract/. Score par champ, et une valeur FAUSSE pèse plus
  qu'une valeur absente — un humain recopie ce qui s'affiche.

Valeurs fausses : 4 → 0. Exactitude ref 62,5 → 75 %, date 62,5 → 75 %,
HT 68,8 → 75 %, TTC 81,2 → 93,8 %.

Cinq bugs réels, dont trois invisibles sans test :
- « Nº » sur les factures françaises est U+00BA (ordinal masculin), pas le signe
  degré. La classe [°o] le rate, le motif principal échoue, et le repli attrape
  le premier jeton ref-shaped du document — très souvent un numéro de TVA.
- Le filtre anti-TVA rejetait « FR73261832 », qui est la vraie référence OVH : un
  numéro FR fait exactement 11 caractères après le préfixe.
- « Montant total (HT) » était lu comme un TTC.
- Une référence coupée par la colonne (« 06-01-26- » / « payment-366753 ») était
  renvoyée amputée : le recollage doit précéder le scan, sinon la queue seule est
  trouvée en premier.
- Un `\b` après `€` ne peut jamais matcher en fin de ligne (€ n'est pas un
  caractère de mot) — la TVA n'était jamais extraite.

adc-008 : une facture fournisseur s'enregistre à SA date, même future, tant que
l'exercice (année civile) ne bascule pas. Le document fait foi ; altérer sa date
ferait diverger l'écriture de sa pièce justificative (CGI art. 289 VII).
Registre validé : 8 règles, 8 ADC, 0 erreur.

scopes.ts : 1232 (factures fournisseur) ajouté à prod-write — oubli initial,
révélé par un 403 en production sur F1048. Le pipeline s'est arrêté sans écrire.

Appliqué en production via le pipeline gated : FAF2026014 (Darnis F1048),
218,50 HT + 43,70 TVA = 262,20 TTC, validée, non réglée.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
arcodange merged commit 3ffa71ca12 into main 2026-08-13 10:48:00 +02:00
arcodange deleted branch arcodange/prod-apply 2026-08-13 10:48:02 +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#83