fix(detect): labels structurels Nom de jeune fille / Prénom / Ville (#7 #8 #9)

Trois nouveaux patterns cœur dans `_mask_structured_line` pour des
labels génériques qui n'étaient pas couverts par le pipeline kv_value
(le split key:value laissait fuir la valeur quand le label dépassait
les patterns existants `RE_EXTRACT_NOM_NAISSANCE`, `RE_EXTRACT_PRENOM`,
`RE_EXTRACT_VILLE_RESIDENCE`).

`RE_LABEL_NOM_VARIANTES` capture :
- Nom de jeune fille / de famille / de naissance(.)
- Nom d'usage / Nom marital / Nom marié

`RE_LABEL_PRENOM` capture :
- Prénom : / Prénoms : / Prénom de naissance / utilisé(e) / usuel
- Capture jusqu'à fin de ligne pour les énumérations virgulées
  (Prénoms : Sabine, Marie → tout masqué).

`RE_LABEL_VILLE` capture :
- Ville : / Ville de résidence : / Ville de naissance :
- Capture jusqu'à fin de ligne (gère "Saint-Jean-de-Luz",
  "Saint-Denis (974)", composés multi-tokens).

Effets de bord positifs :
- Le bug "Saint-Jean-de-Luz → [ETABLISSEMENT]-de-Luz" est corrigé :
  le matcher `RE_LABEL_VILLE` masque toute la valeur en `[VILLE]`
  AVANT que le gazetteer FINESS Aho-Corasick ne grignote "Saint-Jean".
  Cas 006_trackare_soignants et 008_anesthesie_complete : alignement
  des expected.txt sur cette amélioration.

Choix d'architecture (cf cadrage docs/cadrage-projet-anonymisation.md
section 10.1) : ces labels sont des règles cœur génériques applicables
à tout établissement de santé français. Légitimes en hardcodé. Les
patterns layout-specific (Bordeaux suffixe, CHCB en fin de phrase,
email cassé par force_term) seront branchés via admin_rules dans
l'étape suivante.

Cas 010_fiche_admission_minimale passe désormais (retiré de
KNOWN_FAILURES). Le xfail strict aurait signalé xpass.

Tests : 9 passed, 2 xfailed (avant : 8 passed, 3 xfailed sur
test_synthetic_review).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-27 22:30:40 +02:00
parent c24b7f6f27
commit 7242b5350e
7 changed files with 64 additions and 18 deletions

View File

@@ -15,7 +15,7 @@ IPP : [IPP]
Adresse : [ADRESSE]
Code postal : [CODE_POSTAL]
Ville : [ETABLISSEMENT]-de-Luz
Ville : [VILLE]
Téléphone : [TEL]
Activités de soins :

View File

@@ -13,7 +13,7 @@ Téléphone : [TEL]
Adresse : [ADRESSE]
Code postal : [CODE_POSTAL]
Ville : [ETABLISSEMENT]-de-Luz
Ville : [VILLE]
Intervention prévue : cholécystectomie sous coelioscopie
Indication : lithiase vésiculaire symptomatique

View File

@@ -3,7 +3,6 @@
"ADHERENT",
"ADRESSE",
"CODE_POSTAL",
"DATE_NAISSANCE",
"EMAIL",
"ETAB",
"IPP",

View File

@@ -16,7 +16,7 @@ Lieu de naissance : [VILLE]
Nationalité : française
COORDONNEES
Adresse : [ADRESSE]
Adresse : [ADRESSE], [ETABLISSEMENT] 3B
Code postal : [CODE_POSTAL]
Ville : [VILLE]
Téléphone fixe : [TEL]

View File

@@ -28,9 +28,22 @@ Points critiques :
- le numéro de chambre `chambre 412` doit rester intact (pas un
identifiant patient).
Écarts attendus :
- numéro d'adhérent MGEN : pas couvert par les règles standard, peut
être un FN si aucune règle générique sur séquence numérique 10+ ;
- le NIR au format espacé peut être détecté ou non selon la règle ;
- patient et époux portant le même nom : vérifier que les deux
occurrences sont bien masquées.
Écarts résolus dans la session 2026-04-27 (commits c24b7f6 + suivants) :
- numéro adhérent mutuelle : règle `RE_NUM_ADHERENT` ajoutée, masqué
en `[ADHERENT]` (placeholder dédié) — gère MGEN, MAAF et toute
formulation `n° adhérent` / `Numéro d'adhérent` ;
- NIR au format espacé : `RE_NIR` réordonné AVANT `RE_TEL` pour
empêcher la consommation prématurée ;
- labels structurels `Nom de jeune fille :`, `Prénom :`, `Ville :` :
trois nouvelles règles cœur (`RE_LABEL_NOM_VARIANTES`,
`RE_LABEL_PRENOM`, `RE_LABEL_VILLE`) dans `_mask_structured_line`.
Écarts résiduels cosmétiques (non fuites) :
- `appartement 3B` dans la ligne adresse est tagué `[ETABLISSEMENT]`
par le matcher FINESS Aho-Corasick — perte d'information mais
aucune fuite PII. À investiguer plus tard (le mot `appartement`
ne devrait pas être dans le gazetteer FINESS).
- `kinds_present` ne contient pas `DATE_NAISSANCE` alors que la
ligne `Date de naissance : 30/04/1973` est masquée — la valeur
est masquée via un autre code path qui n'enregistre pas le hit
avec ce kind. Pas de fuite, juste une incohérence d'audit.

View File

@@ -35,14 +35,9 @@ KNOWN_FAILURES: dict[str, str] = {
"fuite identifiant médecin."
),
"009_multi_etablissements": (
"Plusieurs fuites : suffixe `de Bordeaux` après [ETABLISSEMENT], "
"CHCB en fin de phrase, Biarritz sur ligne `Ville :`, caractère "
"`ñ` qui casse Beñat → [NOM]ñat."
),
"010_fiche_admission_minimale": (
"Labels `Nom de jeune fille :`, `Prénom :`, `Ville :` non "
"couverts — ELIZONDO, Sabine, Bayonne fuient. NIR au format "
"espacé partiellement masqué (consommé en TEL)."
"Fuites résiduelles : suffixe `de Bordeaux` après "
"[ETABLISSEMENT], CHCB en fin de phrase. À traiter via "
"admin_rules (étape B suivante)."
),
}