Skip to content

feat(task): add --background --await + await subcommand for completion-bound process#347

Open
iamrain2008 wants to merge 1 commit into
openai:mainfrom
iamrain2008:feat/task-await
Open

feat(task): add --background --await + await subcommand for completion-bound process#347
iamrain2008 wants to merge 1 commit into
openai:mainfrom
iamrain2008:feat/task-await

Conversation

@iamrain2008
Copy link
Copy Markdown

Problem

task --background returns the launching CLI process in 1-2 seconds, while the daemon worker continues running for 10-30+ minutes. There is no observable completion signal for the launching caller — the worker is detached (stdio: "ignore", child.unref()) and writes terminal state into plugin state files asynchronously.

Callers (including LLM-driven agents acting on behalf of users) must remember an out-of-band protocol to detect daemon completion: poll status with a specific grep pattern, retry result <job-id>, etc. Reminder-based fixes are unreliable; in practice, callers repeatedly conflate "launching CLI returned" with "Codex task finished" and end up waiting for a completion signal that never arrives.

Root cause

The plugin currently exposes split-brain async semantics:

  1. Launch path is observable via the CLI process exit (1-2s after invocation).
  2. Real work path is observable only by polling plugin state files (no callback).
  3. The launch message ("started in the background as task-xxx") implicitly suggests a future completion signal that never arrives.
  4. No canonical "block until daemon reaches terminal state + print final result" primitive exists.

Out-of-band polling protocols cannot be enforced reliably across callers. The plugin should expose a completion-bound process as a first-class primitive.

Solution

Two additive APIs that make the launching process represent actual daemon completion:

New subcommand: await <job-id>

node scripts/codex-companion.mjs await <job-id> \
    [--timeout-ms <ms>] [--poll-interval-ms <ms>] [--json]
  • Polls job state until terminal (completed | failed | cancelled)
  • On completed: prints same content as result <job-id> + exits 0
  • On failed / cancelled: prints stored failure + exits non-zero
  • On timeout: prints current status + exits 124
  • Default timeout: 6 hours (current status --wait 4-minute default is too short for real delegated work)

New flag on task: --await

node scripts/codex-companion.mjs task --background --await --write "<prompt>"
  • Enqueues detached worker exactly as today (no change to recovery model)
  • Keeps the launching CLI process alive as an awaiter
  • Optional sparse progress lines every N seconds
  • When the worker reaches terminal state: prints final result + exits with terminal status

Used together with a background-style invocation, the caller-visible completion signal now matches actual daemon completion. The "background task notification = work done" mental model finally holds.

Documentation updates

  • `commands/rescue.md`: background examples switch to `task --background --await`. Removes the "subagent must never monitor or fetch results" instruction — with `--await`, monitoring happens inside the plugin CLI.
  • Launch message for plain `task --background` (no `--await`) adds an inline hint pointing to `--await` for callers that need completion notification.

Backward compatibility

  • Plain `task --background` (no `--await`) keeps current behavior unchanged.
  • All existing subcommands (`status`, `result`, `cancel`, `review`, `adversarial-review`) unchanged.
  • New API is purely additive.

Tests

  • `await ` for: completed, failed, cancelled, running-to-completed, timeout.
  • `task --background --await` for: output and exit behavior across terminal states.
  • Existing `task --background` plain-mode tests continue passing.

…n-bound process

Plain task --background returns the launching CLI in 1-2 seconds while the
daemon worker runs for 10-30+ minutes with no observable completion signal.
Callers must remember an out-of-band polling protocol; reminder-based fixes
are unreliable.

Add two additive APIs so the launching process can represent actual daemon
completion:

- await <job-id> [--timeout-ms <ms>] [--poll-interval-ms <ms>] [--json]
  - polls until terminal (completed / failed / cancelled)
  - on completed: prints same content as result <job-id>, exits 0
  - on failed / cancelled: prints stored failure, exits non-zero
  - on timeout: prints current status, exits 124
  - default timeout 6 hours (current status --wait 4 min is too short for
    real delegated work)

- task --background --await
  - enqueues detached worker as today
  - keeps launching CLI alive as awaiter
  - prints final result + exits with terminal status on completion

Used with a background-style invocation, the caller-visible completion
signal now matches actual daemon completion. The "background task
notification = work done" mental model finally holds.

Docs updates:
- commands/rescue.md: switch background examples to --background --await,
  drop "subagent must never monitor or fetch results" instruction
- agents/codex-rescue.md + skills/codex-cli-runtime/SKILL.md: sync
- launch message for plain --background adds hint pointing to --await

Backward compatibility:
- plain task --background (no --await) keeps current behavior
- all existing subcommands unchanged
- new API is purely additive

Tests:
- await <job-id> for completed / failed / cancelled / running-to-completed /
  timeout
- task --background --await output + exit behavior
- existing plain --background tests continue passing
@iamrain2008 iamrain2008 requested a review from a team May 25, 2026 12:32
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 423612c43b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


function renderQueuedTaskLaunch(payload) {
return `${payload.title} started in the background as ${payload.jobId}. Check /codex:status ${payload.jobId} for progress.\n`;
return `${payload.title} queued as ${payload.jobId}.\nThis command is only launch-complete; daemon completion is not signaled here.\nCheck /codex:status ${payload.jobId} for progress.\nFor completion notification, use: task --background --await ...\n`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use await <job-id> in background launch hint

After task --background finishes, the launch message tells users to run task --background --await ... for completion notification, but that command starts a new task instead of waiting on the queued job that was just created. In real usage this can duplicate expensive work or apply changes twice when users follow the suggested command literally. The hint here should point to await <job-id> (using the emitted job id) for observing completion of the existing job.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant