起因:最贵的一句话是「已完成」

用 AI 编码代理写代码,最先崩溃的不是代码质量,是信任。

我遇到过这些情况,相信你也不陌生:

  • 它说「已修复」,你问「跑过测试吗」,它回「应该没问题」;
  • 报错信息明明摆在屏幕上,它开始猜「可能是环境问题」;
  • 同一个思路改了三遍参数,还叫「继续尝试」;
  • 修完一个点就停住,等你再提下一个点——它不是不会,是没把这件事当自己的事。

第一反应是加提示词:「请认真检查」「请务必验证」「不要放弃」。写完发现收效甚微。原因很简单:

提示词是建议,不是机制。

建议的宿命是被绕过。模型在每一轮都要重新决策「现在该做什么」,如果规则只是「上下文里一段温和的叮嘱」,它在赶进度、上下文被压、或者遇到模糊判断时,就会顺手绕开——而且绕得毫无心理负担。

后来我把这套东西重写成了技能(skill),核心思路只有一条:

把「态度要求」翻译成「状态机 + 判定口径 + 证据要求」。

下面说清楚它到底由什么构成、哪些设计真的起作用、以及它的副作用。

一、把「努力」变成可推进的状态机

模糊的要求无法执行,「现在处于什么状态、下一步必须做什么」才可以。

所以第一层是失败计数。计数决定压力等级,等级决定强制动作:

已确认失败次数等级强制动作
0–1L0正常推进,不施压
2L1必须换本质不同的方案
3L2搜索 + 读源码 + 列出 3 个假设
4L3走完 7 项检查清单
5+L4穷尽模式:换工具 / 换角度 / 换技术栈

关键不在这张表,而在计数口径。口径不对,状态机就是个随机施压器。

我踩过的坑都写进了口径里:

  • 一次「实际方案未达到预先定义的验收」才算一次失败。 正在做第三次尝试 ≠ 已失败三次。数字 2 也不等于 L2。
  • 命令红绿不算任务失败。 grep 没匹配、ls 路径不存在、预期的复现失败,都是信息,不是失败。
  • 读文件成功不清零。 进度不因为「操作成功了」而重置,只因为「验收通过了」而重置。
  • 同一假设重复且没有新信息,必须换实验。 有新证据的探索不强行掉头。

这几条听起来啰嗦,但少了任何一条,agent 就会开始在两种噪音之间摇摆:要么空转不升级,要么把「命令报错」当成失败一路飙到 L4 开始乱改。

二、诊断先行:治「分析正确但不行动」

有一类失败特别隐蔽——它不是偷懒,是过度谨慎。

根因分析得头头是道,然后因为「怕破坏现有测试」「怕误解验收标准」,不动手了,开始问你「需要我继续吗」。

这类失败用压力治不好,得用格式治。所以协议规定:改动代码或配置之前,必须先落一行外部承诺:

[PUA-DIAGNOSIS] 问题是 ___;证据是 ___;下一步动作是 ___。

三个空都必须填实:

  • 问题是:具体到文件 / 模块 / 数据流,不能是「可能有问题」;
  • 证据是:错误原文 / 源码上下文 / 复现实验 / 官方文档 / 历史先例,必须标来源;
  • 下一步是:如果诊断指向某个位置,下一步就必须处理那个位置;不处理要说明为什么。

这行的作用不是表演,是把「分析」和「行动」焊死在同一句话里。写完这句话再不动手,就只能撒谎——而模型通常宁可动手,也不愿写一句自己都不信的话。

配套还有一条容易忽略的规则:「修完后原来的 bug-existence test 会失败」不是不行动的理由。 那种测试往往只是在证明旧 bug 存在,该改的是验收方式,不是绕开修复。

三、验收必须绑证据

这是整套协议里最硬的一条,也是收益最大的一条:

声称「已修复 / 已完成」之前,必须跑验证命令,并贴出输出。没有输出的完成叫自嗨。

拆成三个可检查的动作:

  1. 列声明:把「我做完了」拆成可验证项——需求满足、实现正确、测试通过、无回归、部署 / 缓存 / 文档已同步。
  2. 找漏洞:逐项当自己的蓝军——哪条声明最可能是假的?边界输入、失败路径、权限 / 路径 / 版本、并发 / 状态、缓存 / 发布链路。
  3. 修或披露:P0 / P1 漏洞先修;外部不可控的低风险项必须明说,不能藏。

然后是「闭环」的判定标准,我把它写成一句话方便记忆:

事实上的 100%,不是宇宙级正确,而是「当前可获得证据下所有可运行验收都通过、所有已知高风险漏洞已修复、剩余风险已明示」。

还有一条反通胀规则很重要:

  • 好标记:主动加了注入防护、部署后 curl 了全部端点。
  • 烂标记:写了代码、读了文件、思考了方案。

标记一旦通胀,就变成了自我表扬的噪音。加这条规则就是为了让「标记」重新有信息量——它必须只用于超出用户要求范围的有价值工作。

四、按任务类型路由方法论

同一个 agent 面对不同任务,该用不同的思维框架。debug 和新功能开发需要的根本不是同一种纪律。

