Skip to content

fix(methodology): query_methodology lists hot memories under the domain remember writes (#721, slice 9) - #930

Merged
github-actions[bot] merged 2 commits into
mainfrom
fix/721-domain-scope-gaps-methodology
Nov 7, 2026
Merged

github-actions[bot] merged 2 commits into
mainfrom
fix/721-domain-scope-gaps-methodology

Conversation

@cdeust

@cdeust cdeust commented Nov 7, 2026

Copy link
Copy Markdown
Owner

Summary

Tranche 9 de #721 (Refs #721, ne ferme pas l'issue).

query_methodology passait à get_memories_for_domain l'id de profil cognitif renvoyé par detect_domain. Or remember sans domaine explicite écrit sous resolve_cwd(cwd) et, hors d'un dépôt connu, sous le profil détecté résolu comme indice (remember._resolve_domain). Dès que l'id de profil diffère de ce scope (id de profil hérité dans un dépôt connu, ou cortex-cowork hors de son checkout), le démarrage de session listait les mémoires chaudes d'un scope qu'aucune écriture n'utilise. Cause racine : un id de profil était utilisé comme scope mémoire. Correctif : _memory_scope(cwd, profile_domain) lit le scope que remember écrirait pour le même cwd.

detect_gaps a été vérifié et ne change pas : _temporal_gaps ne passe que des domaines relus dans le store (get_domain_entity_counts), et le domain de l'appelant ne va qu'au détecteur d'angles morts du profil.

Refs #721

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Test plan

  • tests_py/handlers/test_query_methodology_domain_scope.py (nouveau, 6 tests, registre de dépôts reconstruit depuis de vrais répertoires sous tmp_path, handler public) : 6 passed avec le correctif ; 5 failed sans le correctif (le seul qui passe est le cas où l'id de profil est déjà le canonique).
  • pytest tests_py/handlers : 1922 passed, 81 skipped (PostgreSQL absent de la session).
  • ruff check / ruff format --check (ruff 0.17.3, version de uv.lock) sur les fichiers modifiés : OK.
  • python scripts/check_craftsmanship.py : OK.
  • Non vérifié : suite PostgreSQL, suite complète, gate de mutation, benchmarks (torch n'est pas téléchargeable dans cette session).

Audit notes

Breaking changes

Aucun.

Reviewer checklist

  • CHANGELOG.md updated under the appropriate section.
  • No secrets / credentials / PII in the diff.

Generated by Claude Code

…in remember writes (#721, slice 9)

query_methodology handed the cognitive-profile id returned by detect_domain
to get_memories_for_domain. remember without an explicit domain writes under
resolve_cwd(cwd) and, outside a known repository, under the detected profile
resolved as a hint (remember._resolve_domain). Whenever the profile id
differs from that scope (a legacy profile id inside a known repository, or
`cortex-cowork` outside its checkout), session start listed the hot
memories of a scope no write used. Read the scope remember would write for
the same cwd.

detect_gaps was checked and needs no change: _temporal_gaps passes only
domains read back from the store (get_domain_entity_counts), and the caller's
`domain` reaches only the profile blind-spot detector.

Refs #721

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYqpLwKt5qrkU1aMWnb
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-07T06:56:29.543956Z fbba011 New commits
🔒 Security Review ✅ Completed 2026-11-07T06:59:31.327403Z fbba011 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 1m 55s —— View job


Review 1/3 of PR #930: no Blockers

The review found no Blockers and approves the PR. It lists three notes with no action needed before merge:

  • Outside a known repository, reads and writes can still pick different domains: the handler detects the domain from cwd, project and first_message, but remember uses cwd only.
  • With an empty cwd, the read and write scopes still differ.
  • The CHANGELOG claim about detect_gaps is worded too broadly.

I did not run the tests, ruff or the craftsmanship gate here because they needed approval. The CI Pipeline run was still going when I posted.

Verdict: approve

@claude

claude Bot commented Nov 7, 2026

Copy link
Copy Markdown

Review 1/3 — PR #930 (slice 9 of #721)

I ran five reviews (code quality, security, performance, tests, docs). None found a Blocker. In a known repository, _memory_scope now reads the same canonical scope that remember._resolve_domain writes. The layers are respected (handler → shared) and the new function carries its source:. On the security side there's no injection (the domain is a bound parameter) and no new cross-project read. The registry is already cached (lru_cache), so the cost on the session-start path is negligible.

Notes, no action before merge

  • Outside a known repository, read and write can still disagree: handler calls detect_domain with cwd+project+first_message (query_methodology.py:320-323), while remember calls it with cwd only (remember.py:87). The tests stub detect_domain with a constant, so they can't see this. A refinement PR could feed _memory_scope from detect_domain({"cwd": cwd}).
  • With an empty cwd, _memory_scope returns resolve_hint(profile) but remember writes "". The docstring and CHANGELOG ("for the same cwd") claim more than the code does in that case. The domain_id is None case is also untested (store.domains[-1] would raise IndexError).
  • The CHANGELOG says detect_gaps "reads only domains taken from the store". That holds for its store reads; _cognitive_style_gaps does use the caller's domain, but only for the profile detector.

Not verified by me: local tests, ruff and the craftsmanship gate (no permission to run them here). The CI Pipeline was still running when I posted this.

Verdict: approve

…he domain remember writes (#721, slice 9)

Check `unit`, run 42347464717 (job 128328248724): the mutation gate kept two
surviving mutants of _memory_scope, `if (cwd) or True` and
`if (profile_domain) or True`. Both are equivalent because the guards were
redundant: resolve_cwd("") and resolve_domain("") already return "". Drop
the guards (`resolve_cwd(cwd) or resolve_hint(profile_domain)`), document the
no-cwd case, and cover an empty cwd and an absent profile.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYqpLwKt5qrkU1aMWnb
@claude

claude Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 1m 39s —— View job


Review 2/3 of PR #930: no Blockers

The fixup shortens _memory_scope to resolve_cwd(cwd) or resolve_hint(profile_domain). It behaves exactly like the old version: both functions already return "" on empty input, so the two mutants that survived were equivalent.

The review lists three notes, with no action needed before merge:

  • A test can't tell "no domain read" from "read with """, so the directory fallback isn't checked.
  • With an empty cwd, the docstring headline and the CHANGELOG still claim reads match remember's writes. Review 1 already raised this.
  • The case with neither a cwd nor a profile is still untested.

I did not run the tests, ruff or the craftsmanship gate here.

Verdict: approve

cdeust commented Nov 7, 2026

Copy link
Copy Markdown
Owner Author

CI autopilot : unit (et merge, qui en dépend) en échec sur 411c855, run 42347464717.

  • Diagnostic : le gate de mutation a gardé deux mutants survivants de _memory_scope, if (cwd) or True et if (profile_domain) or True. Ils sont équivalents parce que les gardes étaient redondantes : resolve_cwd("") et resolve_domain("") renvoient déjà "". La cause est dans le code, pas dans les tests.
  • Correctif fbba011 (fixup! de 411c855) : return resolve_cwd(cwd) or resolve_hint(profile_domain), la docstring décrit le cas sans cwd, et deux tests couvrent un cwd vide et un profil absent. Reproduit en local avec scripts/mutation_check.sh sur la même sélection de tests : 2 survivants avant, 0 après (rc=0). Les 7 fichiers de tests de la sélection : 64 passed ; ruff et le gate craftsmanship : OK.
  • Non vérifié : le reste de la CI (regression, e2e, environment, install ont été sautés après l'échec de unit), la suite PostgreSQL en local.

Generated by Claude Code

@claude

claude Bot commented Nov 7, 2026

Copy link
Copy Markdown

Review 2/3 — PR #930 (slice 9 of #721)

Review 1 found no Blockers. This review covers only fbba011 (fixup), the one commit pushed after 411c855. I ran five reviews (code quality, security, performance, tests, docs) and none found a Blocker.

_memory_scope is now resolve_cwd(cwd) or resolve_hint(profile_domain), and it behaves exactly like the old guarded version for every input. Both functions already return "" on empty input before they call git or build the registry (domain_mapping.py:503-504, :407-408). That makes the two surviving mutants equivalent, so dropping the guards is the right fix. The fixup does not widen what gets read and adds no cost. The new IndexError guard in _read_scope closes the review-1 note about domain_id is None.

Notes, no action before merge

  • tests_py/handlers/test_query_methodology_domain_scope.py:77: _read_scope returns "" both when get_memories_for_domain was never called and when it was called with "". So test_no_profile_…[outside] can't confirm that _get_hot_memories actually falls back to the directory (query_methodology.py:137). Recording which store method was called would fix that.
  • query_methodology.py:160: the docstring headline still says "the domain remember writes". With an empty cwd, remember._resolve_domain writes "" (remember.py:90), while _memory_scope reads resolve_hint(profile). The new sentence describes the read correctly, but the headline and the CHANGELOG ("for the same cwd") should name this exception. Review 1 already raised this; it isn't new.
  • No cwd plus no profile (the global get_hot_memories branch) is still untested.

Not verified by me: local tests, ruff and the craftsmanship gate.

Verdict: approve

@github-actions
github-actions Bot merged commit 8e47b0b into main Nov 7, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants