openai / openai/codex-plugin-cc
codex-companion.mjs: three reliability bugs in background review handling
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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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