Claude 一天写完一个 app,而我之所以我敢用它,是因为另一件事
一个 agent 吭哧吭哧写了一整天代码,最后跟你说"做完了,运行良好"——这话你信几分?
说实话,我信不了几分。而这点不信任,恰恰是后面整件事的起点。
macOS 26(Tahoe)把 Launchpad 删了,我用惯了,干脆让 Claude 从零写一个替代品。一天下来 41 个提交,全屏毛玻璃网格、拖拽建文件夹、触控板分页、全局热键,能跑、能打包、能签名。代码是 Claude 写的,判断和决策是我的。
一开始,我以为难点是"它到底能不能写对"。原生交互不少:长按进整理模式、拖一个 app 建文件夹、文件夹内分页、四指捏合唤起——这些它都写出来了,也能编译通过。如果故事停在这儿,那就是又一个"AI 一天写完一个 app"的爽文。
但代码能跑,不等于我敢把它装到自己电脑上每天开。一个写了一整天、自己说"做完了"的 agent,它对自己的判断能有几分客观?
所以写完之后,我没让 Claude 自己检查自己,而是把整个项目丢给另一个 agent——Codex——来审。写代码的是一个,挑毛病的是另一个。
你要是让写代码的那个 agent "回头看看自己写得怎么样",它大概率告诉你"运行良好、代码整洁"——自己给自己打分,没有不及格的。这跟人一样,谁也不爱否定自己刚干完的活。
换一个独立的 agent 来审,情况完全不同。
Codex 产出了一份文档,逐条把这个启动器跟原生 Launchpad 对比,列出差在哪。而且不是看一遍就完事,是一轮一轮来的——这一点提交历史暴露得很清楚,因为每条它挑出的毛病,Claude 改完都留了对应编号的提交:
第一轮叫 Gap #N,编号一路排到 #15——文件夹打开会裁掉顶行、搜索结果渲染异常、触控板分页是离散跳页不跟手……第二轮叫 Gap re-audit,回头再扫一遍,又揪出 #2 到 #11 一批。第三轮干脆叫 Gap 3rd-scan。最后还单独拎出 Perf 和 Reliability,把性能和可靠性再过一遍。
写一个,审一个,改一个,再审。提交历史本身成了这套来回的记录——哪条还没修、哪条第三轮才修干净,全有迹可循。
这里还有个差别很关键:审的标准是外部的。
不是"我觉得这个文件夹动画挺顺",而是"对比原生 Launchpad,打开文件夹时顶行被裁掉了,这不对"。基准锚在一个项目自己之外、而且是用户早就熟悉的参照系上。审的人独立,尺子也独立——这两件事缺一不可。
我自己做内容系统时踩过同构的坑。早期我也想过让模型自己评判草稿好不好,但自评几乎没用——它不会说自己差。后来我给内容系统配了一份固定的反面清单(钩子弱、太说教、缺数据、AI 味重),让草稿对着这份清单逐条过,才开始挑出真毛病。一种理解是"让 AI 自己看看行不行",另一种是"换一双独立的眼睛、拿一把外部的尺子来量",我站第二种。
第二件让我意外的事,更微妙。
UI 这种东西,agent 是"看不见"的——代码写出来,它并不知道渲染出来长什么样。为了让审查能落到界面上,项目里加了个调试模式,用 SwiftUI 的 ImageRenderer 把启动器的各个状态直接渲染成 PNG,不用录屏就能"看"界面。
如果只到这一步,这是个聪明但危险的工具。危险在哪?
Codex 拿这些截图来审的时候,在文档里自己把这双眼睛的盲区写清楚了。原话大意是:这些截图证明不了真实的模糊效果、触控板手感、键盘焦点和 VoiceOver 输出——它们只对布局和裁切有用。
然后真就出事了。搜索框输入 "co" 的那张截图,本该命中 Codex、Console、Contacts 一堆 app,截出来却是一片空白。
我特别留意它怎么处理这个空白,因为这一步最能看出一个审查到底可不可信。
它没有想当然地判定"搜索坏了、去改代码"。它的结论是:先去真机测;如果真机也空白,那才是 bug;如果只是 ImageRenderer 这个渲染器本身的限制,就把这条限制记下来,再加一个数据层的断言——直接确认 "co" 到底能不能搜出结果。后来这个断言落地了,结果是返回 14 个。
这个差别很关键:截图是空的,但搜索功能本身是好的。要是把"截图空白"当成"搜索坏了"直接去改代码,那就是拿着一张骗人的截图,去修一个根本不存在的 bug。
一个审查者最危险的地方,从来不是它看不见。是它把"渲染出来的样子"当成了"事实就是这样"。给它装眼睛不难,难的是它得知道,这双眼睛在哪些地方会骗自己。
把上面两件事缝起来的,是那份审计文档结尾的一个段落,标题叫 Verification Gaps——没验证的缺口。
它把没做的事,明明白白单列成一栏:
触控板分页和自定义手势,没在真实硬件上测过;多显示器行为,只做了代码审查,没有可视化验证;中文 IME、输入即搜索,没手动测;VoiceOver 的完整流程,没手测;真实的毛玻璃模糊效果,生成截图里根本看不到。
这一栏,才是我整件事里最在意的东西。
因为它把"我审过代码"和"我真机验证过",钉成了两件不同的事,分开写。没验证的,绝不伪装成验证过的。
写到这里我几乎是会心一笑——这不就是我给自己的内容系统定的那条最高优先级铁律吗。
我的写作硬规则第一条是"虚构零容忍":具体的数字、事故、对话、操作细节,必须来自已确认的真实材料;没有,就改成方法论、对比或行业观察,或者明写"未亲身验证"。凡是写"我用过 X",必须带上真实的天数、次数、成本、行数;给不出,就降级成观察,不许写成亲历。
代码这边对应的,就是"代码看过≠真机验证过"。不是同一件事,但那种"我以为我确认了,其实我只是看了一眼"的风险,一模一样。一个审查者报告"我审完了,没问题",和一个写手声称"我亲测过",含金量取决于同一件事:有没有把没验证的部分,诚实地划出来。
我能想到的最强反驳是这样的:
让两个 agent 一个写一个审,既烧两份 token 又拖时间——代码本来就该人来 review,绕这么一圈干嘛?直接我自己看不就完了。
人来 review,当然对,这一步省不掉。
但这一圈改变的不是"要不要人来看",而是人拿到的交付物长什么样。
没有这套来回,你拿到的是一个黑箱:写代码的 agent 信誓旦旦说"做完了,运行良好",你得自己从头逐行判断哪里能信、哪里不能信。
有了这套来回,你拿到的是一个标好了红线的东西:这 12 条对着原生挑出来又改了,这一栏没在真机验证。人的注意力被直接领到该看的地方——真机手感、中文输入法、多屏——而不是浪费在已经被对照检查过的部分。
至于"自己审自己不可信"——这恰恰是我没让 Claude 自审、而是换 Codex 来审的原因。写的人和审的人分开,本身就堵住了"自己给自己打高分"这个最大的漏洞。再加上两根柱子:基准必须是外部的(防止糊弄),清单必须是诚实的(没验证的别装成验证过)。独立的审查者 + 外部基准 + 诚实分栏,这一圈才有意义。
成本确实有,多花一份 token、多绕一道。但它买回来的,是"我知道哪里不能信"——对要交付的东西来说,这比"看起来全都没问题"值钱得多。
跑完这一趟,我对"怎么用 agent 写东西"的判断变了。
以前我盯的是结果:跑通了吗,功能齐了吗,能 demo 吗。现在我多看一层:写完之后,谁来审,拿什么审。
落到操作上,就两件事:
第一,别让写的那个 agent 自己审自己。换一个独立的来挑刺,最好连基准都是外部的——一个它之外、可对照的参照系,而不是"我觉得没问题"。
第二,逼审查给出那一栏"没验证"。哪些是看过代码、但没在真机或真实环境里跑过的?答不出这一栏,或者把没验证的混进"已完成"里,那句"审完了,没问题"就不能信。
这两件事不定,单个 agent 写得再漂亮、自己夸得再响,你拿到的也只是一个看起来很完整的黑箱。
能信的从来不是它写得对,是有另一双独立的眼睛告诉过你:它哪里可能不对,以及哪里还没来得及验。
AI agent · 工作流 · 真实踩坑日志 | ![]() |
夜雨聆风