Chapitres

DOC-04 / Référence technique · Chapitre 08

Mémoire et apprentissage du harness Synedre OS

Ce chapitre décrit l'architecture à trois niveaux de mémoire de Synedre (réflexe, Zettelkasten, vectoriel pgvector), les automates d'indexation associés et la boucle d'apprentissage par cicatrices et leçons.

Mémoire & apprentissage

Cette page décrit comment le harness agentique se souvient grâce à une mémoire à trois niveaux, comment il retrouve l'information pertinente par rappel sémantique, et comment il capitalise erreurs et succès en règles réutilisables.

1. Mémoire à trois niveaux

Le système distingue trois mémoires de granularité et de discipline d'écriture croissantes.

┌──────────────────────────────────────────────────────────────────┐
│ NIVEAU 1 — Mémoire réflexe                                       │
│   Chargée dans CHAQUE session. Règles dures, retours, références.│
│   Stricte et consultable par recherche textuelle ; une entrée    │
│   par ligne dans l'index (≤ 200 caractères par entrée).          │
├──────────────────────────────────────────────────────────────────┤
│ NIVEAU 2 — Base de connaissance doctrinale (Zettelkasten)        │
│   Le « pourquoi » : décisions, doctrine, concepts. Exploratoire. │
│   Zone brouillon = dépôt libre ; zone consolidée = validée       │
│   uniquement sur ordre explicite.                                │
├──────────────────────────────────────────────────────────────────┤
│ NIVEAU 3 — Index vectoriel (sémantique)                          │
│   Index sémantique de tout ce qui précède + tables DB.           │
│   Vecteurs cosinus HNSW 1024 dimensions. Rappel RAG.             │
└──────────────────────────────────────────────────────────────────┘

Niveau 1 — Mémoire réflexe

  • Un fichier d'index central recense toutes les entrées ; les détails sont répartis dans des fichiers thématiques (retours, préférences utilisateur, références projet).
  • Ces fichiers sont injectés dans le contexte de chaque session : c'est la mémoire réflexe, chargée sans rappel explicite.
  • Réservée aux vraies doctrines impactantes. La règle de rédaction : une entrée d'index = une ligne, environ 200 caractères maximum.

Niveau 2 — Base de connaissance doctrinale (Zettelkasten)

  • Organisée en sous-dossiers : notes consolidées, boîte de réception brouillon, cartographies thématiques, journaux quotidiens, notes éphémères.
  • Liens inter-notes en syntaxe wiki. En-tête YAML avec champs type et status.
  • Règle de promotion : la boîte de réception est la zone de dépôt libre (l'agent écrit ici sans restriction) ; la zone consolidée n'est jamais modifiée sans ordre explicite. Aucune fusion automatique brouillon → consolidé n'est autorisée — c'est un garde-fou de gouvernance.

Niveau 3 — Index vectoriel sémantique

  • Table vectorielle avec index HNSW (similarité cosinus) et contrainte d'unicité par couple (type de source, identifiant de source).
  • Vecteurs de dimension 1024, produits par le modèle d'embedding du fournisseur IA.
  • Couvre toutes les sources : mémoire réflexe, base doctrinale, cicatrices, doctrines, chantiers, agents, drills, conduites, itérations ReAct.

2. Indexation

Deux automates distincts alimentent respectivement les niveaux 2 et 3. Il est important de ne pas les confondre :

  • Le premier remplit l'index structurel de la base de connaissance (recherche textuelle et navigation dans l'interface hub).
  • Le second remplit l'index vectoriel (rappel sémantique RAG).

2.1 Indexeur structurel de la base de connaissance

Cet automate parcourt l'ensemble des sous-dossiers de la base de connaissance et maintient une table relationnelle synchronisée.

  • Parse l'en-tête YAML de chaque note et extrait les liens inter-notes.
  • Synchronisation incrémentale : compare la date de modification du fichier à l'état en base ; n'écrit que si la note a changé. Les entrées orphelines (fichier supprimé) sont retirées automatiquement.
  • Colonnes indexées : chemin relatif, type, titre, tags, corps, liens, taille, date de modification, dates d'ajout et de mise à jour.
  • Options disponibles : --force (réindexation complète), --stats (statistiques sans écriture).
  • Planification : toutes les 15 minutes. Idempotent.

2.2 Automate d'embedding vectoriel

Cet automate produit les vecteurs sémantiques via le modèle d'embedding du fournisseur IA (1024 dimensions) et les insère ou met à jour dans l'index vectoriel.

Sources indexées et volumes indicatifs :

Type de source Origine Volume indicatif
Cicatrice Entrées de la table des cicatrices pourvues d'une description ~740
Victoire Cicatrices classées comme victoires ~4
Mémoire réflexe Fichiers de mémoire réflexe (hors index principal) ~226
Base doctrinale Notes de la base de connaissance (toutes zones) ~14
Doctrine Doctrines actives ~25
Chantier Table des chantiers ~10
Agent Table des agents ~30
Drill Table des drills ~31
Conduite Conduites actives ~17
Itération Triplets ReAct (raisonnement / action / observation) ~16
  • Déduplication : chaque chunk est empreintépar hachage SHA-256 de son contenu. Si le couple (type de source, identifiant) présente déjà le même hash, le chunk est ignoré — aucun appel inutile au fournisseur IA.
  • Découpage : stratégie MVP — un fichier = un chunk, tronqué à 16 000 caractères. Un découpage intelligent multi-chunk est prévu pour une phase ultérieure.
  • Traitement par lots : 50 inputs par appel d'embedding.
  • Insertion : UPSERT sur le couple (type de source, identifiant) — la ligne existante est mise à jour si le contenu a changé.
  • Options disponibles : --rebuild (vidage complet puis ré-embedding), --source <type> (source unique), --dry-run.

Réindexation immédiate d'une cicatrice

Dès qu'une cicatrice est gravée au cours d'une boucle ReAct, une fonction de réindexation unitaire insère ou met à jour immédiatement le vecteur correspondant — sans attendre le prochain cycle planifié. La cicatrice devient ainsi recherchable dans le RAG dès la fin du run.

