最近这两个月,我一直在折腾一件事:用 SKILL 编排的方式,把一批跑了六七年的存量代码一点点洗干净。不是推翻重写,而是像做微创手术一样,在尽量不动外部行为的前提下,把里面的隐患、坏味道、重复逻辑逐个处理掉。折腾下来最大的体会是:AI 本身并不稀缺,稀缺的是怎么让 AI 在存量代码里不闯祸。
过去我试过最“散装”的做法,是开一堆对话窗口,让 AI 看一个文件改一个文件,改完合入,跑挂了再回去让 AI 修。一顿操作猛如虎,回头看 diff 全是格式化噪音和顺手“优化”,真正要改的那一行反而被淹没了。后来我把思路换成了 SKILL 编排:先把改造流程拆成一个个可复用的技能包,再像流水线一样按顺序执行,每个环节都有输入、有输出、有验收。这套打法对内有多凶险的存量代码,外有多挑剔的验收标准,都适用。
这篇文章我把整个思路、实操流程、踩过的坑都梳理一遍。如果你也在给老项目做 AI 辅助改造,或者被散装 AI 改崩过代码,这篇应该能给你一个能直接抄作业的路线。
1. 为什么“散装 AI”治不好存量代码的毛病
1.1 “散装 AI”的三宗罪:断上下文、乱漂移、无闭环
先说散装 AI 在存量代码里最常见的翻车现场。第一宗罪是上下文断裂。每次开新对话,AI 就像失忆了一样,你得把模块的背景、业务规则、历史坑重新解释一遍。更麻烦的是,同一个代码库的不同文件之间本来就有隐式关联,散装对话根本没法把这些关联串起来,经常出现改 A 文件时完全不知道 B 文件里的调用方对它有依赖。
第二宗罪是方向漂移。你让 AI 修一个资源未释放的小问题,它改着改着,顺手把整个文件的函数签名重命名了,还把一段 200 行的业务逻辑“优化”成了新写法。你说它有错吧,改得确实更“现代”了;你说它对呢,这次任务只是修三行代码。方向漂移的本质是任务边界不清晰,AI 在长对话里会不自觉扩大改造范围,这对存量代码来说是致命的。
第三宗罪是没有验证闭环。散装模式下,AI 经常给你一句“已完成”,但没有任何测试、没有回归、没有行为对比。存量代码本来就缺测试,结果就是改完靠肉眼 review,合入靠玄学。我见过不少团队,AI 改完上线,线上报错后第一反应是“AI 写的代码不靠谱”,其实问题不在 AI,在于整个流程里没有人给 AI 上紧箍咒。
1.2 存量代码和绿地代码是两种完全不同的物种
绿地代码想怎么设计都行,目录结构、依赖关系、测试体系都是白纸一张。存量代码完全反过来,它是另一个物种。第一,文档和需求早就丢了,业务规则全埋在代码里,有些还是上一批离职同事留下的“艺术品”;第二,测试覆盖率低到可以忽略,很多模块一跑就报依赖错误,更别提自动化回归;第三,隐藏依赖特别多,全局状态、环境变量、配置文件、外部服务,三者之间互相纠缠。
在存量代码里不能谈“重写”,原因很现实:没人敢在缺少测试、缺少行为基线的情况下推倒重来。业务还在跑,线上还在用,谁重写谁背锅。但全盘不动也不行,技术债每天在累积利息。这就逼出了一个结论:只能做微创手术,而不是装修拆墙。
装修可以全砸了重来,反正住户搬走了;手术不行,病人还躺在手术台上,你只能先定位病灶,画好切口,在尽量不伤害周边组织的前提下把问题摘除掉。存量代码改造也是这个逻辑,目标不是“把它重新写漂亮”,而是“在行为不变或最小变化的前提下,解决具体问题”。
2. SKILL 编排的思路:把 AI 从临时工变成专科医生
2.1 SKILL 到底是什么
我理解的 SKILL,就是把特定场景下的工作流程、领域知识、约束条件和验收标准打包成一份可复用的结构化指令。它不是普通 prompt。普通 prompt 是一次性口述,说完就没了;SKILL 是一份沉淀下来的 SOP,AI 每次接到同类任务都按这份协议干活。
一个标准的 SKILL 通常包含这几块:任务目标、输入信息、执行步骤、约束条件、负面清单、输出要求、验收标准。下面是我在一个改造项目里实际用过的 SKILL 骨架,你可以直接拿去改:
--- name: legacy_safe_modify description: 对存量代码模块做最小差异的安全修改 --- ## 任务目标 在保持对外行为不变(或最小变化)的前提下, 修复指定代码片段中的具体问题。 ## 输入 - 目标文件路径 - 函数/方法名 - 问题描述(越具体越好) - 行为快照文件路径 ## 执行步骤 1. 阅读目标文件,确认函数所在模块的上下文 2. 阅读行为快照,明确哪些行为是不可改变的 3. 定位问题点,设计最小改动方案 4. 修改代码,禁止改动与本问题无关的行 5. 执行测试命令,确认全部通过 6. 输出 diff 自检报告 ## 约束条件 - 禁止修改公共 API 签名 - 禁止格式化、重命名、重构无关代码 - 禁止改动异常处理逻辑(除非任务明确要求) - 每次只处理一个函数,改动控制在 20 行以内 ## 负面清单 - 不要顺手“优化”注释 - 不要引入新依赖 - 不要修改 import 顺序与格式 ## 输出要求 - 返回改前改后代码对比 - 返回测试执行结果 - 返回本次改动的行为影响说明 ## 验收标准 - 原有测试全部通过 - diff 中不包含无关修改 - 行为快照中的输入输出样例全部一致这里最关键的设计是“约束条件”和“负面清单”。你在约束里写“注意安全”没有任何用,AI 不知道什么叫安全;你得写“禁止修改公共 API 签名”“每次只处理一个函数”“改动控制在 20 行以内”,机器才能真的遵守。负面清单更是刚需,我试过一个 SKILL 里没写负面清单,AI 每次都忍不住去“美化”代码,加完负面清单之后,这个毛病基本根治了。
2.2 编排是怎么运转的:技能链、输入输出契约、检查点
单个 SKILL 解决不了复杂改造,复杂改造一定需要多个 SKILL 协作,这就是编排。编排的核心是把一个大任务切成若干子任务,每个子任务由一个 SKILL 负责,前一个 SKILL 的输出作为后一个 SKILL 的输入,中间还穿插人工检查点。
具体到存量代码改造,我的编排链路通常是这样的:
code_map(生成模块调用图)→ behavior_snapshot(记录行为基线)→ safe_modify(执行最小改动)→ test_and_review(测试 + 自检)每个环节都有明确的输入输出契约。比如 behavior_snapshot 的输入是目标函数和一组固定输入样例,输出是一份行为快照文件;safe_modify 的输入是目标文件、问题描述和行为快照,输出是 diff 和自检报告。有了这种契约,AI 在执行不同环节时不需要重新解释上下文,直接读文件就行。
编排还有一层隐含的好处:它天然对抗了长上下文的注意力衰减。存量代码改造往往涉及几百上千行代码,全塞进一个上下文里,AI 很快就“记不住”约束条件了。编排后每个子任务只聚焦一个切片,上下文短了,约束的保持率高得多。
2.3 编排带来的三个实在好处:可复用、可审计、可收敛
第一个好处是可复用。这次给订单模块做改造沉淀下来的 code_map、behavior_snapshot、safe_modify 这几个 SKILL,下次给支付模块、用户模块做同类改造时可以直接复用,不需要重新调教 AI。团队里任何一个人拿到这套 SKILL 和方法,都能达到接近的改造质量。
第二个好处是可审计。散装 AI 改完代码,你只能看到最终结果,中间发生了什么全是黑盒。编排模式下每一步都有产物:调用图、行为快照、diff 自检报告、测试输出。出了问题往回追溯,一目了然是哪个环节跑偏了。
第三个好处是可收敛风险。编排把一次大改造拆成了多个小切口,每个切口都有人工检查点。我见过最差的 AI 改造事故,是一次性让 AI 改了三十多个文件,合入后线上服务直接雪崩。用编排之后,一个 SKILL 只动一个点,即使出了问题,回滚范围也小得多。
3. 落地实操:给一段存量代码做“微创手术”
下面用一个我实际处理过的案例来讲完整流程,方便你照着复现。场景是这样的:一个老 Python 服务模块里有个全局缓存字典,多线程环境下并发写入时偶尔会读到脏数据;同时fetch_data函数在异常时把错误吞掉了,调用方拿不到任何提示,问题定位非常困难。
这次手术的目标很明确:缓存并发访问要加锁保护,异常要记录日志但保持原有返回值不变,除此之外不做任何其他改动。
3.1 术前准备:先建立基线再动刀
任何手术前都要先确认病人的基础状态,存量代码改造也一样。第一步,确认工作区干净,记录当前 git commit,保证随时能回滚。第二步,跑一遍模块现有的测试,不管测试覆盖多少,先记下当前是绿还是红。第三步,给目标函数补两条冒烟测试,一条正常路径、一条异常路径,先把行为的“底线”钉住。
这一步很容易被跳过,但我强烈建议不要省。没有基线,后面所有的改造是否成功都无从判断。行为基线还不是写测试就完事,最好再补一个行为快照:给定几组固定输入,记录当前函数的真实输出。异常路径也要记录,比如当前异常时返回 None,那这条行为在术后也必须保持 None,除非需求方明确说允许变化。
3.2 设计手术切口:划定改动边界
术前准备做完,接下来是切口设计。很多人拿到改造任务就急着让 AI 动手,其实最该花时间的恰恰是这一步。你要先回答三个问题:改什么、不改什么、预期变化点是什么。
改什么:这次是fetch_data函数内部,缓存访问要加锁,异常路径要加日志。不改什么:公共函数签名、调用方接口、返回值语义(异常仍返回 None)。预期变化点:并发场景下不再出现脏数据,异常时日志有记录。这三个问题写清楚后,变成一个“改造说明”文件,作为 safe_modify SKILL 的输入。
设计切口时有一个常见误区:想借着这次改造顺手把别的问题也解决了。比如“既然都打开这个文件了,把那个废弃函数也删掉吧”。这种想法一定要克制住。微创手术的精髓是每次只处理一个病灶,切口越小,并发症越少。一个改造任务只解决一个问题,其他问题单独排期,这是我能给的最大建议。
3.3 用 SKILL 驱动实施:小步快跑,每刀都有验证
实施阶段我按前面说的编排链路来。先调用 code_map 生成模块调用图,确认fetch_data只有两个调用方,且都不依赖内部缓存的具体行为,手术区域不会波及外围。再调用 behavior_snapshot 拿到行为基线,这时候术前补的测试和快照文件就派上用场了。
接下来执行 safe_modify。目标文件路径、问题描述、行为快照作为输入,SKILL 会自己读代码、设计方案、改代码、跑测试。我这次要求的改动其实很小,加一把锁,再在异常分支补一条日志。改完后 AI 输出了一份 diff 自检报告,我 review 了一遍,发现它按负面清单老老实实没动其他行,连注释多余的空格都没碰。
这一刀改动小,风险低,可以直接走测试和自检。如果任务复杂,就得多调度几轮:上一刀验证通过,才允许开下一刀。这个过程就像真正的微创手术,每一刀下去之前都要确认不会伤到神经和血管,确认后再落刀。
有个细节值得单独说一下:在执行层,AI 改代码一定要基于“当前工作区最新版本”,不要让它拿着旧代码改完再合入。如果前一步有人改了同一个文件,后一步执行前先重新拉取最新内容,不然会出现“改的版本早已过期”的诡异问题。
3.4 术后缝合:验收与回滚预案
改完代码只是完成了一半,验证才是微创手术的缝合段。我习惯按三个层次验收。第一层跑全部相关测试,确认术前补的冒烟测试和目标模块的原本测试全部通过。第二层做行为快照对比,术前记录的输入输出样例,术后跑一遍,逐条核对。异常路径我尤其看重,如果术前是异常返回 None,术后也必须返回 None,只是多了一条日志。
第三层人工看 diff。不要只扫一遍就合入,要逐文件看,重点盯“无关修改”。我见过 SKILL 明明写了负面清单,AI 还是会偶尔漏一两个“顺手优化”。所以每次合入前我都会跑一下git diff --stat,如果看到文件变更数或行数与手术范围明显不匹配,直接打回重改。
万一验证出了问题,处理原则是直接回滚,不要让 AI 继续“缝缝补补”。回滚到术前 commit,或者用 git revert 回退指定 commit,都比让 AI 在错误基础上继续改更安全。存量代码的毛病本来就多,一次回滚的成本远比一次失控改动带来的连锁反应低。
4. SKILL 的编写与积累:从一次性改造走向体系化
4.1 写一个好用 SKILL 的核心要素
操作次数多了,你会发现 SKILL 的质量直接决定 AI 改造的下限。我总结下来,一个好 SKILL 必备五个要素。
第一,目标单一。一个 SKILL 只解决一个场景问题,不要搞“全能型技能”。code_map 就专注于生成调用关系,safe_modify 就专注于改代码,混在一起时 AI 的注意力会被稀释。这个体验跟人一样,岗位职责越清晰,执行越到位。
第二,约束具体。写“不要乱改”等于没写,写“禁止修改公共 API 签名”“禁止改动异常处理逻辑”才是有效约束。最好是每一条都能在 diff 里被客观检查,这样 AI 违反约束时你能立刻发现。
第三,验收可执行。验收标准写“保证代码质量”没用,要写“原有测试全部通过”“行为快照一致”“diff 中不包含无关修改”。可执行意味着有确定性的检查命令或比对步骤,而不是靠感觉。
第四,示例优先。在 SKILL 里放一两个输入输出示例,比写十句说明奏效。AI 对 Few-shot 的模仿能力远强于对抽象规则的理解,这是大模型的天性。我通常在 SKILL 里加一个“参考示例”小节,直接贴正例和反例。
第五,负面清单必选。告诉 AI 不要做什么,比告诉它要做什么更能防止跑偏。我自己的 SKILL 里,“负面清单”永远独立成节,放在“执行步骤”之后,确保 AI 在生成过程中能高频看到。负面清单的另一个作用是约束范围,AI 看到“不要引入新依赖”时,就不会擅自改 requirements。
第五个也很重要的点是写 SKILL 的人最好自己踩过对应的坑。让一个没做过存量代码改造的人写 legacy_safe_modify,写出来大概率是空话。SKILL 是经验的产品化,没有真实场景支撑,它就是一份漂亮的废纸。
4.2 SKILL 的版本维护和团队协作
SKILL 跑了一段时间后,团队里会积累一批技能,这时候维护问题就来了。我的做法是给 SKILL 建一个独立的 git 仓库,和业务代码分开。目录结构大致长这样:
skills/ code_map/ SKILL.md examples/ sample_call_graph.json behavior_snapshot/ SKILL.md safe_modify/ SKILL.md negative_examples.md test_and_review/ SKILL.mdSKILL 的变化也需要走评审。我见过最典型的问题,是有人为了让 AI 更快完成任务,往 SKILL 里偷偷删掉了一条约束,结果后续所有改造都开始放飞。所以 SKILL 的变更记录要留痕,每次修改都要写清楚原因。我和团队现在的规则是:SKILL 变更必须有至少两个人 review,跟业务代码评审同等对待。
还有一个经常被忽略的点:SKILL 会过期。代码库的目录结构变了,SKILL 里写的路径就要同步更新;工具的接口变了,SKILL 里的执行命令也要跟着改。建议每季度做一次 SKILL 盘点,把半年没被调用的技能标记为待审查,要么让它重新活跃,要么直接归档。技能库不维护,最终会变成和存量代码一样的另一笔技术债。
4.3 和现有工具链结合,让 SKILL 编排跑得更顺
SKILL 编排不是孤立存在的,它要跟团队的现有工具链捏合在一起。第一层是执行环境。AI 跑 SKILL 时需要能直接调用命令行工具,比如用 AST 工具解析代码结构、用 git diff 检查差异、用测试框架跑回归。如果 AI 只能看文本不能执行命令,很多 SKILL 的效果会大打折扣。
第二层是 CI 集成。术后缝合阶段的行为快照对比、测试执行,完全可以挂进 CI,作为每次合入的自动关卡。术前录音、术后对账,这一套逻辑跟自动化测试天然兼容。CI 脚本里加一步behavior_snapshot verify,跑挂了就不让合入,这一步能挡住大量低级回归。
第三层是人工评审通道。SKILL 编排产出的 diff 自检报告、行为快照、测试日志,要能方便地附在评审请求里。评审者看到的不只是几百行 diff,还包括 AI 自己产出的“本次改动影响说明”,评审效率会高很多。
如果你用了一些开源的 Agent 运行时或编排框架,SKILL 也可以直接注册成可调用的工具,让编排层按流程自动路由。多智能体的场景下,每个智能体专注一个 SKILL,互相之间的交接就靠输入输出契约,这条思路和前面讲的是完全一致的。
5. 常见问题与避坑指南
5.1 AI 改错逻辑怎么办
症状:SKILL 里明明写了“禁止修改异常处理逻辑”,AI 还是把异常改成了抛出。原因通常是约束写在了“执行步骤”之后,AI 在长任务执行过程中把步骤中段的约束给忘了。解决办法有两个方向:一是把最关键约束放到任务目标正下方,让 AI 在最开始就高频看到;二是加一个事后自检环节,让 AI 在输出 diff 前先对照约束清单逐条自查。
如果自检还是挡不住,就在编排链路里加一个专门的 verification SKILL。它的唯一职责是检查 AI 产出的 diff 是否违反了约束规则,用规则引擎把“不能改什么”固化成可执行检查。这是最后一道闸门,也是我实测下来最稳的姿势。切记,不要靠“重新对话让 AI 认错再改”来兜底,散装模式的所有缺点在纠错环节会全部重演。
5.2 SKILL 越堆越多,不知道怎么选
症状:团队跑了一个月,技能库膨胀到几十个 SKILL,执行 AI 改造时不知道调哪个。解法是给 SKILL 做分层:底层是原子技能,负责通用操作,比如生成调用图、记录行为快照、执行测试;上层是场景技能,沉淀具体业务场景的经验,比如“链路压测前做静态检查”“订单模块权限点梳理”。原子技能数量少、复用率高;场景技能数量多、针对性强,最好按模块或业务线分类存放。
让执行者知道调哪个,一个好办法是给每个 SKILL 写够质量的 description。很多 Agent 运行时支持根据描述自动匹配技能,描述写得含糊,选错的概率就高。参考标准:描述里要说清楚“这个技能处理什么场景、需要什么输入、产出什么结果、在什么情况下不要用”。
5.3 团队觉得流程重,不想用
症状:引入 SKILL 编排后,每次改造都要先写基线、补测试、走三四个环节,团队抱怨“以前十分钟提交,现在一小时起步”。这个抱怨其实指向一个真实问题:不是所有改动都需要全流程手术。我认可用分类处理的思路:单点 bugfix、一行配置调整,这种“微创小修补”走精简版流程,一个安全修改 SKILL 加一轮测试就够了;跨模块重构、性能优化、架构调整,这种“结构性微创”才走完整编排链路。
流程重不是问题,流程重了但没有换来等价的收益才是问题。让团队接受新方法,最好的方式是挑一个收益最直观的任务先试点,比如修一个长期存在的隐蔽 bug,用 SKILL 编排做干净,把对比结果摆给团队看。价值前置,流程自然就推得动了。
最后再说两句心里话
折腾了这两个月,最深的感觉是:SKILL 编排最大的价值不是让 AI 一次写得更快,而是让产出可复制、可检验、可学习。以前散装 AI 改完代码我心惊胆战,现在每走一步都有对照物,心里踏实多了。如果你也在存量代码里被 AI 坑过,建议从最简单的 code_map 加 behavior_snapshot 两个 SKILL 开始跑,先补上“看得清、比得对”这两件事,再谈自动化改造。微创手术的核心永远是那四个字:先别闯祸。