当代码生成的成本快速下降,团队面对的新难题已不再是 AI 能不能写,而是它会不会在缺少边界时写得过多、改得过头。过度设计、贴合实现的单测和缺乏证据的重构,都可能让看似完整的产出埋下风险。要改善这种状况,需要把工程判断变成 Agent 能执行和验证的约束。
过去大半年,几乎每个使用 Coding Agent(Claude Code、Cursor、Windsurf 等)的工程师都会经历同一种心路历程:
从最初惊叹于它几秒钟写出几十行代码,到后来对着它生成的 PR 陷入深思——AI 很少因为“语法不会”而写错,它绝大多数时候失控,是因为它在错误的优化目标下,把代码写得“太像那么回事了”。
你让它加一个轻量级的 Token 缓存,它顺手给你塞了一套工厂、接口、策略模式加单例;
你让它补单测,它顺手把私有方法的内部实现全 mock 了一遍,测了个寂寞;
你让它做 Code Review,它先夸你一句“架构清晰、逻辑优雅”,然后优雅地放过了最致命的并发竞争;
你让它解释一个老模块,它耐心地读完 30 个文件,然后把你本就能看到的文件列表原封不动地念了一遍。
这些问题,没有一个是语法问题,全都是“工程判断”的问题。
很多人的第一反应是继续往 system_prompt 或 .cursorrules 里加规矩:“不要过度设计”、“多测边界条件”、“认真找 Bug”。但现实是残酷的:规则越长,模型注意力越稀释,最后什么都没约束住。
传统的软件工程规范(Lint、CI、Code Review)是为了对抗人类的惰性与遗忘;
但面对 Agent 时,工程体系必须用来对抗模型的顺从、过度生成与过拟合。
在实际项目踩坑后,我把这些隐性的工程判断抽离出来,写成了 6 个具备明确输入、边界、验证脚本与退出条件的 Agent Skill。它们本质上不是 6 个 Prompt,而是加在 Agent 自主决策链路上的 4 层工程约束环。
code-ablation)约束 Agent 的重构冲动:不要删有价值的复杂度,只消融无价值的包装。
AI 编程有一个极其危险的本能:要么在写新代码时过度设计,要么在重构时把“代码简化”理解成“疯狂删代码,行数越少越好”。
在 code-ablation 这个 Skill 里,我写在最前面的核心约束是:
“只有一个实现只是线索,不是删除依据。”
看一个很典型的场景:
// 很多 AI 看到这里只有一个实现,会直接把它内联掉
export interface TokenStore {
get(key: string): Promise<string | null>;
set(key: string, value: string, ttl: number): Promise<void>;
}
export class RedisTokenStore implements TokenStore { ... }
如果只看当下,删掉 TokenStore 接口确实能省掉 4 行代码。但这个抽象可能承担着跨模块边界、测试桩替换、或者隔离第三方基础设施的责任。盲目删掉它,本质上是在用未来的架构可维护性,换取当下的行数缩减。
因此,这个约束明确框定了消融的前提条件:
Agent 在尝试“简化”代码时,必须先回答:这层抽象到底现在解决了什么真实问题?它如果消失,破坏的是哪个设计边界? 答不上来,就不准动。
test-first + pre-mortem)防止 Agent 陷入“用自己的实现来证明自己正确”的自圆其说。
让 AI 写测试最容易出现的灾难是:它先写完代码,然后照着当前实现的每一行去写断言。 这种测试哪怕覆盖率达到 100%,对回归测试也毫无意义,因为如果明天重构内部实现,测试会全部崩溃;而如果代码逻辑本身理解错了,测试反而固化了错误。
这一层由两个呈对偶关系的 Skill 组成:
test-first:测试约束的是行为契约,不是实现细节这个 Skill 强迫 Agent 遵守一套认识论:测试不仅是给机器跑的,更是给人类维护者看的验收文档。
它强制 Agent 的单测描述必须遵循“业务主语 + 行为 + 触发条件”,严禁出现 should work、test submit、calls charge once 这种面向实现的废话。
更关键的约束是:
需求意图
↓
定义验收场景(契约)
↓
写出必然失败的测试(先红)
↓
编写满足测试的最小实现(再绿)
↓
重构
如果 Agent 测到了私有变量、依赖了未公开的实现细节,必须打回。验证这套测试合不合格的标准只有一个:如果我明天把函数体用完全不同的算法重写一遍,你的测试能不能不改一行直接跑通?
pre-mortem:改变任务的前提,而不是改变提问的措辞普通的 Review Prompt:“请审查这段代码是否存在 Bug。”
在模型的概率分布里,这个任务的前提是:作者写了一段看起来合理的代码,请帮他查漏补缺。 于是模型很自然地进入夸夸群模式,挑几个无关紧要的命名建议就交差了。
而在 pre-mortem Skill 里,我直接切断了这个前提,把它的目标函数强行修改为:
“假设系统已经在半年后的高并发场景下发生了 P0 级事故,现在复盘调查。不要替作者辩解,找出直接导致这次崩溃的 3 个最致命原因。”
当目标从“评价代码”变成“事故调查”时,Agent 的关注点瞬间转移到了:
通过切换任务的立足点,从根源上摧毁了模型默认的“协作迎合倾向”。
self-documenting-code + code-comments)让机器可以表达的留在机器里,让机器无法表达的留给人类。
很多开发者误以为“好代码少写注释”和“详尽注释”是对立的。实际上,这俩是一套严密的信息分流漏斗:
具体逻辑行为 → 由清晰代码自身承载
状态与结构约束 → 由类型系统(Type / Schema)承载
运行时边界限制 → 由断言(Runtime Assert / Guard)承载
行为契约与验收条件 → 由自动化测试(Test)承载
外部无法表达的知识 → 留给注释(Comments)
self-documenting-code:不要让人记住机器本来能记住的事AI 最喜欢写这种代码:
// 错误示范:靠注释维持脆弱的结构
interface ApiResponse {
status: 'loading' | 'success' | 'error';
// 当 status 为 success 时 data 必然存在
data?: UserData;
// 当 status 为 error 时 error 必然存在
error?: Error;
}
这就是典型的“把编译器的活丢给人脑”。只要有人漏看注释,就会产生运行时隐患。
这个 Skill 约束 Agent:必须将状态收敛到结构与类型里:
// 正确做法:用类型消除非法状态
type ApiResponse =
| { status: 'loading' }
| { status: 'success'; data: UserData }
| { status: 'error'; error: Error };
如果代码和类型已经能够自闭环表达“是什么”,任何关于“是什么”的注释全部算作代码噪音,必须清除。
code-comments:保留代码无法表达的决策与外部现实当代码已经被类型和结构极致表达后,剩下的注释应该写什么?
这个 Skill 规定:注释只用来记录外部世界的事实、历史妥协与决策代价。
// 合格的注释:代码无法表达的现实约束
// Safari 16.0~16.3 在页面退入后台时会重复触发 visibilitychange,
// 此处做 150ms 节流以规避主流程重复初始化。
同时设立边界:
context-compression)Agent 应该压缩的是人类的认知负荷,而不是简单地压缩字数。
这是日常体验中最容易被忽视、但最影响人机协作效率的一环。
当一个 Agent 在终端里排查完一个涉及 20 多个文件的老旧复杂 Bug 后,它通常有两种坏习惯:
第一种直接引爆开发者的认知负荷,第二种根本无法建立信任。
context-compression 约束的本质是:要求 Agent 替人类开发者完成最后一次“认知编译”。
源码结构与零散链路
↓(Agent 深度分析)
完整技术结论与因果链
↓(上下文认知压缩)
交付给开发者的心理模型(Mental Model)
它强迫 Agent 在交付结论时,必须组织为:
开发者不是小白,他们只是没有刚刚读过这 20 个文件的即时上下文。Agent 存在的价值,不仅是搞清楚代码,更是帮开发者用最低的认知成本,快速建立起这块代码的心理模型。
回过头看这 6 个 Skill,它们贯穿了一个非常清晰的生命周期:
【理解模块】
↓
context-compression
↓
【设计结构】
↓
self-documenting-code
↓
【实现细节】
↓
code-comments
↓
【验证行为】
↓
test-first
↓
【逆向审查】
↓
pre-mortem
↓
【精简收敛】
↓
code-ablation
在日常使用中,你不需要一股脑把它们全扔给模型。当需要做模块重构时,挂载 code-ablation;当要准备提交关键 PR 时,调用 pre-mortem;当要让它写核心业务逻辑时,触发 test-first。
AI 编码工具发展到今天,代码生成的边际成本几乎已经降到了零。
但软件工程从来不是比拼“谁能在单位时间内生产更多字符”。越是在生成容易的时代,对不必要复杂度的警惕、对独立证伪能力的坚持、以及对认知负荷的控制,反而变得比以往任何时候都更加关键。
这或许就是 AI Coding 时代正在催生的新常态:我们不再只是给人类写规范,我们正在将那些沉淀多年的工程判断,编码成 Agent 必须遵守的可执行契约。
仓库开源在 GitHub:DBAAZzz/skills ,包含各个 Skill 的完整定义、边界条件与配套 scripts,欢迎参考或提 PR 讨论。