codex - 💡(How to fix) Fix Memory read path ignores cwd and injects entire global memory_summary.md into initial context for new sessions [2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openai/codex#17496Fetched 2026-04-12 13:27:39
View on GitHub
Comments
2
Participants
3
Timeline
13
Reactions
0
Author
Timeline (top)
labeled ×5unlabeled ×3commented ×2renamed ×2

Root Cause

A few related design tensions surfaced while tracing this locally:

  • Phase 2 reads all memories_extensions/*/instructions.md files in the consolidation prompt in codex-rs/core/src/memories/prompts.rs:55, so multiple extensions currently influence one shared memory_summary.md.
  • Because the runtime injects one global summary into fresh initial context, those extensions indirectly compete for a single prompt budget over time.
  • This makes instructions.md a mitigation for summary quality, but not a real fix for retrieval/injection scope.

Fix Action

Fix / Workaround

A few related design tensions surfaced while tracing this locally:

  • Phase 2 reads all memories_extensions/*/instructions.md files in the consolidation prompt in codex-rs/core/src/memories/prompts.rs:55, so multiple extensions currently influence one shared memory_summary.md.
  • Because the runtime injects one global summary into fresh initial context, those extensions indirectly compete for a single prompt budget over time.
  • This makes instructions.md a mitigation for summary quality, but not a real fix for retrieval/injection scope.
RAW_BUFFERClick to expand / collapse

What issue are you seeing?

Codex's memory write path is cwd-aware, but the memory read/injection path is not.

Today, phase 2 consolidation explicitly preserves cwd/project boundaries in the memory artifacts:

  • MEMORY.md blocks require applies_to: cwd=... in the schema in codex-rs/core/templates/memories/consolidation.md:197
  • the consolidation instructions say to separate similar tasks across different cwd contexts by default in codex-rs/core/templates/memories/consolidation.md:293
  • the summary/index is organized first by cwd/project scope in codex-rs/core/templates/memories/consolidation.md:546

However, when Codex builds the initial context for a fresh conversation / baseline, the runtime prompt injection path reads and injects the entire global ~/.codex/memories/memory_summary.md without any cwd/project filtering:

  • the initial context builder appends the memory developer prompt in codex-rs/core/src/codex.rs:3764
  • build_memory_tool_developer_instructions(...) reads the whole memory_summary.md in codex-rs/core/src/memories/prompts.rs:234
  • the read prompt injects {{ memory_summary }} wholesale in codex-rs/core/templates/memories/read_path.md:124
  • the full initial context is used when reference_context_item.is_none() in codex-rs/core/src/codex.rs:3928

Steady-state turns appear to use the settings-diff path instead of rebuilding the full initial context, so this is specifically an initial-context / new-conversation boundary issue rather than a claim that the full memory summary is re-injected on every turn.

This still creates a real failure mode for multi-repo users: a fresh session in one repo gets irrelevant memory from other repos injected into context before the model starts working. That is both noisy and architecturally inconsistent with the cwd-aware write/consolidation design.

Concretely, I have a generated memory_summary.md that contains both /Users/georgepickett/polyscraper and unrelated /Users/georgepickett/explore-computer sections. A fresh polyscraper session would get both injected, even though only the polyscraper section is relevant.

This also makes multiple memories_extensions/*/instructions.md files indirectly compete over one shared global summary: phase 2 reads all extension instructions and rewrites one global memory_summary.md, but the runtime still injects that single shared summary into fresh initial context everywhere.

Why this matters:

  • irrelevant context can bias the model toward the wrong workflow
  • unrelated memory competes for the limited injected summary budget
  • the injected summary is truncated to 5,000 tokens in codex-rs/core/src/memories/mod.rs:46, so unrelated repo memory can crowd out the repo that actually matters
  • the system is storing project boundaries in the data model but not respecting them in retrieval/injection

What steps can reproduce the bug?

  1. Enable memories and allow the startup memory pipeline to run. The startup trigger is in codex-rs/core/src/memories/start.rs:14.
  2. Use Codex across at least two distinct repos/cwds so phase 1 and phase 2 build cross-project memory.
  3. Let phase 2 consolidate those memories into a shared ~/.codex/memories/memory_summary.md. Phase 2's global consolidation pass is in codex-rs/core/src/memories/phase2.rs:80.
  4. Confirm that memory_summary.md now contains multiple cwd/project sections.
  5. Start a new top-level session in one repo (for example, /Users/georgepickett/polyscraper).
  6. Observe from the code path that the initial context builder reads the entire memory_summary.md and injects it without filtering to the current cwd/project.

This is easiest to see from the code rather than a single UI screenshot:

  • injection gate: codex-rs/core/src/codex.rs:3764
  • full-file read: codex-rs/core/src/memories/prompts.rs:234
  • prompt template includes the whole summary: codex-rs/core/templates/memories/read_path.md:124
  • fresh baseline path: codex-rs/core/src/codex.rs:3928

What is the expected behavior?

The read path should respect the same repo/cwd boundary that the write/consolidation path is already trying to preserve.

A better architecture would be a hybrid model:

  • maintain a tiny global user profile for genuinely cross-project preferences
  • maintain per-repo/per-cwd memory_summary and MEMORY artifacts for repo-specific workflow, status, runbooks, and history
  • on a new session / fresh baseline, inject:
    • the tiny global profile, plus
    • only the matching repo/cwd summary for the current session
  • keep repo-specific detailed memory (MEMORY.md, rollout summaries, skills) scoped to that repo/cwd for later lookup

At minimum, build_memory_tool_developer_instructions(...) should filter or select the relevant section(s) of the summary by current cwd/project before injection, instead of pasting the entire global file.

Additional information

A few related design tensions surfaced while tracing this locally:

  • Phase 2 reads all memories_extensions/*/instructions.md files in the consolidation prompt in codex-rs/core/src/memories/prompts.rs:55, so multiple extensions currently influence one shared memory_summary.md.
  • Because the runtime injects one global summary into fresh initial context, those extensions indirectly compete for a single prompt budget over time.
  • This makes instructions.md a mitigation for summary quality, but not a real fix for retrieval/injection scope.

Suggested implementation directions:

  • add cwd/project-aware selection inside build_memory_tool_developer_instructions(...)
  • or split artifacts into:
    • global profile summary
    • per-repo/per-cwd summary
    • per-repo/per-cwd detailed memory
  • use current cwd/project root as the primary routing key, with global profile as a fallback/overlay

extent analysis

TL;DR

Filter the memory_summary.md by current cwd/project before injecting it into the initial context to respect repo boundaries.

Guidance

  • Modify build_memory_tool_developer_instructions(...) to select relevant sections of memory_summary.md based on the current cwd/project.
  • Consider splitting artifacts into global profile summary, per-repo/per-cwd summary, and per-repo/per-cwd detailed memory to better respect project boundaries.
  • Use the current cwd/project root as the primary routing key for memory injection, with the global profile as a fallback/overlay.
  • Review the consolidation prompt in codex-rs/core/src/memories/prompts.rs:55 to ensure it does not inadvertently influence the shared memory_summary.md across multiple extensions.

Example

// Example of filtering memory_summary.md by cwd/project
function buildMemoryToolDeveloperInstructions(cwd) {
  const memorySummary = readMemorySummary();
  const relevantSections = memorySummary.sections.filter(section => section.cwd === cwd);
  const filteredSummary = relevantSections.map(section => section.content).join('\n');
  return filteredSummary;
}

Notes

The provided solution assumes that the memory_summary.md file has a structured format that allows for easy filtering by cwd/project. If the format is not structured, additional parsing may be required.

Recommendation

Apply a workaround by filtering the memory_summary.md by current cwd/project before injecting it into the initial context. This will help respect repo boundaries and prevent irrelevant context from being injected. A more permanent solution would involve refactoring the memory artifact storage and retrieval to better respect project boundaries.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING