Memory export/import: bundle roundtrip and foreign paste-import - #340
Merged
farhat-is-coding merged 8 commits intoAug 15, 2026
Merged
Conversation
Successor to the MemU-era export PRs, rebuilt against the layered store. Their flat item list could show a store but never reinstate one — supersession chains, held rows, pinned facts and the hand-authored document had nowhere to live in it. The dare-memory-v2 bundle carries the contract itself, so export → forget everything → import puts the store back exactly: retired history intact, profile intact, chains remapped onto fresh ids. Deliberately absent from the bundle: embeddings (recomputed on import, so the bundle never pins an embedding model), the ledger (an audit trail of what THIS account did — replaying it elsewhere would fabricate history; the import writes one honest row saying what arrived), and conversations (the transcript belongs to its own feature and its own explicit export scope). Import demands an empty store — the flows it exists for start empty, and refusing loudly beats inventing merge semantics. Bundles are user input: every field coerced, enums checked against the real vocabularies, links to unknown ids dropped, damaged rows skipped instead of failing the whole bundle.
A paste from ChatGPT or Claude is not a restore — it is unstructured text of unknown quality making claims about the person. So it goes through the same machinery a conversation goes through: chunked into turns in a real 'Imported memories' conversation (honest provenance a person can open and read), each turn queued as the ordinary writer job on the FIFO memory queue. The gate meets an existing store the way it always does — collisions supersede, safety pins, health is held — so unlike the bundle restore, this path needs no empty store. Two faults the live run flushed out, both fixed here: - The writer had been dying silently for hours. gpt-5.6-luna is a reasoning model, and with the prompt grown to ~7k tokens it spent the entire 900-token completion budget on reasoning, emitted nothing, and every job landed in the failed registry. The max_completion_tokens dialects (the reasoning families) now get 4000. - The snap only inspected add_fact decisions, but a patch_user decision is a fact wearing a heading — the gate reroutes it onto topic_key. The imported allergy line, proposed as patch_user with topic diet_avoid:peanutS, minted a plural slot beside diet_avoid:peanut. The snap now reads the slot a decision will actually land on.
The base branch grew 0008 (holding pre-rule third-party facts), so the ledger-action migration moves to 0009 to keep the graph linear.
3 tasks
- Simplified the handling of user document keys and improved the normalization process. - Updated the logic for merging pinned facts into the user document to prevent duplicates. - Changed references from `user_doc_changed` to `profile_changed` for clarity and consistency. - Removed unused code and comments to enhance readability. - Adjusted tests to reflect changes in the user document structure and logic. - Ensured that the user document maintains its integrity while allowing for updates and merges.
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.
Summary
GET /api/memory/v2/export/produces adare-memory-v2bundle — records with supersession chains, held states, pins, the authored document; no embeddings, no ledger, no conversations.POST /api/memory/v2/import/reinstates it into an empty store: ids remapped, chains relinked, texts re-embedded, one honestimportledger row (never a replayed history). Damaged rows are skipped with readable reasons; a non-empty store refuses.POST /api/memory/v2/import/foreign/takes a free-form paste (from ChatGPT/Claude/etc., prompted by the copyable export prompt in the FE) and runs it through the REAL pipeline: chunked into turns in an "Imported memories" conversation and queued on the same single-worker memory queue live turns use — so every import faces the same writer, gate, guards and ledger as a spoken sentence.Supersedes the June export/import pair (#267) — this version roundtrips the layered store exactly rather than exporting a report.
Stacked on #338 (
farhat/feat/memory-overhaul).Test plan
python manage.py test memory— full suite green (roundtrip, refusals, damaged rows, foreign chunking/caps, scope isolation)