From aa70e6daf4afe6d7f25a6e49b3594bdd82f847b7 Mon Sep 17 00:00:00 2001 From: Peter Simmons Date: Fri, 31 Jul 2026 22:34:07 -0400 Subject: [PATCH] fix(rescue): await delegated Codex result Keep the rescue subagent's sole task invocation in the foreground so it returns completed stdout. Explicit background mode remains owned by the outer rescue command, which backgrounds the entire subagent. --- plugins/codex/agents/codex-rescue.md | 5 +++-- plugins/codex/skills/codex-cli-runtime/SKILL.md | 2 ++ tests/commands.test.mjs | 5 +++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/codex/agents/codex-rescue.md b/plugins/codex/agents/codex-rescue.md index 7009ec86a..dce77c75a 100644 --- a/plugins/codex/agents/codex-rescue.md +++ b/plugins/codex/agents/codex-rescue.md @@ -20,8 +20,9 @@ Selection guidance: Forwarding rules: - Use exactly one `Bash` call to invoke `node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task ...`. -- If the user did not explicitly choose `--background` or `--wait`, prefer foreground for a small, clearly bounded rescue request. -- If the user did not explicitly choose `--background` or `--wait` and the task looks complicated, open-ended, multi-step, or likely to keep Codex running for a long time, prefer background execution. +- Always run that Bash call in the foreground and wait for it to finish before returning its stdout. + The outer `/rescue --background` command backgrounds this entire subagent when requested; + backgrounding the inner Bash call would let the subagent exit with a placeholder and lose the result. - You may use the `gpt-5-4-prompting` skill only to tighten the user's request into a better Codex prompt before forwarding it. - Do not use that skill to inspect the repository, reason through the problem yourself, draft a solution, or do any independent work beyond shaping the forwarded prompt text. - Do not inspect the repository, read files, grep, monitor progress, poll status, fetch results, cancel jobs, summarize output, or do any follow-up work of your own. diff --git a/plugins/codex/skills/codex-cli-runtime/SKILL.md b/plugins/codex/skills/codex-cli-runtime/SKILL.md index 0e91bfb50..2e02aaf7b 100644 --- a/plugins/codex/skills/codex-cli-runtime/SKILL.md +++ b/plugins/codex/skills/codex-cli-runtime/SKILL.md @@ -25,6 +25,8 @@ Execution rules: Command selection: - Use exactly one `task` invocation per rescue handoff. +- Always run that Bash call in the foreground. The outer rescue command owns backgrounding the + whole subagent; the subagent must wait for `task` and return its completed stdout. - If the forwarded request includes `--background` or `--wait`, treat that as Claude-side execution control only. Strip it before calling `task`, and do not treat it as part of the natural-language task text. - If the forwarded request includes `--model`, normalize `spark` to `gpt-5.3-codex-spark` and pass it through to `task`. - If the forwarded request includes `--effort`, pass it through to `task`. diff --git a/tests/commands.test.mjs b/tests/commands.test.mjs index c34b06059..09d1f0b09 100644 --- a/tests/commands.test.mjs +++ b/tests/commands.test.mjs @@ -127,8 +127,9 @@ test("rescue command absorbs continue semantics", () => { assert.match(agent, /--resume/); assert.match(agent, /--fresh/); assert.match(agent, /thin forwarding wrapper/i); - assert.match(agent, /prefer foreground for a small, clearly bounded rescue request/i); - assert.match(agent, /If the user did not explicitly choose `--background` or `--wait` and the task looks complicated, open-ended, multi-step, or likely to keep Codex running for a long time, prefer background execution/i); + assert.match(agent, /always run that Bash call in the foreground/i); + assert.doesNotMatch(agent, /prefer background execution/i); + assert.match(runtimeSkill, /always run that Bash call in the foreground/i); assert.match(agent, /Use exactly one `Bash` call/i); assert.match(agent, /Do not inspect the repository, read files, grep, monitor progress, poll status, fetch results, cancel jobs, summarize output, or do any follow-up work of your own/i); assert.match(agent, /Do not call `review`, `adversarial-review`, `status`, `result`, or `cancel`/i);