feat(rescue): carry the Claude session into a Codex rescue with --session-context - #560
feat(rescue): carry the Claude session into a Codex rescue with --session-context#560r0han01 wants to merge 1 commit into
Conversation
…sion-context A rescue currently receives only the task text the user typed. Codex reads the same repository, but it has no access to what the user and Claude already discussed, ruled out, or tried and abandoned, so it can repeat work the session already established was a dead end. Add an opt-in --session-context flag to `task`, surfaced as `/codex:rescue --session-context`, that attaches the current Claude session as a handoff brief. The brief is assembled in the companion script from the transcript the existing SessionStart hook already records, so Claude never has to read or summarize the conversation itself and the delegation stays cheap on the Claude side. The assembly mirrors how Claude Code survives its own compaction: the summary written by /compact carries the earlier session and the turns recorded after the compact boundary close the gap. Running /compact before a rescue therefore yields a denser brief than a raw transcript would. The flag is deliberately not named --context. PR openai#293 proposes --context <text> for pasting extra free-form context into a rescue prompt. That is a different feature, and the two are complementary rather than competing, so this avoids the name collision. Details: - --session-context is boolean; --session-context-mode selects auto (default), summary, recent, full, or none, and implies the flag - --session-turns and --session-max-chars bound the brief; oldest turns are dropped first and the brief reports how many were omitted - tool calls, thinking blocks, subagent sidechains, meta entries, and injected system-reminder blocks are excluded - the branch and uncommitted file list are attached; diffs are not, so large working trees cannot balloon the prompt - the brief is framed as third-party background and tells Codex to verify it against the repository rather than trust it - with --resume, auto narrows to recent, since the resumed thread already holds the earlier brief - a compact summary older than an hour is flagged so the user can re-run /compact - the task text becomes optional when --session-context is present Resolve the Claude projects directory per call rather than at module load so transcript path resolution can be exercised against a relocated home directory.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 30e78dff29
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| for (let index = bounded.length - 1; index >= 0; index -= 1) { | ||
| const turn = bounded[index]; | ||
| const cost = turn.text.length + 32; | ||
| if (selected.length > 0 && usedChars + cost > maxChars) { |
There was a problem hiding this comment.
Enforce the character cap for a single oversized turn
When the newest usable transcript turn alone exceeds maxChars—for example, after the user pastes a very large log—selected is still empty, so this condition is skipped and the entire turn is attached. A 1 MB latest turn therefore produces roughly a 1 MB prompt despite the default 48 KiB cap, potentially exceeding model limits or unexpectedly increasing cost; truncate the turn or omit it while keeping the final brief within the configured limit.
Useful? React with 👍 / 👎.
Summary
A rescue currently receives only the task text the user typed. Codex reads the same repository, but it has no access to what the user and Claude already discussed, ruled out, or tried and abandoned — so it can spend a run rediscovering a dead end the session had already closed.
/codex:transfersolves the context problem by moving the user into Codex entirely. This PR covers the other half: staying in Claude Code and handing Codex a single task that already carries the session's background.Add an opt-in
--session-contextflag totask, surfaced as/codex:rescue --session-context:Design
The brief is assembled in the companion script, not by Claude. It reads the transcript that the existing
SessionStarthook already records inCODEX_COMPANION_TRANSCRIPT_PATH, reusingresolveClaudeSessionPathfromclaude-session-transfer.mjsso the~/.claude/projectscontainment check still applies. Claude never has to read or summarize the conversation, so the delegation stays cheap on the Claude side — which is much of the point of delegating.Assembly mirrors how Claude Code survives its own compaction. The summary written by
/compactcarries the earlier session, and the turns recorded after the compact boundary close the gap. Running/compactbefore a rescue therefore produces a denser and cheaper brief than a raw transcript, and frees the user's own context at the same time.Bounded by construction. Tool calls, thinking blocks, subagent sidechains, meta entries, and injected
<system-reminder>blocks are excluded.--session-turns(default 30) and--session-max-chars(default 48 KiB) cap the result; oldest turns drop first and the brief states how many were omitted. The branch and uncommitted file list are attached but diffs are not, so a large working tree cannot balloon the prompt — following the intent of bc8fa66.Framed as third-party background. The brief opens by telling Codex this is context from a different agent, not its own memory, and that the repository wins if the two disagree. Without that framing Codex reads "I fixed the token refresh" as its own completed work.
--resumenarrowsautotorecent, since a resumed thread already holds the earlier brief.Why not
--context--contextwas the natural name, but #293 proposes--context <text>for pasting extra free-form context into a rescue prompt. That is a different feature and the two are complementary, so this uses--session-contextto avoid the collision. Happy to rename if maintainers prefer a different spelling.--session-contextis boolean and--session-context-modetakes the value, so--session-context fix the logincannot misparse the task text as a mode.Modes
--session-contextauto)--session-context-mode summary--session-context-mode recent--session-context-mode full--session-context-mode noneTest plan
tests/claude-context-brief.test.mjscovering mode selection, summary/boundary splitting, sidechain and tool-block exclusion,system-reminderstripping, size-based truncation, turn caps, git and non-git working directories, stale-summary detection, partial trailing JSONL lines, path containment refusal, and flag parsing.npm test— 110 tests, 101 pass. The 9 failures (5setup, 3status/result, 1resolveStateDir) reproduce identically on unmodifiedmainin the same environment and are unrelated to this change.npm run buildpasses.task --session-contextagainst a live Claude Code session withgpt-5.4-miniand confirmed Codex answered questions about the branch, changed files, and prior decisions that appear only in the brief.--session-context fix the loginkeeps the full task text and does not consumefixas a mode.Note
claude-session-transfer.mjsnow resolves the Claude projects directory per call instead of at module load, so transcript path resolution can be tested against a relocated home directory. Behavior is unchanged.