You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add a detached effective-context fork for oversized Desktop threads #38091
Codex App on macOS. The proposed primitive belongs in app-server so the App, CLI, and IDE clients can reuse the same semantics.
What feature would you like to see?
Summary
Add a detached effective-context fork for very long threads.
After a manual or automatic compaction has completed, the user should be able to continue in a new task that inherits the source thread's latest effective model context, but does not inherit or expose the source thread's complete conversation history.
This is a performance and working-set feature, not a request for a new handoff summary or different compaction quality.
Motivation
Very long, tool-heavy Codex App threads can become progressively expensive for the Desktop renderer and app-server to hydrate, parse, serialize, and retain. This can remain a problem after model-context compaction because the persisted/UI-visible transcript is still large even though the model now works from a bounded compacted state.
Existing choices do not provide the desired boundary:
A normal fork inherits the conversation history. Paginated reference-backed forks avoid copying the entire parent JSONL, but their logical history still traverses the parent lineage.
A new task has a small transcript, but loses the already-computed effective model context.
A generated HANDOFF.md or handoff prompt performs another lossy summarization step and is aimed at continuity quality rather than local history hydration cost.
The desired operation is conceptually a shallow/compact fork:
source full transcript
|
| latest usable compacted replacement history + surviving suffix
v
new task with bounded model context and no inherited visible turn history
Proposed semantics
An illustrative app-server request could extend thread/fork with an enum such as:
The exact API name is not important. The important behavior is:
Require the source thread to be idle and use the latest successfully persisted effective model context.
Seed the child with the latest usable Compacted.replacement_history plus the surviving post-compaction suffix needed for the next model request.
Persist that bounded snapshot in the child instead of copying the complete source rollout or retaining a history_base that exposes the parent turns.
Preserve normal fork metadata behavior: forkedFromId, cwd/workspace roots, current configuration and instructions, permissions, environments, and optionally the current Goal.
Leave the source thread unchanged and available for audit.
After switching the App to the child, stop hydrating/subscribing to the source so its renderer/app-server state can be released.
For legacy histories, either migrate to paginated history first or return a clear unsupported result. Do not silently fall back to a full-history copy/read for this mode.
The App could expose this as Continue in compact fork or Continue in a lightweight task after a successful compaction. Automatic rollover is not required for the initial version.
Acceptance criteria
The child's first model request receives the same effective conversation state as the source would receive immediately after compaction, apart from intentionally refreshed thread-local context.
The child rollout size is proportional to the effective model context, not the full source rollout.
thread/turns/list on the child does not traverse or return source turns.
Cold resume of the child preserves the same effective context.
The source rollout is not rewritten or deleted.
Navigating to the child does not require the App to hydrate the source transcript.
Additional information
This appears close to existing app-server building blocks:
The repository accepts external PRs by invitation only. If this direction aligns with the intended thread-storage architecture, would the maintainers consider inviting a focused backend-only PR for the experimental app-server primitive? The Desktop button/navigation could remain an internal follow-up.
Hi @ai-jz, that rollout size is valuable stress evidence. Codex Rescue Alpha5 scans large local session histories with bounded memory and produces aggregate size, media, and compaction diagnostics without loading the whole file into RAM or dumping full payloads.
If you still have an affected closed rollout, you can test it locally:
pip install codex-rescue==0.1.0a5
codex-rescue doctor <path-to-rollout.jsonl>
No raw session upload is needed; sanitized aggregate output is sufficient.
codex-rollout-shrinker is a local CLI and transformation core for safely
shrinking and restoring a manually forked and compacted Codex rollout while it
is cold.
The operator performs the model-dependent work in an ordinary Codex frontend:
Fork the source thread.
Switch to the fork and run context compaction.
Wait for compaction to finish.
Close the frontend so its Codex backend releases the rollout writer.
Run inspect, then run the explicitly confirmed shrink command with the
fork thread ID.
Reopen the same fork thread in Codex.
Environment
Windows host: Windows 11, build 10.0.22000.2538;
execution environment: WSL2, Ubuntu 24.04.4 LTS, Linux 6.18.33.2-microsoft-standard-WSL2, x86-64, ext4;
frontend: VS Code 1.134.0 x64 with OpenAI ChatGPT/Codex extension 26.825.41651 running in WSL;
The source was a legacy fork with absent/null history_base, 10 compaction
windows, and a usable window-10 checkpoint. “Turn” is ambiguous in legacy
rollouts, so the raw counters are stated explicitly: the source had 28 task_started events, 28 matching task_complete events, 28 user response_item messages, and 18 turn_context records.
Measurement
Value
Source records
5,982
Source bytes
14,869,588
Latest safe replay boundary
record 5,898
Latest checkpoint
record 5,979, window 10
Newest replacement_history
19 items
Compact JSON size of that replacement array
25,000 bytes
Retained records
86
Published bytes
228,680
Removed records
5,896 (98.5624%)
Removed bytes
14,640,908 (98.4621%)
Source-to-published size ratio
65.02x
If this evidence confirms the use case, would the maintainers prefer an experimental thread/fork strategy or a dedicated app-server operation, and would they invite a backend-only contribution?
What variant of Codex are you using?
Codex App on macOS. The proposed primitive belongs in app-server so the App, CLI, and IDE clients can reuse the same semantics.
What feature would you like to see?
Summary
Add a detached effective-context fork for very long threads.
After a manual or automatic compaction has completed, the user should be able to continue in a new task that inherits the source thread's latest effective model context, but does not inherit or expose the source thread's complete conversation history.
This is a performance and working-set feature, not a request for a new handoff summary or different compaction quality.
Motivation
Very long, tool-heavy Codex App threads can become progressively expensive for the Desktop renderer and app-server to hydrate, parse, serialize, and retain. This can remain a problem after model-context compaction because the persisted/UI-visible transcript is still large even though the model now works from a bounded compacted state.
Existing choices do not provide the desired boundary:
HANDOFF.mdor handoff prompt performs another lossy summarization step and is aimed at continuity quality rather than local history hydration cost.The desired operation is conceptually a shallow/compact fork:
Proposed semantics
An illustrative app-server request could extend
thread/forkwith an enum such as:{ "method": "thread/fork", "params": { "threadId": "<source-thread-id>", "historyScope": "effectiveContext", "excludeTurns": true, "deferGoalContinuation": true } }The exact API name is not important. The important behavior is:
Compacted.replacement_historyplus the surviving post-compaction suffix needed for the next model request.history_basethat exposes the parent turns.forkedFromId, cwd/workspace roots, current configuration and instructions, permissions, environments, and optionally the current Goal.The App could expose this as Continue in compact fork or Continue in a lightweight task after a successful compaction. Automatic rollover is not required for the initial version.
Acceptance criteria
thread/turns/liston the child does not traverse or return source turns.Additional information
This appears close to existing app-server building blocks:
thread/forkalready supports paginated reference-backed forks and bounded model-context reconstruction: Support paginated thread forks #35220load_latest_model_contextreverse-scans paginated rollouts to a usable replacement-history checkpoint:codex/codex-rs/thread-store/src/local/model_context.rs
Lines 26 to 70 in 4c89139
prepared_fork.model_context, but persists paginated forks as parent-history references:codex/codex-rs/app-server/src/request_processors/thread_processor.rs
Lines 4120 to 4194 in 4c89139
Related issues cover different parts of the problem:
HANDOFF.mdworkflow motivated by context drift. This proposal transfers the already-effective compacted model state without generating another summary.The repository accepts external PRs by invitation only. If this direction aligns with the intended thread-storage architecture, would the maintainers consider inviting a focused backend-only PR for the experimental app-server primitive? The Desktop button/navigation could remain an internal follow-up.