Décision architecturale adoptée en mai 2026 : la **détection des entités identifiantes** repose sur du **NER** (`transformers.js` + `bert-base-multilingual-cased-ner-hrl`) plutôt que sur des dictionnaires lexicaux exhaustifs. Les dictionnaires restent des ressources de **remplacement** (candidats de substitution), pas de détection.
- [x] Initialiser le plugin avec le template officiel Obsidian (TypeScript + esbuild)
- [x] Configurer ESLint, Prettier, Jest
- [x] Définir les types partagés de SPECS.md §11.3 : `ScopeType`, `MappingStatus`, `EntityCategory`, `MappingRule`, `Scope`, `Occurrence`, `ReplacementSpan`
- [x] Créer un vault de test avec des fichiers fictifs : `entretien_01.srt`, `entretien_02.cha`, `entretien_03.md`
- [x] Mettre en place le dossier `_pseudonymisation/` dans le vault de test (§13.3)
**Testable :** le plugin se charge dans Obsidian sans erreur.
---
## ✅ Phase 1 — Parser SRT
Objectif : ouvrir un `.srt`, le lire sans l'altérer, identifier les zones textuelles. Priorité haute car c'est le format le plus courant en sortie de Whisper.
- [ ] Implémenter `parsers/SrtParser.ts` :
- Découpage en blocs (numéro / horodatage / texte)
- Identification des zones remplaçables (texte uniquement, pas les timestamps)
- Commande `Pseudonymisation : ajouter une transcription` (Ctrl+P) : ouvre un sélecteur de fichier natif, importe le fichier dans le vault, initialise un mapping JSON vide, ouvre le fichier
- Commande `Pseudonymisation : pseudonymiser le fichier courant` : lit le fichier actif (SRT, CHA/CHAT, MD), charge le mapping JSON correspondant, écrit `[nom].pseudonymized.[ext]` dans `_pseudonymisation/exports/`
- Commande `Pseudonymisation : créer une règle` (disponible sur sélection dans l'éditeur) : modale minimale — source, remplacement, catégorie, portée, priority — écrit dans le mapping JSON du fichier courant
- Tester manuellement : importer `entretien_01.srt`, créer les règles Jean → Pierre et Saint-Jean-de-Luz → Ville littorale, pseudonymiser, vérifier l'export
**Testable — SPECS §17.2 :** `Jean habite Saint-Jean-de-Luz.` → `Pierre habite Ville littorale.` visible dans le fichier exporté dans Obsidian.
Objectif : charger automatiquement les trois niveaux de mapping et visualiser dans l'éditeur les termes déjà pseudonymisés.
- [ ]`mappings/ScopeResolver.ts` : parcourir le dossier `_pseudonymisation/mappings/`, charger tous les fichiers JSON, filtrer et fusionner les règles applicables à un fichier donné (§4, §12.2)
- [ ] Cascade de résolution : fichier → dossier le plus proche → vault — géré par le tri `sortRules` existant via `scopeWeight` (§4.4)
- [ ]**Surlignage éditeur** : extension CodeMirror 6 (`registerEditorExtension`) qui marque dans le fichier ouvert :
- en **orange** : les termes sources (encore à pseudonymiser)
- en **vert** : les termes de remplacement (déjà pseudonymisés)
- se met à jour à chaque changement de fichier actif
- [ ]**Exploitable dans Obsidian** :
- La commande "pseudonymiser" utilise ScopeResolver pour charger les trois niveaux automatiquement
- Commande `Pseudonymisation : créer une règle au niveau dossier / vault`
- Le surlignage apparaît dès qu'un mapping existe pour le fichier ouvert
- Tester : une règle vault s'applique à deux entretiens différents ; les termes s'affichent surlignés dans les deux fichiers
**Testable :** ouvrir un fichier avec des règles de mapping → termes sources en orange, pseudonymes déjà appliqués en vert.
---
## ✅ Phase 6 — Validation sélective et statuts
Objectif : pouvoir remplacer certaines occurrences et en ignorer d'autres.
- [x]`dictionaries/DictionaryManager.ts` : activation / désactivation, portée par dictionnaire (§6.5)
- [x]`adapters/insee.ts` : CSV INSEE prénoms → `DictionaryEntry[]`
- [x] Dans la modale de création de règle : suggestions Coulmont affichées sous forme de boutons cliquables
> **Note :** les dictionnaires embarqués massifs (`cities.json`, `lastnames.json`, etc.) sont **dépriorisés** — la détection des entités sera déléguée au NER en Phase 9. Seuls les dictionnaires de **remplacement** (prénoms Coulmont/INSEE) sont maintenus ici.
Objectif : permettre la détection et le remplacement automatiques des entités identifiantes à partir de dictionnaires locaux, téléchargeables hors-ligne depuis un dépôt dédié.
**Décision architecturale :** le NER (transformers.js) reste le moteur de détection principal pour les entités contextuelles (prénoms, noms, institutions). Les dictionnaires ajoutent une détection exhaustive par liste pour les types dénombrables (communes, institutions connues) et fournissent les remplacements structurés (classes + index).
**Testable (v0.1.3) :** installer le dictionnaire communes → scanner un fichier → modale de révision → décocher les faux positifs → créer les règles → pseudonymiser.
- [ ]**Internationalisation (i18n)** : externaliser toutes les chaînes UI dans un fichier de traduction (`locales/fr.json`, `locales/en.json`) — architecture à définir (standard Obsidian ou `i18next`)
- [ ] Intégration [Meld Encrypt](https://github.com/meld-cp/obsidian-encrypt) dans l'onglet Exports pour le chiffrement des tables de correspondance et des exports pseudonymisés
Objectif : aller au-delà de la pseudonymisation pour offrir des fonctions adaptées aux besoins spécifiques de l'EMCA et de l'analyse conversationnelle.
Périmètre à définir lors de la Phase 10 — pistes envisagées :
- Vérification et correction assistée des conventions Jefferson / ICOR (chevauchements `[`, enchaînements `=`, pauses `(0.5)`, allongements `:`, prosodie `.``,``?`)
- Navigation structurée par tour de parole / séquence (vue panoptique inspirée de Sonal)
- Annotation thématique des tours (codes libres, portée fichier/dossier/vault)
- Export ELAN (`.eaf`) ou Praat (`.TextGrid`) depuis les fichiers annotés
- Couplage audio optionnel via fichier local (Obsidian API `app.vault`) — synchronisation tour ↔ segment audio
- Compatibilité avec le JSON d'échange Whispurge / Sonal pi (SPECS §20.6)
**Testable (v1.0.0) :** un chercheur peut ouvrir une transcription CHAT, la naviguer tour par tour, corriger les conventions, pseudonymiser, annoter thématiquement, et exporter vers ELAN — sans quitter Obsidian.
Ces fonctionnalités sont identifiées comme utiles mais non planifiées dans les phases actuelles.
| Feature | Description | Prérequis |
|---|---|---|
| **Backend spaCy** | Serveur Python sidecar (`fr_core_news_sm`) appelé via HTTP — meilleure précision sur le français, pas de téléchargement de modèle, temps de réponse plus rapide. Requiert Python ≥ 3.9 côté utilisateur. | Phase 9 stable |
| **Modèle CamemBERT-NER** | Remplacer le modèle multilingue BERT par `Jean-Baptiste/camembert-ner` ou `cmarkea/distilcamembert-base-ner` — spécifiquement entraîné sur le français. Nécessite une conversion ONNX et un hébergement HuggingFace. | Phase 9 stable |
| **Score de confiance spaCy** | Exposer les scores d'entités de spaCy (via `displacy` ou scorer) pour filtrer comme avec transformers.js. | Backend spaCy |
| **Désambiguïsation interactive** | Modale contextuelle pour les tokens ambigus ville/prénom (Nancy, Florence…) : affichage du contexte + boutons Personne / Lieu / Ignorer. | Phase 9 |
| 1 | Modifier les fichiers originaux ou fonctionner uniquement par export ? | **Décidé** — export en `.md` pour relire dans Obsidian, puis re-export dans le format inscrit dans les métadonnées du fichier source. L'onglet Exports affiche conditionnellement une option de chiffrement via [Meld Encrypt](https://github.com/meld-cp/obsidian-encrypt) quand on est dans un `*.pseudonymized.*`. |
| 3 | Chiffrement des tables dès la v1 ? | **Décidé** — recommander le plugin [Meld Encrypt](https://github.com/meld-cp/obsidian-encrypt) pour le chiffrement des tables et des exports. Intégration dans l'onglet Exports (Phase 10). |
| 5 | NER avancé plus tard, ou rester sur dictionnaires + regex + validation humaine ? | **Décidé : NER (Phase 9)** — l'objectif du dictionnaire (détection ou remplacement) est déterminé à l'import. Le NER assure la détection ; les dictionnaires fournissent les candidats de substitution. |
| 10 | Internationalisation (i18n) du plugin ? | **Décidé** — l'architecture doit permettre la traduction de l'interface. Toutes les chaînes UI doivent être externalisées dans un fichier de traduction. Implémentation en Phase 10. |