Skip to content

codex:codex-rescue subagent hangs on poll loop; task broker runs under wrong cwd #7

Description

@axisrow

Summary

A codex:codex-rescue invocation (via Agent({ subagent_type: "codex:codex-rescue" }) from Claude Code) hung for 15+ minutes and never returned Codex's output to the session. Root cause is two-fold: (1) the rescue subagent's wait-for-completion pattern is incompatible with Claude Code's runtime sleep restrictions, and (2) the Codex task broker spawns under a wrong cwd (/private/tmp/pr523-review/..., a different repo), so even a completed run would not surface in the caller's context.

Environment

  • Claude Code: 2.1.214
  • Skill runtime: codex:rescue → subagent codex:codex-rescuecodex-companion.mjs task ...
  • Codex fork: etopro-plugins/codex-fork 1.0.6-fork.3 (sha 2ee9914), installed scope: "user" from git-subdir source https://github.com/axisrow/codex-plugin-cc.gitplugins/codex
  • Companion: ~/.claude/plugins/cache/etopro-plugins/codex-fork/1.0.6-fork.3/scripts/codex-companion.mjs
  • Companion subagent forwarding model: glm-5-turbo, effort high, task-call timeout 300000
  • Caller session cwd: /Users/axisrow/Projects/claude-code-cycle-review-skill (branch refactor/skill-linear-numbering)
  • task-resume-candidate --json --cwd <caller> returned available: false → routed to a fresh task

Reproduction

  1. From a Claude Code session in repo A, invoke the codex:rescue skill (or Agent({ subagent_type: "codex:codex-rescue" })) with a non-trivial design question.
  2. The rescue subagent drafts a Codex prompt and invokes codex-companion.mjs task --cwd <repo-A> ... in the foreground.
  3. The Bash call exceeds Claude Code's foreground-sleep / timeout rules; the runtime auto-backgrounds it.
  4. The subagent, attempting to recover, falls back to sleep 60 && tail (blocked) then until grep Thread completed; do sleep 5; done (unbounded) — which itself violates the foreground-sleep rule and hangs the session.
  5. Meanwhile 8+ app-server-broker processes accumulate with --cwd pointing at temp codex-plugin-test-* dirs under an unrelated repo path (/private/tmp/pr523-review/...), not at --cwd <repo-A>.

Observed process state

8+ app-server-broker.mjs serve --endpoint unix:.../cxc-XXXX/broker.sock --cwd /private/var/folders/.../T/codex-plugin-test-XXXX --pid-file .../cxc-XXXX/broker.pid

plus dozens of orphaned cxc-* sockets in $TMPDIR.

Impact

  • codex:rescue is unusable from a Claude Code session: the rescue subagent hangs instead of returning Codex's output.
  • Hygiene: orphaned app-server-broker processes and cxc-* sockets accumulate across sessions, leaking resources (this compounds with the broader orphan-process problem Claude Code/Codex sessions already create on this host).

Likely causes (for the fork maintainer to confirm)

  1. Wait pattern blocked by runtime. The rescue subagent's "wait for Codex thread to finish" step uses a foreground sleep / until grep loop, both incompatible with Claude Code's Bash sandbox (foreground sleep is blocked; unbounded until never exits while Codex is thinking). The companion should expose a blocking-wait primitive the subagent can call once (analogous to wait-for-reviews.sh's backgrounded-sleep pattern, or task --wait that blocks internally rather than returning a thread id the caller must poll).
  2. Broker cwd mismatch. Brokers spawn with --cwd pointing at temp codex-plugin-test-* dirs under an unrelated repo path (/private/tmp/pr523-review/...), not the --cwd the caller passed to task. The broker lookup/selection seems to reuse a stale or wrong broker instead of spawning one bound to the caller's repo. Either brokers must be keyed/selected by cwd, or a fresh broker must be spawned (and reaped) per task --cwd.
  3. No reaping. Brokers and sockets are not cleaned up on task completion / session exit.

Suggested investigation

  • In scripts/codex-companion.mjs, trace how task --cwd <X> selects (or spawns) an app-server-broker and verify the broker's --cwd matches <X>; today it does not.
  • In the codex:codex-rescue subagent's wait step, replace the sleep/until grep polling with a single blocking companion call (e.g. task --wait blocking, or a dedicated wait-for-thread <id> helper) that does not violate Claude Code's foreground-sleep rule.
  • Add broker+socket reaping on task completion and session exit.

Artifacts available on request

  • Subagent transcript: /private/tmp/claude-501/-Users-axisrow-Projects-claude-code-cycle-review-skill/68e398df-bf2d-4981-b7c8-30035d298416/tasks/a9f13e147505596f0.output (JSONL; contains the blocked-sleep tool error, the until grep fallback, the task invocation with --cwd, and the [codex] Thinking. stream).
  • ps -eo pid,etime,command | grep app-server-broker snapshot (above).

Reported from a downstream consumer (claude-code-cycle-review-skill uses this fork for its local Codex review). Happy to run further diagnostics in this environment on request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions