Repository navigation
fix: migrate-root merges memory files by record id instead of skipping them (GIT-100) - #43
Merged
1 commit merged intoSep 22, 2026
Merged
1 commit merged into
1 commit merged into
Conversation
…g them (GIT-100) learnings.json, threads.json, decisions.json and sessions.json were skipped as "already exists", so a destination holding any local memory received none of the project store's, and the report listed the user's scars under "skipped". - Those four are merged by record id: new ids are added; where both sides hold a record the newer wins (updated_at, else resolved_at, last_touched_at, created_at), the destination on a tie or when neither is dated. - Every loser is written to <dest>/migrate-root-conflicts.json with which side was kept, deduplicated so a re-run logs nothing new. - The destination's memory files are backed up to <dest>/backups/ before the first write; nothing is backed up when nothing changes. - Idempotent: a re-run changes nothing. - A memory file that is not a readable list of records is reported as NOT merged (exit 1) and left untouched; never listed as skipped. - Other files keep copy-if-absent; backups/ and the conflicts log are never migrated out of a source. migrate-root.test.ts: "never overwrites a file that already exists" and "reports why each file was skipped" used learnings.json and asserted it was skipped, i.e. the old behaviour. They now use config.json to keep testing the non-memory rule. +11 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
neoneye
pushed a commit
to agent-memory-atlas-archive/gitmem-dev--gitmem
that referenced
this pull request
Sep 22, 2026
Conflicts (blank-supabase.mjs): all result fields and all checks kept. migrate-root.ts auto-merged (gitmem-dev#43's merge + gitmem-dev#45's sameDirectory). tsc clean.
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
migrate-rootmerges the memory files instead of skipping them (GIT-100).learnings.json,threads.json,decisions.json,sessions.jsonare merged by record id:updated_at, thenresolved_at,last_touched_at,created_at. On a tie, or when neither side is dated, the destination wins, since it's the live store.<dest>/migrate-root-conflicts.json, with the id, which side was kept, both timestamps and the full losing record. Entries are deduplicated, so a re-run adds nothing.<dest>/backups/migrate-root-<timestamp>/, before the first write. Nothing is backed up when nothing changes.NOT merged: …, left untouched, and the command exits 1.backups/and the conflicts log are never migrated out of a source.Why
The four memory files were skipped as "already exists", so a destination with any local memory received none of the project store's. The report then listed the user's scars under "skipped":
How to test
CLI end to end (
bin/gitmem.js migrate-root --from …,GITMEM_HOMEpointing at a temp home, run twice). Project hasa(project-only) andb(newer); home hasb(older) andc:Venue: not applicable.
migrate-rootreads and writes only local.gitmemstores, never Supabase.Unit tests: 1285/1285 pass (+11). They cover: no memory file under skipped; add, keep, newer-wins in both directions; key-order-independent equality; a source-only memory file is copied; undated conflict keeps the destination; every loser logged with the kept side; backup taken before write; idempotent re-run (byte-identical files, no backup, 0 new conflicts); source intact; dry-run writes nothing and reports the same merge; unreadable file →
NOT merged, untouched, not skipped; backups and the conflicts log aren't migrated.Existing tests that encoded the old behaviour (changed, not deleted)
tests/unit/commands/migrate-root.test.ts:learnings.jsonand asserted the destination was unchanged and the file listed underskipped. That's exactly the GIT-100 bug: the project store's memory was dropped. The test now usesconfig.json, keeping the copy-if-absent rule for non-memory files. The memory case is covered by the new merge tests.learnings.jsonas its example of a skip. It now usesconfig.json, since a memory file is never skipped.Checklist
npm run test:unitpasses (1285)migrate-root --helpoutput is unchanged; the README doesn't describe the mergeBreaking changes
migrate-rootnow writes into existing destination memory files (after backing them up), where it used to leave them alone. That's the fix.🤖 Generated with Claude Code