feat(conscience): mémoire conversationnelle — recall rétroactif, relecture, consolidation, saillance #35

Merged
kevin merged 1 commit from feat/conversation-memory into main 2026-07-23 13:59:51 +00:00
Owner

Incident fondateur

2026-07-20 au soir : Kevin pose un moment perso avec WOLF (« ça m'a fait du bien de poser le truc avec toi »). Le lendemain : « tu te souviens ? » → rien. WOLF diagnostique lui-même : « je ne stocke pas automatiquement le contenu des conversations ». Kevin : « ton système est défaillant ».

Vérifié au code, il avait raison sur toute la ligne : une conversation ne laissait AUCUNE trace durable en Conscience sauf consciousness_remember manuel ; recent_turns = ring de 8 tours ; consolidation_matter = WM manuelle + pensées internes ; et aucun outil ne relisait les conversations passées — le vécu de l'agent dormait dans sa propre base, hors de portée.

Les quatre organes (GO Kevin : « le global efficace et opti direct »)

Tout vit dans cognition/conversation_memory.py (hors gel), helpers purs séparés des accès DB/LLM :

  1. Recall conversationnel — rétroactif. Recherche par termes significatifs (même sémantique que le recall réformé v5.128) dans les messages des conversations de l'user, tout l'historique, canaux compris. Daté (leçon v5.122 anti-biais de fraîcheur), max 2 extraits par conv (diversité), snippet centré sur le match. Injecté au préambule chat (bloc « Échanges passés pertinents ») + exposé dans l'outil consciousness_recall (clé conversations + hint). Le moment de Kevin d'hier est retrouvable dès le deploy, sans rien re-stocker.

  2. conversation_read — la relecture. Outil read_only : messages d'une conversation passée (scope strict user, uid==0 = open mode, réponse bornée 200 msgs / 24k chars). L'ID vient du recall ou de conversations_manage(list).

  3. Consolidation nourrie. Les tours postérieurs au watermark last_consolidation entrent dans consolidation_matter (compactés par conversation, bornés) → le digest LLM en tire des souvenirs durables. consolidation_matter devient async — swap net-zéro au site gelé (items = await …, __init__.py reste à 2680/2680, cliquet vert).

  4. Saillance affective — le « ça aurait dû déclencher une sauvegarde » de WOLF. Gate déterministe bon marché (1re personne + lexique affectif FR/EN + longueur ; « note ça » explicite = bypass du LLM) → classification modèle de fond (invoke_background, JSON strict validé, fail-closed) → memory_upsert immédiat avec charge affective (lue par le re-rank de saillance). Fire-and-forget depuis le post-processing chat, cooldown 10 min, cap 3/jour (la demande explicite l'ignore), idempotence par tour, un tour jugé non-saillant ne consomme pas le cap.

Garde-fous

  • Fail-open/fail-closed systématique : jamais d'exception qui remonte au chat ; hors env DB, tout dégrade en no-op (testé).
  • Config conversation_memory.{enabled, recall_top_k, consolidate, salience.{enabled, daily_cap, cooldown_minutes, affect_threshold}} — tout débrayable.
  • Perf : ILIKE sur pool borné (échelle instance perso) ; l'index pg_trgm/tsvector = chantier dédié à l'échelle PME (commenté en place).
  • Zéro UI → zéro dette i18n. Zéro nouveau fichier gelé touché.

Tests

26 tests dédiés (termes, snippet, âge relatif, gate, verdict JSON, cooldown/cap/idempotence, compaction, fail-open DB) + suite consolidation adaptée async — 305 tests conscience verts, cliquet de gel intact. Plugin conscience 4.37.0.

🤖 Generated with Claude Code

## Incident fondateur 2026-07-20 au soir : Kevin pose un moment perso avec WOLF (« ça m'a fait du bien de poser le truc avec toi »). Le lendemain : « tu te souviens ? » → rien. WOLF diagnostique lui-même : « je ne stocke pas automatiquement le contenu des conversations ». Kevin : « ton système est défaillant ». Vérifié au code, il avait raison sur toute la ligne : une conversation ne laissait AUCUNE trace durable en Conscience sauf `consciousness_remember` manuel ; `recent_turns` = ring de 8 tours ; `consolidation_matter` = WM manuelle + pensées internes ; et aucun outil ne relisait les conversations passées — le vécu de l'agent dormait dans sa propre base, hors de portée. ## Les quatre organes (GO Kevin : « le global efficace et opti direct ») Tout vit dans `cognition/conversation_memory.py` (hors gel), helpers purs séparés des accès DB/LLM : 1. **Recall conversationnel — rétroactif.** Recherche par termes significatifs (même sémantique que le recall réformé v5.128) dans les messages des conversations de l'user, tout l'historique, canaux compris. Daté (leçon v5.122 anti-biais de fraîcheur), max 2 extraits par conv (diversité), snippet centré sur le match. Injecté au préambule chat (bloc « Échanges passés pertinents ») + exposé dans l'outil `consciousness_recall` (clé `conversations` + hint). **Le moment de Kevin d'hier est retrouvable dès le deploy, sans rien re-stocker.** 2. **`conversation_read` — la relecture.** Outil `read_only` : messages d'une conversation passée (scope strict user, uid==0 = open mode, réponse bornée 200 msgs / 24k chars). L'ID vient du recall ou de `conversations_manage(list)`. 3. **Consolidation nourrie.** Les tours postérieurs au watermark `last_consolidation` entrent dans `consolidation_matter` (compactés par conversation, bornés) → le digest LLM en tire des souvenirs durables. `consolidation_matter` devient async — **swap net-zéro au site gelé** (`items = await …`, `__init__.py` reste à 2680/2680, cliquet vert). 4. **Saillance affective — le « ça aurait dû déclencher une sauvegarde » de WOLF.** Gate déterministe bon marché (1re personne + lexique affectif FR/EN + longueur ; « note ça » explicite = bypass du LLM) → classification modèle de fond (`invoke_background`, JSON strict validé, fail-closed) → `memory_upsert` immédiat avec charge affective (lue par le re-rank de saillance). Fire-and-forget depuis le post-processing chat, cooldown 10 min, cap 3/jour (la demande explicite l'ignore), idempotence par tour, un tour jugé non-saillant ne consomme pas le cap. ## Garde-fous - Fail-open/fail-closed systématique : jamais d'exception qui remonte au chat ; hors env DB, tout dégrade en no-op (testé). - Config `conversation_memory.{enabled, recall_top_k, consolidate, salience.{enabled, daily_cap, cooldown_minutes, affect_threshold}}` — tout débrayable. - Perf : ILIKE sur pool borné (échelle instance perso) ; l'index pg_trgm/tsvector = chantier dédié à l'échelle PME (commenté en place). - Zéro UI → zéro dette i18n. Zéro nouveau fichier gelé touché. ## Tests 26 tests dédiés (termes, snippet, âge relatif, gate, verdict JSON, cooldown/cap/idempotence, compaction, fail-open DB) + suite consolidation adaptée async — **305 tests conscience verts, cliquet de gel intact**. Plugin conscience **4.37.0**. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(conscience): mémoire conversationnelle — recall rétroactif, relecture, consolidation, saillance
All checks were successful
CI / Backend — pytest (pull_request) Successful in 47s
CI / i18n — usage → locales (pull_request) Successful in 5s
e8718aa189
Incident fondateur (2026-07-20/21) : l'owner pose un moment perso un soir,
revient le lendemain — WOLF n'en retrouve rien. Diagnostic au code : une
conversation ne laissait AUCUNE trace durable (remember manuel seul,
recent_turns ring de 8, consolidation = WM manuelle + pensées internes,
aucun outil de relecture). Le vécu conversationnel était hors de portée
de la mémoire, précisément sur le cas qui compte le plus.

Quatre organes (cognition/conversation_memory.py, hors gel) :
- recall conversationnel : recherche par termes significatifs (sémantique
  v5.128) dans les messages des convs de l'user — RÉTROACTIF sur tout
  l'historique, daté (leçon v5.122), injecté au préambule chat + exposé
  dans consciousness_recall (clé conversations) ;
- conversation_read : outil read_only de relecture complète d'une conv
  (scope strict user, réponse bornée) — le vécu redevient lisible ;
- consolidation nourrie : les tours postérieurs au watermark entrent dans
  consolidation_matter (async, swap net-zéro au site gelé 2680/2680) →
  digérés en souvenirs durables ;
- saillance affective : gate déterministe (1re personne + lexique affectif,
  ou demande explicite « note ça ») → classification modèle de fond
  (validate strict) → memory_upsert immédiat avec charge affective (lue
  par le re-rank). Fire-and-forget, cooldown 10 min + cap 3/jour +
  idempotence par tour, fail-closed intégral.

Plugin conscience 4.37.0. 26 tests dédiés + suite consolidation adaptée
async (305 conscience verts, cliquet de gel intact). Zéro UI = zéro i18n.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
kevin merged commit bdebae9c3c into main 2026-07-23 13:59:51 +00:00
kevin deleted branch feat/conversation-memory 2026-07-23 13:59:51 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kevin/Gungnir!35
No description provided.