Planification des automates mémoire

  • Indexeur structurel : toutes les 15 minutes.
  • Automate d'embedding vectoriel : sync incrémental complet quotidien (toutes sources, sans reconstruction). La réindexation unitaire en temps réel (cicatrices ReAct) reste active en parallèle.
  • Boucle de rêve (consolidation doctrinale) : quotidienne, en début de nuit.
  • Détecteur de patterns : hebdomadaire.
  • Détecteur de propositions de compétences : hebdomadaire.
  • Moniteur de propositions de compétences : toutes les heures.
  • Métriques mémoire : quotidiennes, tôt le matin.
  • Consolidation mémoire : mensuelle (1er du mois).
  • Boucle de maintenance nocturne : quotidienne, tôt le matin.

Moteur de rappel sémantique et lexical

Le moteur de rappel permet à un agent de retrouver des fragments de mémoire pertinents à partir d'une requête textuelle. Il est accessible via la compétence /memoire <requête> et expose trois modes de recherche configurables.

Pipeline de recherche

La requête entrante est traitée selon le mode sélectionné, puis les résultats sont re-classés avant d'être retournés :

requête texte
   │
   ├─ mode 'sem'    (similarité vectorielle) ── embedding 1024d → tri par distance cosine
   ├─ mode 'lex'    (correspondance lexicale) ── mots ≥ 3 car. → OR-tsquery → ts_rank
   └─ mode 'hybrid' (DÉFAUT) ────────────────── RRF k=60 : score = Σ 1/(60+rang_i)

[filtre par portée : scope]
LIMIT fetch_k (= k×3 si re-classement par importance)
   │
   ▼
re-classement : score = similarité × (1 + importance/10) × exp(-âge_jours/365)
   │
   ▼
top-K final ──► incrémentation du compteur de rappel

Détail des modes

  • Mode vectoriel (sem) : la requête est transformée en vecteur dense de 1 024 dimensions via le service d'embedding du fournisseur IA. La recherche s'appuie sur la distance cosine entre ce vecteur et ceux stockés en base. Interprétation des scores : au-delà de 0,75 le résultat est très pertinent ; entre 0,65 et 0,75 il est pertinent ; en dessous de 0,65 une validation manuelle est recommandée.
  • Mode lexical (lex) : les mots d'au moins trois caractères sont extraits et combinés en requête OR (« a | b | c ») appliquée sur un index plein-texte français. Un résultat doit correspondre à au moins un terme. Ce mode ne sollicite aucune API externe et rattrape efficacement les slugs et noms propres que l'embedding peut diluer.
  • Mode hybride (hybrid, défaut) : fusionne les deux classements par Reciprocal Rank Fusion (RRF, k = 60). Score final : Σ 1/(60 + rang_i). Un document absent d'un mode reçoit 0 pour ce mode, sans pénaliser l'autre. Les scores RRF sont typiquement inférieurs à 0,1 : seul le rang relatif est significatif, non les valeurs absolues.

Re-classement par importance et récence

Activé par défaut, ce mécanisme sur-récupère k×3 candidats, puis applique aux cicatrices la formule :

score = similarité × (1 + importance/10) × exp(-âge_jours/365)

Effet pratique : une cicatrice récente d'importance maximale est boostée d'un facteur ≈ 2 ; une cicatrice vieille d'un an d'importance minimale est ramenée à ≈ 0,4 × sa similarité brute.

Anti-courbe d'oubli (bump recall)

Chaque cicatrice servie voit son compteur de rappel incrémenté de façon non bloquante. Le processus d'archivage programmé ne purge que les cicatrices dont ce compteur est resté à zéro — garantissant que les connaissances effectivement réutilisées ne sont jamais archivées prématurément.

Portées disponibles

Le paramètre --scope filtre les types de sources interrogées. Les portées exposées sont : iterations, cicatrices, victoires, memory, brain, doctrine, chantiers, agents, drill, conduite, all. La portée brain agrège plusieurs sous-types internes de connaissances structurées.

Options en ligne de commande

  • --k <entier> : nombre de résultats retournés.
  • --mode lex|sem|hybrid : mode de recherche (défaut : hybrid).
  • --scope <portée> : filtre la nature des sources.
  • --json : sortie machine.

Hook pré-chantier

Un hook s'active automatiquement avant toute création de squelette de chantier. Il extrait le titre de l'opération, lance le moteur de rappel en mode hybride (k = 4) sur ce titre, et injecte les quatre résultats les plus pertinents dans le flux de sortie avant la création — sans bloquer l'opération (exit 0 garanti). En cas d'indisponibilité du service d'embedding (limite de débit atteinte), le système bascule automatiquement en mode lexical. L'objectif est d'éviter de recréer une cicatrice, une doctrine ou un chantier déjà connu, en rattrapant les correspondances que l'index linéaire de mémoire principal aurait manquées.

Harness d'évaluation du rappel

Un harness de non-régression vérifie en continu que les modifications apportées au moteur de rappel n'en dégradent pas les performances. Il fonctionne en lecture seule : le compteur de rappel n'est jamais modifié lors des évaluations.

Métriques calculées

Métrique Définition
recall@k Intersection entre les résultats attendus et le top-k, divisée par le nombre de résultats attendus — moyennée sur l'ensemble des requêtes du jeu de test.
mrr@10 Inverse du rang du premier résultat pertinent dans le top-10 (0 si absent) — moyenné sur l'ensemble des requêtes.
top1_accuracy Proportion des requêtes pour lesquelles le premier résultat correspond à un identifiant attendu.

Un résultat est considéré comme correspondant si l'identifiant attendu (insensible à la casse) est une sous-chaîne de l'identifiant retourné — ce qui rend l'évaluation robuste aux préfixes de chemin et aux formats composites.

Contrôle du débit

En modes vectoriel et hybride, le harness respecte un délai fixe entre chaque appel au service d'embedding, avec un backoff exponentiel en cas de limite de débit atteinte (jusqu'à cinq tentatives). En mode lexical, aucun appel externe n'est effectué.

Flags et codes de sortie

Commande / flag Effet Code de sortie
(aucun) Mode gate : compare les métriques courantes au baseline figé ; échoue si la régression dépasse la tolérance. 0 ou 1
--baseline Fige un nouveau baseline en exécutant le mode hybride en production. 0
--mode-sweep Compare les trois modes (lex / sem / hybrid) — informatif uniquement, sans gate. 0
--tol <flottant> Tolérance de régression acceptable (défaut : 0,05). —
--json Sortie machine. —
(baseline absent) Avertissement et arrêt immédiat. 2

Graphe de connaissances (expérience bornée)

Statut : expérience à durée déterminée, décision go/no-go prévue courant 2026. Réversible sans impact sur les composants existants.

