ci-review · diff

git:20260902.7e9351b to git:20260903.ba8990e

96 added, 23 removed. Audit A to A.

---
name: ci-review
description: |
- Install a CI-triggered LLM code reviewer into the current repo: on every push to a PR/MR, Claude Code runs headless, reproduces every claim the change makes ("tests pass", "verified", "supports X"), hunts correctness bugs with concrete failure scenarios, and posts inline comments plus one sticky summary. It judges execution, not direction — the other half of the do-something flywheel. GitHub (anthropics/claude-code-action) and GitLab CI templates. Use when the user says /ci-review, 装一个 CI 代码审查, CI 里自动 code review, 给 PR/MR 加 AI review, 让机器人验证 PR.
+ Install a CI-triggered LLM code reviewer into the current repo: on every push to a PR/MR, Claude Code runs headless, reproduces every claim the change makes ("tests pass", "verified", "supports X"), hunts correctness bugs with concrete failure scenarios, and posts inline comments plus one sticky summary with a machine-readable verdict. Two tiers chosen at install and remembered in the repo: review-only, or auto-merge bot branches (do/* by default) when the verdict passes and no thread is open. Detects GitHub vs GitLab from origin, asks only for what is missing, sets the CI variables itself. Judges execution, not direction — the other half of the do-something flywheel. Use when the user says /ci-review, 装一个 CI 代码审查, CI 里自动 code review, 给 PR/MR 加 AI review, 让机器人验证 PR, 审查通过自动合并.
trigger: /ci-review
compatibility: Claude Code
license: MIT
---
# ci-review
给仓库装一个只回答一个问题的审查机器人:**这次改动宣称做到的事,真的做到了吗?**
它和人类 reviewer 分工:方向、取舍、值不值得做,是人的事;
声明能不能复现、diff 里有没有能写出失败场景的缺陷,是它的事。
配合 do-something 的 MR 模式即成飞轮:do-something 提出方向并实践,ci-review 验证实践质量,
- do-something 下一轮先回应它的评论。人类只在想收割时出现。
+ do-something 下一轮先回应它的评论。开"通过即合并"档后,机器人分支的收割也由机器完成,人类只在想否决时出现。
## 触发条件
- `/ci-review`:装进当前仓库(幂等,已存在的文件不覆盖;`/ci-review --force` 覆盖)。
- - `/ci-review status`:检查已安装的文件与 secrets 是否齐全。
+ - `/ci-review status`:检查文件、合并档位、secrets/variables、最近运行。
+ - `/ci-review merge on|off`:改合并档位。
- ## 安装
+ ## 安装流程
- 依赖检查放最前:当前目录是 git 仓库且有 origin,否则停下说明。
+ 脚本只做确定性的事(识别平台、写文件、改档位、报状态);问用户、设变量由你做。
+ ### 1. 依赖检查
+
+ 当前目录是 git 仓库且有 origin,否则停下说明。GitHub 需要 `gh auth status` 通过,GitLab 需要 `glab auth status` 通过;
+ 未登录就只装文件,变量留给用户手设。
+
+ ### 2. 装文件
+
```bash
- bash <本 SKILL.md 所在目录>/scripts/install.sh [仓库路径] [--force]
+ bash <本 SKILL.md 所在目录>/scripts/install.sh [仓库路径] [--force] [--platform github|gitlab] [--merge on|off]
```
- 脚本按 origin 判平台,复制两个文件并打印下一步:
+ 脚本按 origin 主机名判平台:含 `github.com` → GitHub;含 `gitlab` → GitLab(自建实例也算);
+ 判不出退出码 2。此时用 AskUserQuestion 问"这个仓库托管在哪"(GitHub / GitLab),带 `--platform` 重跑。
| 平台 | CI 配置 | 审查规范 |
|---|---|---|
| GitHub | `.github/workflows/ci-review.yml`(官方 `anthropics/claude-code-action@v1`) | `.github/ci-review.md` |
| GitLab | `.gitlab/ci-review.yml`(`claude -p` 头less,需 `include:`) | `.gitlab/ci-review.md` |
- 审查规范就是 `prompts/review.md` 的副本,落在仓库里供按口味修改;CI 里的 Claude 读它执行。
+ 审查规范是 `prompts/review.md` 的副本,落在仓库里供按口味修改;CI 里的 Claude 读它执行。
- **Secrets 由人设置,脚本只打印清单,不代替。** 模型接入默认走"Anthropic 兼容网关 + API key",
- 不占 Claude 订阅额度:GitHub 用 secret `CI_REVIEW_API_KEY` + 变量 `CI_REVIEW_BASE_URL`、`CI_REVIEW_MODEL`;
- GitLab 用 CI 变量 `ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_BASE_URL`、`ANTHROPIC_MODEL`。
- base URL 留空即官方 Anthropic;想烧 Pro/Max 额度改用 `claude setup-token` 生成的 `CLAUDE_CODE_OAUTH_TOKEN`。
- GitLab 额外需要 `GITLAB_TOKEN`(项目访问令牌,api scope),因为 `CI_JOB_TOKEN` 不能发 MR 评论。
- 审查是工具调用密集型任务,网关上选支持 tool use、上下文够大的模型。
+ ### 3. 问合并档位(仅首次写入 CI 文件时问)
- 安装完成后必须告诉用户:还差哪些 secret、怎么设、开一个 PR/MR 才能看到第一次运行。
+ CI 文件已存在 → 档位以文件里 `CI_REVIEW_MERGE` 为准,不再问,这就是"记住上次选择"。
+ 首次安装 → 用 AskUserQuestion 问一次,两档:
+ | 档位 | 行为 | 选后执行 |
+ |---|---|---|
+ | 仅审查 | 发评论 + 结论,合不合人定 | `install.sh merge off`(默认,可不跑) |
+ | 通过即合并 | 结论 pass 且无未解决线程 → 自动合并,**仅限 `do/*` 分支** | `install.sh merge on` |
+
+ 选"通过即合并"前,用一句话向用户复述后果:机器人分支每次 push 通过审查后几分钟内进默认分支,
+ 人类的收割闸门消失,否决手段变成 revert、关掉档位、或在 PR 里留一条不 resolve 的线程。
+
+ ### 4. 问模型接入(仅缺变量时问)
+
+ 先跑 `install.sh status` 看哪些没设。认证 secret 和网关变量都已有 → 跳过本节。
+ 缺网关变量 → 用 AskUserQuestion 问"模型走哪里":
+
+ | 选项 | BASE_URL |
+ |---|---|
+ | 官方 Anthropic | 留空 |
+ | 智谱 GLM | `https://open.bigmodel.cn/api/anthropic` |
+ | MiniMax | `https://api.minimaxi.com/anthropic` |
+ | DeepSeek | `https://api.deepseek.com/anthropic` |
+ | 其他 Anthropic 兼容网关 | 用户填 |
+
+ 再问模型名(网关上的名字,留空 = CLI 默认)。审查是工具调用密集型任务,提醒用户选支持 tool use、上下文够大的模型。
+ 问完直接设:
+
+ ```bash
+ # GitHub
+ gh variable set CI_REVIEW_BASE_URL --body "<url>" # 官方 Anthropic 则跳过
+ gh variable set CI_REVIEW_MODEL --body "<model>"
+ # GitLab
+ glab variable set ANTHROPIC_BASE_URL "<url>"
+ glab variable set ANTHROPIC_MODEL "<model>"
+ ```
+
+ **API key 不经对话传递**:对话记录明文落盘。让用户在自己的终端里交互式设置,设完你再跑 `status` 确认:
+
+ ```bash
+ gh secret set CI_REVIEW_API_KEY # GitHub,粘贴后回车
+ glab variable set ANTHROPIC_AUTH_TOKEN --masked # GitLab
+ glab variable set GITLAB_TOKEN --masked # GitLab 还要项目访问令牌,api scope;仅审查 Reporter 以上,自动合并 Developer 以上
+ ```
+
+ 想烧 Pro/Max 订阅额度而不是 API key:`claude setup-token` 生成 `CLAUDE_CODE_OAUTH_TOKEN`,按 CI 文件顶部注释改认证字段。
+
+ ### 5. 提交并告知
+
+ 只提交这两个文件(CI 配置 + 审查规范),GitLab 还要在 `.gitlab-ci.yml` 里加 `include: - local: .gitlab/ci-review.yml` 并确认 stages 有 `test`。
+ 最后跑 `install.sh status`,把仍缺的项原样告诉用户,并说明:push 后开一个 PR/MR 才能看到第一次运行。
+
+ ## 合并档位怎么工作
+
+ 合并**不经模型**。模型只在 sticky 第一行写 `<!-- ci-review last=<sha> verdict=pass|fail -->`,
+ CI 里一段普通 shell 核对四个条件,全满足才合并:
+
+ 1. 来源分支匹配 `CI_REVIEW_MERGE_BRANCHES`(默认 `do/*`,空格分隔的 glob;想覆盖所有 PR 改成 `*`)。
+ 2. sticky 的 sha 等于本次 HEAD,且 `verdict=pass`。
+ 3. 无未解决的评审线程(人和机器人的都算)。do-something 与机器人来回 5 轮后会回"留人裁决"停手,那条线程留着就挡住合并。
+ 4. 合并方式 `CI_REVIEW_MERGE_METHOD`(默认 squash)是仓库允许的。
+
+ `pass` 的定义写死在审查规范里:结论"做成了"、本轮 inline 为 0、且至少验证过一条声明;纯文档改动直接 pass;
+ **没有可验证声明就是 fail**,没声明就没验证,不能凭信任合并。
+
+ 模型的 allowedTools 里没有合并权限,PR 正文里的注入最多骗它写个 `pass`,还得过分支和线程两关。
+ 所有档位设置都在 CI 文件顶部,改档位 = 一次 commit,历史可查。
+
## `status` 检查
```bash
- ls .github/workflows/ci-review.yml .github/ci-review.md 2>/dev/null || ls .gitlab/ci-review.yml .gitlab/ci-review.md
- gh secret list 2>/dev/null | grep -E 'CI_REVIEW_API_KEY|CLAUDE_CODE_OAUTH_TOKEN' || echo "缺认证 secret"
- gh variable list 2>/dev/null | grep -E 'CI_REVIEW_BASE_URL|CI_REVIEW_MODEL' || echo "未设网关变量,将走官方 Anthropic"
- gh run list --workflow ci-review --limit 3 2>/dev/null # 最近三次运行
+ bash <本 SKILL.md 所在目录>/scripts/install.sh status
```
+ 输出平台、两个文件是否在、合并档位与范围、secrets/variables 是否设、最近三次运行(GitHub)。
+
## 审查行为(写在 prompts/review.md,此处只列不变量)
- - 范围增量:sticky 总结里记 `<!-- ci-review last=<sha> -->`,下次只审这个 sha 之后的 diff,不重复评论。
+ - 范围增量:sticky 里记 `last=<sha>`,下次只审这个 sha 之后的 diff,不重复评论。
- 先验证声明再找缺陷:正文、commit message、DO.md 日志里的"验证过了"逐条亲自复现。
- 每条发现必须有失败场景,否则不发;风格、命名、"可以考虑"一律不报。
- - 只发评论,不改代码、不 approve、不 request changes。
+ - 只发评论和 verdict,不改代码、不 approve、不 request changes、不合并。
- 评论正文以 `<!-- ci-review -->` 开头,do-something 据此识别机器人线程并对回合数设上限。
## 调口味
- 改审查规范:直接编辑仓库里的 `.github/ci-review.md` 或 `.gitlab/ci-review.md`,下次 push 生效。
- - 换模型或换网关:改仓库变量 `CI_REVIEW_MODEL` / `CI_REVIEW_BASE_URL`(GitLab 改 CI 变量),不用动 workflow。
+ - 换模型或换网关:改仓库变量 `CI_REVIEW_MODEL` / `CI_REVIEW_BASE_URL`(GitLab 改 CI 变量),不用动 CI 文件。
+ - 改合并范围或方式:改 CI 文件顶部的 `CI_REVIEW_MERGE_BRANCHES` / `CI_REVIEW_MERGE_METHOD`。
- 降成本:`concurrency.cancel-in-progress` 已开,连续 push 只审最后一次。
## 错误处理
- Action 报认证失败 → secret 名与 workflow 里 `with:` 字段不匹配,二选一改齐。
- 网关返回 401 → 该网关只认 Bearer 头或只认 x-api-key;模板两种都发,检查 key 是否属于该网关。
- 网关返回 model not found → `CI_REVIEW_MODEL` 写的是官方 ID 而非网关上的名字。
- 报 "Claude Code is not installed on this repository" → workflow 里的 `github_token` 行被删了却没装 Claude GitHub App,二者留一个。
- 评论没出现但 job 成功 → 看 job 日志里 Claude 的输出;常见是 `--allowedTools` 缺 `mcp__github_inline_comment__create_inline_comment`。
- - GitLab 发评论 401/403 → `GITLAB_TOKEN` 权限不够,需要 api scope 且 Reporter 以上。
+ - 合并步骤报 "Resource not accessible by integration" → 仓库 Settings → Actions → Workflow permissions 改成 Read and write。
+ - 合并步骤两次都失败、提示 required status checks / auto-merge not allowed → 分支保护把本 workflow 设成了必需检查,仓库要开 "Allow auto-merge",脚本会退回 `--auto`。
+ - 合并后默认分支上的 `on: push` workflow 没跑 → GITHUB_TOKEN 触发的事件不会再触发 workflow,这是 GitHub 的防递归规则;需要的话把合并 token 换成 PAT。
+ - 通过了却没合并、日志说"未解决线程" → 有人或机器人留了线程没 resolve,这是设计:留人裁决。
+ - GitLab 发评论 401/403 → `GITLAB_TOKEN` 权限不够,需要 api scope 且 Reporter 以上;合并 405 → 令牌不到 Developer,或目标分支受保护。