工程手记 · 上篇
AI 编程助手做项目级对接方案Claude Code
我们的测试全绿了三个月
然后我们把守卫改坏了
它还是绿的。
给 AI 编码助手做企业级对接方案,三个月,十轮全量评审。四端异构、SVN 主线、金融级安全要求。
这篇讲为什么这么设计——不讲怎么配置。
01
先说它到底解决什么
引入 AI 编码助手之后,团队会立刻撞上三件事。不是"可能会",是"一定会"。
它不知道项目的规矩
用错鉴权方式、改了不该改的加密文件、DDL 只写一种数据库方言。
它会声称完成
"已修复并验证通过"——但它没跑过任何命令。用例设计了 80 条,跑了 20 条,剩下 60 条归到"人工补验",然后在总结里写"测试已完成"。
它的产出无法追溯
谁批准的、基于哪版方案、测了什么、没测什么——事后全查不到。
对接方案要做的,就是把这三类问题变成可配置、可执行、可验证的工程设施。
02
四层,每层补上一层的漏
L4 · 验证机制
自检 / 变异测试 / 干净检出可复现
证明前三层真的生效
L3 · 机器闸
审批闸 / 写入范围守卫
真正拦得住的
L2 · 角色流程
agents / skills / 三档流程
怎么干活
L1 · 知识约束
CLAUDE.md / rules / 权限配置
知道什么、不许干什么
每一层解决上一层解决不了的问题:
第一层是文档规则——遵守率取决于 AI 有没有读到那一段。
第二层把规则编排成流程——但流程仍可被跳过。
第三层用 hook 强制——跳不过去。
第四层证明前三层确实装上了且没坏。
跳过任何一层,都会留下"看起来有、实际没有"的假象。
我们付出的最大代价,几乎全部来自第四层缺失:方案写得很完整,但没人能证明它生效。
03
一个需求怎么走完全程
五个阶段,四道人工确认门,三处机器拦截。
阶段 0
需求拆解
功能点 / 业务规则 / 各端影响面 / 测试点
✍ 人工确认门 1 · 拆解结论对不对
阶段 1 + 1.5
方案设计 + 测试一阶段
接口签名 / 数据结构 / 验收标准 / 用例骨架
✍ 人工确认门 2 · 方案 + 验收标准
⛔ 机器闸 · 审批未确认 → 调用被拒
阶段 2
四端并行编码
各 dev agent 只能写自己工程目录
阶段 3
代码评审
✍ 人工确认门 3 · 可提测
阶段 4
测试二阶段
用例填实 / 两表对账 / 回归结论
✍ 人工确认门 4 · 发布放行签字
为什么拆解和设计必须分开?
我们最初合成一步,结果产出大量重复内容。因为这是两种思维:
拆解 → 这个需求包含什么
清单式,穷举
设计 → 这些东西怎么实现
结构式,取舍
混在一起,AI 会一边列功能点一边设计接口,两边都不完整。
阶段 1.5 是后加的
它解决一个具体问题:如果测试用例在编码之后才设计,测试人员会照着已写好的代码去设计用例——
用例变成了代码的镜像,而不是需求的检验。
把用例骨架提到编码之前,用例编号先于代码存在,后面的对账才有基准。
04
不是所有需求都值得走五阶段
我们最初只有一套完整流程。跑了两周,团队反馈:"改个文案也要走六步。"
然后发生的事情完全可以预料——他们开始绕过流程。有人直接改代码不建单,有人建了单但所有确认门一次性全填 yes。
被绕过的流程等于不存在,而且比不存在更糟。
它制造了"我们有流程"的假象,让管理层以为风险被控制了。
解法是三档分流。判档表自上而下、命中即定档:
A 档全部五阶段 · 4 道确认门
触及审批项:认证 / 权限 / DDL / 对外协议 / 加密 / 发布
无条件,不可降档
B 档简版拆解 → 简版设计 → 1 道确认门
有新接口 / 新命令,但不触审批项
C 档直接编码 + 自测 + 评审
纯文案 / 常量 / 字段透传 / 明确的单行 bug
第一行是硬闸,不可降档
哪怕是单行改动,碰了认证、权限、数据库结构、对外协议、加密——无条件 A 档。
没这条会出现什么?我们见过这句话:
"顺手改了一下过滤链,反正是个 C 档小改动。"
过滤链是鉴权核心。改错了,整个系统的权限模型就漏了。
B 档的价值不在轻量,在保留接口对齐
B 档砍掉长篇风险分析没问题,但这四项必须保留:接口签名、数据结构、鉴权级别、数据源归属。
原因很实际:四端之间有两条 HTTP 契约和一条加密签名链。任何一端擅自改了字段名或加密方式,联调时才发现,返工成本远超写文档的成本。如果连这四项都砍了,B 档和 C 档没有区别。
05
流程需要一个物理载体
流程不能只写在文档里。它需要一个机器能读、人工能签的东西。
每个需求有一个审批状态文件:
需求名: v4.0.11-锁具固件OTA优化 档位: A 设计文档: docs/02-design/design-xxx.md 拆解确认: yes← 确认门 1方案确认: yes← 卡 dev agent 调用评审放行: no← 卡发布说明生成发布批准: no← 人工最终签字
三个设计要点:
AI 被禁止写入此文件。它能创建模板,不能改状态——能开单,不能盖章。
两个字段挂着机器闸。「方案确认」不是 yes,调编码 agent 直接被拒;「评审放行」不是 yes,发布说明写不出来。
C 档豁免机器闸,但仍需人工建单——留痕不能省。
三道闸:从"约定"变成"约束"
调编码 agent
无审批文件 或「方案确认: no」→ 拒绝
编码写文件
写到别的工程目录 → 拒绝
生成发布说明
「评审放行: no」或测试总结未落盘 → 拒绝
没有这三道闸,流程图只是一张建议。
有了它们,跳过阶段 1 就真的写不了代码。
06
六条设计思想
照抄结构容易,照抄思想难。只抄结构的方案,会在半年内失效。
思想 一
分层不是为了整洁,是为了控制上下文
AI 每次会话能装进上下文的内容有限,且越靠后的内容越容易被忽略。
我们实测反复出现的现象:全局规则文件超过 200 行后,AI 开始漏读后半部分。表现是——你在第 180 行写了一条规则,它照做;挪到第 250 行,它就当没看见。
这不是模型缺陷,是注意力分配的必然结果。方案设计必须承认这个约束,而不是假装它不存在。
做法是按"是否每次都需要"切分:全局池子只留跨模块的硬约束、命令速查、测试纪律;各端细则改成路径触发——编辑 Java 工程时 Java 规则才进上下文,编辑前端时它不占位置。
但这个机制有边界
路径触发依赖"AI 读了匹配的文件"。如果它不读任何现有文件就直接新建,规则不会加载。
所以要写死一条纪律:"先理解,再修改。"逼它必然先读。
这是贯穿全案的模式
机制有边界时,用纪律补,并把边界写明。
不写明边界,后来人会以为机制是万能的。
思想 二
流程分档,让成本匹配风险
已在第 04 节展开。这里只留一条判断标准——
档位划分是否合理,看一个信号:团队是否开始绕过流程。
如果绕过了,不是团队纪律问题,是你的档位划分让成本没匹配风险。
思想 三
能用机器拦的,不要只写在文档里
文档规则的实际遵守率 = AI 读到那段的概率 × 它当时的判断质量。
两个乘数都不是 100%,乘起来更低。而且这个概率不可观测——你不知道这次它有没有读到,只能从结果反推。
一个必须知道的默认行为
钩子的默认语义是放行:脚本正常退出且没有明确说"拒绝",流程继续。
你的守卫脚本崩溃了,等于没装。
而且崩溃是静默的,你看不出来。
所以所有阻断型守卫必须显式拒绝异常输入:输入为空、解析失败、参数非法,一律拒绝。
我们的写入守卫最早在空输入时放行,后来改成拒绝。原因是——
"守卫在场但不生效"比"守卫不在场"危险得多——前者制造安全假象。
⚠️ 必须诚实标注的边界
权限限制是防误操作护栏,不是不可绕过的强制边界。它挡不住:
· 子进程——脚本里再起一个进程执行命令
· 动态拼接的命令行
· 换一个 shell——规则按工具名匹配
· 主会话直接改文件——闸只约束子代理调用
方案文档必须写明这一点。否则给团队虚假的安全感——这比没有防护更危险,因为人会基于错误的安全假设去做决策。
思想 四
任何事实只有一个权威出处
同一个事实散落多处,改一处漏七处。
这是我们花时间最多的问题类型,超过写方案本身。
它为什么特别难防
因为每一处单独看都是对的。
真实案例:一条关于"测试文档目录形态"的规定,散落在 8 个文件里——流程手册、测试 agent 定义、模板注释、新手指南、自检脚本的断言……
第一轮改了 2 处,以为清了。第二轮又发现 3 处。第三轮才清完。
最糟的一次
我编辑了某个文件的第 40-43 行,却没看同一个文件的第 50/51/54 行——那里有同样的错误表述。
我改了"我看到的那处",而不是"所有那处"。
做法:每个事实挑一个权威文件;其余位置只写指针,不复述内容——复制的那一刻,你就创造了第二个真相源;修正错误后,全库反查所有出现点。
一个反直觉的陷阱
删掉一处引用而不给替代,也会制造第二个真相源。
我们踩过:模板里原本有一句"档位定义见 X",评审时觉得冗余删掉了。结果模板和机器闸各自定义档位,半年后对不上了。
思想 五
证据先于断言
AI 会把"看起来对"写得非常像"确实对",包括它对自己工作的验证报告。
更隐蔽的一种:用例设计了 80 条,跑了 20 条纯逻辑的,剩下 60 条需要环境的归到"人工补验"。然后在总结里写"测试已完成"。没跑的那 60 条,在心理上被当作通过了。
解法是一条纪律 + 两张表。纪律很简单:
声称"完成/修复/通过"之前,必须在当前回复内跑过验证命令并贴出新鲜证据。
关键词是"当前回复内"和"新鲜"——防的是引用几轮之前的旧输出。
表一 · 改动点↔用例映射表
防漏写
左列是本次实际改动的文件和行为,不是测试文档里的用例。每个改动点必须指向 ≥1 个用例编号,或写明"无需测试 + 理由"。
表二 · 测试完成度对账表
防漏跑
测试文档里每个用例编号一行,三态显式标注:
✅ 自动 —— 附测试名/命令
✅ 手测 —— 注明谁测的 + 观察到的现象
❌ 未执行 —— 缺什么依赖 + 补验命令 + 判定标准
为什么两张都要
这是本条最重要的一点。对账表只能保证"文档里的用例都跑了",防不了"测试设计本身漏了改动点"。
我们有五六个改动点,测试文档从来没有对应用例——对账表永远发现不了,因为它只对账文档里有的东西。这些缺口全靠人偶然实测撞见。
映射表是改动驱动(以 diff 为准反推用例)
对账表是文档驱动(以测试文档为准核对执行)
缺一不可。
思想 六 · 最深的一层
验证机制自己必须有鉴别力
我们有一套自检脚本 + 单元测试,长期"全绿"。
第八轮评审时,有人问了一个问题:
如果我故意把守卫改坏这套测试会红吗?
答案是:大部分不会。
测试在跑,测试全绿,但它们没有断言真正关键的行为。绿色只证明测试跑完了,不证明被测对象是对的。
一个具体的假绿
自检脚本里有一条:检查权限配置的"默认模式"字段存在。
问题是——存在不等于正确。有人把这个字段改成"绕过所有权限",自检照样全绿,而十几条禁止规则全部失效。
修正后的写法是断言"值等于预期值",不是断言"字段存在"。这类假绿在自检脚本里成片出现过,后来专门做了一轮反向扫描才清完。
四条判据
测试存在 = 有保护
测试可能根本没断言关键行为。存在性 ≠ 鉴别力
单元测试红 = 门禁会拦
单元测试跑的是函数,门禁跑的是钩子调度。函数对了不代表调度链通
变异测试落盘 = 等价于原缺陷
你注入的变异可能比原缺陷温和得多
观察到失败 = 观察到"没有发生"
"我看到它拒绝了"强于"我没看到它放行"
硬规则
任何测试用例,若没有配套的变异证据(把被测逻辑故意改坏、确认测试变红),视为未编写。
这条规则成本很高——每条测试要多做一次"改坏再改回"。但它是唯一能证明测试有鉴别力的方法。而且它不只适用于本方案:任何"我们有测试所以有保障"的论断,都该被这个问题检验一遍。
07
三个判断点
① 什么时候算"可以推广给团队"?
判据是干净检出可复现:从版本库全新检出一份,不带任何本地状态,跑通全套验证。
这条判据挡住过一次真实事故:工作区里方案跑得好好的,但有 3 个文件从未提交。干净检出后——接线在、闸不在,所有审批调用静默通过。
"在我机器上能跑"对这类方案是完全无效的证据。
② 什么时候算"方案有问题"?
团队开始绕过流程
→ 档位划分不合理,成本没匹配风险
同一个错误反复出现在不同文件
→ 权威出处没建立
"测试全绿"但线上仍出问题
→ 验证机制没有鉴别力
③ 这套东西的天花板在哪?
权限限制挡不住的部分——子进程、动态拼接命令、换 shell、主会话直改——是结构性边界,靠加规则解决不了。要突破需要组织级策略管控或隔离执行环境,那是独立立项。写明了,团队知道哪里还需要人工兜底;不写明,所有人都以为已经安全了。
08
要花多久
盘点1 周· 技术栈真值 / 敏感文件清单 / 审批项
知识层3 天· 全局约束 / 规则 / 权限配置
流程层4 天· agents / skills / 审批机制
机器闸层5 天· 守卫 / 审批闸 / 跨平台调度
验证层5 天· 自检 / 变异证据 / 干净检出
合计约 4 周达到可用状态。
但这只是第一版——我们后续用了两个多月做十轮全量评审,才达到可发布状态。
把"4 周搭完"和"可以推广给团队"当成两件事。
中间隔着的是验证层的成熟度,而那是最容易被低估的部分。
如果只带走一句话
给方案本身建立可证伪的验收判据
比方案写得多完整重要得多。
四端异构 · SVN 主线 · 三个月 · 十轮全量评审
下一篇:搭建手册与配置实样
夜雨聆风