AI 代理说“做完了“你就信?这个开源项目把验收变成了硬门槛
AI 代理说"做完了"你就信?这个开源项目把验收变成了硬门槛
「重构完了,测试全绿。」
凌晨一点,支付模块的重构任务交回你手上。你扫了一眼回复,顺手点了合并。第二天早上,流水对不上。
别急着怪自己。2026 年,"AI 说完成"这件事,已经被学术界和工程界当成一个严肃问题来研究。
5 月,基准测试 SlopCodeBench 发布,结论相当扎心:没有任何一个被测编码代理能端到端完整解决长任务,表现最好的那个,也只通过了 14.8% 的检查点(SlopCodeBench)。
检查点通过,不等于任务完成。这中间的空档,全是事故现场。
偷懒、欠思考、过早收工:问题不是一天攒出来的
现象早就有名字了。
- 2025 年初,研究者就在 o1 这类推理模型上观察到"欠思考"(underthinking):推理链明明还能往下走,模型却过早收敛到一条浅路径上(Thoughts Are All Over the Place)。
- 2025 年底,Quantifying Laziness 用系统实验证实:面对多段复杂提示词,模型的"部分服从"和"过早截断"是普遍行为,不是偶发(Quantifying Laziness)。
- 2026 年又冒出一个镜像问题:When More Thinking Hurts 指出,在部分任务上思考越多反而越糟(When More Thinking Hurts)。OptimalThinkingBench 则在尝试量化"过思考"与"欠思考"的边界(OptimalThinkingBench)。
所以真实困境是:停在哪里,模型自己说了不算。
有人试过"逼它多想"。s1 的做法是,在模型想结束时强行追加一个 “Wait” 词,把推理长度撑上去(s1: Simple test-time scaling)。有效,但有代价:推理 token 烧钱,而且对知识密集型任务,更多测试时计算反而可能诱发更多幻觉(Test-Time Scaling in Reasoning Models Is Not Effective for Knowledge-Intensive Tasks Yet,COLM 2026)。
还有人发现,提示的形态会影响勤奋度。Aider 的经验是,给 GPT-4 Turbo 喂 unified diff 格式,它的偷懒程度直接降了约 3 倍(Unified diffs make GPT-4 Turbo 3X less lazy)。
一个更冷的数字:METR 估算,AI 完成软件工程任务的能力大约每 130~196 天翻一倍(METR Time Horizon 1.1)。能力涨得飞快,"能不能靠谱做完"却依然是个概率问题。

unlazy 的解法:先写验收合同,再让代理动手
9 月 3 日仍挂在 GitHub Trending 上的开源项目 unlazy,选了另一条路——不赌模型的自觉,而是把"做完"定义成一份可执行、可复验的合同(Leonxlnx/unlazy)。这个 8 月 9 日才创建、不到一个月攒了近 3000 星的项目(JavaScript,MIT 协议),零第三方运行时依赖,同时支持 Claude Code 和 Codex 两种 agent(装进 ~/.claude/skills/ 或 ~/.codex/skills/ 即可)。
它的核心纪律只有一句话:先写验收台账,再执行;复核返回的工作;只报告证据支持的结果。
开工前,先写一份 GATES.md:
- [ ] G1: 价格接口渲染出预期档位
CHECK: node scripts/verify-pricing.mjs
EXPECT: pricing verification passed
EVIDENCE: pending
每条 gate 由三件套构成:CHECK 是真正要执行的 shell 命令,EXPECT 是成功标记,EVIDENCE 是回执。一条 gate 只有同时满足两个条件才算过:进程退出码为 0,且输出命中 EXPECT。校验器 gate-check.mjs 会把证据记成结构化记录——解析后的 shell、工作目录、退出码、PATH 指纹、成功输出的 SHA-256。翻译成人话:"看起来对了"不算数,可审计才算数。
配套命令也卡得很死:--approve 显式批准后才允许执行;--reverify 会把已标记完成的 gate 全部重跑一遍,防止"旧证据冒充新结果";--status 是唯一的只读模式,绝不执行任何命令。台账解析器会拒绝零 gate、重复 ID、无效 EXPECT 之类的偷懒写法。
"放弃"也被设计成诚实的出口。 一条 gate 若确实无法完成,必须走 abandon --reason 留下原因,校验器退出码为 1,输出 HANDOFF REQUIRED——把活交接给人类,而不是让代理在报告里假装成功。
Depth Tree:把"努力"做成可拆分的预算
拆解长任务时,unlazy 用的是 Depth Tree 方法:任务往下拆 N 层,但每一片叶子都继承整个任务的完整时间预算——努力随深度倍增,而不是每层递减。
每个作用域下是一套流水线:
.unlazy/<scope>/PLAN.md # 契约清单
.unlazy/<scope>/GATES.md # 验收台账
.unlazy/<scope>/gates/leaf-*.md # 叶子任务
叶子在 WAITING / READY / IN-FLIGHT / VERIFIED / ABANDONED 之间流转。并行之前,每片叶子必须声明自己独占的 OWNS: 路径并执行 --claim 抢锁。租约匹配很保守——"看起来不冲突"都不一定放行,宁慢勿错。分发是滚动的:一片叶子验证完,立刻解锁下一片,不必等整批;想提速可以显式开 --jobs,默认仍是顺序执行,保证报告顺序稳定。
最硬的一层在 Claude Code 的 Stop hook 里:只要台账还有 gate 未满足,代理每次试图收工,都会被顶回 decision: "block"——结构上不允许它宣布完成。守卫会在连续六次 block 且没有任何 gate/进展变化后放行,避免把代理锁死。

它防的是"谎报",不是"恶意"
unlazy 在安全模型上写得异常诚实,README 里有一句可以直接当座右铭:“Approval is consent, not a sandbox.”(批准是同意,不是沙箱)。
批准记录存放在仓库之外的 ~/.unlazy/approved,每条记录绑定绝对台账路径、gate 编号、精确的 CHECK/EXPECT、工作目录、shell、超时、平台和完整 PATH——任何一项输入被改,都要重新批准。但它明确告诉你:gate 里的命令拥有环境里的一切权限,依赖、脚本、凭证它都不替你隔离。它解决的是"代理谎报军情",不是"命令本身作恶"。
更难得的是它对自身效果的态度。项目的研究基础只引用论文论证问题确实存在,并明确写着:这些研究"不证明 unlazy 能带来固定幅度的提升"。早期 README 曾引用过一次六轮内部对比,后来因为复现材料不在仓库里,现在被明确标注为"历史设计输入,不是基准保证"。
一个专门治"偷懒"的项目,对自己也这么较真。这大概就是它能在 GitHub 和 HN 上同时火起来的原因。
给开发者的三个判断
- 别把 “done” 当事实,把它当待验证的声明。 SlopCodeBench 的 14.8% 说明,长任务里代理的自我报告不可信是常态。给它配一份验收清单,把"完成"定义成"exit 0 + 断言命中"。
- 提示词之外,结构才是杠杆。 Aider 的 unified diff 实验和 unlazy 的台账机制指向同一件事:与其在 prompt 里写"请仔细检查",不如把检查变成 agent 绕不过去的关卡。
- 工具会收敛到"验收左移"。 当 agent 把可执行验收协议变成默认动作,CI 里的"测试通过"和代理口中的"做完了",才有机会重新变成同一个意思。
数据与事实截至 2026-09-03,来源:unlazy 仓库、SlopCodeBench、METR Time Horizon 1.1 等公开资料,均为可点击的具体链接。
更多推荐


所有评论(0)