1. 项目概述一个基于确定性规则的PR风险扫描工具在团队协作中代码审查Code Review是保障代码质量、控制风险的核心环节。然而随着项目规模扩大和变更频率加快人工审查的负担越来越重尤其是在面对一个包含数十个文件、数百行代码的Pull Request时审查者很容易因为疲劳或疏忽而遗漏关键风险点。市面上涌现了不少“AI代码审查”工具它们通常的做法是将整个PR的Diff直接扔给一个大语言模型LLM然后问它“这个PR有什么风险”。这种做法听起来很智能但实际用起来却常常让人心里没底。LLM就像一个知识渊博但缺乏具体业务背景的实习生它可能擅长总结代码变更、生成描述性文字但对于“什么变更对我们团队是真正危险的”这个问题它往往只能给出泛泛而谈的建议或者更糟——产生幻觉遗漏掉那些只有团队内部才知道的“高压线”。问题的核心在于团队的风险容忍度和特定业务逻辑这些关键上下文信息并不存在于LLM的训练数据中。pr-review-prep这个项目正是为了解决这个痛点而生。它不是一个试图用AI替代人类判断的“黑盒”而是一个将确定性规则与智能辅助清晰分离的协作工具。其核心思想非常直接用简单、透明、可审计的Shell脚本来定义“风险是什么”然后用LLM基于这些明确的风险信号来生成结构化的审查清单和引导性问题。简单来说它把工作流程拆成了两步风险识别机器做规则驱动通过一个大约60行的Bash脚本scripts/risk-scan.sh使用grep等标准工具基于文件路径、命名模式等启发式规则确定性地标记出PR中可能涉及风险的变更。每一条规则都是一行可读的、可提交到Git进行代码审查的配置。清单生成AI辅助语言增强LLM的角色被限定在它擅长的领域组织语言。它接收上一步产生的“风险标签”和PR的原始信息标题、描述、作者等然后生成一份清晰、易读的Markdown格式审查清单并提炼出PR描述中需要澄清的开放性问题。这种架构带来的最大好处是可预测性和可信任度。审查者可以像审查业务代码一样去审查和修改这些风险扫描规则。当工具提示某个文件有风险时你能清楚地知道是触发了哪条具体的规则而不是面对一个模糊的“模型认为这可能有问题”。这对于在团队环境中建立对自动化工具的信任至关重要。2. 核心设计思路与方案选型2.1 为何放弃“端到端”的LLM方案在项目初期最直接的思路确实是调用LLM API进行全量分析。但经过实践我们发现这种方案存在几个难以克服的缺陷上下文幻觉与不确定性LLM可能会“发明”一些不存在的风险或者对某些真正关键的变更如修改了核心的身份验证逻辑轻描淡写。它的输出每次都可能略有不同这种不确定性在严肃的工程场景中是致命的。缺乏业务上下文LLM不知道你们团队约定俗成的“金科玉律”。比如只有特定两位资深工程师有权修改的“黄金配置文件”config/production/secrets.yml或者任何对数据库迁移脚本db/migrate/的修改都必须附带回滚脚本。这些规则无法通过自然语言描述完整、准确地灌输给LLM。成本与延迟将完整的、可能很长的Diff发送给LLMtoken消耗大响应慢不适合需要快速反馈的审查流程。无法审计与演进风险策略隐藏在LLM的提示词Prompt中难以版本化、难以进行Diff审查。当策略需要调整时你是在调整一段模糊的自然语言指令其最终效果难以预测。基于这些痛点我们决定采用“规则引擎 LLM 格式化”的混合架构。规则引擎负责硬性的、二元的风险判断这部分必须绝对可靠LLM负责软性的、需要语言组织能力的部分提升工具的输出可读性和实用性。2.2 技术栈选型Shell脚本 OpenClaw Agent1. 风险扫描层为什么是Shell脚本选择Bash Shell脚本risk-scan.sh作为规则引擎的实现是基于以下几个考量极致的透明与简单任何开发者都能在几分钟内读懂一个60行的Shell脚本。grep -E、awk、sed等命令是Unix哲学下的标准工具其行为是确定且公认的。零依赖与高可移植性在所有开发环境Linux, macOS, WSL和CI/CD服务器上Bash和GNU Coreutils几乎总是可用的。这避免了引入额外的语言运行时如Python、Node.js所带来的依赖管理问题。完美的“基础设施即代码”脚本本身就是一个纯文本文件可以放入Git仓库享受版本控制、代码审查、回滚等所有软件开发最佳实践。修改风险策略就是提交一个Pull Request来修改这个脚本。高性能针对文件路径列表进行模式匹配Shell脚本的速度极快通常在毫秒级完成对PR审查流程几乎无感。2. 智能编排层为什么是OpenClawOpenClaw是一个本地运行的AI Agent框架。选择它而非直接调用远程API如ChatGPT是基于控制权和集成度的考虑本地运行数据不出域所有代码、Diff信息都在本地处理只有生成清单的指令会发送给配置的LLM可以是本地模型也可以是API。这满足了企业对代码安全性和隐私性的要求。技能Skill化架构pr-review-prep被封装为一个OpenClaw的“技能”Skill。这意味着它可以被无缝集成到OpenClaw支持的各种交互界面中如命令行、Slack、iMessage等。用户只需一句自然语言指令如“review prep for PR_URL”即可触发。依赖声明与自动管理技能的SKILL.md文件可以声明依赖如需要gh命令行工具。OpenClaw可以在首次使用时引导用户安装简化了部署流程。3. 辅助工具GitHub CLI (gh)使用gh来获取PR的Diff、元数据等信息是因为它是与GitHub交互的官方、稳定且功能丰富的命令行工具。它处理了认证、API调用和结果解析比手动拼接HTTP请求更可靠。这个技术栈组合Bash OpenClaw gh确保了工具既强大又轻量既智能又可控。3. 核心细节解析与实操要点3.1 风险启发式规则详解scripts/risk-scan.sh是这个项目的大脑。它的工作原理是接收一个文件路径列表通常是PR中变更的文件然后逐条应用规则进行匹配。一条典型的规则看起来像这样# 示例规则匹配任何对生产环境密钥文件的修改 if echo $file | grep -qE ^config/(production|staging)/.*(secret|key|credential)\.(yml|yaml|json|env)$; then echo HIGH_RISK: Production secret file modified - $file fi让我们拆解一下好的风险规则应具备的特征基于路径模式而非内容初期我们尝试过分析文件内容但这会极大增加复杂性并可能误判。基于路径的规则简单有效。例如^app/controllers/.*_controller\.rb$匹配所有Rails控制器文件控制器变更通常涉及业务逻辑和API端点。^db/migrate/.*\.rb$匹配数据库迁移文件需要仔细审查SQL和回滚逻辑。^deploy/kubernetes/.*\.yaml$匹配K8s部署配置影响服务发布和资源调度。风险等级标识脚本可以输出不同的风险等级如HIGH_RISK、MEDIUM_RISK、PERFORMANCE、SECURITY等。这有助于审查者优先处理最重要的部分。规则应具体且可行动规则的目的不是标记尽可能多的文件而是精准地标记出那些真正需要额外注意力的变更。一条好的规则应该能让审查者立刻明白需要检查什么。例如与其标记“修改了JavaScript文件”不如标记“修改了vendor/目录下的第三方库文件”这可能涉及许可或升级风险。注意规则的设计需要团队共识。最好的方式是在团队会议上共同评审和通过初始的规则集并将其作为团队代码规范的一部分。这能确保工具是辅助者而不是令人反感的“警察”。3.2 OpenClaw技能的结构与契约pr-review-prep作为一个OpenClaw技能遵循其特定的目录结构和契约pr-review-prep/ ├── SKILL.md # 技能元数据、描述、输入输出契约 ├── scripts/ │ └── risk-scan.sh # 核心风险扫描脚本 └── (可能还有其他OpenClaw所需的配置文件)SKILL.md文件是这个技能的“说明书”它定义了技能名称与描述OpenClaw如何识别和调用这个技能。输入契约技能期望接收什么格式的输入。在本例中是包含PR URL的自然语言指令。输出契约技能保证输出什么格式的内容。这是一个关键部分它确保了无论内部脚本如何变化返回给用户或后续流程的结构是稳定的。通常输出是一份结构化的Markdown。依赖声明例如requires: [gh]告诉OpenClaw运行此技能需要GitHub CLI。这种契约化的设计使得技能之间可以互相调用和组合也使得技能的升级不会破坏已有的工作流。3.3 安装与配置的实操陷阱根据README的安装步骤看似简单但实际环境中可能会遇到以下问题1. GitHub CLI (gh) 认证问题gh auth status这条命令是检查关键。常见的认证失败原因有未登录运行gh auth login按照指引选择HTTPS或SSH方式登录。对于CI环境需要使用gh auth login --with-token your_token。多账户冲突如果你有多个GitHub账户gh可能使用了错误的上下文。使用gh auth status --show-token查看当前使用的账户和主机。可以通过gh auth switch切换。2. OpenClaw技能路径问题git clone ... ~/.openclaw/skills/pr-review-prep这里的~/.openclaw/skills/是OpenClaw默认查找技能的目录。但有时OpenClaw的配置可能指定了其他路径。最可靠的方式是查看OpenClaw的配置文件通常位于~/.openclaw/config.yaml或通过openclaw config path命令找到确认skills_dir的设置。3. 脚本执行权限在克隆仓库后需要确保Bash脚本有可执行权限chmod x ~/.openclaw/skills/pr-review-prep/scripts/risk-scan.sh否则在运行时会收到Permission denied的错误。4. 技能加载失败运行openclaw skill reload pr-review-prep后如果技能没有出现可以尝试openclaw skill list查看所有已加载技能确认是否存在。检查OpenClaw的日志文件通常会有更详细的错误信息。日志位置取决于配置可能在~/.openclaw/logs/。实操心得建议将安装过程脚本化。可以创建一个install.sh脚本依次执行克隆、检查依赖、授权、加载技能等步骤并加入错误检查。这对于团队 onboarding 和新环境搭建非常有帮助。4. 完整工作流程与核心环节实现让我们跟随一次完整的pr-review-prep调用看看背后发生了什么。用户输入 review prep for https://github.com/your-org/your-repo/pull/4564.1 步骤一指令解析与技能匹配OpenClaw Agent监听到这条消息。它在其已加载的技能列表中寻找能处理此类指令的技能。pr-review-prep技能的SKILL.md中定义了它能处理像 “review prep for ” 这样的模式。Agent将指令和提取出的PR URL传递给pr-review-prep技能的入口点。4.2 步骤二获取PR数据技能内部会调用GitHub CLI来获取PR的详细信息# 提取PR编号和仓库信息假设URL解析已完成 PR_NUMBER456 REPOyour-org/your-repo # 获取PR的差异diff这是审查的核心材料 gh pr diff $PR_NUMBER --repo $REPO /tmp/pr_diff.txt # 获取PR的元数据JSON格式包含标题、作者、body描述等 gh pr view $PR_NUMBER --repo $REPO --json number,title,author,body,baseRefName,headRefName,files,additions,deletions /tmp/pr_meta.json这里使用了--json参数来获得结构化的数据便于后续用jq等工具解析。4.3 步骤三执行风险扫描这是核心环节。脚本会从元数据中提取变更的文件列表然后交给risk-scan.sh处理。# 从JSON中提取变更文件路径列表 FILE_LIST$(cat /tmp/pr_meta.json | jq -r .files[].path | tr \n ) # 调用风险扫描脚本 RISK_REPORT$(cd /path/to/skill/scripts ./risk-scan.sh $FILE_LIST)risk-scan.sh会遍历$FILE_LIST中的每个文件路径应用所有已定义的规则并生成一个包含风险标记的报告字符串。4.4 步骤四构造LLM提示词并生成清单OpenClaw技能接着会构造一个给LLM的提示词Prompt。这个Prompt不是让LLM去发现风险而是让它基于已知信息进行组织和撰写。一个简化的Prompt模板可能是你是一个资深的工程团队负责人正在准备审查一个GitHub Pull Request。请根据以下信息生成一份结构清晰、重点突出的代码审查清单。 PR元信息 - 标题{title} - 作者{author} - 源分支{headRefName} - 目标分支{baseRefName} - 变更概况{additions}行新增{deletions}行删除。 自动化风险扫描发现 {risk_report} PR描述 {body} 请生成一份Markdown格式的审查清单包含以下部分 1. **概览**简要总结这个PR的目的。 2. **高风险区域需重点审查**根据上面的风险扫描结果列出每一项风险并说明审查者应该关注什么。 3. **常规审查项**包括测试覆盖、文档更新、回滚方案等通用检查点。 4. **开放性问题**从PR描述和变更中提炼出需要作者澄清的2-3个关键问题。 注意清单应具体、可操作。对于风险项直接引用扫描报告中的文件名和风险类型。然后将这个Prompt发送给配置的LLM可能是本地的Llama、通过API使用的GPT等获取生成的Markdown文本。4.5 步骤五输出最终结果最后技能将LLM生成的Markdown内容返回给OpenClaw AgentAgent再将其呈现给用户在CLI中打印在Slack中发送消息等。一份生成的审查清单示例## PR审查清单feat/add-user-auth-logic (#456) **作者**alice | **分支**feature/auth - main | **变更**120 -45 ### 1. 概览 本次PR旨在为用户模块添加新的双因素认证2FA逻辑。 ### 2. 高风险区域需重点审查 - **生产环境配置变更**config/production/secrets.yml 被修改。风险扫描标记为 HIGH_RISK。 - **审查重点**确认新增的 twilio_auth_token 配置项符合密钥管理规范未将明文密钥硬编码。检查其访问权限是否被正确限制。 - **核心认证控制器**app/controllers/api/v1/auth_controller.rb 被修改。 - **审查重点**仔细审查新增的 #verify_2fa 方法。确保其中没有逻辑漏洞如时序攻击、异常处理完备并且与现有的 #login 方法流程整合正确。 ### 3. 常规审查项 - [ ] **测试覆盖**检查 spec/controllers/api/v1/auth_controller_spec.rb 是否已更新覆盖新的2FA验证场景成功、失败、超时、重试。 - [ ] **文档更新**确认 docs/api/authentication.md 已同步更新说明了2FA的启用方式和API响应变化。 - [ ] **回滚方案**此功能涉及数据库迁移db/migrate/20231010120000_add_2fa_secret_to_users.rb。请确认已提供对应的回滚迁移down 方法并评估回滚对已启用2FA用户的影响。 - [ ] **前端兼容性**对应的前端仓库是否有PR联动API响应格式的变化是否已通知前端团队 ### 4. ❓ 开放性问题 1. PR描述中提到“在验证失败5次后锁定账户1小时”。这个锁定是用户级别的还是IP级别的锁定的状态是持久化到数据库还是存储在缓存中缓存失效策略是什么 2. 新的Twilio集成是否已确认在公司的供应商管理清单中报备其SLA和错误处理机制是否已考虑可以看到最终清单是结构化、可操作的并且风险部分直接关联到了确定性的扫描结果审查者可以有的放矢。5. 如何为你的团队定制与扩展pr-review-prep的真正威力在于它可以被轻松地定制以适配任何团队独有的工作流和风险模型。5.1 添加新的风险启发式规则所有定制都发生在scripts/risk-scan.sh文件中。假设你的团队有以下规定可以相应添加规则场景一标记对特定“黄金文件”的修改只有团队Tech Lead有权修改数据库核心架构定义文件。# 在 risk-scan.sh 中添加 if [[ $file lib/core/db_schema.rb ]]; then echo BLOCKER: Core database schema modified - requires Tech Lead review. File: $file fi场景二标记Cron任务或重试配置的变更这类变更若出错可能导致定时任务堆积或消息重复处理。if echo $file | grep -qE ^(config|cronjobs?)/.*(cron|schedule|retry)\.(yaml|yml|json)$; then echo MEDIUM_RISK: Scheduling or retry configuration changed - verify intervals and idempotency. File: $file fi场景三标记PR模板本身的修改修改PR模板会影响所有后续的PR需要谨慎。if [[ $file .github/PULL_REQUEST_TEMPLATE.md ]]; then echo META: PR template modified - this will affect all future PRs. File: $file fi场景四标记对第三方依赖许可证的更新if [[ $file THIRD_PARTY_LICENSES ]] || [[ $file *package-lock.json ]]; then echo LEGAL: Third-party dependency or license file changed. File: $file fi添加规则后记得提交一个Pull Request来修改这个脚本让团队其他成员进行代码审查——这正是“将审查策略代码化”理念的体现。5.2 调整LLM提示词以改变输出风格如果你觉得默认生成的清单风格不符合团队习惯可以修改技能中构造Prompt的逻辑。例如你可以要求更严厉或更温和的语气。增加或减少审查项比如强制要求检查“是否更新了变更日志CHANGELOG”。改变输出格式例如要求以Jira Ticket注释的格式输出或者生成一个简单的检查列表。重要提示修改Prompt属于“软性”调整其输出有一定的不确定性。而修改Shell脚本规则是“硬性”调整行为是完全确定的。团队应更侧重于维护和完善确定性的规则集。5.3 集成到CI/CD流水线虽然pr-review-prep主要设计为交互式工具但你也可以将其集成到CI/CD中例如作为GitHub Actions的一个步骤# .github/workflows/pr-review-prep.yml name: PR Review Prep on: pull_request: types: [opened, synchronize] jobs: generate-checklist: runs-on: ubuntu-latest steps: - name: Checkout PR uses: actions/checkoutv3 - name: Setup OpenClaw run: | # 安装OpenClaw和gh-cli的步骤... - name: Run PR Review Prep env: PR_URL: ${{ github.event.pull_request.html_url }} run: | openclaw run review prep for $PR_URL review-checklist.md - name: Post Checklist as Comment uses: actions/github-scriptv6 with: script: | const fs require(fs); const checklist fs.readFileSync(review-checklist.md, utf8); github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: ## 自动化审查清单\n\n${checklist} });这样每当有新的PR创建或更新时机器人会自动在PR下方生成一份审查清单为人工审查者提供即时引导。6. 常见问题与排查技巧实录在实际使用和推广pr-review-prep的过程中我们遇到并解决了一些典型问题。6.1 问题风险扫描脚本没有输出任何结果但PR明明有变更。排查思路检查文件列表输入首先确认传递给risk-scan.sh的文件路径列表是否正确。可以在脚本开头加一句echo Processing files: $来调试。可能是上游获取文件列表的命令如jq解析出错了。检查规则匹配逻辑你的规则可能是大小写敏感或路径模式不匹配。例如规则中是^app/controllers/但文件路径是./app/controllers/。使用grep -i进行不区分大小写匹配或确保路径是相对仓库根目录的。检查脚本执行环境确保脚本是在正确的目录下执行的相对路径的规则才能生效。在脚本中使用pwd命令打印当前目录。解决方案示例#!/bin/bash # risk-scan.sh 顶部添加调试信息 set -x # 开启调试模式打印每条执行的命令 echo [DEBUG] Current directory: $(pwd) echo [DEBUG] Received files: $ for file in $; do echo [DEBUG] Checking file: $file # ... 原有规则 ... done6.2 问题OpenClaw无法识别“review prep for”这个指令。排查思路技能加载状态运行openclaw skill list确认pr-review-prep在列表中且状态正常。技能模式匹配检查SKILL.md中的patterns或triggers配置。确保它包含了类似[review prep for *, analyze pr *]这样的模式。*是通配符。OpenClaw日志查看OpenClaw的详细日志通常能看到指令解析和技能匹配的过程。日志可能会显示“No skill matched”或具体的错误信息。6.3 问题LLM生成的清单内容空洞或跑题。排查思路Prompt质量这是最常见的原因。你的Prompt可能没有给LLM足够的约束或清晰的指令。确保Prompt中明确要求LLM基于提供的风险报告来生成清单而不是自己发明风险。风险报告格式检查传递给LLM的{risk_report}部分是否清晰。确保风险扫描脚本的输出是简洁、标签化的如[HIGH_RISK] ...便于LLM解析。LLM模型能力如果你使用的是较小的本地模型其指令跟随和格式化能力可能较弱。尝试换用能力更强的模型如GPT-4、Claude-3或者优化Prompt采用更严格的“系统指令用户指令”格式。优化后的Prompt片段示例你是一个专注于代码质量和风险的助手。你的任务是根据提供的确定性的风险扫描结果生成审查清单。 ## 指令 - 你必须且只能基于下方“风险扫描结果”部分的内容来生成“高风险区域”清单。 - 不要臆造不存在于扫描结果中的风险。 - 扫描结果中的每一行都是一个独立的风险项请为每一项生成一个审查要点。 ## 风险扫描结果 {HIGH_RISK: Modified production secret file - config/production/secrets.yml} {MEDIUM_RISK: Changed database migration - db/migrate/20231010_add_column.rb} ## 你的输出 ...6.4 问题在CI/CD中运行权限不足无法访问GitHub。排查思路GitHub Token在CI环境如GitHub Actions中gh工具需要使用Token进行认证。你需要创建一个具有repo权限的GitHub Personal Access Token (PAT) 或使用GitHub Actions内置的GITHUB_TOKEN。认证方式在CI脚本中使用echo $YOUR_TOKEN | gh auth login --with-token进行认证。对于GitHub Actions通常可以这样设置- name: Authenticate GH CLI env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 或你自己的PAT run: | echo $GH_TOKEN | gh auth login --with-token gh auth status仓库权限确保使用的Token对该PR所在的仓库有读取权限。6.5 性能与规模化考量对于超大型PR修改文件超过100个当前的简单脚本遍历可能稍慢但通常仍在可接受范围秒级。如果遇到性能瓶颈可以考虑并行处理使用xargs -P或 GNUparallel来并行检查多个文件。规则引擎优化将多条grep规则合并成一个更复杂的正则表达式减少进程启动开销。缓存如果PR的基分支base branch相同可以缓存一些通用的文件列表分析结果但此场景收益有限。一个更高级的优化方向是将风险规则编译成更高效的数据结构如前缀树但这会大大增加代码复杂度违背了项目“简单透明”的初衷。对于绝大多数团队当前的实现已经绰绰有余。7. 总结与演进思考使用pr-review-prep近半年后我们团队最大的感受是它没有减少代码审查的工作量但显著提高了审查的效率和针对性。审查者不再需要从一片代码海洋中自己寻找可能的暗礁工具已经像雷达一样标出了可疑区域。这让审查者可以把宝贵的认知资源集中在真正的逻辑判断和设计讨论上而不是消耗在“找问题”上。这个项目的哲学很吸引人对机器和AI做它们各自擅长的事。让确定性的规则去做二分判断让概率性的语言模型去做信息组织和语言生成。这种清晰的职责分离带来了可预测性、可审计性和最终的信任。对于想要引入类似工具的团队我的建议是从小处着手先定义3-5条你们团队公认的、最核心的风险规则比如“修改支付相关代码”、“改动核心数据库表结构”。将其实现到risk-scan.sh中。作为辅助而非判决明确告知团队这个工具生成的清单是“审查助手”的建议而不是必须通过的检查项。最终决定权仍在人类审查者手中。迭代规则定期比如每季度回顾风险扫描的结果。看看哪些规则频繁触发但都是误报需要调整规则哪些真正的线上事故所涉及的变更没有被规则覆盖到需要新增规则。让规则库随着团队经验一起成长。拥抱可审计性将修改risk-scan.sh视为一项重要的代码变更要求至少有一名其他成员进行审查。这本身就是一次对团队风险策略的讨论和共识巩固。未来这个模式可以扩展到更多场景比如在提交Commit时运行一个更轻量级的扫描阻止某些高风险模式的代码进入仓库或者与Jira、Linear等项目管理工具集成自动将审查清单附到对应的任务卡上。核心不变的是保持风险判断逻辑的简单、透明和可版本化。