在 Windmill 仓库中落地本地 AI 代码审查:local-review Skill 的冷上下文子代理工作流
2026/9/15 9:28:33 网站建设 项目流程

在 Windmill 仓库中落地本地 AI 代码审查:local-review Skill 的冷上下文子代理工作流

【免费下载链接】windmillOpen-source developer platform to power your entire infra and turn scripts into webhooks, workflows and UIs. Fastest workflow engine (13x vs Airflow). Open-source alternative to Retool and Temporal.项目地址: https://gitcode.com/GitHub_Trending/wi/windmill

本文围绕 Windmill 开源仓库中的.agents/skills/local-review/SKILL.md技能文档展开,系统讲解如何在本地复现 GitHub CI 自动代码审查(Claude / Codex / Pi 三套评审器)的效果:为什么必须用"冷上下文"子代理来跑审查、完整的四步执行流程、子代理 Prompt 模板、统一的输出格式,以及如何通过gh把结果回写到 PR。读完本文,你将掌握一套可直接复用的、与 CI 完全同策略的本地 AI 审查工作流,并理解其背后的REVIEW.md共享策略与安全设计。

一、为什么要用"冷上下文"子代理做本地审查

Windmill 仓库的 GitHub 自动审查动作会在每个 PR 上运行 Claude / Codex / Pi 三套 AI 评审器,而 local-review 技能 的存在意义,就是让开发者能在本地跑出与 CI 相同质量的审查。

技能文档中给出了一个非常关键的设计理由:审查必须在全新上下文中运行,而不是在当前的会话内联执行。如果开发者刚刚在 diff 上反复迭代,主会话已经吸收了作者的推理和"合理化解释",会产生锚定效应(anchoring)——审查者会顺着作者思路走,漏掉 CI 能够抓住的问题。子代理以冷启动的方式开始工作,就像 CI 一样"一无所知",因此更容易发现主会话会本能忽略的缺陷。

从 AGENTS.md 的说明可以看到,这个技能的编排逻辑在三种 CLI 中是共享的:Claude Code 通过.claude/skills/符号链接读取技能文件,Codex 和 Pi 直接读取.agents/skills/。调用方式分别为:

  • Claude Code:/local-review
  • Codex:$local-review(或/skills选择器)
  • Pi:pi --skill local-review/skill:local-review

技能的前置元数据(frontmatter)也明确约束了使用时机:description字段写明 "Code review the current PR (or branch diff against main) for bugs, security, and AGENTS.md compliance. MUST use when asked to review code."——即一旦用户要求审查代码,就必须走这套流程。

二、完整工作流程:四个步骤

local-review 技能把整个审查编排拆成四个阶段,其中"确定 PR 范围"这一步成本低,在主会话中完成;其余步骤全部交给冷上下文的子代理。

第 1 步:确定 PR 范围(主会话内完成)

  • 如果提供了参数,把它当作 PR 编号或分支名;
  • 否则从当前分支与main的差异中自动检测;
  • gh pr view <n>git rev-parse <branch>确认 PR / 分支确实存在。

第 2 步:委派给冷上下文子代理

将审查委托给一个全新的子代理,Prompt 必须自包含,包含以下要素:

  • 要审查的 PR 编号或分支名;
  • 指令:先读REVIEW.md获取策略,再读 diff 触及目录下的所有AGENTS.md
  • 精确的输出格式(见下文第四节);
  • 是否请求了--comment(若需要则让子代理产出行内评论 JSON);
  • 用户提供的任何"附加审查者指令(Additional reviewer instructions)"。

不同 CLI 的实现方式不同,技能文档给出了明确指引:

  • Claude Code:使用Agent工具,subagent_type: branch-diff-reviewer(只读工具、专为此场景设计);若不可用则回退到general-purpose
  • Codex / Pi:若 CLI 暴露了全新会话的子代理机制则使用它;否则直接告诉用户在全新的 CLI 会话中运行该技能并停止——在当前会话内联执行会破坏"冷上下文"的意义。

