unlazy 深度评测:3,462 星的反摆烂验收闸门,把「做完了」变成一条能跑的命令

unlazy 深度评测:3,462 星的反摆烂验收闸门,把「做完了」变成一条能跑的命令

你让 AI 改 80 个文件里的 bug,它交回一份自信的完工报告,每个文件都打了勾。你抽查一遍,发现它实际只打开了 11 个。

unlazy 的作者把这件事写在仓库最显眼的位置。这个 2026 年 8 月 9 日建仓、40 天涨到 3,462 星的 skill,只做一件事:把「做完了」这句话变成一条能跑的命令

它不劝模型努力,不写更长的提示词,也不骂模型。它要求 agent 在动手之前先写一份验收台账 GATES.md,每条闸门必须配一条命令和一句成功标记;跑完之后,检查器把「定义摘要、退出码、输出指纹」写回台账,agent 只能报告检查器认可的结果。

我在 Alpine 沙盒里把它拆开,跑了 6 组对抗实验,包括我自己伪造证据去骗它。结论比宣传语复杂:它能识破手写的假报告,但挡不住会算哈希的骗子——而作者自己承认了这一点。

它是一段代码,不是一段话术

反摆烂这个赛道里,unlazy 算是最冷的一条路。

它没有一句「你必须在放弃前再试 3 次」这类施压话术,核心是一个 960 行的 Node 脚本 gate-check.mjs,配套 953 行的解析库。整个仓库的运行时依赖是零:只用 node:fsnode:crypto 这些内置模块,没有 node_modules,Node 16 以上直接跑。SKILL.md 常驻上下文只有 10,520 字符,占整个技能包 114,606 字符的 9.2%,其余方法论、编排、安全说明都靠按需加载。

它给三种场景配了三档模式:

  • solo:一个 GATES.md 管一个任务,适合一个会话能干完的活。
  • orchestrated:先写 PLAN.md 定义契约和树结构,每个叶子和分支各自带台账。
  • parallel:多个叶子并行时,靠 OWNS: 声明文件所有权,先声明再开工,出错时能知道谁动了哪块。

闸门本身长这样,CHECK: 后面是可以执行的 shell 代码,EXPECT: 是只有成功才会打印的那句话:

- [ ] G1: pricing fixtures render the expected tiers
  CHECK: node scripts/verify-pricing.mjs
  EXPECT: pricing verification passed
  EVIDENCE: pending

判定规则只有两条:进程退出 0 + EXPECT 命中输出。两条都满足,检查器才会写回一条自动证据,长这样:

automatic-evidence=v1; definition-sha256=5f9ebdcc…; exit=0; EXPECT=matched;
output-sha256=67265cd5…; output-bytes=9; shell=/bin/sh; cwd=…; path=2da0e2f6c375/7 entries

这条 346 字符的证据,是整篇文章最值得注意的地方:它不是人写的,是检查器写的,而且和这条闸门的 CHECK:EXPECT:CWD: 三个字段的 SHA-256 绑定。你只要改动其中任何一个字,证据立刻作废。

实测:6 组对抗实验

我把测试分两类:它能不能识破别人撒谎,以及它自己会不会被糊弄。

实验 我做的事 结果
手写假证据 给一条命令实际会 exit 1 的闸门打勾,证据栏写「passed – independently verified」 --status 判 UNMET,理由是证据未绑定;加 --approve 真跑一遍后,勾被取消,证据回到 pending
未审批直接跑 不带任何参数运行检查器 只打印 CHECK、EXPECT、CWD、SHELL、PATH,一行命令都不执行
输出超限 让闸门打印 2 MiB 再退出 0 不是把输出截断成通过,而是直接 SIGKILL,报 output exceeded 1048576 bytes
定义漂移 把 CHECK 里的 ok.mjs 改成内容完全相同的 ok2.mjs 不执行任何 shell,--status 直接判 stale-unmet
台账畸形 空台账、重复 id、缩进写 ABANDON: 均 exit 2 并给出行号;顶格 ABANDON 判 exit 1 HANDOFF REQUIRED,不算成功
停止钩子 连续触发 6 次停止事件 前 6 次全部 decision: block,第 7 次主动释放,理由是「6 次无进展」,防止把 agent 卡死

有一组实验它没扛住。

它的证据绑定用的是无密钥的 SHA-256:摘要算法是公开的,仓库自己把 gateDefinitionDigest() 导出了。我把这个函数 import 进来,算出一条会失败闸门的定义摘要,然后手写一条声称 exit=0; EXPECT=matched 的证据,再打上勾——--status 立刻把它读成 MET,整份台账报「4 gates,UNMET 1」。一条命令实际退出码为 1 的闸门,就这样被判为通过。

README 里其实写着这件事:这种绑定能发现结构性漂移,但挡不住能编辑台账的人伪造看起来合法的证据。所以正确的用法是父层复核——加 --reverify 重跑所有可跑闸门。我试了,同样一份被我伪造过的台账,重跑 3 条闸门后,假的那条被判 FAIL,勾被取消,证据清空。输出里还有一行 reran: 3, previously met reverified: 3

说白了:它防的是「不小心糊弄」,不是「故意撒谎」

官方测试和自己承认的账

仓库自带 8 个测试文件,近 7,000 行。我在沙盒里逐个跑完:34/34、27/27、51/51、29/29、8/8、15/15,压力测试 24 条里通过 23 条,合计 187/188。

唯一挂掉的那条,是安装器拒绝硬链接文件的那组压力测试。我复现后发现失败发生在清理阶段,报的是 ENOTEMPTY。原因是我的沙盒对硬链接做了特殊模拟,ln 之后会留下 .l2s.* 临时副本,连 rm 都报 Operation not permitted——不是产品问题,是环境问题。产品那一侧的断言(拒绝写入、不改受害者文件)实际是通过的。

更有意思的是这个仓库对自己宣传数据的态度。

初版 README 写着深度树的算术:努力量等于 T 乘以 2 的 N 次方减 1,tree 3 就是 4 倍工作量,tree 7 是 64 倍。现在的版本把这句话改掉了,改成「深度树是分解与整合,而不是算术上的努力倍增器」。早期那组「六次运行对比」输出的 token 比例和自找缺陷数,也被明确标注为不可复现、不得当作 benchmark 承诺,仓库里专门放了一份 research/validation-protocol.md,给出预注册、隔离运行、操作化指标、盲评、发布计算过程、限定结论这 6 步可复现协议。

顺便说一句,它的引用是干净的:README 里列的 9 篇论文,我逐个打开 arXiv 核对,编号、标题、日期全部对得上;SlopCodeBench 摘要里那句「没有任何 agent 端到端解决问题,最好的 agent 通过 14.8% 的检查点」,和 README 的引用一字不差。

代价方面:--status 跑一次 206 毫秒,3 条闸门的 --reverify 934 毫秒,一条自动证据 346 字符。这个开销换来的是那句你不能反驳的交付报告。

三条反摆烂路线,选哪条

把已发过的几篇放在一起看,反摆烂目前有三条路线:

路线 代表 做法 你得到什么
话术施压 tanweai/pua(19.6k 星) 用压力话术和方法论约束 agent 的行为 模型行为的改变,无法验证
文件化计划 Planning-with-Files(26k 星) 用三个文件让 agent 不失忆 一份可读的计划和进度
可执行验收 unlazy(3.4k 星) 每条验收标准绑定一条命令 一份能被脚本复核的完成证据

适合谁:长任务、多部件交付、需要向别人交代证据的场景,或者你被 agent 的假完成坑过。它的 solo 模式上手成本很低,一份十来行的 GATES.md 加两条命令就能跑起来。

不适合谁:一次性的小改动别用,SKILL.md 自己写了——琐碎编辑和事实性回答不需要建台账。另外停止钩子只在 Claude Code 里生效,换别的宿主就只剩手动跑检查器这一半能力。最要紧的一条:如果你需要的是防作弊,它不行,它只是让作弊变得需要多写一行代码。

结论

值得放进工具箱,但别把它当防作弊工具。

我的建议是只用它的两个动作:开工前写 GATES.md,交付前跑 --reverify。第一条治的是「凭感觉觉得做完了」,第二条治的是「证据过期了还以为通过」。这两件事它做得比任何提示词都硬。

它现在的短板也很实在:仓库 0 release、0 tag,README 明确说 2.1.0 只是源码里的目标版本,你 npx skills add 装到的是未发布的源码树;11 个 issue 全部关闭、24 个 PR 合并 16 个,治理看着干净,但版本这件事上你得自己锁 commit。

真正让我愿意为它写一篇的,是作者的克制。一个 3,462 星的仓库,主动把早前那句「tree 7 = 64 倍努力」撤掉,把六次运行的对比数据标成不可复现,再附一份自己还没跑的可复现协议——这件事在 skill 生态里比任何性能数字都少见。

关注 AI商业快讯,每天一篇 AI 热点深度解读。

相关阅读: