run_hook wrote the envelope to stdin before draining and outside the timeout, so a hook that never reads a large envelope blocked the runner until it exited and was then marked failed with EPIPE. The drains ran one after the other, so a hook that filled stderr while stdout was still open deadlocked until the timeout killed it. Now stdin, stdout and stderr are serviced concurrently with the wait, all under the hook deadline; EPIPE on stdin is not a failure, and a grandchild holding the pipes open can't keep the permit past the deadline. Tests cover both cases plus stderr capture on failure. Co-authored-by: Grok Bot <grokbot@users.noreply.github.com>
1 file changedLine totals unavailable