원본 저장소의 제목, 예시, 코드, 표, 링크, 이미지를 유지해 표시합니다.
PR Review (single-agent, CI-safe)
Review a PR across 12 domains sequentially, then write review.json. A separate posting script turns the JSON into GitHub inline review comments.
If no PR number provided, diff against `origin/main` and print JSON to stdout.
Step 0 — Load prior dismissals (PR runs only)
Skip if no PR number provided.
Fetch all existing bot reviews on this PR:
gh api repos/{owner}/{repo}/pulls/$PR_NUMBER/reviews \
--jq '[.[] | select(.body | test("<!-- cc-pr-review -->"; "i")) | {id: .id, commit_id: .commit_id, submitted_at: .submitted_at}]'For each bot review found, fetch its inline comments:
gh api repos/{owner}/{repo}/pulls/$PR_NUMBER/reviews/$REVIEW_ID/comments \
--jq '[.[] | {id: .id, body: .body, path: .path, line: (.line // .original_line), reactions: .reactions}]'Also fetch any reply threads on those inline comments:
gh api repos/{owner}/{repo}/pulls/$PR_NUMBER/comments \
--jq '[.[] | select(.in_reply_to_id != null) | {id: .id, in_reply_to_id: .in_reply_to_id, body: .body}]'Build `SUPPRESSED_FINDINGS`: one entry per dismissed finding, { id, path, line, commit_id }, where commit_id is the commit the prior review was posted against.
A finding is dismissed if its prior inline comment has:
- A 👎 reaction (
.reactions["-1"] > 0), or - A human reply containing dismissal language: "intentional", "by design", "won't fix", "false positive", "ignore", "not applicable", "expected"
Extract the finding id from the prior comment body — each inline comment posted by the script contains an HTML comment <!-- id: {finding-id} --> in the first line.
Escape hatch — re-evaluate if the code changed since the dismissal. The PR diff always contains every PR-changed line, so compare against the prior review's commit instead:
HEAD_SHA=$(gh pr view $PR_NUMBER --json headRefOid --jq .headRefOid)
gh api repos/{owner}/{repo}/compare/$COMMIT_ID...$HEAD_SHA \
--jq '[.files[] | {filename: .filename, previous_filename: .previous_filename, patch: .patch}]'Run this once per distinct commit_id. Remove an entry from SUPPRESSED_FINDINGS when its path matches a file's filename or previous_filename and any of these hold:
- A hunk overlaps the finding. For each hunk header
@@ -start,count +..., the old-side interval isstarttostart + max(count, 1) - 1(countis 1 when omitted). It overlaps if that interval intersectsline - 5toline + 5. Check the whole interval, not juststart: a hunk that begins well before the finding can still span it. - The entry has no
line(file-level finding). - The file has no
patch(binary or too large to diff).
Also remove every entry for a commit_id whose compare call fails (for example, the commit was force-pushed away).
If no prior reviews or no dismissals: SUPPRESSED_FINDINGS is empty.
Step 1 — Get the diff and PR metadata
- PR number given →
gh pr view $PR_NUMBER(title and body, used by the scope domain) andgh pr diff $PR_NUMBER - No PR number →
git diff origin/main(no metadata; the scope domain skips PR hygiene)
Step 2 — Run 12 domain reviews sequentially
Read the reference file for each domain, then analyze the diff. Record findings with their exact file path and line number.
Before recording any finding: if its computed id ({domain}-{kebab-title}) is still in SUPPRESSED_FINDINGS after Step 0, skip it silently.
- Security —
Read .claude/skills/cc-pr-review-ci/references/security.md - Performance —
Read .claude/skills/cc-pr-review-ci/references/performance.md - React/TypeScript —
Read .claude/skills/cc-pr-review-ci/references/react-ts.md - Testing —
Read .claude/skills/cc-pr-review-ci/references/testing.md - Test Validity —
Read .claude/skills/cc-pr-review-ci/references/test-validity.md - DevOps/CI —
Read .claude/skills/cc-pr-review-ci/references/devops.md - Holistic —
Read .claude/skills/cc-pr-review-ci/references/holistic.md - Duplication —
Read .claude/skills/cc-pr-review-ci/references/duplication.md - Bug Hunting —
Read .claude/skills/cc-pr-review-ci/references/bug.md - Scope/Hygiene —
Read .claude/skills/cc-pr-review-ci/references/scope.md - Maintainability —
Read .claude/skills/cc-pr-review-ci/references/thermo.md - Comments —
Read .claude/skills/cc-pr-review-ci/references/comments.md
Step 3 — Write review.json
- Read
.claude/skills/cc-pr-review-ci/references/format.mdfor the exact schema.
- Merge all domain findings into a single
findingsarray. Assign each finding a stableidfollowing the{domain}-{kebab-title}convention.
- Determine verdict:
- Any
critical→CHANGES_REQUESTED highonly →APPROVED_WITH_SUGGESTIONSobservationsonly or none →APPROVED
- Write the JSON:
- PR run: write to
$REVIEW_OUTPUT_PATH(default/tmp/review.json) - Local run (no PR number): print to stdout
Do not call `gh` to post anything. The workflow's post-review.js step handles all GitHub writes.
