-
Notifications
You must be signed in to change notification settings - Fork 3k
fix(core): preserve managed memory during microcompaction #6714
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
wenshao
merged 4 commits into
QwenLM:main
from
yiliang114:codex/6487-preserve-memory-read
Jul 11, 2026
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
f7122c0
fix(core): preserve managed memory during microcompaction
yiliang114 f8f2aca
Merge branch 'main' into codex/6487-preserve-memory-read
wenshao 06862d0
Merge branch 'main' into codex/6487-preserve-memory-read
yiliang114 96a51bd
test(core): cover managed memory read errors
yiliang114 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # Managed Memory Microcompaction Preservation | ||
|
|
||
| ## Problem | ||
|
|
||
| Managed-memory topic files are loaded lazily with `read_file`. Microcompaction currently treats those results like ordinary tool output and replaces older content with `[Old tool result content cleared]`. The memory index remains available, and recent fixes let a later `read_file` return real bytes again, but the active model is not guaranteed to notice that it must reload the memory. | ||
|
|
||
| Issue #6487 also reports a stale index after `/remember`; PR #6497 already owns that part. This design only addresses managed-memory content removed by microcompaction. | ||
|
|
||
| ## Chosen design | ||
|
|
||
| Add a narrow `MicrocompactOptions` callback that identifies `read_file` paths whose successful results must be preserved. Before building idle, forced, or size-based clearing plans, microcompaction correlates each response with its request-side `file_path` and removes protected results from the compactable set. Other tools, ordinary file reads, errors, and responses whose path cannot be resolved retain the current behavior. | ||
|
|
||
| Every production microcompaction entry point supplies the same predicate: | ||
|
|
||
| - pre-send idle and size-based compaction | ||
| - `/compress-fast` | ||
| - memory-pressure history compaction | ||
|
|
||
| The predicate recognizes project, user, and team managed-memory roots using realpath-aware containment. Symlinks that escape a managed root are not protected. | ||
|
|
||
| ## Why this level | ||
|
|
||
| Injecting every loaded memory body into the system instruction would make memory permanently consume context and would replace the existing index-plus-lazy-read design. Reattaching every memory file after full compaction needs a separate token budget and restoration policy. Preserving only managed-memory reads from microcompaction directly fixes the reproduced clearing behavior with a bounded change and leaves full compaction as the existing hard context-reduction boundary. | ||
|
|
||
| Full compaction is therefore intentionally not byte-preserving. Its summary sees the pre-compaction memory content, `MEMORY.md` indexes remain in the system instruction, and the file-read cache is cleared so the model can reload exact bytes. This change guarantees preservation only across microcompaction. | ||
|
|
||
| ## Risk and tests | ||
|
|
||
| Repeated reads of managed-memory files can retain multiple copies until full compaction. That is an intentional tradeoff: durable guidance is more important than reclaiming those tool-result tokens, while full compaction remains available as the hard cap. | ||
|
|
||
| Tests cover project, user, and team roots; ordinary reads; symlink escapes; idle, forced, and size-based paths; mixed protected and compactable results; ambiguous or missing response IDs; and eviction metadata. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| # Managed Memory Microcompaction Implementation Plan | ||
|
|
||
| > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. | ||
|
|
||
| **Goal:** Keep successful managed-memory `read_file` results available across every microcompaction trigger without changing ordinary tool-result compaction. | ||
|
|
||
| **Architecture:** A realpath-safe memory-path helper classifies project, user, and team memory. Microcompaction receives a pure preservation predicate, correlates response IDs to request paths, and excludes protected reads before calculating clear plans and metadata. The three production callers pass the same predicate. | ||
|
|
||
| **Tech Stack:** TypeScript, Vitest, Node.js filesystem/path APIs. | ||
|
|
||
| ### Task 1: Specify preservation behavior | ||
|
|
||
| **Files:** | ||
|
|
||
| - Modify: `packages/core/src/services/microcompaction/microcompact.test.ts` | ||
|
|
||
| 1. Add helpers that build paired `read_file` calls/results with IDs and paths. | ||
| 2. Add failing tests for idle/force and size-only preservation, ordinary reads, mixed/ambiguous IDs, and eviction metadata. | ||
| 3. Run `cd packages/core && npx vitest run src/services/microcompaction/microcompact.test.ts` and confirm the new assertions fail because the option is ignored. | ||
|
|
||
| ### Task 2: Add safe memory path classification | ||
|
|
||
| **Files:** | ||
|
|
||
| - Modify: `packages/core/src/memory/paths.ts` | ||
| - Modify: `packages/core/src/memory/team-paths.test.ts` | ||
|
|
||
| 1. Add failing tests for project, user, team, outside, and symlink-escape paths. | ||
| 2. Add a read/retention-specific helper that resolves the nearest existing real path and checks all three managed roots without changing write-approval semantics. | ||
| 3. Run the path tests and confirm they pass. | ||
|
|
||
| ### Task 3: Exclude protected reads from clear plans | ||
|
|
||
| **Files:** | ||
|
|
||
| - Modify: `packages/core/src/services/microcompaction/microcompact.ts` | ||
|
|
||
| 1. Extend `MicrocompactOptions` with the preservation predicate. | ||
| 2. Correlate `functionResponse.id` to request-side `read_file` paths. | ||
| 3. Exclude a result only when its path mapping is unambiguous and every candidate path is protected. | ||
| 4. Apply the filtered tool-reference set before idle/force and size-based planning so token counts and eviction metadata stay accurate. | ||
| 5. Run the focused microcompaction tests and confirm they pass. | ||
|
|
||
| ### Task 4: Wire every production caller | ||
|
|
||
| **Files:** | ||
|
|
||
| - Modify: `packages/core/src/core/client.ts` | ||
| - Modify: `packages/core/src/core/geminiChat.ts` | ||
| - Modify: `packages/core/src/services/memoryPressureMonitor.ts` | ||
| - Test: corresponding focused test files | ||
|
|
||
| 1. Resolve relative paths against the configured target directory. | ||
| 2. Pass the same managed-memory predicate through pre-send idle/size, `/compress-fast`, and memory-pressure compaction. | ||
| 3. Add or update focused caller tests that verify the option reaches microcompaction. | ||
| 4. Run all affected focused tests. | ||
|
|
||
| ### Task 5: Verify and review | ||
|
|
||
| **Files:** | ||
|
|
||
| - Review all changed files. | ||
|
|
||
| 1. Run Prettier on changed files. | ||
| 2. Run focused tests for microcompaction, path classification, client, GeminiChat, and memory-pressure behavior. | ||
| 3. Run `npm run build && npm run typecheck` from the worktree root. | ||
| 4. Run an independent code review, fix important findings, and repeat focused verification. | ||
| 5. Re-run the original E2E reproduction against `node dist/cli.js` after a fresh bundle. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.