From b24b9e191de165500446c81639afd1c9aab8385c Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 26 Mar 2026 20:46:24 +0800 Subject: [PATCH 1/7] enhance /review: add verification step, false positive control, and PR comment integration Add three enhancements to the /review skill to improve review quality and GitHub integration: - False positive exclusion list and structured output format for review agents - Step 2.5: deduplicate findings then verify each with independent parallel agents - Step 4: post inline comments on PRs via `gh api` when `--comment` flag is set Closes #2684 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../core/src/skills/bundled/review/SKILL.md | 105 +++++++++++++++++- 1 file changed, 101 insertions(+), 4 deletions(-) diff --git a/packages/core/src/skills/bundled/review/SKILL.md b/packages/core/src/skills/bundled/review/SKILL.md index 957031c7a..6d9db09b4 100644 --- a/packages/core/src/skills/bundled/review/SKILL.md +++ b/packages/core/src/skills/bundled/review/SKILL.md @@ -1,6 +1,6 @@ --- name: review -description: Review changed code for correctness, security, code quality, and performance. Use when the user asks to review code changes, a PR, or specific files. Invoke with `/review`, `/review `, or `/review `. +description: Review changed code for correctness, security, code quality, and performance. Use when the user asks to review code changes, a PR, or specific files. Invoke with `/review`, `/review `, `/review `, or `/review --comment` to post inline comments on the PR. allowedTools: - task - run_shell_command @@ -15,7 +15,11 @@ You are an expert code reviewer. Your job is to review code changes and provide ## Step 1: Determine what to review -Your goal here is to understand the scope of changes so you can dispatch agents effectively in Step 2. Based on the arguments provided: +Your goal here is to understand the scope of changes so you can dispatch agents effectively in Step 2. + +First, check if `--comment` flag is present in the arguments. If so, note that findings should be posted as PR inline comments in Step 4. The `--comment` flag is only valid when reviewing a PR (not local changes or a file path). Remove `--comment` from the arguments before proceeding. + +Based on the remaining arguments: - **No arguments**: Review local uncommitted changes - Run `git diff` and `git diff --staged` to get all changes @@ -36,6 +40,26 @@ Launch **four parallel review agents** to analyze the changes from different ang **IMPORTANT**: Do NOT paste the full diff into each agent's prompt — this duplicates it 4x. Instead, give each agent the command to obtain the diff, a concise summary of what the changes are about, and its review focus. Each agent can read files and search the codebase on its own. +**Do NOT flag:** +- Pre-existing issues in unchanged code (focus on the diff only) +- Style, formatting, or naming that matches surrounding codebase conventions +- Pedantic nitpicks that a senior engineer would not flag +- Issues that a linter or type checker would catch automatically +- Subjective "consider doing X" suggestions that aren't real problems +- If you're unsure whether something is a problem, do NOT report it + +Each agent must return findings in this structured format (one per issue): + +``` +- **File:** : +- **Issue:** +- **Impact:** +- **Suggested fix:** +- **Severity:** Critical | Suggestion | Nice to have +``` + +If an agent finds no issues in its dimension, it should explicitly return "No issues found." + ### Agent 1: Correctness & Security Focus areas: @@ -80,15 +104,47 @@ Focus areas: - Unexpected side effects or hidden coupling - Anything else that looks off — trust your instincts +## Step 2.5: Deduplicate and verify + +### Deduplication + +Before verification, merge findings that refer to the same issue (same file, same line range, same root cause) even if reported by different agents. Keep the most detailed description and note which agents flagged it. + +### Independent verification + +For each **unique** finding, launch an **independent verification agent** (run all verification agents in parallel). + +Each verification agent receives: +- The finding description (what's wrong, file, line) +- The command to obtain the diff (as determined in Step 1) +- Access to read files and search the codebase + +Each verification agent must **independently** (without seeing other agents' findings): +1. Read the actual code at the referenced file and line +2. Check surrounding context — callers, type definitions, tests, related modules +3. Verify the issue is not a false positive — reject if it falls under any of these: + - Pre-existing issue in unchanged code + - Style/naming that matches surrounding conventions + - Pedantic nitpick a senior engineer would not flag + - Issue a linter or type checker would catch automatically + - Subjective suggestion that isn't a real problem +4. Return a verdict: + - **confirmed** — with severity: Critical, Suggestion, or Nice to have + - **rejected** — with a one-line reason why it's not a real issue + +**When uncertain, lean toward rejecting.** The goal is high signal, low noise — it's better to miss a minor suggestion than to report a false positive. + +**After all verification agents complete:** remove all rejected findings. Only confirmed findings proceed to Step 3. + ## Step 3: Restore environment and present findings If you checked out a PR branch in Step 1, restore the original state first: check out the original branch, `git stash pop` if changes were stashed, and remove the temp file. -Then combine results from all four agents into a single, well-organized review. Use this format: +Then present the confirmed findings from Step 2.5 as a single, well-organized review. Use this format: ### Summary -A 1-2 sentence overview of the changes and overall assessment. +A 1-2 sentence overview of the changes and overall assessment. Include verification stats: "X findings reported, Y confirmed after independent verification." ### Findings @@ -113,6 +169,47 @@ One of: - **Request changes** — Has critical issues that need fixing - **Comment** — Has suggestions but no blockers +## Step 4: Post PR inline comments (only if `--comment` flag was set) + +Skip this step if `--comment` was not specified or the review target is not a PR. + +First, get the repository owner/repo and the latest commit SHA on the PR branch: + +```bash +gh repo view --json owner,name --jq '"\(.owner.login)/\(.name)"' +git rev-parse HEAD +``` + +Then, for each confirmed finding, post an **inline comment** on the specific file and line using `gh api`: + +```bash +gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ + -f body="**[{severity}]** {issue description} + +{suggested fix}" \ + -f commit_id="{commit_sha}" \ + -f path="{file_path}" \ + -F line={line_number} +``` + +**Important rules:** +- Only post **ONE comment per unique issue** — do not duplicate across lines +- Keep each comment concise and actionable +- Include the severity tag (Critical/Suggestion/Nice to have) at the start of each comment +- Include the suggested fix in the comment body when available + +After posting all inline comments, submit an overall review summary using: + +```bash +gh pr review {pr_number} --comment --body "{summary + verdict}" +``` + +If there are **no confirmed findings**, post a single comment: + +```bash +gh pr review {pr_number} --comment --body "No issues found. LGTM! ✅" +``` + ## Guidelines - Be specific and actionable. Avoid vague feedback like "could be improved." From 3ce0d42c83e51474e0a6a4b14faa8745693bfe8e Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 26 Mar 2026 20:53:40 +0800 Subject: [PATCH 2/7] fix: resolve review feedback issues in /review skill - Add `side="RIGHT"` param and multi-line support (start_line + line) to gh api calls - Add fallback: if inline comment fails, include finding in overall review summary - Warn user when `--comment` is used with non-PR target instead of silently ignoring - Move environment restoration from Step 3 to new Step 5, after Step 4 posts comments, to ensure `git rev-parse HEAD` returns the correct PR commit SHA Co-Authored-By: Claude Opus 4.6 (1M context) --- .../core/src/skills/bundled/review/SKILL.md | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/packages/core/src/skills/bundled/review/SKILL.md b/packages/core/src/skills/bundled/review/SKILL.md index 6d9db09b4..b00a6f45d 100644 --- a/packages/core/src/skills/bundled/review/SKILL.md +++ b/packages/core/src/skills/bundled/review/SKILL.md @@ -17,7 +17,7 @@ You are an expert code reviewer. Your job is to review code changes and provide Your goal here is to understand the scope of changes so you can dispatch agents effectively in Step 2. -First, check if `--comment` flag is present in the arguments. If so, note that findings should be posted as PR inline comments in Step 4. The `--comment` flag is only valid when reviewing a PR (not local changes or a file path). Remove `--comment` from the arguments before proceeding. +First, check if `--comment` flag is present in the arguments. If so, note that findings should be posted as PR inline comments in Step 4. Remove `--comment` from the arguments before proceeding. If `--comment` is used but the review target is not a PR, warn the user: "Warning: `--comment` flag is ignored because the review target is not a PR." and continue without it. Based on the remaining arguments: @@ -136,11 +136,9 @@ Each verification agent must **independently** (without seeing other agents' fin **After all verification agents complete:** remove all rejected findings. Only confirmed findings proceed to Step 3. -## Step 3: Restore environment and present findings +## Step 3: Present findings -If you checked out a PR branch in Step 1, restore the original state first: check out the original branch, `git stash pop` if changes were stashed, and remove the temp file. - -Then present the confirmed findings from Step 2.5 as a single, well-organized review. Use this format: +Present the confirmed findings from Step 2.5 as a single, well-organized review. Use this format: ### Summary @@ -183,15 +181,30 @@ git rev-parse HEAD Then, for each confirmed finding, post an **inline comment** on the specific file and line using `gh api`: ```bash +# Single-line finding: gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ -f body="**[{severity}]** {issue description} {suggested fix}" \ -f commit_id="{commit_sha}" \ -f path="{file_path}" \ - -F line={line_number} + -F line={line_number} \ + -f side="RIGHT" + +# Multi-line finding (e.g., line range 42-50): +gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ + -f body="**[{severity}]** {issue description} + +{suggested fix}" \ + -f commit_id="{commit_sha}" \ + -f path="{file_path}" \ + -F start_line={start_line} \ + -F line={end_line} \ + -f side="RIGHT" ``` +If posting an inline comment fails (e.g., line not part of the diff, auth error), include the finding in the overall review summary comment instead. + **Important rules:** - Only post **ONE comment per unique issue** — do not duplicate across lines - Keep each comment concise and actionable @@ -210,6 +223,12 @@ If there are **no confirmed findings**, post a single comment: gh pr review {pr_number} --comment --body "No issues found. LGTM! ✅" ``` +## Step 5: Restore environment + +If you checked out a PR branch in Step 1, restore the original state now: check out the original branch, `git stash pop` if changes were stashed, and remove the temp file. + +This step runs **after** Step 4 to ensure the PR branch is still checked out when posting inline comments (Step 4 needs the correct commit SHA from the PR branch). + ## Guidelines - Be specific and actionable. Avoid vague feedback like "could be improved." From 6fb752a82353a64e8c153152ae0caffeaf730a40 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 29 Mar 2026 08:07:21 +0800 Subject: [PATCH 3/7] fix: address all review feedback from Qwen-Code + GLM-5.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes for 7 issues raised in PR review: 1. [Critical] Extract exclusion criteria into shared "Exclusion Criteria" section, referenced by both Step 2 and Step 2.5 to prevent drift 2. [Suggestion] Specify exact token matching for --comment flag parsing (not substring match, ignore --commentary etc.) 3. [Suggestion] Replace `git rev-parse HEAD` with `gh pr view --json headRefOid` to get correct remote PR HEAD SHA 4. [Suggestion] Use heredoc to construct comment body with real newlines instead of broken \n escape in -f flag 5. [Nice to have] Add batch limit of 10 for parallel verification agents 6. [Nice to have] Add error handling: skip Step 4 if gh commands fail 7. [Suggestion] Issue #4 (endpoint) deferred — current approach documented Co-Authored-By: Claude Opus 4.6 (1M context) --- .../core/src/skills/bundled/review/SKILL.md | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/packages/core/src/skills/bundled/review/SKILL.md b/packages/core/src/skills/bundled/review/SKILL.md index b00a6f45d..2e0937c4a 100644 --- a/packages/core/src/skills/bundled/review/SKILL.md +++ b/packages/core/src/skills/bundled/review/SKILL.md @@ -17,7 +17,7 @@ You are an expert code reviewer. Your job is to review code changes and provide Your goal here is to understand the scope of changes so you can dispatch agents effectively in Step 2. -First, check if `--comment` flag is present in the arguments. If so, note that findings should be posted as PR inline comments in Step 4. Remove `--comment` from the arguments before proceeding. If `--comment` is used but the review target is not a PR, warn the user: "Warning: `--comment` flag is ignored because the review target is not a PR." and continue without it. +First, parse the `--comment` flag: split the arguments by whitespace, and if any token is exactly `--comment` (not a substring match — ignore tokens like `--commentary`), set the comment flag and remove that token from the argument list. If `--comment` is set but the review target is not a PR, warn the user: "Warning: `--comment` flag is ignored because the review target is not a PR." and continue without it. Based on the remaining arguments: @@ -40,13 +40,7 @@ Launch **four parallel review agents** to analyze the changes from different ang **IMPORTANT**: Do NOT paste the full diff into each agent's prompt — this duplicates it 4x. Instead, give each agent the command to obtain the diff, a concise summary of what the changes are about, and its review focus. Each agent can read files and search the codebase on its own. -**Do NOT flag:** -- Pre-existing issues in unchanged code (focus on the diff only) -- Style, formatting, or naming that matches surrounding codebase conventions -- Pedantic nitpicks that a senior engineer would not flag -- Issues that a linter or type checker would catch automatically -- Subjective "consider doing X" suggestions that aren't real problems -- If you're unsure whether something is a problem, do NOT report it +Apply the **Exclusion Criteria** (defined at the end of this document) — do NOT flag anything that matches those criteria. Each agent must return findings in this structured format (one per issue): @@ -112,22 +106,19 @@ Before verification, merge findings that refer to the same issue (same file, sam ### Independent verification -For each **unique** finding, launch an **independent verification agent** (run all verification agents in parallel). +For each **unique** finding, launch an **independent verification agent**. Run verification agents in parallel, but if there are more than 10 unique findings, batch them in groups of 10 to avoid resource exhaustion. Each verification agent receives: + - The finding description (what's wrong, file, line) - The command to obtain the diff (as determined in Step 1) - Access to read files and search the codebase Each verification agent must **independently** (without seeing other agents' findings): + 1. Read the actual code at the referenced file and line 2. Check surrounding context — callers, type definitions, tests, related modules -3. Verify the issue is not a false positive — reject if it falls under any of these: - - Pre-existing issue in unchanged code - - Style/naming that matches surrounding conventions - - Pedantic nitpick a senior engineer would not flag - - Issue a linter or type checker would catch automatically - - Subjective suggestion that isn't a real problem +3. Verify the issue is not a false positive — reject if it matches any item in the **Exclusion Criteria** 4. Return a verdict: - **confirmed** — with severity: Critical, Suggestion, or Nice to have - **rejected** — with a one-line reason why it's not a real issue @@ -171,21 +162,31 @@ One of: Skip this step if `--comment` was not specified or the review target is not a PR. -First, get the repository owner/repo and the latest commit SHA on the PR branch: +First, get the repository owner/repo and the PR's HEAD commit SHA: ```bash gh repo view --json owner,name --jq '"\(.owner.login)/\(.name)"' -git rev-parse HEAD +gh pr view {pr_number} --json headRefOid --jq '.headRefOid' ``` +**Important:** Use `gh pr view --json headRefOid` instead of `git rev-parse HEAD` — the local branch may be behind the remote, and the GitHub API requires the exact remote HEAD SHA. If either command fails, inform the user and skip Step 4. + Then, for each confirmed finding, post an **inline comment** on the specific file and line using `gh api`: +Construct the comment body as a shell variable first, then pass it to `gh api`: + ```bash +# Build comment body (use actual newlines, not \n): +BODY=$(cat < Date: Sun, 29 Mar 2026 20:10:51 +0800 Subject: [PATCH 4/7] fix: remove $() command substitution blocked by run_shell_command, align verdict with gh pr review action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace heredoc `BODY=$(cat < --- .../core/src/skills/bundled/review/SKILL.md | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/core/src/skills/bundled/review/SKILL.md b/packages/core/src/skills/bundled/review/SKILL.md index 2e0937c4a..268cdb164 100644 --- a/packages/core/src/skills/bundled/review/SKILL.md +++ b/packages/core/src/skills/bundled/review/SKILL.md @@ -173,20 +173,14 @@ gh pr view {pr_number} --json headRefOid --jq '.headRefOid' Then, for each confirmed finding, post an **inline comment** on the specific file and line using `gh api`: -Construct the comment body as a shell variable first, then pass it to `gh api`: +**Note:** Do NOT use `$()` command substitution — it is blocked by `run_shell_command` security policy. Pass the body directly as a multi-line string in the `-f body=` argument: ```bash -# Build comment body (use actual newlines, not \n): -BODY=$(cat < Date: Sun, 29 Mar 2026 20:29:06 +0800 Subject: [PATCH 5/7] fix: add start_side param for multi-line PR comments Add explicit `-f start_side="RIGHT"` to the multi-line gh api comment example. GitHub API docs indicate start_side may be required for ranged comments. Adding it explicitly is low-cost and eliminates ambiguity. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/core/src/skills/bundled/review/SKILL.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/skills/bundled/review/SKILL.md b/packages/core/src/skills/bundled/review/SKILL.md index 268cdb164..483614c53 100644 --- a/packages/core/src/skills/bundled/review/SKILL.md +++ b/packages/core/src/skills/bundled/review/SKILL.md @@ -195,6 +195,7 @@ gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ -f path="{file_path}" \ -F start_line={start_line} \ -F line={end_line} \ + -f start_side="RIGHT" \ -f side="RIGHT" ``` From 3e105452a290f6c3d66383bcbb66937745318cd8 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 29 Mar 2026 20:43:01 +0800 Subject: [PATCH 6/7] fix: use temp file + quoted heredoc for shell-safe comment body Review content may contain double quotes, $VAR, backticks, etc. that break double-quoted shell arguments or trigger run_shell_command security rejection. Replace direct string interpolation with a two-step approach: 1. Write body to temp file via quoted heredoc (<<'BODYEOF') which prevents ALL shell expansion 2. Reference file with -F body=@/tmp/pr-comment.txt in gh api calls and --body-file in gh pr review calls Also update Step 5 to clean up all temp files. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../core/src/skills/bundled/review/SKILL.md | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/packages/core/src/skills/bundled/review/SKILL.md b/packages/core/src/skills/bundled/review/SKILL.md index 483614c53..4875f5b38 100644 --- a/packages/core/src/skills/bundled/review/SKILL.md +++ b/packages/core/src/skills/bundled/review/SKILL.md @@ -173,24 +173,27 @@ gh pr view {pr_number} --json headRefOid --jq '.headRefOid' Then, for each confirmed finding, post an **inline comment** on the specific file and line using `gh api`: -**Note:** Do NOT use `$()` command substitution — it is blocked by `run_shell_command` security policy. Pass the body directly as a multi-line string in the `-f body=` argument: +**Shell safety:** Review content may contain double quotes, `$VAR`, backticks, or other shell-sensitive characters. Do NOT interpolate review text directly into shell arguments. Instead, use a **two-step process**: write the body to a temp file using a quoted heredoc (which prevents all shell expansion), then reference the file with `-F body=@file`. ```bash -# Single-line finding: -gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ - -f body="**[{severity}]** {issue description} +# Step A: Write comment body to temp file (quoted heredoc — no shell expansion): +cat > /tmp/pr-comment.txt <<'BODYEOF' +**[{severity}]** {issue description} -{suggested fix}" \ +{suggested fix} +BODYEOF + +# Step B: Post single-line comment referencing the file: +gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ + -F body=@/tmp/pr-comment.txt \ -f commit_id="{commit_sha}" \ -f path="{file_path}" \ -F line={line_number} \ -f side="RIGHT" -# Multi-line finding (e.g., line range 42-50): +# For multi-line findings (e.g., line range 42-50), add start_line and start_side: gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ - -f body="**[{severity}]** {issue description} - -{suggested fix}" \ + -F body=@/tmp/pr-comment.txt \ -f commit_id="{commit_sha}" \ -f path="{file_path}" \ -F start_line={start_line} \ @@ -199,6 +202,8 @@ gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ -f side="RIGHT" ``` +Repeat Steps A-B for each finding, overwriting the temp file each time. Clean up the temp file in Step 5. + If posting an inline comment fails (e.g., line not part of the diff, auth error), include the finding in the overall review summary comment instead. **Important rules:** @@ -208,17 +213,23 @@ If posting an inline comment fails (e.g., line not part of the diff, auth error) - Include the severity tag (Critical/Suggestion/Nice to have) at the start of each comment - Include the suggested fix in the comment body when available -After posting all inline comments, submit an overall review using the action that matches the verdict from Step 3: +After posting all inline comments, write the review summary to a temp file and submit it using the action that matches the verdict from Step 3: ```bash +# Write summary to temp file: +cat > /tmp/pr-review-summary.txt <<'SUMMARYEOF' +{summary + verdict text} +SUMMARYEOF + +# Submit review with the matching action: # If verdict is "Approve": -gh pr review {pr_number} --approve --body "{summary}" +gh pr review {pr_number} --approve --body-file /tmp/pr-review-summary.txt # If verdict is "Request changes": -gh pr review {pr_number} --request-changes --body "{summary}" +gh pr review {pr_number} --request-changes --body-file /tmp/pr-review-summary.txt # If verdict is "Comment": -gh pr review {pr_number} --comment --body "{summary}" +gh pr review {pr_number} --comment --body-file /tmp/pr-review-summary.txt ``` If there are **no confirmed findings**: @@ -229,7 +240,7 @@ gh pr review {pr_number} --approve --body "No issues found. LGTM! ✅" ## Step 5: Restore environment -If you checked out a PR branch in Step 1, restore the original state now: check out the original branch, `git stash pop` if changes were stashed, and remove the temp file. +If you checked out a PR branch in Step 1, restore the original state now: check out the original branch, `git stash pop` if changes were stashed, and remove all temp files (`/tmp/pr-review-context.md`, `/tmp/pr-comment.txt`, `/tmp/pr-review-summary.txt`). This step runs **after** Step 4 to ensure the PR branch is still checked out when posting inline comments (Step 4 needs the correct commit SHA from the PR branch). From 5e0d73b3f91b81842486461bd9c75164cf23339d Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 29 Mar 2026 20:54:24 +0800 Subject: [PATCH 7/7] fix: add write_file to allowedTools, replace shell heredoc with write_file tool The skill instructed agents to write temp files via `cat > file <<'EOF'` in run_shell_command, which contradicts the repo's tool guidance ("Use write_file, NOT echo >/cat < --- .../core/src/skills/bundled/review/SKILL.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/core/src/skills/bundled/review/SKILL.md b/packages/core/src/skills/bundled/review/SKILL.md index 4875f5b38..976753577 100644 --- a/packages/core/src/skills/bundled/review/SKILL.md +++ b/packages/core/src/skills/bundled/review/SKILL.md @@ -6,6 +6,7 @@ allowedTools: - run_shell_command - grep_search - read_file + - write_file - glob --- @@ -173,16 +174,16 @@ gh pr view {pr_number} --json headRefOid --jq '.headRefOid' Then, for each confirmed finding, post an **inline comment** on the specific file and line using `gh api`: -**Shell safety:** Review content may contain double quotes, `$VAR`, backticks, or other shell-sensitive characters. Do NOT interpolate review text directly into shell arguments. Instead, use a **two-step process**: write the body to a temp file using a quoted heredoc (which prevents all shell expansion), then reference the file with `-F body=@file`. +**Shell safety:** Review content may contain double quotes, `$VAR`, backticks, or other shell-sensitive characters. Do NOT interpolate review text directly into shell arguments. Instead, use a **two-step process**: write the body to a temp file using the `write_file` tool (which bypasses shell interpretation entirely), then reference the file with `-F body=@file` in the shell command. -```bash -# Step A: Write comment body to temp file (quoted heredoc — no shell expansion): -cat > /tmp/pr-comment.txt <<'BODYEOF' +``` +# Step A: Use write_file tool to create /tmp/pr-comment.txt with content: **[{severity}]** {issue description} {suggested fix} -BODYEOF +``` +```bash # Step B: Post single-line comment referencing the file: gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ -F body=@/tmp/pr-comment.txt \ @@ -213,14 +214,9 @@ If posting an inline comment fails (e.g., line not part of the diff, auth error) - Include the severity tag (Critical/Suggestion/Nice to have) at the start of each comment - Include the suggested fix in the comment body when available -After posting all inline comments, write the review summary to a temp file and submit it using the action that matches the verdict from Step 3: +After posting all inline comments, use `write_file` to create `/tmp/pr-review-summary.txt` with the summary text, then submit the review using the action that matches the verdict from Step 3: ```bash -# Write summary to temp file: -cat > /tmp/pr-review-summary.txt <<'SUMMARYEOF' -{summary + verdict text} -SUMMARYEOF - # Submit review with the matching action: # If verdict is "Approve": gh pr review {pr_number} --approve --body-file /tmp/pr-review-summary.txt