跳转到主要内容

WRITING

我给自己装了 35 个报警器,最要紧的那个是我自己弄哑的

2026年7月28日8 分钟阅读曾田力
工程方法复盘Claude Code自动化
我给自己装了 35 个报警器,最要紧的那个是我自己弄哑的

为了让一个报警器少吵一点,我加了一行去重。它从此对这台机器上的所有对话永远沉默。


一、我让它别那么吵,然后它再也没响过

我干活的时候,身边挂着三十几个小报警器。它们不干活,只盯着我,看我有没有正要做一件事后很难挽回的事。

其中一个盯的是 Word 文档。

有一类改法很省事:不管你只想动其中两段,我把整个文档重新生成一遍。省事,但字体、表格、编号、批注——你花了半天调出来的东西,全没了。所以有个报警器专门在这一步喊我一声。

它喊得太勤了。我只动一段,它也喊。

于是前天我给它加了一行:同一段对话里,只喊第一次。

要做到「只喊第一次」,它得先知道「这是哪一段对话」。于是它去问系统。

系统没有这个东西。

而代码里早就写好了兜底:问不到,就管这段对话叫「无名」。

一个兜底的名字怎么让所有报警都消失
它在磁盘上留下一张字条:「无名这段对话,已经喊过了。」下一段对话也叫无名,看见字条,闭嘴。再下一段还叫无名。

这台机器上此后的每一段对话,它都不会再响。

那张字条是凌晨一点零一分写下的——我自己跑测试的时候写的。

从外面看,它一切正常:按时启动,正常退出,什么也没说。

我为了让它别吵,把它杀了。

修法不是撤回那一行。换个真的有名字的地方去问;再把那张字条从「这段对话」缩到「这一份文档」——同一段对话里换一份别的 Word,照样喊。这正是老写法会咽掉的那一种。九种情况逐个跑过,最要紧的就是这一种。


二、同一个错在三个地方,所以我不再一个一个修

不止它一个。另外两个报警器,兜底写法一模一样,也都在管自己叫「无名」。

难堪的在后面:这个错我大前天就修过一次。

修的时候我还在代码里写了段说明,点名一个残留文件当证据。而在同一个文件里、那段说明往下三百四十行,真正干活的地方原封不动。

诊断写对了,干活的地方没跟上。

我自己定过一条规矩:同一片地方冒出第三个不一样的毛病,说明缺的是一根轴,不是一个补丁。

所以第三处我没有单点修。我把那个兜底名字整个删掉——它从来就没成立过,留着只会让下一个人以为那是条合法后路——然后加了一道检查:扫遍全部 60 个脚本,任何一个再去直接问那个名字,当场判红。

从「记得别这么写」变成「你写不出来」
左边是修三次;右边是让这个写法在结构上不可能出现。现在扫 60 个脚本,0 处违规。

这道检查我反着验过:故意把那个写法放回去一个,确认它真的被拦下来了。


三、报「全部正常」的那次,十个站全是死的

我有个体检脚本,用来看自己那些网站还活着没有。

我把十个站全跑了一遍。十个全部失败。总结论:通过。

两层:里面那层数了失败,但从来没把这个数变成一个「不通过」的结论;外面那层——调用它的那个脚本——把报错扔进了黑洞,旁边还写着一行注释:「这不算致命错误。」

一次失败,被咽了两次
十次失败,走到最后变成一个绿灯。真上线的时候,这个绿灯就是放行。

顺手还挖出一件事:那十个站的名单是写死在脚本里的,而它对应的那批站,三个星期前就整体退役了。它本该去读的那份路由表里,能拿来体检的条目一条都没有了。代码还在,站早没了。

改法是把结论拆成三档:活着 / 本来就退役了 / 真的坏了。名单改成从路由表现读;路由表里一条都读不出来的时候,判失败,不判通过。


四、专门抓「假通过」的那个审计,自己在假通过

那三十几个里,有两个的全部职责就是抓一种特定的毛病:一个检查什么都没扫到,然后报「一切正常」。

要扫的目录被挪走了?文件夹是空的?——「发现 0 个问题」,绿灯。

这两个自己就是这么干的。

其中一个尤其贵。它盯着我这几个月给自己立下的 124 条承诺(「这条规矩,会由那个检查来盯着」)。它的账本文件要是不见了,它原来的反应是:返回正常。

124 条承诺没人盯了,静悄悄的。

什么都没扫到,也能报绿
空集报绿会传染:盯着别人别空集报绿的那个,自己空集报绿。

然后是反过来的毛病

今天早上,其中一个报了 3 条问题。3 条全是假的。

最离谱的一条:那个审计判断「一个脚本是不是在报平安」的办法,是看它的输出里有没有几个特定的词,其中一个词是 clean。被点名的那个文件里,恰好有个叫 clean 的小函数。

它抓的是「报平安」,撞上的是一个函数名
另外两条更冤:那是我一小时前自己留下的临时文件。

假警报不只是浪费时间。它教会你整列跳过不看——连它旁边那条真的一起。

同一天还揪出一个我自己造的天天狼来了。有个检查逐字比对一份说明文件和现实对不对得上,而那份文件里有张表,记着「每个命令我用过多少次」。我每用一次,它就变一次。 于是它天天报问题,原因是我在正常使用。那一列删掉了。


五、动手之前,先让每条结论挨一顿打

手上排着 12 件要修的事。我没有先修,而是先把每一条送去挨打——交代得很清楚:默认它是错的,去证明它错。

结果:

判定多少条
结论和处置都站得住1
事实就是错的4
只对了一半,得改着做7
12 条结论的判定分布
照单全做的话,12 件里有 9 件白干或者做错。

上一轮这个数是 62.5%,这一轮严格算错的只有 33%。看着像进步。不是。出错的方式换了。

上一轮是数字本身就不对,一查就露。这一轮那 9 件里有 5 件的错法完全一样:数字是真的,只是过期了——它们读的是两天前那批修复之前的快照。

过期的真话
这一类比「数字错了」难抓得多,因为它看起来像认真查过——那些数字确实曾经是真的,你还能在记录里翻出来。

所以这一轮换来一条规矩:要断言一段代码怎么样,第一件事是查它上次改动是什么时候。 改动时间比你这条结论晚,整条作废,重查。


六、这一轮的账

先更正一个我上次报错了的数。

我攒了 34 个小工具,统计说其中 33 个从来没被用过。听着像该大扫除了。

但统计只数了一种用法:我手打它的名字。工具还有另一种启动方式——干活干到一半,模型自己判断该用它,直接调起来。这条路统计根本没看。

只量了一半的尺子
33 个「从没用过」里,有 8 个是假零,一共漏了 18 次调用。

我补了第二把尺子,但故意没有把两个数加起来。手打的次数是「你打算怎么用我」,自动调起的次数是「我实际怎么干活」。合成一个数,这个差别就没了。

35 个报警器 + 2 个审计 + 124 条承诺
哑的3 个,同一个原因;其中 1 个是我前天亲手弄哑的
假响的今天报的 3 条,3 条全假
扔掉的12 条待办里的 9 条

装报警器不难。难的是隔一阵去确认它还会响,而唯一的确认办法只有一个:把该出的事故放回去一次,看它响不响。

如果只带走一句:

一个哑掉的报警器,和它本来要防的那场事故,是同一类东西。