Pre-flight Checks
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
- Install or check out the Codex plugin at
8058269b (plugin/codex version 0.1.2).
- Start a loopback HTTP server on
ENGRAM_PORT that accepts POST /prompts but delays its response for longer than two seconds.
- Invoke
plugin/codex/scripts/user-prompt-submit.sh with a valid cwd, session_id, and prompt, while capturing stdout and stderr as Codex does.
- 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.
Pre-flight Checks
status:approvedbefore a PR can be openedBug Description
The Codex
UserPromptSubmithook starts prompt persistence in a background subshell, but only redirectscurloutput. 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 stalledPOST /promptscan make the hook reporttimed out after 2seven though the foreground shell has already exited.Steps to Reproduce
8058269b(plugin/codexversion0.1.2).ENGRAM_PORTthat acceptsPOST /promptsbut delays its response for longer than two seconds.plugin/codex/scripts/user-prompt-submit.shwith a validcwd,session_id, andprompt, while capturing stdout and stderr as Codex does.curl --max-time 2exits.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 /promptsresponse 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:
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
Additional Context
The minimal fix is to redirect stdin, stdout, and stderr on the entire detached subshell before
&: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.