Repository navigation
Resume and interrupt Codex sessions (#395) - #405
Merged
Merged
Conversation
…em with SIGINT first (#395) A Codex sub-agent call still running at turn end is now killed background work, as a command is, so its session gets the one Resume. An interrupt sends a Codex session SIGINT, the only signal Codex stops cleanly on, before SIGTERM and SIGKILL. Tests cover the Resume on Codex ending the same way, counting against no Repair cap, and the interrupt order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lled-work tracking (#395) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 5, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Codex sessions now handle killed background work and interrupts the way Claude sessions do. The Resume path,
codex exec … resume <thread id>with every flag passed again, already came from #394. This PR adds the sub-agent case, interrupts, and the tests the issue asks for.CodexProgress::item(item) command_execution track_running(id, item, unwrapped command) + collab_tool_call + track_running(id, item, "agent spawn_agent: <first line of its prompt>") turn.completed killed = still running # each gets the one Resume, as on ClaudeThe fake
codexnow catches SIGINT and SIGTERM and waits for its script, so each test's script decides how the session stops and records which signals reached it.Evidence
an_interrupt_sends_a_codex_session_sigint_and_the_run_ends_as_interruptedfailed. Its agent recordedTERM\n, where the test expectsINT\n.a_sub_agent_call_still_running_when_the_turn_completes_is_killed_background_workfailed with no killed work.After: all 12 tests in
tests/codex_sessions.rspass, and so does the fullcargo testsuite. The new tests:resume fake-thread-1cargo teststarting Repair 5 of 5and goes greenINTonly, and the Run ends withthirdshift: failed run (interrupted)INTand thenTERMMerge Danger
Door: two-way
Blast Radius: Codex sessions only
Claude sessions still get SIGTERM, then SIGKILL. A Codex session that ignores SIGINT can now take up to 20s to stop, where it took 10s before.
Unaddressed findings
Standards
running: Vec<(String, String)>is a tuple standing in for a type (Primitive Obsession). This predates the change, and the PR only rewords its doc.tests/background_work.rs. I kept them on purpose: the acceptance criteria ask for this behaviour on Codex end to end, through Codex's own stream and arguments.Spec
collab_tool_callhas completed, throughagents_states. The issue defines killed work as "item.started but no item.completed", and that is what the code follows. The research doc marks theagents_statessignal as inference that needs a live check, so I left it out.wait,send_inputorclose_agentcall still in progress at turn end also counts as killed work. This rarely happens. When it does, a Resume is the right response anyway: the session stopped mid-call.codexalone. That matches how SIGTERM is already sent. Codex puts the commands it spawns in their own groups, so in practice onlycodexreceives it.Closes #395
🤖 Generated with Claude Code