pr-feedback — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited pr-feedback (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Fetch all review feedback and CI status from the PR associated with the current branch, triage each item, implement fixes, and propose responses.
All commands auto-detect the repository and PR from the current branch.
Run all four fetch commands to collect every feedback surface:
python3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py threads # unresolved inline review threads
python3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py ci # CI check status and failures
python3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py comments # general PR comments, review bodies, PR description
python3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py annotations # check run annotations and code scanning alertsIf any fails (no PR for current branch, auth issues), report the error and stop.
threads returns unresolved_threads with thread_id, path, line, and comments (each with node_id, database_id, diff_hunk).
ci returns ci_summary (pass/fail/pending counts) and failed_checks (with run_id, job_id for log fetching). On a failed fetch it returns empty counts plus an error field -- see Step 4.
comments returns pr_body (may contain bot-appended review content), pr_comments (each with node_id, database_id), review_bodies (top-level bodies of submitted reviews -- where CodeRabbit, Copilot and similar bots post their summary), and pr_author.
annotations returns annotations (check run annotations) and code_scanning_alerts. Run it on every PR -- see Step 3 for why a green CI does not mean there are no annotations.
For each unresolved thread, read the file at the commented path and lines for context. Read the entire thread (including replies) to understand the final ask. Classify into one of three actions:
Implement when the comment is:
Dismiss (with concise, respectful explanation) when:
Ask (escalate to user) when:
When in doubt between Implement and Ask, prefer Ask.
Process comments from pr_comments that contain actionable review feedback. Skip CI status messages, merge bot noise, and other non-review content. Look for:
Triage these using the same Implement / Dismiss / Ask criteria. Since these are not tied to specific lines, read the relevant files mentioned in the comment for context.
Scan pr_body for bot-appended review sections. Common patterns:
Extract actionable items and triage them. Pay particular attention to "must-fix" items -- they indicate merge-blocking concerns from the bot's perspective.
Flag any findings that are factually incorrect (hallucinations). These need correction in the response phase.
Process review_bodies the same way as general PR comments. These are the top-level bodies of submitted reviews, which are a different surface from pr_comments -- a bot review summary usually lands here, not in the comments list. state tells you how seriously to weigh it: CHANGES_REQUESTED is blocking, COMMENTED is advisory, APPROVED bodies are usually just a sign-off and can be skipped unless they raise a concern.
These are the inline findings GitHub renders in the Files changed tab -- lint violations, type errors, security findings, and similar -- attached to a line of code rather than to a review comment. They are invisible to threads, comments, and ci, so they must be read from annotations.
Do not skip this step when CI is green. A check run can report conclusion: success while still carrying failure-level annotations, so ci_summary.failed == 0 says nothing about whether annotations exist. Triage on the annotation contents, never on the check's pass/fail bucket.
Each annotation carries check_run_name, annotation_level (failure, warning, or notice), path, start_line, title (e.g. ruff (TC002)), message, and in_files_changed.
Split them on in_files_changed before deciding anything:
`in_files_changed: true` -- the annotation is on a file this PR touches. Treat it as in scope and fix it, subject to the same Implement / Dismiss / Ask criteria as review comments. A failure-level annotation on a changed file is the highest-priority item in the whole run.
`in_files_changed: false` -- the annotation is on a file the PR never touched, so it is almost always a pre-existing violation that the linter reports repo-wide. Do not fix these. Fixing them inflates the diff with unrelated changes and makes the PR harder to review. Report them in the summary as pre-existing, and let the user decide whether they want a separate cleanup PR.
Two details worth knowing:
GitHub Actions attaches a location-less annotation with the message Process completed with exit code N and a synthetic path like .github. It is a restatement of the job's exit status, not a finding. Ignore it; the real findings are the other annotations from the same check run. It is kept in the output so the count matches the annotations_count GitHub reports.
When several annotations share a title and message across many files, they are one rule firing repeatedly. Fix the ones in changed files together in a single pass and describe them as one item in the summary rather than listing each occurrence.
code_scanning_alerts.alerts holds GitHub code scanning (CodeQL and other SARIF uploads) results for the PR, each with severity, rule_id, path, and message. Treat anything at high or critical severity as merge-blocking and raise it even if the user did not ask about security.
If code_scanning_alerts.available is false, read reason and mention it once, then move on -- it is a capability gap, not a finding:
Advanced Security must be enabled -- code scanning is not turned on for this repository. Nothing to fetch.not authorized to read code scanning alerts -- the token lacks the security_events scope. The user can grant it with gh auth refresh -h github.com -s security_events.Always check, even when every review comment is handled and CI is green -- a conflicting branch blocks merge and CI often will not run at all ("Checks awaiting conflict resolution"):
gh pr view {number} --json mergeable,mergeStateStatus,baseRefNameIf mergeable is CONFLICTING, rebase onto the base branch and resolve so both sides survive. Then re-verify the PR's own guarantees, not just that tests pass: a textual merge can succeed while silently breaking the PR's intent. If the PR asserts a measured property (query count, timing, output equality), re-measure it after the merge -- new code from the base branch may depend on something this PR removed or narrowed.
Identify what landed to cause it:
git log --oneline origin/{head}..origin/{base} -- <conflicting paths>If ci_summary.failed is 0, skip this section. This does not let you skip Step 3 -- annotations are independent of the check's pass/fail bucket.
If ci returned an error field, no check data was retrieved. An empty result does not mean the build is clean, so never report it as passing. no checks reported on the '<branch>' branch means the PR genuinely has no CI configured -- say so and move on. Anything else is a fetch failure: report it verbatim and treat CI status as unknown.
For each entry in failed_checks, fetch the failed job logs:
gh run view {run_id} --log-failed 2>&1 | tail -200Diagnose each failure and classify:
Fix when:
Skip (with explanation) when:
When fixing, read the relevant test file and source file to understand the failure, then apply the fix.
You run as a subagent, so you cannot ask the user anything. Stop after the code changes are made and verified. Do not commit, do not push, and do not post any reply, reaction, or resolve.
Return a report grouped by action:
Verify before you report: run the lint and the tests that cover the files you changed, and give the caller the result.
Write this plan into the report. The caller gets the user's approval and runs it.
python3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py resolve THREAD_IDpython3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py reply DATABASE_ID "Fixed: ..."python3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py reply DATABASE_ID "Explanation..."python3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py react review DATABASE_IDreact takes an optional --content (+1, -1, laugh, confused, heart, hooray, rocket, eyes), defaulting to +1. Use --content eyes for items in the Ask bucket: it signals the comment was seen and is pending a decision, which +1 wrongly reads as agreement.
Draft a single follow-up PR comment addressing multiple non-threaded items together:
python3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py comment "Response text..."Use this for:
To react to a general PR comment: python3 ~/.claude/skills/pr-feedback/scripts/pr_feedback.py react issue DATABASE_ID
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.