openai / openai/codex-plugin-cc

Robustness: detached-worker spawn error handling, dead-worker reconciliation, atomic + serialized state writes

Open
#377 1 comment 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

Thanks for the plugin. While hardening our setup we hit several robustness issues in the job-state / worker lifecycle (v1.0.4) that can silently lose job records or leave jobs wedged. File:line are against the v1.0.4 tag.

Medium

  1. Detached worker spawn has no error handlerscripts/codex-companion.mjs, spawnDetachedTaskWorker. child.unref() is called with no child.on("error", …); a failed spawn (ENOENT/EACCES) goes undetected, the job is recorded with pid: null, and a subsequent cancel silently no-ops. Suggest attaching an error handler that marks the job failed.

  2. Crashed worker stuck running foreverscripts/codex-companion.mjs, waitForSingleJobSnapshot. Status is polled with no PID-liveness check, so a SIGKILL'd worker never self-transitions (the catch that writes status: "failed" never runs). Suggest a process.kill(pid, 0) liveness probe (ESRCH → failed) or a timeout→failed fallback in the read path.

  3. state.json written non-atomically, and the read-modify-write is unserializedscripts/lib/state.mjs (saveState, writeJobFile, updateState). Two distinct problems:

    • Plain fs.writeFileSync can be observed mid-write; loadState then hits its catch and silently returns empty state, dropping all job records. Suggest temp-file + fs.renameSync for an atomic replace.
    • updateState does loadState → mutate → saveState with no lock. Concurrent writers — parent enqueue, the worker's progress updates (createJobProgressUpdater), and the SessionEnd cleanupSessionJobs in scripts/session-lifecycle-hook.mjs — each load, patch their own copy, and last-writer-wins drops other jobs. Suggest a lock (or compare-and-swap) around the RMW. Repro: ~25 concurrent writers adding distinct jobs → most are lost.

Low

  1. generateJobId uses Math.random() (scripts/lib/state.mjs) — prefer crypto.randomUUID() / crypto.randomBytes.
  2. ensureGitRepository runs twice per review.
  3. handleResult / handleTaskResumeCandidate are not awaited.
  4. status --wait exits 0 on timeout (reads as success); readJobFile has no JSON parse guard.

Happy to send a PR for any of these if useful.

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 in scripts/codex-companion.mjs at spawnDetachedTaskWorker and waitForSingleJobSnapshot, then inspect saveState, writeJobFile, updateState, and loadState in scripts/lib/state.mjs. Reproduce the concurrent-writer loss and failed or killed worker cases described in the issue. Done means worker failures become visible, dead jobs do not remain running indefinitely, and state writes are atomic and serialized without dropping records.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.