Skip to content
Back to skills

Review Agent Feedback

ASecurity

Use when a PR/MR has bot review threads (Kody, CodeRabbit, Copilot, Gemini) to verify against the code, reply, rate, and resolve: "봇 리뷰 검증해줘", "리뷰 스레드 resolve". New reviews: pr-review.

  • 6 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
ai-agentspythongobashreactgitapi

Works with

  • cli
  • api
  • mcp

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned November 7, 2026

npx -y skills add m16khb-org/issueops --skill review-agent-feedback --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Review Agent Feedback?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Review Agent Feedback
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/m16khb-org-review-agent-feedback/badge)](https://www.skillsdirectory.com/skills/m16khb-org-review-agent-feedback)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: review-agent-feedback
description: 'Use when a PR/MR has bot review threads (Kody, CodeRabbit, Copilot, Gemini) to verify against the code, reply, rate, and resolve: "봇 리뷰 검증해줘", "리뷰 스레드 resolve". New reviews: pr-review.'
---

# Review Agent Feedback

**A bot's finding is a claim, not a fact — and a reply is not a resolution.** Every
automated review thread gets one verdict grounded in the code as it exists at the
PR/MR head, one in-thread reply that states that verdict with evidence, one reaction
the reviewer can learn from, and one resolution — then the thread is re-read and the
report says what the remote actually shows.

Works on GitHub (`gh`) and GitLab (`glab`), self-hosted included; provider is
auto-detected from `origin` or the URL. Canonical location:
`issueops/skills/review-agent-feedback` (home skill paths are symlinks installed
by `issueops update`). `agents/openai.yaml` exposes it as `$review-agent-feedback`
on Codex. Call the script as `<skill>/scripts/review_threads.py`, where `<skill>` is
this directory.

## Pipeline

```
1 List     review_threads.py list   → bot threads, normalised, with already_handled
2 Verify   you, per thread          → verdict + evidence (code, diff, tests, rules)
3 Plan     plan.json                → verdict / reply / reaction / resolve per thread
4 Apply    review_threads.py apply --dry-run, then apply → verified ledger
5 Report   ledger table             → what the remote shows, not what was sent
```

### 1. List

```bash
out=<repo>/.issueops/issues/<issue-number>/review/<provider>-<number>; mkdir -p "$out"   # no linked issue: <repo>/.issueops/tmp/review-agent-feedback/<number>
python3 <skill>/scripts/review_threads.py list --pr <number|!n|#n|URL> --repo-dir <repo> > "$out/threads.json"
```

`threads.json`, `plan.json`, and the ledger live under that `$out` — the per-issue
artifact folder's ignored `review/` area (same rule as `pr-review`); they are working files,
not commits. The issue number comes from the PR/MR body's issue link or the IssueOps record.

Read `threads.json`. It contains only bot-authored threads (`--all` adds humans);
each has `reviewer`, `mention`, `resolvable`, `resolved`, `path`, `line`,
`already_handled`. Skip threads whose `already_handled` equals the verdict you would
give now — they were finished by an earlier run. Threads with `resolvable: false`
(summary / status notes) are not part of the job unless the user names them. If
`state` is not open, say so before doing anything. If the list is empty after those
filters, report "처리할 봇 스레드 없음" with the counts and stop.

With a full URL, `--repo-dir` is only needed for the verify step (a clone at the
PR/MR head); provider, host, and project come from the URL. With a bare number the
`origin` remote of `--repo-dir` decides them.

For GitLab hosts whose token lives in a profile-scoped MCP server rather than the
CLI, reproduce the calls in `references/providers.md` through that `glab_api` tool —
the paths and fields are identical; the `gitlab-usecase` skill governs profile choice.

### 2. Verify (you)

For every thread, before writing a word of reply:

- Open the file at the PR/MR head (`git fetch` + checkout or `git show <head_sha>:<path>`),
  not the diff hunk alone; follow the symbol one hop upstream (where the value is
  produced/validated) and one hop downstream (where it is consumed).
- Decide whether the change under review introduced the issue or it is pre-existing
  (`git blame`/base branch), and whether a cited project rule really names it.
- Run the fastest relevant check when the claim is about behaviour (the test, a
  typecheck, a reproduction). Where the claim cannot be checked, the verdict is
  `hold`, not `valid`.
- Verdict: `valid` · `partial` · `invalid` · `out_of_scope` · `hold`
  (definitions and default reaction/resolve in `references/providers.md`).

### 3. Plan

Write `plan.json` (schema in the script docstring). Each reply is Korean prose in this
shape; the script prepends the reviewer's mention and appends the idempotency marker:

```md
**판정: 타당** (또는 부분 타당 / 타당하지 않음 / 범위 밖 / 보류)

근거: <파일:라인 · 호출 경로 · 명령 결과>. <봇의 전제 중 맞는 것/틀린 것>.

조치: <적용한 수정과 커밋 · 별도 이슈 · 현재 코드가 안전한 이유 · 보류 사유>
```

Identifiers, paths, and commands stay verbatim; never quote secret values. A reply
must contain the evidence that decided the verdict — "확인했습니다" alone is not a reply.

Before posting `plan.json`, invoke the `fluent-korean` skill and apply it to every
`reply`. These replies are published to a remote thread a human reads, so the polish
pass is a precondition for posting, not an option.

Rules for the plan:

- `hold` threads (waiting on a human, a follow-up promised in this PR/MR that is not
  pushed yet, or the user said leave it open) keep `resolve: false` and a
  `reason_open`; every other verdict resolves, whether accepted or rejected.
- Reaction rates the finding's usefulness for **this** change: 👍 correct and
  actionable here, 👎 false, misleading, over-severe, or not actionable here.
- The user's overrides ("resolve 하지 마", "반응 달지 마") go into `reaction`/`resolve`
  fields, not into skipped steps.

### 4. Apply

```bash
python3 <skill>/scripts/review_threads.py apply --pr <ref> --repo-dir <repo> --plan plan.json --dry-run   # preview reply bodies and planned actions
python3 <skill>/scripts/review_threads.py apply --pr <ref> --repo-dir <repo> --plan plan.json             # post, react, resolve, then re-read
```

The script replies to the original thread, adds the reaction on the reviewer's note,
resolves the thread, then re-fetches it and marks each row `ok`, `unverified`, or
`error`. It never duplicates a reply or reaction on re-run and refuses to resolve
`resolvable: false` threads. Single primitives (`reply`, `react`, `resolve`,
`unresolve`, `verify`) exist for partial redo.

### 5. Report

Present the ledger as a table — one row per thread: file:line · reviewer · verdict ·
reply id · reaction · resolved (and `reason_open` when not) · status. A row that is
`unverified` or `error` is reported as not done, with the observed state. Then, if any
verdict changed code, point at the commit; if any is `hold`, list what the human must
decide.

## Hard rules

- Verify before replying; a verdict without opened code is `hold`.
- Reply, react, resolve, read back — for every handled thread, in that order. Missing
  any one of the four means the thread is not handled. A `hold` thread is the one
  exception: reply and read back, reaction `none`, no resolve, `reason_open` in the report.
- Never resolve a thread you did not reply to, and never resolve a `hold`.
- Never post through a second path (web UI, another tool) to "fix" a failed row — re-run
  the script or the primitive so the ledger stays true.
- Never print tokens; the script masks known token shapes in output and errors.

| Rationalisation | Reality |
|---|---|
| "The bot is usually right, I'll accept it" | The 2026 `!5581` findings looked right and were blocked upstream by validation. Open the code. |
| "I replied, that's enough" | An open thread is open review debt; the MR still shows it as blocking. Resolve or say why not. |
| "It's out of scope, so I'll just resolve it silently" | The reviewer learns nothing and the author cannot see why. Reply with the scope reason, then resolve. |
| "The POST returned 201" | The ledger's `observed` block is the deliverable. Read back or report unverified. |
| "This reviewer doesn't learn from reactions" | The reaction is also the author's and the next reviewer's signal. Add it unless the user opts out. |

Files in this skill

  • SKILL.md7.6 KB
  • agents/openai.yaml423 B
  • references/providers.md6 KB
  • scripts/review_threads.py24.3 KB
  • scripts/review_threads_test.py8.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.