feat: MEMORY.md / BOOTSTRAP.md cross-session long-term memory (closes #160)#172
Open
luceinaltis wants to merge 2 commits into
Open
feat: MEMORY.md / BOOTSTRAP.md cross-session long-term memory (closes #160)#172luceinaltis wants to merge 2 commits into
luceinaltis wants to merge 2 commits into
Conversation
Closes #160. Introduces a durable layer above the auto-generated Tier 2 summaries: - MEMORY.md at ~/.qracer/MEMORY.md with a machine-managed auto region (delimited by <!-- BEGIN:auto --> / <!-- END:auto -->) that is regenerated from FactStore after every thesis save; everything outside the auto region is user-curated and preserved verbatim. - BOOTSTRAP.md at ~/.qracer/BOOTSTRAP.md — optional raw text loaded once at ConversationEngine init and injected as a system turn so preferences reach the synthesizer without code changes. New module qracer/memory/memory_file.py exposes load/save/parse/render, refresh_memory(doc, fact_store), refresh_memory_file(path, fact_store), and load_bootstrap(path). ConversationEngine gains memory_path and bootstrap_path kwargs plus a memory_document property. CLI wires both files in `repl()` and adds `memory show / refresh / edit` commands.
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
Closes #160.
docs/memory-system.mdline 38 flagged MEMORY.md / BOOTSTRAP.md as 구현 예정 — Tier 2 summaries are auto-generated per-session but there was no durable bridge between them and the user-curated long-term context. This PR adds that layer.~/.qracer/MEMORY.md— a single Markdown file with a machine-managed auto region delimited by<!-- BEGIN:auto -->/<!-- END:auto -->. The auto region holds open theses (with entry/target/stop/catalyst) and upcoming catalysts, regenerated fromFactStoreafter every thesis save. Everything outside the auto region is user-curated free text and preserved verbatim across refreshes.~/.qracer/BOOTSTRAP.md— optional raw text loaded once atConversationEngineinit and pushed onto the session history as asystemturn so long-term preferences ("I'm a long-term value investor") reach the synthesizer without code changes.What changed
qracer/memory/memory_file.py(new) — self-contained module:MemoryDocumentdataclass (auto_theses, auto_catalysts, user_content, last_updated) plussummary_line()for briefings.render_memory(doc)/parse_memory(text)round-trip.load_memory(path)/save_memory(doc, path)with atomic.tmp-swap writes and tolerant fallbacks for missing/unreadable/malformed files.refresh_memory(doc, fact_store, catalyst_horizon_days=30)— pure function that regenerates the auto region fromFactStore.get_open_theses()andget_upcoming_catalysts()without mutating user content.refresh_memory_file(path, fact_store)— convenience wrapper.load_bootstrap(path)— returnsNonefor missing/empty files.qracer/conversation/engine.py— two new optional kwargs (memory_path,bootstrap_path)._prime_long_term_memory()runs at the end of__init__: BOOTSTRAP.md content becomes asystemturn; MEMORY.md with non-empty auto content becomes a renderedsystemturn._persist_factsnow calls_refresh_memory_file()after a successful thesis save so the auto region stays current. All load/save paths are try/except-guarded — a malformed MEMORY.md can never break the query loop. Newmemory_documentproperty exposes the cached doc.qracer/cli.py—repl()wiresmemory_path = _user_dir() / "MEMORY.md"andbootstrap_path = _user_dir() / "BOOTSTRAP.md"into the engine, and surfaces✓ MEMORY.md: N active theses, M upcoming catalystson startup when a doc loads._repl_loopacceptsmemory_pathand handles three new commands:memory show— print the file (or a hint if absent).memory refresh—refresh_memory_file()and sync the engine's cached doc.memory edit— launch$EDITOR(falls back tonano/vi), seeding the file with a canonical template on first use.BANNER +
_HELP_TEXTupdated accordingly.docs/memory-system.md— replaces the 구현 예정 banner with the new format spec and CLI command list.Scope mapping (issue #160)
memory editsystemturn in_prime_long_term_memory_refresh_memory_fileruns after every_persist_factssave — supersession flips happen insideFactStore.save_thesis, so the regenerated open-theses list reflects them on the next renderload_bootstrap+ system-turn injectionmemory show,memory edit,memory refreshTest plan
uv run pytest tests/memory/test_memory_file.py tests/conversation/test_engine.py— 81 passed (24 newtest_memory_filecases + 7 newTestLongTermMemoryengine cases).uv run pytestfull suite — 809 passed, 14 skipped.uv run ruff checkon changed files — clean.uv run pyright qracer/memory/memory_file.py qracer/conversation/engine.py— 0 errors, 0 warnings.New tests cover
memory_file*Last updated:*falls back tonow(); bullets outside the## Active Thesesheading are ignored; user content between auto region and trailing sections is captured.last_updatedbumped.save_memorycreates parent dirs; missing file returns default;refresh_memory_filepreserves user section on disk;.tmpfile cleaned up after atomic swap.None; empty file returnsNone; non-empty returns stripped content.summary_linecounts.Engine integration
systemmessage inhistory.memory_document.systemmessage in history.engine.memory_documentreflects the new thesis.Manual verification