fix(memory): preserve distinct facts during remember and import - #139
Merged
Merged
Conversation
Limit remember and import deduplication to byte-identical active content. Keep fuzzy diff suggestions advisory, preserve distinct subjects and changed values, and resolve import duplicate indexes and edges to existing memories. Update canonical docs and host guides for deliberate forgetting. Validated with go build -o mnemon ., make test, and all 193 CLI E2E checks. Reproduced replacement and near-duplicate skipping on unmodified master, then verified the fixed CLI and SQLite records in isolated synthetic stores without embeddings.
5 tasks
This was referenced Sep 14, 2026
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
rememberandimportretain distinct content even when lexical or embedding similarity suggests an update or duplicate. They skip only byte-identical content, found across all active insights rather than the five heuristic candidates.rememberstill returnsdiff_suggestionfor the supervising agent; retiring an old fact requires an explicitforget <old-id>after the replacement is stored and checked.Import reuses the actual existing ID for an exact duplicate, preserving draft-index edge resolution and repeat-import behavior.
--no-diffstill inserts exact repeats. The fuzzy classifier is unchanged, so the polarity work in #135 remains independent.Why
Fixes #134. Shared vocabulary cannot establish that two facts refer to the same subject, value, or relationship. The same unsafe assumption existed in the import path, which also replaced conflicting content. This change removes that source of soft deletion and silent skipping without adding a subject parser, schema, or replacement flag.
The isolated CLI reproduction on base
6c371ec7dce7af05aa55f31fb1b7c1aea81205dbstores Alpha, then Beta:Before: the second write returns
updated/UPDATEwith Alpha'sreplaced_id; only Beta remains active. Longer facts sharing more than 90% of tokens can instead returnskipped/DUPLICATE, losing Beta. Reversing the roles in a relationship can produce the same false duplicate.After: both distinct facts are added and remain retrievable, with no similarity-driven soft deletion. An exact repeat still skips and reports the correct existing ID, including content without searchable tokens and exact matches outside the fuzzy candidate limit.
All comparisons use fresh synthetic stores and an unavailable loopback embedding endpoint. Raw command output and reusable comparison scripts are retained locally; the table summarizes those operations. Existing lifecycle pruning remains a separate policy.
Validation
go build -o mnemon .andmake testpass, includinggo vet ./....bash scripts/e2e_test.sh: 193/193 checks pass with embeddings unavailable.--no-diff.make test, and all 258 combined CLI E2E checks. Both PRs are independently based onmaster.Checklist
make test)bash scripts/e2e_test.sh); full Agency/process/Docker integration is outside this Memory-only change--no-diff