Reticle 深度评测:1,263 Star 的 AI 代理验证层,3 个故障抓 2 个、第 3 个要你先交账本

用过编码代理(coding agent,也就是能自己改代码的 AI 程序)的人都见过这一幕:它说「已修好,构建通过」,你打开页面,按钮点下去没反应。

这不是它偷懒。编码代理的天性是产出改动,它天生乐观;而验证的天性是去把事查清楚,并且随时准备回一句「不行」。两件事方向相反,所以它写代码快,查自己写的代码就慢,甚至根本不查。

今天评测的 reticlehq/reticle 就是冲着这个缝隙来的。它的口号只有一句:你说做完了,我来判断这是不是真的。结论先给:它确实能看见截图看不见的东西,但前提是你得先把应用内部的「账本」交到它手里。

它是什么:把判决书,而不是截图,交给代理

Reticle 往你的应用里塞一个只在开发环境生效的小程序,再在本机 127.0.0.1 的 4400 口起一个服务当桥。代理通过 MCP(也就是模型上下文协议,给 AI 接外部工具的插座)拿到一组工具,可以看页面、点元素、读网络请求、读状态,然后断言——也就是用一句话声明「应该发生什么」,让工具去核对。

它返回的是三种判决之一:是、否、说不准。只有「是」才算通过,说不准就是说不准,不允许用一个含糊的绿灯糊过去。判决书上还带三样东西:决定这次判定的那条网络请求、那次状态变化、那行控制台输出,以及一个可以直接点开的「文件:行号」。

和截图比对类工具的根本差别在这里:截图工具看的是「屏幕上长什么样」,Reticle 看的是「程序自己认为发生了什么」。屏幕会撒谎,程序内部的账本不太会。

仓库规模不小,也够实:3,137 个 TypeScript 文件,其中实现代码 1,251 个文件 24.1 万行,测试 1,886 个文件 29 万行——测试比实现多出五万行。近 30 天 377 次提交、376 个合并的 PR,开源许可证按包声明为 Apache-2.0(可商用),1,263 颗星,2026 年 6 月建仓,五个月长到这个体量。

实测:我在一个 React 应用里埋了 3 个故障

光看 README 不算评测。我搭了一个最小的前端示例应用,故意埋了三个真实的烂摊子:

  1. 页面加载时发一个会返回 500 的请求,界面把它吞掉,照常显示「一切正常」;
  1. 一个链接指向的页面里抛异常,控制台报错;
  1. 顶部徽标显示「0 个部署」,但程序内部记着 3 个——界面在撒谎,而且撒得很自洽。

第一条命令是零安装的:在应用目录里跑 npx @reticlehq/server,它自己找开发服务器、自己开浏览器、不往你项目里写任何文件。对着干净的版本,它给的是「是」;对着埋了故障的版本,它当场报出 5 处问题,原文是 Failed request on /: POST /api/deploy: HTTP 500 和 Console error on /broken: Uncaught Error: status page broke,退出码 1。

前两个故障,就这么被一条命令抓到了。

第三个没抓到,而且抓不到得理直气壮:那条零安装的体检只检查「页面能不能开、有没有控制台报错、有没有失败请求、同源链接能不能打开」,徽标显示 0 而账本记着 3,在它眼里完全合规。我故意用文字断言去问「页面上是不是有 0」,它回答是——因为屏幕上确实写着 0。

真正的解法是让它把两边对起来看。我在应用里手动注册了一个账本(一个带读取和订阅两个方法的普通对象),然后用一条「比对」断言:

reticle verify http://localhost:5179 --expect '{"kind":"compare",
  "left":{"from":"state","store":"deploy","path":"items.length"},
  "right":{"from":"text","scope":"[data-testid=\"nav-badge\"]"},"as":"number"}'

结果 verified: no——账本是 3,徽标是 0,不一致。同一时刻,把左边换成页面上那句真话「共 3 个部署」,判决立刻变成 verified: yes。

所以严格说,三个故障它都抓得住。差别在门槛:前两个一条零安装命令就报出来,第三个要你先交出账本、再写一行比对。

这一步是整个评测里最有价值的一步:它抓住的是「每一处单独看都对、合起来是错的」。这类毛病,截图比对和读无障碍树的工具都看不见,因为它们只能读到屏幕,读不到屏幕背后的账本。

