From 61f8d1e9f30bb72074aaec8629ce212338c7bf41 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 22 Apr 2026 23:39:25 -0700 Subject: [PATCH 1/2] ci(review, mention): unblock AI-authored PRs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two gaps, both preventing reviews on AI-authored PRs: 1. claude-review.yml: extend the author_association gate to also allow PRs opened by claude[bot] (our issue-to-PR pipeline). The old gate skipped the review job entirely — AI-authored code was merging with no review, which is the OPPOSITE of what we want. See PR #55 which landed unreviewed due to this. 2. claude-mention.yml: inject PR/issue number, URL, kind, commenter login, and the full comment body into the prompt. In the pinned action version the triggering comment is not reliably forwarded as context, so an @claude mention like "review this PR" was producing "I don't see a specific task in this mention, could you share the PR number?" — the agent had no idea which PR fired the workflow. Gate safety: github.event.pull_request.user.login is set by GitHub's auth system from the actual PR author. GitHub reserves the [bot] suffix for apps and enforces globally unique app slugs, so claude[bot] is specifically Anthropic's Claude app (which has to be installed in the HarperFast org to open PRs here). Fork-triggered workflow runs have no access to secrets regardless, so even a hypothetical bypass has a read-only blast radius. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/claude-mention.yml | 30 ++++++++++++++++++++++++++-- .github/workflows/claude-review.yml | 9 ++++++--- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/.github/workflows/claude-mention.yml b/.github/workflows/claude-mention.yml index 5c84eed..b2f5aa4 100644 --- a/.github/workflows/claude-mention.yml +++ b/.github/workflows/claude-mention.yml @@ -83,11 +83,37 @@ jobs: --model claude-sonnet-4-6 --max-turns 48 --allowedTools "Read,Write,Edit,Grep,Glob,mcp__github_inline_comment__create_inline_comment,Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*),Bash(gh pr checkout:*),Bash(gh pr create:*),Bash(gh issue view:*),Bash(gh issue comment:*),Bash(git:*),Bash(npm install:*),Bash(npm ci:*),Bash(npm run:*),Bash(npm test:*),Bash(bun install:*),Bash(bun run:*),Bash(bun test:*),Bash(npx:*)" - # In agent mode the action uses the triggering comment as the - # prompt. The text below layers supplemental context on top. + # In agent mode the action can use the triggering comment as the + # prompt, but we inline it explicitly below to guarantee the agent + # always has PR/issue number, URL, and the commenter's exact + # request — without these, the agent has been observed to respond + # "I don't see a specific task in this mention, could you share + # the PR number?" which defeats the whole point of the workflow. prompt: | You were invoked via an `@claude` mention on ${{ github.repository }}. + ## Mention context + + - Repo: ${{ github.repository }} + - Target number: #${{ github.event.issue.number || github.event.pull_request.number }} + - Target URL: ${{ github.event.issue.html_url || github.event.pull_request.html_url }} + - Target kind: ${{ github.event.issue.pull_request && 'pull request' || (github.event.pull_request && 'pull request' || 'issue') }} + - Commenter: @${{ github.event.comment.user.login }} + + The commenter wrote: + + > ${{ github.event.comment.body }} + + Start by reading the target so you have real context: + - For a PR: `gh pr view ` then `gh pr diff ` if you need + the changes. + - For an issue: `gh issue view `. + + Then act on the request. If the request is "review this PR", + post the review as a single `gh pr comment` following the + review discipline in `.github/review-scopes/universal.md` (in + this repo) — do NOT treat review as a code-edit task. + ## Conventions Read `CLAUDE.md` in the repo root first. Its "Code Conventions" diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index b000e91..a24a9d6 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -10,12 +10,15 @@ concurrency: jobs: review: - # Only review PRs authored by HarperFast org members / collaborators. - # External PRs are not auto-reviewed — a maintainer can opt one in later - # via an @claude mention (handled by a separate workflow). + # Review PRs authored by HarperFast org members / collaborators AND + # PRs opened by our own issue-to-PR bot (claude[bot]) — AI-authored PRs + # need review MOST, not least. External human PRs are not auto-reviewed; + # a maintainer can opt one in via an `@claude` mention (handled by a + # separate workflow). if: >- contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.pull_request.author_association) + || github.event.pull_request.user.login == 'claude[bot]' runs-on: ubuntu-latest # Bumped from 10 to 15. We've observed the Claude review step stall on a # single long-running API call inside the 10-min window on substantial From c49895d1167c3f9f8926a7d9252d730632328ac5 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 22 Apr 2026 23:49:17 -0700 Subject: [PATCH 2/2] ci(mention): render multi-line comments correctly; note action-version TODO Review feedback on #57: 1. A single `>` markdown blockquote only marks its first line as quoted; subsequent lines render as plain paragraphs. For a multi-line @claude request the agent still reads all content, but the prompt's visual framing is wrong. Swap to a fenced code block so the entire comment body renders as quoted text regardless of line count. 2. Add a TODO comment near the inline-injection block so the reason it exists doesn't become mystery-cruft six months from now. When claude-code-action reliably forwards the triggering comment as the prompt, this wrapper can collapse back to supplemental context. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/claude-mention.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/claude-mention.yml b/.github/workflows/claude-mention.yml index b2f5aa4..7ffd99c 100644 --- a/.github/workflows/claude-mention.yml +++ b/.github/workflows/claude-mention.yml @@ -89,6 +89,10 @@ jobs: # request — without these, the agent has been observed to respond # "I don't see a specific task in this mention, could you share # the PR number?" which defeats the whole point of the workflow. + # + # TODO: revisit if a future claude-code-action release reliably + # forwards the triggering comment as the prompt. This inline + # injection can then collapse back to supplemental context. prompt: | You were invoked via an `@claude` mention on ${{ github.repository }}. @@ -100,9 +104,11 @@ jobs: - Target kind: ${{ github.event.issue.pull_request && 'pull request' || (github.event.pull_request && 'pull request' || 'issue') }} - Commenter: @${{ github.event.comment.user.login }} - The commenter wrote: + The commenter wrote (verbatim, including any multi-line content): - > ${{ github.event.comment.body }} + ``` + ${{ github.event.comment.body }} + ``` Start by reading the target so you have real context: - For a PR: `gh pr view ` then `gh pr diff ` if you need