Review Pull Requests
Reviews GitHub pull requests for completeness, quality, and merge
readiness according to repository conventions.
Use GitHub MCP pull_request_read with method: get to retrieve:
- PR number, title, body
- Author, assignees, reviewers
- State (open, closed, merged), draft status
- Base and head branches
- Labels
- Linked issues (from
closingIssuesReferences or parsed from body)
- Created and updated timestamps
Fallback command if MCP is unavailable:
bash
1gh pr view <pr_number> --json number,title,body,state,isDraft,headRefName,baseRefName,author,assignees,labels,commits,reviews,additions,deletions,changedFiles,url,createdAt,updatedAt
If the PR is not found, stop and report an error.
Check PR title and body:
-
Title: Verify it follows Conventional Commits format if
require_conventional_commits is true:
- Pattern:
^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|security|revert)(\(.+\))?!?: .+$
- Max 72 characters
- Lowercase first word after colon
- No trailing period
-
Body: Verify it contains:
- A clear description of what changed and why.
- If
require_linked_issue is true, at least one issue reference
(Closes #N, Fixes #N, Resolves #N, or Refs #N).
- If the change is breaking, a
BREAKING CHANGE: footer or ! in
the title.
-
Labels: Check that the PR has appropriate labels (e.g., bug,
enhancement, documentation, chore).
-
Draft Status: If the PR is still a draft, note this in the
report. Full review continues but recommendations defer to "mark
ready for review" before merging.
Step 3: Validate Linked Issues
If require_linked_issue is true:
-
Parse issue references from the PR body and title.
-
For each referenced issue:
- Verify the issue exists and is open (or recently closed if the PR
was the closing action).
- Check that the issue has the
ready label (not needs-triage or
blocked).
- Verify that the PR scope aligns with the issue description.
-
If no issues are linked, add a high-severity finding.
-
If multiple issues are linked, verify they are related and the PR
scope is appropriate.
Step 4: Review Commit History
Use GitHub MCP pull_request_read with method: get to retrieve commit
list, or use fallback:
bash
1gh pr view <pr_number> --json commits --jq '.commits[].messageHeadline'
Validate commits:
-
If require_conventional_commits is true:
- Check that each commit message follows Conventional Commits format.
- Flag commits with unclear or generic messages ("fix", "update",
"wip").
-
Check for:
- Merge commits (should be rare; squash merges are preferred).
- Revert commits without explanation.
- Commits that add and then immediately remove the same code (churn).
-
Recommend squashing fixup commits or clarifying commit intent if the
history is confusing.
Step 5: Review Changed Files
Use GitHub MCP pull_request_read with method: get_files to list all
changed files, or use fallback:
bash
1gh pr diff <pr_number> --name-only
Validate changes:
-
Source code changes:
- If
require_tests is true and source code was modified, verify
that test files were also added or updated.
- Flag large diffs (e.g., 500+ lines changed in a single file)
without clear justification.
-
Documentation changes:
- If source code, APIs, or configuration changed, verify that
corresponding documentation was updated.
- Check that README, AGENTS.md, or docs/ files reflect the changes.
-
Configuration or infrastructure changes:
- If
Makefile, moon.yml, .github/workflows, Dockerfile, or
package.json changed, verify the changes are intentional and
documented.
-
Sensitive files:
- Flag changes to
.env files, secret managers, or credential
storage.
- Verify no secrets or credentials are committed in the diff.
Step 6: Check CI Status (conditional)
If check_ci_status is true:
-
Use GitHub MCP pull_request_read with method: get_check_runs to
list all CI checks.
-
Verify that all required checks have passed:
- Conclusion must be
success for required checks.
- Flag checks with
failure, cancelled, timed_out,
action_required, stale, or startup_failure.
-
If any required checks are still pending or in progress, note this in
the report and defer merge recommendation until checks complete.
Fallback command:
bash
1gh pr checks <pr_number>
Use GitHub MCP pull_request_read with method: get_reviews,
method: get_review_comments, and method: get_comments to fetch
existing reviews and comments.
Check:
-
Unresolved review comment threads: If review comment threads
exist and are not resolved, flag this as a high-severity blocker to
merge. Each unresolved thread must be addressed by either:
- Making the requested code change and resolving the thread
- Replying with clarification and resolving if the reviewer accepts
- Discussing and reaching consensus before resolving
-
Review status:
- Count approvals (
APPROVED), rejections (CHANGES_REQUESTED),
and comment-only reviews (COMMENTED).
- Verify that at least one CODEOWNERS-designated reviewer has
approved if repository rulesets require it.
- If any reviewer has requested changes, flag as high-severity until
those changes are addressed and the reviewer re-reviews.
-
Stale reviews: If reviews are older than the latest commit,
suggest re-requesting review (medium severity).
-
General PR comments: Review general issue comments on the PR
(not code review comments) for guidance, questions, or blockers.
These comments do not have the same authority as code review
comments but may contain important context:
- Flag unanswered questions from maintainers as medium severity.
- Note any blockers or dependencies mentioned in comments.
- Treat general comments as advisory unless they come from
CODEOWNERS or contain explicit blocking language.
Fallback:
bash
1gh pr view <pr_number> --json reviews,comments --jq '.reviews[] | {author: .author.login, state: .state, submittedAt: .submittedAt}'
Step 7a: Check Merge Conflicts and Branch Status
Use GitHub MCP pull_request_read with method: get_status or gh
CLI to check:
-
Merge conflicts: Verify the PR branch can be cleanly merged into
the base branch. If conflicts exist, flag as high-severity blocker.
bash
1gh pr view <pr_number> --json mergeable,mergeStateStatus
mergeable: CONFLICTING indicates merge conflicts
mergeStateStatus: DIRTY indicates conflicts or other issues
-
Branch update needed: Check if the base branch has advanced past
the PR head and the PR branch needs updates:
- Compare base branch HEAD with the merge base of the PR
- If the PR is behind the base branch and repository policy requires
up-to-date branches, flag as medium severity
- Recommend updating the branch via merge or rebase
-
Branch protection compliance: Verify the PR satisfies all branch
protection rules:
- Required status checks passing
- Required reviews obtained
- No unresolved conversations (if required by ruleset)
- Linear history requirement (squash merge ready)
Fallback:
bash
1gh pr view <pr_number> --json mergeable,mergeStateStatus,statusCheckRollup
Step 8: Score and Classify Findings
Assign severity to each finding:
- High: Missing linked issue (when required), CI checks failing,
secrets in diff, unresolved review threads, merge conflicts,
changes requested by reviewers, breaking changes without
documentation.
- Medium: Non-conventional commit messages, missing tests (when
required), missing documentation updates, large diffs without
justification, draft PR not marked ready, branch needs update,
unanswered maintainer questions in comments, stale reviews.
- Low: Minor title/body formatting issues, missing labels,
advisory comments from non-reviewers.
Calculate a quality score starting from 100:
- High:
-25 each (max penalty 75)
- Medium:
-12 each (max penalty 36)
- Low:
-5 each (max penalty 20)
Clamp to [0, 100].
Set overall_status:
fail if any high-severity finding exists
warn if no high findings but medium/low findings exist
pass if no findings exist
Set merge_ready:
true only if:
overall_status is pass
- All required CI checks have passed
- PR is not a draft
- At least one approving review exists (if required by rulesets)
- No unresolved review conversations
- No merge conflicts
- No reviewers have requested changes
- Branch is up to date with base (if required by repository policy)
Step 9: Generate Review Report
Produce a structured report:
-
Summary:
- PR number, title, author, branch
- State, draft status, linked issues
- CI check status
- Merge status (conflicts, branch up to date)
- Review status (approvals, changes requested, unresolved threads)
- Comment resolution status (resolved vs unresolved review comments)
- Overall status and score
-
Findings: Each finding with severity, category, description, and
recommended action.
-
Merge Recommendation:
- If
merge_ready is true: "PR is ready to merge."
- Otherwise: List blockers and recommended next steps.
Example finding structure:
json
1{
2 "severity": "high",
3 "category": "linked-issue",
4 "message": "PR does not reference any GitHub issue",
5 "suggestion": "Add 'Closes #N' or 'Refs #N' to the PR body"
6}
If post_review is true:
- Format the review report as GitHub-flavored Markdown.
- Use GitHub MCP
pull_request_review_write with method: create and
event: COMMENT to post the review.
Fallback:
bash
1gh pr comment <pr_number> --body "<review_report_markdown>"
The comment should start with:
markdown
1## 🤖 Pull Request Review
2
3> Posted by AI agent. Review findings below.
If merge_ready is true and no high/medium findings exist, post an
approving review with event: APPROVE. Otherwise, post as a comment
only.
Step 11: Return Outputs
Return:
findings array
overall_status
merge_ready
score
If the PR passes all checks, return merge_ready: true with a score of
100 and an explicit passing statement.
Definition of Done
This skill is complete when:
- The PR has been fully reviewed across metadata, commits, changes,
tests, docs, and CI status.
- Findings are categorized by severity with actionable guidance.
- A merge-readiness determination has been made.
- If
post_review was true, the review was successfully posted to the
PR.