仓库自己也承认这是它唯一的结构性优势。它自带一套 88 条的故障题库(86 条真故障 + 2 条「看着像坏了其实没坏」的陷阱),与一份 Playwright 脚本正面对比:Reticle 抓到 85 条,Playwright 59 条,两边对干净版本都零误报。差距并不均匀——26 条是 Playwright 结构上就不可能看到的(要读应用状态、要读客户端自己伪造的 500),剩下能看到的那些,两者打平。

值得单独说的一点:它公开撤回自己的数字

评测一个自称能验证一切的项目,最该看的是它怎么对待自己的数字。这一点它做得比多数项目狠。

它仓库里有一份基准测试的说明,明写着旧数据不能当基线。理由是那些历史记录出自一个有四处缺陷的测量脚本,而四处缺陷全都对自己的产品有利:有一项检查的统计范围缩水了,却依旧判定通过;有两个从没跑过的工具,被记成「全盘零分」;还有一条故障的判定条件宽到连请求地址本身都能满足。

更狠的是变更日志里那条自我更正:单条故障的输出成本,原先公布的是自己 4,134 字节、对手 7,899 字节,复测后发现实际是自己 9,261 字节、对手 5,849 字节——结论反了,于是把旧结论整个撤回,写明「不要重复引用它」。它甚至专门为「跳过对手能用的接口就直接判对手抓不到」这类自欺写过一段反省,把六条改判回平手。

这种自我拆台,比任何一个漂亮数字都更能说明这套判据是可信的。

三个我自己踩到的坑,和它不适合谁

第一个坑:账本名写错,它给你的是「否」,不是「说不准」。 我把账本名故意写成一个不存在的名字,判决是 verified: no,理由是「声明的后果没有发生」,附带的证据只是提示「搜过的账本有这些」。也就是说,配置写错和功能真坏了,在 CI 里长得一模一样。这跟它「说不准就说不准」的原则不一致,属于需要你自己留一层校验的地方。

第二个坑:断言写错一个字段,直接判「说不准」。我把限定作用范围的字段写成了一个对象而不是字符串,它返回「说不准」,并明确说明「这条断言没有解析成功,所以什么都没运行」。态度是对的,但它和「功能失败」共用同一个退出码 1。脚本里想区分「写错了」和「真坏了」,得自己解析输出。

第三个坑:没录过任何流程时,那道 CI 闸门是空转的。项目说明里写着它能拦住「改了受流程覆盖的代码却没重新验证」的提交。我在一个没有任何流程的项目里跑它,输出写着通过为假、原因为「没有流程」,并解释「这里没有存下来的流程,所以没什么可查,这不算这次改动的失败」——但退出码是 2。CI 里只要写了「非零就当失败」,它就会误伤;反过来,只要写成「非零一律放过」,它又会在真有流程时也放过。判定条件得写成只认 0 和 2 两种。

另外两件要提前知道的:自动探索模式(没流程时让它自己跑一遍并录下来)需要把项目连到它的云端平台,不连就用不了,原文是「这个项目没有连到平台上,请先连接,或者你自己驱动这段旅程」;首次运行如果没有本机 Chromium,它会当场下载约 150 MB。

至于坑之外的分工,我认为是这样的:

你要解决的问题 更合适的工具
界面到底有没有骗人、请求有没有静默失败、状态和显示对不对得上 Reticle 这类进得去程序内部的工具
跨浏览器、跨设备、别人的站点能不能用 Playwright 这类从外部驱动的工具
像素级还原、无障碍合规扫描、安全漏洞 各用各的专职工具

它自己不回避这个边界:仓库里写着看不到 IndexedDB、Web Worker、闭合的影子根节点和跨域内嵌框,也写着单步操作里的竞态只能部分覆盖。专门为「界面在撒谎」这一类毛病买的工具,不必拿它当万能测试框架。

结论

一句话判断:如果你每天都在让代理改前端代码、又反复被「它说好了其实没好」坑,这套东西值得放进观察清单,甚至值得今天就装到一个项目上试半天。 它抓不到的东西比它承诺的少,抓住的那些又恰好是别的工具结构性看不到的;再加上它敢公开撤回自己的漂亮数字,可信度够。

但别指望装上就自动生效。它需要你在应用里点明「哪些元素重要、哪个账本说了算」——这就是我标题里说的「先交账本」。你不交,它就退回成一个好用的体检工具;你交了,它才变成那个能对代理说「不行」的裁判。

仓库地址:https://github.com/reticlehq/reticle

关注 AI商业快讯,每天一篇 AI 热点深度解读。

相关阅读:

发表评论