# OPTIONAL scheduler — use this ONLY if your repo already lives on GitHub. The portable, # runner-agnostic path is loop-run.sh (cron / Windows Task Scheduler / systemd / by hand) — # no GitHub Actions dependency. This file just wraps the same loop-run.sh idea in Actions. # Copy to .github/workflows/pr-watch.yml, PIN the action/CLI versions, add the # ANTHROPIC_API_KEY secret. The SCHEDULER is the authorizer (no auto-mode session in the # loop), and the child runs gated (--permission-mode dontAsk + a narrow allowlist), never # bypassPermissions on a shared runner. See references/claude-code-loops.md. name: pr-watch on: schedule: - cron: "*/10 * * * *" # every 10 min (matches loop.config.yaml cadence: 10m) workflow_dispatch: {} permissions: contents: write # commit STATE.md / run-log.md back pull-requests: write # post the at-most-one summary comment (L1 stays report-only) concurrency: group: pr-watch # never overlap two ticks cancel-in-progress: false jobs: tick: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # <-- pin to a SHA in production # Kill switch: a 'loop-pause' label on the repo, or a committed PAUSED sentinel. - name: Honor the kill switch id: gate env: { GH_TOKEN: "${{ github.token }}" } run: | if [ -f .loops/pr-watch/PAUSED ]; then echo "paused=1" >> "$GITHUB_OUTPUT"; fi if gh label list --limit 100 | grep -qi '^loop-pause'; then echo "paused=1" >> "$GITHUB_OUTPUT"; fi - name: Install Claude Code if: steps.gate.outputs.paused != '1' run: npm i -g @anthropic-ai/claude-code # <-- pin a version # The run: same prompt every tick (cache-friendly), gated with dontAsk + an # allowlist scoped to exactly what an L1 report loop needs (read-only + gh + STATE writes). - name: Run one tick if: steps.gate.outputs.paused != '1' env: ANTHROPIC_API_KEY: "${{ secrets.ANTHROPIC_API_KEY }}" run: | cd .loops/pr-watch claude -p "$(cat run.md)" \ --permission-mode dontAsk \ --append-system-prompt "$(cat STATE.md)" \ --allowedTools 'Bash(gh pr list:*)' 'Bash(gh pr view:*)' 'Bash(gh pr comment:*)' 'Read' 'Write(STATE.md)' 'Write(run-log.md)' \ --max-turns 30 - name: Persist STATE + run-log if: steps.gate.outputs.paused != '1' run: | git config user.name "pr-watch-loop" git config user.email "loop@users.noreply.github.com" git add .loops/pr-watch/STATE.md .loops/pr-watch/run-log.md git diff --cached --quiet || git commit -m "chore(loop): pr-watch tick $(date -u +%FT%TZ)" git push