diff --git a/.github/workflows/claude-issue-to-pr.yml b/.github/workflows/claude-issue-to-pr.yml index 64f4c3f..8aa8c68 100644 --- a/.github/workflows/claude-issue-to-pr.yml +++ b/.github/workflows/claude-issue-to-pr.yml @@ -39,9 +39,11 @@ jobs: steps: - name: Checkout + # Default shallow fetch (depth 1). The agent can commit and push on + # a shallow clone; `git log` / `git blame` aren't reached for by + # the current prompt. Bump to a deeper fetch only if we see the + # agent blocked on history lookups. uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 0 - name: Clone shared Harper skills # Pinned to a SHA (not `main`) so agent behavior is reproducible diff --git a/.github/workflows/claude-mention.yml b/.github/workflows/claude-mention.yml index 8c03738..1faf804 100644 --- a/.github/workflows/claude-mention.yml +++ b/.github/workflows/claude-mention.yml @@ -45,9 +45,11 @@ jobs: steps: - name: Checkout + # Default shallow fetch (depth 1). The agent can commit and push on + # a shallow clone; `git log` / `git blame` aren't reached for by + # the current prompt. Bump to a deeper fetch only if we see the + # agent blocked on history lookups. uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 0 - name: Clone shared Harper skills # Pinned to a SHA (not `main`) so agent behavior is reproducible diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index 12b07c5..9137119 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -43,6 +43,13 @@ jobs: steps: - name: Checkout + # Full history so the review agent can use `git blame` / `git log` + # / `git diff ...HEAD` for context — who wrote a line, how + # old it is, whether this PR's author has touched it before. Those + # signals materially improve review quality on non-trivial diffs. + # Paired with a tightly-scoped `Bash(git :*)` allowlist + # below (no `Bash(git:*)` — that would allow `git push --force`, + # `git reset --hard`, etc.). uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 @@ -119,7 +126,11 @@ jobs: claude_args: | --model claude-sonnet-4-6 --max-turns 24 - --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Read,Grep,Glob" + # Read-only allowlist. Git subcommands are scoped individually — + # deliberately NOT `Bash(git:*)`, which would permit `git push + # --force`, `git reset --hard`, etc. The subcommands listed here + # are all strictly read-only. + --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr view:*),Read,Grep,Glob,Bash(git diff:*),Bash(git log:*),Bash(git blame:*),Bash(git show:*)" prompt: | REPO: ${{ github.repository }} PR NUMBER: ${{ github.event.pull_request.number }} @@ -149,10 +160,26 @@ jobs: that executes PR code — the PR's tests are already checked separately. - The only allowed Bash commands are: - - `gh pr view` / `gh pr diff` — inspect the PR (already run - at start, you can re-invoke if needed) - - `gh pr comment` — post the final review comment + The allowed Bash commands are: + - `git diff ...HEAD` — the PR diff, local (no API + round-trip). `` is typically `origin/main`. + - `git log`, `git show` — history context. Use these to + understand WHY a line is the way it is before flagging + it. "This load-bearing check was added 3 years ago in + commit abc123 with a fix for bug X" is often the + difference between a blocker finding and a non-finding. + - `git blame ` (or with `-L start,end`) — who wrote + which lines, when. Especially useful for judging whether + a changed line is new code from this PR (fair review + target) or pre-existing code the PR merely touched + (per the layered scope, pre-existing gaps are NOT + blockers). + - `gh pr view` — PR metadata (title, body, author, + labels). Already run at start; re-invoke if needed. + - `gh pr comment` — post the top-level summary comment. + + Git subcommands are scoped individually on purpose — no + write operations are permitted. Do NOT write files during the review — not to `.claude-pr/`, not to `/tmp/`, not anywhere. The `Write` and `Edit` tools