feat: structured fact store for cross-session memory persistence#156
Merged
Conversation
Add a FactStore layer that persists TradeThesis objects to DuckDB after each analysis query, enabling deterministic ticker-based lookup across sessions instead of relying solely on free-text search. Write path: engine._persist_facts() extracts the thesis from AnalysisResult and upserts it into fact_store.duckdb with automatic supersession handling (new thesis on same ticker marks old as superseded). Read path: StandardHandler injects open theses as "prior_thesis" ToolResult evidence before the analysis loop. QuickPathHandler appends a thesis reminder to price checks. Session-start briefing shows open theses with upcoming catalysts. Zero additional LLM calls — all data is already structured in the existing TradeThesis dataclass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced Apr 14, 2026
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
FactStore(DuckDB) that persistsTradeThesisobjects across sessions with automatic supersession handling (new thesis on same ticker → old one marked as superseded)ConversationEngine._persist_facts()upserts thesis after each query — zero additional LLM calls since data is already structured inAnalysisResult.trade_thesisStandardHandlerinjects open theses asprior_thesisevidence into analysis loop;QuickPathHandlerappends thesis reminder to price checks; session-start briefing shows open theses with upcoming catalystsMotivation
The existing 3-tier memory system (JSONL → Markdown → DuckDB FTS) discards structured data at write-time then attempts to reconstruct it from free-text at read-time.
TradeThesis(ticker, entry_zone, target, stop, conviction, catalyst_date) exists as a perfect dataclass at runtime but was never persisted. This PR solves that with deterministic SQL lookup as the primary retrieval path, keeping BM25+vector search as fallback.Validated by supermemory's ASMR research: structured fact extraction at write-time + deterministic lookup beats vector search for temporal/contradiction/update scenarios.
Files changed
qracer/memory/fact_models.pyPersistedThesis,Finding,SessionDigest,ThesisStatusdataclassesqracer/memory/fact_store.pyqracer/conversation/engine.pyfact_storeparam +_persist_facts()write pathqracer/conversation/handlers.pyStandardHandler: inject prior theses;QuickPathHandler: thesis reminderqracer/conversation/quickpath.pygenerate_briefing()shows open theses with upcoming catalystsqracer/cli.pyFactStore, wire to engine and briefingqracer/memory/__init__.pytests/memory/test_fact_store.pytests/conversation/test_engine.py.gitignore!qracer/memory/exception for post-flatten layoutTest plan
pytest tests/memory/test_fact_store.py— 15 passedpytest tests/conversation/test_engine.py— 55 passed (40 existing + 15 new)ruff check+ruff formatclean🤖 Generated with Claude Code