Skip to content

fix(memory): make recall useful across agents — scopes, crawler noise, watcher storm, access bump - #9

Merged
qdequele merged 2 commits into
mainfrom
qdequele/memory-quality
Oct 9, 2026
Merged

qdequele merged 2 commits into
mainfrom
qdequele/memory-quality

Conversation

@qdequele

@qdequele qdequele commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Why

A review of the installed daemon (2026-10-08) found the memory store was 99.8% crawler noise: 22,385 docs, 21,708 of them copies under .claude/worktrees/ misfiled as fact. Only 15 agent-written memories existed and they were unreachable by scoped recall. Four code-level causes:

  • classify_path treated any Markdown under a /.claude/ path as a memory.
  • Scope was root + first component, so every project under ~/Projects/Meilisearch shared one scope and exact-match filters returned nothing.
  • The watcher called forget() for every file deleted under ~/Projects (181k deletion tasks in one day, 86k 404 log lines).
  • The last_accessed_at bump used POST (replace); it only failed to wipe memories because the embedder template rejected the partial doc.

What changed

Crawler — agent-agnostic classification (Claude Code, Codex, Gemini CLI, Cursor, Windsurf, Cline, Zed, Copilot instruction files; Claude/Codex/Windsurf/Cline memory files), linked git worktrees skipped, scope = nearest git repo, each agent's knowledge roots indexed, bulk state load, watcher pre-filter, memd crawl run --reset.

Memory service — hierarchical scopes (self + ancestors + global + sub-paths), scope normalisation, PUT-based access bump.

Agents — hooks for Claude Code, Codex and Gemini CLI; directives for Windsurf and Cline; memd context injects only memories (never crawled project files) and reads the hook payload's cwd; memd capture handles all three payload shapes and rejects injected context; memd setup --agents a,b; memd doctor --fix prunes task history.

Verification

  • cargo fmt --check, cargo clippy --all-targets -D warnings, cargo test (86 tests) green.
  • Release binary run against the live engine: scoped context for three projects, JSON hook output, capture gate with Claude and Gemini payloads, search.

After upgrading, run memd crawl run --reset once so existing crawled docs pick up the new scopes.

🤖 Generated with Claude Code

…, watcher storm, access bump

The store was 99.8% crawler noise (22k docs, 21.7k of them worktree copies
misfiled as `fact`), every project shared one scope so scoped recall returned
nothing, the watcher issued a delete task for every file removed under
~/Projects (181k/day), and the access bump replaced documents via POST.

Crawler
- Classify by agent-agnostic rules: instruction files for Claude Code, Codex,
  Gemini CLI, Cursor, Windsurf, Cline, Zed, Copilot; memory files for Claude
  Code (~/.claude/projects/*/memory), Codex, Windsurf, Cline. Drop the
  `/.claude/` catch-all that indexed every doc inside a worktree.
- Skip linked git worktrees (`.git` is a file) and `.claude/worktrees`.
- Scope = nearest git repository; Claude memory dirs resolve their slug back
  to the project path.
- Index each agent's knowledge roots (memories, global rules) so one agent's
  memory is visible to all the others.
- Load crawler state in a few paged requests instead of one GET per file.
- Watcher ignores paths the classifier doesn't recognise; deletions no longer
  hit the engine.
- `memd crawl run --reset` rebuilds from scratch.

Memory service
- Hierarchical scopes: a query scoped to /a/b/c matches /a/b/c, its ancestors,
  `global`, and sub-paths (STARTS WITH, with a fallback for older engines).
  Scopes are normalised (~ expanded, worktree segment stripped).
- `last_accessed_at` bumps use PUT (merge); POST would have replaced the
  memory with `{id, last_accessed_at}`.

Agents
- Session-start and end-of-turn hooks for Claude Code, Codex (hooks.json) and
  Gemini CLI (JSON hook output); directives for Windsurf and Cline.
- `memd context` reads the hook payload's cwd, injects only agent/user
  memories plus other agents' memory files, never crawled project files.
- `memd capture` handles Claude, Codex and Gemini payloads and rejects
  injected context (skill loads, subagent hand-backs, system reminders).
- `memd setup --agents a,b` for scripted, explicit selection.
- `memd doctor --fix` prunes finished engine tasks older than a week.
- Claude Code memory slugs never resolve to `global`: worktree and
  sub-directory sessions map to their repository, unknown slugs to a
  reconstructed path. A `global` fallback injected one project's notes into
  every other session.
- `MEMORY.md` index files are classified `reference`, so they are searchable
  but not injected.
- Crawled memory files take their title from front matter (`description`,
  then `name`), not the file name.
- `memd context` lists real memories first, then other agents' memory files
  about the project, and never shows an agent its own memory directory.
@qdequele
qdequele force-pushed the qdequele/memory-quality branch from 8cd3712 to 93cd75b Compare October 9, 2026 07:15
@qdequele
qdequele added this pull request to stack #11 October 9, 2026 08:08
@qdequele
qdequele merged commit de7beb1 into main Oct 9, 2026
1 check 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.

1 participant