大家好,我是Zack。
先说一个我这周踩了三次的坑。
让 agent 改一个脚本,它改完说”好了”。我一跑,报错。把报错贴回去,它又改,还是报错。来回四轮,最后发现——那个报错在我让它改之前就存在。
四轮里三轮是白跑的。
后来我改了一处:让它动手之前,先做三件只读的事。返工次数直接砍了一半。
原来的做法:上来就改
我以前的提示词长这样:
scripts/post_one.js 跑不通了,帮我修一下
这句话有三个坑。
第一,它不知道改之前是什么状态。改完还是红的,它以为是自己改坏的,就接着改本来没问题的地方。
第二,我贴给它的报错夹着一堆无关的东西——本地没提交的其他改动、上一次跑留下的缓存。
第三,它手里那份文件可能是旧版本。同一轮里我自己改过一次,它还按上一版的行号下手。
三个坑最后都变成同一件事:返工。
现在的做法:动手前先做三件只读的事
我现在的任务开头固定加一段:
动手之前先做下面三件事,把结果贴给我,这个阶段不要改任何文件:
1. 跑一遍基线,记录当前结果
2. 报错先缩到最小复现
3. 重新读一遍你要改的文件当前版本
三件事做完,等我确认再动手。
关键是最后那句”不要改任何文件”。不写这句,它大概率顺手就改了。
第一件:先跑一遍基线
基线就是”改之前,现在是什么状态”。绿的还是红的,红在第几行。
改完再跑一次,跟基线一比,就知道是它改好的还是本来就好的。
我这个运营仓库 scripts/ 下有 59 个 js 文件,全量语法检查跑一遍 1.5 秒,结果 0 报错:
# 基线:59 个文件,1.5 秒出结果
for f in scripts/*.js; do node --check "$f"; done
1.5 秒换后面不用猜,这笔账怎么算都划算。
不同项目跑基线的命令不一样,常用的就这几条,直接抄:
# Node 项目:跑测试;只看改动的加 --onlyChanged
npm test -- --silent
# Python 项目:-q 精简输出,红了直接看失败用例名
pytest -q
# Go 项目
go test ./... 2>&1 | tail -20
# 实在没有测试的,先做语法检查当基线
for f in scripts/*.js; do node --check "$f"; done
跑完让它把结果原样贴出来,别让它总结成”测试通过”。贴出来的原文里有几条用例、挂在哪一行,这些细节总结完就没了。
没有现成测试也没关系,让它先补一个最小的:跑得起来、能过能挂就行,别追求覆盖率。
第二件:报错先缩到最小复现
日志别整段贴。300 行的堆栈,有用的往往只有中间十几行。
缩复现我用一个命令:
# 把没提交的改动先收起来,只留能触发报错的那部分
git stash push -m "tmp: 排除无关改动"
# 再跑一次,看还复现不
git stash pop # 确认完放回来
还复现,说明跟那些改动无关,范围立刻小一半。
再不行就新建个空目录,只放能触发报错的那个最小输入。
它拿到的复现范围越小,定位越快——这个不用解释,你想想自己 debug 也一样。
第三件:让它重读当前文件
它改错行,多半不是笨,是它手里那份文件过时了。
同一轮里你自己动过一次,前面插了 12 行,它还按旧行号去改,位置就全偏了。
所以我在任务里写死一句:
动手前先重新读一遍目标文件的当前内容,不要凭上一轮的记忆改行号。
补丁打不上、改的位置对不上,先怀疑这个,别怀疑它能力。
前后对比
同一类任务,我这个月跑了大概二十次,体感差别是这样:
| 对比项 | 原来的做法 | 加三件只读的事 |
|---|---|---|
| 动手前步骤 | 0 步 | 3 步(都是只读) |
| 动手前多花时间 | 0 | 约 1-2 分钟 |
| 平均返工轮次 | 3-4 轮 | 1-2 轮 |
| 归因错误(把旧问题当新问题) | 三次里有一次 | 基本没有 |
| 改完不敢确定是不是它改好的 | 经常 | 有基线,能确定 |
多花的 1-2 分钟,换的是少跑两轮。一轮来回按 5 分钟算,净赚。
数字是我自己这二十来次的体感,不是严格统计——样本就我一个人,你那边项目不一样,可能没这么明显。
两条能迁移到自己活儿里的原则
第一条:只读的事让它多做,写的事让它少做。
跑测试、读文件、查日志,这些不会搞坏东西,让它放开跑。真要改文件,一步一 commit,坏了只退一步。
具体就两条命令,提交前必看:
# 看一眼它到底动了几个文件、各改了多少行
git diff --stat
# 按一个小步提交,别攒到最后
git add -p src/xxx.js && git commit -m "fix: 只改报错那一段"
git diff --stat 这行很值:它说改了一个文件,stat 显示动了四个,你就知道该问一句了。
我吃过亏——提交历史里躺着一次 120 files changed, 11669 insertions 的整包提交,出问题只能整包退,退完连好的改动一起没了。
第二:它说”好了”不算,基线说了才算。
验收看的是基线到现在的差值,不是它自己的总结。
顺带说一句,这个原则对人也一样。别人交给你一个”改好了”的东西,先问一句”改之前是什么样”。
还有两个我没解决的问题
这三招在单文件、能跑起来的任务上好使,但有两种情况还是没辙:
一是跑一次要十几分钟以上的任务,基线成本高,我目前是隔几天才跑一次完整基线,中间靠局部冒烟顶着。
二是涉及多个服务联调的,基线本身就不稳定,绿和红会自己跳,这种我还没找到省事的办法。
有更好做法的,欢迎在留言里指个路。
以上就是我这周在用的三件只读的事。
你现在让 agent 改东西之前,会先让它跑一遍基线吗?还是跟我以前一样上来就改?
欢迎留言聊聊你的做法,踩过的坑也可以一起说说。
公众号:Zack说AI