Before submitting
Area
apps/server (Codex adapter, CodexSessionRuntime)
Steps to reproduce
Same as #4683:
- Open a Codex conversation with automatic memories enabled.
- Exchange a few ordinary messages.
- Let post-turn memory consolidation run.
Expected behavior
Memory consolidation output stays out of the user's chat.
Actual behavior
The memory worker's messages and tool activity are saved into the open conversation. #5468 fixed this for memory threads that announce themselves with thread/started and a memory_consolidation source. It still happens when Codex streams the worker's items (item/agentMessage/delta, item/completed, warning) without sending thread/started first. The filter never learns that thread id, so the output falls through to the parent path. @gfdelarue hit this on 0.0.38 with Codex CLI 0.153.3 (comment on #8989). The persisted rows had data.threadId set to the worker threads.
Impact
Minor bug or occasional failure
Version or commit
Reproduced in tests against main at a3abb52. Reported live on 0.0.38.
Environment
Codex CLI 0.153.3 (reporter), NixOS; tests on Windows 11.
Logs or stack traces
No response
Workaround
Turn off automatic memories in Codex.
Why this isn't a one-line fix
I tried twice in #8989, and both attempts were closed. Notes for whoever picks this up:
-
Dropping output from any unknown foreign thread fixes the leak but also loses real subagent output. Codex can stream a v2 child's items before the subAgentActivity or thread/started that registers it, and on arrival that child looks the same as unannounced memory work.
-
Holding unknown-thread output until the thread is identified, then replaying it, works in principle. It passes the leak test and the early-child test. Review turned up seven ordering bugs in four rounds, though:
- replay re-ran receiver-turn bookkeeping and restored an older turn;
- a replayed old error cleared a child's newer live turn, so Stop skipped it;
- every root delta scanned all held threads;
- a child that failed before registering stayed interruptible;
- the new root's output was stranded after a resume fallback;
- an early memory
turn/completed marks the session ready before the open response, so the real root's output gets held;
- a replayed old error marks a newer running child as failed.
The first five are fixed on the prototype. The last two are not.
-
A clean fix probably needs a signal that says "this thread is memory work" on every notification, or a decision on what to do with output from threads that are never identified.
The prototype and its tests are on SunkenInTime:wip/codex-unannounced-memory (CodexSessionRuntime.ts and CodexCollabRuntime.integration.test.ts). The integration tests that replay unannounced memory output and early child items fail on main and could be reused for any fix.
Before submitting
Area
apps/server (Codex adapter,
CodexSessionRuntime)Steps to reproduce
Same as #4683:
Expected behavior
Memory consolidation output stays out of the user's chat.
Actual behavior
The memory worker's messages and tool activity are saved into the open conversation. #5468 fixed this for memory threads that announce themselves with
thread/startedand amemory_consolidationsource. It still happens when Codex streams the worker's items (item/agentMessage/delta,item/completed,warning) without sendingthread/startedfirst. The filter never learns that thread id, so the output falls through to the parent path. @gfdelarue hit this on 0.0.38 with Codex CLI 0.153.3 (comment on #8989). The persisted rows haddata.threadIdset to the worker threads.Impact
Minor bug or occasional failure
Version or commit
Reproduced in tests against
mainat a3abb52. Reported live on 0.0.38.Environment
Codex CLI 0.153.3 (reporter), NixOS; tests on Windows 11.
Logs or stack traces
No response
Workaround
Turn off automatic memories in Codex.
Why this isn't a one-line fix
I tried twice in #8989, and both attempts were closed. Notes for whoever picks this up:
Dropping output from any unknown foreign thread fixes the leak but also loses real subagent output. Codex can stream a v2 child's items before the
subAgentActivityorthread/startedthat registers it, and on arrival that child looks the same as unannounced memory work.Holding unknown-thread output until the thread is identified, then replaying it, works in principle. It passes the leak test and the early-child test. Review turned up seven ordering bugs in four rounds, though:
turn/completedmarks the sessionreadybefore the open response, so the real root's output gets held;The first five are fixed on the prototype. The last two are not.
A clean fix probably needs a signal that says "this thread is memory work" on every notification, or a decision on what to do with output from threads that are never identified.
The prototype and its tests are on SunkenInTime:wip/codex-unannounced-memory (
CodexSessionRuntime.tsandCodexCollabRuntime.integration.test.ts). The integration tests that replay unannounced memory output and early child items fail onmainand could be reused for any fix.