我最开始用 AI 写代码,是完全没立规矩的——它写得又快又像样,我就放手让它写。
然后很快被现实教育了:它能在一个for循环里查数据库,一个列表接口悄无声息打出几十条 SQL;代码里魔法值满天飞,if (status == 3)、timeout > 5000这种数字到处裸奔,谁也说不清 3 是什么、5000 从哪来;命名、分层、异常处理各写各的,一个项目看着像五个人同时提交的。功能确实跑得通,但那代码我都不敢细看。
就是被这些具体的烂代码逼到份上,我才反应过来:得给它立规矩了。中途我还天真地以为是模型不够强,换了个更贵的——结果一样,它只是把不守规矩的方式升级得更体面了。
这篇记录我是怎么一层层给 AI 上枷锁的:先写规则,再定流程,中间也去拜读过业界那几套很成熟的 SDD 框架,最后才想明白一件事——只要约束还停留在"说"的层面,它就一定有办法绕过去。真正的转折,是我把规矩从提示词里搬到了磁盘上——而且我特意做得很小、很轻,复制进项目当天就能用,不用先学一套方法论。
第一层:写规则,先治"代码写得太烂"
最先加的规矩很朴素:建个规则文件(就是现在AGENTS.md那类东西),把最扎眼的几个坑一条条写死。而且一开始全是编码规范——因为逼我动手的就是前面那些脏代码:
- 禁止在循环里做数据库 / 远程调用,批量场景走批量接口。 - 不许出现魔法值:状态码、阈值一律提成常量或枚举。 - 命名、分层、异常处理跟随项目既有约定,不许自创风格。有用吗?真有用。N+1、魔法值这种一眼扎眼的问题,它开始主动避开了,交付的东西终于像个懂行的人写的。尝到甜头后,我又往这个文件里补了些行为约束(不许擅自扩需求、不许乱改稳定代码、模糊就先问),越权乱改的毛病也压下去不少。
但很快发现新的问题:代码质量上去了,过程还是乱的。我让它改个东西,它上来闷头一顿输出,改完我才发现它理解的需求跟我要的根本不是一回事,方向从第一步就歪了。
规则能约束"写成什么样",约束不了"它到底有没有跟你想一块儿去"。
第二层:定流程,逼它"先对齐再动手"
于是我加了流程,核心就一句话:别急着写,先把认知和需求跟我对齐。
具体要求 AI:
- 动手前,先把它理解的目标、范围、不确定的点列出来,向我提问,把模糊的地方摊开;
- 然后由它制定计划、由我来审——计划没通过,不许碰代码。
这一步的价值比规则大得多。因为它把"事后返工"变成了"事前拦截":很多脑补和扩需求,在提问那一步就暴露了,我一句话就能摁回去。相当长一段时间,我觉得这套够用了。
直到我开始让它干更大、更跨模块的活。问题来了:计划它确实出了,但出在聊天记录里。一个任务聊到第 30 轮,早期的对齐结论、中途改过的决定,全埋在滚动窗口里,它自己都开始"记混",前后矛盾。更烦的是,换个会话、换个工具,之前所有对齐全部清零。
流程解决了"要不要对齐",但没解决"对齐的东西存哪、下次还算不算数"。
第三层:业界早有这套东西,只是对我太重了
顺着这个痛点搜,我发现"先对齐、把决策落成文件"这事业界早有名字,叫SDD(Spec-Driven Development,规范驱动开发),也有一批很成熟的实现(OpenSpec、spec-kit 这些)。它们的核心主张跟我自己摸出来的方向完全一致:把一次改动落成磁盘上的规范工件,别散在聊天里。看到这儿我挺服气——说明我大方向蒙对了。
但真上手,我卡住了。这些框架都很完整,完整到一上来就是一整套命令、目录、schema、模板、还有一堆 skills,我得先花半天搞懂它怎么转,才敢往项目里放。我承认它们强,可对我这种就想赶紧把活干完的人,光那一大坨文件清单就够我头大的。我要的其实特别朴素:文件少到一眼看完、不用装一堆东西、不用先学一套方法论、复制进项目当天就能用。
于是我退回到自己的需求上:大方向照搬业界验证过的,但落地成一个我能直接上手的小版本。
第四层:可就算有了工件,它还是能绕过去
真正让我下决心自己造轮子的,是这么个体验:文件是建了,可 AI 照样会**“假装走流程”**。
- 说好让它先出计划、我点头再动手,结果它文档刚生成,我还没看,转头就改起代码来了;
- 更常见的是,它压根不理这套,看到需求直接开写,你事后追问"计划呢、工件呢",它才回头补一份;
- 让它自己核对"实现跟规格里有没有对不上的地方",它也能敷衍回一句"已核对,没问题",实际根本没逐条比。
我盯着这事想了很久,才想通根子在哪:这些约束说到底还是停在"话"和"文档"上,靠的是 AI"愿意配合"。我无意去说哪个框架不好——人家本来也没承诺替你物理拦住什么,它们给的是秩序,让流程更清楚。可秩序不等于强制:只要没有任何东西会因为 AI 跳过某一步而"当场报错失败",一个能读写你文件系统的 Agent,就能大摇大摆地走过去。
一句话:软约束只能约束愿意配合的人;对一个能跳过步骤、自己给自己盖章的 Agent,等于没约束。我要的,是把"没对齐、没批准就想改代码"变成一个会当场失败的动作。
转折:把门禁从"话"变成"脚本"
想明白这点,解法其实就一个方向——别让约束停在文字上,让它变成一个会失败的东西。
我做的东西很小,小到有点拿不出手:就四份文件,加一个校验脚本。四份文件是——CLARIFY.md(这次有哪些还没答的问题)、SPEC.md(到底做什么、怎么算验收、以及审批状态)、PLAN.md(拆成哪些任务、动哪些文件)、progress.md(执行留痕,只增不改)。那个脚本干的事也朴素:把"能不能开始改代码"交给它的返回码说了算,而不是 AI 的自觉。它会真的去读磁盘上这四份文件,逐条卡:
# 编码前必须跑,不过就不许动代码 .\scripts\check-change.ps1 -ChangeId order-refund-flow-001 -RequireApproved它校验的就三件事,但每一件都戳在之前 AI 爱钻的空子上:
- 四件套齐不齐——想跳过建工件直接干?文件不存在,报错。
SPEC.md是不是真approved——状态得是approved,而且approvedBy、approvedAt不能是空的、不能是占位符。你想自己填?格式和占位符检测会拦你一手,逼这个"审批动作"至少留下可追溯的痕迹。CLARIFY.md还有没有没答的阻塞问题——只要有一行同时命中"阻塞"和"待答复",直接判定不通过:
specgate check: FAILED - CLARIFY contains an unanswered blocking question这么一改,性质就变了。之前是"AI 你觉得你遵守了就行",现在是"你要么把工件填到能通过校验,要么就别想往下走"。它没法靠一句口头承诺糊弄过去,因为糊弄不过一个会返回非零退出码的脚本。
(这里插个真实的小坑,如果你也自己在 Windows 上写这种校验脚本:PowerShell 5.1 读没有 BOM 的 .ps1 会按 GBK 解码,你源码里写的中文匹配串会乱码,导致门禁直接失效、还以为是逻辑错了。我最后是把"待填写"“阻塞”"待答复"这些中文判断词全用 Unicode 码点拼出来,让脚本源码保持纯 ASCII,才稳。)
但我没骗自己:这依然不是万能锁
写到这儿,得说点诚实的,不然就成了吹自己工具了。
这套门禁是"纵深防御",不是"沙箱"。只要 AI 跟你用的是同一个文件读写权限,它就总有办法:
- 干脆不跑脚本,直接改代码;
- 把校验脚本本身改成永远返回 OK;
- 改了
PLAN.md清单之外的文件; - 事后回填 progress,伪造执行记录。
这些我在会话内确实根除不了。所以我对这套东西的定位很清楚:它不是"物理拦住",而是"抬高作弊成本 + 留下能对账的证据链"。真正的硬约束,来自权限圈之外——比如接进 CI 做 required check、开分支保护、要真人 review,让 AI 没有合并权;比如 git 历史对账,提交时间和approvedAt对不上、实际 diff 和 PLAN 清单对不上,一翻一个准。
门禁能保证的是:AI 改的每一处代码,要么留下了合规的审批痕迹,要么就跟它对不上账。至于它有没有越权,交给圈外机制和事后审计去判。至少,它再也没办法一边破坏规矩、一边装得跟什么都没发生一样。
回头看这四层
一路走下来,其实是有条明线的,每一层都在补上一层漏掉的东西:
| 层次 | 解决什么 | 没解决什么 |
|---|---|---|
| 规则文件 | 代码写成什么样 | 过程乱、方向歪 |
| 流程(提问+计划审核) | 事前对齐认知 | 结论存聊天里,会忘、会清零 |
| 业界 SDD 框架 | 决策落成磁盘工件 | 对我太重、要先学;且仍靠自觉,能绕过 |
| 脚本门禁 | 让"合规"变成一个会失败的东西 | 同权限下的逃逸,得靠 CI / 人审兜底 |
如果你也在被"AI 不听话"折磨,我的体会是:先别急着换更强的模型,模型再强也只是把不守规矩藏得更深。真正管用的,是把你心里那条"必须怎样"的线,从"跟它说清楚",一步步变成"它绕不过去的东西"。
能写成脚本的约束,就别只写在提示词里。
这套我自己用的骨架开源在这儿:四份文件模板、一个校验脚本、一份 AGENTS 总线,没了。不用装环境、不用学命令,复制进你项目当天就能用;嫌管得宽,就自己删两条——它本来就是我按自己的毛病攒的,你尽管改成合你手的形状。地址放这儿:https://gitee.com/hero520/specgate。也特别想听听——你们都是怎么治 AI 不守规矩这毛病的?尤其同样被"一堆文件"劝退过的人,评论区聊聊。