From 190a779f6d3c237a3ac50601d672168180f1d58c Mon Sep 17 00:00:00 2001 From: shreyash0502 Date: Tue, 14 Apr 2026 00:25:19 +0530 Subject: [PATCH 1/3] ci: add resolved-thread dedupe + opt-out label to claude code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two changes to the claude-code-review workflow: 1. Resolved-thread dedupe — fetch existing review threads via GraphQL before reviewing and apply a posting gate to every inline comment: - Skip if an unresolved thread already covers the same (path, line, topic) - Skip resolved threads where the fix was applied or author declined - Unresolve the original thread (no new comment) if a resolved actionable ask was not addressed in the current code 2. Opt-out label — `skip-claude-review` on a PR suppresses the workflow on subsequent commits. Removing the label re-enables it. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/claude-code-review.yml | 97 +++++++++++++++++++++++- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 0e60bd899..c188efbad 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -12,6 +12,11 @@ on: jobs: claude-review: + # Opt-out: PR authors can apply the `skip-claude-review` label to suppress + # the bot on subsequent commits. Removing the label re-enables review on + # the next push. + if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-claude-review') }} + # Optional: Filter by PR author # if: | # github.event.pull_request.user.login == 'external-contributor' || @@ -39,9 +44,95 @@ jobs: plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' plugins: 'code-review@claude-code-plugins' prompt: | - Read CLAUDE.md at the repo root first — it references Agents.md and agent_docs/ which contain all project conventions, architecture, and rules. Follow every convention defined there during your review. + You are reviewing PR #${{ github.event.pull_request.number }} in ${{ github.repository }}. + + STEP 1 — Fetch existing review threads and issue comments BEFORE reviewing. + Run this GraphQL query and read the results carefully: + + gh api graphql -f query=' + query($owner:String!,$repo:String!,$num:Int!){ + repository(owner:$owner,name:$repo){ + pullRequest(number:$num){ + reviewThreads(first:100){ + nodes{ + id + isResolved + path + line + comments(first:20){ nodes{ author{login} body }} + } + } + comments(first:100){ + nodes{ author{login} body } + } + } + } + }' \ + -f owner=${{ github.repository_owner }} \ + -f repo=${{ github.event.repository.name }} \ + -F num=${{ github.event.pull_request.number }} + + STEP 2 — Build a set of issues already covered by prior bot comments + (threads whose first comment is authored by a bot or this workflow's + identity). Treat each prior comment as "(path, line, topic)". + + STEP 3 — Dedupe policy. For each issue you are about to raise, look for a + prior thread covering the same (path, line, topic): + + • If an UNRESOLVED thread exists for this (path, line, topic) → SKIP. + Don't duplicate an open thread; the user will get to it. + + • If a RESOLVED thread exists for this (path, line, topic), classify the + ORIGINAL comment: + (a) Actionable ask (it requested the author to change something — + e.g. "rename X", "use Y instead", "extract this", "add null check"): + → Read the CURRENT code at that location. + - If the requested change WAS made → SKIP (user fixed it). + - If the requested change was NOT made → UNRESOLVE the + original thread (do NOT post a new comment). Use: + + gh api graphql -f query=' + mutation($id:ID!){ + unresolveReviewThread(input:{threadId:$id}){ + thread{ id isResolved } + } + }' -f id= + + where is the thread.id from STEP 1. + → If thread replies show the author/maintainer explicitly + disagreed or declined ("won't fix", "intentional", "ship it + anyway") → SKIP regardless of code state. The decision was made. + (b) Informational / nit / praise / question (not an ask for a change): + → SKIP. Resolution means acknowledged; don't re-post and don't + unresolve. + + • If a prior comment raised a DIFFERENT topic on the same line → OK to post. + • New issues the prior review missed entirely → post normally. + + STEP 4 — Read CLAUDE.md at the repo root first — it references Agents.md + and agent_docs/ which contain all project conventions, architecture, and + rules. Follow every convention defined there during your review. + + STEP 5 — Run the review. The /code-review plugin below will analyze the PR + and propose inline comments. You MUST apply STEP 3 as a POSTING GATE on + every single comment the plugin wants to create — this includes comments + the plugin would post via mcp__github_inline_comment__create_inline_comment + or via `gh pr comment`. Concretely: + + BEFORE every call to mcp__github_inline_comment__create_inline_comment: + 1. Compute (path, line, topic) of the comment you are about to post. + 2. Look it up in the dedupe set from STEP 1. + 3. Apply STEP 3. If STEP 3 says SKIP → do NOT call the tool at all. + If STEP 3 says UNRESOLVE → call the unresolveReviewThread mutation + INSTEAD of posting a new comment. + 4. Only post if STEP 3 says OK to post. + + The same gate applies to the summary comment: when summarizing, do not + list issues whose threads you chose to skip or unresolve — summarize + only genuinely new findings and any threads you unresolved. + + Now run the plugin: /code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }} --comment use_sticky_comment: true claude_args: | - --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)" - + --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*),Bash(gh api graphql:*),Bash(gh api:*)" From 8f770fec87526468c4099d06ebdfdba5fe398f1b Mon Sep 17 00:00:00 2001 From: shreyash0502 Date: Tue, 14 Apr 2026 00:34:43 +0530 Subject: [PATCH 2/3] chore(skill): forbid source PR refs and @-mentions inside doc file edits The enhance-claude-docs skill was baking provenance like (Source: PR #184) and reviewer @-mentions directly into the documentation files (e.g., agent_docs/conventions.md), creating permanent cross-link noise in source PRs and burning contributor handles into long-lived docs. Updates Step 6 with explicit content rules for doc edits: no #N refs, no @-mentions, no verbatim quoting. Provenance stays in the PR body and terminal output where it belongs. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/skills/enhance-claude-docs/SKILL.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.claude/skills/enhance-claude-docs/SKILL.md b/.claude/skills/enhance-claude-docs/SKILL.md index 6e38f7973..8c82ced7f 100644 --- a/.claude/skills/enhance-claude-docs/SKILL.md +++ b/.claude/skills/enhance-claude-docs/SKILL.md @@ -175,6 +175,16 @@ If actionable insights exist: 5. For `agent_docs/architecture.md`, update tables or sections as appropriate. 6. For `Agents.md`, update the quick reference or add new sections. +### Content rules for doc edits + +The text written into the doc files must be self-contained guidance, not a changelog. + +- **Do not include source PR references** (`#327`, `Source: PR #184`, etc.) in the file content — they create permanent cross-link noise in the source PRs. +- **Do not include @-mentions** (`@swati354`, `reviewer @maninder noted`) in the file content — handles don't belong in long-lived docs. +- Rewrite each insight as a generalized rule/convention; don't quote the original comment verbatim. + +Provenance belongs in the PR body (Step 7) and the terminal output (Step 8) — not inside the docs. + --- ## Step 7: Create or Update PR From 77d1306e08053a038490afd9834a50cb97bbc53a Mon Sep 17 00:00:00 2001 From: shreyash0502 Date: Tue, 14 Apr 2026 00:55:39 +0530 Subject: [PATCH 3/3] ci(review): suppress summary comment on no-op runs Previous prompt told the bot to "summarize" without saying when, which made it post a "No new issues" filler summary on runs where no action was taken. The current uipath-typescript workflow posts zero plugin summaries today; this prompt would have changed that behavior. Now: post a summary ONLY if the run posted a new inline comment or unresolved a thread. Otherwise stay silent. Preserves the audit-log value (notifying the author when their thread was unresolved) without adding noise on no-op pushes. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/claude-code-review.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index c188efbad..449fd6bd4 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -127,9 +127,15 @@ jobs: INSTEAD of posting a new comment. 4. Only post if STEP 3 says OK to post. - The same gate applies to the summary comment: when summarizing, do not - list issues whose threads you chose to skip or unresolve — summarize - only genuinely new findings and any threads you unresolved. + Top-level summary comment — POST ONLY IF the run produced an action. + An action means: (a) you posted at least one new inline comment, OR + (b) you unresolved at least one previously-resolved thread. If neither + happened, post NO summary comment at all — stay completely silent. + Do NOT post filler summaries like "No new issues" or "Nothing to report". + + When you DO post a summary, list only: (a) the new findings you posted + this run, and (b) any threads you unresolved this run. Do not list + issues you skipped via the dedupe gate. Now run the plugin: /code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }} --comment