12 KiB
ROADMAP — PseudObsidian-ization
Plugin Obsidian de pseudonymisation et correction de transcriptions (conventions Jefferson / ICOR / SRT / CHAT).
Chaque phase produit quelque chose de testable. Les critères d'acceptation renvoient aux sections de SPECS.md.
État actuel (mai 2026)
Phases 0 à 6 terminées. La Phase 7 est en cours : l'intégration de l'outil Coulmont est opérationnelle (suggestion de prénoms sociologiquement équivalents via coulmont.com). Le travail porte maintenant sur la constitution de dictionnaires lexicaux embarqués (prénoms, toponymes, institutions) et leur intégration dans le moteur de suggestion pour les phases de scan automatique.
✅ Phases 0–6 Parsers · Moteur · Commandes UI · Portées · Surlignage · Validation sélective
🔄 Phase 7 Dictionnaires — Coulmont ✅ · Dictionnaires JSON/CSV · Ressources embarquées
⏳ Phase 8 Scan automatique (détection sans règle préexistante)
⏳ Phase 9 Interface complète (panneau latéral 4 onglets)
⏳ Phase 10 Publication communauté Obsidian
✅ Phase 0 — Boilerplate
- Initialiser le plugin avec le template officiel Obsidian (TypeScript + esbuild)
- Configurer ESLint, Prettier, Jest
- Définir les types partagés de SPECS.md §11.3 :
ScopeType,MappingStatus,EntityCategory,MappingRule,Scope,Occurrence,ReplacementSpan - Créer un vault de test avec des fichiers fictifs :
entretien_01.srt,entretien_02.cha,entretien_03.md - 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)
- Représentation interne : tableau de
SrtBlock { index, start, end, lines[] }
- Tests unitaires sur
entretien_01.srtfictif - Vérifier que la reconstruction du fichier à partir de l'AST est identique à l'original (round-trip)
Testable — SPECS §17.4 : après parse + reconstruction, les horodatages et numéros de blocs sont inchangés.
✅ Phase 2 — Parser CHAT / CHA
Objectif : ouvrir un .cha, distinguer métadonnées, tours de parole et lignes dépendantes.
- Implémenter
parsers/ChatParser.ts:- Lignes
@(métadonnées) → préservées telles quelles - Lignes
*LOCUTEUR:→ tour de parole, zone remplaçable - Lignes
%(dépendantes) → préservées ou traitées séparément selon action explicite - Représentation interne :
ChatLine { type: 'meta'|'turn'|'dependent', speaker?, content }
- Lignes
- Tests unitaires sur
entretien_02.chafictif - Vérifier le round-trip
Testable — SPECS §17.5 : les lignes @, * et % sont conservées après parse + reconstruction.
✅ Phase 3 — Mapping basique : sélection → règle → application fichier
Objectif : premier flux complet, portée fichier uniquement. C'est le cœur du MVP v0.1 (SPECS §16.1).
- Commande "Créer une règle depuis la sélection" (§10.1) : modale minimale (source, remplacement, catégorie, portée = fichier par défaut)
mappings/MappingStore.ts: lecture / écriture deentretien_XX.mapping.json(portéefile)scanner/OccurrenceScanner.ts: scan du fichier courant, liste des occurrences avec contexte gauche/droite (§7.2)- Vue latérale minimale — onglet Occurrences : fichier, ligne, contexte, remplacement proposé, bouton valider/ignorer (§10.3)
pseudonymizer/ReplacementPlanner.ts: construit le plan de remplacement (§12.1)pseudonymizer/SpanProtector.ts: résolution des spans, application droite-à-gauche (§12.4, §12.5)- Export du fichier pseudonymisé (
nom.pseudonymized.srt/.cha/.md) sans table de correspondance (§14.1) - Export de la table JSON séparément (§14.2)
Testable — SPECS §17.1 : Bonjour Jean. → règle Jean → Pierre → export contient Bonjour Pierre. et la table JSON contient le mapping.
✅ Phase 4 — Priorité z-index et protection des spans imbriqués
Objectif : garantir qu'un remplacement court ne s'applique pas à l'intérieur d'un segment long déjà traité.
- Champ
prioritydansMappingRule: entier libre, défaut 0 (comme z-index CSS — §8.4) sortRules: tri parprioritydécroissant, puis longueur source décroissante, puis portée locale (§12.3)resolveSpans: élimination des chevauchements selon ce tri (§12.4)- Tests de non-régression obligatoires (§18.2) : Jean/Saint-Jean-de-Luz, Paul/Saint-Paul, Montpellier/CHU, Marie/Sainte-Marie
- Exploitable dans Obsidian :
- 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
- Commande
Testable — SPECS §17.2 : Jean habite Saint-Jean-de-Luz. → Pierre habite Ville littorale. visible dans le fichier exporté dans Obsidian.
✅ Phase 5 — Portée dossier et vault + surlignage éditeur
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
sortRulesexistant viascopeWeight(§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.
- Statuts par occurrence :
suggested,validated,ignored,partial,conflict,disabled,needs_review(§5.4) - Validation occurrence par occurrence, par lot, ou globale (§10.5)
- Mapping au statut
partialquand certaines occurrences seulement sont remplacées (§17.3) - Exploitable dans Obsidian :
- Commande
Pseudonymisation : scanner le fichier courant→ liste les occurrences candidates dans une modale - Chaque occurrence : bouton Valider / Ignorer / Faux positif
- Prévisualisation diff par occurrence avant application (§7.4)
- Menu contextuel sur sélection : Créer une règle / Pseudonymiser cette occurrence (§10.2)
- Tester : trois occurrences de
Jean, en valider deux, ignorer une → statutpartialdans le JSON
- Commande
Testable — SPECS §17.3 : mapping Jean → Pierre passe au statut partial après validation sélective.
🔄 Phase 7 — Dictionnaires : import et suggestions
Objectif : importer des dictionnaires existants (Coulmont, INSEE, etc.) et générer des suggestions de remplacement.
- Format interne
DictionaryEntryavecgender,decade,socialClass,replacementCandidates[](§6.3) dictionaries/JsonDictionaryImporter.ts: import JSON format SPECS §6.3dictionaries/CsvDictionaryImporter.ts: import CSV + mapping des colonnes (§6.4)adapters/coulmont.ts: CSV Coulmont →DictionaryEntry[]adapters/insee.ts: CSV INSEE prénoms →DictionaryEntry[]adapters/geoapi.ts: GeoAPI INSEE (villes +sizeClass) →DictionaryEntry[]dictionaries/DictionaryManager.ts: activation / désactivation, portée par dictionnaire (§6.5)- Dictionnaires embarqués :
firstnames.json,lastnames.json,cities.json,ambiguous.json,protected.json - Exploitable dans Obsidian :
- Commande
Pseudonymisation : importer un dictionnaire(JSON ou CSV) - Dans la modale de création de règle : suggestions issues des dictionnaires actifs
- Tester : importer
prenoms_coulmont.json, créer une règle pourJean→ candidats proposés depuis le dictionnaire
- Commande
Testable : suggestion automatique de remplacement à partir d'un dictionnaire Coulmont importé.
⏳ Phase 8 — Détection automatique et chevauchements
Objectif : scanner un fichier sans règle préexistante et détecter les entités candidates.
scanner/DictionaryScanner.ts: croisement texte × dictionnaires actifs (§7.2)scanner/RegexScanner.ts: heuristiques typographiques (majuscule initiale, locuteurs CHAT, formats Jefferson/ICOR)mappings/ConflictDetector.ts: détection des chevauchements (§8.5)- Marquage automatique
needs_reviewpour les occurrences chevauchantes ambiguous.json: tokens ville/prénom ambigus — signalement pour validation manuelle- Exploitable dans Obsidian :
- Commande
Pseudonymisation : scanner le fichiersans mapping préexistant → propose des candidats depuis les dictionnaires et les heuristiques - Modale de désambiguïsation : contexte du tour + boutons Ville / Prénom / Ignorer
- Tester : scanner
entretien_01.cha, voirJeanetSaint-Jean-de-Luzdétectés, chevauchement signalé
- Commande
Testable : scan automatique → détection de candidats → résolution manuelle de l'ambiguïté ville/prénom.
⏳ Phase 9 — Interface complète et correction des conventions
- Vue latérale complète : 4 onglets Occurrences / Mappings / Dictionnaires / Exports (§10.3)
- Onglet Mappings : modifier source, remplacement, catégorie, portée, priority (z-index), désactiver
- Onglet Exports : choix format, vérification absence de table dans l'export (§10.4)
- Rapport de pseudonymisation (§14.3)
correction/checker.ts: vérification des conventions Jefferson/ICOR- Suggestions de correction au survol
- Exploitable dans Obsidian :
- Panneau latéral complet accessible via l'icône ruban
- Workflow complet : ouvrir → scanner → valider → pseudonymiser → exporter sans table
- Tester le workflow de bout en bout sur
entretien_01.srtetentretien_02.cha
⏳ Phase 10 — Publication
- README utilisateur en français avec captures d'écran
- Guide de démarrage rapide pour les chercheurs ICAR
- Trancher les questions ouvertes de SPECS §20
- Publication sur le répertoire communautaire Obsidian
- Licence : MIT ou EUPL (selon contraintes CNRS)
Questions ouvertes (SPECS §20)
| # | Question | Statut |
|---|---|---|
| 1 | Modifier les fichiers originaux ou fonctionner uniquement par export ? | À trancher |
| 2 | Tables de correspondance dans le vault ou hors vault par défaut ? | À trancher |
| 3 | Chiffrement des tables dès la v1 ? | À trancher |
| 4 | Métadonnées CHAT dès le MVP ou à partir de la v0.3 ? | À trancher |
| 5 | NER avancé plus tard, ou rester sur dictionnaires + regex + validation humaine ? | À trancher |
| 6 | Compatibilité exacte à viser avec les JSON de Sonal pi / Whispurge ? | À explorer |
| 7 | Couplage audio optionnel via fichier local (API Obsidian) ? | À explorer |
| 8 | Export ELAN ou Praat ? | À explorer |
| 9 | Liste canonique pour ambiguous.json (Nancy, Florence, Lorraine…) ? |
À constituer |