ADR 0093 – Apprentissage des corrections
Accepté (2026-10-17, fil B du jalon 4, cadre : ADR 0086 « étage 1 bis »)
ADR 0093 – Apprentissage des corrections
Statut : Accepté (2026-10-17, fil B du jalon 4, cadre : ADR 0086 « étage 1 bis »)
L’assistant ne doit pas reproduire la même erreur tous les jours. Il retient quels mots du titre ont conduit à quelle valeur d’un champ, par simple comptage, sans modèle.
Décision
Stockage. Migration V17__assist_hint.sql : assist_hint(word, field, value, hits, updated_at), clé (word, field, value). word est un mot significatif du titre (sans accents ni casse, singulier approché, 3 lettres au moins, hors mots de liaison, 12 par titre au plus).
Champs apprenables. Ceux des guess.rules[].set et ceux de la clé facultative guess.learn (config/captures/*.yaml, champs à énumération vérifiés au chargement). Rien d’autre n’est jamais retenu.
Ce qui nourrit la table (un coup par mot pour chaque champ apprenable) :
- à la création d’une capture : les valeurs saisies par marque et les devinettes acceptées (une correction ou une confirmation) ;
- à la sortie d’un nœud de l’inbox (événement
InboxLeft, publié parNodeService.setInbox(false), écouté après la validation de la transaction du classement) : les valeurs de ses champs apprenables au moment du classement — « Classer comme… » comme « Accepter » ; une annulation de lot ne défait pas ce qui a été appris. Une valeur égale audefaultdu schéma (posée par le type, pas choisie) n’est pas retenue.
L’apprentissage n’atteint jamais l’écriture qui l’a provoquée : transaction à part, erreur journalisée, mots et champs écrits dans un ordre fixe (pas d’interblocage entre deux écritures concurrentes). Une valeur apprise que la configuration n’admet plus (retirée de l’énumération) n’est pas proposée.
Ce qu’elle produit. Pour un champ apprenable non saisi, la valeur la plus retenue pour les mots du titre devient une devinette d’origine learned : confiance = part de cette valeur parmi les valeurs retenues × m / (m + 1), où m est le nombre de corrections par mot trouvé (2 corrections concordantes : 0,67 ; 9 : 0,90). Sous minConfidence, ou en cas d’égalité entre deux valeurs, rien n’est proposé. Une devinette apprise remplace celle d’une règle quand elle est au moins aussi confiante ; autoAccept ne la rend « sûre » qu’à partir d’environ 6 corrections concordantes.
Maîtrise. GET /api/assist/hints (nombre de lignes) et DELETE /api/assist/hints (« Oublier ce que l’assistant a appris », bouton de la page Données). L’export ZIP contient assist-hints.json (mot, champ, valeur, nombre). La sauvegarde (pg_dump) la couvre déjà.
Alternatives écartées
- Bayésien naïf complet (probabilités sur tous les mots, lissage) : le volume personnel ne le justifie pas ; le comptage par mot est lisible et explicable (« parce que chaudière → maison, 5 fois »).
- Apprendre de toute modification d’un nœud : bruit (corrections de statut, de date) ; seules les valeurs des champs déclarés apprenables comptent.
- Table de poids globale par champ : mélange des domaines ; le mot reste la clé.
Limites connues
- Pas d’oubli progressif : une habitude abandonnée met du temps à céder la place (le bouton « Oublier » est total ; un oubli par mot est reporté).
- Seuls les champs à énumération s’apprennent ; le projet proche et les dates, non.
- La table ne contient pas d’identifiant de nœud : supprimer un nœud n’efface pas ce qu’il a appris.