diff --git a/.claude/skills/setup-agent-team/security.sh b/.claude/skills/setup-agent-team/security.sh index e48275ef..1c754500 100644 --- a/.claude/skills/setup-agent-team/security.sh +++ b/.claude/skills/setup-agent-team/security.sh @@ -35,7 +35,7 @@ elif [[ "${SPAWN_REASON}" == "triage" ]] && [[ -n "${SPAWN_ISSUE}" ]]; then ISSUE_NUM="${SPAWN_ISSUE}" WORKTREE_BASE="/tmp/spawn-worktrees/triage-${ISSUE_NUM}" TEAM_NAME="spawn-triage-${ISSUE_NUM}" - CYCLE_TIMEOUT=300 # 5 min for issue triage + CYCLE_TIMEOUT=600 # 10 min for issue triage elif [[ "${SPAWN_REASON}" == "review_all" ]]; then RUN_MODE="review_all" WORKTREE_BASE="/tmp/spawn-worktrees/security-review-all" diff --git a/.claude/skills/setup-agent-team/trigger-server.ts b/.claude/skills/setup-agent-team/trigger-server.ts index 7ddba6bf..38a72086 100644 --- a/.claude/skills/setup-agent-team/trigger-server.ts +++ b/.claude/skills/setup-agent-team/trigger-server.ts @@ -388,6 +388,22 @@ const server = Bun.serve({ } } + // Dedup: reject if a non-issue run with the same reason is already in progress + if (!issue) { + for (const [, run] of runs) { + if (!run.issue && run.reason === reason) { + return Response.json( + { + error: "run with this reason already in progress", + reason, + running: runs.size, + }, + { status: 409 } + ); + } + } + } + // Disable idle timeout for this request — the stream may be silent for // minutes at a time while Claude thinks. 0 = no timeout. server.timeout(req, 0); diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 3bce84fa..985584e1 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -4,8 +4,8 @@ on: issues: types: [opened, reopened] schedule: - # Consolidated review + scan — every 20 min - - cron: '*/20 * * * *' + # Consolidated review + scan — every 45 min (must exceed 35-min cycle timeout) + - cron: '0,45 * * * *' workflow_dispatch: inputs: mode: