Skip to content

Memory export/import: bundle roundtrip and foreign paste-import - #340

Merged
farhat-is-coding merged 8 commits into
farhat/feat/memory-overhaulfrom
farhat/feat/memory-portability
Aug 15, 2026
Merged

Memory export/import: bundle roundtrip and foreign paste-import#340
farhat-is-coding merged 8 commits into
farhat/feat/memory-overhaulfrom
farhat/feat/memory-portability

Conversation

@farhat-is-coding

Copy link
Copy Markdown
Collaborator

Summary

  • GET /api/memory/v2/export/ produces a dare-memory-v2 bundle — 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 honest import ledger 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.
  • Migration renumbered to 0009 behind the base branch's third-party backfill.

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)
  • Live HTTP roundtrip on a 310-row store: export → wipe → import → 310/310 with chains intact and retrieval immediate
  • Red-team round 2 (Codex) ran against this branch tip

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.
- 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.
@farhat-is-coding
farhat-is-coding merged commit 40bfdb1 into farhat/feat/memory-overhaul Aug 15, 2026
1 check passed
@farhat-is-coding
farhat-is-coding deleted the farhat/feat/memory-portability branch August 15, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant