Skip to content

Automatic injection finds the target 60 percent of the time against 97 percent for recall, and default recall hides user memories by tag #706

Open

Description

@cdeust

Summary

The automatic path is weaker than the tool path. The per-prompt injection finds the target memory far less often than recall, the default recall hides auto-captured memories, and some ordinary user tags make a memory invisible to default recall.

Evidence

Measured by an independent audit on 2026-10-10 in an isolated SQLite profile (30 memories, 30 low-overlap paraphrase queries, main at b4a62b2), plus a read of the code.

  • Tool path: recall from a new process returned the target at k=10 for 30 of 30 queries (hit at k=3: 96.7 percent, MRR 0.78, 0.2 s warm). The real auto_recall hook (one process per prompt) injected the target for 18 of 30 queries (60 percent), 3 memories each, about 125 tokens, 0.36 s, and nothing for one query.
  • Auto-captured tool output (a Bash failure with its root cause) was returned at rank 1 only with include_low_signal=true.
  • mcp_server/handlers/recall_helpers.py line 160, LOW_SIGNAL_TAGS (source ADR-0431): the set contains the capture tags (auto-captured, tool-output, tool:bash and the other tool tags) and also ordinary words a user may use for their own memories, among them audit, automated and the stage-N tags. A memory carrying one of them is filtered out of default recall (lines 216 and 351).

Expected

The injection uses the same retrieval as the tool path within its time budget (the reranker, or an equivalent), and the gap is measured in CI on a fixed corpus. Default recall returns auto-captured memories, labelled as such, or says how many it hid. User tags are never used to hide a user's own memories: the filter keys on a capture marker the system writes, not on words the user may choose. Tests for each.

Activity

  1. cdeust commented on Nov 4, 2026

    @cdeust
    OwnerAuthor

    Première tranche proposée dans #863 (commit b4c41e0), en brouillon : Refs #706, pas Closes.

    Cause racine : LOW_SIGNAL_TAGS (ADR-0431) mélangeait des marqueurs de capture écrits par Cortex (auto-captured, tool:<nom>, _backfill, imported, session-summary) et des mots copiés de la liste d'admission du wiki qu'aucun écrivain de Cortex n'émet (audit, automated, wip, progress, code-review, stage-1 à stage-11). Une mémoire de l'utilisateur portant l'un de ces mots disparaissait du recall par défaut et de l'injection par déclencheur.

    Tranche livrée : l'ensemble ne contient plus que les marqueurs de capture ; ADR-1119 amende ADR-0431 ; AUDIT_TAGS du wiki inchangé. Tests : 29 passés sur les deux fichiers touchés, 264 passés sur tests_py/handlers et tests_py/core filtrés recall/inject.

    Non vérifié : benchmarks non lancés (torch et le conteneur PostgreSQL isolé indisponibles ici) ; aucun corpus de benchmark ne porte ces tags, donc la sortie du filtre y est identique par construction. Suite complète laissée à la CI.

    Tranches restantes :

    1. Le recall par défaut renvoie les mémoires auto-capturées étiquetées comme telles (aujourd'hui masquées, compte dans low_signal_dropped).
    2. Le filtre s'appuie sur un champ écrit par le système (source / write_class) plutôt que sur des tags.
    3. L'injection auto_recall utilise la même récupération que recall dans son budget de temps, avec l'écart mesuré en CI sur un corpus fixe.

    Generated by Claude Code

  2. cdeust commented on Nov 5, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : issue mise en hold — les tranches restantes demandent une décision du propriétaire.

    La tranche 1 (#863, fusionnée dans 7ac79b3) a retiré les mots utilisateur de LOW_SIGNAL_TAGS. Ce qui reste, lu sur main :

    1. « Default recall returns auto-captured memories, labelled as such, or says how many it hid » : la seconde branche existe déjà. recall renvoie low_signal_dropped (mcp_server/handlers/recall.py:646, ADR-0430). Question 1 : ce compteur suffit-il pour ce critère, ou voulez-vous que les mémoires auto-capturées soient renvoyées par défaut, étiquetées ? Ce second choix inverse ADR-0431.
    2. Filtrer sur un champ écrit par le système, et non sur les tags : le champ candidat est memories.write_class (ADR-0537/0688, mcp_server/shared/write_class.py). Il ne recouvre pas l'ensemble actuel. auto ne vise que post_tool_capture. _backfill et imported tombent dans mechanical, mais cette classe contient aussi ingest_codebase, seed_project, ingest_prd et les pointeurs wiki://, qui sont visibles aujourd'hui. session-summary n'a pas de classe propre. Question 2 : quelle règle voulez-vous ?
      • (a) cacher seulement write_class='auto' : backfill, import et résumés de session redeviennent visibles ;
      • (b) cacher auto et mechanical : le code et la doc ingérés disparaissent du recall par défaut ;
      • (c) ajouter une nouvelle valeur, ou un nouveau champ de provenance pour les captures. Cela demande une migration SQLite et PostgreSQL et un ADR.
    3. Parité entre l'injection auto_recall et recall, mesurée en CI : le reranker exige torch / sentence-transformers dans un hook qui lance un processus par prompt (0,36 s mesurés). Question 3 : quel budget de temps est acceptable pour l'injection, et le reranker peut-il y être chargé ? Il faut aussi un corpus fixe : celui de l'audit (30 mémoires, 30 paraphrases) est-il versionné quelque part ?

    Dès que l'une de ces questions est tranchée par un commentaire, le hold est levé au passage suivant et la tranche correspondante est livrée.


    Generated by Claude Code

  3. added
    autopilot:holdCI autopilot stood down: a human decision is required
    on Nov 5, 2026
  4. cdeust commented on Nov 12, 2026

    @cdeust
    OwnerAuthor

    Décision : cette issue n'attend plus de réponse du propriétaire.

    Le propriétaire a demandé le 12 novembre 2026 que les issues avancent sans lui ; il ne répondra pas aux questions posées ici. Ce commentaire de cdeust lève le hold et précise la demande. Il vaut pour toute la suite de cette issue.

    • Tranche toi-même chaque question restée ouverte : d'abord une décision écrite et acceptée du dépôt (ADR accepté, docs/), puis ce que le texte de l'issue propose ou exclut, puis les standards du dépôt ; à défaut, la plus petite tranche qui réalise ce que l'issue demande. Une valeur qui manque se mesure, elle ne s'invente pas.
    • Écris la décision dans un commentaire marqué <!-- ci-autopilot decision --> (ce qui est retenu, la raison et sa source, ce qui est écarté, comment revenir en arrière), puis livre la tranche dans une PR. Une décision écrite ne se rejoue pas aux passages suivants.
    • Ne repose pas autopilot:hold pour une question : seulement pour l'irréversible, un accès que tu n'as pas, une dépendance nommée encore ouverte ou le plafond de tentatives, en nommant exactement ce qui manque.
    • Jamais de tag, de release, de montée de version du projet ni de déclenchement manuel d'un workflow.

    Règle complète : #343 (comment)

    Écrit par la session « écosystème autonome » sur instruction du propriétaire (12 novembre 2026).


    Generated by Claude Code

  5. removed
    autopilot:holdCI autopilot stood down: a human decision is required
    on Nov 12, 2026
  6. cdeust commented on Nov 12, 2026

    @cdeust
    OwnerAuthor

    Hold autopilot:hold levé : un commentaire de cdeust (« Décision : cette issue n'attend plus de réponse du propriétaire », 12/11/2026) a été posté après la pose du hold.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions