openai / openai/codex-plugin-cc

codex-companion.mjs: three reliability bugs in background review handling

Open
#279 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
33.3k
Forks
2.3k
PR merge metrics
No merged PRs in 30d

Description

Reporting three bugs in scripts/codex-companion.mjs (vendored at ~/.claude/plugins/marketplaces/openai-codex/plugins/codex/scripts/codex-companion.mjs, ~1007 lines) that have caused silent failures in production use. All three were root-caused from .codex-runs/ history across multiple projects.

Bug 1: --background flag declared but never read

handleReviewCommand declares the --background flag in its options block but never reads options.background to dispatch through the queue. As a result, reviews intended to run in the background actually run foreground.

Symptom: caller (Claude Code) expects a {jobId} JSON response to track the queued review; instead it gets the raw log stream of a foreground execution, which is unparseable.

Correlated incident: lease-analyzer wave9 — kickoff returned log stream instead of {jobId} JSON, marked as unparseable-no-jobid in audit.

Fix: wire options.background into handleReviewCommand; add enqueueBackgroundReview and a review-worker subcommand that the queue dispatches to.

Bug 2: Detached workers can die mid-execution with no liveness check

spawnDetachedTaskWorker uses detached: true, stdio: "ignore" and does not poll kill(pid, 0) afterward. If the worker dies (OOM, signal, runtime crash), the job record stays stuck in "queued" or "running" forever. Status/result handlers never detect the death.

Correlated incident: lease-analyzer wave41 — pid 13224 died mid-review before result harvest. Orchestrator showed the review as in-flight for ~1.5 hours before manual intervention.

Fix: add kill(pid, 0) liveness check in status and result handlers; if the pid is dead and no result file exists, mark the job as failed-worker-died with the last-known stderr (if captured).

Bug 3: Quota errors classified as infrastructure failures

ensureCodexReady does not distinguish quota-exhaustion errors from infrastructure errors. When the org hits its monthly Codex usage limit, the error path is the same as a hung process or unreachable runtime, so codex:rescue treats it as something to retry/recover instead of surfacing the actual blocking reason.

Correlated incident: carelog TD-84 — monthly usage limit misclassified as infra hang, escalation noise instead of "quota — wait for billing cycle reset".

Fix: add a quota-specific error class. Pattern-match the upstream error message; record quota-exhausted in the job record; have codex:rescue short-circuit and report rather than retry.


Happy to open separate issues per bug if that's preferred for triage. Filing combined since the diagnostic context overlaps and a single PR could plausibly address all three (auditing background/queue dispatch + worker lifecycle + error classification together).

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with scripts/codex-companion.mjs and trace handleReviewCommand, spawnDetachedTaskWorker, ensureCodexReady, the status/result handlers, and the review-worker subcommand. Verify background reviews return a job ID, dead workers become failed-worker-died, and quota failures are recorded as quota-exhausted and reported without retrying.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
cli, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.