[Windows Desktop 26.707.8479.0] New windows still fan out full conversation snapshots for every streaming thread
Summary
The Microsoft Store Windows desktop package OpenAI.Codex_26.707.8479.0 still ships the unbounded connected-client snapshot fan-out described in #20781.
When a new desktop client/window connects, the production bundle iterates every entry in streamingConversations and calls broadcastConversationSnapshot. Each snapshot contains the complete in-memory conversationState, including loaded turn history. With large resident threads, opening an otherwise empty window can therefore serialize and broadcast unrelated multi-hundred-megabyte conversation state, producing large app-server CPU/memory bursts and whole-system pointer/UI stalls.
This report confirms that the same mechanism remains in a current Windows desktop build after the July 2026 desktop integration update. It is not a Git indexing report, and it intentionally keeps the separate per-thread MCP lifecycle issue out of scope.
Environment
- OS: Windows 11 x64
- Surface: Codex inside the Microsoft Store ChatGPT/Codex desktop app
- Package:
OpenAI.Codex_26.707.8479.0_x64__2p2nqsd0c76g0 - Bundled app-server reported at startup:
0.144.2 - Verification date: 2026-07-13
- Workload: multiple local Codex threads/windows, including very large completed histories
Current production-bundle evidence
Read-only inspection of the installed app.asar shows the connected-client branch is still effectively:
handleClientStatusChanged({ status }) {
if (status === "connected") {
for (const conversationId of this.streamingConversations) {
this.broadcastConversationSnapshot(conversationId);
}
return;
}
}
The snapshot path still dispatches the full state:
change: {
type: "snapshot",
revision,
conversationState
}
There is no selected-thread filter, completed-thread exclusion, turn-count/byte gate, lazy hydration boundary, or backpressure around this branch.
The bundle does contain a 256 MiB IPC ceiling, but it is applied only after serializing the entire broadcast:
const serialized = JSON.stringify(message);
const payloadBytes = Buffer.byteLength(serialized, "utf8");
if (payloadBytes > 268435456) {
// drop broadcast
}
That is not an effective performance bound:
- The complete conversation state has already been constructed and JSON-serialized before the check.
- Payloads below 256 MiB, including the ~116 MiB frames already documented in #20781, are still sent in full.
- A dropped oversized broadcast can still incur the CPU, allocation, and copying cost that causes the input stall.
No Skipping large conversation snapshot broadcast or equivalent pre-serialization guard exists in this Windows build.
Sanitized measured reproduction from the same machine/build family
On the immediately preceding 26.707 Store build, with three large threads already resident:
- rollout sizes were approximately 4.81 GiB, 1.905 GiB, and 0.135 GiB;
- the newly opened blank task was approximately 0.002 GiB and was not the payload source;
- opening the new window drove the shared app-server to approximately 624% CPU and 30.7 GiB working set;
- after partial draining it was still approximately 360% CPU and 9.95 GiB working set;
- live Git process count remained zero;
- a later blank-window acceptance test still produced an approximately three-second pointer stall and grey renderer while about 89 GiB of system RAM remained free.
The current 26.707.8479.0 build was inspected rather than deliberately stress-reproduced again because the original path causes disruptive whole-system input stalls. The exact triggering fan-out and full-state serialization code remains present.
Steps to reproduce
- Keep several local Codex threads resident, including one or more large completed histories.
- Open a new Codex/ChatGPT desktop window or otherwise connect a new desktop client.
- Observe
client-status-changed: connected. - Observe a full
thread-stream-state-changedsnapshot for every conversation retained instreamingConversations, not only the selected thread. - Measure app-server/renderer CPU, memory, IPC payload size, and pointer responsiveness.
The blank new thread itself may be tiny; the cost comes from unrelated state already resident in the shared app-server.
Expected behavior
A newly connected window should receive only the minimum state required to render its current route.
At minimum:
- completed/inactive threads should not remain eligible for reconnect snapshot fan-out;
- a new client should not receive complete snapshots for unrelated threads;
- thread hydration should start from metadata plus a bounded recent tail;
- older turns should load lazily/paginate on demand;
- snapshot size/count limits must run before full JSON serialization;
- oversized state should use a bounded/paginated protocol rather than build-and-drop;
- patch updates should remain the normal steady-state path.
Requested regression coverage
Please add a test that:
- creates multiple conversations, including a completed large-history thread;
- connects a second client/window;
- asserts the second client does not receive full snapshots for unrelated/completed conversations;
- asserts CPU work and serialized bytes remain bounded independently of retained history size.
Related
- #20781 documents the same
streamingConversations -> broadcastConversationSnapshot(full conversationState)mechanism and remains open. - The May report includes ~116 MiB frames and 250–400% CPU; a follow-up comment records a 405 MiB Desktop payload.
- This new issue is the Windows Store
26.707.8479.0current-build confirmation.
Please publish the fixed desktop version in the changelog when this path is bounded. The generic phrase “additional performance improvements and bug fixes” does not let affected users know whether it is safe to remove local containment or retest giant histories.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