From 3572593d16616da6093436fe7e37c09d46e53500 Mon Sep 17 00:00:00 2001 From: Aditya Purandare Date: Sun, 16 Aug 2026 20:20:25 +0530 Subject: [PATCH] fix(trajectory-plugin): bound capture-hook call to avoid lost hook output capture-with-serve.sh execed trajectory capture-hook with no timeout of its own, relying entirely on Claude Code's outer hook timeout. When the shared serve daemon is busy for 20-30s+ on unrelated work (batch repairs, marker evaluation, publish retries), the hook gets hard-killed by the host tool and its output is discarded. Wrap the call in timeout/gtimeout (default 5s, overridable via TRAJECTORY_CAPTURE_HOOK_TIMEOUT_SECONDS) so it fails open instead. Co-Authored-By: Claude Sonnet 5 --- plugin/trajectory/hooks/capture-with-serve.sh | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/plugin/trajectory/hooks/capture-with-serve.sh b/plugin/trajectory/hooks/capture-with-serve.sh index bcbdd54..6566bdf 100755 --- a/plugin/trajectory/hooks/capture-with-serve.sh +++ b/plugin/trajectory/hooks/capture-with-serve.sh @@ -25,4 +25,25 @@ if [ ! -x "$BINARY" ]; then exit 0 fi -exec "$BINARY" capture-hook --wait-notify "$WAIT_NOTIFY" "$EVENT_TYPE" +# The shared serve daemon can be busy for tens of seconds on other work (batch +# repairs, marker evaluation, publish retries). Without a bound here, Claude +# Code's own hook timeout eventually SIGKILLs this process and discards the +# hook's output. Fail open before that happens instead. +CAPTURE_TIMEOUT="${TRAJECTORY_CAPTURE_HOOK_TIMEOUT_SECONDS:-5}" +case "$CAPTURE_TIMEOUT" in + ''|*[!0-9]*) CAPTURE_TIMEOUT=5 ;; +esac + +TIMEOUT_BIN="" +for candidate in timeout gtimeout; do + if command -v "$candidate" >/dev/null 2>&1; then + TIMEOUT_BIN="$candidate" + break + fi +done + +if [ -n "$TIMEOUT_BIN" ]; then + "$TIMEOUT_BIN" "$CAPTURE_TIMEOUT" "$BINARY" capture-hook --wait-notify "$WAIT_NOTIFY" "$EVENT_TYPE" || exit 0 +else + exec "$BINARY" capture-hook --wait-notify "$WAIT_NOTIFY" "$EVENT_TYPE" +fi