Skip to content

Scope stores to the project, and measure the semantic backend - #3

Merged
Ninadnj merged 2 commits into
mainfrom
feat/project-stores-and-real-embeddings
Aug 12, 2026
Merged

Scope stores to the project, and measure the semantic backend#3
Ninadnj merged 2 commits into
mainfrom
feat/project-stores-and-real-embeddings

Conversation

@Ninadnj

@Ninadnj Ninadnj commented Aug 11, 2026

Copy link
Copy Markdown
Owner

The two changes from the "what would make this actually work day to day" list. (#3, session hooks, deliberately left for later.)

1. Memories were shared across every project

The default store was a single global ~/.agent_memory/store.json, and all three MCP configs in the README pointed at it. Since recall matches on similarity alone, your booking app's answer to "how do we deploy?" could surface while you're working on your portfolio site. Invisible on day one, confusing by month three.

Resolution order is now:

  1. AGENT_MEMORY_PATH if set
  2. .agent_memory/store.json in the enclosing git repo — the normal case
  3. ~/.agent_memory/store.json outside a repo

.git is tested for existence, not directory-ness, so worktrees and submodules work. --global opts back in, agent-memory stats prints the active store, and a one-time notice points at existing global memories so upgrading doesn't look like data loss — on stderr, because stdout carries the MCP protocol.

2. The semantic backend shipped unmeasured

SentenceTransformerEmbedder existed but had never been scored, and its relevance floor was a guess. Now measured on the same benchmark:

Hashing MiniLM
Developer phrasing (40% word overlap) 0.93 0.86
Outsider paraphrase (3% word overlap) 0.43 0.79
Average 0.68 0.82
Off-topic queries rejected 6/12 12/12

It isn't a clean sweep, and that's the useful finding. Exact word matching genuinely wins when the words match — hashing is better and needs no model download. But real use is the second row: you write a memory in March and ask in July, in different words. The README now recommends the real extra for daily use and keeps hashing as the offline/CI default.

The floor was recalibrated against evidence, not just the sweep. Off-topic queries are fully rejected from 0.15 and labelled recall is flat to 0.35, so the sweep alone can't pick a value. Probing real paraphrases found "which AI model answers customer questions" scoring 0.22 against the memory that answers it — which the previous 0.25 guess would have thrown away. Floor set to 0.20.

Also fixed a latent break: sentence-transformers 5.x renamed get_sentence_embedding_dimension. Both names now work — the same failure mode as the mcp 1.x/2.x rename that broke the server before.

eval/run_eval.py takes --embedder and writes the two runs to separate files, so a machine with the model installed can't overwrite the results CI regenerates and diffs.

Verification

  • 74 tests (was 65), plus 9 sentence-transformers tests that skip without the extra
  • Hashing eval still byte-stable; CI's staleness check unaffected
  • Full JSON-RPC session over real stdio with MiniLM loaded: 8 tools listed, memory_boot resolved a paraphrased query correctly, off-topic returned nothing, clean exit, zero protocol corruption
  • Two projects verified isolated: B's recall cannot see A's memories

Known limits, now stated in the README

Nothing writes memories for you yet — the agent must choose to call memory_write/memory_handoff. That's the next piece, and it's what session hooks would fix.

🤖 Generated with Claude Code

Two changes aimed at making this usable day to day rather than just
correct on a benchmark.

Per-project stores
- The default was a single global ~/.agent_memory/store.json shared by
  every project, and all three README configs pointed at it. Recall
  matches on similarity alone, so one project's "how do we deploy"
  answer could surface while working on another.
- The store now resolves as: AGENT_MEMORY_PATH, then .agent_memory/
  store.json in the enclosing git repository, then the global file when
  outside a repo. `.git` is tested for existence, so worktrees and
  submodules (where it is a file) work too.
- `--global` opts back into the shared store, `agent-memory stats` prints
  which store is in use, and a one-time stderr notice points at existing
  global memories so upgrading does not look like data loss. It goes to
  stderr because on the MCP server stdout carries the protocol.

Measured the sentence-transformers backend
- It shipped unmeasured with a guessed relevance floor. Now scored on the
  same benchmark and published in results_sentence_transformers.md:

                        hashing   MiniLM
    developer phrasing     0.93     0.86
    paraphrase             0.43     0.79
    off-topic rejected     6/12    12/12

  Not a clean sweep, which is the interesting part: exact word matching
  genuinely wins when the words match. MiniLM wins where real use lives.
  The README now recommends the `real` extra for daily use and keeps
  hashing as the offline/CI default.
- Calibrated its floor from the sweep plus observed behaviour: off-topic
  queries are fully rejected by 0.15 and recall is flat to 0.35, so the
  sweep alone cannot choose. Set to 0.20, just under the 0.22 scored by a
  real paraphrase against the memory that answers it. The previous 0.25
  guess would have rejected it.
- Fixed a latent break: sentence-transformers 5.x renamed
  get_sentence_embedding_dimension. Both names are now supported — the
  same failure mode as the mcp 1.x/2.x rename.
- eval/run_eval.py takes --embedder and writes the two runs to separate
  files, so a machine with the model installed cannot overwrite the
  results CI regenerates and diffs.

Tests 65 -> 74, plus 9 sentence-transformers tests that skip without the
extra. Verified over a real JSON-RPC stdio session: 8 tools, paraphrased
query resolved, off-topic rejected, no protocol corruption.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 918992997d

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread README.md Outdated
| Developer phrasing — 40% word overlap | **0.93** | 0.86 |
| Outsider paraphrase — 3% word overlap | 0.43 | **0.79** |
| Average of the two | 0.68 | **0.82** |
| Off-topic queries correctly rejected | 6/12 | **12/12** |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Correct the off-topic query rejection denominator

The evaluation runs only four off-topic queries, while min_score_sweep counts returned memories and uses k * len(off_topic) (12 candidate slots) as the denominator. Consequently, 6/12 and 12/12 cannot represent “queries correctly rejected”; this incorrectly suggests that twelve off-topic questions were tested and does not reveal how many queries returned no memories. Report a query-level count or relabel the row as rejected candidate-memory slots.

Useful? React with 👍 / 👎.

The page had grown by accretion — heavy evaluation analysis before the
reader knew what the thing was, quickstart buried two thirds down, and
install instructions in three different places.

Reordered to try it -> understand it -> evidence -> reference:

- Quick start first, with a real terminal session whose output is copied
  from an actual run: a paraphrased query that shares no words with the
  memory it finds, and an off-topic query that returns nothing.
- One install table replacing three scattered pip lines.
- "How it works" as a three-row tool table before the sequence diagram.
- Evaluation consolidated under "Does it actually work?", keeping the
  random control, the embedder comparison and the caveats.
- New Reference section: CLI commands, memory types, environment
  variables, Python API, migration — previously scattered or unwritten.
- Added CI/Python/licence badges.

Every number in the page is checked against eval/results*.json, the
shipped floors, the test count and the tool count.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Ninadnj
Ninadnj merged commit 5633eac into main Aug 12, 2026
4 checks passed
@Ninadnj
Ninadnj deleted the feat/project-stores-and-real-embeddings branch August 12, 2026 20:54
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