Files
ASPIC/journal/ASPIC-Journal. 27. Pilotage Vocal.md

30 KiB

27. Pilotage vocal — multi-agents (1ᵉʳ-2 septembre 2026)

Contexte et bouton micro (1er septembre 2026). Suite de la ToDoList (section 26) : nouveau bouton micro dans le bandeau, positionné après l'avatar pour une place fixe à l'écran. Comportement centralisé dans un fichier partagé micro.js, chargé sur chaque écran hôte — reconnaissance vocale réelle via l'API Web Speech du navigateur (mode "cloud" du navigateur, l'audio étant envoyé à un service externe, voir réflexions stratégiques section 3), écoute continue avec redémarrage automatique tant que l'utilisateur n'a pas explicitement refermé le micro. Un mot déclencheur filtre les phrases prises en compte, pour ignorer la conversation de fond non destinée à ASPIC — principe conservé tout au long de cette section ; seul son fonctionnement (un seul nom fixe au départ, puis plusieurs agents) a évolué.

Mode notation. Une phrase d'ouverture ("[nom], ajoute une tâche" / "un truc à faire" / "note ça dans ma todolist") fait basculer dans un mode où le nom de l'agent n'est plus exigé pour chaque ligne suivante — tout ce qui est capté est ajouté tel quel, jusqu'à une phrase de clôture ("c'est tout [nom]") ou d'annulation ("[nom] annule"). Volontairement sans interprétation à ce stade (décision explicite de Jean-Marc, 1er septembre) : le texte part tel quel en base pour constituer un corpus de vrais essais, avant de définir des règles d'interprétation dans un prochain chantier (étape 2, envisagée via n8n, avec des règles modifiables par l'utilisateur).

Abandon du fichier texte, pivot vers une table SQL (2 septembre). La première implémentation écrivait les dictées dans un fichier texte global (notes_lilou/dictees.txt), plombée par des soucis de droits d'écriture (www-data hors du groupe propriétaire du dossier), puis par un échec pur et simple constaté au test du lendemain matin (aucune mise à jour du fichier malgré l'appel). Sur proposition de Jean-Marc, pour ne pas perdre plus de temps sur une approche provisoire : chaque ligne de dictée est désormais stockée directement dans une table MySQL, ASP_ConsignesVoix, structure finale à ce jour :

CREATE TABLE `ASP_ConsignesVoix` (
  `CVX_Incr` int NOT NULL AUTO_INCREMENT,
  `CVX_Consigne` varchar(200) NOT NULL,
  `CVX_Type` varchar(12) NOT NULL,
  `CVX_DateHeure` datetime NOT NULL,
  `CVX_CodeUser` varchar(3) NOT NULL,
  `CVX_AgentTraitant` varchar(20) NOT NULL,
  PRIMARY KEY (`CVX_Incr`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CVX_Type (ajoutée en cours de session, voir plus bas) distingue ouverture / contenu / cloture / annulation sur chaque ligne, pour qu'un futur automatisme ("robot") sache, sans ré-analyser le texte brut, où commence et finit un lot, et s'il doit être exécuté ou écarté — clôture et annulation distinguées à ce niveau, malgré un traitement du contenu identique dans les deux cas (décision du 1er septembre, maintenue). CVX_AgentTraitant (ajoutée plus tard dans la session, voir "Généralisation multi-agents" ci-dessous) porte en clair le nom de l'agent adressé, appelée à devenir une clé étrangère (CVX_IncrAgent) une fois le modèle stabilisé.

Corrections apportées en conditions réelles. Plusieurs bugs identifiés et corrigés au fil des essais de Jean-Marc :

  • une phrase d'ouverture ou de clôture/annulation dite dans la même phrase que du contenu, sans pause ("Lilou, ajoute une tâche, [contenu]" tout d'une traite), perdait silencieusement le contenu situé après la phrase de contrôle repérée — corrigé symétriquement des deux côtés (ouverture, puis clôture/annulation) ;
  • couper le micro manuellement pendant une notation en cours abandonnait le contenu déjà dicté — corrigé en traitant la coupure manuelle comme une clôture normale, avec un marqueur explicite ("(coupure manuelle du micro)") ;
  • une clôture prononcée ("c'est tout Lilou") transcrite par erreur en "c'est tous les loups" par le moteur de reconnaissance passait inaperçue — diagnostiquée après une demande explicite de Claude à Jean-Marc de fournir un export exact plutôt qu'une nouvelle tentative à l'aveugle (une première hypothèse s'étant déjà révélée fausse), puis corrigée par une tolérance dédiée à cet homophone de phrase entière.

Incident de confidentialité et retrait du traçage de débogage. Un traçage brut temporaire (toutes les phrases reconnues, trigger ou non), ajouté pour diagnostiquer le bug ci-dessus, a enregistré des bribes d'un appel téléphonique confidentiel reçu pendant que le micro était resté ouvert. Jean-Marc a supprimé les lignes lui-même et signalé l'incident sans gravité particulière ; Claude a retiré l'intégralité de cette fonctionnalité de traçage dès que l'incident a été rapporté, sans attendre. Risque résiduel identifié : même sans traçage, l'écoute continue envoie l'audio ambiant au service de reconnaissance tant que le micro est ouvert, qu'un agent soit reconnu ou non — seul le mode local ("on-device", encore expérimental) éliminerait complètement cet envoi (voir réflexions stratégiques, section 3). Mitigation partielle apportée dans la foulée : voir coupure pour inactivité ci-dessous.

Coupure automatique pour inactivité. Ajoutée en réponse directe à l'incident ci-dessus : après DUREE_INACTIVITE_MS (10 minutes par défaut) sans interaction réelle avec un agent, le micro se referme tout seul, comme un clic manuel — notation en cours clôturée proprement plutôt que perdue. Le bruit de fond ignoré (aucun agent reconnu) ne repousse volontairement pas ce délai, puisque c'est justement le cas qu'on veut détecter (une conversation qui ne s'adresse à aucun agent, comme lors de l'incident).

Généralisation multi-agents (2 septembre). Jean-Marc a souhaité que l'information "à quel agent s'adresse la note" soit explicitement stockée plutôt que sous-entendue, en vue d'un futur système où plusieurs assistants IA nommés se partageraient les tâches (voir réflexions stratégiques, section 11, le "bureau à l'ancienne"). Nouvelle table ASP_Agents :

CREATE TABLE `ASP_Agents` (
  `AGN_Incr` int NOT NULL,
  `AGN_Nom` varchar(20) NOT NULL,
  `AGN_Fonction` varchar(40) NOT NULL,
  `AGN_Variantes` varchar(200) NOT NULL,
  `AGN_Defaut` varchar(1) NOT NULL DEFAULT 'N'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

micro.js charge cette liste au démarrage via un nouvel endpoint agents.php (GET, même principe que utilisateurs.php), et construit dynamiquement le motif de reconnaissance de chaque agent — plus aucun agent codé en dur dans le script. lilou_notes.php a été renommé agent_notes.php (il ne sert plus un seul agent) et accepte désormais {agent, lignes} en entrée.

AGN_Variantes — tolérer les confusions sans coder en dur. Après trois cas réels indépendants de confusion de reconnaissance le même jour (Lilou/Milou/Loulou, Matilda/Mathilda/Mathilde, Karl/Carl), le mécanisme a été généralisé : chaque agent porte en base une liste de graphies alternatives (AGN_Variantes, séparées par une virgule), repliées dans le motif de reconnaissance de son nom — modifiable par Jean-Marc directement en base, sans code. Règle explicitement posée à cette occasion : une variante doit rester un nom propre ou un mot rare en tête de phrase, jamais un mot français courant ("car", "calme"...), qui déclencherait l'agent sur n'importe quelle phrase du quotidien commençant par ce mot. Seule exception qui reste codée en dur : l'homophone "les loups" pour la clôture de Lilou, qui porte sur la phrase entière et non sur le seul prénom (aujourd'hui inerte, Lilou n'étant plus dans ASP_Agents — voir plus bas).

AGN_Defaut — agent de repli piloté par la donnée. Le champ agent, s'il arrive vide dans agent_notes.php (compatibilité avec un client qui ne le renseignerait pas), résout désormais l'agent à utiliser via ASP_Agents.AGN_Defaut = 'O', avec un repli supplémentaire sur le premier agent de la table si aucun n'est marqué par défaut. Plus aucun nom d'agent figé en dur dans le code, y compris côté micro.js (titre du panneau de notation, secours en cas d'échec de chargement de agents.php).

Retrait de Lilou et Karl (décision de Jean-Marc). Les essais réels ont montré des confusions de reconnaissance récurrentes et non résolues sur ces deux noms — "car"/"calme"/"Carl" pour Karl (une notation entière restée bloquée, jamais refermée, lors d'un essai), "Philou"/"loulou" en plus de "Milou" pour Lilou. Plutôt que d'empiler encore des tolérances, avec le risque à la fois de multiplier les faux déclenchements (sur des mots français courants) et de fragiliser le système face à un accent ou une prononciation différente de celle testée, Jean-Marc a choisi de retirer ces deux agents plutôt que de corriger indéfiniment. Liste active à l'issue de cette session : Viktor (Agent Commercial, variante "Victor"), Matilda (Agent Administratif, variantes "Mathilda"/"Mathilde", agent par défaut), Léon (Agent Commercial Export, aucune variante nécessaire à ce jour), Nikita (Agent Financier, aucune variante nécessaire à ce jour) — ces deux derniers n'ayant provoqué aucune confusion observée en essai réel.

Méthode de travail à noter pour la suite. Plusieurs diagnostics de cette session (le bug "les loups", un déploiement resté sur l'ancien lilou_notes.php après le renommage, les confusions Matilda/Karl/Viktor) ont été résolus après avoir explicitement demandé à Jean-Marc une preuve concrète (export SQL exact, ligne de console) plutôt qu'en tentant une nouvelle correction à l'aveugle sur simple hypothèse — approche à reconduire systématiquement.

État à la fin de cette session. Fonctionnalité validée de bout en bout sur les quatre agents actifs (ouverture → contenu → clôture, y compris avec variantes de prononciation). Version applicative incrémentée une fois pour cette session, V1.006.

Reste à faire (à la clôture de la session du 1-2 septembre).

  • Étape 2 : règles d'interprétation du contenu dicté (aujourd'hui stocké tel quel, sans traitement), envisagées via n8n, avec des règles modifiables par l'utilisateur.
  • Continuer à observer les agents actifs en usage réel ; envisager d'autres retraits, ou l'ajout de nouvelles variantes via AGN_Variantes, si de nouvelles confusions apparaissent — sans jamais y ajouter un mot français courant.
  • Vérifier concrètement que le .htaccess du dossier /journal bloque bien l'accès direct (curl -I doit répondre 403, pas 200) — point resté en suspens depuis le 31 août, sans lien avec le pilotage vocal mais toujours ouvert.
  • Documentation utilisateur : pas encore mise à jour pour cette fonctionnalité, encore en phase d'essais techniques (choix des noms d'agents notamment) — à envisager une fois l'usage stabilisé.

3 septembre 2026 (soirée) : vers l'étape 2 — constitution d'une banque de dictées réelles avant toute règle d'interprétation (V1.010)

Reprise de session le même jour (voir aussi section 28, où le micro de l'écran de fond est branché sur la reconnaissance vocale réelle plus tôt dans cette même soirée). Discussion engagée par Jean-Marc après avoir montré les évolutions du pilotage vocal à sa compagne, qui a directement fait le lien avec son expérience de SAP dans une grosse PME (application qui rame, arrêts brutaux, procédures lourdes pour un simple changement — délai moyen de 2-3 jours via un prestataire externe pour créer un utilisateur ou corriger un bug de saisie). Jean-Marc en tire une conviction : l'aspect vocal sera vraisemblablement un atout concurrentiel important vis-à-vis de futurs clients, ce qui augmente l'exigence de fiabilité plutôt que de la relâcher — inquiétude explicite sur la capacité du projet à tenir cette fiabilité une fois le pilotage vocal étendu au-delà de la ToDoList (contacts, catalogue, devis et affaires en cours, facturation...), sans tomber dans un empilement de règles/rustines au cas par cas comme cela avait déjà été nécessaire pour Lilou/"les loups" (voir plus haut).

Distinction actée avec Claude, développée en détail dans les réflexions stratégiques (section 12) : deux problèmes différents, à ne pas traiter par le même mécanisme. D'un côté, la confusion de reconnaissance en amont (mot déclencheur mal transcrit) — un problème de reconnaissance audio, déjà traité par AGN_Variantes et le choix de noms d'agents qui passent bien à l'oral, dont la surface d'erreur ne grandit pas avec le nombre de modules d'ASPIC. De l'autre, l'interprétation d'une dictée déjà bien captée — transformer "il faut ajouter un contact, il s'appelle Pierre Chartier, il est plombier à Quimper..." en une action structurée (quel module, quelle opération, quels paramètres). Conclusion : ni RAG ni base vectorielle pour ce deuxième problème (outil de recherche floue dans un corpus, pas de déclenchement d'action) — un LLM à sortie structurée (function calling) contre un catalogue d'actions par module est l'outil adapté, sans avoir besoin de pgvector avant qu'un vrai besoin de recherche floue (catalogue produits, historique de devis) n'apparaisse. Modèle affiné avec Jean-Marc pour le retour visuel sur le post-it : deux statuts distincts plutôt qu'un seul niveau de confiance — "à corriger" (information manquante/incohérente, l'IA n'a pas su comprendre) versus "à valider" (l'IA a bien compris et préparé l'action, mais cette action précise exige toujours un accord humain avant exécution réelle, par nature — ex. l'envoi d'un devis à un client — indépendamment du niveau de confiance de l'interprétation). Deux signes graphiques distincts envisagés sur le post-it (un point d'interrogation pour "à corriger", proposé par Jean-Marc ; un symbole différent, à définir, pour "à valider") plutôt qu'un seul, pour que Jean-Marc sache d'un coup d'œil ce qu'on attend de lui sans ouvrir le post-it.

Décision pour cette session : ne pas anticiper les règles, constituer d'abord un corpus réel. Cohérent avec la leçon déjà tirée de Lilou/"les loups" — ce qui semble naturel en le pensant seul (ex. faire commencer chaque instruction par le prénom d'un agent) se révèle différent une fois dicté réellement et de façon détendue. Jean-Marc a d'ailleurs déjà relevé, avant même d'avoir l'outil, deux exemples concrets : il commence souvent une instruction par "il faut"/"il faudrait" plutôt que par le prénom d'un agent, et utilise aussi bien "puis" que "ensuite" pour marquer un enchaînement — points à garder tels quels dans le corpus plutôt qu'à corriger à la main, l'objectif de cette phase étant justement de laisser le vrai usage remonter ces variations plutôt que de les deviner.

Outil construit : micro_test.js + dictees_test.php + table ASP_DicteesTest. Outil de mise au point interne, explicitement pas destiné aux futurs utilisateurs (précision de Jean-Marc). Table créée par Jean-Marc lui-même (voir convention actée en tête de journal) :

CREATE TABLE `ASP_DicteesTest` (
  `DCT_Incr` int NOT NULL,
  `DCT_Theme` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'Gestion des Contacts',
  `DCT_Texte` text NOT NULL,
  `DCT_Date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `DCT_Utilisateur` varchar(3) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

Choix de conception actés avec Jean-Marc, plusieurs à contre-courant du réflexe initial de Claude :

  • Aucun mot déclencheur. Le clic sur le micro fait déjà office de signal explicite de début — contrairement à micro.js en écoute ambiante continue, qui doit filtrer une conversation de fond d'une vraie commande, ce problème ne se pose pas ici : tout ce qui est dit après le clic est un essai volontaire. Ça répond directement à la remarque de Jean-Marc sur le prénom d'agent en tête de phrase — cette contrainte est un artefact du filtrage en écoute ambiante, pas une exigence de l'interprétation elle-même.
  • Pas de segmentation "à la main". Le "silence de x secondes" évoqué par Jean-Marc n'est pas un réglage exposé par l'application : c'est le moteur de reconnaissance du navigateur qui décide, en interne, quand un énoncé est terminé (chaque événement result avec isFinal=true correspond déjà à "ce qui a été dit avant une pause") — même mécanisme que celui déjà éprouvé en production dans micro.js, repris tel quel plutôt que réinventé.
  • Restitution au fur et à mesure. Contrairement à micro.js (interimResults=false), ce script active interimResults=true : le texte apparaît progressivement dans une fenêtre dédiée (fond noir, texte blanc, overflow-y:auto) pendant la dictée, la ligne se fige (et s'enregistre) dès que le silence est détecté, puis une nouvelle ligne démarre.
  • Aucune suppression possible, y compris pour un essai raté. Décision explicite de Jean-Marc, à contre-courant d'une première proposition de Claude (bouton de suppression pour nettoyer un essai avorté) : "les dictées ratées feront partie de la vie des futurs utilisateurs" — la banque doit refléter la réalité, pas une version nettoyée qui fausserait la conception des règles de correction à venir.
  • Fenêtre vidée à chaque fermeture du micro, rouverte vide au prochain clic — purement un retour visuel immédiat, la table continue évidemment d'accumuler tous les essais d'une session à l'autre.
  • Thème fixé à la valeur par défaut de la colonne ('Gestion des Contacts'), non transmis par le script — évite de dupliquer une valeur qui doit rester pilotée par la table.

Branché, comme détaillé en section 28, sur le micro de l'écran de fond (#micro-desk) à la place de micro.js, le temps de cette phase — décision explicite de Jean-Marc de réutiliser ce micro plutôt que de construire un écran séparé, pour permettre des essais rapides et répétés en se décontractant sur le sujet. micro.js n'est pas modifié pour ça (seul le repli d'id ajouté plus tôt dans la soirée y reste, voir section 28) et continue de tourner normalement sur liste_contacts.html.

Endpoint dictees_test.php : reçoit {"texte": "..."}, enregistre tel quel dans ASP_DicteesTest avec l'utilisateur de la session — même squelette que agent_notes.php (session requise, POST uniquement), sans logique de lot ni de type de ligne (chaque énoncé est indépendant ici, pas de notion d'ouverture/clôture).

Testé par Claude en navigateur headless avec un faux moteur de reconnaissance piloté à la main (restitution en direct, figeage de ligne au bon moment, deuxième essai qui ne recouvre pas le premier, fenêtre bien vidée à la fermeture) avant livraison. Premier essai réel le soir même, concluant : micro laissé ouvert par Jean-Marc pour une session de dictées, une phrase dite par sa compagne dans la pièce correctement captée (voir section 28) — confirme que l'écoute continue et le redémarrage automatique tiennent la route en usage prolongé, pas seulement en essai bref.

Fichiers touchés (3 septembre, soirée)

micro_test.js (nouveau), dictees_test.php (nouveau), ecran_fond.html (charge micro_test.js à la place de micro.js, voir section 28), version.php (V1.010). Table ASP_DicteesTest créée par Jean-Marc directement en base.

Reste à faire.

  • Laisser Jean-Marc constituer un vrai volume de dictées sur le thème "Gestion des Contacts" avant toute analyse — aucune règle d'interprétation à écrire tant que le corpus n'est pas jugé suffisant.
  • Une fois ce corpus analysé : concevoir le catalogue d'actions pour le module Contacts (actions, paramètres attendus, lesquelles exigent une validation par nature) et le mécanisme d'appel LLM à sortie structurée correspondant (voir réflexions stratégiques, section 12).
  • Reconnecter micro.js (vrai pilotage) sur le micro de l'écran de fond une fois cette phase de mise au point terminée — une seule ligne à changer dans ecran_fond.html (voir section 28).
  • Étendre MARQUEUR_FIN_LIGNE dans micro.js pour accepter "puis" en plus de "ensuite" (retour d'usage de Jean-Marc, 3 septembre) — sans urgence, à faire quand on retouche micro.js.
  • Concevoir les deux signes graphiques distincts pour les post-its "à corriger" / "à valider" évoqués plus haut — non codé, ni même définitivement choisi pour "à valider" (le point d'interrogation de "à corriger" est acté).
  • Étendre l'outil de banque de dictées à d'autres thèmes (catalogue, devis...) le jour où ces modules existeront — DCT_Theme est déjà prévu pour ça, seule la valeur par défaut en base et le script de capture sont à dupliquer/adapter.

3 septembre 2026 (nuit) : dictée d'adresses mail — diagnostic en plusieurs couches et deux bugs de robustesse trouvés grâce à un diagnostic en direct (V1.011)

Reprise de session le même soir, Jean-Marc ayant commencé à utiliser réellement l'outil de banque de dictées (section précédente) pour s'entraîner sur le thème "Gestion des Contacts". Constat immédiat et sévère : la dictée d'une adresse mail échoue environ 49 fois sur 50 — bien au-delà de ce qu'un utilisateur tolérerait, quelle que soit la qualité du reste du pilotage vocal (Jean-Marc : "si une dictée d'adresse mail pose problème dans plus de 10% des cas, la solution ne sera pas utilisée").

Diagnostic établi à partir d'exports réels de ASP_DicteesTest, pas d'hypothèses de table (même méthode que celle qui avait permis de trouver le bug "les loups", voir plus haut) — trois causes distinctes, à ne pas confondre :

  • Vocabulaire incohérent. Les mots dictés pour la ponctuation ("point", "tiret", "arobase", "tiret du bas") ne sont convertis en symbole par le moteur gratuit du navigateur que de façon incohérente — parfois convertis, parfois laissés en toutes lettres, parfois avalés purement et simplement. "tiret" est en plus régulièrement confondu avec le verbe "tirer" (homophone). Vérifié auprès de la documentation officielle : Google propose bien une option dédiée à cette conversion (enableSpokenPunctuation) dans son API Cloud Speech-to-Text payante, mais elle n'est pas exposée dans l'API gratuite du navigateur (webkitSpeechRecognition) — l'application doit donc faire elle-même cette conversion.
  • Segmentation non fiable. Le moteur découpe parfois une même adresse dictée en plusieurs lignes indépendantes, sans qu'un délai de silence permette de distinguer fiablement "il continue la même adresse" de "il change de sujet" (des écarts de 3 à 4 secondes s'observent dans les deux cas sur un même export réel).
  • Lettres avalées sur les mots inventés. Distinct des deux points précédents et plus grave : sur un mot sans aucun support linguistique réel (ex. "mvl-tls", un sigle interne), le moteur perd parfois des lettres entières ("mvl-tls.fr" transcrit "mvtls.fr") — une perte acoustique pure, invisible dans le texte reçu et donc jamais rattrapable par un quelconque post-traitement. Explication retenue : les moteurs de reconnaissance actuels s'appuient sur un modèle de langage qui favorise les séquences ressemblant à quelque chose de connu (d'où la fiabilité, à l'inverse, de "gmail.com" — une chaîne quasi mémorisée tant elle est fréquente) ; un sigle inventé n'a aucun appui de ce genre.

Position actée avec Jean-Marc sur ce dernier point : aucune solution, gratuite ou payante, ne peut garantir un fonctionnement parfait en toute situation sur un mot rare/inventé — dit explicitement pour ne pas laisser croire qu'une simple bascule vers une API payante réglerait tout. Le vrai levier pour ce cas précis serait le vocabulaire personnalisé ("boosting" — Google Cloud speech adaptation/phrase hints, Deepgram keyterm prompting), qui permet de fournir au moteur une liste de mots attendus (noms de domaine ASPIC, société, agents...) pour augmenter leur probabilité de reconnaissance — même principe que AGN_Variantes déjà en place pour les agents, appliqué cette fois au vocabulaire métier. Comparatif de prix et détail de la piste API conservés dans les réflexions stratégiques (section 12, addendum du même soir) plutôt que dans ce journal technique.

Décision : épuiser d'abord la piste gratuite avant d'envisager une API payante, le coût en dollars étant négligeable à l'usage envisagé mais le changement d'architecture bien réel (audio à faire transiter par un serveur détenant une clé, fin de la solution 100% navigateur/sans serveur actuelle).

"Mode adresse" ajouté à micro_test.js. Plutôt que de deviner où s'arrête une adresse dans un flux libre, reprise du principe déjà éprouvé du mode notation de micro.js (ouverture/clôture explicites) — ici au clic plutôt qu'à la phrase, pour ne pas dépendre d'un mot de clôture lui-même mal reconnaissable :

  • Activé/désactivé via un bouton dédié dans la fenêtre de test ; tant qu'il est actif, chaque fragment reconnu s'empile dans un buffer affiché en direct au lieu d'être enregistré comme une ligne indépendante — la segmentation du moteur n'a alors plus d'importance.
  • Le bouton "Valider" clôt le buffer : les fragments sont concaténés, passés dans un dictionnaire de conversion (point/tiret/tiret du bas/arobase → symboles, y compris l'alias "tirer"→"tiret" restreint à ce mode précis) qui retire aussi les espaces restants, puis comparés à une forme email/domaine attendue pour un simple retour visuel vert/orange — indicatif seulement, n'empêche jamais l'enregistrement (cohérent avec la règle "aucun essai raté supprimé" actée le 3 septembre après-midi).
  • Le texte brut (fragments concaténés tels que dictés) et le texte normalisé sont conservés tous les deux — nouvelle colonne DCT_TexteNormalise (ajoutée en base par Jean-Marc lui-même, VARCHAR(255) NULL), NULL pour toutes les lignes hors "mode adresse". Rien n'écrase la matière brute déjà actée comme précieuse pour la suite.
  • Un compteur simple (conforme/non conforme) affiché dans la fenêtre donne une lecture immédiate du taux d'échec au fil des essais.

Deux bugs de robustesse trouvés en cours de test réel, tous deux corrigés le même soir grâce à un bloc de diagnostic temporaire ajouté spécifiquement pour ça (DIAGNOSTIC_ACTIF/logDiag, affichage en direct de chaque démarrage/arrêt/erreur du moteur avec horodatage précis — y compris les erreurs normalement masquées comme "no-speech") :

  1. La fenêtre entière était vidée à chaque redémarrage automatique du moteur, pas seulement à l'ouverture volontaire du micro — bug préexistant à ce soir, resté invisible tant que les dictées s'enchaînaient vite, devenu très visible avec une dictée hésitante (adresse mail, beaucoup de silences de réflexion → beaucoup de redémarrages automatiques → fenêtre effacée avant d'avoir pu être lue). Signalé côté utilisateur par l'indicateur micro de Chrome clignotant en continu. Corrigé en ne réinitialisant la fenêtre qu'au tout premier démarrage suivant un clic utilisateur réel, jamais lors d'une relance automatique.
  2. Boucle de redémarrage incontrôlée, révélée par le diagnostic une fois le premier bug corrigé : jusqu'à plus de 1800 cycles démarrage/arrêt en quelques secondes, avec des erreurs "aborted" au passage — le code d'origine relançait reconnaissance.start() immédiatement à chaque arrêt, sans aucun délai ni protection. Corrigé par un coupe-circuit : au-delà de 5 redémarrages consécutifs en moins de 800 ms, l'écoute s'arrête proprement avec un message explicite, plutôt que de boucler indéfiniment en silence.

Résultat après correctifs, sur un tout petit échantillon (4 essais passés par le mode adresse) : 2 adresses parfaitement normalisées, 1 quasi-bonne (un mot parasite collé en tête, sans lien avec la ponctuation), 1 ratée — non pas à cause d'un bug, mais parce que deux adresses distinctes avaient été dictées à la suite sans clic "Valider" entre les deux, fusionnées en une seule chaîne par le buffer (comportement voulu du mode adresse, pas un défaut). Progrès net par rapport au ~1/50 de départ, mais échantillon bien trop petit pour trancher — Jean-Marc prévoit une campagne de tests en nombre le lendemain (4 septembre) et enverra les résultats.

Fichiers touchés (3 septembre, nuit)

micro_test.js (mode adresse + diagnostic temporaire + deux correctifs de robustesse), dictees_test.php (colonne DCT_TexteNormalise optionnelle en entrée), version.php (V1.011). Colonne DCT_TexteNormalise ajoutée par Jean-Marc directement en base (ALTER TABLE, communiqué par Claude, jamais exécuté côté Claude — voir convention actée en tête de journal).

Reste à faire.

  • Laisser Jean-Marc constituer un vrai volume d'essais d'adresses mail via le mode adresse (le 4 septembre) pour mesurer un taux de réussite fiable, plutôt que de statuer sur un échantillon de 4.
  • Retirer le bloc de diagnostic temporaire (DIAGNOSTIC_ACTIF/logDiag) une fois le comportement confirmé stable sur cette campagne — pas destiné à rester en l'état.
  • Décider si le cas "deux adresses dictées sans clic Valider entre les deux" (voir résultat ci-dessus) mérite un traitement automatique, ou reste une simple consigne d'usage.
  • Si le taux d'échec mesuré reste trop élevé après cette campagne : évaluer en conditions réelles (pas seulement sur la documentation) Google Cloud Speech-to-Text (phrase hints/boost) et Deepgram (keyterm prompting) avec le vocabulaire métier d'ASPIC — voir réflexions stratégiques, section 12.
  • Le problème des "lettres avalées" sur les mots inventés (ex. "mvl-tls.fr") reste entier et sans solution de contournement identifiée à ce stade, y compris avec le mode adresse — à garder en tête pour la suite plutôt qu'à considérer comme résolu.