第 3 步:原样接收子代理的发现

收到子代理的结果后逐字转达给用户,不做重新总结、不再二次判断、不筛选。整个"冷上下文"方案的全部价值,就在于把主会话会轻易忽略的问题暴露出来,任何过滤都等于前功尽弃。

第 4 步:按需发布评论(--comment

如果用户请求了--comment,由主会话负责发布(因为子代理是只读的),具体命令见本文第五节。

三、子代理 Prompt 模板

技能文档提供了一个可直接复用的自包含 Prompt 模板,核心是 7 个步骤:

Review <PR #N | branch X> against main per the policy in REVIEW.md. Steps: 1. Read REVIEW.md (repo root) for the full policy: severity triage, public-surface checklist, AGENTS.md compliance, test coverage assessment. 2. Read AGENTS.md (repo root) and any AGENTS.md in directories touched by the diff. 3. Get the diff: `gh pr diff <N>` (if PR) or `git diff main...<branch>`. 4. Get context: `gh pr view <N>` (if PR) or `git log main..<branch> --oneline`. 5. Read changed files only when the diff alone is insufficient to validate a finding. 6. Self-validate each finding: "is this definitely a real issue a senior engineer would flag?" Discard if uncertain. 7. Output findings in the exact format below. Do not modify any files. <paste output format from below> <if --comment requested:> Additionally emit a JSON array of inline comments suitable for the GitHub reviews API, one per finding that maps to a specific line: [{"path": "...", "line": N, "side": "RIGHT", "body": "[P1] ..."}, ...]

这个模板有几个值得注意的工程细节:

  • 第 1、2 步强制先读策略再审查REVIEW.md是共享审查策略(见第四节),AGENTS.md是被 diff 触及目录的"贡献者规则",审查时引用规则原文;
  • 第 5 步限定阅读范围:只有 diff 不足以验证某个发现时才去读完整文件,避免审查者陷入整仓上下文;
  • 第 6 步要求自校验:每个发现都要过一遍"资深工程师是否真的会标记这个问题",不确定就丢弃——这直接对应REVIEW.md中 "Only report issues you are confident are real" 的策略;
  • 第 7 步"不修改任何文件":子代理是只读审查者,写操作一律留给主会话。

四、共享审查策略 REVIEW.md:裁决、分级与检查清单

REVIEW.md是 local-review 与 CI 自动审查共用的单一策略源,本地技能与 codex-pr-review CI 工作流 都直接以它为审查依据。

4.1 裁决行(Verdict)——每条审查的第一行

每条审查必须以单个裁决行开头(唯一允许出现在裁决行之上的内容是可选的对作者 @ 提及):

  • Good to merge——无阻塞问题,也没有值得提出的 nit;
  • Mergeable, but should ideally address nits: <short list>——无阻塞项,但存在值得一看的 P2 发现,需在列表中逐条点名(例如 "doc/code mismatch infoo.rs, half-finishedpub fn bar");
  • Should address issues before merging: <short list>——至少一个 P0 或 P1 发现,需在列表中逐条点名阻塞问题(例如 "missing auth check on new/api/xhandler, SQL injection inbuild_query")。

列表中的名称必须与正文中的发现一一对应:出现在裁决里的必须带完整上下文出现在正文,正文里的阻塞项必须浮现在裁决中。

4.2 触发作者提醒

如果 Prompt 上下文提供了PR AUTHOR(GitHub 登录名),且裁决不是 "Good to merge",则在顶层审查评论中、裁决行之前加一行cc @<PR_AUTHOR>;裁决为 "Good to merge" 时跳过(作者无事可做)。行内评论不加 @ 提及,它只属于顶层汇总评论。

4.3 审查策略

  • 只报告确有把握、且由本 PR 引入的问题;
  • 聚焦 bug、安全问题、性能和明确的AGENTS.md违规;
  • 不报告风格 nit、推测性担忧、既有问题,或 linter / 类型检查器显然能抓到的内容;
  • 发布前自校验:"这真的是问题吗?"不确定就丢弃;
  • diff 不足以验证时再读额外文件;
  • 不修改任何文件

4.4 严重度分级(P0 / P1 / P2)

这是整个策略的核心,也是 CI 裁决的依据:

级别含义典型场景
P0致命安全/数据问题RCE、认证绕过、数据丢失、代码中的密钥、SQL 注入、路径穿越、公开面上的认证破坏
P1显著缺陷明显 bug、新公开面缺少认证/授权检查、在可能的异步路径上做阻塞 I/O、竞态条件、对调用方可控参数缺少输入校验、可观察的性能回退
P2结构/风格问题模块放置错误、文档与代码不一致、未完成的公开抽象(pub fn+#[allow(dead_code)]+TODO)、AGENTS.md风格违规、命名与函数行为矛盾

P0 和 P1 必须上报;P2 仅在 diff 邀请时才报(新增pub fn、新模块、新导出的组件、有意义的重构)。

4.5 新公开面检查清单

对本 PR 引入的任何pub fn/pub async fn/ 导出的 Svelte 组件 / 导出的 prop,逐项核查:

  • (a) 认证/授权:doc 注释中写明授权预期,或在函数体内强制执行。一个触及工作区数据、密钥、文件或进程、却没有认证检查或 "caller MUST verify" 契约的pub fn,属于 P1;
  • (b) 模块归属:函数是否放在模块职责相符的位置(对照模块级//!文档注释)——比如 config 读取器被放进external_ip.rs属于 P2;
  • (c) 是否半成品pub fn+#[allow(dead_code)]+TODO组合说明该函数应与其调用方一起落地,并引用相关AGENTS.md规则;
  • (d) 输入校验:每个调用方可控的参数都要防御注入 / 路径穿越 / 溢出 / NUL 字节。

4.6 测试覆盖评估

每条审查的结尾必须有一个简短的 "Test coverage" 小节,按 diff 实际触及的层次校准,未触及的类别直接跳过:

  • 后端backend/下的 Rust):新逻辑期望有 Rust 单元测试;新增/修改 API 处理器、worker 步骤、队列/定时行为、DB 访问时,还要期望(或指出缺失)集成测试;纯重构 PR 若现有测试已覆盖则无需新增;
  • 前端frontend/下的 Svelte / TS):代码库一般不测试 Svelte 组件,不要要求组件测试;只为新增的纯逻辑工具(如已有*.test.ts兄弟文件的flowDiffpreviousResults、copilot 逻辑)标记缺失测试;
  • CI / 工作流 / 文档 / 纯配置:不期望自动化测试,但要明确说明"已考虑过"。

随后说明合并前还需要哪些手工验证:每个手工场景用一小段话描述(哪个页面 / 动作 / 输入,什么可观察结果能证明正确性);若 diff 没有可操作的应用面(纯后端内部、CI、文档或重构),直接说明。

4.7 附加指令与历史讨论

  • 若 Prompt 包含 "Additional reviewer instructions" 小节,视为触发审查的人给出的额外指引,必须遵循;
  • 若包含 "Prior PR discussion" 小节,说明该 PR 已有审查活动:找到自己之前的评论并考虑在内,聚焦最新提交的变化,不重复人类已反驳或已解决的问题。

五、发布评论:gh命令实操

当用户请求--comment时,主会话负责发布。技能文档给出了两类命令。

顶层 PR 评论

gh pr review --comment --body "<summary from subagent>"

特定行内评论(使用子代理产出的 JSON 数组):

gh api repos/{owner}/{repo}/pulls/{pr}/reviews \ -f body="<summary>" -f event="COMMENT" -f comments="<json from subagent>"

行内评论 JSON 的格式即第三节模板中约定的结构:{"path": "...", "line": N, "side": "RIGHT", "body": "[P1] ..."}

六、输出格式规范

子代理必须严格遵循以下输出格式(以## Code review开头):

## Code review <verdict line per REVIEW.md> Found N issues: 1. [P0|P1|P2] <description> <file_path:line_number> 2. [P0|P1|P2] <description> <file_path:line_number>

并以 "Test coverage" 小节结尾。未发现问题时的输出模板:

## Code review Good to merge. No issues found. Checked for bugs, security, and AGENTS.md compliance.

这个格式与 CI 侧的 Codex 输出格式保持同构——.github/codex/pr-review.prompt.md规定 CI 评审输出必须以## Codex Review开头、按 P0/P1/P2 标注严重度并给出文件路径与行号,本地与远端只是标题前缀不同。

七、Codex 对应物:local-review-codex(推前审查)

仓库中还提供了 local-review-codex 技能,它在推送到远端之前,用与 CI 中codex-pr-reviewGitHub Action完全相同的策略和推理强度,对"尚未推送的工作"(已提交 + 未提交)做一次本地 Codex 审查。

与 CI 的对应关系(完全一致的部分)

  • 策略:REVIEW.md(严重度分级、公开面检查清单、AGENTS.md 合规、测试覆盖);
  • 推理强度:model_reasoning_effort="xhigh"
  • 输出:以## Codex Review开头的 Markdown,发现按 P0 / P1 / P2 标注并带 file:line。

与 CI 的差异(仅本地特有)

  • 本地模型为gpt-6-astra,CI 保持gpt-5.6-sol;这不是遗漏——gpt-6-astra已确认在本地codex login使用的 ChatGPT 认证上可用,而 CI 用OPENAI_API_KEY认证、该层级对该模型未验证;
  • 范围是当前分支与main在 merge-base 处的差异,包含未提交的改动(CI 审查的是已推送的 PR diff);
  • 沙箱为read-only(CI 在临时 runner 上用danger-full-access),Codex 只能读 diff 和文件,不能改动工作树;
  • 冷上下文天然成立:codex exec是独立冷进程,不会锚定当前聊天会话——与 local-review 坚持子代理是同一个理由。

运行方式与前置条件

bash .agents/skills/local-review-codex/run.sh # review vs main (default) bash .agents/skills/local-review-codex/run.sh <base> # review vs a different base ref

前置条件包括:codexCLI>= 0.153.4且已通过codex login认证(环境中存在OPENAI_API_KEY时其优先级更高,但可能无法访问gpt-6-astra);用git fetch更新 base ref 以保证 merge-base 准确。旧版 CLI 会以 "requires a newer version of Codex" 拒绝该模型,run.sh 会预先检查版本。

run.sh 的实现细节

从源码看,run.sh 有若干值得学习的工程处理:

  • 版本预检:解析codex --version并做语义化版本比较,|| true保证解析失败时不会在set -e下中止——"无法判断版本"应当放行到 exec,而不是杀死审查;
  • 认证告警OPENAI_API_KEY存在时打印警告,因为认证优先级可能导致模型不可用,且报错会指向模型而非真正的认证问题;
  • base 引用回退:优先本地 ref,回退origin/<base>,兼容 CI / 单分支克隆只有origin/main的情况;
  • merge-base 定位:用git merge-base HEAD <base>计算 BASE_SHA,git diff <BASE_SHA>会把未提交的工作树改动一并折入;
  • 未跟踪文件单独收集git ls-files --others --exclude-standard——git diff永远看不到未跟踪文件,而全新模块、新技能目录这样的整目录新文件不能被静默跳过,Prompt 中明确指示对每个未跟踪路径直接cat阅读、视为全部新增;
  • 零工作树污染:Prompt 与输出都写入mktemp临时文件,trap 'rm -f ...' EXIT清理,仓库中不落任何临时文件;
  • 无改动提前退出:BASE_SHA 与 HEAD_SHA 相同且无未跟踪文件时输出 "No changes vs main — nothing to review" 并退出 0。

八、与 CI 自动审查的关系:从本地到 GitHub Actions

local-review 的初衷就是"在本地跑出 CI 会跑的审查"。对照 codex-pr-review.yml,可以看到 CI 侧如何把同一策略工程化:

  • 认证选择:优先OPENAI_API_KEY,其次CODEX_AUTH_JSON,都未配置则跳过 Codex 审查;
  • Fork PR 安全边界:自动pull_request触发从不审查 fork PR(fork 代码运行在带密钥的环境中不可信);只有维护者通过/codex评论走workflow_call路径才允许审查 fork,且 fork 路径从 base ref 读取审查策略(git show origin/$PR_BASE_REF:REVIEW.md)并切换到workspace-write沙箱、禁用网络以阻断密钥外泄;
  • ready_for_review 去重:代理驱动的 PR 只有经过干净的/review轮次并带有作者标记评论才会转为 ready;CI 通过"作者标记 + 早于标记的 github-actions[bot] Codex 非阻塞裁决"双重证据跳过冗余复审;
  • 凭据脱敏:发布评论前用防御性逻辑把泄漏进评审文本的 API 密钥、auth JSON、token 全部替换为[REDACTED]
  • EE 代码替换:持有WINDMILL_EE_PRIVATE_ACCESS时先 checkoutwindmill-ee-private并用./backend/substitute_ee_code.sh --copy替换 EE 代码,保证审查针对的是完整编译树。

本地 local-review-codex 与 CI 的对应关系是刻意保持的:CLI 版本在两侧相同(都钉在 0.153.4),只有模型不同,因此本地推前审查可以看作"在 PR 存在之前就先跑一遍 CI 会跑的 Codex 评审"。

九、在 PR 提交流程中的位置:与 pr 技能的集成

pr 技能 把 local-review 与 local-review-codex 明确纳入了开 PR 的标准流程:创建 draft PR 前,必须同时跑两套审查、不可跳过——

  • local-review:Claude 原生的 branch-diff-reviewer 子代理审查;
  • local-review-codex:与 CI 完全同策略的冷 Codex 审查,提供 Claude 视角看不到的独立观点(codexCLI 缺失或版本过旧时在总结中说明并继续,绝不阻塞 PR)。

两者捕获的问题类型不同,任一者发现问题就先修复再提交。随后的"审查轮次(draft → ready)"同样以REVIEW.md的三种裁决驱动:review-round.sh 通过/review评论触发 CI 上的 Codex、Claude、Pi 评审器(draft 上也可运行),等待工作流完成后每个评审器打印一行裁决;出现任何 "Should address issues before merging" 就修复 P0/P1 并开启新轮次;全部干净后以✅ Review round clean @ <head-sha>标记评论 +gh pr ready翻转。

这一整套设计表明,local-review 不是孤立的技巧,而是 Windmill 仓库"本地推前审查 → CI 多评审器轮次 → 干净后才合并"质量闭环中的第一道闸门。

十、小结

回顾 local-review 技能的核心设计,可以提炼出三条可迁移到任何仓库的实践原则:

  1. 冷上下文优于热上下文:AI 审查的价值来自"不知道作者意图"的客观视角,内联在当前会话中的审查会被锚定效应污染——这是本技能存在的最根本理由;
  2. 策略单一化REVIEW.md作为唯一的审查策略源,本地子代理、本地 Codex、CI 的 Codex/Claude/Pi 全部共用,裁决行、P0/P1/P2 分级、公开面检查清单、测试覆盖评估在所有入口保持一致,避免"本地与 CI 结论打架";
  3. 输出可机器消费:统一的## Code review格式 + 带 file:line 的分级发现 + 行内评论 JSON,让主会话可以直接把子代理结果透传给gh,实现"冷审查、热发布"的分工。

对于希望给自己的开源项目建立 AI 审查管线的团队,Windmill 仓库中 local-review、local-review-codex、REVIEW.md 以及 codex-pr-review.yml 四份文件构成了一套完整、可对照、可复制的参考实现。

【免费下载链接】windmillOpen-source developer platform to power your entire infra and turn scripts into webhooks, workflows and UIs. Fastest workflow engine (13x vs Airflow). Open-source alternative to Retool and Temporal.项目地址: https://gitcode.com/GitHub_Trending/wi/windmill

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询