Skip to content

bug(codex): background prompt capture holds hook pipes open #731

Description

@infantesromeroadrian

Pre-flight Checks

  • I have searched existing issues and this is not a duplicate
  • I understand this issue needs status:approved before a PR can be opened

Bug Description

The Codex UserPromptSubmit hook starts prompt persistence in a background subshell, but only redirects curl output. The subshell itself inherits the hook's captured stdout and stderr file descriptors. Codex waits for captured pipe EOF under the handler timeout, so a slow or stalled POST /prompts can make the hook report timed out after 2s even though the foreground shell has already exited.

Steps to Reproduce

  1. Install or check out the Codex plugin at 8058269b (plugin/codex version 0.1.2).
  2. Start a loopback HTTP server on ENGRAM_PORT that accepts POST /prompts but delays its response for longer than two seconds.
  3. Invoke plugin/codex/scripts/user-prompt-submit.sh with a valid cwd, session_id, and prompt, while capturing stdout and stderr as Codex does.
  4. Observe that the foreground shell exits quickly, but the captured pipes remain open until the background curl --max-time 2 exits.

Expected Behavior

Prompt persistence remains fail-silent and non-blocking. The hook should return valid JSON immediately and stay comfortably within its existing two-second handler budget, regardless of POST /prompts response latency.

Actual Behavior

The background subshell keeps the capture pipes open. In a controlled reproduction, the foreground shell exited in 0.039 seconds while captured output reached EOF only after 2.072 seconds. Codex then reported:

UserPromptSubmit hook (failed)
error: hook timed out after 2s

Operating System

macOS

Engram Version

1.19.0+harness.1 (Codex plugin 0.1.2 from upstream commit 8058269; the defect is still present on current main)

Agent / Client

Other (OpenAI Codex)

Relevant Logs

foreground shell exit: 0.039s
captured pipe EOF:      2.072s
no-prompt control:      0.040s
fast-POST control:      0.072s

Additional Context

The minimal fix is to redirect stdin, stdout, and stderr on the entire detached subshell before &:

(
  # detect project and POST /prompts
) </dev/null >/dev/null 2>&1 &

With an intentionally slow server, that form returned in 0.031 seconds. Increasing the hook timeout only masks the descriptor leak; it does not restore the intended non-blocking behavior. A regression test can execute the public hook interface against a delayed loopback server, capture stdout/stderr, assert that the POST was attempted, and require sub-second return.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions