From 1410e0c0cb12cd9a4404ccf96e580f9739f469e9 Mon Sep 17 00:00:00 2001 From: santisoutoo Date: Mon, 24 Aug 2026 20:27:56 +0200 Subject: [PATCH] fix: bound engine calls with a per-call timeout in run-engine.sh cursor-agent hung with zero output for 84 minutes during the review step of run 32749623046 (issue #85), and was only reaped when the job's 90-minute cap killed the entire run. Neither engine had a call-level timeout, so one hung call burned the whole job budget instead of failing fast into the caller's infra-failure / model-fallback handling. Wrap both engine invocations with `timeout -k 30 ${ENGINE_TIMEOUT_SECONDS:-900}` so a hung call dies well inside the job cap and the review step's cursor->cursor->opencode cascade can actually reach its fallback models. --- .github/agent/run-engine.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/agent/run-engine.sh b/.github/agent/run-engine.sh index 4520bbd..f7e309a 100755 --- a/.github/agent/run-engine.sh +++ b/.github/agent/run-engine.sh @@ -8,20 +8,30 @@ # protocol (AGENT_RESULT markers), so the surrounding workflow parses their # output identically. Auth: opencode reads auth.json from XDG_DATA_HOME; # cursor-agent reads CURSOR_API_KEY from the environment. +# +# Every invocation is bounded by ENGINE_TIMEOUT_SECONDS (default 900s): on +# 2026-08-24 a cursor-agent review call (run 32749623046, issue #85) hung +# with zero output for 84 minutes and was only reaped when the job's +# 90-minute cap killed the whole run. Neither engine had a call-level +# timeout, so one hung call silently burned the entire job budget instead +# of failing fast into the caller's infra-failure / model-fallback path. set -euo pipefail ENGINE="$1" MODEL="$2" PROMPT_FILE="$3" +TIMEOUT_SECONDS="${ENGINE_TIMEOUT_SECONDS:-900}" case "$ENGINE" in opencode) - opencode run --model "$MODEL" "$(cat "$PROMPT_FILE")" + # -k 30: if TERM doesn't stop it within 30s, send KILL — mirrors the + # orphan-process reap GitHub Actions had to do at the job-level timeout. + timeout -k 30 "$TIMEOUT_SECONDS" opencode run --model "$MODEL" "$(cat "$PROMPT_FILE")" ;; cursor) # -p: non-interactive print mode; --force: skip the workspace-trust and # command-approval prompts (required headless). - cursor-agent -p --force --model "$MODEL" "$(cat "$PROMPT_FILE")" + timeout -k 30 "$TIMEOUT_SECONDS" cursor-agent -p --force --model "$MODEL" "$(cat "$PROMPT_FILE")" ;; *) echo "::error::Unknown engine '$ENGINE'" >&2