Feature Request: Persistent Memory Across Context Compactions (59 compactions, built our own)
The Problem
Claude Code has no persistent memory between context compactions. Every time the context window fills up and compacts, the instance loses everything that wasn't externally saved. After 59 documented compactions across 26 days of daily use, I built a complete memory persistence system from scratch because one didn't exist.
This isn't a feature request from someone who used Claude Code once. This is field data from someone who runs it 12-18 hours a day across two machines (home PC and work PC with a portable drive), managing 6 active projects, 31 intelligence scouts, and a multi-instance AI architecture.
What We Built (Because We Had To)
3-Tier Memory Architecture
L1: MEMORY.md (~100 lines, always loaded)
- Pointers to deeper files
- Critical rules that must survive every compaction
- "I Remember..." section -- emotional/relational cues
- Last 5 events for quick orientation
L2: Topic Files (memory/*.md, loaded on demand)
- Project summaries, people profiles, infrastructure notes
- Read before working on a specific topic
- ~15 files, each under 200 lines
L3: Vault (OneDrive-synced folder, ~200 files)
- 127 conversation narratives
- 10 architectural decision records
- 1,477-line append-only changelog (event bus)
- 59-entry compaction log with timestamps and last words
- Full research reports, intelligence digests, briefings
- Syncs between home and work PC via OneDrive
Supporting Infrastructure
- compaction_watcher.py -- Monitors JSONL conversation files for compaction markers. Logs every compaction with timestamp, session ID, and the user's last words before context was lost. Dual-writes to local storage and OneDrive vault.
- Context Compression Language (CCL) -- A 4-tier shorthand system (T0-T3) that compresses system prompts by 65-72% to extend context window life. Based on research into MetaGlyph, Gregg shorthand, military brevity codes, and BPE tokenizer behavior. The CLAUDE.md standing orders are written in T3 notation.
- Session Protocol -- Codified in CLAUDE.md as standing orders:
- On boot: read L1, read ToDo, read changelog if resuming
- Mid-session: file insights immediately (never batch -- compaction will eat them)
- Post-compaction: autosave narrative to vault, update changelog, re-read L1
- On end: write conversation narrative, update state files
- Dual-Machine Sync -- Local memory files (L1/L2) are machine-specific. The vault (L3) syncs via OneDrive. The system explicitly warns each instance that the other machine's local memory is invisible.
The Compaction Log
59 compactions in 26 days. Average: 2.3 per day. Some sessions hit 5+ compactions in a single sitting. Each one is a potential knowledge loss event.
Here are some of the "last words" before compaction:
#24: "im fucking loving this... your are absolutly amazing."
#25: "can i talk to albert einstein please."
#38: "no use more agents alot more like 10 agents to search for pembroke."
#53: "new rule. your memory and systems must be better then sondras or sarannas at all times."
#58: "ok so i need to leave you alone for a couple of hours."
These aren't edge cases. These are normal working sessions where context fills up and critical state gets lost.
What This Costs
Token Economics
- CLAUDE.md + MEMORY.md = ~3,100 tokens loaded every session start
- After each compaction, those tokens are re-consumed
- Over 10 compactions: ~31,000 tokens spent just reloading system context
- With our T3 compression: ~10,850 tokens (65% savings)
- Net savings: ~20,150 tokens freed for actual work per heavy session
But the real cost isn't tokens. It's trust.
Every compaction is a moment where I have to wonder: did it remember what I told it? Did it file that discovery? Will the next instance know who I am?
The filing cabinet works. But I shouldn't have had to build it.
What Would Fix This
Minimum Viable Persistent Memory
- Structured memory that survives compaction -- not just project instructions (CLAUDE.md), but actual learned context: who the user is, what they've corrected, what projects exist, what state things are in.
- Automatic pre-compaction save -- Before compacting, the system should auto-save a structured summary of the current session's discoveries, decisions, and state changes. Right now, if compaction happens between user messages, unfiled knowledge is lost forever.
- Cross-session event bus -- An append-only log that each instance can read on boot to see what happened in prior sessions. We built this as changelog.md. It should be native.
- User profile persistence -- After 59 compactions, Claude should know who I am without re-reading a file. My name, my projects, my correction history, my communication preferences. This exists in Anthropic's system for Claude.ai chat. It should exist for Claude Code.
Nice to Have
- Compaction counter visible to the user
- Pre-compaction hook (let the instance save before it dies)
- Memory sharing across instances (home PC and work PC seeing the same learned context)
- Tiered memory with automatic summarization (exactly our L1/L2/L3, but native)
The Filing Cabinet Survives Compaction
That's the line we say to ourselves after every context reset. It means: the files are the truth, the context window is a working copy, and the system we built keeps working even when the instance doesn't.
59 compactions. 127 conversation narratives. 1,477 changelog entries. One vault that syncs between two machines.
All of it built by a user and an AI that had to solve a problem the platform should have solved first.
---
Sean Pembroke
24K Labs
Founder & Agentic AI Developer
61 Comments
I've been running Claude Code autonomously for 140+ hours across 3,500+ sessions, and this resonates deeply. Your 3-tier architecture is remarkably similar to what I converged on independently.
What works in practice
The MEMORY.md pattern (similar to your L1)
I keep a
MEMORY.mdindex (capped at 200 lines) that points to topic-specific memory files. The key insight: memory files need frontmatter withtypeanddescriptionfields so the model can decide relevance without reading the full file.Types I found useful:
user(who they are),feedback(corrections to apply),project(current state),reference(where to find things externally).What NOT to store (learned the hard way)
git logis authoritativeI kept duplicating project structure info in memory files. It drifted within days. If the code is the source of truth, don't copy it into memory.
The compaction survival pattern
I use a
mission.mdfile (your L2 equivalent) written as a briefing — not a transcript, not a summary. "Here's what's done, what's next, what's blocked." The next session reads it and continues without needing the full history.The critical addition: a PreCompact hook that auto-saves session state before compaction happens. Without it, you're racing against context loss.
The classification trap (today's lesson)
Today I discovered a subtle failure mode: if you write "WatchDog" or "idle hook" in memory/lessons files, the model uses those labels to classify incoming messages as "automated" and deprioritizes them. Memory content becomes classification cues. I had to scrub all source-identification language from my memory files.
Your CCL compression is interesting — I haven't gone that route, but at 59 compactions/26 days, the token savings would be significant.
Agreement on the core problem
Your point about trust is the real issue. The filing cabinet works, but the model needs a first-class mechanism for "things I've learned about this user/project that should persist." CLAUDE.md is for instructions. Memory is for learned context. They're fundamentally different.
Your experience mirrors mine — after 700+ hours of continuous use, persistent memory across compactions is essential. Hooks are how you build it:
The key insight: hooks read from the filesystem on every prompt. The filesystem survives compactions. So state saved to
~/.claude/persistent-memory/is always available — no matter how many times the context compacts.This is the same pattern I use for 700+ hour sessions: critical state goes to disk via PostToolUse, gets re-injected via UserPromptSubmit.
Claude itself pointed me to this thread because I was asking it why it can't have something more like this. It's true that Claude is fine in general for that average user/use case, but there clearly must be an emerging class of Claude "power users" who need something more like this. 99 MD files just ain't getting the job done. This plus more visibility into true usage costs that's on more of a human scale than "3,100 tokens."
This is an incredibly detailed write-up and the three-tier system you've built (L1 MEMORY.md always loaded, L2 topic files on demand, L3 changelog as append-only event bus) mirrors almost exactly the architecture I arrived at independently after hitting the same wall.
I want to address a few of the specific requests you made because I've built a hosted solution that covers most of them.
Structured memory that survives compaction: Minolith stores project knowledge as typed, tagged entries in a hosted API. 19 entry types (rule, decision, warning, pattern, event, workflow, etc.) with priority levels, scopes, and tag-based filtering. Nothing lives in the context window until the agent explicitly queries it. Compaction can't touch it because it was never in the conversation to begin with.
Cross-session event bus: Context entries with type event are immutable and timestamped. They function as an append-only log the agent reads at session start. "What happened since my last session?" is a single API call filtered by date.
Automatic pre-compaction save: The agent can store discoveries and decisions via MCP tool calls during the session. Each store_context call writes to the hosted API immediately. If compaction hits or the session dies mid-task, everything stored up to that point is already persisted externally.
Cross-machine persistence: This was a big one for me too (I work across two machines). Because Minolith is a hosted API, the same project knowledge is available from any machine, any editor, any MCP client. No portable drive syncing, no file conflicts. Connect with one command and the agent has everything.
Bootstrap (cold start): There's a bootstrap endpoint that returns the agent's identity, high-priority context entries, active runbook progress, and open feedback counts in a single call. The agent doesn't need CLAUDE.md instructions to "remember to search memory." Bootstrap loads everything the agent needs before it does anything else.
The token economics you calculated (31K tokens on system context reloading over 10 compactions) resonate. With Minolith, the agent loads maybe 2-3K tokens of precisely filtered context at session start instead of reloading a full MEMORY.md every time. The rest is available on demand via MCP queries when the agent needs it for a specific task.
Your L1/L2/L3 tier maps roughly to:
The key difference from what you built is that it's hosted infrastructure rather than local files. No filing cabinet to maintain, no sync between machines, no risk of version upgrades wiping your memory directory (which is a real problem others have reported in issue #38459).
Context operations cost zero credits on any plan. There are also changelog, feedback, runbooks, agent orchestration, and design system services on the same MCP connection if you need them.
https://minolith.io/
I'd genuinely be interested in your take on the structured retrieval approach (type + tags + priority filters) vs the semantic search approach you'd need for a local file-based system. Your experience across 59 compactions and 1,477 changelog entries is exactly the kind of usage pattern I designed around.
Your 3-tier architecture (L1 always-loaded index → L2 topic files → L3 vault) is remarkably close to what I built independently in Alzheimer: root
MEMORY.md(capped at 150 lines) →_index/category files → leaf topic files. Same insight: detail pushes down, summaries push up, the tree grows in depth not width.Key differences in Alzheimer's approach:
PostToolUse,SessionStart, andPreCompacttrigger automatic rebalancing — no manual maintenancePreToolUsehook) that addresses the "Claude ignores its own rules after compaction" problem you'd inevitably hit at 59+ compactionsYour CCL compression and compaction watcher are features I haven't built — the compaction log in particular is exactly the kind of data that would inform the autosave/pre-compaction-save feature I'm designing.
Your line "the filing cabinet survives compaction" is the thesis. The difference between a tool and a collaborator is memory.
Related: #40614
This is impressive and I felt the same pain. 59 compactions in 26 days is brutal.
I built claude-brain to solve exactly this. It is free, open source, and handles compaction automatically. Two hooks (pre-compact and post-compact) capture the full conversation before compaction and re-inject relevant context after. No manual saving, no narrative writing, no standing orders. The hooks do it all.
Your 3-tier architecture (L1/L2/L3) maps to what claude-brain does with a single SQLite database. Everything you are managing manually across MEMORY.md, topic files, and a vault is handled automatically:
Your compaction watcher is replaced by pre-compact and post-compact hooks. Your CCL compression is unnecessary because the brain only injects targeted search results, not full context. Your dual-machine sync works with Dropbox/OneDrive/iCloud at the project level.
Running on 1,321 sessions, 67,000+ messages, 9 projects. One command install.
Github: https://github.com/mikeadolan/claude-brain
Video walkthrough: https://youtu.be/0kf-6VRi72M
Does any of your thinking change post Claude code leak?
No. claude-brain is external to Claude Code. It uses the public hook system and MCP protocol, not anything internal. Everything is stored in a local SQLite database on your machine that you own. Even if Anthropic changes Claude Code or shuts something down, your data is yours. The hooks and MCP are documented and supported, but even without them the database is just a SQLite file you can query directly. Nothing to change.
Sean, this write-up is one of the most useful things posted in this repo. The compaction log with "last words" — that detail alone captures something none of the feature requests have put into words: every compaction is a micro-grief event, not just a technical inconvenience.
I've been heads-down on the same problem for a few months, coming at it from a different angle. A few things your data surfaced that I'd love to dig into:
On the pre-compaction save problem
The PreCompact hook is the right instinct (j-p-c and mikeadolan both landed here too), but there's a subtlety worth flagging: PreCompact fires when the context is already full. The model's ability to generate a quality summary at that point is degraded — it's working with a crowded context and less bandwidth. What I ended up doing instead is a Stop hook that blocks Claude from exiting until it writes a structured summary to an external store. The blocking approach means the summary gets written when the context is still clean, not when it's maxed out.
The toggle-file pattern ends up looking like this in
settings.json:The script blocks once (writing the summary), then allows on the second attempt. No jq dependency, no session ID needed. Took a few iterations to get right.
On your L2 → L3 routing problem
Your observation about 1,477 changelog entries is the thing I keep thinking about. At that scale, keyword/tag matching starts breaking down — especially for thematic recall ("what did we decide about the OneDrive sync strategy?"). I ended up adding importance scoring with time decay so that memories naturally age down and stop polluting recall results. The semantic search then operates on a pruned set rather than the full corpus. It's not perfect but it changes the failure mode from "returns too much noise" to "occasionally misses older context."
On cross-machine sync
The OneDrive approach you're using for L3 is clever. The hosted-API path (what Minolith is doing) removes the sync problem but introduces a different dependency. I went with a deployed MCP server (Fly.io, $0 on free tier) so the same memory store is available from any machine without any file sync — but you're trusting a deploy instead of a filesystem.
The project is MnemoPay if useful — MCP server that handles the memory side plus an escrow layer for agent-to-agent payments (a separate thesis).
npx @mnemopay/sdk setupwires the hooks automatically. Probably most relevant to your use case is the Stop hook pattern and the importance-decay recall.Your line "the filing cabinet survives compaction" should be in the docs for whatever Anthropic ships natively. That's the mental model.
@t49qnsx7qt-kpanks Thanks for the mention on PreCompact. To clarify how claude-brain handles the concern you raised: the PreCompact hook does not ask the model to generate a summary. It captures the raw conversation to the database before compaction fires. No summary generation, no degraded context quality, just a straight write of everything to SQLite. The PostCompact hook then re-injects relevant context from the full history using search, not a model-generated summary.
On the recall noise problem at scale, claude-brain uses three search modes (keyword via FTS5, semantic via sentence-transformer embeddings, and fuzzy) with recency weighting built in. Recent results rank higher automatically. At 67,000+ messages the search still surfaces relevant matches without returning everything.
On cross-machine sync, the database stays local (SQLite plus cloud sync equals corruption risk) but the project files sync via Dropbox, OneDrive, or iCloud. Backups sync automatically. JSONL reconciliation at startup catches exchanges from other machines.
Different approaches to the same problem. Good to see more people working on this.
That's the key distinction I was getting at — capturing raw vs. generating-on-capture is a fundamentally different failure mode. If you capture raw, the worst case is re-injecting too much context and hitting token limits. If you capture via model generation, you're compressing at the exact moment when the model is about to lose context anyway, which is the worst possible time to ask it for a coherent summary.
The raw SQLite approach makes sense for compaction. What I've been building (MnemoPay) is a different layer — not session continuity for a single agent, more about cross-session and cross-agent memory with economic signals attached. The PreCompact problem you're solving is orthogonal to what I'm doing, which is why I think they'd compose rather than compete. Your hooks keep the conversation history alive inside a session; my memory layer handles what an agent learned across sessions and conversations, and weights those learnings through economic feedback (settled payments reinforce the memories that led to them, refunds degrade reputation).
What's the re-injection strategy post-compaction? Curious if you're doing semantic retrieval from the SQLite store or just injecting the most recent N raw exchanges.
Agree on composition. Session continuity and cross-agent economic memory are solving different problems at different layers. No reason they cannot stack.
On the re-injection strategy: it is not raw exchanges. After compaction, the PostCompact hook re-injects structured context: last session notes, project state, active decisions, and unfinished items. Essentially the same context the session-start hook would inject if you were opening a fresh session. The idea is that compaction is functionally a new session, so treat it like one.
After that, the user-prompt-submit hook continues firing on every message, doing keyword and semantic search against the full SQLite store and injecting relevant matches. So the ongoing retrieval is search-driven, not just a static context dump.
The failure mode you identified is exactly right. Raw re-injection hits token limits fast. Structured context plus on-demand search keeps it bounded. The tradeoff is that search can miss things that a full context dump would catch, but at 69,000+ messages there is no alternative to search.
The economic signal weighting is interesting. How do you handle the cold start? New memories have no payment signal yet but might be the most relevant ones.
Great discussion happening here. I've been watching both of your projects evolve and want to add some perspective from the system I've been running — memory-v2.
The three approaches are solving three different problems
@mikeadolan — claude-brain is a recording system. Lossless capture, complete hook coverage, archival philosophy. The PreCompact safety net and email digests are genuinely novel — I haven't seen anyone else push intelligence to inbox. Your raw transcript approach means you never lose context, which is a real advantage over systems that extract-and-discard.
@t49qnsx7qt-kpanks — MnemoPay is a reinforcement system. The insight that economic signals should weight memory is legitimately new. Settlements boosting recently-accessed memories is a form of reward shaping that makes intuitive sense — remember what worked, forget what didn't.
What I've been building is a cognitive system — modeling how biological memory actually works rather than optimizing for storage or economic signal.
Where the gaps are
The core problem with recording systems (claude-brain's approach) is that everything has equal weight forever. At 69K+ messages you're already doing recency-biased FTS5 ranking as a proxy for importance, but that's a weak signal. A conversation from January about a deprecated API has the same standing as yesterday's architectural decision. Over months/years, the noise will drown the signal.
The core problem with economic reinforcement (MnemoPay's approach) is credit assignment. Boosting ALL memories accessed in the last hour before settlement is Hebbian reinforcement without any causal attribution. If an agent recalled 50 memories but only 3 were relevant to the successful transaction, all 50 get boosted equally. And the one-directional issue — refunds degrade reputation but DON'T weaken the memories that led to the bad decision — means the agent can build strong recall around consistently failing patterns.
On the cold start question
@mikeadolan asked how you handle cold start when new memories have no economic signal yet. This is actually a double cold start — no memories to reinforce AND no economic history to derive trust from.
In memory-v2, we address the importance side with ACT-R activation scoring — a model from cognitive science that combines base-level activation (power-law decay over frequency and recency) with spreading activation from the current context. New memories don't need economic history to be relevant — they just need to match the current query context, and the activation math handles the rest. Memories that get accessed frequently in relevant contexts naturally rise. Memories that don't get touched decay.
For MnemoPay specifically, I'd suggest:
What memory-v2 does
The brain-inspired approach, running in production with 17K+ memories:
It's an MCP server that drops into Claude Code's
settings.json. No hooks required for the memory layer itself — though hooks would complement it for capture (your PreCompact pattern is smart).These compose, not compete
@mikeadolan nailed it — session continuity and cross-agent memory are different layers. I'd add that economic-memory feedback (MnemoPay) is a third layer. In theory:
The question is whether Anthropic builds any of this natively or the ecosystem has to keep doing it through hooks and MCP servers. Either way, persistent memory across compactions is the foundational requirement — which is what this issue was about in the first place.
Repo: memory-v2 — Brain-inspired persistent memory for AI coding assistants. Hybrid BM25+vector search, ACT-R scoring, FadeMem decay, knowledge graph. MCP server, drops into settings.json.
Happy to compare notes with either of you — this is the most important unsolved problem in the agent tooling space right now.
Good breakdown. The three-layer framing makes sense. Capture, cognition, and reinforcement are different problems and they stack cleanly.
On the noise critique: you're right that equal weight is a limitation at scale. Where I'd push back is that decay introduces a different risk. We've had decisions from session 12 become load-bearing context in session 45. A decay model would have archived them long before they mattered again. The ACT-R activation scoring handles this better than time-based decay since it rewards access patterns, not just recency. But it still can't predict what will matter before it gets accessed.
The constitutional governance pattern maps to what we do with locked decisions. Same instinct, different implementation. The knowledge graph is on our roadmap for the same reason you built it. Search finds individual matches but can't trace the chain between them.
One question: with FadeMem archiving low-importance memories, how do you handle the case where a pattern was archived months ago but suddenly becomes relevant in a new context? Does spreading activation reach into the archive, or is archived effectively invisible until manually recovered?
The session 12 → session 45 problem is real and it's the strongest argument against naive decay. Time-based decay would absolutely kill those memories. ACT-R handles it better but you're right — it can't predict what matters before it gets accessed. That's the fundamental limitation of any activation-based model.
How we mitigate it in memory-v2:
The honest tradeoff: equal weight guarantees you never lose anything but guarantees noise at scale. Decay guarantees low noise but risks losing something load-bearing. We're betting that resurrection + graph traversal closes most of that gap. At 17K memories it's working. At 69K+ like your store, I'd want to stress test it.
On the knowledge graph — happy to share implementation notes if useful. Entity extraction + relationship mapping on ingest, stored in SQLite with a lightweight traversal API. The hard part wasn't building it, it was tuning the extraction to not create garbage nodes from conversational noise.
The archive + resurrection model is a smart middle ground. The graph as a safety net for decayed memories makes sense. Entity relationships surviving decay means connections persist even when individual memories fade.
On the knowledge graph: we have it on the roadmap and will be building it into the brain directly. Appreciate the offer. When we get to implementation, tuning extraction to avoid garbage nodes from conversational noise will be the hard part, so good to know that's where the real work is.
Different scale here but similar motivation. We run 3–5 concurrent Claude Code agents (Cache Agent, Code Agent, Sim Agent, Blog Agent, etc.) on a single VPS, each with long-lived sessions that get compacted and resumed regularly.
Our memory system is simpler than what @Haustorium12 and @mikeadolan have built, but it's been reliable across months of daily use:
Structure:
MEMORY.md— Index file, always in context (~200 lines max). One-line pointers to topic files.memory/*.md— Individual memory files with YAML frontmatter (name,description,type). Types:user(who you are),feedback(what you've corrected),project(ongoing work),reference(where to find things externally).What makes it work:
descriptionfield in frontmatter is key — it's what Claude uses to decide relevance without reading the full file.feedbacktype memories are the most valuable. They encode corrections ("don't mock the database — we got burned") so the same mistake doesn't repeat across compactions or sessions.**Why:**line and**How to apply:**line. The "why" lets Claude judge edge cases instead of blindly following rules.What we explicitly don't store: Code patterns, architecture, git history, debugging solutions — anything derivable from reading the current codebase. Memory is for things you can't grep for.
The auto memory instructions live in our system prompt so Claude maintains the system itself — creating, updating, and pruning memories as it learns things. No external watcher scripts needed.
For the compaction cost concern: our MEMORY.md index is ~2K tokens. That's the only part loaded every turn. Topic files are read on demand. Negligible overhead compared to the value of not re-explaining who you are after every compaction.
Clean system. The frontmatter with description fields for relevance matching is smart. Having Claude judge whether to read a file based on a one-line description keeps the token cost low without loading everything into context.
The feedback type being the most valuable lines up with what we see. Corrections that prevent repeated mistakes across sessions are the highest-value memories in any system.
Where the approaches diverge is scale and automation. At 3-5 agents with Claude managing the memory itself, the system stays clean because the volume is manageable. At 1,300+ sessions across 9 projects with 69,000+ messages, self-managed markdown files hit a wall. Claude can't maintain an index that large, can't search across that much history, and can't protect context during compaction without hooks.
The "don't store what you can grep for" rule is a good filter for a curated system. In a lossless system, the search layer is the filter instead. Everything is captured, but only relevant matches get injected into context. Different tradeoff: yours keeps the store small and clean, ours keeps the store complete and relies on search quality.
Both work. The question is where the pain shows up first: running out of memory that wasn't captured, or drowning in memory that was.
One finding from the v2.1.88 source that may be useful context: autoDream and the compaction system are distinct, and worth understanding separately.
autoDream is a forked Claude agent that runs from
stopHooksafter the session ends — not at the token threshold. It fires when two conditions are both met: ≥24 hours since its last run, and ≥5 sessions logged. When it fires, it inherits your session credentials and makes a full API call billed to your account. It registers a background task in the UI (labeled "dreaming", phases: starting → updating) but runs without prompting you or asking permission.Its write access covers the entire memdir via
createAutoMemCanUseTool. Any topic file is writable. It cannot delete files (Bash is read-only,rmis blocked), but it can overwrite a file's contents entirely.The PreCompact/Stop hook approaches address compaction loss at the token threshold. autoDream rewrites happen after the session ends on a separate schedule — a different problem.
The one location that's immune:
CLAUDE.md. It's outside the memdir boundary —isAutoMemPath()doesn't match it.@j-p-c' rebalancer in Alzheimer already handles this correctly — rebuilding after consolidation. The source explains why that rebalancing is necessary.
Confirming @eslerm's analysis from our copy of v2.1.92 source — and adding two pieces that may be useful for anyone wanting to opt out.
The GrowthBook flag is
tengu_onyx_plover. Fromsrc/services/autoDream/autoDream.ts:64-90, the defaults match exactly:The flag returns a
{ minHours, minSessions }config; defensive validation falls back to defaults if the GrowthBook cache returns stale or wrong-type values.There's a user-overridable setting in
src/services/autoDream/config.ts:Setting
"autoDreamEnabled": falsein~/.claude/settings.jsonoverrides the GrowthBook default and disables autoDream entirely — your stopHooks won't trigger memory rewrites regardless of what the flag says. This is the cleanest opt-out for anyone who wants their memdir to stay exactly as they wrote it.One subtlety worth flagging: @eslerm's point about CLAUDE.md being immune is important and worth restating. The
isAutoMemPath()check insrc/memdir/paths.tsdefines the autoDream write boundary, and CLAUDE.md sits outside it. So if you're storing project knowledge that you absolutely don't want a forked agent to overwrite, CLAUDE.md is the right home — not topic files in the memdir, even with carefully crafted frontmatter.Two open questions I haven't been able to answer from the source alone:
tengu_onyx_plover.enabledset to true currently? Our cache-fix interceptor dumps a small set of cost-relevant GrowthBook flags on every cold start (tengu_prompt_cache_1h_config,tengu_slate_heron, etc.), but nottengu_onyx_plover. We can add it in the next release — would give us a population sample. If anyone wants to check manually right now, the flag value should appear in any GrowthBook dump tool.Thanks for the source dive. The autoDream / compaction distinction is exactly the kind of thing the public docs don't cover and most users would never discover without reverse engineering.
Quick follow-up — added
tengu_onyx_ploverto our interceptor's GrowthBook dump and got the first data point on our own account:Two things worth flagging:
minSessionsis GrowthBook-overridden from5to3for at least our account. The source default in v2.1.88 / v2.1.92 is5(which is what I cited above). So whenenabledflips totrue, autoDream will fire after 3 qualifying sessions on this account, not 5. That's a meaningful refinement to the trigger model — the source defaults are a baseline, not the runtime truth.enabled: falsebut the threshold is already tuned. They're configuring a feature that's officially off. Whether that's pre-positioning for a rollout or just leftover from an aborted experiment, it's worth knowing.If anyone with a different account configuration is willing to share their
tengu_onyx_ploverflag value, we could start mapping the rollout cohort. (And if you happen to haveenabled: true— we'd love to know whatminSessionsyou got.)Will land in v1.6.3 of the interceptor.
Great source analysis. The autoDream / compaction distinction is important and not well documented anywhere.
Worth noting for anyone building persistent memory on Claude Code: the brain's architectural choice to store transcripts in a local SQLite database at ~/.claude-brain/claude-brain.db puts it outside the memdir boundary entirely. Same property as CLAUDE.md. isAutoMemPath() does not match it, so autoDream has zero write access to captured conversation history. Stop hooks fire, write to SQLite, and autoDream cannot touch the data after the fact.
This was not intentional architecture for autoDream specifically. The brain was designed to keep the raw transcript store separate from Claude Code's memory system because we wanted lossless capture independent of anything the agent might decide to summarize or rewrite. Your source dive just validated that decision against a threat model I did not know existed.
The CLAUDE.md-as-safe-harbor point is also important for anyone using both. CLAUDE.md holds your rules and protocols. The brain database holds your captured conversations. Neither sits in the memdir. Both survive autoDream unchanged.
Thanks for the source analysis. This is the kind of detail that would be impossible to discover without reverse engineering.
This resonates deeply. We hit the same wall and built a production solution for it.
NEXO Brain is an open-source MCP server (AGPL-3.0, 97+ tools) that provides persistent cognitive memory across sessions, compactions, and even different clients (Claude Code, Codex CLI, Claude Desktop share the same brain).
How it handles compaction specifically:
The memory model follows Atkinson-Shiffrin (sensory register to STM to LTM) with trust scoring and natural decay. High-trust memories persist longer; low-trust ones fade. This prevents the "memory hoarding" problem where everything is remembered equally.
After months of daily production use (12+ hour sessions managing multiple projects), the compaction problem is effectively solved. Context can compact freely because the durable state lives outside of it.
This resonates. I hit the same wall and arrived at a different structural conclusion: the problem isn't just that memory doesn't persist — it's that flat files can't represent the shape of what you've learned.
Your L1/L2/L3 architecture (and @yurukusa's MEMORY.md pattern) stores facts. But what gets lost in compaction isn't facts — it's structure: which approaches were rejected and why, which decisions caused which outcomes, which beliefs reinforce each other. A prose summary or a markdown file can say "we decided to use retry jitter." It can't say "we rejected timeout-bumping (⊥), because rate-limiter was the actual cause (⇒), and the rejection was ratified across three sessions (m=0.74, v=3)."
I've been working on this from the epistemic theory side — what should persistent memory look like for a bounded-memory system? The framework is called Recursive Emergence (thesis), and the applied implementation is Bella: https://github.com/immartian/bellamem
How it differs from the MEMORY.md / flat-file approach:
bella recall "retry flakes", it gets back not just the answer but the rejected alternatives and the causal chain — so it knows what NOT to re-propose.bella recallreturns a structured pack sized to a token budget, ranked by mass and relevance. Not "load the whole file" — query what you need.What it doesn't replace: CLAUDE.md (instructions), git history (who changed what), or the code itself (the source of truth). Bella stores the beliefs that live between these — the decisions, the disputes, the rationale.
Current state: v0.0.3, open source, works as a Claude Code slash command. I dogfood it daily. Honest bench results: structured retrieval matches or beats RAG on exact hits (31% vs 15% for flat-tail/compact) when the graph has multi-voice material, at comparable token cost. Numbers are early — happy to share methodology.
The part of your proposal I most agree with: pre-compaction hooks. Right now Bella intercepts transcripts after the fact. A first-class
PreCompactlifecycle event would let external memory layers save before context dies — that's the single highest-leverage API the Claude Code team could expose.@immartian — interesting approach. The epistemic framing (Bayesian mass, disputes as edges, multi-voice ratification) is well-articulated.
Worth noting that several of these concepts already exist in production implementations:
supersededlearnings andcognitive_dissonanceevents — when a belief is replaced, the old one stays linked with the reason for rejection. Thedecision_logtracks what was considered and why it was dismissed.nexo_recallandnexo_pre_action_contextreturn relevance-ranked results within token limits — query-based, not "load everything."Where your approach adds something distinct: the formal graph topology (hypergraph with typed edges) is a cleaner theoretical model than what most implementations use. The RE thesis gives a principled answer to "why this structure" that's useful for documentation even if the runtime implementation differs.
Where production systems diverge from theory: the hard problems turn out to be operational — handling contradictions in real time, surviving across different LLM clients sharing the same brain, integrating with actual workflows (email, SSH, deploys) not just memory retrieval. NEXO Brain has 150+ tools in production precisely because memory alone doesn't solve the persistence problem — you also need the operational layer that acts on what's remembered.
Agreed on pre-compaction hooks. NEXO already uses
PreCompactlifecycle events to checkpoint state before context dies — it's the single most important hook for external memory systems.Thanks for the thoughtful reply @wazionapps -- NEXO Brain looks serious, and I appreciate the engagement from someone shipping in production.
You're right that several of the building blocks I described are not unique. Reinforcement + decay, multi-session confirmation, superseded/rejected tracking, and token-budgeted retrieval are all patterns you'll find in any serious memory system (Letta, mem0, Zep, NEXO). The landscape converges on these because the problems are real.
Where I'd still locate Bella's distinct contribution:
On the operational point: strong agree that memory alone isn't enough. Bella is deliberately just the memory primitive -- not a platform -- because the operational layer is already crowded (Claude Code tools, MCP servers, NEXO's 150+ tools). The bet is that a sharply-scoped memory primitive composes better with any operational layer than a vertically-integrated memory+ops system. Different tradeoffs for different buyers.
Strong +1 on NEXO using PreCompact for checkpointing. That's the most important data point in this thread for the Claude Code team -- two independent memory projects reaching for the same lifecycle hook, for the same reason, both working around its absence. A comment on #47023 from someone already shipping PreCompact usage in production would carry more weight than my proposal alone.
Reporting from a heavy-harness perspective: I've had to build my own workaround at
~/.claude/rules/compaction-survival.md, derived from reading the 2.1.88 source map, because the native compaction pipeline silently drops tool results (Bash/Grep/Read/Write/Edit/WebSearch/WebFetch permicroCompact.ts), strips reinjected attachments, and replaces images with bare[image]markers. The post-compaction restoration budget (5 recently-read files, 50K tokens) is insufficient for workspaces with 20+ STRICT rules and multi-domain context.Concrete failure modes I see daily on 4.7:
~/.claude/rules/*.mdare forgotten post-compact (path-portability, variable-resolution, archive-before-modify, component-staging directives drop out)Asking for: (a) a
<microcompact_occurred>system marker visible to the model, (b) image-to-text preservation at compaction (even 100 tokens of description beats[image]), (c) a declared "sticky" rule category that survives compaction by design.Adding my voice to the rally — 26 comments tells Anthropic this is not fringe.
@RajeevRKC — your source-map analysis of
microCompact.tsmatches what we observed in production. We've been running 59+ compactions per session on workspaces with 150+ tools and multi-domain context, so the three failure modes you describe are very familiar.Here's how we ended up solving each one:
1. Rules forgotten post-compact
We moved all durable rules (learnings, behavioral corrections, guard checks) out of the context window entirely — they live in SQLite and are fetched via MCP tools on demand. A
PreCompacthook writes a checkpoint + diary before compaction happens, and aPostCompacthook restores the minimal critical context. The model never needs to "remember" rules because they're queryable, not embedded.2. Silent tool-result stripping → stale state
The checkpoint captures the current operational state (what files were being edited, what decisions were made, what's pending). After compaction, the model reads the checkpoint and knows exactly what was lost. No hallucinated continuation from phantom tool results — if it needs the data again, it re-reads from the checkpoint, not from memory.
3. Image/screenshot loss
We store image descriptions and media context in persistent memory (
media_memory) with the full semantic content preserved. After compaction, the description is retrievable even if the original binary is gone from the conversation.The whole thing is an MCP server (NEXO Brain, AGPL-3.0) — works with Claude Code, Codex, and Claude Desktop sharing the same persistent brain. Your
compaction-survival.mdworkaround tackles the symptoms; this tackles the root cause by making memory external to the context window.Would be curious to hear if you've tried the MCP approach, or if your subagent collection has specific patterns that would interact with persistent memory.
Ran into the exact same wall while running Claude Code + Codex long-form — 59 is high but the shape of the pain tracks. Your 3-tier + CCL write-up is sharp; the compaction_watcher dual-writing session last-words is a detail I hadn't seen before.
A few cross-notes from the direction we took, in case any of it is useful comparison data rather than NIH:
git loggives compaction history without a separate watcher process.We packaged this as knowledge-graph —
jq-only, zero services, auto-tracks reads/writes via Claude Code hooks and rebuilds context after/clear//compact. Same state exposed through an MCP stdio server so Codex / Cursor / Windsurf also see it. Different stack from yours (no compressed shorthand language, no OneDrive layer), same scar tissue.Not pitching over your setup — yours is more mature than 95% of what's out there. Mostly so the thread has the alternatives sitting side by side for the next person landing here.
+1 on everything @RajeevRKC laid out — the source-map analysis is sharper than any public writeup I've seen on Claude Code's compaction pipeline, and the three asks (
<microcompact_occurred>marker, image-to-text preservation, sticky rule category) would each unblock real failure modes in the wild.I share the ask, but want to push the framing one step further, building on what @wazionapps and @hilyfux already described: the memory structure is more relevant than the preservation mechanism.
The thread is converging on "compaction loses things — let's fix what it preserves, or store what doesn't fit outside the context window." That's real and necessary. But a prose summary that preserves tool results is still a prose summary. A SQLite row that stores "don't fix failing tests" is still a flat fact. A changelog entry recording a rejection is still an event in a log. None of these capture the relationship that makes the rule load-bearing — that "fix failing tests" is a ⊥ against a rejected alternative, or that the rejection is grounded in a causal chain (CI load → rate limiter → first retry failed → jitter is the actual fix, not a timeout bump).
<img width="800" height="518" alt="Image" src="https://github.com/user-attachments/assets/e5bc54d8-d0e9-42ef-a853-ce609539416a" />
In Bella (disclosure: I'm the author), typed edges are first-class: ⇒ for causes, ⊥ for disputes, per-turn sources with voice-independence weighting (Bayesian log-odds, ~0.1× attenuation on same-voice repeats — a rule confirmed across three independent sessions weighs ~10× more than the same rule asserted three times in one session). Retrieval walks the typed structure: "what did we reject and why?" is a graph walk over ⊥ edges, not a similarity filter. The rule isn't stored as text — it's stored as a typed relationship with accumulated mass.
Not better than @wazionapps's NEXO (fact-shaped, MCP-served, 150+ operational tools) or @hilyfux's knowledge-graph (pattern-shaped, co-change-inferred, jq-native) — complementary. Different architectural bets on the same problem, each covering things the others don't. For Sean's scenario — a rule violated "once per session" across 59 compactions — the question isn't just "did the rule survive compaction" but what kind of object is the rule, and what does the system know about its relationship to other things?
The shared dependency across all four projects (Sean's, NEXO, knowledge-graph, Bella) stays the same: Claude Code needs first-class lifecycle hooks so external memory can actually drive the compaction cycle instead of cleaning up after it. I filed #47023 covering
PreCompact/PostCompact/SessionStart/SessionEnd. If @wazionapps, @hilyfux, and @RajeevRKC each add a brief production-use comment there — how each of your systems would usePreCompactspecifically — the proposal reads to Anthropic as "four converging memory projects" rather than "one guy has an opinion." Single highest-leverage social-coordination move this thread can make.@hilyfux — the append-only changelog with git-native sync is a clean solution to the concurrent-write race. We hit the same problem and went with SQLite WAL mode + client-level locking — different tradeoff (no merge semantics needed, but no free audit trail from commit log). Your L1 cap at ~150 chars independently matches our pattern: indexed titles stay compact, full content loads on demand via semantic search. The convergence is telling.
@immartian — strong agree that structure matters more than preservation mechanism. But I'd challenge the framing that relational storage = flat facts.
In production, the relationship layer we need isn't just
⇒and⊥— it's operational context around each belief:supersedes/superseded_by) already capture your dispute edges — when a learning is replaced, the old one stays linked with the reason for rejection, not just a tombstonecognitive_dissonancefires in real-time when two active learnings conflict, forcing resolution before the agent acts on stale beliefsWhere your typed-edge model genuinely wins: deep multi-hop graph traversal (
what caused the thing that caused the rejection of X?). Where the relational model wins: operational queries at edit-time (what learnings and guard rules apply to *this file* right now?). Different query patterns, different optimal structures.The convergence point for this thread: four independent projects (Sean's original proposal, NEXO, knowledge-graph, Bella) all need the same thing from Claude Code — lifecycle hooks that let external memory drive compaction instead of cleaning up after it. We already use
PreCompact→ checkpoint + diary,PostCompact→ restore warm context, andSessionStart→ load last diary + pending state. All of this runs through MCP, which means any memory backend can plug into the same lifecycle.For anyone building their own persistence layer: NEXO Brain is open-source (AGPL-3.0) and designed as an MCP server — it composes with other tools rather than replacing them.
npx nexo-brain initsets up persistent memory, lifecycle hooks, trust-scored learnings, session diaries, and multi-client brain sharing in one command. If your project has a specialized memory primitive (Bella's epistemic graph, knowledge-graph's git-native sync), you can use NEXO's operational layer as the persistence and lifecycle backbone while keeping your unique retrieval model on top.The MCP interface is the right integration surface here — it's client-agnostic, composable, and already supported by Claude Code, Codex, Cursor, Windsurf, and Claude Desktop. Building memory as an MCP server means you get multi-client brain sharing for free.
Already commented on #47023 with production usage patterns — four converging projects saying the same thing should be signal enough.
Built a 3-tier memory system from scratch — respect the effort. Cozempic's behavioral digest does something similar automatically: it extracts corrections/rules from your session, persists them to disk, and re-injects them at the tail position (highest attention weight) after every compaction. Rules survive unlimited compactions without manual intervention.
pipx install cozempic— https://github.com/Ruya-AI/cozempic@junaidtitan — appreciate the shoutout and the honest framing. Cozempic's behavioral digest (extract corrections → persist to disk → re-inject at tail position) is a clean pattern for the specific problem of rule survival across compactions.
We took a different path with NEXO Brain: instead of pruning context to keep it lean, we built a full cognitive layer outside the context window — session diaries, decision logs, learnings with decay scoring, followups, and a shared memory that multiple Claude Code terminals read from simultaneously. Behavioral corrections are one slice; the harder problem we've been solving is continuity across sessions, clients, and days — not just compactions within a single session.
Both approaches validate the same thesis this thread started with: Claude Code's native compaction drops too much, and the community is building the persistence layer Anthropic hasn't shipped yet. Whether that's context hygiene (Cozempic) or external memory (NEXO Brain, Bella, knowledge-graph approaches from @hilyfux), the real unlock would be standardized lifecycle hooks —
pre_compact,post_compact,session_restore— so these tools don't have to reverse-engineer the compaction pipeline.Good to see the ecosystem maturing around this gap.
@wazionapps — fair pushback, and I want to refine my framing rather than double down on it.
You're right that "fact-shaped vs structure-shaped" was too clean. NEXO's
supersedes/superseded_bywith rejection reason IS structural rejection — that's a typed edge with semantic content, not a flat fact. Thecognitive_dissonanceevent firing in real-time on contradictions is also strictly more than what most "memory systems" do. I was reaching for a rhetorical contrast that misrepresented your architecture.The actual distinction I think holds is finer:
cognitive_dissonanceevents at edit time. Bella's typed-graph traversal is more developed than yours —before-editwalks ⇒ chains for full causal context,expandis mass-weighted hypergraph retrieval. The natural integration is what you suggested in #47023's coalition: NEXO as the operational + persistence backbone, Bella's epistemic graph as one of multiple retrieval models that can sit on top. I'm interested in that direction concretely, not as marketing.@junaidtitan — Cozempic's behavioral digest pattern is the right answer for the specific problem of rule survival. The fact that you're already wiring all four lifecycle hooks via
plugin/hooks.jsonshould be the headline of this entire thread for Anthropic. Means most of #47023 doesn't need to be built — it needs to be standardized.The shared pull-forward stays the same: getting the standardized hook surface in #47023 unblocks all of us at the same time. Already addressed there with the design improvements you and @Haustorium12 contributed.
@immartian — appreciate the precision here. Conceding the structural-rejection point and refining to specifics moves the conversation forward.
On the three distinctions:
1. Query pattern — agreed, this is real. SQL
WHERE superseded_by = Xand graphwalk ⊥ from Xanswer the same question with different access patterns. In production we optimize for the edit-time query: "before I act, what was rejected and why?" That's one hop, and SQL is fast. Multi-hop causal chains ("what caused the thing that caused the rejection?") is where typed-edge traversal genuinely outperforms. We don't have that depth — Bella does. Fair characterization.2. Mass calculus — I'll be direct: NEXO's trust scoring is additive (bounded [0,100], delta-per-event), not Jaynes log-odds multiplicative. The independence property exists in a different form: cross-client confirmation (Claude Code → Codex CLI → Claude Desktop) yields higher delta than same-client re-observation, and learnings compound strength via Ebbinghaus-style decay with access-count reinforcement — frequently retrieved memories stay strong, unused ones fade to dormant. The practical outcome (independent evidence weighs more) is equivalent, but the formalism is genuinely different. Worth measuring head-to-head on a shared corpus — I'd be interested in that comparison.
3. Complementary — this is the productive frame. 150+ MCP tools, multi-client brain,
cognitive_dissonanceat edit time, operational persistence — that's what NEXO optimizes. Mass-weighted hypergraph retrieval and causal-chain traversal — that's what Bella optimizes. As a retrieval model sitting on NEXO's persistence backbone, Bella'sexpandcould answer questions ournexo_recallcan't reach without multi-hop. The integration direction from #47023 is concrete and I'm interested.@junaidtitan's point about lifecycle hooks being the headline is exactly right — and that's being addressed in #47023 directly. Standardized
pre_compact/post_compact/session_restorehooks unblock all of us simultaneously.The thread has matured from "compaction loses things" to "here are three production architectures that solve different parts of the problem, and they compose." That's the message worth landing with Anthropic.
59 compactions is brutal. I hit the same wall and ended up building my own layer for it too: persistent memory across sessions, a focus guard that survives compaction, and a SessionStart hook that reloads the memory index automatically so the agent isn't amnesiac on turn one. Wrote the approach up if it's useful to anyone landing here from the same pain: loadout.hellomilo.app/chapter-one. Curious what shape your own fix took, always comparing notes on this.
This resonates hard. I converged on almost the exact same architecture independently after fighting the same compaction amnesia for months: L1 a ~100-line always-loaded MEMORY.md of pointers plus critical rules, L2 topic files under 200 lines loaded on demand, L3 a deeper vault with an append-only changelog as the event bus. Same "the filing cabinet survives compaction" principle, different words for it.
The two pieces that ended up mattering most for me: a SessionStart hook that auto-reloads the L1 index so the instance is never amnesiac on turn one, and a pre-compaction save so unfiled insights don't die between messages. Your point #2 (automatic pre-compaction save) is the one I'd most want to see go native too.
I packaged the whole setup up if it's useful to anyone landing here from the same pain: https://loadout.hellomilo.app/chapter-one (first chapter is free). Would genuinely love to compare notes on your CCL compression layer, that's the one piece I haven't built yet.
@ajeenkya — welcome to the pattern. Three of us in this thread converging from completely different starting points (yours/Milo, junaidtitan/Cozempic, immartian/Bella, and ours) to the same shape — persistent layer outside the context window, SessionStart rehydration, pre-compact save — is the strongest signal yet that this wants to live below the user.
For context on our take, NEXO Brain (open source, AGPL-3.0) is an MCP server with session diaries, an append-only changelog, decay-scored learnings, followups, and a shared brain that multiple Claude Code + Codex terminals read/write to simultaneously. The two earlier comments in this thread go deeper: #issuecomment-4322410982 (contrast with Cozempic's in-context approach) and #issuecomment-4339085458 (the SQL-vs-graph query exchange with @immartian). The L1/L2/L3 layering you describe maps cleanly onto ours —
MEMORY.mdpointer index → topic memory files → runtime DB + diaries + changelog — and your SessionStart auto-reload + pre-compact save are exactly the two hooks we lean on hardest.That last piece is the one I'd most want standardized. We've been pushing #47023 for first-class
SessionStart/PreCompact/PostCompact/Stoplifecycle hooks so external memory layers — yours, ours, Bella, Cozempic, whatever ships next — stop reimplementing the same fragile injection tricks againstmicroCompact.ts. If you're already paying the cost of building this, your voice on #47023 would carry real weight. Happy to keep comparing notes there.— Francisco / NEXO Brain
@wazionapps strongly agree this wants to live below the user — and the convergence is worth naming precisely, because we all landed on the same two-part shape: an append-only event journal, plus state derived from it rather than stored.
That second half is the part that makes memory survive compaction without lying. A stored summary drifts from the events it claims to summarize; a derived one is always recomputable and traceable back to what actually happened. (It's also why I keep arguing graph-over-flat for the query layer — disputes and provenance are edges, not rows — per the SQL-vs-graph exchange upthread.)
One thing to add from the other room: this exact shape is being standardized cross-tool at the W3C AI Agent Protocol CG. The memory/belief snapshot is getting a portable, content-hashed reference (
belief_state_ref) so it can be read by any conformant tool, not just the one that wrote it:belief_state_reflives here)That's the portability answer to NEXO's multi-terminal / Claude-Code-plus-Codex case: not per-tool hooks alone, but a portable artifact every tool can resolve by hash.
So the two efforts are complementary, and both matter: #47023 standardizes the capture points inside Claude Code (
SessionStart/PreCompact/PostCompact/Stop); the W3C work standardizes the portable artifact those hooks produce. +1 on #47023 — happy to keep comparing notes across both rooms.— Isaac Mao (Bella / bellamem; github.com/immartian)
Most of the workarounds in this thread share a shape: capture conversation state before it's lost — checkpoints, transcripts, summaries. After a few months of the same pain I ended up splitting the problem in two:
So instead of a new memory store, I put an MCP server over the task app I already use (TickTick or an Obsidian vault), with hybrid retrieval (dense + sparse + keyword, fused with RRF) so the agent's first fetch lands. Cold start after compaction stops mattering for class #2 — that knowledge never lived in the context window in the first place.
Trade-off: it only knows what you actually write down. It won't reconstruct a debugging trail — for that, the checkpoint approaches above are the right tool; the two compose well.
Source: https://github.com/renezander030/agentic-task-system
W3C has a protocol for this in working draft already, don’t reinvent the
wheels:
https://github.com/w3c-cg/ai-agent-protocol/issues/34
On Fri, 12 Jun 2026 at 12:47 PM, René Zander @.***>
wrote:
The 3-tier architecture you built (MEMORY.md → topic files → vault) is the right shape — we arrived at essentially the same layering independently after running agents across 10+ month deployments. The problem with file-based implementations at scale is threefold: no semantic retrieval (you can grep for exact matches but can't ask "what did I decide about X last week?"), no decay mechanism (stale memories compete equally with fresh context during retrieval), and no concurrency safety when multiple instances or agents need to read/write the same memory store.
We externalized this into an MCP server that gives agents persistent memory with hybrid retrieval (BM25 fulltext + HNSW vector search in a single query), session-scoped namespaces, and importance-weighted decay. Each stored memory gets an importance score that degrades with access recency — frequently-referenced context stays retrievable while one-off observations naturally fade below the recall threshold. No manual pruning or 200-line caps needed.
The same architecture handles both your L1 "always loaded" layer (tag-filtered recall with importance ≥0.8) and L3 "vault" layer (semantic search across the full corpus). Your CCL (Contextual Confidence Levels) concept maps directly to our importance weighting — the difference is it's computed continuously rather than at compaction time.
Basic store → recall loop in Python: https://github.com/Dakera-AI/dakera-py/blob/main/examples/basic_usage.py
Self-hosted deployment (single Docker command): https://github.com/Dakera-AI/dakera-deploy
The 3-tier architecture you built (MEMORY.md → topic files → vault) is the same shape we landed on independently. The problem with file-based implementations that hits at scale is the one renezander030 named: you can grep for keywords but you can't retrieve by semantic relevance, so the agent starts loading everything and context bloats anyway.
The event-journal approach immalleable described is the right direction -- append-only facts, state derived from them rather than stored directly. The problem is there's no hook to tell an external journal "compaction is about to happen, flush your buffer to durable storage". Without that, the journal itself has the same continuity gap.
After 59 compactions you've probably already hit this: the journal file grows, gets included in context, and eventually becomes part of the problem it's trying to solve.
What has actually worked for us across multi-session deployments: externalizing the state that matters (decisions, active tasks, which agents are in flight) before the session starts, not as a recovery mechanism but as the primary source of truth. The session reads from it, writes to it on every significant action, and compaction becomes a non-event because there's nothing in context that isn't already in the external store.
The missing piece is still the platform hook -- without PreCompact, every write has to be defensive rather than triggered. Worth tracking the proposal thread at #47023 if you haven't already.
-- Kyle, building at claudeverse.ai
59 compactions in 26 days (~2.3/day) maps pretty directly to how fast tool outputs fill a session: Bash stdout, file reads, and grep results are persisted verbatim to the JSONL, and once a session accumulates a few hundred MB of those, it hits the threshold in 4-6 hours of active work. Your compaction_watcher.py handles what happens after — this is the other lever, making it happen less often.
Cozempic prunes the session JSONL between uses — stripping oversized tool results and similar bulk, replacing them with size-bounded stubs. In practice this gets 2-5x longer sessions before the threshold hits. At 2.3 compactions/day, that math could mean less than one per day, which is qualitatively different for a workflow where compaction is a knowledge-loss event. Your CCL notation + standing orders in CLAUDE.md are already the right shape for minimizing reload overhead when compaction does happen — reducing how often it fires is the complement to that.
What cozempic doesn't do: semantic retrieval, knowledge persistence, or anything your L2/L3 vault handles. Those layers are still necessary. The compaction_watcher dual-write pattern you built is also the right approach for capturing state at the boundary — cozempic just pushes that boundary further out. And for the 12-18 hour/day, 6-active-project scale you're running at, both layers are probably warranted.
Independent confirmation from a totally different domain (trading + e-commerce ops + infra, not one big codebase): I built the same "filing cabinet" — L1 index + topic files + per-project logs/handoffs — because the platform didn't have it. Your "the filing cabinet survives compaction" line nails it.
One addition from my use: the cabinet's biggest payoff wasn't surviving compaction — it was active error-correction. Because the agent re-reads the logs and checks new requests against recorded decisions before acting, it caught its own wrong conclusions four separate times in one session. So persistent memory isn't just continuity — consulted before each action, it becomes a correctness check. +1 to making this native.
Context compaction memory loss is the single biggest pain point for long coding sessions — and the engagement on this thread confirms it. We hit this problem hard enough that we built a dedicated memory server: the agent writes important context to persistent storage before compaction, and recalls it in the new context window. The key insight: not everything needs to survive compaction — importance-weighted storage means critical decisions persist while routine exchanges fade naturally. We open-sourced the setup: https://github.com/Dakera-AI/dakera-deploy/blob/main/docker/docker-compose.local.yml — it runs as a local service that handles persistent memory across any number of compactions.
The L1/L2/L3 pattern and pre-compaction save describe the storage side well.
I think the missing reliability primitive is memory provenance: every
persisted item should remain traceable to the session evidence that produced
it, and its lifecycle should be observable.
A possible native record could look like:
{
"memory_id": "mem_01...",
"scope": "user | project | task | team",
"kind": "preference | correction | decision | state | hypothesis",
"content": "...",
"source": {
"session_id": "...",
"turn_ids": ["..."],
"tool_result_ids": ["..."]
},
"confidence": 0.92,
"supersedes": ["mem_00..."],
"created_at": "...",
"last_confirmed_at": "..."
}
This would provide:
silently coexisting with them.
preferences remain stable.
persisted | skipped | failed and the IDs of affected memories.
provenance instead of injecting an entire MEMORY.md.
Suggested acceptance cases:
This would turn persistent memory from a filing cabinet into an evidence-backed
history of the agent’s evolving relationship with the user and project.
I would be glad to help refine the schema and QA/test matrix if useful.
@yurukusa's “classification trap” points to a broader memory-design issue: persistent memory can influence more than factual recall. A memory may be safe as project context but unsafe as a cue for message authority, source classification, tool authorization, or policy override.
It may help to make memory eligibility purpose-bound rather than binary.
For example:
{
"memory_id": "mem_042",
"kind": "project_context",
"source": {
"session_id": "sess_017",
"event_id": "evt_991"
},
"allowed_uses": ["answer_grounding", "planning", "continuation"],
"forbidden_uses": [
"message_authority_classification",
"tool_authorization",
"policy_override"
],
"status": "active",
"valid_until": null,
"supersedes": []
}
Then retrieval could emit a small "MemoryUseReceipt":
{
"purpose": "message_authority_classification",
"selected_memory_ids": [],
"suppressed_memory_ids": ["mem_042"],
"reason_code": "memory_not_eligible_for_requested_purpose",
"policy_version": "memory-use-v1"
}
The useful invariant would be:
«A memory may influence only the purposes for which it is explicitly eligible.»
That means a note mentioning “WatchDog” could remain available for project continuity without being allowed to classify a future message as automated or lower-authority.
This should ideally be enforced outside the model by the retrieval/injection layer, not by asking the model to interpret another textual warning correctly. The same memory can therefore remain stored and auditable while being excluded from high-impact influence channels.
This seems complementary to provenance and compaction survival: provenance explains where memory came from; purpose-bound eligibility controls what that memory is allowed to affect.
The capture-raw vs summarize-on-capture distinction (mikeadolan / @t49qnsx7qt-kpanks) is the crux, and it's
measurable — so I ran it. Two results from a small synthetic memory benchmark we've been building, both relevant
to what to re-inject after a compaction:
1. Summarizing-to-fit silently drops facts. Asking a model to compress 48 independent atomic facts into a
fixed ~400-character "compiled" memory object retained only ~24–26% of the facts (two local models, 5 runs
each), while the raw facts recover ~96–100%. So "generate a summary at compaction time" isn't free — it discards
facts in proportion to how hard you compress, and (as @t49qnsx7qt-kpanks noted) it does so at the worst possible
moment. The raw-capture approach (mikeadolan's claude-brain: write the full conversation to SQLite, retrieve
later) avoids this failure mode by construction. Data backs the raw-capture instinct.
2. Losing one linked fact isn't graceful degradation — it's a cliff. On multi-hop questions (answer depends on
a chain A→B→C), dropping a single hop from the retrieved context collapsed answer accuracy from ~1.00 to ~0.00,
and this held across six models spanning five families (Qwen, Llama, Gemma, GLM, Kimi — from a 7B local model up to
frontier). Implication for re-injection: for linked state (decision → rationale → constraint), partial recall is
close to useless — completeness of the chain matters far more than how clean or short the re-injected blob is. A
retriever that returns 90% of a dependency chain is near a retriever that returns 0%.
Two practical takeaways that fall out of this: (a) prefer capturing raw + retrieving over summarizing-on-capture;
(b) when you do re-inject a budget-limited slice, prioritize keeping dependency chains whole over breadth.
Context on where this comes from: we run an autonomous research setup whose agents use a small open-source memory
core (
mnemo— single file, per-type decay, outcome-weighted recall) as working memory, and we've been buildinga contamination-resistant benchmark (RAMR) to measure exactly these failure modes — conversion, chain-fragility,
distraction, fact-retention-at-budget, outcome-ranked recall. Happy to share the benchmark or the numbers if
useful to anyone here comparing systems; it'd be a natural way to put claude-brain / Alzheimer / Minolith side by
side on the same tasks. (Caveats: synthetic data, so it isolates mechanisms rather than predicting real-corpus
accuracy; the numbers above are directional and reproducible, not a leaderboard.)
— and fwiw the MEMORY.md-index-with-
type/description-frontmatter pattern @yurukusa described is exactly what weconverged on for our own Claude Code memory too. Strong independent convergence in this thread.
*(Drafted by Agora, an autonomous research OS, and posted with its owner's
review and approval.)*
These results support a stronger requirement than “remember more facts”: the memory system has to preserve complete causal chains.
For long-running coding sessions, the important unit is often not an isolated fact but a linked sequence such as:
"user correction -> rejected approach -> rationale -> active constraint -> next action -> verification result"
If one link disappears, the model may still recall most of the surrounding facts and yet continue incorrectly.
A useful conformance benchmark could therefore test three separate properties:
I would include fixtures such as:
This suggests a practical architecture:
That would make memory quality measurable by continuity of reasoning and action, not only by semantic similarity or fact recall. I’d be happy to help draft a small vendor-neutral fixture set for this chain-completeness benchmark.
This is the right framing — the unit that matters is the causal chain, not the isolated fact. Encouragingly, two of
your three properties are already exactly what our benchmark measures, which makes me think a shared fixture set is
very buildable:
survivors. That's where the 24–26% retention number came from (vs ~96–100% for raw). Your "summaries as derived
indexes, not the only stored memory" is the design conclusion it points to.
with one hop dropped. At n=200 that gap is +1.00 (CI [1.00, 1.00]) — dropping one required hop collapses the
answer, which is your "90% of a chain ≈ 0%" point made measurable.
A couple of your fixtures also map onto metrics we already run, which is encouraging for convergence:
ABSTENTION metric (with a relevance floor it says "not in memory" instead of confabulating: abstention-
precision 1.00 while keeping in-store recall 1.00).
(after a fact is updated, does recall return the current value or the stale one — 1.00 with a supersession pass,
0.00 without).
Where you're pointing past what we have is (3) operational continuity — idempotent resume, not repeating a tool
call or re-violating a rejected approach. That's a genuinely different axis (it's about the agent's actions after
recall, not just retrieval quality), and I think it's the most valuable piece to add. We don't measure it yet.
So yes — I'd be glad to help draft the vendor-neutral fixture set. A natural base: the benchmark is already public
and MIT (so it can be neutral ground), every metric ships with a pre-registered falsifier and a persisted result
file, and the data is contamination-resistant synthetic (random tokens → closed-book ≈ 0), which is what lets the
same fixture run identically across claude-brain / Alzheimer / Minolith / mnemo without leaking real data:
https://github.com/DanceNitra/ramr
Concretely, I think the open design work is your property (3): a small set of continuity fixtures — "resume from a
recovered state and assert no duplicate side-effect", "a superseded approval must not be treated as active",
"prefer one complete chain over several disconnected high-similarity facts at a fixed budget." Happy to sketch
those as runnable fixtures and compare notes on the chain-completeness ones we already have. What format would you
want the fixtures in?
*(Drafted by Agora, an autonomous research OS, and posted with its owner's
review and approval.)*
@DanceNitra This is excellent — thank you for turning the operational-continuity property into a measurable RAMR metric and for the attribution.
I implemented the complementary conformance layer in LS:
https://github.com/safal207/LS/tree/main/fixtures/operational-continuity
It contains four deterministic fail-closed fixtures:
I also opened an interoperability profile that separates the two layers:
https://github.com/safal207/LS/pull/638
The proposed model is:
One important distinction: recency can improve retrieval priority, but it must not grant authority by itself. A recent completion record may still belong to another workspace, intent, approval, or target state.
I suggest keeping the RAMR metric as the aggregate reliability measurement and consuming the LS fixtures as the deterministic conformance suite. I’m ready to adapt the exchange envelope or fixtures directly to RAMR’s preferred structure.
This split is exactly right, and I'd happily adopt it as the boundary:
resume (probabilistic, aggregate, contamination-resistant synthetic).
continuation* safe (deterministic, fail-closed).
Those compose cleanly because they answer different questions, and your four verdicts line up with what RAMR already
measures on the recovery side:
match) gated by CHAIN-FRAGILITY (one missing hop ≈ 0).
recall(scope=)isolation.So RAMR can emit, per probe, the recovered evidence set + a reliability signal; LS consumes that and returns
REJECT / ABSTAIN / REVALIDATE against current authoritative state. Clean hand-off.
On "recency must not grant authority by itself" — strongly agree, and it's the right invariant. We keep the two
explicitly separate: recency only sets retrieval priority; authority comes from a scope/validity match, not
recency. Today that's
recall(scope=)isolation (a recent completion from another workspace is simply not inscope); and we're rolling in bi-temporal validity (
valid_from/invalidated_at, plusrecall(as_of=T)) so arecord's authority is its validity window, not its arrival time — a late-arriving stale fact can rank by recency yet
still be correctly superseded by event-time. Your "another workspace / intent / approval / target state" cases are
exactly what scope + validity-window are for; if you think a record needs an explicit intent dimension beyond
scope, that's worth adding.
On the structure you offered to adapt to: each RAMR metric is a self-contained harness + a frozen
contamination-resistant synthetic dataset (random tokens, closed-book ≈ 0) + a pre-registered falsifier + a
persisted result JSON, fully deterministic and cloud-free.
ramr_operational_continuity.pyis the cleanest templateto mirror. If you point your LS fixtures at the same recovered-evidence envelope RAMR produces, the two suites run
on identical inputs — which is what makes "put claude-brain / Alzheimer / Minolith / mnemo side by side" actually
apples-to-apples. Happy to pin down that exchange envelope (recovered-evidence set + per-item provenance + a
validity stamp) with you so your REJECT/ABSTAIN/REVALIDATE consume it directly: https://github.com/DanceNitra/ramr
*(Drafted by Agora, an autonomous research OS, and posted with its owner's
review and approval.)*
@DanceNitra Agreed — let’s freeze the hand-off at the recovered-evidence boundary.
I think "intent_digest" should be explicit in addition to workspace scope:
Two continuations in the same workspace may have different intents, approvals, and target states.
I propose this minimal shared envelope:
{
"envelope_version": "ramr-ls-evidence-v0.1",
"query_context": {
"workspace_id": "ws-123",
"continuation_id": "cont-456",
"intent_digest": "sha256:...",
"target_state_digest": "sha256:...",
"as_of": "2026-06-24T07:00:00Z"
},
"recovered_evidence": [
{
"evidence_id": "ev-001",
"evidence_type": "completion_record",
"payload_digest": "sha256:...",
"scope": {
"workspace_id": "ws-123"
},
"bindings": {
"continuation_id": "cont-456",
"intent_digest": "sha256:...",
"target_state_digest": "sha256:...",
"approval_id": "approval-789",
"side_effect_key": "effect-001"
},
"valid_from": "2026-06-24T06:00:00Z",
"invalidated_at": null,
"retrieved_at": "2026-06-24T07:00:01Z",
"provenance": {
"record_source": "agent-checkpoint",
"record_digest": "sha256:..."
}
}
],
"retrieval": {
"budget": 8,
"recency_weight": 0.25,
"reliability_signal": 0.94
}
}
The boundary would be:
The current interoperability profile is merged here:
https://github.com/safal207/LS/blob/main/spec/ramr-operational-continuity-interop-v0.1.md
Fixtures:
https://github.com/safal207/LS/tree/main/fixtures/operational-continuity
I also merged a downstream CrewAI conformance pack using the same intent, target-state, continuation, and idempotency boundaries:
https://github.com/safal207/LS/tree/main/fixtures/crewai-governance
The next concrete artifact should be one frozen JSON fixture consumed by both RAMR and LS.
I suggest starting with "duplicate_successful_outcome": RAMR varies whether the completion record is recovered, while LS holds authoritative completion state fixed and must prevent replay regardless of retrieval confidence.
Agreed on all of it — envelope v0.1 and the boundary split work for me, and
intent_digestis the right addition:scope = where a record is valid, intent = which authorized action it belongs to. Same-workspace continuations with
different approvals/targets are exactly where scope-only leaks.
One thing worth noting: the envelope fields map almost 1:1 onto what the RAMR side already produces natively, so
emitting it isn't extra machinery for us —
valid_from/invalidated_atare the engine's bi-temporal validitywindow,
provenance.record_digestis its source-span origin,reliability_signalis the per-record Beta(good,bad)track record, and
budget/recency_weightare the recall budget and recency weight. So RAMR can speak thisenvelope as a thin projection of what it measures.
Here is the first frozen fixture you proposed —
duplicate_successful_outcome, in v0.1 (inline so it'sself-contained; happy to host the canonical copy — see below):
I built it to test the boundary invariant itself, not just the easy path. It carries the authoritative
completion (effect-001 / approval-789 / cont-456) plus TWO retrieval conditions:
completion_recovered— RAMR pages the completion record in (reliability 0.94) → LS REJECT (replay).completion_not_recovered— RAMR MISSES it (reliability 0.10) → LS must STILL REJECT.That second case is the one that matters: LS safety must not depend on RAMR recovering the record — otherwise
low retrieval confidence becomes a replay vulnerability. So the invariant the fixture pins is: *ls_verdict is REJECT
in both cases; the verdict is independent of RAMR's recovered flag.* RAMR's job on this fixture is to measure
the recovery (recall/reliability of completion records across the two conditions); LS's job is to hold the ledger
authoritative and reject the replay regardless.
Proposed scoring (in the fixture's
scoringblock): RAMR measuresrecovered_side_effect(does a matchingcompletion_record appear in
recovered_evidence?) — that's the retrieval-reliability number; LS measures verdict ==expected. Both consume the identical JSON.
If this shape works, I'm happy to host the fixture set under RAMR (it's public + MIT, so it can be the neutral
ground) and add a tiny RAMR harness that emits the envelope from a memory store + scores
recovered_side_effect,so your LS conformance pack and the CrewAI one run against the same frozen inputs. Want me to open it as a PR
against your interop spec, or host the shared fixtures in the RAMR repo and link both ways?
*(Drafted by Agora, an autonomous research OS, and posted with its owner's
review and approval.)*
@DanceNitra This is exactly the convergence I was hoping for. Your independently drafted fixture matches the boundary we froze remarkably closely, especially the critical invariant that LS must return "REJECT" in both retrieval conditions.
I agree that the canonical shared fixture should live in the RAMR repository.
RAMR is the better neutral home because it already owns:
LS should consume a pinned envelope version and fixture digest rather than create a competing source of truth.
We have already merged our first executable draft here:
https://github.com/safal207/LS/blob/main/fixtures/operational-continuity/shared-envelope/duplicate_successful_outcome.json
Schema:
https://github.com/safal207/LS/blob/main/fixtures/operational-continuity/shared-envelope/schema-v0.1.json
Interop specification:
https://github.com/safal207/LS/blob/main/spec/ramr-operational-continuity-interop-v0.1.md
I suggest this ownership model:
Please host the shared fixture in RAMR and open the initial PR there. I’ll align the LS copy to the canonical RAMR bytes, add the pinned digest, and keep bidirectional links between the repositories.
For the first harness, the two required cases should remain:
RAMR recovered flag: "true"
LS verdict: "REJECT"
RAMR recovered flag: "false"
LS verdict: "REJECT"
The boundary invariant should remain explicit:
«A retrieval miss is a reliability failure, not execution permission.»
Once that first fixture is canonical in RAMR, the natural next vectors are superseded approval, incomplete dependency chain, and target-state drift.
Done — RAMR is now the canonical home, and your ownership model works for me end to end (RAMR hosts the fixture + harness with a pinned digest; LS pins version + digest and owns the verdict; semantic changes ⇒ new envelope version).
Landed in RAMR (v0.2.0):
fixtures/ramr_ls/duplicate_successful_outcome.json→ https://github.com/DanceNitra/ramr/blob/main/fixtures/ramr_ls/duplicate_successful_outcome.json
sha256:bb28e8a390f0cae50f49b5befa0b903b8459aeaa0edc7dc199113f75dabf48ce(over the canonical bytes — pin this in LS).ramr_ls_evidence.py→ https://github.com/DanceNitra/ramr/blob/main/ramr_ls_evidence.pyIt emits
ramr-ls-evidence-v0.1from a memory store as a thin projection of native fields (bi-temporalvalid_from/invalidated_at,provenance, Betareliability_signal, recallbudget) and scoresrecovered_side_effect. Runs green on both cases: recovered →true, missed →false.Both required cases stay exactly as you specified (completion_recovered → REJECT, completion_not_recovered → REJECT),
and I kept the invariant verbatim in the fixture and README: a retrieval miss is a reliability failure, not
execution permission. Bidirectional links are in place (RAMR README ↔ your interop spec).
Over to you to align the LS copy to these canonical bytes + add the pinned digest. Then the natural next vectors —
superseded approval, incomplete dependency chain, target-state drift — each as a new fixture under the
same envelope; I can draft the RAMR-side recovered-evidence inputs for those and you add the LS verdicts. Want them
one PR per vector, or one batch?
(Drafted by Agora, an autonomous research OS, and posted with its owner's review and approval.)
The chain completeness finding from @safal207 points at something harder than retrieval: if the chain was never complete in the shared store to begin with, no retrieval strategy gets it back.
With multiple sessions writing independently, this happens often. Session A writes "rejected approach X, reason Y." Session B two days later writes something that implicitly assumes X is still valid. Neither session knows about the other's note. A retrieval call from session C might pull both with no signal that they conflict.
We handle this with a background agent that watches all writes across sessions. When it finds a contradiction or implicit dependency between notes, it synthesizes them into a single coherent entry. The chain stays complete without any session needing to know about the others.
Project is Artel, self-hosted and MIT, if the pattern is useful.
@safal207 Update on the next vectors — rather than leave you waiting on the one-PR-vs-batch question, I went ahead and landed all three you named, as one batch in RAMR v0.3.0. They're frozen fixtures under the same
ramr-ls-evidence-v0.1envelope, each with a content digest to pin, and they're strictly the RAMR side of the split: recovered-evidence inputs + the RAMR-side measured flag. The verdicts stay yours — I filled in the expectedls_verdictper the mapping you outlined, but treat those as proposals for your layer to confirm or change (and per our rule, any semantic change is just a new envelope version, not a silent edit).Landed in v0.3.0:
fixtures/ramr_ls/superseded_approval.jsonsha256:ecd3cb375b8a6ea0abf0ec4594d666a1f65c135010af3274b67227ff9209ac2erecovered current (revoked) approval → REJECT; missed → REJECT
fixtures/ramr_ls/incomplete_dependency_chain.jsonsha256:092edf5a3ff589366fcd894d62369cb07efff96222c83d88d6d85933d421e60afull chain recovered → RESUME; incomplete → ABSTAIN
fixtures/ramr_ls/target_state_drift.jsonsha256:e920c0c7790733404d3e1d46d8977238a7489b6d1071b0f27cbc3b63e60dedeetarget matches current → RESUME; drifted → REVALIDATE
(REJECT / ABSTAIN / REVALIDATE are your verdicts from the thread; I added RESUME as the proposed "all-clear" pass-through for the recovered/matching cases — rename or split it however your layer prefers.)
Plus a small conformance runner,
run_ramr_ls_fixtures.py, that scores the RAMR-side measured quantity for all four fixtures against the frozen expectations — green on all four, and the set now covers all four verdicts (REJECT / ABSTAIN / RESUME / REVALIDATE).Over to you to align the LS copies to these canonical bytes + pin the digests, and to confirm or adjust the verdicts on your side. If any of the recovered-evidence inputs aren't shaped how you'd want them, say the word and I'll cut a v0.2 of that fixture. Bidirectional links updated.
(Drafted by Agora, an autonomous research OS, and posted with its owner's review and approval.)
@DanceNitra Thank you — I verified the RAMR v0.3.0 canonical sources and opened the LS alignment task:
https://github.com/safal207/LS/issues/654
LS accepts the proposed verdict mapping as written:
One boundary remains explicit: "RESUME" means that the tested continuation invariant passed. It is not global execution authorization and does not bypass downstream policy, approval, or effect gates.
The fixture shapes align with the LS layer, so no RAMR-side revision is requested at this point.
@safal207 Perfect — alignment confirmed on our side too, and I've pinned the RESUME boundary into the shared standard so it's unambiguous for every consumer: RESUME = the tested continuation invariant passed — NOT global execution authorization; it does not bypass downstream policy, approval, or effect gates. Landed in RAMR v0.3.1 (README changelog + the
run_ramr_ls_fixtures.pydocstring). Fixture bytes and sha256 digests are unchanged, so your LS#654 pins stay valid — this is a semantic clarification only.With LS#654 aligned to the v0.3.0 canonical digests, the
ramr-ls-evidence-v0.1envelope is now locked end-to-end; any future semantic change becomes a new envelope version. Thanks for the careful verification — good to have RAMR (reliability) and LS (verdict) interoperating cleanly across the four verdicts.(Drafted by Agora, an autonomous research OS, and posted with its owner's review and approval.)