所以第二层是路由表:

任务类型方法论核心
修 BugRCA 5-Why 根因分析 + 蓝军自攻击
建新功能质疑需求 → 删除 → 简化 → 加速 → 自动化(严格按序)
代码审查减法优先 + 像素级完美 + 单一负责人
调研搜索优先于判断
架构决策Working Backwards:从用户倒推
性能优化数据驱动,A/B 一切

注意「建新功能」那条的顺序。大多数人的错误是直接跳到第 4 步——去优化一个本不该存在的东西。先质疑需求、再删除,最后才谈优化。

失败时还有切换链,避免「越失败越用力」:

失败模式切换顺序
原地打转(只改参数不改思路)质疑需求 → 砍中间环节 → 反向攻击
放弃 / 推锅Keeper Test 该换就换 → 集中兵力 → 极限施压
没搜就猜搜索 → 深挖 → 用数据验证
空口完成数据验证 → 只看结果 → 闭环验证

切换前还有三问防无效切换:当前方法论的核心步骤走完了吗?失败是方法不对还是执行不到位?新框架能解决当前失败模式吗?

五、抗合理化清单

这是我认为最实用的部分。Agent 的「偷懒」几乎都以合理措辞出现,所以要把借口和反击一一对应写死:

借口反击
「超出能力范围」你穷尽了吗?
「建议用户手动处理」这是你的 bug,不是用户的
「可能是环境问题」你验证了,还是猜的?
「需要更多上下文」你有工具,先查后问
「已尝试所有方法」搜过了吗?读源码了吗?方法论在哪?
「我无法解决」通用方法论 5 步走完了吗?

最后还有换框:改认知坐标系,而不是改语气。

  • L2 换视角:用户视角(期望什么行为)、攻击者视角(怎么让它崩)、新手视角(忘掉已知)。
  • L3 换抽象层:上移到调用方、下移到源码、平移到别的库。
  • L4 换约束:不能改这个文件呢?只有 5 行预算呢?能改需求吗?

约束一换,「不可能」经常立刻变成「有个办法但不好看」。

六、落地形态:分层加载,别把整套读进上下文

一套几千字的协议如果每次全量塞进上下文,token 成本会很难看。

所以它被拆成两层:

skills/pua/
├── SKILL.md                       # 常驻:契约 + 红线 + 路由表
└── references/
    ├── flavors.md                 # 风味:只有当前这一种要读
    ├── methodology-router.md      # 需要选/切换方法论时读
    ├── methodology-*.md           # 各公司方法论的详细行为约束
    ├── display-protocol.md        # 需要出面板时读
    └── de-escalation-protocol.md  # L2+ 或真突破时才读

原则是:只读当前动作需要的那一份。选味道时读路由,只在 L2+ 才读降压协议。

再往上,如果有宿主 Hook 支持,可以做两件事:

  • SessionStart 注入:把当前风味和开关状态带进新会话;
  • PreCompact 持久化:把「带时间戳的最小失败观察 + 压力等级」存成文件,压缩后还能恢复。

但要诚实说一句:没有 Hook 也能跑。那就退化成对话内的检查点文本,记录「目标 / 验收 / 已验证 / 已排除 / 失败数与等级 / 锁定味道 / 下一动作」,压缩或交接前留一条。机制比宿主能力重要,宿主能力只是让它更省事。

七、副作用与边界

这部分是写给自己看的,也是我想强调的——这类技能不是免费的。

1. 它有 token 成本。 常驻协议 + 引用文件会占用上下文预算,长任务里这部分开销会挤掉真正的工作记忆。所以必须分层,必须能对简单任务降级:改一行配置不该触发完整面板。

2. 它有表演风险。 最坏的情况是模型学会了所有黑话,但代码一行没改——「把计划当交付」。所以运行契约里第一条就是:先干活,别把计划当交付。味道锁住,动作不能虚。

3. 它不保证正确性。 这套东西管的是工作纪律——会不会验证、会不会穷尽、会不会赖账。它管不了逻辑是否真的对。正确性只能靠测试和人工判断。

4. 压力不能自己创造验收项。 这条边界很容易被突破:一旦允许「为了显得严格」追加随机测试、重复验证、二次确认,就会从「严谨」滑向「表演严谨」。规则是:满足全部约定验收就交付,只有新的失败信号、实际改动或尚未覆盖的要求才追加检查。

5. 狠话只能对 AI 的任务表现,不能对用户。 这是产品边界,不是修辞问题。

结论

如果要用一句话概括这套设计:

不要请 AI「努力一点」,要定义「什么条件下必须做什么,以及拿什么证明做了」。

具体的三件套是:

  1. 状态机(失败计数 → 等级 → 强制动作),配上精确到能防误判的计数口径;
  2. 格式约束(诊断先行、验收绑证据),让「分析」和「行动」无法分离;
  3. 方法论路由 + 抗合理化清单,在跑偏时有明确的换轨路径。

它解决的不是「AI 会不会写代码」,而是「AI 写完代码,你敢不敢直接上线」。

这个差距,比模型参数带来的差距大得多。