Add a detached effective-context fork for oversized Desktop threads
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
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:
- 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.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:
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:
{
"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:
- 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_historyplus 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_basethat 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/liston 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:
thread/forkalready supports paginated reference-backed forks and bounded model-context reconstruction: https://github.com/openai/codex/pull/35220- Legacy-to-paginated rollout migration has landed: https://github.com/openai/codex/pull/37175
- CLI/background migration tooling has landed: https://github.com/openai/codex/pull/37348
- Current
load_latest_model_contextreverse-scans paginated rollouts to a usable replacement-history checkpoint: https://github.com/openai/codex/blob/4c89139da96f3e982f123c8b739e3de9bc4570be/codex-rs/thread-store/src/local/model_context.rs#L26-L70 - Current fork processing already obtains
prepared_fork.model_context, but persists paginated forks as parent-history references: https://github.com/openai/codex/blob/4c89139da96f3e982f123c8b739e3de9bc4570be/codex-rs/app-server/src/request_processors/thread_processor.rs#L4120-L4194
Related issues cover different parts of the problem:
- #25251 reports the Desktop CPU/memory impact of opening a large thread. This proposal adds an explicit escape hatch after successful compaction.
- #34268 and #35647 cover fork storage amplification. Reference-backed paginated forks address physical duplication, but still retain logical parent history.
- #36584 proposes a
HANDOFF.mdworkflow motivated by context drift. This proposal transfers the already-effective compacted model state without generating another summary. - #22641 proposed an automatic fresh-session handoff prompt. This proposal instead uses normal fork metadata plus the actual effective model context, and is motivated by Desktop/session engineering cost.
- #30194 covered recovery when compaction fails or cannot reclaim context. This proposal assumes compaction succeeded and detaches the new task from the oversized UI-visible transcript.
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with codex-rs/thread-store/src/local/model_context.rs and its load_latest_model_context path, then inspect the existing fork processing in codex-rs/app-server/src/request_processors/thread_processor.rs. Determine how a fork can persist the effective model context without parent-history references. Done means the listed acceptance criteria hold, including bounded child context, no source-turn traversal, preserved source rollout, and cold-resume support.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend-api-design, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100