Skip to content

Fix MCP response format, FTS5 sanitization, and embedding caching - #12

Merged
thrr87 merged 5 commits into
mainfrom
codex/shared-memory-upgrade
Feb 5, 2026
Merged

thrr87 merged 5 commits into
mainfrom
codex/shared-memory-upgrade

Conversation

@thrr87

@thrr87 thrr87 commented Feb 5, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • MCP tools/call response format: Wrap tool payloads in MCP-spec CallToolResult with content blocks ({content: [{type: "text", text: ...}]}), fixing both HTTP server and stdio transport
  • FTS5 query sanitization: Escape metacharacters (", *, AND, OR, etc.) by quoting each token before passing to MATCH, preventing crashes on user input in both entity search and memory query
  • Embedding model caching: Cache EmbeddingModel and SentenceTransformer instances at module level to avoid expensive re-instantiation on every search query

Test plan

  • All 91 existing tests pass after changes
  • Manual test: search with FTS5 metacharacters (hoard search '"test" AND foo')
  • Verify MCP response shape has result.content[0].text via curl

🤖 Generated with Claude Code

piotr-auguscik and others added 5 commits February 5, 2026 21:47
- Wrap tools/call responses in MCP CallToolResult content blocks
  (server.py and stdio.py) so clients receive spec-compliant
  {content: [{type: "text", text: ...}]} payloads
- Sanitize FTS5 queries by quoting tokens to prevent crashes on
  metacharacters like ", *, AND, OR in bm25.py and memory store
- Cache EmbeddingModel and SentenceTransformer instances at module
  level to avoid re-loading on every search query
- Update all test assertions to parse the new content wrapper

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The tools/call content wrapper introduced in the previous commit broke
CLI admin commands (tokens create/list/remove, setup provisioning, and
the openclaw_client helper) which read tool result fields directly.
Unwrap the content block transparently in both _call_mcp helpers so
all downstream callers continue to work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add _process_duplicates: compares memory embeddings via cosine
  similarity within the same scope, with idempotency guards and
  model/dimension compatibility checks
- Add _process_conflicts: detects slot+scope overlaps among active
  memories, appends to existing unresolved conflicts rather than
  creating duplicates, handles NULL scope_id with IS NULL semantics
- Extract SentenceTransformer cache to shared public module
  (hoard.core.memory.model_cache) used by store.py and worker.py
- Raise embed_memory job priority to 10 so embeddings are ready
  before detection jobs run (detection gracefully no-ops if missing)
- Add write.duplicates.similarity_threshold config default (0.85)
- Add 10 new tests covering detection, idempotency, missing
  embeddings, mismatched models, NULL scope_id, and conflict
  append behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ired)

Both _process_duplicates and _process_conflicts now filter the source
memory through active_memory_conditions before proceeding, preventing
creation of duplicate/conflict records for already-inactive memories.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cover all three inactive-memory paths (retracted, superseded, expired)
for both duplicate and conflict detection, confirming each is a no-op.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@thrr87
thrr87 merged commit 26fe2ba into main Feb 5, 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