Cette expérience vise à déterminer si la proximité structurelle — « quels hooks et cicatrices se trouvent à deux sauts au maximum du fichier que l'agent s'apprête à modifier ? » — surpasse la similarité sémantique du moteur de rappel et le matching lexical du détecteur d'entropie pour la sélection du contexte pertinent.

Modèle de données

Trois tables constituent l'expérience :

  • Table des nœuds : huit types fermés (hook, event, cicatrice, doctrine, note, chantier, chemin, commande), contraints par vérification SQL.
  • Table des arêtes : huit types de relation fermés ; chaque arête porte une preuve obligatoire, un niveau de confiance et une origine (derive pour les arêtes calculées, manuel pour les arêtes saisies à la main). Les arêtes manuelles ne sont jamais écrasées ni élaguées.
  • Table de journalisation ombre : compare à chaque invocation ce que le graphe aurait proposé par rapport aux résultats du matching lexical, sans rien modifier au comportement réel.

Peuplement du graphe

Le graphe est peuplé par des extracteurs strictement déterministes : paramètres système, en-têtes de hooks, liens entre documents, corps des hooks et relations de protection. Aucun modèle de langage n'intervient dans l'extraction : une arête générée par LLM déplacerait le risque d'hallucination dans le graphe lui-même.

Requête de voisinage

Une requête de proximité remonte tous les nœuds atteignables en deux sauts maximum depuis un chemin ou une commande donnée, via une traversée récursive non orientée. La confiance d'un chemin est le produit des confiances de ses arêtes.

Mode ombre

Lorsque le mode ombre est activé dans la configuration locale, le détecteur d'entropie journalise silencieusement ce que le graphe aurait injecté, sans modifier le comportement en production. La latence ajoutée est inférieure à 300 ms et tout échec est silencieux.

Critères de décision (go/no-go)

Le graphe sera adopté si son rappel@5 dépasse celui du mode vectoriel de 15 points au moins, ou si l'union des deux méthodes dépasse le vectoriel seul de 20 points — et si la latence médiane reste sous 150 ms.

Mesure initiale (J0)

Méthode Rappel@5 Latence p50
Graphe de connaissances seul 0,03 7,5 ms
Mode vectoriel seul 0,30 —
Union graphe + vectoriel 0,30 —

Verdict J0 : no-go en l'état. La cause est structurelle : la relation de protection ne capture que les hooks qui inspectent la chaîne de commande ; les hooks qui testent un état (présence d'un marqueur de fusion, contenu de fichier) sont invisibles au graphe. Par ailleurs, seule une minorité de hooks cite une cicatrice dans son en-tête. La décision finale sera rendue après sept jours d'analyse des journaux du mode ombre.

Boucle d'apprentissage : erreurs → vérifications → suggestions → leçons

C'est le cœur de la capitalisation. Une erreur (ou un succès) devient une donnée, puis une suggestion concrète, puis — après validation humaine — une règle chargée dans toutes les sessions futures.

 Chantier / boucle ReAct
      │ erreur résolue (ou succès reproductible)
      ▼
Registre des cicatrices  (kind=failure | victory ; leçon associée)
      │ réindexation vectorielle immédiate
      │ scoring d'importance (LLM) ; learnable=true/false
      ▼
Moteur d'apprentissage  (LLM : cicatrice apprenante → suggestion)
      │ INSERT suggestion (status='pending')
      ▼
Hub de validation  (validation HUMAINE : feed / apply / [id])
      │ status → applied | refused | modified
      ▼
Journal d'audit  +  application réelle dans la destination
      │ (directive orchestrateur / config / mémoire / inbox / skill / outil)
      ▼
Boucle fermée : la règle est en mémoire ou dans la directive → réflexe session suivante

4.1 Le registre des cicatrices

Le registre des cicatrices est la source unique des leçons. Chaque enregistrement porte notamment : un identifiant, le codename de l'agent concerné, le type d'erreur, une description, la leçon tirée, la cause racine, l'agent correcteur, le tenant associé, la sévérité, l'état de résolution, la nature (kind), un score d'importance, un compteur de rappels, la date du dernier rappel, un indicateur d'apprentissabilité, des tags, une catégorie proposée, la confiance et le raisonnement de qualification, ainsi que la date d'ajout.

  • kind sépare échecs et succès dans la même table : failure (majoritaire), cicatrice, victory, plus quelques valeurs héritées (bug, mistake, convention, pattern).
  • La leçon (check_added) : pour un échec, ce qu'on a ajouté pour ne pas recommencer ; pour une victoire, le pattern à reproduire.
  • Le score d'importance (entier) est calculé par LLM inline lors de l'enregistrement, via le routage IA configuré pour la fonctionnalité de scoring d'importance (par défaut un modèle Mistral léger). Non bloquant : si le LLM est indisponible, le champ reste nul et la boucle nocturne rattrape. Ce score pondère le rappel (bonus ×2 pour importance maximale).
  • L'indicateur d'apprentissabilité (learnable) est la porte d'entrée du moteur d'apprentissage.
  • Graver une victoire : invoquer le skill dédié (/graver-victoire) en passant le champ kind à "victory". Jamais de SQL brut. Les tags doivent être fournis sous forme de tableau PostgreSQL littéral (chaîne "{a,b,c}"), pas d'une liste Python.

4.2 Le moteur d'apprentissage — cicatrice apprenante → suggestion

Le moteur d'apprentissage suit un pipeline en cinq étapes :

  1. Récupération : les cicatrices marquées comme apprenantes et n'ayant pas encore généré de suggestion sont récupérées, triées par importance décroissante puis par date, avec un plafond par exécution (50 par défaut).
  2. Purge des données personnelles avant envoi au LLM : un filtre de dépersonnalisation est appliqué à la cicatrice, puis réappliqué à la sortie du LLM avant insertion — défense en profondeur.
  3. Appel LLM : le modèle est appelé avec un prompt figé (mode JSON) via le fournisseur IA configuré. Note : pour ce moteur spécifique, le fournisseur et le modèle sont définis en dur dans le code (un modèle Mistral léger) et n'utilisent pas le routage IA dynamique de la base de données.
  4. Format de sortie LLM : le modèle renvoie un objet JSON structuré contenant la destination visée, le texte de la suggestion, ainsi qu'un avant/après illustrant le changement proposé.
  5. Insertion : la suggestion est insérée avec le statut pending. Le processus est idempotent, avec un délai de courtoisie entre chaque appel LLM.

Les six destinations possibles pour une suggestion :

Destination Sens
claude_md Règle à ajouter ou modifier dans la directive de l'orchestrateur
settings_json Configuration des hooks, permissions ou variables d'environnement
memory Note persistante de mémoire de niveau 1 (réflexe session)
brain_inbox Nouvelle note Zettelkasten dans l'inbox conceptuelle (doctrine)
skill Création ou amélioration d'un skill invocable
chantier_outil Nouveau chantier ou outil automatisé dans le cœur du système

4.3 Tables d'apprentissage et validation humaine

Trois tables structurent ce pipeline :

  • Table des suggestions : identifiant, référence à la cicatrice source, destination visée, texte de la suggestion, avant/après, statut, date de création.
  • Cycle de statuts : pending → applied | refused | modified.
  • Journal d'audit : identifiant, référence à la suggestion, auteur de l'application, horodatage, instantané du diff appliqué.

La validation est exclusivement humaine, via le hub. Trois routes exposent le flux : lecture de la liste des suggestions en attente, application d'une suggestion (passage à applied avec enregistrement dans le journal d'audit), et mise à jour individuelle (refus ou modification). Le moteur ne fait que proposer — aucune auto-application n'est possible.

4.4 Leçons post-chantier (module Montessori)

Un module dédié génère des leçons synthétiques à l'issue d'un chantier. Il est invocable via un skill spécifique et assigné à l'agent @academy.

  • Il charge un bundle d'audit du chantier : métadonnées, travaux, tâches, les 30 dernières itérations de tâches, les cicatrices liées et les journaux d'exécution (tronqués à ~6 000 caractères par exécution). Le volume total est plafonné à ~45 000 tokens.
  • Garde-fou ROI : refuse un chantier de moins de 3 travaux (contournable avec un flag explicite).
  • Chemin principal : l'agent Claude est invoqué via un pont de spawn node-pty, avec des outils restreints en lecture seule (Read, Grep, Glob). Deux tentatives sont effectuées, avec une pause entre les deux. Ce chemin n'utilise pas le client IA générique.
  • Chemin de secours (uniquement si le fournisseur principal est absent ou explicitement remplacé) : appel au client IA générique avec un modèle Mistral léger. Trois tentatives avec backoff exponentiel (2 s puis 4 s).
  • Prompt figé en 5 sections : delta tokens estimés vs réels, top 3 erreurs récurrentes, top 3 patterns à standardiser, 1 doctrine candidate, 1 outil à créer.
  • Sortie : une note de leçon déposée dans l'inbox du Vault, avec frontmatter indiquant le type, le statut draft et le relecteur assigné.
  • Promotion : jamais automatique. Le fondateur examine la note et la déplace manuellement vers la mémoire permanente (RAG) ou la mémoire de réflexe de niveau 1. Doctrine des trois niveaux de mémoire.

4.5 Pipeline patterns → skills (opérationnel)

Distinct de la boucle cicatrices → suggestions, un second pipeline opérationnel transforme les patterns récurrents observés dans les boucles ReAct en propositions de skills. C'est le pattern d'auto-amélioration par détection de récurrence.

Itérations de tâches (raison / action / observation, status done|pass)
      │ scan hebdomadaire
      ▼
Détecteur de propositions de skills  (LLM-first, via <pont-de-spawn>)
      │ INSERT proposition (status='pending', itérations sources, preuve de pattern)
      ▼
Page hub de validation  (Vue + API)  ── validation HUMAINE (fondateur)
      │ liste / valider-rejeter / stats
      ▼
Promotion → skill natif  (devient invocable /<slug>)
  • Le détecteur de propositions de skills (cron hebdomadaire, dimanche à 04h UTC, après la synthèse quotidienne) : charge un lot d'itérations de tâches récentes au statut done ou pass, les soumet à un LLM (invoqué via subprocess avec un timeout de 180 s) qui repère les patterns présents dans au moins 3 tâches et méritant un skill. Pour chaque proposition : si le slug proposé existe déjà (skill natif ou proposition en cours), l'entrée est ignorée ; sinon, une proposition est insérée avec le statut pending, les identifiants des itérations sources et le texte de preuve fourni par le LLM. Flags --dry-run et --limit disponibles. Approche LLM-first plutôt que clustering statistique (volume d'itérations encore faible).

  • Le moniteur de propositions (cron horaire) : alerte le fondateur si le nombre de propositions au statut pending dépasse un seuil configuré (défaut : 10). Cool-down d'une heure via fichier d'état. Fournit des statistiques : totaux par statut, temps moyen de validation, validations par agent, ajouts dans la dernière heure. Notifications via le client e-mail de la façade — jamais via SMTP direct.

  • Validation humaine : une page hub dédiée expose la liste des propositions, le détail et les actions valider/rejeter, ainsi que des statistiques. Une proposition validée est promue vers le registre des skills natifs.

À ne pas confondre : un second squelette de détection de patterns (cron du dimanche à 03h) est présent dans le code mais reste inactif — sa propre docstring l'indique explicitement : il scanne et journalise, mais ne crée pas encore de propositions (logique de pattern matching à venir). C'est bien le détecteur décrit ci-dessus qui alimente réellement le registre de propositions.

4.6 Autres automates connexes de la boucle

4.6.1 La boucle nocturne de maintenance (cron quotidien, 04h UTC)

La boucle nocturne de maintenance consolide la mémoire et produit des insights en dix fonctionnalités (F1–F5, F7–F11 — F6 est réservée au scoring d'importance en ligne). Garde-fou transversal : jamais de fusion automatique de l'inbox vers la mémoire permanente ; le mode sans écriture (--dry-run) est la valeur par défaut.

Le fournisseur et le modèle de chaque fonctionnalité sont résolus dynamiquement depuis le routage IA en base de données.

  • F1 — Détection de cicatrices répétées : compare les cicatrices du jour J au registre vectoriel (similarité cosinus ≥ 0,85, top 11 voisins) ; si au moins 2 occurrences similaires sont trouvées dans le passé, un draft de promotion est créé dans l'inbox.
  • F2 — Compaction des transcripts de session : analyse les journaux de session du jour (max 30 sessions, les sessions contenant des secrets sont ignorées par regex) via LLM ; extrait 3 à 5 faits durables (décision, livraison, cicatrice, constat) et les dépose dans le journal quotidien du Vault. En mode sans écriture, aucun appel LLM n'est effectué.
  • F3 — Récapitulatif matinal : e-mail de synthèse envoyé au fondateur via la façade e-mail. Ignoré si aucun draft ni journal n'a été produit.
  • F4 — Détection de divergence documentaire :
    • 4a : vérifie 5 paliers canoniques dans le fichier de tarification ;
    • 4b : scan récursif de patterns obsolètes définis dans un fichier de configuration YAML dédié (seuils : ≥ 3 occurrences × ≥ 2 fichiers) ;
    • 4c : fichiers Markdown avec tableau ≥ 6 lignes et plus de 50 % de contenu numérique → recommandation de migrer vers une table en base de données.
    Les résultats alimentent des drafts dans l'inbox.
  • F5 — Réflexion nocturne : inspirée des Generative Agents (Park et al., 2023). Pour chaque agent actif, les 20 dernières cicatrices résolues sont soumises au LLM, qui génère 3 questions introspectives et 3 abstractions, déposées dans l'inbox. En mode sans écriture, seul le décompte des agents éligibles est effectué.
  • F7 — Courbe d'oubli : archive (état resolved=2) les cicatrices de plus de 180 jours sans aucun rappel (recall_count=0) ; plafond de 200 archivages par exécution. Jamais d'effacement — réversible par mise à jour. Les cicatrices archivées deviennent invisibles au moteur de rappel sémantique (qui filtre sur resolved=1).
  • F8 — Pro-activité chantier ↔ e-mails : scrute les chantiers avec contacts externes non vides (statuts paused, planning, discovery, dev), relie automatiquement les e-mails entrants/sortants par adresse expéditrice, reconstruit le fil complet, et le LLM classe la situation en : archive-refused, act-now, awaiting-them ou no-action-needed. (Agent Marco Polo.)
  • F9 — Audit d'obsolescence des chantiers : Marco Polo version interne (lecture seule). Scrute les chantiers paused ou planning inactifs depuis un seuil de jours configurable, calcule des signaux d'obsolescence et classe via LLM en still-relevant, maybe-obsolete ou archive-recommended. Les verdicts non-still-relevant remontent dans le récapitulatif matinal pour décision du fondateur.
  • F10 — Audit de dérive des personas : mensuel, auto-gaté au 1er du mois. Scanne les agents actifs, mesure le score de dérive de chaque persona, persiste l'historique et remonte le top 3 des agents drifting dans l'e-mail matinal.
  • F11 — Tick de coût quotidien : agrège les coûts de la veille par agent, compare à la moyenne des 7 derniers jours, envoie une alerte e-mail si le delta dépasse 20 %.

4.6.2 Le classificateur de cicatrices

Un automate dédié classifie les cicatrices non encore qualifiées (sans catégorie proposée). Le LLM renvoie un objet structuré qui est mappé colonne par colonne :

  • La catégorie proposée alimente le champ error_type_proposed ;
  • La sévérité reclassifiée met à jour severity si elle diffère de la valeur actuelle ;
  • Le score de confiance alimente qualify_confidence ;
  • Les tags mettent à jour le tableau de tags ;
  • Le raisonnement alimente qualify_reasoning.

Point d'attention : le verdict learnable renvoyé par le LLM n'est pas écrit directement dans la colonne learnable par cet automate. Il est sérialisé en préfixe du champ qualify_reasoning sous la forme learnable:true|false\n….

4.6.3 Pipeline de consolidation de la mémoire de niveau 1

Un pipeline de maintenance mensuelle assainit la mémoire de niveau 1. Il est déclenché le 1er de chaque mois à minuit UTC (avec verrou anti-chevauchement) et suit quatre étapes séquentielles :

  1. Validation de l'environnement : vérification des prérequis Python et des chemins nécessaires. Cette étape tourne en sous-processus isolé pour éviter les effets de bord d'import. Si elle échoue, le pipeline s'arrête immédiatement.
  2. Détection des liens morts : analyse du fichier d'index de mémoire et identification des références pointant vers des fichiers inexistants.
  3. Archivage des fichiers obsolètes : déplacement des notes démantelées ou obsolètes vers une destination d'archivage hors-dépôt, et suppression des références correspondantes dans l'index.
  4. Déduplication par empreinte : identification et suppression des fichiers parfaitement identiques (empreinte SHA-256).

Un rapport JSON est généré à chaque exécution, indiquant pour chaque étape : succès, durée et erreur éventuelle.

Le pipeline expose trois flags :

Flag Effet
(aucun) Pipeline complet avec écriture réelle
--dry-run Les étapes 3 et 4 sont court-circuitées ou simulées. Attention : l'étape 2 (détection des liens morts) s'exécute toujours, même en mode sans écriture, et peut produire des fichiers de rapport.
--validate-only S'arrête après l'étape 1 (validation d'environnement uniquement)

Les codes de sortie sont standardisés :

Code Sens
0 Pipeline complet OK (ou --validate-only OK)
1 Validation d'environnement KO — aucune autre étape exécutée
2 Erreur fatale dans une étape — pipeline arrêté
3 Mode --dry-run terminé (indicatif, aucune modification persistée)

Deux variables d'environnement sont indispensables (vérifiées à l'étape 1) : le chemin vers le répertoire de mémoire de niveau 1 et la destination d'archivage. Si l'une est absente, le pipeline retourne le code 1 sans exécuter aucune autre étape.

Un quiz exécutable de non-régression (16 vérifications en 4 modules, score 100 % requis) valide l'état réel du système après toute modification du pipeline :

  • Environnement / dépendances / cron : présence des scripts, dépendances Python installées, répertoire de mémoire accessible, entrée cron présente ;
  • Exécution : --validate-only retourne exit 0 ; --dry-run retourne exit 3 ou 0 ; détection des liens morts fonctionnelle ; validation de cohérence sémantique opérationnelle ;
  • Rapports : présence d'un rapport, 4/4 étapes OK, 0 liens morts, index de mémoire comportant au moins 10 liens ;
  • Documentation / rôles : support de formation complet, codes de sortie documentés, rôles documentés, frontmatter conforme.

Attention : le support de formation (docs/consolidation_training.md) est lu en dur par 4 des 16 vérifications du quiz. Le supprimer ferait passer le score sous 100 % et bloquerait le pipeline en non-régression. Toute suppression de ce fichier exige d'adapter préalablement ces 4 vérifications.

Un automate de métriques de mémoire (cron quotidien à 06h UTC) alimente une série temporelle sur 90 jours : nombre de fichiers de mémoire, taille en Ko, nombre de lignes dans l'index, liens morts et orphelins. Des alertes sont émises dans le tableau de bord de monitoring si des seuils sont dépassés.

4.7 Rappel du modèle utilisateur (canal structuré, distinct du RAG sémantique)

Le rappel sémantique vectoriel n'est pas l'unique canal de mémoire. Un module dédié charge le modèle utilisateur depuis une table de profil (dimensions JSONB) pour l'injecter dans les briefings agents — c'est un rappel structuré et ciblé, pas vectoriel.

  • Tranches directes (clés des dimensions JSONB) : style de communication, emploi du temps, profil, compétences, historique, préférences, données strictement privées.
  • Tranche composite core : style de communication + préférences cognitives + horaires de rendez-vous. Calibrée pour l'injection en briefing (moins de 1 000 tokens) et n'incluant jamais les données strictement privées.
  • API : get_profile(slice=…) retourne un dictionnaire ; format_for_briefing(...) retourne un texte prêt à injecter. En ligne de commande : python3 -m <module-profil-utilisateur> --slice core [--json|--format-briefing].

5. Boucle de maintenance nocturne

Cette couche orchestre la cohérence de la documentation et la santé globale du système. Un orchestrateur nocturne inspecte la fidélité de la documentation, mesure la santé globale, répare mécaniquement les références mortes, déclenche la régénération autonome des chapitres dérivés, et pousse un instantané assaini vers synedre.com.

La séquence d'étapes est la suivante :

  1. Percevoir — le détecteur de dérive mesure l'écart entre documentation et code.
  2. Couverture — le scanner de couverture identifie les angles morts.
  3. Réparer — le correcteur de références mortes traite mécaniquement les liens brisés.
  4. Régénérer — la réécriture profonde, gatée, recompose les chapitres dérivés.
  5. Proposer — le cycle de staging produit des brouillons en attente de validation.
  6. Publier la doc — la publication automatique applique les gardes-fous (fuite, anti-gourou, dérive).
  7. Re-percevoir — le détecteur de dérive tourne une seconde fois, après publication, pour mesurer l'état réel final.
  8. Soigner — le bilan de santé agrège cinq dimensions et produit une note de soin.
  9. Publier l'instantané — le synchroniseur pousse l'instantané assaini vers synedre.com (best-effort).

Planification : la boucle s'exécute quotidiennement à 05h00 UTC via le planificateur de tâches système. Les événements sont journalisés dans un fichier de log dédié.

5.1 L'orchestrateur de la boucle

L'orchestrateur est le point d'entrée unique de la boucle de maintenance nocturne. Il applique plusieurs garde-fous globaux :

  • Kill-switch par base de données : si la configuration active du système indique que la boucle est désactivée, l'orchestrateur s'arrête silencieusement sans exécuter aucune sous-étape.
  • Verrou anti-emballement : un fichier de verrou portant le PID courant est créé au démarrage. Si un processus précédent est encore vivant, la boucle s'interrompt immédiatement. Le verrou est supprimé dans tous les cas à la fin de l'exécution, y compris en cas d'exception dans une sous-étape.
  • Codes de retour sémantiques : les codes 1 et 2 signalent respectivement une dérive présente et un état de santé critique — ce sont des statuts informatifs, non des échecs fatals. La boucle ne sort en erreur réelle que si une sous-étape plante effectivement.
  • Rapport quotidien : à la fin de chaque exécution, un récapitulatif idempotent (étape : code de retour) est inséré dans la table de rapport du matin. L'opération est idempotente (DELETE + INSERT sur la clé de la boucle).
  • Double mesure de dérive : le détecteur de dérive tourne une première fois en début de nuit, puis une seconde fois après la publication de la documentation. Cela garantit que le bilan de santé final reflète l'état réel post-régénération, et non l'état du début de nuit.

Les flags disponibles sur l'orchestrateur sont les suivants :

Flag Effet
(aucun) Exécution complète en mode live.
--dry-run Toutes les sous-étapes reçoivent --dry-run ; le kill-switch est contourné.
--no-deep Saute l'étape de réécriture profonde.
--deep-max N Nombre maximum de chapitres traités en réécriture profonde (défaut : 4). La convergence réelle est bornée par --deep-budget-sec.
--deep-budget-sec N Budget mur en secondes pour la réécriture profonde (défaut : 4500 s = 75 min). La boucle ne démarre plus de nouveau chapitre au-delà de ce seuil.

5.2 Le bilan de santé

Le composant de bilan de santé agrège cinq dimensions en un instantané idempotent par date d'exécution, et produit un item visible dans le tableau de bord du matin.

Dimension Source de données Seuil critique
Proprioception Table de dérive documentaire ≥ 1 chapitre avec référence morte
Couverture Table de couverture documentaire Toujours en avertissement si ≥ 1 unité non couverte
Dette Backlog des tâches Au moins un item de priorité P0 en attente
Apprentissage Vue agrégée des cicatrices Rafraîchissement absent depuis plus de 3 jours (cron de refresh inactif)
Automates Journal d'erreurs cron + registre des automates ≥ 1 script désactivé dans le périmètre vaisseau-mère
  • Périmètre vaisseau-mère : seuls les automates appartenant au périmètre vaisseau-mère et marqués actifs entrent dans le calcul de santé. Un automate client ou volontairement désactivé ne dégrade pas la métrique.
  • Note de soin (agent Nightingale) : l'agent Gardien de la Santé lit les signes vitaux et rédige une note de soin en trois phrases maximum (en anglais). Cette voix est stockée dans le champ de métriques JSON de la ligne de bilan global. Si l'agent est indisponible, la valeur reste nulle sans bloquer le bilan.
  • Flags : --dry-run (bilan affiché, aucune écriture) ; --no-voice (métriques seules, sans note de soin).
  • Codes de sortie : 0 = ok, 1 = avertissement, 2 = critique.

Le bilan de santé écrit dans deux destinations :

Destination Rôle
Table de santé Instantané par date d'exécution et dimension (UPSERT idempotent), score 0–100, métriques JSON, résumé textuel.
Table de rapport quotidien Item du rapport du matin, idempotent sur la clé et la date.

5.3 Le synchroniseur d'instantané public

Ce composant lit les derniers instantanés de santé et de dérive documentaire depuis la base de données du vaisseau-mère (lecture seule), assainit le contenu (suppression des adresses IP, chemins internes, identifiants clients), puis pousse un instantané JSON vers la base de données de synedre.com.

Garde-fous :

  • Aucune écriture n'est effectuée côté vaisseau-mère : l'accès est strictement en lecture.
  • La migration de la table cible est idempotente (CREATE TABLE IF NOT EXISTS) et s'exécute automatiquement au premier run.
  • Un seul instantané par jour est conservé (UPSERT sur la date).
  • En cas d'erreur lors de la publication vers synedre.com, le composant renvoie un code d'erreur et journalise sur la sortie d'erreur standard, mais n'interrompt pas la boucle nocturne (comportement best-effort).

L'instantané publié expose : la santé globale et par dimension (scores, statuts, résumés assainis), la liste des chapitres en dérive (slug, type, score), et la note de soin de l'agent Nightingale. Ces données alimentent le cadran de maintenance visible sur synedre.com/documentation.

Flags : --dry-run (affiche le JSON, aucune écriture vers synedre.com).
Codes de sortie : 0 = ok, 1 = erreur de lecture vaisseau-mère, 2 = erreur de publication.

6. Façade IA centralisée

Tout appel vers un fournisseur d'intelligence artificielle dans le système passe par une façade unique. Cette doctrine garantit la traçabilité, la substituabilité des fournisseurs et le contrôle des coûts. La façade expose deux fonctions canoniques :

embed(text, *, provider="auto", model=None) -> list[float]

complete(mission, *, context="", provider="auto", model=None,
         json_output=False, timeout=90,
         api_key=None, meter_tag=None) -> str | dict | None

Routage par base de données

Lorsque provider="auto", la façade lit la table de routage IA en base de données. Cette table expose les colonnes feature, embed_provider, complete_provider, model et extra (JSONB). La structure repose sur une ligne de fallback global et des lignes par fonctionnalité qui fusionnent avec le fallback.

Avantage opérationnel : changer de fournisseur IA revient à mettre à jour une ligne en base de données. Aucun redéploiement n'est nécessaire ; la boucle nocturne relit la configuration à chaque exécution.

En cas d'indisponibilité de la base de données, la façade bascule sur des valeurs par défaut canoniques : Mistral pour l'embedding, Claude pour la complétion.

Fournisseurs et modèles

Usage Fournisseurs valides Modèle par défaut
embed Mistral, Voyage, OpenAI mistral-embed / voyage-3 / text-embedding-3-small
complete Claude (Anthropic), Mistral, OpenAI claude-haiku-4-5 / mistral-large-latest / gpt-4o-mini

Comportement par fournisseur

  • Embedding : chaque fournisseur dispose de son propre adaptateur HTTP. Mistral réutilise le module de rappel vectoriel interne pour l'embedding.
  • Complétion Claude (Anthropic) : deux chemins de facturation coexistent.
    • Chemin API directe : si une clé API Anthropic est fournie (paramètre ou variable d'environnement), la façade appelle directement l'API Anthropic. Ce chemin est réservé aux usages facturés sur compte Console Anthropic (clients en mode Agence Étendue). Il embarque une logique de retry sur erreurs 429/5xx (3 tentatives avec backoff) et trace chaque complétion dans la table de métriques d'usage IA (provider, modèle, tag de facturation, tokens entrée/sortie, coût estimé en USD). Les alias courts (haiku, sonnet, opus) sont résolus vers les identifiants complets de modèle.
    • Chemin CLI : en l'absence de clé API, la façade délègue à l'agent Gauss (persona neutre), sur le forfait Max interne. Ce chemin est réservé à l'usage interne.
  • Complétion Mistral : appel HTTP direct, température fixée à 0.0, format JSON activable. 3 tentatives (2 retries) sur erreurs 429/5xx avec backoff. Les erreurs 4xx autres que 429 sont permanentes et ne déclenchent pas de retry.
  • Complétion OpenAI : appel HTTP direct vers l'API OpenAI.

Traçabilité et parsing robuste

  • Métriques d'usage : chaque complétion via le chemin API directe Anthropic est tracée en base (provider, modèle, tag de facturation, tokens, coût). Ce mécanisme est fail-soft : une erreur de traçage ne bloque pas la complétion. Il permet la refacturation par client via le champ meter_tag.
  • Parsing JSON robuste : en mode json_output, la façade tente d'abord un parsing direct, puis un nettoyage des balises de code, puis une extraction par motif {…}. Ce pipeline évite les échecs sur les réponses légèrement mal formées des modèles.

Garde-fous structurels

  • Aucun I/O au niveau module : toute logique est encapsulée dans des fonctions.
  • Imports providers en mode lazy : les dépendances ne sont chargées qu'à l'usage.
  • Pas de shadowing de la variable de log.

Clés API

Aucune valeur de clé n'apparaît dans cette documentation. Les clés sont lues exclusivement depuis l'environnement d'exécution via des variables nommées. Les fichiers porteurs sont exclus du dépôt Git (.gitignore).

Variable d'environnement Fournisseur Fichier porteur
Clé API Mistral Mistral Fichier d'environnement local (exclu du dépôt)
Clé API Voyage Voyage Fichier d'environnement local (exclu du dépôt)
Clé API OpenAI OpenAI Fichier d'environnement local (exclu du dépôt)
Clé API Anthropic Anthropic — chemin API directe (clients Agence Étendue) Fichier d'environnement local (exclu du dépôt)
Mot de passe base de données PostgreSQL — base du vaisseau-mère Fichier d'environnement hôte (exclu du dépôt)

Le chargement des variables est effectué au démarrage des automates Python : les fichiers d'environnement à la racine du dépôt sont parsés et les valeurs sont injectées dans l'environnement du processus via os.environ.setdefault (sans écraser les variables déjà présentes dans l'environnement système).

Souveraineté : Mistral est le fournisseur d'embedding canonique, conformément à la doctrine de souveraineté numérique européenne du projet.

7. Connexion à la base de données

Les automates Python se connectent à la base de données du vaisseau-mère via le port exposé par le conteneur de base de données sur la machine hôte. La connexion précise le nom de la base cible et le schéma de recherche dédié au vaisseau-mère, afin d'isoler les tables système des tables publiques.

  • Le conteneur de base de données héberge une base dont le nom diffère du nom du conteneur lui-même — distinction importante pour les scripts de connexion.
  • Le schéma de recherche est passé en option de connexion (search_path) de façon à ce que les requêtes sans préfixe de schéma ciblent automatiquement le bon espace de noms.
  • L'utilisateur de connexion est dédié aux automates et dispose des droits strictement nécessaires.

Tableau récapitulatif des composants

Le tableau suivant recense les principaux composants du système, classés par rôle fonctionnel. Chaque entrée indique le type d'exécution et la responsabilité conceptuelle du composant.

Composant Type Rôle
Indexeur de notes Tâche cadencée (toutes les 15 min) Parcourt la base de notes et les indexe dans le registre relationnel de la mémoire structurée.
Synchroniseur d'embeddings Tâche cadencée (nocturne) + appel inline Calcule et stocke les vecteurs sémantiques (1024 dimensions) pour toutes les sources ; supporte la réindexation ciblée à chaud lors d'un cycle ReAct.
Moteur de rappel RAG Recherche hybride (lexicale, sémantique, fusion par score) avec re-classement et mécanisme de promotion des résultats pertinents.
Harnais d'évaluation du rappel Assurance qualité Suite de non-régression mesurant recall@k, MRR@10 et précision en tête de liste, à partir d'un jeu de données doré et d'une ligne de base figée.
Greffon de rappel pré-chantier Hook automatique (avant création) Déclenche une recherche hybride (top 4) avant toute création structurée, sans bloquer le flux.
Orchestrateur de maintenance nocturne Tâche cadencée (nocturne, 05 h) Pilote la boucle complète : perception → couverture → réparation → régénération → proposition → publication de documentation → re-perception → soin → publication finale.
Bilan de santé Rapport multi-dimensionnel Évalue cinq dimensions de santé du système et consigne les résultats dans les registres de suivi quotidien.
Synchroniseur de santé public Synchronisation Exporte un instantané assaini (sans données sensibles) vers le VPS public, disponible jour par jour.
Façade IA Couche d'abstraction Point d'entrée unique pour les opérations d'embedding et de complétion ; gère le routage par fonctionnalité, le double chemin d'accès au modèle principal et la comptabilité d'usage par requête.
Moteur d'apprentissage Moteur Identifie les leçons marquées comme apprenables et génère des suggestions de consolidation à valider.
Rétrospective post-chantier Boucle de rétroaction Produit une leçon structurée à l'issue de chaque chantier ; utilise le modèle principal avec repli automatique sur un modèle alternatif en cas d'indisponibilité.
Consolidateur de features Tâche cadencée (toutes les 4 h, mode simulation par défaut) Consolide jusqu'à dix axes de fonctionnalités en mode test ; aucun effet en production sans validation explicite.
Détecteur de propositions de compétences Tâche hebdomadaire (LLM-first, fonctionnel) Analyse les patterns d'itérations et insère des propositions de nouvelles compétences dans le registre dédié, prêtes à validation humaine.
Moniteur de propositions de compétences Tâche horaire Émet une alerte vers le fondateur lorsque le nombre de propositions en attente dépasse un seuil configuré.
Détecteur de patterns (squelette) Tâche hebdomadaire — MVP inactif Analyse et journalise les patterns détectés, mais ne crée aucune proposition. Distinct du détecteur fonctionnel ci-dessus.
Qualificateur de leçons LLM Attribue à chaque leçon un type d'erreur, un niveau de sévérité, un score de confiance et un raisonnement ; marque automatiquement les leçons éligibles à l'apprentissage.
Hygiène de la mémoire Tâche mensuelle Nettoie la base de notes : supprime les liens morts, archive les entrées obsolètes, déduplique par empreinte de contenu ; produit un rapport mensuel.
Métriques mémoire Tâche cadencée (toutes les 6 h) Calcule les indicateurs de volumétrie et de qualité de la mémoire, conserve un historique sur 90 jours, émet des alertes si des seuils sont franchis.
Rappel utilisateur Recall contextuel Exploite le modèle utilisateur (préférences et dimensions comportementales en JSON) pour produire des briefings personnalisés à destination des agents.
Graphe de connaissances Expérimentation (go/no-go prévu ~2026-09-01) Construit un graphe déterministe, interrogeable en au plus deux sauts, avec évaluation intégrée et rapport parallèle non intrusif.

Registres de données

Registre Rôle
Registre des leçons Leçons d'échec et de victoire, niveau d'importance, éligibilité à l'apprentissage.
Registre vectoriel Vecteurs sémantiques (index HNSW, similarité cosinus).
Registre de notes structurées Index relationnel du Zettelkasten.
Registre des propositions de compétences Propositions générées, en attente de validation humaine.
Référentiel de compétences Compétences validées et actives (cible de promotion des propositions).
Registre des suggestions d'apprentissage Suggestions LLM en attente de validation.
Journal d'audit des apprentissages Trace immuable de chaque suggestion appliquée après validation.
Série temporelle mémoire Indicateurs de santé de la mémoire sur 90 jours glissants.
Modèle utilisateur Dimensions comportementales et préférences (JSON), utilisées pour les briefings agents.
Snapshots de santé Instantanés quotidiens des cinq dimensions de santé plus score global.
Snapshots publics assainis Instantanés exportés vers le VPS public, nettoyés de toute donnée sensible.
Table de routage IA Source de vérité unique pour le routage par fonctionnalité : fournisseur d'embedding, fournisseur de complétion, modèle cible, paramètres étendus.
Journal d'usage IA Enregistrement par requête : fournisseur, modèle, étiquette de comptabilité, tokens entrants/sortants, coût estimé — base de la refacturation par client.

Interfaces et points d'entrée utilisateur

  • Cadran de validation des compétences — interface hub permettant au fondateur d'approuver ou de rejeter les propositions de nouvelles compétences générées automatiquement.
  • Interface mémoire — permet à l'utilisateur de consulter et d'enrichir la base de connaissances du système.
  • Interface d'apprentissage — point d'entrée pour déclencher ou superviser les cycles d'apprentissage.
  • Interface de gravure de victoire — permet d'enregistrer explicitement un succès notable sous forme de leçon durable.
  • Jeu de données doré — ensemble de requêtes de référence utilisé par le harnais d'évaluation pour mesurer la qualité du rappel.
  • Ligne de base figée — snapshot des métriques recall@k, MRR et top-1 servant de seuil de non-régression automatique.