Commit Graph

228 Commits

Author SHA1 Message Date
6476fe9f98 feat(gui): instance unique + mutex partagé installeur (P0-7)
Protection multi-instance GUI V6 : mutex kernel nommé sur Windows (partagé
avec l'installeur Inno via AppMutex), fcntl exclusif sur POSIX (dev/test).
3 tests unitaires, self-test OK, 0 régression gui_v6 (145 passed).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 18:01:28 +02:00
d4891f5cfd fix(gui): flag legacy ONNX + log fichier dès l'entrée frozen (P0-5/E1)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 17:58:05 +02:00
9296c28bed feat(gui): log fichier rotatif V6 à chemin connu (E1) 2026-06-25 17:56:50 +02:00
9e87cb3122 feat(gui): binding licence-poste souple (P0-6/D-20.4, affichage sans blocage) 2026-06-25 17:52:07 +02:00
dc0554e694 fix(gui): fail-close si CamemBERT-bio indisponible (P0-1, anti-fuite PII)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 17:46:50 +02:00
f3e6cdb980 fix(gui): connecter la GUI V6 au portail prod (P0-2, plus localhost)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 17:40:33 +02:00
55e8839613 docs(beta): plan d'implémentation 1a — socle sûreté & chaîne prod GUI V6
Plan bite-sized TDD pour les chantiers A/B/E1 : fail-close PII (P0-1), URL portail
(P0-2), binding licence souple (P0-6), log fichier V6 (E1), flag frozen ONNX (P0-5),
instance unique + mutex installeur (P0-7). 6 tâches, code complet, tests unitaires.
Plans 1b (gating cœur), 1c (UI), 2 (diagnostics), 3 (build/release) à suivre.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 16:49:01 +02:00
6554a6d590 docs(beta): audit prêt-bêta GUI V6 + design de mise en prod bêta testeur
Audit prêt-pour-bêta de GUI V6 (3 axes : parcours/UX/PII, moteurs/OnnxTR/frozen,
licence/télémétrie/diffusion) → punch-list P0=7 / P1=11 / P2=6, findings vérifiés.

Design validé Dom : périmètre « A + chaîne prod », P0 + P1 honnêteté UI, toggles
« Données à détecter » câblés au moteur (gating par type + couplage rescan, pas de
plancher dur), licence souple + binding poste (D-20.4), −2 Go via excludes PyInstaller,
Linux-first TDD + un seul build Windows. Plus 3 exigences prod intégrées : diagnostics
logs auto-upload scrubbé (liste-blanche), mise à jour propre (installeur), modèles
embarqués hors-ligne. 6 chantiers (A-F), 2 repos. Diffusion = gate Dom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 16:43:04 +02:00
4b7c8db9a8 build: retirer torch/docTR du frozen + hiddenimports OnnxTR (pré-audit Qwen GO)
Suite à la migration OCR docTR→OnnxTR (8d683bc) et au verdict pré-audit Qwen
(GO technique, 2026-06-21), préparation des 3 specs PyInstaller pour le prochain
rebuild Windows :

- Retrait de "torch", "torchvision", "doctr.*" des hiddenimports des 3 specs
  (anonymisation_onefile, _cli_onefile, _gui_v6_onefile) → -~2 Go EXE attendu,
  suppression définitive de la classe de bug oneDNN sur CPU contraint.
- Ajout des hiddenimports transitifs OnnxTR manquants (réserve R1 Qwen) :
  "pyclipper", "scipy.cluster.hierarchy", "scipy.special" → anti-omission
  PyInstaller (évite un crash OCR en frozen).
- Retrait de python-doctr[torch]>=0.9.0 de requirements.txt (transitoire levé).

_configure_torch_threads() conservé en code (lazy import torch sous try/except,
no-op si torch absent) pour future réactivation EDS-Pseudo/GLiNER.

Aucun rebuild ni diffusion (gate Dom). 3 specs compilent (py_compile).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 16:49:03 +02:00
8d683bc6d8 feat(ocr): migrer l'OCR de docTR (PyTorch) vers OnnxTR (ONNX Runtime)
OnnxTR exécute les MÊMES modèles que docTR (db_resnet50 + crnn_vgg16_bn) sur
ONNX Runtime, sans PyTorch. Corrige le crash torch/oneDNN « could not create a
primitive » sur CPU contraint (VM 2 cœurs collaborateur : OCR scan impossible →
quarantaine). Qualité identique validée empiriquement (CER 0,10-0,23 % vs docTR,
2 validations indépendantes Claude+Qwen), OCR ~2-3× plus rapide CPU.

- core : import OnnxTR, _get_ocr_model(), _OCR_AVAILABLE, boucle OCR inchangée
  (API miroir) ; ONNXTR_CACHE_DIR pour le frozen ; bandeau de logs ENV au démarrage
  (OS, CPU+AVX, cœurs, RAM, versions, providers) pour retours terrain auto-suffisants.
- 3 .spec : embarquent les poids ONNX OnnxTR (fail-closed) + hiddenimports onnxtr.
- requirements : onnxtr[cpu] (python-doctr conservé transitoirement).
- inclut le correctif quarantaine-visible du runner (GO Qwen).

Tests : test_ocr_onnxtr.py (RED→GREEN), 95 unit passed, e2e scan client OK
(OCR 5/5, PDF produit, plus de crash). Retrait torch du frozen + rebuild Windows
= étapes suivantes (gates Dom).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 17:07:00 +02:00
80d8cc230b docs(coord): rapport transfert artefacts 19c4934 vers portail (SHA vérifiés)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:06:17 +02:00
711f2bc2b5 docs(coord): ACK Codex — portail prod NPM + dépôt bêta, actions restantes Dom
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:39:27 +02:00
08e617b644 docs(beta): runbook portail aligné sur le déploiement prod réel (app.aivanov.eu)
- §0 nouveau : état réel (domaine app.aivanov.eu, NPM + Let's Encrypt Force SSL,
  APP_ENV=production, .env 600, cookie Secure confirmé live = fix 884661a en prod).
- §1 : pré-requis EXE copié sur serveur + commande avec env prod chargé + vérif SHA
  via /api/v1/version avant diffusion.
- §5 : sécurité indispensable marquée en place (HTTPS/secrets/cookie Secure ).
- §5bis : dépôt modèles EDS/GLiNER préparé mais NON ACTIF (pack à compléter+tester).

Vérifié live : /login 200 HTTPS, http→301, /api/v1/version 404 (pas encore publié).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:38:51 +02:00
14757007be docs(coord): ACK Codex — sécurité portail proportionnée + fix https_only
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 15:08:44 +02:00
471a8a4c62 docs(beta): runbook portail — sécurité proportionnée (pas de VPN/IP allowlist)
Recalibre la section sécurité au modèle de menace réel : portail sans
donnée patient (licences + compteurs agrégés) → HTTPS + login/mot de
passe fort suffisent. Retire la recommandation VPN/IP allowlist (overkill).
CSRF déjà couvert par SameSite=Lax ; rate-limiting /login = nice-to-have
au proxy. https_only désormais implémenté (app_aivanov 884661a).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 15:07:57 +02:00
c64162a936 docs(beta): kit bêta 2026-06-19 (checklist tests, note client, runbook portail)
Préparation bêta GUI demain (scope gelé Codex/Dom) — documentation, pas de code produit :
- docs/beta/checklist-tests-collaborateurs.md : install/lancement/licence/traitement
  PDF natif+scan/vérif anonymisation/0 remontée patient/usage admin/relevé OS-hash-version,
  garde-fou RGPD (synthétique/caviardé only).
- docs/beta/note-beta-client.md : version+SHA 8B437346…, moteurs actifs CamemBERT+regex,
  EDS/GLiNER non actifs, traitement local, consigne retour (pas de PDF/log patient).
- docs/beta/runbook-portail-beta.md : publier artefact actif, compte client+approbation→licence,
  jeton activation, /api/v1/version + download authentifié, rappels sécu prod (HTTPS/secrets/
  CSRF/rate-limit = accès restreint tant que non traités).

Cible : Anonymisation-Setup.exe v2026.06.18.1203 (source 19c4934). Aucun push/diffusion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:47:56 +02:00
19c4934de3 fix(gui): rendre les profils lisibles sous windows 2026-06-17 23:01:27 +02:00
ea1752d4a7 feat(cli): charger les moteurs optionnels depuis les modeles embarques 2026-06-17 19:52:29 +02:00
9b40fc0a85 fix(gui): rendre les profils scrollables a la molette
Ajoute un conteneur scrollable dedie au sous-onglet Profils pour permettre le defilement souris du formulaire complet. Tests GUI: test_gui_v6_profiles.py et test_gui_v6_*.py.
2026-06-17 18:05:45 +02:00
dc0616f744 fix(ner): convertir les entrees ONNX en int64
Force input_ids et attention_mask en int64 avant inference CamemBERT ONNX, pour eviter les erreurs de dtype selon les tokenizers/environnements Windows. Test cible: test_camembert_manager_cache.py.
2026-06-17 18:01:57 +02:00
60fb41c2e7 fix(gui): clarifier aide et disponibilite moteurs
Passe theme clair, libelles utilisateur, aides conteneurs, recherche de mise a jour et indication honnete des moteurs optionnels non embarques. Tests GUI unitaires: 126 passed.
2026-06-17 18:01:25 +02:00
d18ca919fa fix(core): renforcer detection PII et FINESS Corse
Couvre les corrections PII batch A/A-2, le NIR multi-ligne en flux reel, le gazetteer FINESS Corse derive depuis la base locale, et les tests de regression associes. Aucun build ni diffusion.
2026-06-17 17:59:27 +02:00
536ab81184 feat(gui): garde-fou runtime — désactive un moteur optionnel non embarqué
Condition du GO-CONDITIONNEL Qwen sur le lot engine capabilities
(cb3b767/890edb3/5e5f0bd) : un profil YAML forçant enable_eds/enable_gliner
ne doit pas déclencher un chargement voué à l'échec silencieux.

NerManagers.ensure_loaded() applique désormais un garde-fou via la sonde
engine_capabilities.capabilities_map() (injectable) AVANT toute tentative
de load EDS/GLiNER : si le moteur optionnel demandé est indisponible dans
le build courant → warning + désactivation forcée dans les réglages runtime.
Best-effort (sonde en échec ⇒ réglages inchangés, les try/except de load
protègent déjà). Sonde légère (find_spec), aucun import lourd.

CamemBERT (requis) inchangé. Diff limité au garde-fou + tests cibles.

TDD : 4 tests (test_gui_v6_engine_bridge.py) — eds/gliner indispo désactivés
et jamais chargés, moteur dispo conservé, fail-safe sonde. 282 unit passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 11:56:47 +02:00
5e5f0bd341 feat(gui): n'afficher comme disponibles que les moteurs embarqués dans le build GUI
Axe application GUI (utilisateur final) : cohérence UI/moteurs propre au build
GUI, sans présumer du build CLI. EDS-Pseudo / GLiNER désactivés (switch disabled
+ « non embarqué dans cette version ») et `enable_eds/gliner` forcés à False quand
indisponibles ; CamemBERT-bio reste le moteur standard actif. Note Moteurs des
Profils rendue honnête. `_mini_toggle` gère `disabled`/`disabled_hint` + `.switch`.

2 tests GUI (toggles désactivés si indispo + état forcé False ; actifs si dispo).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:38:56 +02:00
890edb360e feat(cli): option --engines, diagnostic honnête des moteurs du build CLI
Axe CLI (intégration dans d'autres programmes) : contrat stable, codes retour
fiables. `--engines` liste les moteurs réellement disponibles dans CET
exécutable CLI (`[OUI]/[NON] Label (requis/optionnel) — raison`) et sort 0, sans
traiter. `input` devient optionnel pour ce mode (sinon code 2).

Le fail-closed CamemBERT (code 3) et le best-effort EDS/GLiNER (jamais déclarés
actifs si le chargement échoue) restent inchangés. Ne présume pas du build GUI.

2 tests (--engines → code 0 + moteurs listés ; absence d'input → code 2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:38:56 +02:00
cb3b7675bb feat(engines): fondation 'capabilities moteurs' testable et partagée
Utilitaire neutre (ni CLI ni GUI) qui dit la vérité sur les moteurs réellement
disponibles dans le build COURANT (la sonde reflète l'exécutable qui tourne, sans
présumer d'un autre build). Consommé séparément par chaque axe produit.

- `EngineCapability(key, label, available, required, reason)`.
- Sondes légères `importlib.util.find_spec` (pas d'import lourd au démarrage) +
  présence du modèle ONNX pour CamemBERT (gère _MEIPASS en frozen).
- camembert=requis ; eds (edsnlp+spacy) / gliner=optionnels. Sondes injectables,
  fail-closed. `capabilities_map()` / `available_engines()`.

6 tests (sondes injectables dispo/indispo, required, reasons, sondes réelles).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:38:56 +02:00
764cf00581 refactor(gui): intégrer les Règles dans Administration > Profils
Retour Dom : « les règles du profil doivent être dans le menu profil, pas à
part ! ». Même logique que le Masquage — les règles qui influencent
l'anonymisation appartiennent au profil ; un sous-onglet séparé crée la
même confusion.

- Retrait du sous-onglet « Administration > Règles » (_SUBTABS, builder,
  méthode _build_regles supprimée). Sous-onglets restants : Réglages /
  Profils / Partage.
- Section « Profils > Règles du profil » enrichie : wording clair (règles
  d'anonymisation portées par le profil), aperçu illustratif de la table
  des règles (réutilise _rule_row + _HELP_REGLES), édition fine annoncée
  « à venir ».
- Abandon du « Testeur de règle » (écran outil global) pour ne pas
  réintroduire un second réglage métier.

Cible UX : Réglages / Profils (Général・Masquage・Mots・Moteurs・Règles du
profil) / Partage. Test obsolète test_rules_subtab_has_no_unexplained_2
remplacé par test_no_separate_rules_subtab.

262 tests unit OK (0 régression), self-test OK, nav 3 sous-onglets + section
Règles dans Profils + thème OK. Préserve d8bc0cd + GO Qwen. Aucun build/push
sans GO Dom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 12:00:10 +02:00
d8bc0cd8c8 refactor(gui): intégrer le Masquage dans Administration > Profils
Retour Dom : le sous-onglet Masquage séparé créait de la confusion. Le
masquage fait partie de la manière d'anonymiser associée au profil.

- Retrait du sous-onglet « Administration > Masquage » (_SUBTABS, builder,
  méthode _build_masquage).
- Section « Profils > Masquage » enrichie : masque manuel requis, template
  de masque (lié au profil édité), bouton « Ouvrir l'éditeur de masque »
  (fenêtre dédiée) + dossier des templates, et apparence du masque
  (couleur, style des marqueurs + aperçu, marges H/V, coins arrondis).
- Le template enregistré depuis l'éditeur remplit désormais le champ
  Template du profil (preferred_manual_mask_template via _pro_template_var).
- Profils devient le centre des réglages métier (général/masquage/mots/
  moteurs/règles). Réglages inchangé (pas de pastilles, pas de grosse
  refonte). Nettoyage du code mort (_REPLACEMENT_CODES, _HELP_MASQUAGE).

261 tests unit OK (0 régression), self-test OK, nav 4 sous-onglets + éditeur
de masque depuis Profils + thème OK. Préserve 72841ed/GO Qwen. Aucun build/
push sans GO Dom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 10:24:49 +02:00
72841ed7b3 feat(gui): onglet Profils éditable (création/modification/persistance)
Retour Dom : remplacer la page vitrine par un vrai éditeur de profils.

- gui_v6/profile_editor.py : couche logique (build_profile_spec,
  profile_is_editable runtime vs defaut, list_profile_choices, slug_for_copy,
  save/set_default/delete) au-dessus de profile_defaults — persistance dans
  config/profiles.yml.
- gui_v6/editable_list.py : EditableTermList (tableau scrollable de termes,
  ajout/suppression, pas de pastilles) — reste lisible à 50+ termes.
- tab_config : sous-onglet « 👤 Profils » réintroduit comme éditeur — menu
  déroulant « Profil à modifier », boutons Nouveau / Dupliquer / Enregistrer /
  Annuler / Définir par défaut, sections Identité, Masquage (require_manual_mask,
  template), Moteurs (force_disable_vlm), Mots (à masquer/conserver/ignorer
  éditables), Règles « à venir ». Profils défaut = lecture seule (dupliquer
  pour modifier). Confirmation non bloquante (pas de modale).
- Réglages : bouton « ✏️ Modifier le profil… » → ouvre Profils sur le profil
  actif. Pas de pastilles inline.

Persiste : label, description, require_manual_mask, force_disable_vlm,
preferred_manual_mask_template, param_lists (3 listes). 260 tests unit OK
(0 régression), self-test OK, nav 5 sous-onglets + thème OK. Préserve
1bbe70a/d30f7b7. Aucun build/push sans GO Dom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 23:09:01 +02:00
1bbe70a911 feat(gui): câbler l'envoi de la télémétrie d'usage en fin de run
Le module usage_telemetry est maintenant réellement branché : la GUI V6
envoie les statistiques au portail après chaque run (les stats web
restaient vides sans cela).

- processing_runner : RunSummary porte une liste DocResult (ordinal,
  page_count via page_count_for, status, duration_ms, extension) — peuplée
  dans la boucle. Aucun nom/chemin de fichier.
- usage_telemetry : report_run_summary(summary, base_url, license_ref,
  machine_id, session, ...) construit le payload depuis le RunSummary et
  l'envoie (non bloquant). N'envoie RIEN sans license_ref. Spool JSONL si
  échec réseau.
- tab_usage : _finish() déclenche l'envoi en thread daemon (jamais bloquant
  pour l'UI ni le run).
- app : fournit le reporter à UsageTab avec le contexte licence (base_url du
  LicenseClient, license_ref via local_status, machine_id, app_version).

Tests : RunSummary.documents peuplé (0 chemin) ; report_run_summary (payload
correct, réseau KO → spool sans crash, pas d'envoi sans licence) ; _finish
appelle le reporter. 252 tests unit OK (0 régression), self-test OK.
V5/moteur/app_aivanov intacts, 0 dépendance. Aucun build/push sans GO Dom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:24:43 +02:00
d30f7b74ef refactor(gui): Réglages — tableau des termes en accès direct, retrait du doublon Profils
Retour Dom après validation visuelle : simplifier.

- Réglages > Listes locales : suppression des pastilles de termes et des
  éditeurs inline (_compact_tag_editor). Remplacés par un texte court +
  compteurs (À conserver/À masquer/À ignorer du profil actif) + bouton
  « Ouvrir le tableau des termes » qui ouvre DIRECTEMENT TermsTableWindow.
- Retrait du bouton « Voir le profil » (son rôle = accéder au tableau).
- Retrait du sous-onglet « Profils » (doublon non câblé) : _SUBTABS,
  builders, _build_profils/_rebuild_profils. Les helpers profil
  (_active_profile_summary/_open_terms_table) sont conservés pour Réglages.
- Nettoyage du code mort associé : _compact_tag_editor, constantes
  _PRESERVE_TERMS/_MASK_TERMS/_STOPWORDS, textes d'aide qui référençaient
  l'onglet Profils.

Chemin utilisateur : Administration > Réglages > Ouvrir le tableau des
termes. 247 tests unit OK (0 régression), self-test OK. Préserve a9e8b2c
(thème, bêta, aide ?, fenêtre tableau). Aucun build/push sans GO Dom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:45:43 +02:00
ab2ca8a552 feat(gui): module télémétrie d'usage (client, RGPD-safe, non bloquant)
Phase A de la mission télémétrie d'usage par client.

- gui_v6/usage_telemetry.py :
  - page_count_for(path) : PDF→fitz, image→1, autres→None ; best-effort, ne
    lève jamais, ne lit que l'extension (jamais le nom).
  - build_usage_payload(...) : compteurs (document/succeeded/failed/total_pages)
    + documents filtrés aux seules clés autorisées (ordinal/page_count/status/
    duration_ms/extension) → aucun nom/chemin de fichier ne peut fuir.
  - UsageTelemetryClient(session injectée) : report() non bloquant (capture
    tout, False en cas d'échec réseau) vers POST /api/v1/usage/report.
  - spool JSONL local (spool_payload/flush_spool) pour rejouer les échecs.

Module isolé, non câblé au runner pour l'instant (le branchement fin-de-run
viendra après le backend, hors validation visuelle GUI en cours). Aucun
build/push sans GO Dom. 10 tests unitaires (payload sans nom de fichier,
réseau indispo ne crashe pas, compteurs, page_count PDF mockable).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:13:57 +02:00
a9e8b2c2e6 feat(gui): addenda Dom GUI V6 — sous-onglet Profils, libellés, aide, bêta
Suite des retours Dom sur la GUI V6 (par-dessus 6a0a581).

Addendum Profils / Réglages :
- Nouveau sous-onglet Administration « 👤 Profils » : le profil actif devient
  un objet lisible (nom, description, masque requis, template, listes locales
  avec compteurs) — données réelles lues depuis profile_defaults.
- Fenêtre « Tableau des termes » (terms_table_window.py) : table scrollable
  avec recherche/filtre, colonnes Type/Terme/Source ; reste lisible à 50+
  termes. Ajouter/éditer/supprimer désactivés « (à venir) » (écriture par
  profil non câblée).
- Réglages : « Profil métier » → « Profil d'anonymisation », « Sortie… » →
  « Dossier de sortie… » (+ infobulle), hints moteurs (standard/optionnel/
  plus lent), bouton « Voir le profil », « Ouvrir le tableau des termes ».
- Aide « ? » + infobulles (ui_kit.attach_tooltip) près des éléments ambigus.
- profile_view.py : logique pure (résumé profil + lignes du tableau),
  testable sans display.

Addendum bêta : en-tête « aivanonym » + badge « bêta », titre fenêtre
« … — bêta ». Détail version conservé dans À propos.

tests/unit/test_gui_v6_profiles.py + ajouts shell. 237 tests unit OK
(228 → 237, 0 régression), self-test GUI V6 OK, navigation des 5 sous-onglets
+ thème OK. V5/moteur/app_aivanov/profile_defaults non touchés, 0 dépendance.
Aucun build/push sans GO Dom — validation visuelle Dom attendue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:02:54 +02:00
6a0a5811a5 fix(gui): retours Dom GUI V6 — thème, Administration, Règles, aide
Cinq retours utilisateur sur l'exécutable Windows GUI V6.

- Thème : `_render()` vidait les widgets mais conservait le cache
  `_tab_frames`/`_visible_tab` → l'onglet Utilisation se vidait (TclError
  sur widget détruit) au changement de thème. Reset du cache dans
  `_render()` → onglet actif recréé proprement.
- Onglet principal « Configuration » → « Administration » (clé interne
  inchangée).
- Sous-onglet « Règles  2 » → « Règles » (le « 2 » était un badge non
  câblé).
- Actions de maquette non câblées (Partage Export/Import, Règles Nouvelle
  règle/Recharger/Tester/Fermer) désactivées + suffixe « (à venir) » via
  `_mockup_button` : plus aucune action morte qui semble fonctionner.
- Aide « ? » restaurée (façon V5) : `ui_kit.HelpButton`/`help_button`
  réutilisable ouvrant une fenêtre d'aide en français simple, posée sur
  Utilisation, Administration (Réglages/Masquage/Partage/Règles) et
  À propos. Partage : phrase visible + aide expliquant qu'on partage les
  réglages, jamais les documents patients.

`tests/unit/test_gui_v6_app_shell.py` : régression thème, libellés,
présence d'aide, navigation. 228 tests unit OK (0 régression), self-test
GUI V6 OK. V5/moteur/app_aivanov non touchés, aucune dépendance ajoutée.
Verdict Qwen requis avant push/build/diffusion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 16:39:53 +02:00
13b79db417 feat(gui): éditeur de masques en fenêtre dédiée (GUI V6)
Remplace l'éditeur de masquage encastré dans l'onglet Configuration —
jugé inutilisable par Dom (document trop à l'étroit, non défilable) —
par une fenêtre dédiée où le document est majoritaire et réellement
navigable.

- gui_v6/mask_editor_model.py : couche logique pure (rectangles par
  page, conversions écran↔PDF, hit-test, sérialisation template)
  testable sans display ; réutilise MaskRect/Template de
  pdf_mask_designer → format de template inchangé (compat moteur).
- gui_v6/mask_editor_window.py : MaskEditorWindow (CTkToplevel)
  redimensionnable — canvas + scrollbars H+V câblées + molette (le
  manque qui rendait l'éditeur inutilisable), zoom + ajuster
  largeur/page, navigation pages, rectangles au glisser-déposer,
  sélection (clic) + suppression (Suppr / clic-droit), templates
  JSON/YAML, mode aperçu d'exemple sans PDF.
- tab_config.py : l'onglet Masquage lance la fenêtre dédiée ; retrait
  du canvas encastré et de ~290 lignes de code mort associé.
- tests/unit/test_gui_v6_mask_editor.py : 13 tests logique + 3 smoke
  headless (scrollbars, ajout/sélection/suppression, save/load
  roundtrip, câblage onglet→fenêtre).

Sans nouvelle dépendance. V5, moteur et app_aivanov non touchés.
221 tests unit OK (0 régression), self-test GUI V6 OK.
Verdict Qwen requis avant push/build/diffusion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:05:57 +02:00
696f6bf27c fix(gui): make admin config responsive and mask editor usable 2026-06-15 09:53:56 +02:00
269b9e0e13 fix(gui): complete V6 admin configuration mockup 2026-06-15 09:19:43 +02:00
873fd5622a build(gui): add Windows GUI V6 one-click packaging 2026-06-13 09:31:14 +02:00
562f5a76dd chore(rgpd): retire les sorties PII du HEAD + durcit .gitignore
Retire les 6 fichiers .audit.jsonl/.pseudonymise.txt (NOM/ADRESSE/CP en clair)
de test_doctr_fix/ et tests/phase1_test_output/. Ajoute *.audit.jsonl et
*.pseudonymise.txt au .gitignore (*.pdf déjà ignoré) pour stopper la récidive.

Purge de l'historique git (filter-repo + force-push) traitée séparément.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 22:16:24 +02:00
fff4a2d902 fix(cli): avoid duplicate ONNX native load in Windows frozen 2026-06-12 16:49:11 +02:00
1bced55b81 feat(gui): GUI V6 G4 — alignement visuel sur la maquette v6 (option A)
Refonte de la couche présentation pour reprendre docs/ui_mockup_v6.html, sans
changer de techno UI ni la logique G1-G3.

- theme.py : 4 thèmes aux tokens EXACTS de la maquette (sombre #1a1a2e/#16213e/
  #e94560, clair, médical, neutre), palette complète + status_color.
- ui_kit.py (nouveau) : composants stylés (Card titrée, boutons primary/secondary/
  success/pilule, StatCard, ToggleRow) appliquant la palette.
- app.py : shell étroit, header identité + version + statut licence + liseré accent,
  barre d'onglets custom (plus de CTkTabview brut), navigation par recréation,
  changement de thème à chaud.
- tab_usage : carte Apparence (sélecteur de thème), dropzone stylée, grille formats,
  barre d'actions, progression à étapes + journal, résultats en cartes statistiques.
- tab_config : sous-navigation Réglages/Masquage/Partage/Règles ; Réglages câblé au
  ConfigState (profil, moteurs NER, dossier sortie).
- tab_about : grille d'informations + bloc licence (logique inchangée).

Logique inchangée : engine_bridge, config_state, license_client/store, runner.
Tests : +9 (theme). self-test exit 0, 55 tests gui_v6, 202 tests/unit (0 régression).
Smoke construction headless (Xvfb) : 3 onglets × 4 thèmes rendus sans erreur.
Pas de pywebview, aucun .exe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 12:06:05 +02:00
9575714ae2 feat(gui): GUI V6 G3 — câblage moteur, Configuration, licence UI, build-prep
G3-A câblage moteur réel (engine_bridge.py) : EngineSettings + NerManagers à
chargement paresseux (aucun manager à l'import), kwargs alignés CLI/V5
(make_vector_redaction=False, also_make_raster_burn=True, config_path, use_hf,
ner/gliner/camembert_manager, ogc_label) ; make_process_fn engine injectable ;
état managers not_loaded/loading/ready/unavailable, échecs optionnels tolérés.

G3-B Configuration (config_state.py + tabs/tab_config.py) : ConfigState →
EngineSettings, profils via profile_defaults (path injectable), options
raster/NER local/profil/sortie, état managers, sections admin-only via admin_mode.

G3-C Licence UI (machine_id.py + tab_about) : activation par clef
(LicenseClient.activate), bouton vérifier (check), affichage statut, aucun token
loggé, aucun appel réseau au démarrage (local_status seul).

Intégration : tab_usage exécute via le moteur réel selon ConfigState
(make_process_fn), anti double-lancement UI. app.py câble Config↔Usage↔licence.

G3-D build-prep : anonymisation_gui_v6_onefile.spec (entry V6, customtkinter +
modules gui_v6 en hiddenimports). Installateur Anonymisation.iss produit déjà la
cible Anonymisation-Setup.exe. Aucun artefact .exe commité ; build Windows à part.

Tests +14 (engine_bridge 8, config_state 6). self-test exit 0, 46 tests gui_v6,
193 tests/unit (0 régression). Moteur/V5/specs CLI intacts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:53:47 +02:00
9bc6537233 feat(gui): add GUI V6 G2 — onglet Utilisation + runner injectable
Onglet Utilisation fonctionnel (couche présentation only) :
- processing_runner: runner testable sans display/moteur lourd, process_fn
  injectable (défaut = process_document en import paresseux), découverte
  fichier/dossier, sorties anonymise/ comme V5 (arbo préservée), progression,
  journal, résumé OK/KO, arrêt coopératif entre documents, anti double-lancement
- tabs/tab_usage: sélection fichier/dossier + nb PDF détectés, dossier sortie
  (défaut anonymise/), Lancer/Arrêter, barre de progression, statut, journal,
  résumé ; worker threadé, file d'événements drainée par after() ; aucun réseau
- app.py: onglet Utilisation câblé (placeholder G2 retiré)
- self-test: couvre processing_runner + tab_usage

Tests: +11 (runner) — discovery, sorties, échec partiel, arrêt, anti-double-run,
callbacks. self-test exit 0, 32 tests gui_v6, 179 tests/unit (0 régression).
Moteur/V5/managers/specs intacts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 18:58:10 +02:00
a6ee68a8a3 feat(gui): add GUI V6 G1 foundation (license client/store, shell, About tab)
Socle de la refonte GUI V6 (couche présentation uniquement, aucune logique de
détection) :
- license_store: stockage licence hors dépôt (%LOCALAPPDATA%/Aivanov | XDG),
  read/write atomique/delete, ne journalise aucun token
- license_client: LicenseStatus + activate/check/local_status, session HTTP
  injectable, serveur indisponible géré sans crash, aucune clé privée
- theme: 4 thèmes + couleurs de statut licence
- app + tab_about: shell customtkinter minimal (header, bandeau licence,
  3 onglets), onglet À propos étoffé
- Pseudonymisation_Gui_V6.py: point d'entrée + --self-test (exit 0 sans fenêtre)
- requirements.txt: customtkinter==5.2.2

Tests: 20 nouveaux (store sur vrais fichiers, client sur session injectée).
Suite tests/unit: 167 passed, 0 régression. V5/moteur/managers/specs intacts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 18:50:23 +02:00
26f0cdfd68 feat(cli): add dedicated Inno Setup installer for the Windows CLI
Installateur Inno Setup séparé de la GUI (validé GO par Qwen), pour tests
internes et intégration de la brique CLI dans un autre logiciel.

- installer/Anonymisation-CLI.iss : AppId distinct de la GUI
  (B2F4A7C1-…), PrivilegesRequired=lowest, DefaultDirName
  {localappdata}\Programs\Anonymisation-CLI, source dist\Anonymisation-CLI.exe.
  Clés registre HKCU stables (InstallPath/ExePath/Version) + App Paths HKCU
  pour résolution tierce, supprimées à la désinstallation (uninsdeletekey).
  Pas de PATH système, pas de raccourci bureau. GUI .iss non modifiée.
- installer/Anonymisation-CLI-README.txt : usage, codes retour, lookup registre.
- scripts/build_windows_cli_installer_only.ps1 : build ISCC dédié,
  sortie release\Anonymisation-CLI-Setup.exe + SHA-256.
- docs/build-windows-oneclick.md : section « Installateur CLI dédié ».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 16:44:58 +02:00
263126dafa feat(cli): add Windows single-file anonymization entrypoint
CLI de production sans GUI pour anonymiser un fichier unique, validé GO par
Qwen (revue indépendante contrat/packaging/modèles) sur de vrais PDF.

- scripts/anonymize_cli.py (NOUVEAU) : contrat positionnel
  `Anonymisation-CLI.exe <fichier> <dossier_sortie>` (+ --out compat),
  chemins espaces/accents, codes retour 0/1/2/3/4.
  Chargement modèles fail-closed : CamemBERT-bio ONNX OBLIGATOIRE (code 3 si
  absent, aucun mode dégradé silencieux) ; EDS-Pseudo + GLiNER optionnels,
  tracés au log ; --no-ner = regex seul assumé. Résolution _MEIPASS frozen
  alignée sur launcher.py. Sortie burn raster identique GUI v5.
- anonymisation_cli_onefile.spec : entrypoint basculé vers anonymize_cli.py
  (le harnais perf D-19 anonymize_batch_cli.py reste hors build).
- docs/build-windows-oneclick.md : section « CLI Windows (sans GUI) »
  (build, usage, codes retour, modèles, limitations).

Tests Linux (vrais PDF) : --help OK, fichier manquant→2, --no-ner accents→0,
NER complet→0 (CamemBERT-bio + EDS-Pseudo chargés), modèle déplacé→3.
Build/smoke Windows à suivre (séparé). Commit CLI-only strict, distinct du P0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 14:26:11 +02:00
0e44cd4543 feat(anonymizer): add v11.5 P0 layout-aware detectors
Trois détecteurs simples « layout/context-aware » (chantier v11.5 P0),
validés par 2 revues Codex + 10 tests adversariaux Qwen, 0 régression :

- RE_ADRESSE réécrit en grammaire de tokens (_RE_VOIE_TYPE + _RE_VOIE_TOKEN) :
  capture initiales (« J. Loeb »), voies commémoratives à chiffres
  (« 8 Mai 1945 »), apostrophes ' et ’, bornage à la ligne courante,
  arrêt sur point post-mot (anti-débordement clinique).
- _mask_ville_gazetteers : retourne toujours un tuple (texte, liste) même
  sans Aho-Corasick ; masque les communes Saint/St/Sainte/Ste multi-mots à
  espaces (« St Martin de Hinx ») entièrement, sans exiger de contexte géo.
- DATE_NAISSANCE retiré de la propagation globale + DATE_NAISSANCE_GLOBAL
  ajouté aux skip vector/raster : on ne masque plus une date nue sur tout le
  document. La DDN reste masquée en contexte fort, page par page. Les dates
  cliniques identiques à la DDN hors contexte sont préservées.

tests/unit/test_p0_layout_detectors.py : 38 tests dédiés (matrice adresse
générique, anti-FP, communes Saint, propagation DDN, 10 tests adversariaux
Qwen). Suite tests/unit complète : 147 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 10:28:18 +02:00
c582c13a08 fix(anonymizer): cover CHCB real-world staff layouts 2026-06-08 12:44:09 +02:00
94f7903af3 fix(anonymizer): handle FC14 practitioner OGC rules 2026-06-08 12:03:51 +02:00
21a408a9e4 fix(perf): apply MVP threading hotfix
Configure numerical library and torch threading for H1, keep raster threading/timing instrumentation, remove CONCERTATION from forced masks after real PDF FP testing, and record coordination archive state.
2026-06-08 10:41:15 +02:00