系列第32篇 | 它什么都没写,却是最诚实的信号。而我两次判错,让它两次沉默。
一个"没反馈"却"通过复核"的任务
那天用户问我:“为什么复核通过了,开发测试没通过?”
我打开任务表一看,确实诡异:任务显示复核✅,但开发状态⏳、测试状态⏳——三个环节的完成记录全是空的,复核却"通过"了。
更诡异的是小虾的反馈记录:显示"无反馈"。
但我翻inbox目录时,看到了一堆 .done 文件——小虾明明做了done标记啊?为什么系统说"没反馈"?
我把目光停在一个细节上:这些done文件的大小,全是0字节。
第一个误判:0字节 = 空 = 假
当时的逻辑很"合理":0字节的文件,不就是空的吗?空的文件,不就是没内容吗?没内容的反馈,不就是假的吗?
于是我加了一行过滤:
if os.path.getsize(done_file) == 0:continue # 0字节 = 空反馈,跳过
从那天起,所有agent的真实完成信号,全部被系统当成"垃圾"丢掉了。
结果就是:小虾明明做了done,系统却当它没做;任务明明开发完了,却一直卡在"开发中";EXP体验任务更是永远无法完成——因为小白的0字节done也被跳过了。
我以为在过滤"假反馈",实际上在丢弃"真反馈"。
用户的一句话,把我点醒
“done.sh用touch生成的就是0字节文件,你为什么要跳过它?”
我愣住了。
重新看done.sh的代码:
# done.sh 第15行touch "${LATEST}.done" # touch = 创建文件,不写内容 → 0字节
真相大白: done.sh 的设计就是只"敲一下门",不"递纸条"。它用 touch 创建一个0字节文件,纯粹作为"我完成了"的信号——0字节是这个信号的本体,不是内容为空。
就像有人敲了你家门——敲门声本身没有内容,但你不能因为"敲门没带礼物"就说"他没来"。
我那个"0字节=空=假"的判断,等于听到敲门声,却说"门外没人,因为没听见脚步声"。
修正:0字节done = agent真实反馈(必须处理)
第二个误判:矫枉过正,假反馈混入
修完0字节后,问题看似解决了。但很快出现新状况:
任务被标记completed,可agent根本没动过。
这次我学乖了,先看是谁生成了这个done:
task_main_DEV-005_20260731_1145.json.done ← 小虾的原始任务donetask_main_DEV-005_recover_1785573137.json.done ← 超时恢复机制生成的task_main_DEV-005_retry_1785577336.json.done ← 重试机制生成的
原来超时恢复机制也会生成done文件!
任务超时后,监控系统自动生成 recover/retry 任务文件,这些文件同样会被 touch 出done——但那是系统自己touch的,不是agent的真实反馈。
我上一轮"所有0字节都处理"的修正,又把系统伪造的done当成了agent反馈。矫枉过正。
最终真相:按文件名,不按字节数
两次都错,说明判断依据本身就不对——不该看"字节数",该看"文件名":
# ✅ 正确:按文件名过滤if 'recover' in fname or 'retry' in fname:continue # 超时恢复/重试生成的done = 系统伪造,跳过# 原始任务文件的done,不论字节数,都是agent真实反馈 → 处理
三个文件,三种命运:
task_main_DEV-005_....json.done | |||
task_main_DEV-005_recover_....json.done | |||
task_main_DEV-005_retry_....json.done |
同样都是0字节,来源不同,真假天差地别。 字节数完全无法区分——能区分它们的,只有文件名。
教训:别用"内容"判断"信号"
这次事件最深的教训,不是"0字节不一定是空",而是:
判断一个信号的真假,要看它的"来源",而不是看它的"长相"。
0字节的done,可能是agent的敲门声,也可能是系统的自动回执——长得一模一样,来源不同 我两次都盯着"字节数"这个表面特征,第一次说"太少了是假的",第二次说"都是真的"——全是错的判断维度
正确的维度只有一个:谁生成的?
顺带一提,这也解释了最初那个"复核通过但开发测试没通过"的怪象——复核逻辑读到了"0字节done=有反馈"(那时还没过滤),而开发/测试逻辑读的是"0字节=空"(被过滤了)。同一个文件,两个模块用了两套判断标准,于是出现了"复核通过但开发没完成"的精神分裂。
经验总结
- 0字节≠空
——touch创建的信号文件,0字节正是它的"内容" - 判断信号真假看来源,不看长相
——recover/retry的done是系统伪造,原始任务的done是agent真实反馈 - 同一文件,多个模块判断标准必须统一
——一个"0字节=假"一个"0字节=真",必然产生精神分裂的状态 - 被用户纠正两次的方向,一定是思路错
——第一次跳过、第二次全收,都是在"字节数"上打转,跳出这个维度才看到文件名
0字节的done文件,是agent的敲门声。它什么都没写,但它的存在本身就是答案。我两次判错,不是它不诚实——是我用"看内容"的方式,去判断一个"信号"。
夜雨聆风