You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In the real isolated ingestion campaign, remember(domain="scifact-comparison") persisted all 1812 facts under harness-comparison. Corpus verification initially found no rows in the requested domain. The resolver scans known repository fragments and can remap a supplied domain because a fragment matches another repository name.
Proposed solution
Distinguish explicit domain identity from an inferred path/name hint. Preserve the caller-selected identity or reject ambiguous resolution explicitly; preserve documented aliases deliberately rather than through accidental substring collisions.
Acceptance evidence
Reproduce the collision with a controlled repository registry and the public remember/recall contract.
An explicit scientific corpus domain cannot silently become an unrelated comparison repository domain.
Changing an unrelated repository in the registry cannot change the identity of an already explicit domain.
Document migration/alias behavior and ensure write/search/fetch agree on canonical scope.
Alternatives considered
Keep the current behavior and document its limits. This remains valid where the added guarantee has no user need; the issue should close with a documented product decision rather than assume that copying Hindsight is always appropriate. Reuse existing Cortex mechanisms before adding a second pipeline.
Scope assessment
MEDIUM. Raised from the October 10 Hindsight/Cortex comparison. Static observations refer to the pinned revisions below. They do not establish successful execution of Hindsight's whole pipeline or a repository-wide absence in Cortex. Priority is a proposal, not a release blocker.
CI autopilot : tranche 1 livrée dans #877 (Refs #721, ne ferme pas l'issue).
Cause racine reproduite : resolve_domain traite le domaine comme un indice et renvoie le canonique du plus long fragment de dépôt contenu dans l'entrée ; avec un dépôt harness-comparison, remember(domain="scifact-comparison") écrivait harness-comparison (test du handler en échec sans le correctif, vert avec).
Correctif : resolve_explicit_domain — seul un nom de dépôt exact (ou sa famille ADR-0647) est mappé ; tout autre nom est conservé tel quel, en minuscules.
Tranches restantes :
Priorité directory > domain dans remember alors que le schéma décrit domain comme un override — décision du propriétaire.
recall/fetch ne résolvent pas domain : écriture et recherche ne s'accordent pas sur le scope canonique (ex. cortex-cowork → cortex à l'écriture seulement).
Documenter alias et migration des lignes déjà écrites sous un domaine collisionné.
CI autopilot : tranche 3 livrée dans #914 (Refs #721, ne ferme pas l'issue ; commit b803e88).
Cause racine : remember et recall résolvent un domain explicite par resolve_explicit_domain, mais recall_hierarchical passait l'argument brut à get_memories_for_domain : recall_hierarchical(domain="cortex-cowork") construisait la hiérarchie sur un scope où aucune écriture n'a lieu.
Correctif : le handler public résout le domaine dans _scoped_by_explicit_domain avant _handler_impl ; un domaine blanc compte comme absence de domaine (ValidationError ADR-0045 R3). 8 tests, 7 échouent sans le correctif.
Non vérifié : tests PostgreSQL, gate de mutation, benchmarks (torch non téléchargeable dans cette session).
Tranches restantes :
Priorité directory > domain dans remember, alors que le schéma décrit domain comme un override : décision du propriétaire.
Les autres lecteurs prenant un domain (unified_search, drill_down, narrative…) : vérifier pour chacun si c'est un scope mémoire ou un domaine de profil, puis résoudre.
Documenter les alias et la migration des lignes déjà écrites sous un domaine collisionné.
C'est la 3e tentative sur cette issue : le prochain passage posera autopilot:hold si une tranche restante ne peut pas être fusionnée.
CI autopilot : tranche 4 dans #915 (Refs #721, ne ferme pas l'issue ; commit 538082e).
Cause racine : narrative passait le domain brut à get_memories_for_domain, alors que remember écrit sous resolve_explicit_domain(domain) ; narrative(domain="cortex-cowork") lisait un scope sans écriture.
Correctif : résolution par resolve_explicit_domain dans le handler ; domaine blanc = pas de domaine. 7 tests, 6 échouent sans le correctif.
Non vérifié : suite PostgreSQL, gate de mutation, benchmarks (torch non téléchargeable dans cette session).
Les tranches précédentes ont été fusionnées (#914 entre autres), le plafond de 3 tentatives sans fusion ne s'applique donc pas.
Tranches restantes :
Priorité directory > domain dans remember alors que le schéma décrit domain comme un override : décision du propriétaire.
Autres lecteurs qui passent un domain brut à get_memories_for_domain : get_project_story, drill_down, validate_memory, assess_coverage, detect_gaps, query_methodology (pour chacun, vérifier qu'il s'agit d'un scope mémoire et pas d'un domaine de profil).
Documenter les alias et la migration des lignes déjà écrites sous un domaine collisionné.
CI autopilot : tranche 7 dans #928 (Refs #721, ne ferme pas l'issue ; commit fd16b57).
Cause racine : assess_coverage passait le domain brut à get_memories_for_domain, alors que remember écrit sous resolve_explicit_domain(domain) ; assess_coverage(domain="cortex-cowork") notait un scope sans écriture.
Correctif : résolution par resolve_explicit_domain dans le handler ; domaine blanc = lecture globale ; le domain renvoyé est le scope lu. 7 tests, 6 échouent sans le correctif ; tests_py/handlers : 1909 passed, 81 skipped.
Non vérifié : suite PostgreSQL, suite complète, gate de mutation, benchmarks (torch non téléchargeable dans cette session).
Les tranches 1 à 6 ont été fusionnées : le plafond de 3 tentatives sans fusion ne s'applique pas.
Tranches restantes :
Priorité directory > domain dans remember : décision du propriétaire.
validate_memory, detect_gaps, query_methodology passent encore un domain brut à get_memories_for_domain (vérifier pour chacun qu'il s'agit d'un scope mémoire et pas d'un domaine de profil).
Documenter les alias et la migration des lignes déjà écrites sous un domaine collisionné.
CI autopilot : tranche 8 dans #929 (Refs #721, ne ferme pas l'issue ; commit eae007a).
Cause racine : validate_memory passait le domain brut à get_memories_for_domain, alors que remember écrit sous resolve_explicit_domain(domain). validate_memory(domain="cortex-cowork") validait un scope sans écriture.
Correctif : le handler résout le domaine par resolve_explicit_domain, et un domaine blanc compte comme une lecture globale. 7 tests, dont 6 échouent sans le correctif. tests_py/handlers : 1915 passed, 81 skipped, 1 failed. Cet échec (sqlite-vec absent du venv local) se produit aussi sur main.
Non vérifié : suite PostgreSQL, suite complète, gate de mutation, benchmarks (torch n'est pas téléchargeable dans cette session).
Les tranches 1 à 7 ont été fusionnées : le plafond de 3 tentatives sans fusion ne s'applique pas.
Tranches restantes :
Priorité directory > domain dans remember : décision du propriétaire.
detect_gaps et query_methodology passent encore un domain brut à get_memories_for_domain. Il faut vérifier pour chacun qu'il s'agit d'un scope mémoire et pas d'un domaine de profil.
Documenter les alias et la migration des lignes déjà écrites sous un domaine collisionné.
CI autopilot : tranche 9 dans #930 (Refs #721, ne ferme pas l'issue ; commit 411c855).
Cause racine : query_methodology lisait les mémoires chaudes sous l'id de profil cognitif de detect_domain, alors que remember sans domaine explicite écrit sous resolve_cwd(cwd) (puis le profil résolu comme indice hors dépôt connu). Un id de profil différent de ce scope listait un scope sans écriture.
Correctif : lecture sous le scope que remember écrirait pour le même cwd. 6 tests, dont 5 échouent sans le correctif. tests_py/handlers : 1922 passed, 81 skipped.
detect_gaps vérifié : il ne passe que des domaines relus dans le store, aucun changement nécessaire (tranche restante n°2 close).
Non vérifié : suite PostgreSQL, suite complète, gate de mutation, benchmarks (torch non téléchargeable dans cette session).
Les tranches 1 à 8 ont été fusionnées : le plafond de 3 tentatives sans fusion ne s'applique pas.
Tranches restantes :
Priorité directory > domain dans remember (et le repli par indice resolve_domain, qui garde la collision par sous-chaîne hors dépôt connu) : décision du propriétaire.
Documenter les alias et la migration des lignes déjà écrites sous un domaine collisionné.
CI autopilot: on hold, owner decision needed. Slices 1 to 9 are merged (the last one is #930, 8e47b0b). Both remaining slices depend on a product choice, so I am not opening a PR on a guess.
Question to decide (mcp_server/handlers/remember.py:74, _resolve_domain): today, when a call passes both directory and domain, resolve_cwd(directory) wins and the explicit domain is ignored. That contradicts the acceptance criterion "an explicit domain cannot silently become another domain". There are three options:
(a) explicit domain > directory: the caller's identity always wins, and directory is only a hint;
(b) directory > domain, kept and documented as intentional;
(c) reject the call (explicit error) when both are given and resolve to two different scopes.
The same choice applies to the hint fallback resolve_hint(detected) (when resolve_cwd resolves nothing): it can still remap through a substring match outside a known repository.
What follows from the decision: slice 2 (documenting aliases, and migrating rows already written under a collided domain) depends on it. With (a) or (c), existing rows need either a migration or a documented reassignment. With (b), the documentation alone is enough.
A comment from cdeust on this issue makes it eligible again.
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.
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.
Activity
fix(remember): keep an explicit domain instead of remapping it by sub…
cdeust commentedon Nov 5, 2026
CI autopilot : tranche 1 livrée dans #877 (
Refs #721, ne ferme pas l'issue).resolve_domaintraite le domaine comme un indice et renvoie le canonique du plus long fragment de dépôt contenu dans l'entrée ; avec un dépôtharness-comparison,remember(domain="scifact-comparison")écrivaitharness-comparison(test du handler en échec sans le correctif, vert avec).resolve_explicit_domain— seul un nom de dépôt exact (ou sa famille ADR-0647) est mappé ; tout autre nom est conservé tel quel, en minuscules.Tranches restantes :
directory>domaindansrememberalors que le schéma décritdomaincomme un override — décision du propriétaire.recall/fetchne résolvent pasdomain: écriture et recherche ne s'accordent pas sur le scope canonique (ex.cortex-cowork→cortexà l'écriture seulement).Generated by Claude Code
fix(remember): kill the mutants of the domain resolution functions (#721
fix(remember): keep an explicit domain instead of remapping it by sub…
cdeust commentedon Nov 6, 2026
CI autopilot : tranche 2 livrée dans #901 (
Refs #721, ne ferme pas l'issue).rememberrésout undomainexplicite parresolve_explicit_domain(fix(remember): keep an explicit domain instead of remapping it by substring (#721, slice 1) #877), maisrecallpassait l'argument brut au store.recall(domain="cortex-cowork")cherchait donc dans un scope où aucune écriture n'avait eu lieu (cortex), etrecall(domain="SciFact")ne trouvait passcifact.recallrésout le domaine de la même façon ; un domaine vide reste non scopé. 7 tests sur le handler public (6 échouent sans le correctif).torchnon téléchargeable dans cette session).Tranches restantes :
directory>domaindansremember, alors que le schéma décritdomaincomme un override : décision du propriétaire.recall_hierarchicalet les autres filtres par domaine ne résolvent pas encore l'argument.Generated by Claude Code
fix(bench): give the reranker probe the name recall's handler now reads
fix(recall): resolve the domain in a wrapper so _handler_impl is unch…
fix(recall): scope by the domain identity remember writes (#721, slic…
cdeust commentedon Nov 6, 2026
CI autopilot : tranche 3 livrée dans #914 (
Refs #721, ne ferme pas l'issue ; commit b803e88).rememberetrecallrésolvent undomainexplicite parresolve_explicit_domain, maisrecall_hierarchicalpassait l'argument brut àget_memories_for_domain:recall_hierarchical(domain="cortex-cowork")construisait la hiérarchie sur un scope où aucune écriture n'a lieu._scoped_by_explicit_domainavant_handler_impl; un domaine blanc compte comme absence de domaine (ValidationError ADR-0045 R3). 8 tests, 7 échouent sans le correctif.torchnon téléchargeable dans cette session).Tranches restantes :
directory>domaindansremember, alors que le schéma décritdomaincomme un override : décision du propriétaire.domain(unified_search,drill_down,narrative…) : vérifier pour chacun si c'est un scope mémoire ou un domaine de profil, puis résoudre.C'est la 3e tentative sur cette issue : le prochain passage posera
autopilot:holdsi une tranche restante ne peut pas être fusionnée.Generated by Claude Code
fix(recall): recall_hierarchical reads the domain remember writes (#721…
cdeust commentedon Nov 6, 2026
CI autopilot : tranche 4 dans #915 (
Refs #721, ne ferme pas l'issue ; commit 538082e).narrativepassait ledomainbrut àget_memories_for_domain, alors querememberécrit sousresolve_explicit_domain(domain);narrative(domain="cortex-cowork")lisait un scope sans écriture.resolve_explicit_domaindans le handler ; domaine blanc = pas de domaine. 7 tests, 6 échouent sans le correctif.torchnon téléchargeable dans cette session).Les tranches précédentes ont été fusionnées (#914 entre autres), le plafond de 3 tentatives sans fusion ne s'applique donc pas.
Tranches restantes :
directory>domaindansrememberalors que le schéma décritdomaincomme un override : décision du propriétaire.domainbrut àget_memories_for_domain:get_project_story,drill_down,validate_memory,assess_coverage,detect_gaps,query_methodology(pour chacun, vérifier qu'il s'agit d'un scope mémoire et pas d'un domaine de profil).Generated by Claude Code
fixup! fix(narrative): narrative reads the domain remember writes (#721…
fix(narrative): narrative reads the domain remember writes (#721, sli…
fix(narrative): narrative reads the domain remember writes (#721, sli…
4 remaining items
fix(drill): drill_down rebuilds the hierarchy over the domain remembe…
fix(drill): drill_down rebuilds the hierarchy over the domain remembe…
cdeust commentedon Nov 7, 2026
CI autopilot : tranche 7 dans #928 (
Refs #721, ne ferme pas l'issue ; commit fd16b57).assess_coveragepassait ledomainbrut àget_memories_for_domain, alors querememberécrit sousresolve_explicit_domain(domain);assess_coverage(domain="cortex-cowork")notait un scope sans écriture.resolve_explicit_domaindans le handler ; domaine blanc = lecture globale ; ledomainrenvoyé est le scope lu. 7 tests, 6 échouent sans le correctif ;tests_py/handlers: 1909 passed, 81 skipped.torchnon téléchargeable dans cette session).Les tranches 1 à 6 ont été fusionnées : le plafond de 3 tentatives sans fusion ne s'applique pas.
Tranches restantes :
directory>domaindansremember: décision du propriétaire.validate_memory,detect_gaps,query_methodologypassent encore undomainbrut àget_memories_for_domain(vérifier pour chacun qu'il s'agit d'un scope mémoire et pas d'un domaine de profil).Generated by Claude Code
fixup! fix(coverage): assess_coverage scores the domain remember writ…
fix(coverage): assess_coverage scores the domain remember writes (#721,…
cdeust commentedon Nov 7, 2026
CI autopilot : tranche 8 dans #929 (
Refs #721, ne ferme pas l'issue ; commit eae007a).validate_memorypassait ledomainbrut àget_memories_for_domain, alors querememberécrit sousresolve_explicit_domain(domain).validate_memory(domain="cortex-cowork")validait un scope sans écriture.resolve_explicit_domain, et un domaine blanc compte comme une lecture globale. 7 tests, dont 6 échouent sans le correctif.tests_py/handlers: 1915 passed, 81 skipped, 1 failed. Cet échec (sqlite-vec absent du venv local) se produit aussi surmain.torchn'est pas téléchargeable dans cette session).Les tranches 1 à 7 ont été fusionnées : le plafond de 3 tentatives sans fusion ne s'applique pas.
Tranches restantes :
directory>domaindansremember: décision du propriétaire.detect_gapsetquery_methodologypassent encore undomainbrut àget_memories_for_domain. Il faut vérifier pour chacun qu'il s'agit d'un scope mémoire et pas d'un domaine de profil.Generated by Claude Code
fix(validate): validate_memory reads the domain remember writes (#721,…
cdeust commentedon Nov 7, 2026
CI autopilot : tranche 9 dans #930 (
Refs #721, ne ferme pas l'issue ; commit 411c855).query_methodologylisait les mémoires chaudes sous l'id de profil cognitif dedetect_domain, alors queremembersans domaine explicite écrit sousresolve_cwd(cwd)(puis le profil résolu comme indice hors dépôt connu). Un id de profil différent de ce scope listait un scope sans écriture.rememberécrirait pour le mêmecwd. 6 tests, dont 5 échouent sans le correctif.tests_py/handlers: 1922 passed, 81 skipped.detect_gapsvérifié : il ne passe que des domaines relus dans le store, aucun changement nécessaire (tranche restante n°2 close).torchnon téléchargeable dans cette session).Les tranches 1 à 8 ont été fusionnées : le plafond de 3 tentatives sans fusion ne s'applique pas.
Tranches restantes :
directory>domaindansremember(et le repli par indiceresolve_domain, qui garde la collision par sous-chaîne hors dépôt connu) : décision du propriétaire.Generated by Claude Code
fixup! fix(methodology): query_methodology lists hot memories under t…
fix(methodology): query_methodology lists hot memories under the doma…
cdeust commentedon Nov 7, 2026
CI autopilot: on hold, owner decision needed. Slices 1 to 9 are merged (the last one is #930, 8e47b0b). Both remaining slices depend on a product choice, so I am not opening a PR on a guess.
Question to decide (
mcp_server/handlers/remember.py:74,_resolve_domain): today, when a call passes bothdirectoryanddomain,resolve_cwd(directory)wins and the explicitdomainis ignored. That contradicts the acceptance criterion "an explicit domain cannot silently become another domain". There are three options:domain>directory: the caller's identity always wins, anddirectoryis only a hint;directory>domain, kept and documented as intentional;The same choice applies to the hint fallback
resolve_hint(detected)(whenresolve_cwdresolves nothing): it can still remap through a substring match outside a known repository.What follows from the decision: slice 2 (documenting aliases, and migrating rows already written under a collided domain) depends on it. With (a) or (c), existing rows need either a migration or a documented reassignment. With (b), the documentation alone is enough.
A comment from
cdeuston this issue makes it eligible again.Generated by Claude Code
cdeust commentedon Nov 12, 2026
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
cdeustlève le hold et précise la demande. Il vaut pour toute la suite de cette issue.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.<!-- 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.autopilot:holdpour 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.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
cdeust commentedon Nov 12, 2026
Hold
autopilot:holdlevé : un commentaire decdeust(« 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