V1.15.17 Evolutions des consignes

This commit is contained in:
2026-09-08 01:29:41 +00:00
parent d287607e45
commit 0f7437fa77
18 changed files with 1361 additions and 121 deletions
+5 -3
View File
@@ -59,9 +59,9 @@ Pour les trois documents de ce projet (ce journal — résumé/index —, les R
- 29. Interprétation vocale des contacts par LLM
- 30. Chantier des consignes — moteur générique
*(Numérotation et titres repris du découpage fait par Jean-Marc le 31 août 2026, légèrement reformulés par lui à cette occasion — se référer aux fichiers eux-mêmes pour le libellé exact. Section 27 (Pilotage vocal) validée de bout en bout et son fichier définitif déposé dans `/journal` le 2 septembre 2026. Section 28 (Écran de fond) ouverte le 2 septembre 2026, toujours **en cours** — passée d'une maquette graphique exploratoire à un premier essai fonctionnel réel, puis (soirée du 2 au 3 septembre) à une pastille de comptage sur le classeur Contacts et à un premier affichage réel des post-its personnels sur le tableau de liège. Section 29 (Interprétation vocale des contacts par LLM) ouverte et son fichier définitif déposé le 4 septembre 2026 après validation de bout en bout sur un premier corpus réel ; fichiers de section à déposer par Jean-Marc, voir Statut actuel. Section 30 (Chantier des consignes — moteur générique) ouverte le 6 septembre 2026, fichier définitif rédigé le soir même après validation de bout en bout du mécanisme sur des cas réels ; fichier de section à déposer par Jean-Marc, voir Statut actuel.)*
*(Numérotation et titres repris du découpage fait par Jean-Marc le 31 août 2026, légèrement reformulés par lui à cette occasion — se référer aux fichiers eux-mêmes pour le libellé exact. Section 27 (Pilotage vocal) validée de bout en bout et son fichier définitif déposé dans `/journal` le 2 septembre 2026. Section 28 (Écran de fond) ouverte le 2 septembre 2026, toujours **en cours** — passée d'une maquette graphique exploratoire à un premier essai fonctionnel réel, puis (soirée du 2 au 3 septembre) à une pastille de comptage sur le classeur Contacts et à un premier affichage réel des post-its personnels sur le tableau de liège. Section 29 (Interprétation vocale des contacts par LLM) ouverte et son fichier définitif déposé le 4 septembre 2026 après validation de bout en bout sur un premier corpus réel ; fichiers de section à déposer par Jean-Marc, voir Statut actuel. Section 30 (Chantier des consignes — moteur générique) ouverte le 6 septembre 2026, fichier définitif rédigé le soir même après validation de bout en bout du mécanisme sur des cas réels ; **substantiellement complétée le 7 septembre 2026** (hiérarchisation cohérence/Tests/IA, traçabilité de l'agent, `REA_NomAffiche`, premier appel IA réel dans une consigne avec avertissement bloquant) — fichier de section mis à jour à déposer par Jean-Marc, voir Statut actuel.)*
## Statut actuel (2-6 septembre 2026)
## Statut actuel (2-7 septembre 2026)
**Écrans "Identification" et "Liste des contacts"** (avec panneau détail intégré) : aboutis depuis le 25 août 2026, testés en production. **Prospection** (formulaire externe, vérification mail, envoi de doc) : livrée et testée en conditions réelles le 26 août 2026 (section 18). **Dépôt Git** en place depuis le 27-28 août (section 20), avec circuit de livraison FileZilla → SSH VPS → `git push` (section 23) — l'écriture directe par Claude reste bloquée côté proxy Anthropic, contournement adopté sans gêne. **MIRADOR** (authentification centralisée multi-bases, identifiant = email) branché et validé à deux utilisateurs le 30 août 2026, déployé sur `aspic.mvl-tls.fr` (développement) et `crm.aspic.bzh` (test), chacun avec son propre environnement Docker (sections 21, 24, 25).
@@ -101,6 +101,8 @@ Version incrémentée une seule fois pour l'ensemble de cette session (pastille
**6 septembre 2026 : chantier des consignes — un moteur générique pour sortir du code en dur (V1.14.15).** Détail complet en section 30 du journal, fil conceptuel complet en Réflexions stratégiques, section 15. Résumé : reprise le soir même, sous forme concrète, de la distinction règles/consignes esquissée le matin — première mise en œuvre volontairement circonscrite à la fiche Contacts (création/modification). Deux tables créées par Jean-Marc (`ASP_Fonctions` : catalogue de fonctions génériques ; `ASP_Consignes` : instructions actives par contexte/champ), un moteur générique unique (`moteur_consignes.php`, fonction `appliquerConsignes()`) qui lit ces tables à l'exécution et applique traitements (mise en forme silencieuse) puis tests (validation, avec message d'erreur personnalisé), et une bibliothèque de fonctions du catalogue (`consignes_fonctions.php` : `MAJUSCULE`, `NON_VIDE`, `PREMIERE_LETTRE_MAJUSCULE`). `contacts.php` réduit à un seul appel au moteur, plus aucun contrôle de champ écrit en dur. Détour initial corrigé par Jean-Marc (Claude avait d'abord codé en dur un contrôle par champ au lieu du moteur générique demandé), puis abandon délibéré de la validation en temps réel côté écran au profit de la robustesse — révélant au passage un bug préexistant (message d'erreur générique affiché au lieu du message réel du serveur), corrigé. Ajustements d'interface demandés en cours de test : toast d'erreur centré et rouge sur le panneau de saisie, rendu correct des retours à la ligne saisis dans un message d'erreur. Preuve de concept validée par Jean-Marc en fin de session : ajout de nouvelles consignes (`NON_VIDE` sur Prénom et Ville) sans la moindre modification de fichier PHP/JS, comportement immédiatement actif avec les fichiers déjà livrés. Version incrémentée une seule fois pour l'ensemble de cette session, sur les deux compteurs anticipés dès le début (code et conception) : **V1.14.15**.
**7 septembre 2026 : chantier des consignes — hiérarchisation, traçabilité et premier appel IA réel dans une consigne [Évolutions majeures] (V1.15.17).** Détail complet en section 30 du journal, fil stratégique en Réflexions stratégiques, section 17. Résumé : reprise le lendemain matin par une session dédiée au lien entre Claude et l'ordinateur de Jean-Marc (voir Réflexions stratégiques, section 16 — chantier finalement clos, sans suite), puis, le soir, extension substantielle du chantier des consignes ouvert le 6 septembre. Un badge de chargement générique (`consignes_apercu.php`, convention de fonction jumelle `_seraitDeclenchee`) prévient désormais l'utilisateur qu'un appel IA va réellement se produire avant qu'il ne soit lancé. Bug de coût découvert par Jean-Marc et corrigé structurellement : une soumission vouée à échouer sur un Test déclenchait quand même, en pure perte, un Traitement IA coûteux — le moteur exécute désormais trois phases strictement séquentielles (Traitements de cohérence, puis Tests, puis seulement si tout est passé les Traitements IA), sur la base d'un seul attribut déjà présent au catalogue (`FON_VisuelAttenteIA`). Traçabilité renforcée : un nom d'agent resté codé en dur ("Mat") a été remplacé par une source unique de vérité (`CNS_Agent`, la consigne elle-même) ; nouvelle colonne `REA_NomAffiche` sur `ASP_Realisations`, un instantané écrit une seule fois à la création (session utilisateur côté humain, nom d'agent côté IA) plutôt qu'une jointure recalculée à la lecture — écartée pour sa complexité et son incompatibilité avec une future architecture multi-bases (MIRADOR). Renommage `ASP_Agents.AGN_Nom` → `AGN_Prenom` à l'origine d'une régression du pilotage vocal (cinq fichiers pré-existants non mis à jour, "aucun impact" affirmé à tort par Claude sans avoir vérifié) — corrigée le soir même, leçon actée pour la suite (grep systématique avant d'affirmer l'absence d'impact d'un changement de schéma). Nouveau Test générique `consigne_sans_chiffre()`, appliqué par Jean-Marc sur Nom/Prénom/Ville sans retoucher un seul fichier. Premier vrai appel IA dans une consigne : `consigne_completer_code_postal()` journalise désormais un échec (ville ambiguë, ex. Paris) au lieu de rester silencieuse, via une nouvelle clé réservée générique `_avertissement` affichée immédiatement à l'écran — trois itérations d'affinage de ce retour visuel dans la soirée, jusqu'à un message réellement bloquant (bouton "Valider" explicite, pas de disparition automatique) qui ne fait que finaliser l'affichage sans jamais redéclencher un enregistrement. Version incrémentée deux fois au fil de cette même journée de travail (code en tout début, conception en fin de session, section 17 des Réflexions stratégiques étant jugée majeure) : **V1.15.17**.
**Reste à faire, noté au passage :**
- Décider s'il faut renforcer le prompt d'extraction pour neutraliser les mots parasites/formules de politesse dictés autour d'une adresse mail (bug identifié le 4 septembre sur le corpus réel, correction non encore actée par Jean-Marc).
- Clarifier l'origine de la coupure de fin de dictée observée sur un essai du 4 septembre (minuteur de silence à 3,5s vs interruption réelle) avant de décider si `DUREE_SILENCE_ARRET_MS` (`contact_ia_panel.js`) doit être allongée.
@@ -125,7 +127,7 @@ Version incrémentée une seule fois pour l'ensemble de cette session (pastille
- Revoir les règles de calcul des pastilles rouge/orange/vert (`calculerGroupe()`) pour éviter un tableau trop chargé en rouge/orange maintenant que le vert quitte le tableau immédiatement.
- Décider du comportement du clic sur un post-it (aujourd'hui inerte) : ouvrir `liste_todolist.html` sur la tâche précise, ou afficher un détail directement sur l'écran de fond.
- Capacité du tableau (20) et taille de la grille (4×5) dans `ecran_fond.html`/`todolist.php` sont des valeurs provisoires posées avant d'avoir les vrais pixels de la version finale — à ajuster ensemble après usage réel prolongé.
- Concevoir un nouveau type de consigne pour les cas nécessitant un appel IA en cours de traitement (ex. retrouver le code postal d'une ville saisie sans code postal) — contrat de retour plus riche que Traitement/Test actuel (silencieux / besoin de précision / question à poser), gestion d'échec réseau, coût et latence d'un appel externe (chantier des consignes, section 30) — session dédiée à prévoir.
- Concevoir le contrat de retour complet à trois issues (silencieux / besoin de précision / question à poser) pour les consignes à appel IA — le 7 septembre n'en a construit qu'un premier incrément à deux issues (succès silencieux / échec avec avertissement bloquant), voir section 30. À généraliser le jour où un second cas concret en montrera le besoin réel, pas par anticipation.
- Écran de gestion des consignes par le boss (au lieu d'`INSERT`/`UPDATE` SQL à la main) — à construire après stabilisation du contrat ci-dessus, pour ne pas le refaire (chantier des consignes, section 30).
- Réflexion sur un catalogue restreint de consignes/fonctions avancées à proposer aux futurs utilisateurs de l'agence, sans leur ouvrir la création libre de A à Z — argument commercial identifié par Jean-Marc le 6 septembre (voir réflexions stratégiques, section 15).
- Accumulation de plusieurs messages d'erreur à la fois dans le moteur de consignes (aujourd'hui, seul le premier test en échec est remonté).
@@ -230,3 +230,53 @@ Point explicitement acté avec Jean-Marc : **aucune solution, gratuite ou payant
3. Réfléchir à un **catalogue restreint et curaté** de consignes et de fonctions avancées, à proposer aux futurs clients de l'agence — Jean-Marc a été explicite sur le fait qu'il n'envisage pas d'ouvrir à ses futurs utilisateurs une création libre de consignes avancées "de A à Z" ; il y voit au contraire un argument commercial pour de futures mises à jour payantes ("Possibilité de nouvelles consignes pour vos assistants"). Ce point rejoint directement la distinction actée plus haut entre mécanisme générique (partagé, neutre) et catalogue de fonctions (à curater soigneusement, puisqu'il devient potentiellement un produit en soi).
**Statut : premier cas concret bâti et validé, philosophie plus large confirmée par la pratique.** Le moteur générique de consignes existe, fonctionne, et a déjà changé de comportement une fois sans code — scellant, à l'échelle d'un cas modeste, l'intuition posée le matin même en section 14. Trois directions ouvertes pour la suite (consignes IA, écran de gestion, catalogue commercial), aucune engagée à ce stade au-delà de la discussion.
## 16. Lier une session à l'ordinateur de Jean-Marc — vers la fin des allers-retours de fichiers, et une question de fond sur la visibilité du code (7 septembre 2026)
**Origine — une question posée en marge, pas un chantier planifié.** Jean-Marc a repéré, dans des mails d'Anthropic, l'existence d'une fonctionnalité permettant de donner à Claude un accès en lecture/écriture direct à un ou plusieurs répertoires de son poste, et a demandé confirmation. Vérification faite (documentation officielle Anthropic) : la fonctionnalité existe bien — une session peut être liée à un ordinateur via l'application desktop Claude ("Link to this computer"), avec ensuite un octroi d'accès dossier par dossier (jamais le disque entier d'un bloc), strictement à la demande de l'utilisateur.
**Le vrai motif, une fois creusé : soulager une friction bien réelle du circuit de livraison actuel.** Le mode de fonctionnement en place depuis le début du projet (fichiers envoyés en pièce jointe de conversation, à télécharger, parfois renommés en double par le navigateur, puis copiés/renommés à la main dans le dossier de transfert SFTP de Jean-Marc) fonctionne mais coûte de l'attention à chaque fichier, avec un risque concret d'erreur relevé par Jean-Marc lui-même : *"Parfois, notamment quand nos échanges sont intenses, je loupe un téléchargement et je suis aux fraises."* Deux irritants précis identifiés et confirmés techniquement réglés par ce mécanisme :
- Le contournement `.js.txt` pour les fichiers JavaScript (nécessaire jusqu'ici uniquement parce que la livraison passait par le téléchargement navigateur, peu compatible avec ce type de fichier) — disparaît entièrement avec une écriture directe sur disque.
- Le renommage automatique en doublon (`toto_47.php` au lieu d'écraser `toto.php`) — même cause, même remède : en écrivant directement dans le dossier cible, le fichier livré porte son nom final et écrase silencieusement l'ancien, sans étape de tri manuel.
**Mécanique vérifiée dans la documentation officielle, à retenir pour la mise en œuvre :**
- Une fois un dossier accordé pour une tâche/projet lié à un ordinateur, l'autorisation est retenue d'une session à l'autre — pas besoin de la redonner à chaque ouverture. Condition permanente cependant : l'application desktop Claude doit être ouverte et la machine joignable au moment où une session cloud veut effectivement toucher aux fichiers ; application fermée, le pont est simplement indisponible (pas une erreur, pas une perte de la permission).
- Concernant le NAS Synology de Jean-Marc, accédé sous Windows via une adresse IP locale : un partage réseau **mappé sur une lettre de lecteur** (ex. `Z:\`) est pris en charge par le sélecteur de dossier ; un chemin UNC brut (`\\192.168.x.x\partage`) ne l'est pas directement. Jean-Marc a confirmé que son NAS est déjà monté par lettre — pas de point de blocage de ce côté. Seule variabilité relevée par Jean-Marc lui-même : le NAS peut se mettre en veille en cas d'inactivité prolongée et mettre un instant à répondre, mais reste actif par construction lorsqu'il est à son bureau.
**Décision : Jean-Marc prépare un répertoire réseau dédié au développement d'ASPIC (`Développement`), avec une arborescence calquée sur celle du VPS**, pour que déposer un fichier reçu de Claude s'y réduise à un simple report dans le bon sous-dossier, sans réflexion supplémentaire. Ce pont ne remplace à aucun moment la gestion du dépôt GitHub, que Jean-Marc continue d'opérer intégralement lui-même — **précision explicite de sa part : la clé GitHub ne sera pas donnée à Claude dans le cadre de cette organisation**, ce qui clôt d'un coup la question du blocage de push déjà bien documentée (journal de développement, section 23) : le sujet devient sans objet plutôt que contourné.
**Question de fond soulevée en cours de discussion : la documentation soignée du code a un revers.** Jean-Marc a exprimé une satisfaction ancienne et jamais obtenue de ses développeurs précédents — voir le code commenté avec soin, but qu'il avait longtemps réclamé sans l'obtenir — tout en identifiant lui-même la contrepartie : plus un fichier est documenté, plus il informe un œil indiscret qui y aurait accès (un visiteur via "Afficher le code source" sur les fichiers HTML/JS réellement exposés au navigateur ; ou, dans une hypothèse plus lointaine, un client final ayant lui-même accès aux fichiers de son propre hébergement, si le modèle (a) de la section 5 — éditeur déployé chez le client — était un jour retenu pour un projet one-shot). Rappel de contexte déjà posé et confirmé toujours valable : les fichiers PHP ne sont eux-mêmes jamais transmis au navigateur (exécution côté serveur), donc leurs commentaires ne sont, par construction, jamais visibles d'un simple visiteur — le risque concret porte avant tout sur les fichiers HTML/JS, et plus largement sur toute situation où quelqu'un obtiendrait un accès direct aux fichiers sources eux-mêmes plutôt qu'au seul rendu navigateur.
**Solution retenue : une version "exploitation" du code, générée à la demande, jamais systématiquement.** Plutôt que de renoncer à la qualité de documentation acquise sur ce projet (dont la valeur pour la continuité du travail avec Claude reste entière, voir section 2), Jean-Marc a proposé de pouvoir demander, ponctuellement et une fois l'application arrivée à un certain point de maturité, une copie des sources débarrassée de tout commentaire — à déployer à la place de la version pleinement documentée, celle-ci restant la référence de travail. Décision actée : construire cet utilitaire (retrait de commentaires par analyse syntaxique réelle du langage — pas une simple recherche/remplacement de texte, qui risquerait de corrompre une chaîne de caractères contenant `//` ou un délimiteur de commentaire), à ranger dans un sous-dossier `Exploitation` du futur répertoire réseau, en miroir de `Développement`. Portée explicitement limitée, pour ne pas se tromper sur ce que ça protège réellement : un simple retrait de commentaires (le code, sa mise en forme et ses noms de variables restent identiques, ce n'est pas une minification ni un chantier d'obscurcissement) réduit la fuite d'information gratuite vers un œil curieux, mais ne constitue pas une vraie protection contre un acteur déterminé — cohérent avec le constat déjà posé en section 5 (aucune protection réelle n'existe pour du PHP/JS vanilla livré tel quel).
**Confrontation au réel : la demande d'accès a buté sur un bug documenté de Windows, pas sur une erreur de configuration.** Une fois le répertoire préparé côté NAS, la demande d'octroi pour `G:\01. Version 1\000. Développement` a été refusée par le mécanisme de sélection de dossier, avec un message ne pointant vers aucune cause côté Jean-Marc ("Ask the user to connect the folder they want using the folder picker on their device, or pick a different folder"). Plutôt que de proposer une manipulation au hasard, recherche faite : il s'agit d'un bug Windows réel et déjà documenté (plusieurs tickets ouverts sur le dépôt public `anthropics/claude-code`, dont #38468, #24927, #24964) — le sélecteur de dossier de l'application desktop rejette actuellement, sous Windows, tout dossier situé hors du profil utilisateur (`C:\Users\<utilisateur>\`), y compris un lecteur réseau mappé sur une lettre pourtant explicitement pris en charge par la documentation officielle ; les jonctions/liens symboliques ne contournent pas le problème, la résolution du chemin réel bloquant également ce chemin de traverse. Statut du bug à la date de cette session : non résolu, ticket fermé comme doublon sans correctif. Une tentative parallèle, créer un nouveau projet directement à partir d'un dossier pour voir si un autre point d'entrée existait, n'a fait apparaître aucune option de partage de fichiers. Conclusion honnête tirée de cet épisode, formulée par Jean-Marc lui-même et retenue comme point de vigilance pour la suite des échanges : une fonctionnalité présentée comme possible en théorie peut ne pas l'être réellement au moment de passer à l'action — une raison de plus, au-delà de ce chantier précis, de rester prudent sur ce qu'affirme Claude tant que ce n'est pas vérifié en conditions réelles.
**Une seule alternative restait disponible — un dossier sous `C:\` — et Jean-Marc l'a refusée, pour deux raisons distinctes et toutes deux jugées valables.** La première, posée sous forme d'image par Jean-Marc lui-même : donner l'accès à une pièce, même partiel, se choisit d'abord sur la pièce la moins sensible — entre un coffre-fort à espace réduit et une pièce d'armoires de rangement, l'accès s'ouvre sur la seconde, jamais sur le premier ; le disque `C:` héberge le système et le profil de l'utilisateur, il n'a pas vocation à devenir un point d'échange de fichiers de développement, quel que soit le soin apporté à la restriction du dossier précis accordé. La seconde raison, plus concrète et finalement décisive : une expérience vécue par Jean-Marc, un disque `C:` d'un poste stratégique arrivé à saturation à un moment où personne n'avait le temps de s'en occuper, avec pertes de données à la clé. Le volume actuel d'ASPIC sur le réseau (un peu plus de 65 Mo) est dérisoire au regard des quelque 300 Go encore libres sur le NVMe de son poste — mais Jean-Marc raisonne sur la durée du projet et sur la tendance (de nouvelles applications viendront occuper `C:` au fil du temps), pas sur l'instantané d'aujourd'hui. Claude a reconnu ce raisonnement comme fondé plutôt que d'insister sur la marge disponible dans l'immédiat.
**Décision finale, actée par Jean-Marc : abandon complet de l'accès direct au disque, retour à l'organisation existante.** Dans ses propres mots : *"restons zen, oublions cette idée d'accéder directement à une partie de mon disque autre que C: et restons sur l'organisation actuelle."* Le circuit de livraison redevient donc, sans changement, celui décrit en ouverture de cette section (téléchargement depuis la conversation, contournement `.js.txt` pour le JavaScript, renommage manuel `toto_nn.php` → `toto.php`) — les deux irritants identifiés en début de section restent entiers, faute d'un mécanisme technique aujourd'hui utilisable pour les résoudre. Effet positif retenu malgré tout par Jean-Marc : l'occasion de cette exploration l'a poussé à réorganiser son stockage réseau, une remise en ordre qu'il envisageait depuis longtemps et qu'il n'aurait pas faite sans ce prétexte.
**Fil ouvert et volontairement laissé de côté : un connecteur GitHub repéré au compte de Jean-Marc.** En cherchant le sélecteur de dossier, Jean-Marc a découvert qu'une intégration GitHub était déjà activée au niveau de son compte Anthropic, sans qu'elle soit pour autant utilisable dans la conversation en cours (les outils disponibles n'en portaient aucune trace au moment de la vérification). Jean-Marc a choisi de ne pas creuser ce point maintenant ("je vais voir plus tard pour cette connexion GitHub"), sans lien avec la décision de ne pas donner sa clé GitHub à Claude pour l'organisation de fichiers locale (section précédente), qui reste, elle, définitivement actée et non remise en cause par cette découverte.
**L'utilitaire de retrait de commentaires reste construit et disponible, indépendamment de l'issue de ce chantier.** Le renoncement à l'accès disque direct ne remet rien en cause côté "version exploitation" : les deux scripts (un pour le PHP par analyse syntaxique réelle via `token_get_all()`, un pour le HTML/JS via `terser` en configuration retrait-de-commentaires seul, sans compression ni renommage) ont été construits et validés ce même jour sur des fichiers réels du projet (syntaxe vérifiée après traitement, contenu fonctionnel inchangé) — prêts à resservir le jour où Jean-Marc en fera la demande, quel que soit le circuit de livraison alors en place pour les faire parvenir.
**Statut en fin d'échange : chantier clos, pas suspendu.** Contrairement à la formulation précédente de ce paragraphe (qui envisageait deux chantiers parallèles en cours), l'accès direct au disque de Jean-Marc est abandonné, pas différé — à ne pas rouvrir sans qu'il en fasse à nouveau la demande, par exemple si Anthropic corrige un jour le bug identifié ci-dessus. Le circuit de livraison par téléchargement reste donc la référence pour la suite du projet. Le numéro de version (partie `<conception>`) n'a pas été avancé à l'occasion de cette section, conformément à la décision initiale de Jean-Marc — la nouvelle organisation qui devait servir de test grandeur réelle pour ce déclenchement n'ayant finalement pas vu le jour, ce report reste sans objet pour l'instant plutôt que remis à plus tard.
## 17. Sortir du code en dur : règles et consignes comme mécanisme générique [Évolutions majeures] (7 septembre 2026)
**Origine.** Dès le lendemain de la première mise en œuvre du moteur générique (section 15), Jean-Marc a engagé exactement le chantier que cette section-là avait explicitement mis de côté comme méritant "une session dédiée" plutôt qu'un simple ajout au catalogue : une consigne capable d'appeler l'IA en cours de traitement (retrouver le code postal d'une ville saisie sans code postal), avec tout ce que ça implique de nouveau pour le moteur — coût réseau à ne jamais gaspiller, traçabilité de qui a réellement agi, et honnêteté du retour utilisateur en cas d'échec. Suffisamment substantiel pour justifier une nouvelle section plutôt qu'un addendum à la section 15.
**Le prix de la vitesse : hiérarchiser pour ne jamais payer un appel IA en pure perte.** Premier essai réel de Jean-Marc sur le nouveau moteur : une soumission vouée à échouer sur un Test (ex. champ obligatoire vide) déclenchait quand même, avant l'échec, un Traitement coûteux faisant appel à l'IA — appel réseau gaspillé, et aucune trace n'en subsistait puisque l'enregistrement entier était de toute façon rejeté ensuite. Diagnostic de Jean-Marc, structurel plutôt qu'un simple correctif ponctuel : *"il faut qu'on hiérarchise les traitements : d'abord les traitements de cohérence, après les traitements par IA."* Plutôt que de traiter ce cas précis à part, l'ordre d'exécution du moteur lui-même a été restructuré en trois phases séquentielles, distinguées par un seul attribut déjà présent dans le catalogue (`FON_VisuelAttenteIA`, voir plus bas) : d'abord les Traitements sans appel IA, puis tous les Tests (le premier échec arrête tout avant d'atteindre la moindre étape IA), et seulement une fois tous les Tests passés, les Traitements IA. Une seule distinction générique déjà présente sert donc à la fois de commande d'affichage (le badge, ci-dessous) et de garde-fou de coût — aucune nouvelle colonne, aucun cas particulier par fonction.
**Un badge générique pour ne jamais laisser l'utilisateur dans le flou pendant un appel réseau.** Un Traitement pouvant désormais réellement contacter un service externe avant la fin d'un enregistrement, Jean-Marc a voulu un retour visuel plutôt qu'un silence pendant l'attente. Nouvel endpoint `consignes_apercu.php`, et une convention de fonction jumelle : tout Traitement marqué `FON_VisuelAttenteIA='O'` doit être accompagné d'une fonction `<fonction>_seraitDeclenchee(array $valeurs): bool` — pure, sans appel réseau — répondant à "ce traitement se déclencherait-il réellement sur ces valeurs", utilisée pour décider, avant même de tenter l'enregistrement, s'il faut afficher un badge de chargement générique. Volontairement générique plutôt que personnalisé par agent/couleur : Jean-Marc a explicitement écarté un badge coloré par agent (*"si un jour un traitement fait appel à plusieurs agents à la suite, il ne faudrait pas que l'écran se transforme en sapin de Noël"*) et son affichage systématique à chaque enregistrement, IA ou non (*"l'utilisateur pourrait s'affoler sur le coût systématique d'une insertion client"*). Plusieurs allers-retours sur la taille du badge (130 → 50 → 25 → retour à 65px) avant validation — un détail purement cosmétique, mais qui a nécessité de regarder le rendu réel (Playwright) plutôt que de deviner une valeur en pixels dans l'abstrait.
**Traçabilité : qui a réellement agi, jamais un nom inventé.** Premier jet de Claude sur la journalisation d'une action IA : un prénom d'agent codé en dur ("Mat"). Repéré et corrigé après une question directe de Jean-Marc (*"d'où sors-tu le diminutif Mat ?"*) — Claude a reconnu l'avoir inventé, sans source. Décision retenue : le nom de l'agent journalisé dans une réalisation vient désormais uniquement de `CNS_Agent` (la consigne elle-même), jamais d'une valeur proposée par la fonction de traitement — même principe que celui déjà en place pour un agent en échec de Test. Dans le prolongement direct, Jean-Marc a voulu qu'un enregistrement de réalisation garde le prénom affiché de qui a agi (humain ou IA) sans avoir besoin de le recalculer plus tard : *"si on stocke le prénom de l'utilisateur d'un côté et le prénom de l'agent en dur on est cool."* Une première proposition de Claude (jointure `ASP_Users` recalculée à la lecture) a été explicitement écartée par Jean-Marc, sur deux arguments distincts : la complexité de la requête (*"Ta requête SQL risque d'être compliquée non ?"*) et surtout la portabilité multi-bases du projet (*"comment vas-tu faire pour les agents qui sont dans une autre base ?"*, en écho direct à l'architecture MIRADOR, section 8). Solution retenue : un instantané écrit une seule fois à la création de la réalisation (`REA_NomAffiche`) — côté humain via `$_SESSION['USR_Prenom']` fixé une fois pour toutes à la connexion, côté IA via le nom déjà connu de l'agent — zéro requête supplémentaire à la lecture, zéro risque de base croisée.
**Un renommage anodin en apparence, une leçon retenue.** À l'occasion de cette traçabilité, Jean-Marc a rappelé l'existence d'une table `ASP_Agents` déjà en place (utilisée pour le pilotage vocal, sections 11-12) et proposé d'harmoniser sa colonne `AGN_Nom` en `AGN_Prenom`, cohérent avec `USR_Prenom`. Claude a validé le renommage en affirmant "aucun impact côté code" — sans avoir grep le nom de colonne dans l'ensemble des fichiers existants. Conséquence concrète et immédiate pour Jean-Marc : *"j'ai un message qui me dit que la liste des agents n'est pas disponible !"* — cinq fichiers pré-existants (`agents.php`, `micro.js`, `contact_ia_panel.js`, `contact_ia_interprete.php`, `agent_notes.php`) référençaient encore `AGN_Nom`, cassant au passage le pilotage vocal. Réaction de Jean-Marc, sans dramatisation : *"Classique à ce stade du développement."* Leçon explicitement actée par Claude comme réflexe permanent pour la suite du projet, au-delà de ce seul incident : **grep systématiquement le nom d'une colonne dans tout le code avant d'affirmer "aucun impact" sur un changement de schéma, même quand ça semble anodin** — un changement de schéma n'est jamais gratuit à évaluer sans preuve, quelle que soit l'ancienneté ou la banalité apparente de la colonne touchée.
**Le premier vrai "contrat de retour enrichi" pour une consigne à appel IA — plus modeste que prévu, mais réel.** La section 15 anticipait un contrat à trois issues (silencieux / besoin de précision / question à poser) pour ce type de consigne, jugé trop tôt à concevoir dans l'abstrait. Ce qui a réellement été construit ce soir est un premier incrément volontairement plus modeste : réutilisation du mécanisme de clé réservée déjà existant (`_realisation`, jamais écrite dans `$data`, extraite par le moteur) et ajout d'une seconde clé du même type, `_avertissement` — une simple chaîne, affichée immédiatement à l'écran, sans que le front-end sache jamais d'où elle vient (mécanisme générique, pas un cas particulier "code postal" câblé côté écran). `consigne_completer_code_postal`, quand elle ne peut rien déduire d'exploitable pour une ville ambiguë ou inconnue (le cas Paris, découpée en arrondissements, sans code postal unique), laisse désormais une trace honnête dans tous les cas : une `_realisation` est journalisée que l'appel ait réussi ou échoué (Jean-Marc avait explicitement signalé l'anomalie inverse : *"il y a un appel fait à l'IA et pas de trace dans les réalisations, ce qui n'est pas normal"*), et `_avertissement` fait en plus remonter l'échec à l'utilisateur sans délai. À noter honnêtement : ce n'est pas encore le contrat à trois issues complet envisagé en section 15, seulement un succès silencieux ou un échec avec avertissement — un choix délibéré de construire la plus petite chose réelle plutôt que l'abstraction complète par anticipation, dans la continuité de la discipline déjà appliquée sur ce projet ("généraliser à partir de 3 répétitions concrètes constatées", section 6).
**D'un toast qui disparaît à un message qui exige une décision.** Trois allers-retours d'affinage dans la soirée sur le seul retour visuel de cet avertissement, chacun corrigeant un défaut concret repéré par l'usage réel : rouge et centré comme un vrai message d'erreur plutôt qu'un toast neutre en bas d'écran ; le panneau reste en mode édition au lieu de repasser silencieusement en mode vue (*"tu peux l'afficher en rouge et centré et rester dessus comme un message d'erreur"*) ; puis, une fois testé, le message disparaissait encore trop vite et la fiche restait visuellement "non validée" aux yeux de Jean-Marc malgré un enregistrement réellement réussi en base — solution retenue : un message réellement bloquant, sans disparition automatique, avec un unique bouton "Valider" dont le clic est la seule chose qui referme le message et fait alors passer l'affichage en mode vue. Dans les mots de Jean-Marc : *"je souhaite que le message s'affiche et reste en place [...] avec une instruction claire 'Saisissez le code postal vous-même' et que lorsque l'utilisateur clique, la fiche soit validée."* Point de conception à retenir : ce clic ne redéclenche jamais un enregistrement, il ne fait que clore l'état "attention requise" — le contact concerné est déjà bel et bien enregistré depuis le tout début de la séquence.
**Statut.** L'ensemble validé par Jean-Marc au fil des essais réels de la soirée même, aucune modification de code en attente au-delà de ce qui est déjà livré. Deux points laissés ouverts consciemment plutôt qu'oubliés : le contrat à trois issues complet (silencieux/besoin de précision/question à poser) reste à concevoir le jour où un second cas concret en montrera le besoin réel, plutôt que d'être généralisé dès maintenant sur la seule base de ce premier exemple ; et le clic sur "Valider" ne relance aujourd'hui aucune revalidation automatique du champ concerné — à ajouter délibérément si un futur cas le justifie, pas par anticipation.
Version : `<code>` avait déjà avancé plus tôt dans cette même session de travail (`V1.14.15` → `V1.15.15`) pour du code livré en amont de cette réflexion ; c'est cette section-ci qui justifie de faire avancer `<conception>` de 15 à 17 (16 ayant déjà été utilisé plus tôt le même jour par la section précédente, in fine sans incidence sur la conception d'ASPIC) — nouvelle version : **V1.15.17**.
@@ -67,10 +67,36 @@ Conventions retenues pour les valeurs de colonnes (choisies par Jean-Marc, diff
**Test réel réussi en fin de session, sans aucune modification de code :** Jean-Marc a ajouté trois nouvelles lignes dans `ASP_Consignes` (`NON_VIDE` sur `CNT_Prenom` et `CNT_AdrVille`, réutilisant la fonction déjà cataloguée) — comportement immédiatement actif après dépôt des fichiers déjà livrés, aucun fichier PHP/JS retouché. Preuve de concept validée par Jean-Marc : *"On peut dire qu'on n'est pas mauvais !"*
**Reste à faire, noté en fin de session :**
- Concevoir un nouveau type de consigne pour les cas nécessitant un appel IA en cours de traitement (ex. retrouver le code postal d'une ville saisie sans code postal) — contrat de retour plus riche que Traitement/Test actuel (silencieux / besoin de précision / question à poser), gestion d'échec réseau, coût et latence d'un appel externe. Session dédiée à prévoir, pas un ajout mineur au catalogue existant.
**Reste à faire, noté en fin de session du 6 septembre :**
- Concevoir un nouveau type de consigne pour les cas nécessitant un appel IA en cours de traitement (ex. retrouver le code postal d'une ville saisie sans code postal) — contrat de retour plus riche que Traitement/Test actuel (silencieux / besoin de précision / question à poser), gestion d'échec réseau, coût et latence d'un appel externe. Session dédiée à prévoir, pas un ajout mineur au catalogue existant. *(Premier incrément construit dès le lendemain, voir 7 septembre 2026 ci-dessous — pas encore le contrat complet à trois issues.)*
- Écran de gestion des consignes par le boss (au lieu de `INSERT`/`UPDATE` SQL à la main) — à construire après stabilisation du contrat ci-dessus, pour ne pas le refaire.
- Réflexion sur un catalogue restreint de consignes/fonctions avancées à proposer aux futurs utilisateurs de l'agence, sans leur ouvrir la création libre de A à Z — argument commercial identifié par Jean-Marc ("Possibilité de nouvelles consignes pour vos assistants").
- Accumulation de plusieurs messages d'erreur à la fois (le moteur ne remonte aujourd'hui que le premier test en échec).
- Gestion des consignes transverses à toute la fiche (`CNS_Champ` NULL, ex. contrôle de doublon) — non traitée par le moteur actuel.
- Distinction Saisie/Validation réellement exploitée un jour (temps réel), si le besoin redevient assez fort pour justifier la complexité écartée ce soir.
## Suite — 7 septembre 2026 : hiérarchisation, traçabilité, et premier appel IA réel dans une consigne
**Contexte stratégique complet : Réflexions stratégiques, section 17 ([Évolutions majeures]).** Ce qui suit est le compte rendu technique correspondant.
**1. Badge de chargement IA générique.** Nouvel endpoint `consignes_apercu.php` et convention de fonction jumelle : tout Traitement marqué `FON_VisuelAttenteIA='O'` dans `ASP_Fonctions` doit être accompagné d'une fonction `<FON_NomPHP>_seraitDeclenchee(array $valeurs): bool`, sans aucun appel réseau, qui répond seule à "ce traitement se déclencherait-il réellement sur ces valeurs". `auMoinsUneConsigneIaSeraitDeclenchee()` (`moteur_consignes.php`) interroge ces fonctions jumelles pour toutes les consignes actives du contexte/portée, avant même une tentative d'enregistrement — `liste_contacts.html` n'affiche le badge `#badge-ia-actif` que si la réponse est positive, jamais de façon systématique. Rendu : rond, centré à l'écran comme un toast d'erreur, 65px de côté après plusieurs essais (130 → 50 → 25 → 65), vérifiés au rendu réel via Playwright plutôt qu'en pixels devinés. `pointer-events:none` (jamais un obstacle au clic, même principe que les autres éléments purement informatifs de l'écran de fond).
**2. Hiérarchisation des trois phases d'`appliquerConsignes()`.** Bug réel découvert par Jean-Marc : une soumission vouée à échouer sur un Test déclenchait quand même, avant l'échec, un Traitement IA coûteux — appel réseau gaspillé, sans même laisser de trace puisque l'enregistrement entier était rejeté ensuite. Le moteur exécute désormais trois phases strictement séquentielles, distinguées par le seul attribut `FON_VisuelAttenteIA` déjà présent : (1) tous les Traitements de cohérence (`FON_VisuelAttenteIA != 'O'`), (2) tous les Tests (le premier échec arrête tout, avant d'atteindre la moindre étape IA), (3) seulement si tous les Tests ont réussi, les Traitements IA (`FON_VisuelAttenteIA = 'O'`). Nouvelle fonction interne `executerTraitements(array $consignesTraitement, array &$data, array &$journalisations, array &$avertissements): void`, appelée deux fois (phase 1 et phase 3) avec un sous-ensemble différent de consignes.
**3. Traçabilité de l'agent réel dans une réalisation journalisée.** `executerTraitements()` ne fait plus confiance à un nom d'agent proposé par la fonction de traitement elle-même (source d'un bug déjà corrigé : un prénom "Mat" resté codé en dur sans aucune source) — le nom journalisé dans `_realisation.agent` vient désormais systématiquement de `$c['CNS_Agent']` (la consigne active elle-même), tronqué à 15 caractères UTF-8, avec un repli sur la valeur de la fonction puis sur `'IA'` seulement si `CNS_Agent` est vide. Même principe déjà en place côté `$agentEchec` pour un Test en échec.
**4. `REA_NomAffiche` — instantané du nom affiché, jamais recalculé à la lecture.** Nouvelle colonne sur `ASP_Realisations`, remplie une seule fois à la création de chaque ligne : côté humain, `$_SESSION['USR_Prenom']` (désormais chargé et stocké en session dès `aspic.php`, à la connexion — requête étendue `SELECT USR_Nom, USR_Prenom FROM ASP_Users`) ; côté IA, le même nom d'agent que celui journalisé dans `_realisation.agent` (voir point 3). Une première approche par jointure `ASP_Users` recalculée à la lecture a été écartée (complexité de la requête, et surtout incompatibilité avec un futur agent hébergé dans une autre base MIRADOR) au profit de cet instantané écrit une seule fois — zéro requête supplémentaire à la lecture, zéro risque de base croisée. `realisations.php` (GET et POST) et `contacts.php` (`journaliserRealisationsIA()`) mis à jour en conséquence ; `liste_contacts.html` affiche `r.REA_NomAffiche || r.REA_CodeUser || ""` et la colonne "Qui ?" a été élargie de 40 à 90px pour ne plus tronquer "Jean-Marc"/"Matilda".
**5. Renommage `ASP_Agents.AGN_Nom` → `AGN_Prenom` (à l'initiative de Jean-Marc), et une régression corrigée.** Fait pour homogénéiser avec `USR_Prenom`. Claude a validé ce renommage en affirmant "aucun impact côté code" sans avoir grep le nom de colonne dans l'ensemble du projet — cinq fichiers pré-existants du pilotage vocal (`agents.php`, `micro.js`, `contact_ia_panel.js`, `contact_ia_interprete.php`, `agent_notes.php`) référençaient encore `AGN_Nom`, cassant la liste des agents ("la liste des agents n'est pas disponible !"). Tous corrigés le même soir. Leçon actée pour la suite (voir Réflexions stratégiques, section 17) : grep systématiquement le nom d'une colonne dans tout le code avant d'affirmer "aucun impact" sur un changement de schéma.
**6. `consigne_sans_chiffre()` — nouveau Test générique.** `consignes_fonctions.php` : `return trim($valeur) === '' || !preg_match('/\d/', $valeur);`. Ajoutée au catalogue (`ASP_Fonctions`, code `SANS_CHIFFRE`) puis appliquée par Jean-Marc lui-même via trois nouvelles lignes `ASP_Consignes` (Nom, Prénom, Ville) — aucun fichier PHP/JS retouché pour l'étendre à un troisième champ, confirmant une fois de plus le principe du chantier.
**7. `consigne_completer_code_postal()` — premier vrai appel IA dans une consigne, avec trace honnête en cas d'échec.** Reprend le contrat existant (`_realisation`, clé réservée déjà en place) et introduit une nouvelle clé réservée symétrique, `_avertissement` — une simple chaîne, affichée immédiatement à l'écran par le front-end sans qu'il sache jamais d'où elle vient. Quand l'IA ne peut rien déduire d'exploitable (ville ambiguë comme Paris, découpée en arrondissements) : une `_realisation` est journalisée dans tous les cas (même en échec — corrige l'anomalie signalée par Jean-Marc : un appel IA sans la moindre trace), et `_avertissement` est en plus renvoyé au front. `moteur_consignes.php` (`executerTraitements()`) extrait les deux clés en parallèle dans un nouveau tableau `$avertissements`, remonté par `appliquerConsignes()` (nouveau paramètre `?array &$avertissements = null`) puis par `contacts.php` dans la réponse JSON (`'avertissements' => $avertissementsIA`).
**8. Affichage de l'avertissement côté écran — trois itérations dans la soirée.** D'abord un toast neutre, identique aux autres. Puis rouge et centré comme un vrai message d'erreur (`afficherToast(message, true)`), et le panneau reste en mode édition au lieu de repasser en mode vue après l'enregistrement (`afficherDetailPourId(idContact, avertissements.length ? "edition" : "vue")`) — pour que l'utilisateur puisse corriger tout de suite le champ resté incomplet, `contactCourant` étant malgré tout rafraîchi pour éviter un double POST en cas de nouvelle tentative d'enregistrement. Puis, une fois testé, le message disparaissait encore trop vite et la fiche restait visuellement "non validée" alors qu'elle était bien enregistrée : `afficherToast()` accepte désormais un 4ᵉ paramètre optionnel (`onValider`) qui, s'il est fourni, supprime la disparition automatique et ajoute un bouton "Valider" (nouvelle classe `.toast-bouton`) — le clic ferme le message et exécute `onValider`, ici un simple `basculerModeDetail("vue")` (aucune revalidation, aucun nouvel enregistrement déclenché, le contact étant déjà enregistré depuis le début de la séquence). Le texte de l'avertissement, côté `consignes_fonctions.php`, a été rendu plus impératif ("Saisissez le code postal vous-même.") en cohérence avec ce fonctionnement bloquant.
**Version.** `<code>` déjà avancé en tout début de cette session de travail (`V1.14.15` → `V1.15.15`, avant même le badge IA du point 1). `<conception>` avancé en fin de session à `17` (Réflexions stratégiques, nouvelle section 17) — version finale de la session : **V1.15.17**.
**Reste à faire, noté en fin de session du 7 septembre :**
- Le contrat de retour à trois issues (silencieux / besoin de précision / question à poser), envisagé le 6 septembre, reste à concevoir dans son ensemble — ce qui a été construit ce 7 septembre n'en couvre que deux (succès silencieux, échec avec avertissement), volontairement, en attendant un second cas concret qui justifierait la généralisation.
- Tous les points laissés ouverts le 6 septembre (écran de gestion des consignes, catalogue commercial restreint, accumulation de plusieurs messages d'erreur, consignes transverses `CNS_Champ` NULL, distinction Saisie/Validation) restent entiers, aucun n'a été traité ce 7 septembre.