fix: route /codex:rescue through the Agent tool to stop Skill recursion (#234)#235
Open
pengyou200902 wants to merge 1 commit intoopenai:mainfrom
Open
fix: route /codex:rescue through the Agent tool to stop Skill recursion (#234)#235pengyou200902 wants to merge 1 commit intoopenai:mainfrom
pengyou200902 wants to merge 1 commit intoopenai:mainfrom
Conversation
…on (openai#234) `commands/rescue.md` previously told the forked runner to "Route this request to the `codex:codex-rescue` subagent", but `codex:codex-rescue` is an `Agent` subagent — not a `Skill`. When the main Claude Code agent called `Skill(codex:rescue)` programmatically, the fork interpreted the prose as a skill route, tried `Skill(codex:codex-rescue)` (unknown), then fell back to `Skill(codex:rescue)`, which re-entered this command and hung the session with no Codex job ever starting. - Name the transport explicitly: use the `Agent` tool with `subagent_type: "codex:codex-rescue"`. - Add `Agent` to `allowed-tools` so the fork can invoke it without a permission prompt. - Forbid `Skill(codex:rescue)` / `Skill(codex:codex-rescue)` and instruct the fork not to retry on failure. - Map `--background` onto `Agent(..., run_in_background: true)`. - Add regression tests in `tests/commands.test.mjs` that pin the Agent-tool routing and block the old "Route this request to the `codex:codex-rescue` subagent" phrasing.
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
Fixes #234. When the main Claude Code agent called
Skill(codex:rescue)programmatically (not via the user-typed slash command), the forked runner re-entered this same command and hung the session for minutes, burning tokens and never starting Codex.Root cause:
commands/rescue.mdtold the fork to "Route this request to thecodex:codex-rescuesubagent", without naming the transport.codex:codex-rescueis anAgent-tool subagent, not a skill, but the fork resolved the ambiguous prose by:Skill(codex:codex-rescue)→Unknown skill.Skill(codex:rescue)→ re-forked into itself → infinite recursion.The slash command path is unaffected because Claude Code's slash-command router dispatches directly and does not go through that prose resolution.
Fix
commands/rescue.md: replace the ambiguous prose with an explicit instruction to use theAgenttool withsubagent_type: "codex:codex-rescue".Agenttoallowed-toolsso the fork can invoke it without a permission prompt.Skill(codex:rescue)/Skill(codex:codex-rescue)and telling the fork not to retry viaSkillon failure.--backgroundontoAgent(..., run_in_background: true)so the existing execution-mode semantics still work.tests/commands.test.mjs: add regression assertions that pin the Agent-tool routing and reject the old "Route this request to thecodex:codex-rescuesubagent" phrasing.Both of the workarounds suggested in the issue are applied (explicit transport + narrowed tool surface); the prose fix is the load-bearing change.
Test plan
Automated:
node --test tests/commands.test.mjs -t "rescue command absorbs continue semantics"— rescue regression test passes against the patched file.node --test tests/*.test.mjs— full suite: 85/86 pass, same baseline asmain. The single remaining failure (result \$ARGUMENTSvsresult "\$ARGUMENTS"in the quoting assertion) predates this PR; it was introduced in fix: quote $ARGUMENTS in cancel, result, and status commands #168 and is unrelated.rescue.mdtemporarily reverted to the pre-fix HEAD, the new assertions fail on the missingAgentallow-listing, the missingsubagent_type: "codex:codex-rescue"routing line, and the lingering "Route this request to thecodex:codex-rescuesubagent" sentence — confirming they actually catch Skill(codex:rescue) infinite-recurses when invoked programmatically from main agent #234.Surrogate manual (verifying the pieces the fork touches):
rescue.mdfrontmatter parses as valid YAML;allowed-toolsisBash(node:*), AskUserQuestion, Agent;Skillis not allow-listed.agents/codex-rescue.mdhasname: codex-rescue, soAgent(subagent_type: "codex:codex-rescue")resolves under thecodexplugin namespace..claude-plugin/plugin.jsonand the marketplace manifest still declare thecodexplugin at 1.0.3 withsource: ./plugins/codex.node scripts/codex-companion.mjs task-resume-candidate --json→{"available": false, ...}on a clean session.Live end-to-end (requires a fresh Claude Code session with this branch's plugin loaded; not runnable from the session that prepared this PR because the installed plugin there is published 1.0.3 scoped to other project dirs):
Skill(codex:rescue, args: "<task>")and confirm the fork invokesAgent(subagent_type: "codex:codex-rescue")→node codex-companion.mjs task ...without recursion./codex:rescue <task>as a user and confirm the slash-command path is unchanged.