
你说「加上 CSV 导出」,Agent 说「做完了」。你说「把首页调快点」,Agent 说「快多了」。
中间发生了什么?不知道。改了哪些文件、为什么这么改、验证过没有——你手里只有这两句话。Vibe Coding 把写代码变成了黑盒:需求进去,结论出来,过程不可见。
autodev 就是为打开这个黑盒写的 Agent Skill。仓库简介的说法是 Stop letting your agent grade its own homework——换成一句话:把黑盒打开,让验收标准、测量过程和结果都变成能看见的东西。
先把意图对齐成人确认过的、能跑的 test,再在约定的边界里迭代,最后交付一张能复验的表或图。
三个阶段:Clarify(对齐)→ Loop(迭代)→ Handoff(交付)。功能开发交付一张 baseline 对比表,性能优化交付一张真实的过程图。
黑盒里缺的不是诚实,是考卷
值得先想清楚的一件事:Agent 的自我报告为什么不可信,往往不是因为它在编。
现在的模型太强也太快——一口气改十几个文件、跑完构建、顺手修掉报错,再给你一段流畅的总结。它多半没撒谎,但「做完了」「快多了」这种话里没有验收标准:feature 用起来什么样、优化到底快了多少、边界情况有没有被顺手改掉,你读完全都不知道。而且模型越强,这段话越像模像样,你越挑不出「其实没做到」的那部分——自我报告的参考价值,反而随能力上升而下降。
更靠前的一层麻烦是对齐本身。自然语言上的同意,不保证双方理解一致。它可能实现了错误的行为、改掉了你想保留的流程、或者认真优化了一个根本不代表目标的数字——这种偏差要到交付那一刻才暴露,之前写的一切都是返工。
两句话合起来就是 autodev 要解决的问题:验收标准不能住在 Agent 嘴里。 它得被拿出来,变成人确认过的、能执行的、改之前先测过一次的东西。这就是 README 里那三个词的意思:
| 理念 | 含义 |
|---|---|
| Verifiable · 易验证 | 确认后的 test、准确的命令和实际执行记录,让人能复验结果 |
| Measurable · 可度量 | baseline 和最终结果用同一把尺子、可比的条件 |
| Visible · 够直观 | 功能开发交一张对比表,性能优化交一张过程图 |
它们不是三个阶段的名字,而是贯穿全程的要求:用偏离意图的 test 拿到全绿,或者用虚构数据画出漂亮的图,都不算成功。
Clarify:对齐发生在动手之前
整个流程是 User input → Clarify → Loop → Handoff,用户输入只是触发器。Clarify 是最重的一步——它不只是问问题,查代码、维护 test、试运行、测 baseline 全在里面。
功能开发的 Clarify 先确认影响面:能不能加模块、能不能删模块、既有流程能不能动——一个 feature 需求不是重新设计项目的通行证。然后进入 human-in-the-loop 的 test 共建:查现有 test、删掉或更新过时的、补上缺失的、跑起来给人看,改到人确认「这套能跑的 test 就是验收标准」为止。
性能优化的 Clarify 是另一套顺序:先共建唯一的那把尺子——一个数值 benchmark,或者多个 benchmark 的固定加权和,权重和归一化方式在测量之前定死;量出 baseline;之后才确认目标、可改文件和墙钟时间预算。
几个容易低估的设计:
- 「能跑」不等于「已通过」。 还没实现的 feature,test 红着是 baseline 的正确形态;为了拿一次绿的试运行就提前实现,反而是违规。反过来,如果确认后的 test 一上来就全绿,得先验证功能是不是真的已经存在——就算一行代码不改,交付的对比表照样要交。
- baseline 不许被覆盖。 之后所有提升都跟最初那份原始记录比;删掉过时 test 是准备工作,不算开发收益;不同版本 test 的结果不能拼成一次「提升」。
- 已给的决定直接复用。 你在需求里写明的边界不重复询问,也没有「必须问满几轮」的指标。
Loop:在共识里迭代,不许换尺子
约定和 baseline 就绪之后才进 Loop。Loop 的职责是实现共识,而不是边写代码边重新解释什么叫成功。
功能开发很简单:在确认的影响面内实现,跑到全部约定 test 通过——没有时间预算,一个 feature 不会因为做到一半被放弃而变得更好,也不会被随手加一个 attempt 上限。
性能优化是个 do-while:先跑一轮「改 → 测 → 保留或回滚」,之后才检查达标或超时。就算 baseline 已经满足目标,也不能跳过第一次尝试;退出条件看的是被保留的最佳已验证分数,一次被拒或无效的 attempt 不能用来宣告达标。两条硬约束压着它:
- 回滚只回滚这一次 attempt。 恢复最佳状态时只撤销本次改动,绝不允许顺手重置整个仓库、改写历史、或者动你无关的工作。
- 预算凌驾一切。 每次尝试都受剩余墙钟时间约束,超时直接打断进行中的 attempt;进 Loop 时预算已经耗尽,就报告耗尽,而不是擅自开工。
Loop 里也不能换尺子:意图、test 含义、可改范围有任何变化,回 Clarify 重新对齐、重测 baseline,而不是在迭代中途悄悄调整。
Handoff:交付的是证据,不是总结
交付物的形式本身就是约定的一部分,两个场景各有一种必需产物:
| 功能开发 | 性能优化 | |
|---|---|---|
| 必需产物 | 一张 baseline/最终结果对比表 | 一张 baseline → 尝试 → 最终结果的过程图 |
| 展示内容 | 同一套确认后的 test,含汇总和未解决失败 | 唯一分数随尝试的变化、目标、保留结果和停止状态 |
| 复验依据 | test 与源码版本、原始输出、重跑命令 | benchmark 与源码版本、真实历史、测量条件、重跑命令 |
文字总结替代不了对比表,一个最终数字也替代不了过程图。那张图还有一堆硬性要求:标出原始 baseline、每次有效测量、被拒的尝试、最终交付的是哪个候选、目标线和停止原因;可以加 best-so-far 线,但必须标注成「推导出的保留状态」,免得把最后一次尝试误当成交付的那个;崩溃和超时的 attempt 标 invalid,不许编一个分数填上去。
不完整也要交:没跑成一次尝试、或者没有验证到任何提升,图上就如实展示 baseline 并注明,交付被阻塞同样如实标注——不虚构一段优化轨迹,也不把没跑完的东西说成完成了。
它从 autoresearch 那学了什么
这套机制不是空想出来的,灵感来自 karpathy 的 autoresearch。
那个项目做得非常干净:给 Agent 一个真实的 LLM 训练环境,让它整夜自己试。只准改 train.py,prepare.py 不许碰;每次训练固定 5 分钟;拿 val_bpb(validation bits per byte)当 metric,低了留下、高了丢掉,重复。一晚上大概跑 100 次实验,早上醒来收获一份实验日志和一个(大概)更好的模型。
这套 loop 里三件事是对的,而且和「训练」无关:
- benchmark 先冻结,再动手。 不许改的文件提前划出来,改之前先测一次。
- budget 固定。 不是「跑到好为止」,而是「5 分钟里能做到的最好是什么」——每次 attempt 才互相可比。
- 留下还是丢掉,脚本说了算。 Agent 自己的结论不参与决策。
autoresearch 缺的是另一半:它只有 metric,没有 correctness gate,更没有人来确认那把尺子量的是不是你想要的东西。 在训练场景里这不算问题——val_bpb 变低就是真的变低。但换到日常代码就漏了两个洞:一是 Agent 可以把跑分刷上去、同时弄坏你的 feature,缓存输入、缩评测集、放松容差,在 diff 里全都像进步;二是更隐蔽的,它可能优化了一个你根本不关心的数字,或实现了一个你以为说清楚、其实没说清楚的功能。
所以 autodev = autoresearch 的 keep-best loop + 人确认过的 test 当前置条件。加上这层之后,它就不绑 GPU、不绑训练了——任何有 test、能说出一个数字的项目都能用。而在现在的版本里,这一层已经不只是 loop 外的一道门禁,它长成了自己的阶段:Clarify。
30 秒上手
安装只有一行:
npx skills add Momoyeyu/autodev -g然后像平常一样提需求。加 feature 会先对齐影响面、共建 test:
为筛选后的交易列表增加 CSV 导出。Clarify 影响 新增 export 模块;既有列表渲染流程不变 —— 已确认 test 共建 4 条:空结果 / 带筛选 / 中文转义 / 表头顺序 —— 可执行,已确认 baseline 4 条全 FAIL(exportCsv 未定义),环境本身健康Loop → 在确认的影响内实现,直到 4 条全绿Handoff → 一张对比表:同一套 test 的 baseline vs 最终结果
做优化先确认唯一的尺子、量出 baseline,再定边界:
把 API 的 p95 延迟降到 200 ms 以下。实现修改仅限 src/api/,优化时间预算 20 分钟。待确认的约定: 分数 p95_ms ↓ —— 唯一的 test:bench/api.js,5 次取中位数 baseline 264.8 ms(原始输出已存档,之后不许覆盖) 目标 ≤ 200 ms,达标可提前退出 可改 src/api/**(benchmark、输入、计分公式都在边界外) 预算 20 分钟墙钟时间,含最终复测你在需求里写明的 src/api/ 和 20 分钟会被直接复用,不会再来问一遍。确认之后它开始跑,每轮先改、再测、再保留或回滚,跑完才判断继不继续。预算用完,你拿到的是过程图背后的完整记录:每次 attempt 的分数、保留还是被拒、最终交付的是哪个候选。

怎么保证它不作弊
机制散在三个阶段里,挑最能说明问题的几条:
- 尺子只有一把,且在 baseline 之前定死。 一个 benchmark,或者固定加权和——权重先讲清楚再测量。分项读数只是诊断,不是多个优化目标;看见谁赢之后再挑权重,就是作弊。
- 测量依据上锁。 benchmark、输入数据、计分公式都在可改文件之外,并记录 hash 或等价标识。缩小负载、改条件、预热没申报的缓存,都不算实现上的提升;篡改测量的尝试无论报出多好的分数都作废。
- 过程必须留痕。 每次 attempt 记录时间、代码版本、实际分数、保留/被拒/失败。崩溃和超时没有分数,标 invalid 而不是记 0;时间耗尽不等于达标,就如实写。
兜底的一条:没被验证的提升就当不存在。 baseline 已达标也要先认真试一轮再下结论;真没有验证到提升,就如实展示,不编轨迹。
顺带说一句:真正有信息量的是被拒绝的那些 attempt。一次从不回滚、图上全是直线上行的运行,要么任务太平凡,要么它在作弊——这些规则就是用来分辨这两种情况的。
适用边界
同一套结构换个组合就是另一个场景:
| 场景 | test | 可改范围 | 交付 |
|---|---|---|---|
| 开发 feature | 共建 test:baseline 红 → 最终绿 | 确认的架构/流程影响 | 对比表 |
| 修 bug | 复现 test 红 → 绿 | 同上 | 对比表 |
| 性能 | 唯一分数:p95 ↓ | 指定的实现文件 | 过程图 |
| 打包体积 | 唯一分数:字节数 ↓ | 同上 | 过程图 |
| 模型质量 | 唯一分数:validation loss ↓ | 训练实现;负载、时长、验证集在边界外 | 过程图 |
范围上刻意收得很紧:不带任何脚本、不绑任何框架。约定每次现场生成,判定复用你项目里已有的命令——npm test、pytest、你自己的 benchmark 脚本。框架专用模板是有意排除的:一旦这个 skill 认识了 Jest,它就不再适用于 Rust 了。
skill 本体也只有一份 SKILL.md 加五份按需加载的 reference——渐进式披露,只读当前阶段的那一份,不预加载整个目录。对 Agent 来说上下文也是预算,写 skill 和写 prompt 一样,每一行都在花它的注意力。
求 star
仓库:github.com/Momoyeyu/autodev · MIT 协议
任何能加载 SKILL.md 的 Agent 都能用——Claude Code、Cursor、Codex CLI、OpenCode,以及你自己的 Agent。
如果你也想:
- 把 Vibe Coding 的黑盒打开,不再靠 Agent 的自我报告判断「到底改好没改好」
- 让「对齐」发生在写代码之前,而不是返工之后
- 看看一个 Agent Skill 能把约定写多细(三个阶段五份 reference,各自只在需要时加载)
那来给个 star、提个 issue、丢个 PR——尤其欢迎真实的 loop 运行记录,包括 Agent 试图糊弄自己 benchmark 的那种。