ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI写代码时代,如何用Skill构建可验证的代码评审证据链

AI写代码时代,如何用Skill构建可验证的代码评审证据链 1. 为什么“敢不敢合并”成了 AI 写代码时代的新瓶颈过去一年我身边几乎所有团队都在用 AI 辅助写代码。从最早的 Copilot 补全到后来 Cursor、Claude Code、Codex 这类能直接改多文件的 Agent写代码这件事的门槛确实被拉低了一大截。以前一个需求要拆任务、排期、写单测现在你把需求描述清楚Agent 能一口气给你生成三四个文件的改动连测试都顺手补上。但有意思的是代码产出速度上去了团队的交付速度却没有同步提升反而卡在了一个很微妙的地方——代码评审。我观察到的现象是AI 生成的 PR 越堆越多评审的人却越来越不敢点那个 Merge 按钮。原因不复杂AI 写的代码“看起来都对”但你就是说不清它到底改了什么、为什么这么改、有没有顺手把别的地方搞坏。以前人写的代码你能从提交信息、代码风格、改动范围里读出作者的意图现在 AI 一次性改十几个文件diff 拉下来几百行评审者面对的是一个“黑箱产物”。于是出现了一种很拧巴的状态写代码的人觉得 AI 都写完了评审应该很快评审的人觉得这堆改动我没法判断只能一行行硬看看完还是心里没底。这就是标题里说的“敢不敢合并”的问题。它本质上不是技术问题而是信任问题。人写的代码信任来自“我了解这个同事的水平”AI 写的代码信任必须来自“我能验证这次改动的依据”。所以真正缺的不是更强的模型而是一套能给出证据链的评审机制。我最近在几个项目里试了一套基于 Skill 的代码评审流程核心思路就是让 Agent 在提交改动的同时附上一份可核查的证据链评审者不再靠感觉判断而是靠证据决策。这套东西不复杂但确实把“敢不敢合并”这件事从玄学变成了流程。2. 先搞清楚AI 代码评审到底难在哪2.1 传统评审假设的“作者在场”被打破了传统代码评审有一个隐含前提写代码的人就在旁边你能问他“这里为什么这么改”。评审意见可以来回讨论作者能解释意图评审者能追问边界情况。但 AI 生成的改动作者是“模型”它不会在评论区跟你对话你问它它可能还会编一个听起来很合理的理由。这就导致评审从“对话式确认”变成了“单向审查”评审者必须自己重建整个改动的上下文。我踩过的一个坑是早期我们让 Agent 直接生成 PR提交信息就一句“fix bug”。评审的人打开 diff发现它改了三个文件其中一个文件跟这个 bug 看起来毫无关系。追问下去才发现Agent 在修 bug 的过程中顺手重构了一个工具函数而这个重构影响了另一个调用方。这种“顺手改动”在人写代码时也会发生但人会主动在提交信息里说明AI 不会。评审者如果没有证据链就只能靠 diff 逐行反推效率极低。2.2 diff 本身不携带“意图”只携带“结果”git diff是一个很诚实的工具它只告诉你“什么变了”不告诉你“为什么变”。对于人写的代码评审者可以结合提交信息、issue 链接、代码注释来推断意图。但 AI 生成的 diff 往往缺少这些上下文或者上下文是模型编的。更麻烦的是AI 很擅长写出“局部正确”的代码——每一行看起来都没问题但整体逻辑可能偏离了原始需求。举个例子需求是“给用户列表加一个按注册时间排序的功能”。AI 可能确实加了排序但它顺手把分页逻辑也改了理由是“排序后分页需要调整”。这个改动本身可能没错但它超出了需求范围评审者如果只看 diff很容易忽略这个“范围蔓延”。证据链的价值就在于它要求 Agent 在改动时明确标注哪些改动是需求直接要求的哪些是必要的连带改动哪些是它自己认为的优化。评审者可以针对每一类改动分别判断。2.3 评审者的认知负荷被 AI 放大了人写代码时改动量通常和需求复杂度成正比评审者能根据改动规模预估需要投入的精力。但 AI 可以在几分钟内生成几百行改动评审者的认知负荷瞬间拉满。我做过一个粗略统计同样一个中等复杂度的需求人写代码平均产生 80 到 120 行 diff评审时间约 15 分钟AI 生成的平均 300 到 500 行 diff评审时间反而要 40 分钟以上因为评审者需要额外花时间理解“这堆改动是怎么来的”。所以问题的核心不是“AI 写得对不对”而是“评审者能不能快速建立对这次改动的信任”。证据链就是用来降低这种认知负荷的它把“理解改动”这件事从评审者身上部分转移到了 Agent 身上Agent 必须自己说清楚改动的来龙去脉评审者只需要验证这些说法是否成立。3. 这套代码评审 Skill 的整体设计思路3.1 核心目标让每一次改动都有据可查这套 Skill 的设计目标很明确Agent 提交的每一个改动都必须附带可验证的证据。证据不是一句“我改好了”而是具体的、可追溯的信息包括改动对应的需求来源、影响范围分析、测试验证结果、以及风险标注。评审者拿到的不再是一个孤零零的 diff而是一个“改动包”里面包含了判断这次改动是否安全所需的所有材料。我选择用 Skill 的形式来实现而不是写一个独立的评审工具原因是 Skill 可以嵌入到 Agent 的工作流里。Agent 在生成代码的同时就生成证据而不是事后补。这很关键因为事后补的证据往往是编的而生成时同步记录的证据更接近真实过程。Skill 本质上是一组约束和模板它规定了 Agent 在改动代码时必须输出哪些信息、以什么格式输出、以及如何验证这些信息的真实性。3.2 为什么是 Skill 而不是 Prompt很多人会问为什么不直接写一个复杂的 Prompt 让 Agent 输出证据我的实测结论是Prompt 太容易被“绕过”。Agent 在面对复杂任务时会优先满足代码生成的需求把证据输出当成附加任务质量很不稳定。而 Skill 是一套结构化的能力封装它可以定义明确的输入输出格式、强制性的检查步骤、以及失败时的回退逻辑。更重要的是Skill 可以被复用和组合。比如我有一个“需求解析 Skill”一个“改动影响分析 Skill”一个“测试生成 Skill”代码评审 Skill 可以把它们串起来形成一个完整的证据链生成流程。Prompt 做不到这种模块化每次都要重新描述一遍而且不同项目之间很难迁移。Skill 的另一个好处是它可以携带工具调用比如自动运行测试、自动分析依赖图这些都不是纯文本 Prompt 能稳定实现的。3.3 证据链的四个核心组成部分我设计的证据链包含四个部分缺一不可。第一部分是需求映射这次改动对应哪个需求、哪个 issue、哪段原始描述。Agent 必须明确引用来源不能自己编一个需求。第二部分是改动清单逐个文件、逐个函数说明改了什么以及为什么改。这里要求区分“需求直接要求”“必要连带改动”“主动优化”三类评审者可以按类别审查。第三部分是影响分析这次改动可能影响哪些调用方、哪些测试、哪些配置。Agent 需要基于代码依赖图给出分析而不是泛泛而谈。第四部分是验证记录跑了哪些测试、结果如何、有没有手动验证的步骤。这部分必须有可复现的命令和输出。这四个部分组合起来评审者就能快速判断需求对不对、改动范围合不合理、影响面有没有遗漏、验证够不够充分。如果某一部分缺失或含糊评审者可以直接打回要求 Agent 补充。这就把“敢不敢合并”变成了“证据够不够合并”决策标准从主观感觉变成了客观清单。4. 核心细节拆解证据链是怎么生成和验证的4.1 需求映射从模糊描述到可追溯来源需求映射这一步看起来简单实际上最容易出问题。AI 生成代码时往往是从一个模糊的自然语言描述开始的比如“优化一下登录流程”。这个描述本身没有明确的边界Agent 可以自由发挥。证据链要求 Agent 在开始改动前先把需求拆解成可验证的条目并标注每条的来源。我的做法是让 Skill 强制 Agent 输出一个“需求条目表”每条包含需求描述、来源用户原话、issue 链接、文档段落、验收标准。验收标准必须是可测试的比如“登录失败时返回 401 而不是 500”而不是“提升用户体验”。如果 Agent 无法为某条需求找到明确来源它必须标注“推断需求”评审者可以重点审查这类条目。注意需求映射不是让 Agent 复述一遍需求而是让它把需求翻译成可验证的断言。这一步做扎实了后面的改动清单才有对照基准。我实测下来这一步能过滤掉大约三成的“范围蔓延”问题。因为 Agent 一旦被要求明确引用来源它就不太敢随意添加需求之外的功能。即使添加了也会被标注为“推断需求”评审者一眼就能看到。4.2 改动清单三类改动的区分与标注改动清单是证据链的核心。我要求 Agent 对每一个改动都标注类别需求直接要求、必要连带改动、主动优化。这个分类不是形式主义它直接对应评审者的审查策略。需求直接要求的改动评审者重点看实现是否正确必要连带改动评审者重点看是否真的必要、有没有更小的改法主动优化评审者重点看是否超出范围、是否引入风险。为了让这个分类可操作Skill 里定义了一套判断规则。比如如果一个改动是为了让需求代码通过编译或测试它属于必要连带改动如果一个改动是 Agent 自己觉得“这样更好”但需求没提它属于主动优化。主动优化默认需要评审者显式批准否则应该拆分成独立的 PR。我踩过的一个坑是早期没有区分这三类Agent 把所有改动混在一起评审者根本分不清哪些是必须的、哪些是可选的。结果就是评审者要么全部接受要么全部打回没法做精细决策。加上分类之后评审效率明显提升因为评审者可以先把主动优化挑出来单独讨论剩下的必要改动快速过一遍。4.3 影响分析基于依赖图而不是猜测影响分析是最容易被敷衍的部分。很多 Agent 会写一句“本次改动不影响其他模块”但实际上它根本没检查。为了强制 Agent 做真实的影响分析我在 Skill 里集成了一个简单的依赖分析步骤Agent 必须列出被改动函数的调用方以及这些调用方是否受影响。具体做法是Skill 调用代码索引工具比如基于 AST 的调用图分析生成被改动符号的上下游列表。然后 Agent 需要逐个判断调用方的输入输出是否兼容、是否有边界情况变化、是否需要同步修改。如果 Agent 判断“不影响”它必须给出理由比如“该调用方只使用了返回值的存在性不关心具体值”。这个步骤听起来有点重但实际跑下来对于中等规模的项目依赖分析通常在几秒内完成。它带来的价值是巨大的评审者不再需要自己手动去搜调用方Agent 已经把影响面列出来了。我遇到过好几次Agent 的影响分析里标注了“调用方 A 可能受影响”评审者一看确实是个遗漏点直接避免了一次线上事故。4.4 验证记录可复现的命令与输出验证记录是证据链的最后一环也是最容易被造假的一环。Agent 可能会写“已运行测试全部通过”但实际上它根本没跑。为了防止这种情况Skill 要求验证记录必须包含可复现的命令和真实输出片段。比如$ pytest tests/test_login.py -v tests/test_login.py::test_login_success PASSED tests/test_login.py::test_login_failure PASSED tests/test_login.py::test_login_locked PASSED评审者可以自己复制命令跑一遍验证 Agent 说的是不是真的。如果 Agent 无法运行测试比如环境不允许它必须明确标注“未验证”而不是假装验证过。我个人的经验是只要 Skill 强制要求输出真实命令和输出Agent 造假的概率会大幅下降因为它知道评审者会核查。提示验证记录里最好包含至少一个“负面测试”也就是验证改动没有破坏原有功能的测试。只跑新功能的测试是不够的评审者更关心回归风险。5. 实操过程从零搭建这套评审 Skill5.1 环境准备与基础依赖搭建这套 Skill 不需要特别复杂的环境。我用的是一台普通的开发机装了 Python 3.11、Git、以及一个支持 Skill 机制的 Agent 框架。具体框架名字这里不展开因为不同团队用的可能不一样核心是框架要支持自定义 Skill、工具调用、以及结构化输出。如果你用的是支持 Skill 的 Agent 平台通常只需要在配置里注册 Skill 的描述和参数 schema。基础依赖包括一个代码解析库我用的是 Python 的ast模块加networkx做调用图、一个测试运行器pytest 或项目自带的、以及一个 diff 解析工具git diff加自定义解析。这些都不是必须的你可以根据项目语言替换成对应的工具。关键是 Skill 的流程设计工具只是实现手段。我建议先在单个项目上试点不要一上来就全团队推广。因为 Skill 的输出格式和团队现有的评审习惯需要磨合试点期间可以收集评审者的反馈调整证据链的详细程度。太简略了没用太详细了评审者不看这个平衡需要实际跑几轮才能找到。5.2 Skill 的输入输出定义Skill 的输入是一个“改动请求”包含原始需求描述、当前代码库状态commit hash、允许改动的文件范围。输出是一个结构化的“证据包”包含前面说的四个部分。我用 JSON 来定义输出格式方便后续解析和展示。一个简化的 schema 大概是这样{ requirement_mapping: [ {desc: ..., source: ..., acceptance: ...} ], change_list: [ {file: ..., symbol: ..., category: direct|necessary|optimization, reason: ...} ], impact_analysis: [ {symbol: ..., callers: [...], affected: true, reason: ...} ], verification: [ {command: ..., output: ..., passed: true} ] }这个 schema 的好处是评审者可以快速扫描每个部分不需要读大段文字。如果某个部分为空或者明显敷衍评审者可以直接要求 Agent 补充。我在实际使用中会把证据包渲染成一个 Markdown 评论附在 PR 描述里评审者打开 PR 就能看到结构化的证据而不是一堆散乱的文字。5.3 关键步骤让 Agent 先“说清楚”再“动手”这套 Skill 最重要的一个设计原则是Agent 必须先输出证据包的前两部分需求映射和改动计划才能开始改代码。这个顺序不能反。因为一旦 Agent 先改了代码它就会倾向于为已完成的改动找理由而不是基于需求做规划。先规划后执行证据链的质量会高很多。具体流程是Agent 收到需求后先调用 Skill 生成需求映射和改动计划这两部分会展示给用户或评审者确认。确认通过后Agent 才执行代码改动并在改动过程中实时更新改动清单和影响分析。最后运行测试填充验证记录。这个流程把评审提前到了改动之前而不是事后补救。我实测下来这个“先规划”的步骤能显著减少返工。以前 Agent 直接改代码改完发现方向不对要回滚重来。现在规划阶段就能发现需求理解偏差及时纠正。虽然多了一步确认但整体效率反而更高。5.4 与 Git 工作流的集成证据包最终要落到 Git 工作流里。我的做法是Agent 完成改动后自动生成一个 PRPR 描述里包含完整的证据包。同时Skill 会在 PR 上打标签比如evidence-complete或evidence-missing方便评审者筛选。如果证据包不完整PR 会被标记为needs-evidence评审者可以直接要求补充而不是硬着头皮看 diff。另外我会把验证记录里的命令和输出作为 PR 评论单独发一条方便评审者直接复制运行。如果项目支持 CI还可以把证据包里的验证命令接入 CI自动跑一遍和 Agent 的记录做交叉验证。这样即使 Agent 造假CI 也能发现。我试过把验证命令接入 GitHub Actions效果很好评审者看到 CI 通过加上 Agent 的记录信任度明显提升。6. 常见问题与排查技巧实录6.1 Agent 输出的证据包太啰嗦怎么办这是最常见的问题。Agent 为了显得“完整”会把每个改动都写一大段理由导致证据包比 diff 还长。评审者根本没耐心看。我的解决方法是在 Skill 里限制每个条目的字数比如改动理由不超过 50 字影响分析不超过 100 字。同时要求 Agent 用结构化字段而不是自然语言段落评审者可以按需展开。另外我会把证据包分成“摘要”和“详情”两层。摘要只列关键信息比如改动文件数、风险等级、验证是否通过。详情才是完整的证据链。评审者先看摘要有疑问再展开详情。这个分层设计大幅降低了评审者的阅读负担。6.2 影响分析总是漏掉间接调用方间接调用方是指“调用方的调用方”Agent 在做依赖分析时容易只分析一层。我的经验是在 Skill 里明确要求分析深度至少两层并且对于公共工具函数要分析到所有直接和间接调用方。如果调用方太多可以按模块聚合但必须列出模块名。还有一个技巧是让 Agent 标注“高风险符号”也就是被多处调用的函数或类。这些符号的改动默认需要更严格的审查。我通常会让 Skill 自动计算每个被改动符号的调用方数量超过阈值的自动标红评审者优先看这些。6.3 验证记录里的测试跑不起来有时候 Agent 写的测试命令在评审者环境里跑不起来原因是环境差异。比如 Agent 用的是虚拟环境里的 pytest评审者直接跑系统 pytest 就找不到依赖。解决方法是在验证记录里明确标注运行环境比如“在项目根目录、激活 venv 后运行”。如果项目有 Docker最好用 Docker 命令保证环境一致。另外如果测试确实跑不起来Agent 应该标注“未验证”并说明原因而不是编一个假的输出。我在 Skill 里加了一条规则如果验证命令执行失败Agent 必须原样输出错误信息不能修改或省略。评审者看到错误信息可以判断是环境问题还是代码问题。6.4 评审者不信任 Agent 的证据怎么办这是信任建立的问题需要时间。我的做法是初期让 Agent 的证据包和人工评审并行评审者可以对照证据包和自己的判断看看 Agent 有没有漏掉什么。跑一段时间后评审者会发现 Agent 的证据包确实能覆盖大部分关注点信任就慢慢建立起来了。另外我会定期抽查证据包的质量比如随机选几个 PR人工验证 Agent 的影响分析是否准确。如果发现造假或遗漏就调整 Skill 的规则。这个过程有点像训练一个新同事一开始要盯着后面就可以放手了。常见问题排查思路解决技巧证据包太啰嗦检查字数限制是否生效分层展示摘要详情影响分析漏间接调用检查分析深度配置强制两层高风险符号标红测试命令跑不起来检查环境标注用 Docker 或明确 venv评审者不信任并行运行定期抽查逐步建立信任调整规则7. 几个我踩过的坑和实测有效的技巧第一个坑是过度依赖 Agent 的自我评估。早期我让 Agent 自己判断“这次改动风险高不高”结果它几乎总是说“风险低”。后来我改成让 Skill 根据客观指标计算风险等级比如改动文件数、影响调用方数量、是否涉及公共接口。客观指标比 Agent 的自我评估可靠得多。第二个坑是证据包和代码不同步。有时候 Agent 改了代码但忘了更新证据包导致证据包和实际 diff 对不上。解决方法是让 Skill 在生成 PR 前做一次一致性检查对比证据包里的改动清单和实际 diff不一致就报错。这个检查很关键否则证据链就失去意义了。第三个技巧是把证据包纳入代码库。我会让 Agent 把证据包作为一个 Markdown 文件提交到仓库里比如docs/evidence/PR-123.md。这样证据链就跟着代码一起版本化了以后回溯的时候还能看到当时的判断依据。这个做法在排查线上问题时特别有用能快速定位某次改动的影响范围。第四个技巧是给证据包打分。我设计了一个简单的评分规则需求映射完整得 1 分改动分类清晰得 1 分影响分析有依赖图得 1 分验证记录可复现得 1 分。满分 4 分低于 3 分的 PR 自动打回。这个评分让评审标准变得非常明确Agent 也知道该往哪个方向努力。8. 后续可以怎么扩展这套东西这套 Skill 目前主要解决的是“单次改动的证据链”问题。往大了说它还可以扩展成团队级的评审知识库。比如把每次评审中发现的遗漏点记录下来反哺到 Skill 的规则里让 Agent 下次生成证据时更全面。我试过把历史评审意见做成一个检查清单Skill 在生成影响分析时会自动对照这个清单效果不错。另一个扩展方向是和 CI/CD 深度集成。现在验证记录还是 Agent 手动填的未来可以让 CI 自动生成验证记录Agent 只负责引用。这样证据链的可信度会更高因为 CI 的输出是客观的。我目前的做法是让 CI 跑一遍测试然后把结果和 Agent 的记录做对比不一致就报警。还有一个方向是跨项目的证据链复用。比如一个公共库的改动它的影响分析可以复用到所有依赖它的项目里。这需要更复杂的依赖图管理但长期来看能大幅降低评审成本。我还在探索这个方向目前只在单项目内做了试点效果已经很明显了。最后分享一个小技巧证据链的格式不要追求完美先跑起来再迭代。我一开始花了很多时间设计 schema结果实际用的时候发现很多字段根本用不上。后来改成先用最简单的格式评审者缺什么就加什么反而迭代得更快。这套东西的核心不是格式而是“让 Agent 说清楚依据”这个习惯。习惯养成了格式怎么调都行。
返回列表