fix(search): return round-trippable drawer IDs - #2090
Merged
igorls merged 1 commit intoAug 2, 2026
Conversation
gnusam
pushed a commit
to gnusam/mempalace-pgsql
that referenced
this pull request
Jul 29, 2026
Adapts upstream PR MemPalace#2090. search_memories hits carried no ID at all in this fork, so a search result could not feed mempalace_delete_drawer or any dedup flow without a separate lookup. Each hit now includes the stored drawer ID alongside text/wing/room/similarity. Co-authored-by: fatkobra <fatkobra@users.noreply.github.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
drawer_idto everysearch_memories()result pathparent_drawer_idfor chunked MCP drawersProblem
A single ID choice does not work for every stored drawer.
A raw physical chunk ID is insufficient for a chunked MCP drawer because
mempalace_get_drawerresolves that physical row directly and returns onlythat chunk. Conversely, mined and ordinary single-row drawers generally do
not have a
parent_drawer_id.The public result contract therefore needs to be conditional per hit:
This makes the returned ID directly usable with
mempalace_get_drawerforboth chunked and non-chunked drawers.
Implementation
Vector and hybrid results
The IDs returned by the backend query are aligned with the document column.
Each result exposes its logical parent when one exists and otherwise exposes
its own stored ID.
The ID list is defensively padded for compatibility with legacy test mocks
that return documents but omit query IDs.
Filtered-query recovery
The unfiltered retry plus Python-side metadata filtering now preserves IDs
alongside documents, metadata, and distances.
Without this, a filtered search that entered the recovery path would still
lose the drawer identity.
SQLite BM25-only fallback
The metadata query now joins
embedding_metadatatoembeddingsandretrieves
embeddings.embedding_id.This is the stored public Chroma ID. The internal numeric SQLite row ID is
not exposed to callers.
Backend lexical union
_merge_bm25_union_candidates()usesLexicalHit.idas the stored-IDfallback and uses
parent_drawer_idwhen the lexical hit represents achunked logical drawer.
MCP retrieval
This PR does not change the MCP drawer retrieval implementation. It fixes
the ID produced by search so the existing
mempalace_get_drawerlogicalchunk-group reconstruction is reached for chunked drawers.
Tests
Regression coverage verifies:
parent_drawer_id;mempalace_get_drawerand reconstructs the complete content;non-matching results;
LexicalHit.idsemantics;_parent_drawer_idremains absent from the public response.Relationship to #1219
#1219 exposes the raw ID returned by the normal vector query.
This PR implements the broader contract reported in #2080:
backend lexical-union result builders;
This is not intended to disregard #1219. Maintainers can decide whether this
PR should replace that implementation or whether the existing PR should be
adapted.
Fixes #2080
Related to #1026
Related to #1219
How to test
Checklist
python -m pytest tests/ -v)ruff check .)