From code-reviewer
Publish PR review results to Azure DevOps — posts findings as inline/file/general comments, posts context questions as inline `[QUESTION]` comments, manages the review summary thread (replies to existing thread instead of creating duplicates), and optionally approves or merges the PR. Use this skill when the pr-review workflow reaches Step 12 and needs to publish its collected findings, questions, and verdict to ADO. Also usable standalone for any workflow that needs structured comment posting to a PR. Trigger when: "post review results", "publish findings to PR", or when invoked from pr-review Step 12. NOT for analysis or grading — this skill only handles the publishing/posting workflow.
How this skill is triggered — by the user, by Claude, or both
Slash command
/code-reviewer:post-pr-reviewThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Publish structured review results (findings, context questions, and summary) to an
Publish structured review results (findings, context questions, and summary) to an Azure DevOps pull request. This skill owns the full "write to ADO" workflow — the caller provides the data, this skill handles formatting, deduplication, thread management, and posting.
The caller MUST provide the following fields. Validate all required fields before proceeding — reject with a clear error if any are missing.
| Field | Type | Description |
|---|---|---|
prNumber | integer | PR number in Azure DevOps |
repository | string | Repository name (e.g., MyRepository) |
botPrefix | string | Bot prefix for all comments (e.g., [<reviewer>'s bot]) |
findings[] | array | Graded findings from review — each with severity, blocker flag, category, file, line, issue, suggestion |
questions[] | array | Context questions from Step 10 — each with file, line, uncertainty, what answering unlocks |
verdict | enum | APPROVE, APPROVE_WITH_COMMENTS, or REQUEST_CHANGES |
reviewType | enum | initial or re-review |
outputFormatMarkdown | string | The formatted review summary markdown (from output-format.md template) |
| Field | Type | Description |
|---|---|---|
project | string | ADO project name (auto-detected from git remote if omitted) |
approveAfterPosting | boolean | If true and verdict is APPROVE, approve the PR after posting. Default: false (confirm with user first) |
mergeAfterApproval | boolean | If true, merge after approval. Default: false |
mergeStrategy | enum | squash, noFastForward, rebase, rebaseMerge. Default: squash |
isSmallDelta | boolean | When true, the caller is posting a trivial re-review delta and the summary must use small-delta mode. Default: false |
smallDeltaSummary | string | Required when isSmallDelta is true. A 1-3 sentence delta-only summary reply |
Each item in findings[] must have:
- Severity: CRITICAL | HIGH | MEDIUM | LOW
- Blocker: true | false
- Category: string (e.g., "Security", "Performance", "Code Quality")
- File: string (path relative to repo root)
- Line: integer (1-based line number, or null for file-level)
- Issue: string (description of the problem)
- Suggestion: string (proposed fix with code example)
Each item in questions[] must have:
- File: string (path relative to repo root)
- Line: integer (1-based line number)
- CodeContext: string (the code snippet that triggered the question)
- Uncertainty: string (what the reviewer cannot determine)
- WhatAnsweringUnlocks: string (what the reviewer could assess with an answer)
- SuggestedAnswers: string[] (optional — 2-3 possible answers to guide the author)
findings[] items have the required structurequestions[] items have the required structureisSmallDelta is true, verify reviewType is re-review,
smallDeltaSummary is present, and the summary is no longer than 3 sentencesIf project is not provided, auto-detect from git remote:
git remote get-url origin
Parse: https://<org>.visualstudio.com/<project>/_git/<repository>
When multiple agents flag the same issue (same file + same line range + similar description), keep the more detailed version and discard the duplicate.
Deduplication rules:
Post findings in priority order (most severe first):
For each finding, select the comment type:
Inline comment (preferred) — when Line is not null:
mcp__azure-devops__addPullRequestInlineComment
repository: <repository>
pullRequestId: <prNumber>
path: /<file>
position: { line: <line>, offset: 1 }
comment: <formatted comment>
File comment (fallback) — when Line is null or inline fails:
mcp__azure-devops__addPullRequestFileComment
repository: <repository>
pullRequestId: <prNumber>
path: /<file>
comment: <formatted comment>
General comment (last resort) — when file is not in PR diff:
mcp__azure-devops__addPullRequestComment
repository: <repository>
pullRequestId: <prNumber>
comment: <formatted comment>
Finding comment format:
For blocking findings:
<botPrefix> [BLOCKER] **<Severity>** (<Category>)
<Issue description>
**Suggestion:** <Suggestion with code example>
For non-blocking findings:
<botPrefix> **<Severity>** (<Category>)
<Issue description>
**Suggestion:** <Suggestion with code example>
Blocker classification (from Review Thread State Machine):
Error handling: If an inline comment fails (line not in diff), retry as a file comment. If that also fails, fall back to a general comment referencing the file and line.
Post each question as an inline comment anchored to the relevant code line.
Questions use the [QUESTION] tag — distinct from findings.
<question_deduplication> Step 5a: Check for existing questions (MUST do before posting)
Before posting any questions, check for questions we already asked in a previous review iteration. This requires the full set of PR comment threads.
Reuse already-fetched comments: If PR comment threads were already fetched
earlier in this workflow (e.g., by Step 4's finding dedup or any prior step),
reuse that data — do NOT call getPullRequestComments again. Only fetch if no
prior step has retrieved comments yet:
mcp__azure-devops__getPullRequestComments
repository: <repository>
pullRequestId: <prNumber>
Cache for later: Store the fetched threads so Step 6 (summary thread management) can reuse them instead of making another API call.
Scan all comment threads for existing [QUESTION] threads by looking for
threads whose root comment contains BOTH:
botPrefix (e.g., [<reviewer>'s bot])[QUESTION] tagBuild an existing-questions list from matching threads:
| File | Uncertainty (first 100 chars) | Thread Status | Thread ID |
Step 5b: Filter out duplicate questions
For each question in questions[], check if it already exists by matching:
Uncertainty field substantially overlaps with
an existing question's text (same core question, even if wording differs slightly)If a match is found → skip posting and record it as a duplicate. The existing thread already captures the question — re-posting would clutter the PR.
What counts as a duplicate:
Track results:
skippedQuestions[] — questions that already exist on the PR
newQuestions[] — questions that need to be posted
</question_deduplication>
Step 5c: Post new questions only
For each question in newQuestions[]:
mcp__azure-devops__addPullRequestInlineComment
repository: <repository>
pullRequestId: <prNumber>
path: /<file>
position: { line: <line>, offset: 1 }
comment: <formatted question>
Question comment format:
<botPrefix> [QUESTION] **Clarification Needed**
**Code:**
`<CodeContext>`
**Question:** <Uncertainty>
**Why this matters:** <WhatAnsweringUnlocks>
**Possible answers:** <SuggestedAnswers, if provided>
Key rules:
[BLOCKER] tagnewQuestions[] has more than 10 items, post the top 10 (highest review
impact) and note the remainder in the summary"All <count> questions were already asked in a previous review iteration."The review summary is the top-level overview of the entire review. To keep the PR clean, we reuse the existing summary thread instead of creating new ones.
<summary_thread_management> Workflow:
Search for existing summary thread:
Reuse already-fetched comments: If Step 5a already fetched PR comment
threads, reuse that cached data — do NOT call getPullRequestComments again.
Only fetch if Step 5 was skipped (no questions to post):
mcp__azure-devops__getPullRequestComments
repository: <repository>
pullRequestId: <prNumber>
Scan all comment threads for a thread whose root comment contains BOTH:
botPrefix (e.g., [<reviewer>'s bot])# PR Review: or ## Re-Review Summary:If existing summary thread found → reply to it:
mcp__azure-devops__addPullRequestComment
repository: <repository>
pullRequestId: <prNumber>
comment: <new summary markdown>
Post the new summary as a reply to the existing thread using the thread ID. This keeps all review summaries in one conversation thread.
How to reply to an existing thread:
Use getPullRequestComments to find the thread ID of the existing summary.
Then use addPullRequestComment — the ADO MCP tools handle thread replies
when you reference the parent thread.
Note: Do NOT close or resolve the old summary. The new reply supersedes it naturally. The thread stays Active until the PR is approved.
If no existing summary thread → create new one:
mcp__azure-devops__addPullRequestComment
repository: <repository>
pullRequestId: <prNumber>
comment: <summary markdown>
Post as a new general comment. This becomes the summary thread for future re-reviews.
Summary identification markers:
botPrefix followed by a known heading# PR Review: <PR Title>## Re-Review Summary: PR #<prNumber><small_delta_summary>
If reviewType is re-review and isSmallDelta is true:
smallDeltaSummary as the entire comment body.smallDeltaSummary.
</small_delta_summary>Summary content selection:
smallDeltaSummary.outputFormatMarkdown provided by the caller. Append a
questions summary section if any questions were posted:## Context Questions Asked (<count>)
The following areas need clarification from the PR author. These are non-blocking
but answers will improve review confidence:
| # | File | Line | Question |
|---|------|------|----------|
| 1 | path/to/file.cs | 45 | <brief uncertainty> |
| ... | ... | ... | ... |
Approve — only when ALL conditions are met:
APPROVEapproveAfterPosting is true OR user explicitly confirms[BLOCKER] findings existmcp__azure-devops__approvePullRequest
repository: <repository>
pullRequestId: <prNumber>
Merge — only when ALL conditions are met:
mergeAfterApproval is true OR user explicitly confirmsmcp__azure-devops__mergePullRequest
repository: <repository>
pullRequestId: <prNumber>
mergeStrategy: <mergeStrategy>
Always confirm merge strategy with the user:
Return a structured confirmation to the caller:
## Post-PR-Review Complete
- **PR**: #<prNumber> in <repository>
- **Findings posted**: <count> (<critical> critical, <high> high, <medium> medium, <low> low)
- **Questions posted**: <count> (<skipped> skipped as already asked)
- **Summary**: <new thread | replied to existing thread #<threadId>>
- **Verdict**: <verdict>
- **Approved**: Yes / No
- **Merged**: Yes / No
- **Errors**: <any posting failures, with details>
When referencing ADO entities in comments:
#12345 (hash prefix)!4567 (exclamation prefix)! is for PRs, # is for work items/bugscode-reviewer:pr-review (Step 12), code-reviewer:re-review (Step 5)npx claudepluginhub gautam-achieveai/claudeplugins --plugin code-reviewerProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.