danielmiessler / danielmiessler/LifeOS

MemoryTurnStart sends the whole hot layer as one hook output; once memory fills, Claude Code cuts it to a 2KB preview and most memory never reaches the model

Open
#2,103 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
19k
Forks
2.5k
Avg merge
8d 17h
Merged PRs (30d)
1

Description

**Version**

LifeOS v7.40.4 (latest release). Claude Code 2.1.268.

**What is broken**

`MemoryTurnStart` writes both hot-layer files (`PRINCIPAL_MEMORY.md`, `DA_MEMORY.md`) to stdout as a single UserPromptSubmit output on a session's first prompt, on any memory change, and every 20 prompts. At the stock caps (48 entries × 256 chars per file) that output can reach about 24.6K characters. Claude Code saves an oversized hook output to a file and puts only a `Preview (first 2KB)` plus the file path into the model's context. So on those turns the model sees the first several principal entries and none of the DA entries. The 🧠 delta line and the `` block are written after the memory dump, so they are cut too. Nothing errors, so the loss is silent. It stays invisible until memory fills, which may be why it hasn't been reported: a new install's memory is small.

**Where (file:line)**

- `LifeOS/install/hooks/MemoryTurnStart.hook.ts:109-111`: `if (shouldInject(sessionId)) { const memory = loadMemory(); if (memory) process.stdout.write(memory); }` runs before the delta (`:113-114`) and ground (`:119-128`) writes.
- `LifeOS/install/hooks/LoadMemory.hook.ts:54-71`: renders both full files into one block; the caps allow ~12,288 chars each.
- The header comment in `MemoryTurnStart` (`:42`) sizes the block at "~1.5K tokens"; the caps allow roughly four times that.

**Repro on a clean tree**

1. Fresh v7.40.4 install. Fill each hot-layer file with 48 entries of about 200 characters each (any content, correct prefixes).
2. Start a new `claude` session and send any prompt.
3. The UserPromptSubmit result for MemoryTurnStart reads `Output too large (≈20KB). Full output saved to: … Preview (first 2KB)`.
4. Ask the model, with no tools allowed, to quote the last entry of `DA_MEMORY.md`. It can't; that entry was never in context.

**Negative control**

Trim both files to about 8 entries each (about 3KB total) and repeat. The output arrives inline, with no "Output too large", and the model can quote the last DA entry. On our install, outputs around 2-3KB always arrived inline, and a 10.1KB output spilled. So the threshold sits somewhere near 10K. We don't know it exactly, and we didn't find it documented.

**Suggested fix (shape; tested on a modified install, not on a clean tree)**

- Minimum: write the delta and ground blocks BEFORE the memory dump, so a cut can only take the tail, and warn when the output exceeds a budget instead of failing silently.
- What we run: `@`-import both memory files from `CLAUDE.md` (the same way the identity files load: no size cutoff, prompt-cached). The hook stops dumping; it snapshots entries on the first prompt and then sends only entries added or retired since the last send. If the imports are missing, it falls back to the stock dump.
- Caveat for that approach: Claude Code loads `CLAUDE.md` and its imports into custom and general-purpose subagents (only Explore and Plan skip it), so hot memory then reaches every such agent. We moved money and medical detail out of hot memory before switching, and added a curator rule against putting it back.

**Related:** #2075 (the subagent-detection bug) makes the memory hook skip itself on many installs, which would also hide this one.

- [x] Searched open and closed issues.
- [ ] Repro run against a clean tree. NOT YET: ours is a modified install; the repro steps above are written to be run on a clean one.
- [x] Personal data removed.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the clean-tree reproduction in LifeOS/install/hooks/MemoryTurnStart.hook.ts, especially lines 109-128, and inspect how LifeOS/install/hooks/LoadMemory.hook.ts lines 54-71 renders both files. Verify the output-size behavior before choosing between ordering, budgeting, or CLAUDE.md imports. Done means hot memory, delta, and ground information reach the model without silent truncation, with behavior covered for full and small memories.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
ai, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.