"把使用者名下已經開好的 PR 蒐集起來、帶回每一個的 review 狀態、列出來讓他決定要請誰看,然後通知對的人。Trigger: '我的 PR', 'request PR review', 'ask someone to review my PR', 'PR 狀態', '催 review', '催 PR', 'PR 被 approve 了嗎', '幫我掃我的 PR', '請同仁 review', '請同仁幫我 review', '請大家 review', '請大家幫我 review', '請大家幫忙看一下', '找人 review', '找誰 review', '請[人名/角色]幫我 review', '請[人名/角色]幫忙看 PR'. 主語為同仁/大家/人名/角色的「請X幫我 review」屬於催 review 範疇,不要 route 到 review-pr。" 使用者問**自己的** PR 現在怎麼樣,或想找人來看。例如「我的 PR」「PR 狀態」 「催 review」「PR 被 approve 了嗎」「請同仁幫我 review」。 「請〈某人/大家〉幫我 revie...
Scanned 9/5/2026
Install to Claude Code
npx -y skills add HsuanYuLee/polaris --skill request-pr-review --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Request Pr Review?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/hsuanyulee-request-pr-review)More formats (shields.io, HTML) on the badges page.
---
name: request-pr-review
description: |
"把使用者名下已經開好的 PR 蒐集起來、帶回每一個的 review 狀態、列出來讓他決定要請誰看,然後通知對的人。Trigger: '我的 PR', 'request PR review', 'ask someone to review my PR', 'PR 狀態', '催 review', '催 PR', 'PR 被 approve 了嗎', '幫我掃我的 PR', '請同仁 review', '請同仁幫我 review', '請大家 review', '請大家幫我 review', '請大家幫忙看一下', '找人 review', '找誰 review', '請[人名/角色]幫我 review', '請[人名/角色]幫忙看 PR'. 主語為同仁/大家/人名/角色的「請X幫我 review」屬於催 review 範疇,不要 route 到 review-pr。"
使用者問**自己的** PR 現在怎麼樣,或想找人來看。例如「我的 PR」「PR 狀態」
「催 review」「PR 被 approve 了嗎」「請同仁幫我 review」。
「請〈某人/大家〉幫我 review」主語是別人,仍然屬這裡——那是催 review,不是自己動手 review。
不用於:review 別人的 PR(走 review-pr)、掃團隊待看的 PR(走 review-inbox)。
metadata:
author: ""
version: 4.0.0
scope: universal
tools:
- name: gh
provision: manual
why: 開 PR、讀 review、建 release、查 CI
fix: 裝 GitHub CLI 並完成 `gh auth login`——二進位檔裝得起來,登入只有人做得到
- name: jq
provision: framework
why: 解析 API 回應的 JSON
install: mise:aqua:jqlang/jq
---
# request-pr-review — 請人來看已經開好的 PR
實作做完、PR 開出來了,缺的是最後一步:**請同事看**。這支 skill 承載那一步的全部——這批
總共有多少、分在哪些 repo、每一個現在被誰看了、要通知誰。
三步,順序固定,**中間那一步是人**:
1. **query** 名下所有 open PR,帶回每一個的 review 狀態。
2. **列出來問使用者要怎麼處理**——列的東西要足夠讓他當場決定,不用再去 GitHub 翻一遍。
3. **照他的決定通知對的人**。
## 這支 skill 不知道的三件事
**要看哪個 org、哪個 repo 通知誰、一張單長什麼樣。** 三者都由認領那個 org 的 skill 在
自己的 `SKILL.md` 宣告,這裡掃所有 skill 找那一行:
```
<!-- {任意前綴}-PR-CONTEXT-{org}: {命令} -->
```
鍵裡那一段就是 org 名,所以掃一次同時回答「要 query 誰」與「拿到之後問誰」。一個宣告都
沒有時說出來並停下——**不猜一個 org,不用占位字串當預設值**。
**命令裡的相對路徑,錨是宣告它的那份 `SKILL.md` 所在的目錄**,不是呼叫者當下的 cwd——核心
跑它之前會先切過去。宣告行寫得出來的只有相對路徑,而「相對於我自己」在 skill 被單獨帶到
別的環境時仍然成立,「這個 workspace 的 root 在哪」在那裡沒有答案。
宣告的命令要認得兩個模式,第一個參數就是模式名:
| 模式 | 進 | 出 |
|---|---|---|
| `notify --repo R` | 參數 | 這個 repo 的 PR 通知誰,格式由那一層自己定 |
| `ticket` | stdin:`repo⇥number⇥title⇥branch` | `repo⇥number⇥單號⇥單的 URL` |
`ticket` 走 TSV 而不是把 PR 的 JSON 丟過去:那個資料結構是這支 skill 的事,交出去等於逼
每一家公司的知識層都得認得它。**這裡不認得任何一家公司的單號長什麼樣**,也不該認得。
所以這裡沒有前置設定要人先準備,也不需要任何環境變數。author 沒指定時自己偵測:
```bash
MY_USER="$(gh api user --jq '.login')"
```
approval threshold 是公司 pack 的知識,不是這支 skill 的:幾票算看過了由那家公司說,寫在它自己
的 pack 裡(repo-notes 那支的 PR 與 review 慣例那一份)。`check-pr-approval-status.sh` 的
`--threshold` 沒給時用 2,公司 pack 說的數字不是 2 時就帶 `--threshold N`。以前這裡寫「讀
workspace config 的 shared defaults」並在 pipe 裡放一個 `$APPROVAL_THRESHOLD`——那個鍵從來
不存在,那個變數整支 skill 沒有人賦值,讀到的永遠是腳本的預設值。
## Bundled Scripts
路徑相對於本 skill 目錄。
| Script | 用途 | 輸出 |
|--------|------|------|
| `scripts/resolve-pr-context.sh` | `orgs` 列出被宣告的 org;`notify` / `ticket` 轉交給認領那個 org 的命令 | org 清單/那一層的答案 |
| `scripts/fetch-user-open-prs.sh` | 名下所有 open PR,含 org/base/head | PR JSON array |
| `scripts/check-pr-approval-status.sh` | approval 數、stale、被指名還沒看的 reviewer | 加上 approval 欄位 |
| `scripts/fetch-pr-review-comments.sh` | 還沒被回覆的 actionable comments | 加上 `unaddressed_comments` |
| `scripts/check-pr-ci-status.sh` | CI 狀態 | 加上 `ci` |
| `scripts/attach-pr-ticket.sh` | 這個 PR 屬於哪一張單 | 加上 `ticket` |
| `scripts/plan-pr-notify.sh` | 這批要通知哪裡,逐個 repo 給建議 | `repo⇥狀態⇥數量⇥目的地` |
Script 是 deterministic source;不要在入口重寫它們的 API、stale 或 bot filter 邏輯。
## Lazy-load Map
| 何時讀 | Reference | 用途 |
|--------|-----------|------|
| 產出報告、加 label、組通知訊息時 | `references/request-pr-review-reporting.md` | 報告表格、label 處理、訊息要說出哪幾件事 |
| 那份報告要分哪幾段、每一段寫什麼 | `references/report-format.md` | 交出去給人讀的報告共用的段落骨架 |
| 判讀 approval / stale 語意前 | `references/stale-approval-detection.md` | stale approval 的權威定義 |
| 訊息送出前 | `.claude/rules/style-and-language.md` | 語言關卡 |
## 1. Query:這批是哪些、狀態如何
一條 pipe 走完,每一段各補一類狀態:
```bash
"$SKILL_DIR/scripts/fetch-user-open-prs.sh" \
| "$SKILL_DIR/scripts/check-pr-approval-status.sh" \
| "$SKILL_DIR/scripts/fetch-pr-review-comments.sh" --author "$MY_USER" \
| "$SKILL_DIR/scripts/check-pr-ci-status.sh" \
| "$SKILL_DIR/scripts/attach-pr-ticket.sh"
```
結果為 `[]` 就回報沒有 open PR,結束。
**問不到的東西不會被讀成「沒問題」**,這是這一步的重點:
| 欄位 | 值 | 意思 |
|---|---|---|
| `branch_status` | `unreachable` | base/head 沒問到。不是「base 是預設分支」 |
| `ci.state` | `UNREACHABLE` | 這一趟沒問到 CI。**不是 PASS,也不是 NONE** |
| `ci.state` | `NONE` | 真的沒有設任何 check |
| `ticket` | `null` | 沒查出屬於哪張單。**不是「這個 PR 沒有單」**——那幾筆會被逐個指名 |
某個 org 整個問不到時,其餘 org 的結果照常回來,問不到的那些被逐個指名;全部問不到時
非 0 退出,而不是回一個看起來像「沒有 PR」的空陣列。
## 2. 列出來,讓使用者決定
報告要讓人**當場**決定,不用再去別的地方查。逐個 PR 給出:
- repo、編號、標題、連結
- **它屬於哪一張單**(`ticket.key` 與 `ticket.url`)。卡住的 PR 要回頭解問題時,那張單就是
去處。查不出來的標成「查不出」並且**不要寫成「沒有單」**——那是兩件事
- approval:`valid_approvals`/`threshold`,有 stale 要標出來
- 被指名但還沒回應的 reviewer(`requested_reviewers`)
- 還沒被回覆的意見數(`unaddressed_comments`)
- CI 狀態;`FAIL` 要帶上是哪幾個 check(`ci.failing`)
- 這個 PR 適不適合現在請人看,不適合的話卡在哪。**`unaddressed_comments` 不是 0 的不請票**:
reviewer 留的每一串含 nit 都要處置並回在原串(`swe-knowledge` 第 5 條),還沒做到就先做,
請人再看一次沒處理完的東西是浪費他的時間
- **`valid_approvals` 到了 `threshold`、`unaddressed_comments` 是 0、CI 綠的那幾顆,不是
「請人看」的候選,是「按 merge」的候選。** 誰按由公司 pack 說;
公司 pack 說作者按的,就直接按,不把「要不要 merge」列成待決
最後給出總數與 repo 分布。
**然後停下來等使用者選。** 沒有得到選擇之前不通知、不加標記、不動任何一個 repo。
**不自動挑一批送出去。** 判斷可以給,決定不代做。
## 3. 通知對的人
只處理使用者選中的那些。**先給出建議,再送**:
```bash
printf '%s' "$SELECTED" | "$SKILL_DIR/scripts/plan-pr-notify.sh"
```
它逐個 repo(不是逐個 PR)算出要送去哪,輸出 `repo⇥狀態⇥數量⇥目的地`。**把這份建議連同
目的地一起給使用者看過再送**——目的地是通知的一半,一個沒被看過的目的地跟沒被選過一樣。
退出碼 4 的意思是「我答完我答得出的,剩下這幾個要你給」,**不是壞掉**:
- **`known`** → 照宣告那一支 skill 自己的說明送出。**怎麼送、送到哪、訊息長什麼樣,都是
那一層的事**——這支 skill 不認得任何一個目的地的形狀。目的地那一欄裡指出一份訊息版型時
就去讀它,照它說的形狀組;沒有版型的話說出來,不要安靜地自己定一個形狀。
- **`unknown`** → 對使用者說出「這幾個 repo 我不知道要通知誰」,把宣告那一層印出來的
修法原樣附上,**問他要一個目的地**。不猜一個,也不沿用別的 repo 的——同一個 org 底下
不同 repo 送去不同地方是常態。
- 拿到答案之後**當下記下來**,照宣告那一層說的方式(訊息裡會寫)。只用在這一次的話,
下一次會再問一次同樣的問題,而被問的人會以為自己上次沒講清楚。
一個 repo 問不到不擋其餘的:其他 repo 照常送,問不到的那幾個等答案。
**訊息的預設形狀是每個 PR 的標題與連結,加一句請人看,沒有別的。** 要多說必須說得出
「讀的人不看這段就決定不了要不要點進去」,而且形狀是一個 PR 一行。approval 數、逐位
reviewer 狀態、CI、施工過程都不進通知——那些在上一步給使用者看的那份報告裡。判準與正反例
在 `references/request-pr-review-reporting.md` 的〈通知訊息〉。
**沒有任何東西在擋長訊息**,語言關卡只驗語言。這是刻意的:寫的人自己負責。
送出前把訊息寫成 temp markdown 並通過語言關卡:
```bash
bash "$SKILL_DIR/scripts/validate-language-policy.sh" --blocking --mode artifact <訊息檔>
```
送完之後逐個回報:送出去的是哪幾個、送到哪、成功與否。**送不出去要說出來**,不能只報成功
的那些。
## Hard Safety Rules
- **不動任何一個 repo 的 git 狀態**:不 rebase、不 push、不切分支、不 stash。base 過期是
報告上的一行,要不要處理是使用者的決定。
- 不自動修正 CI failure 或 review comments。
- 不代替使用者決定要通知誰、通知哪幾個。
- 不使用 `gh pr view --json reviews` 取代 bundled approval script。
- 不使用 `gh pr checks --json` 取代 bundled CI script。
- 不把問不到的狀態讀成通過——`UNREACHABLE` 不是 `PASS`。
- 不通知已達標的 PR。
- 不把「已達標」寫成「可 release / 已完成」。
- 不忽略 stale approval。
- 不把未通過語言關卡的訊息送出。
- 訊息不使用「催促」、「催」、「趕快」等字眼;用「麻煩大家幫忙」、「有空幫忙看一下」。
<!-- PROSE-EXTERNAL-PATHS: docs-manager/ — 動手對象:那是 specs 站台自己的 repo,這支 skill 往它寫東西、讀它的結構,不是我們抄一份放著的知識 -->
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!