fix(tools): stop memory file paths from colliding on one customId - #1566
Open
rajarshidattapy wants to merge 1 commit into
Open
fix(tools): stop memory file paths from colliding on one customId#1566rajarshidattapy wants to merge 1 commit into
rajarshidattapy wants to merge 1 commit into
Conversation
`normalizePathToCustomId` flattened `/`, `.` and `_` all to `_`, so /memories/notes.txt, /memories/notes_txt and /memories/notes/txt shared the customId `memories_notes_txt`. Since customId is the document identity for create/view/str_replace/insert/rename/delete, creating one path silently overwrote another, and deleting one destroyed both. Escape the separators instead (`__` = `_`, `_s` = `/`, `_d` = `.`) so the encoding is reversible and distinct paths always get distinct ids. Reads fall back to the old id when the stored file_path matches exactly, so documents written before this change stay reachable and get promoted on the next write.
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.
Fixes #1547
Problem
normalizePathToCustomIdflattened/,.and_all to_, so the mapping was not injective:/memories/notes.txtmemories_notes_txt/memories/notes_txtmemories_notes_txt/memories/notes/txtmemories_notes_txtcustomIdis the document identity forcreate,view,str_replace,insert,renameanddelete, so two paths sharing one id meantcreatesilently overwrote an unrelated file,viewreturned whichever document won last, anddeletedestroyed both. Nested memory directories (/memories/projects/foo.mdvs/memories/projects_foo.md) are the realistic trigger.Fix
Escape the separators instead of flattening them, making the encoding reversible:
Every
_in the output opens a two-character sequence, so decoding is unambiguous and distinct paths always get distinct ids./memories/notes.txtnow maps tomemories_snotes_dtxt.Hashing was the other option in the issue, but
getFileDocumentpasses the customId as the semantic search query (q) and then exact-matches the result — a hex digest as the query would stop retrieving the document at all.Existing documents
Changing the encoding orphans anything written under the old ids, which would be its own silent data loss. So
getFileDocument— the single lookup every command routes through — falls back to the legacy id, guarded by an exactmetadata.file_pathmatch, since legacy ids are the ambiguous ones and must not be trusted on their own. The next write to that path re-adds it under the new id, so the fallback self-heals rather than lingering. The search query stays the legacy (word-preserving) form, so search relevance is unchanged.Tests
Added to
packages/tools/src/claude-memory.test.ts:file_pathis still readablefile_pathis not served (reports not-found)Existing tests that hardcoded the old ids were updated to the new encoding.
claude-memory.test.tsandtool-operations.test.ts: 27/27 pass. The two failing files elsewhere inpackages/tools(the staletest/directory importing./claude-memory) fail identically onmainand are untouched here.