fix(mirror): upsert by stable slug + bump 0.6.0rc16 (P0)#122
Merged
Conversation
…bump rc16 P0: the mnemon-mirror save path wrote a brand-new document on every local-file edit, so one intentional memory edited several times in a session became N near-identical docs (the at-save vector dedup can't catch it — divergent edits clear the overlap threshold while being the same memory by identity). - store.save() gains optional source_key (caller-owned stable identity). At most one live doc per (collection, source_client, source_key): unchanged re-save idempotent; changed re-save invalidates prior + inserts with an auditable invalidated_by supersession chain. - Generic content-hash dedup scoped to invalidated_at IS NULL so an A->B->A revert surfaces a fresh memory, not a resurrected dead row. - memory_save tool threads source_key; mirror.py keys it to the file's frontmatter name (slug). - Additive documents.source_key column + index migrate in place; pre-existing rows stay NULL = old insert-only behaviour. - path uuid-salted to hold UNIQUE(collection, path) under same-ms re-insert. - +5 store regression tests + mirror payload assertion; suite 750 green. Version bumped 0.6.0rc15 -> 0.6.0rc16 for soak. Co-Authored-By: Claude Opus 4.7 (1M context) <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.
P0 — auto-mirror re-inserts on every edit (surfaced 2026-05-15)
A Claude Code auto-memory file's normal lifecycle is draft → refine → finalize-on-merge — often several edits within one session. The
mnemon-mirrorsave path wrote a brand-new mnemon document on each edit instead of upserting by the file's slug, so a single intentional memory edited 3× became 3 near-identical docs (concrete:reference-morning-signal-iam-decoupledmirrored 3× on 2026-05-15 — ids 2253/2256/2259). The at-save vector-overlap dedup can't catch it: successive edits diverge enough to clear the threshold while still being the same memory by identity.Fix —
source_key(stable caller-owned identity)store.save()upsert-by-key — optionalsource_key. At most one live (non-invalidated) doc per(collection, source_client, source_key): unchanged re-save is idempotent; changed re-save invalidates the prior live row(s) and inserts a fresh one with an auditableinvalidated_bysupersession chain. Generic content-hash dedup now scoped toinvalidated_at IS NULLso an A→B→A revert surfaces a fresh visible memory rather than resurrecting a dead row'saccess_count.documents.source_keycolumn + lookup index, applied in place on existing vaults. Pre-existing rows stayNULL= old insert-only behaviour (no-op for everything predating this).memory_savetool (shared byserver_remote) threadssource_key.mirror.pykeyssource_keyto the file's frontmattername(slug).pathuuid salt — the upsert path can re-insert identical content within the same millisecond (in-session A→B→A revert), which collided withUNIQUE(collection, path)under the oldtime-ms + hash-prefixscheme.Tests
+5
storeregression tests (changed-reedit supersession, idempotent unchanged re-save, distinct-slug isolation, A→B→A revert, no-source_key insert-only preservation) + mirror payload assertion. Full suite 750 passed.Release
Version bumped
0.6.0rc15→0.6.0rc16for soak. CHANGELOG updated.Operator follow-up (not in this PR)
One-shot
memory_forgetsweep of pre-fix same-slug pile-ups in the live default vault (source_client='mnemon-mirror'grouped by title, keepmax(created_at)).🤖 Generated with Claude Code