给 AI 写一本法典——从“向它许愿”到“让它守规矩”

先讲一件真实发生的事。

2025 年初,我给内部系统加一个功能:导出 Excel。需求很小,我甚至没写文档,直接在对话框里打了句"给列表页加个导出按钮"。

AI 十分钟内搞定了。改前端、加接口、写 SQL,一气呵成。PR 打开的时候我挺高兴,直到 review 发现:导出列和列表页对不上、十万行数据直接卡死服务、没有权限校验、测试只覆盖了最理想的路径。

代码能跑,测试全绿,AI 说完成了。交付是失败的。

后来我又试了一次。同一个需求,这次先确认导出哪些列、大数据量怎么处理、谁有权限,写成文档再动手,拆成三个能独立验收的小任务,最后让人对照原始需求 review 一遍。第一次确实慢一些,但后续维护和换人接手都稳得多。

两次用的是同一个模型。差距不在模型。

核心观点
同一个需求,两条路径,同一个模型。差的是你有没有一套可执行的规矩

早期我犯过的错误,很多人应该都犯过。

“帮我把这个模块重构一下。“结果 AI 把原来能看懂的代码,改成了连自己都看不懂的样子。

“加个测试。“它写了一堆测试,测的都是理想路径。边界条件?异常情况?没人问,它也不问。

“这个 bug 修一下。“它确实修了,但没动根本原因,换个输入就再犯。

最离谱的一次:我让 AI “优化一下这个函数”,它把 30 行代码压缩成 8 行,“简洁多了”。简洁是简洁了,可读性归零。后来换人接手,花了半天才搞明白那 8 行在干什么。

共同点:我给了一个模糊的愿望,AI 补上了所有默认答案。默认答案错得很有礼貌——代码能编译,测试通过,没有任何报错。

能跑的陷阱
“能跑"比报错更危险。报错会逼你停下来想,能跑让你以为自己已经想过了。

后来我读到一篇讲 AI 工作流的文章,《从 AI 写代码到 AI 工作流》

文章说:同一个需求,“直接让 AI 写"和"先对齐再动手"两条路径,用的是同一个模型。差距在于流程:需求对齐、设计决策、任务拆分、逐步实现、独立评审、知识交接,六个阶段,少一个就出岔子。

我同意。但读完心里有个疑问:文章说"要有六个阶段”,然后呢?谁来执行?

靠自觉?靠每天早上开工前默念一遍"今天我要走六个阶段”?还是靠一份没人会认真读的内部文档?

我把这个问题推到底:流程如果不变成某种"可执行的东西”,它就只是一份愿望清单。AI 不需要愿望清单,AI 需要的是明确到每一行的指令。

所以我写了 ByronFinn/dev-skills——一套遵循标准 skill 规范的技能集,加载到 AI 之后,它就知道规矩了。

功能清单和安装方式我不重复了,之前的一篇盘点写过。这里只说设计上的三个决定:

第一,每个技能都是纯文本。 SKILL.md 是入口指令,REFERENCE.md 是详细流程,格式模板另放一个文件。没有运行时,没有脚手架,没有额外依赖。规矩本身是文本,加载机制是平台的事——Skill 的加载和执行机制 那篇拆过。

第二,每个技能补一个具体的洞。 12 个技能覆盖从构思到发布,每个都单独成立。挑六个核心的说:

  • /think 发散构思,收敛成决策完备的 PRD:目标、方案、验收标准、技术决策,以及明确不做什么。
  • /grill 对抗性审读,把每个未决问题、模糊假设、没定义好的术语逐个逼到墙角,不解决完不放行。
  • /story 垂直切片,把方案拆成能独立执行、独立验收的小任务。水平切写出来的用例,测的是想象出来的行为。
  • /tdd 子代理编排的测试驱动开发,每个验收标准一个周期。
  • /review 三方并行评审:测试、代码、影响各由一个子代理独立审,报告合并后矛盾不自动消解,交给真人裁。
  • /research 从权威信源(官方文档、源码、规范)取经,写成版本化、不可变的记录,大版本更新就开新档案,旧档永久冻结。

第三,规矩不是写给人的,是写给 AI 加载器的。 有人可能会说,这不过是把"好的工程实践"写成了文档。是的,关键不在"写好”,在加载之后 AI 就守这个规矩。

同一条愿望,两条路径:左边靠许愿,右边靠规矩

回到开头的"导出 Excel”。

技能加载之后,我不再说"加个导出按钮”。/think 开工,AI 开始问:导出哪些列?大数据量怎么处置?权限?并发?/grill 上来审读,“大数据量"这种词过不了关:十万?一百万?一千?不定义清楚不放行。/story 切成三个任务:小数据量基础导出、大数据量异步导出加下载链接、权限校验,每个都能独立验收。/tdd 里,权限校验缺失会被自己的用例抓住,不是靠运气。最后 /review 三方并行,矛盾交给真人判。

同样的"导出 Excel”,两次都是 AI 写的代码。第一次靠许愿,第二次靠规矩。

关键区别
AI 本来就聪明,聪明到能把你没想清楚的地方补成看起来很完美的样子。规矩的作用不是放大 AI 的能力,而是挡住它的默认答案——让你的判断有机会落地。
/tdd 的两道人工门与两个独立进程

/tdd/review 的核心设计是子代理编排:测试子代理和开发子代理是两个独立进程,各自从零开始,各自从磁盘重读所有上下文。测试子代理不知道代码会怎么写,开发子代理必须真正读懂用例才能让测试变绿。

子代理为什么该独立——上下文隔离、防止污染、无状态行为可推理——这些在多代理架构那篇已经论证过,不重复。这里补两个"独立"落实在流程上的细节:

第一,两道人工门。 场景设计完,人审一遍;用例写完,再审一遍;然后开发子代理才动手。审不出问题就重来,人不能缺席。

第二,记忆不共享。 测试子代理和开发子代理在同一个编排进程下,但没有任何共享的对话记忆。开发子代理只能从用例本身理解行为,不能从"测试子代理刚才说过的话"里猜。

这句话可能让你失望,但我说的是实话:技能解决不了所有问题。

它能解决的是"AI 忘了规矩”。解决不了"规矩本身是错的"。PRD 的质量取决于人的判断。/grill 审读再狠,如果初始需求就是错的,也只是把错误的方向执行得更彻底。/tdd 的测试再全面,如果测的是错误的行为,那也只是错误地做对了事情。

有没有银弹?没有。

没有银弹
技能只是让"没有银弹"这个事实变得不那么痛苦。它不能替你思考,但它能确保你思考过的东西有机会变成代码,而不是被一个看似聪明实则懒惰的默认答案覆盖掉。

我做 dev-skills 的时候,脑子里一直有一个画面:

某个深夜,你写了个功能,第二天早上来了个新同事接手。他不需要问你"这个设计为什么这么搞"“那个边界条件当时怎么考虑的”——他打开 PRD,看 ADR,翻 research 记录,全在那儿。

无非是想要:下次有人问"为什么这么做"的时候,你可以指着文件说,看那儿。

相关内容