diff --git a/docs/superpowers/plans/2026-06-25-gui-v6-beta-plan-1b-gating-coeur.md b/docs/superpowers/plans/2026-06-25-gui-v6-beta-plan-1b-gating-coeur.md index 0b4e200..e4a254e 100644 --- a/docs/superpowers/plans/2026-06-25-gui-v6-beta-plan-1b-gating-coeur.md +++ b/docs/superpowers/plans/2026-06-25-gui-v6-beta-plan-1b-gating-coeur.md @@ -153,7 +153,7 @@ Add `disabled_kinds: set = None` kwarg to `process_pdf` (~l.4973). After `cfg = - [ ] **Step 1 — Failing test.** Refactor inline patterns into `_build_residual_patterns(disabled_kinds)` and test : labels include {NIR,EMAIL,IBAN,TEL} when none disabled ; NIR absent when `{"NIR"}` (EMAIL/IBAN restent) ; TEL absent when `{"TEL"}` ; **et** quand NIR disabled, le pattern TEL ne matche PAS un NIR en clair (test : `_build_residual_patterns({"NIR"})` appliqué à « 1 85 05 74 123 456 78 » → 0 match). - [ ] **Step 2 — Run, expect FAIL.** -- [ ] **Step 3 — Implement.** `_build_residual_patterns(disabled)` : EMAIL+IBAN toujours ; NIR si `"NIR" not in disabled` ; TEL si `"TEL" not in disabled` ; **quand NIR disabled, le pattern TEL doit exclure les spans de type NIR** (13-15 chiffres groupés) — soit en pré-masquant les spans NIR-like, soit en bornant le pattern TEL. Gate la branche INSEE-names (~l.5470) sous `"NOM" not in disabled`. Brancher `cfg.get("disabled_kinds")`. **Seuil adaptatif (suggestion re-revue Qwen)** : `SEUIL_RESCAN_RESIDUEL=0` est trop strict quand des catégories sont décochées (un fragment de 8 chiffres peut matcher le pattern TEL résiduel → quarantaine injustifiée) ; passer le seuil à **1 si `disabled_kinds` non vide**, 0 sinon (préserve la rigueur quand tout est activé). +- [ ] **Step 3 — Implement.** `_build_residual_patterns(disabled)` : EMAIL+IBAN toujours ; NIR si `"NIR" not in disabled` ; TEL si `"TEL" not in disabled`. **Quand NIR disabled, pré-masquer les spans NIR-like (13-15 chiffres groupés) UNIQUEMENT pour le scan TEL** (PAS EMAIL/IBAN/NIR — sinon on efface la queue numérique d'un IBAN et on affaiblit son backstop toujours-actif). Gate la branche INSEE-names (~l.5470) sous `"NOM" not in disabled`. Brancher `cfg.get("disabled_kinds")`. **Seuil résiduel : rester strict à `SEUIL_RESCAN_RESIDUEL` (0), INCONDITIONNEL.** Un seuil relâché (1 quand des catégories décochées, suggestion initiale Qwen) affaiblirait globalement les backstops toujours-actifs EMAIL/IBAN (un vrai email fuité ne quarantainerait plus). La contamination croisée (donnée d'une catégorie décochée matchant un pattern actif) **n'apparaît qu'après Task 3** (avant, le texte masque encore tout) et y est traitée **span-précisément** (cf. Task 3), seuil restant 0. **[Divergence assumée vs suggestion Qwen seuil adaptatif — corrigée en revue qualité Claude, à confirmer en re-revue Qwen.]** - [ ] **Step 4 — Run, expect PASS.** - [ ] **Step 5 — Non-régression :** `.venv/bin/pytest tests/unit/ -q`. - [ ] **Step 6 — Commit :** `git commit -m "feat(core): coordination quarantaine résiduelle NIR/TEL décochés (P1-2/F-4)"` @@ -173,6 +173,7 @@ Add `disabled_kinds: set = None` kwarg to `process_pdf` (~l.4973). After `cfg = - selective_rescan (~4159) : DATE_NAISSANCE(4203), ADRESSE(4205-4207), ETAB(4229-4251), ADHERENT(4200-4201), TEL(4191-4193), NIR(4187-4188). - Phase-0 multiline : DATE_NAISSANCE(~3014), NIR(~3034). - **Propagation globale step 4e (F-2 #1, F-4)** : boucle `_CRITICAL_PII_TYPES`/`{kind}_GLOBAL` (~5279-5286) — ne pas propager une catégorie désactivée. +- **Résiduel post-gating (coordination Task 2, F-4)** : une fois une catégorie laissée EN CLAIR dans le texte, **pré-masquer ses spans avant le scan résiduel de quarantaine** (depuis les hits filtrés de l'audit Task 1 — les capturer au moment du filtre, ou recomposer) pour éviter une quarantaine injustifiée. **Le seuil résiduel reste 0** (backstops EMAIL/IBAN/NIR/TEL stricts — un vrai leak quarantaine toujours). C'est le pendant texte du premask NIR⇄TEL de Task 2, généralisé aux catégories décochées. - **VLM (F-2 #2, CRITIQUE scanné)** : `_apply_vlm_on_scanned_pdf` (~4898-4965) — masque dans texte+raster indépendamment ; gate par `_category_of(vlm_kind)`. - Post-mask cleanups (F-2 #6) : NOM orphan (~5098/5137/5148), TEL fragment (~5118/5128). @@ -212,7 +213,7 @@ Add `disabled_kinds: set = None` kwarg to `process_pdf` (~l.4973). After `cfg = - **F-1** : `_category_of` dérivé (VLM_CATEGORY_MAP + EDS_LABEL_MAP + suffixe _GLOBAL) + **test anti-dérive** → couvre les 15 kinds de Qwen ET ceux qu'il a ratés. Default-deny. **CODE_POSTAL→ADRESSE** (décision Dom 2026-06-26). ✓ - **F-2** : Task 3 liste consolidée incl. propagation globale, VLM, Trackare, structured/critical, cleanups. ✓ - **F-3** : Task 4 adresse gaté + images/barcodes documentés conservateurs + SKIP_KINDS vérifiés. ✓ -- **F-4** : Task 2 coordonne résiduel + **exclusion NIR-like du pattern TEL** + gate selective_rescan/propagation (Task 3). ✓ +- **F-4** : Task 2 coordonne résiduel + **exclusion NIR-like du scan TEL UNIQUEMENT** (backstop IBAN préservé) + **seuil résiduel strict 0** (pas de relâchement aveugle des backstops EMAIL/IBAN) + gate selective_rescan/propagation (Task 3). Contamination croisée des catégories décochées traitée span-précisément en Task 3. ✓ - **F-5** : Task 3 impose le gating NER **intra-boucle** (per-hit), jamais per-function. ✓ - **Risque résiduel** : un site oublié ⇒ catégorie reste masquée (test rouge), JAMAIS fuite croisée (default-deny + filtre par catégorie). Livrable PDF garanti par T1 seul. - **Décision Dom 2026-06-26 (TRANCHÉE)** : CODE_POSTAL (CP/ZIP) → catégorie ADRESSE (suit le toggle « Adresses »). VILLE reste toujours masquée (hors décision).