Jev 给这一行打标签。代码来做判定。

TL;DR:README Clew 2 会检查公开的 GitHub README 是否与其代码相符,适用于 JavaScript 和 TypeScript 仓库。一个名为 Jev 的小型决策模型会标注每一行 README 属于哪种声明,五项固定的代码检查会判定它是否属实,然后由Claude Haiku撰写摘要。我用五天时间构建了它,借助AdaL——SylphAI 的编程智能体——为 AdaL 的“What Would Jev Do?”黑客松而做。它的第一次真实测试是我自己的一个旧仓库,结果它判断错了。

AdaL 的“What Would Jev Do?”黑客松只要求一件事:用AdaL——SylphAI 的编程智能体——构建一个项目,让 Jev 真正派上用场。我并没有要解决的问题。我只有一个模型,和一个截止日期。

Jev是一个小型决策模型,来自TypeSafe。DigitalOcean 的文章称它为“一个连一句话都写不出来的 AI 模型”,而这正是它的意义所在。你给它一个问题、回答规则和一组固定的标签。它挑出一个标签,并告诉你它有多确定,用一个 0 到 1 之间的数字表示。你通过Glasser来调用它,该服务负责运行 Jev 调用并按次收费。

从这样一个工具起步有点奇怪。我的项目通常从问题开始,然后再选模型。这次是从模型开始,所以我去找一个适合它的问题。我第一个想法是改造我Hot AR Summer 系列里的应用,因为它们本来就是确定性的。然后我又过了一大堆想法。Dewey。Pun Court。Sortes。Which Door。Saint of Small Things——我太喜欢它了,不忍心把它硬塞进一个并不合适的格式里。我也排除了法律类工具。每一个有趣的想法都死在评审标准里的同一句话上:“项目应当存在的明确理由。”

于是我回到一个我已经有的理由。五月我构建了README Clew,因为我一直担心我的 README 和我自己的仓库对不上。它确实管用,而它自己的 README 列出了两个诚实的局限。当时是要求 Claude 逐字引用 README,这只是一条提示词规则,而不是代码检查。而且它有时会把“Frontend (Vite)”这样的说明性标签当成包名,从而产生误报。

这两个局限都是标注问题。而标注正是 Jev 唯一擅长的事。

一个 clew(读作“clue”)是一团线。在希腊神话中,Ariadne 给了 Theseus 一个线团,让他能顺着它走出迷宫。README Clew 顺着这条线,从每一行 README 追溯到代码。它也是我的Clew Suite公民科技工具套件。

GitHub logo earlgreyhot1701D/readme-clew-2

检查你的 README 是否与代码一致。适用于任何公开 JS/TS 仓库的 Chrome 扩展 + 网页。规则和五个确定性验证器判定什么是真的,Jev 以校准后的置信度为 README 各行打标签,Haiku 解释发现的问题。行级关联凭证、状态徽章、JSON 导出。使用 AdaL 构建,用于 What Would Jev Do?

README Clew 2

README Clew 2: checks whether your README matches your code

检查 GitHub README 是否与其代码一致。

在线地址: https://readme-clew-2.vercel.app

粘贴一个公开的 JavaScript 或 TypeScript 仓库,按下 SCAN,即可得到一份声明账本:README 中每一行可检查的内容、代码对它的说法,以及由谁判定。

为 AdaL “What Would Jev Do?” 黑客松构建,2026 年 10 月 6 日至 11 日。

为什么叫“clew”?clew(读作“clue”)是一团线。在希腊神话中,Ariadne 给了 Theseus 一个线团,让他能顺着它走出迷宫,“clue”一词正源于此。README Clew 顺着这条线,从每一行 README 追溯到代码。它也是作者那套公民科技工具的名字。


它的功能

README 会漂移。命令被改名、环境变量被删除、包被替换,而 README 仍在承诺旧的东西。README Clew 2 会读取……

它的功能

README 会漂移。命令被改名、环境变量被删除、包被替换,而 README 仍在承诺旧的东西。README Clew 2 逐行读取 README,并把每一行归入四类之一:

类别 含义
矛盾 README 声称如此,代码却不同意
缺失 代码实现了它,README 却从未提及
无法验证 没有代码检查能测试它,或者 Jev 不确定这是哪类行
已验证 README 与代码一致

每一行都显示确切的 README 行、代码证据,以及由谁判定:某条规则或 Jev。

Scan report for README Clew v1: 0 contradicted, 4 missing, 139 unverifiable, 8 verified. A yellow strip reads Gaps found, 4 missing. The Missing rows name esbuild-plugin-pino, orval, drizzle-kit and pino-http, each with the file that imports it and the label Decided by: rule.

这是对 v1 的真实扫描。没有矛盾,还有四个代码导入但 README 从未提及的包。新版本审计了旧版本。

Jev 从不拥有最终决定权

我围绕构建的规则:模型永远不决定什么是真的。

代码把 README 拆成行,并在没有任何模型参与的情况下处理掉简单的那些:标题、徽章、空行。对于剩下的,Jev 判断这一行属于哪种声明。一个依赖、一条命令、一个环境变量、一个文件或 URL,或者某种没有任何代码检查能覆盖的东西。

只有当 Jev 至少有 0.8 的置信度认为某一行属于四种可检查类型之一时,这一行才会进入代码检查。低于这个阈值,它就会落入 Unverifiable,并标记为“Jev 不确定”。然后五个确定性验证器读取package.json、文件树和源码,并做出判断。相同的输入,相同的答案。Claude Haiku 在最后仅根据计数和名称写一段简短总结。它从不会看到 README 的行,所以一个植入了指令的 README 无法与它对话。

这两种错误的代价并不对等。把一行判为 Unverifiable 只会损失一点覆盖率。把一行正确的判为 Contradicted 则会损失你的信任。我从 MLH 的 Swift 那里借用了这个框架,他发表了我让 Jev 做到了零错误。我仍然在使用 Flash-Lite。就在我写 Jev 的问题的同一天。他的经验重塑了这次构建:描述每个检查器看不到什么,而不是描述 README 的一行长什么样;不给 Jev 任何示例;按行而不是按运行来统计错误。

我的做法是把最可怕的失败转化为代码,而不是提示词。一个只出现在正文里的包名,无论 Jev 有多确定,都永远不会被标记为 Contradicted。

在一个包含 32 行 README 的留出集上,设置冻结后运行两次:

指标 第 1 次运行 第 2 次运行
越过 0.8 阈值的错误标签 0 0
端到端的误判 Contradicted 0 0
发现的真实漂移 3 / 3 3 / 3

32 行是一个小样本。它支持的是“足够安全可以发布”,而不是一个测得的错误率。

README Clew 2 key numbers from testing, in the site's cyan terminal style beside a ball of yarn. One Jev call: $0.00002 in 495 milliseconds. One full 283-line README: 3 calls, about 1.4 seconds, $0.0024. All early test calls: about half a cent. Scans the $11 covers: about 1,200. Label drift between identical runs: 4 or 5 of 283 lines. Tests at submission: 474, all offline. Jev across the whole build: 153 runs, $0.15.

一次完整扫描大约花费一美分。其中大约 $0.009 是 Jev。

一个智能体,一份构建日志

我负责指导、验证和决策。AdaL编写了代码和测试,运行了 Jev 评估,部署到 Vercel,并驱动真实浏览器进行 QA。Claude(Opus 5.5)编写了规格和架构,在每个检查点审查 AdaL 的工作,并撰写了文档。

AdaL 从一个AGENTS.md它每一轮都会读取:先提出方案,一次一个块,只触碰被点名的文件,停下来等 QA 检查点。我上一次构建给我留下了一个 1200 行的上帝文件,所以这一次每个文件都设了 200 行上限,由一个会让测试套件失败的测试来强制执行。写在提示词里的规则只是一个请求。一个会失败的测试才是规则。

AdaL 全都照做了,而且很快。在计划模式下,它提出并确认计划的速度快到我把提示词粘贴进去、走开一会儿,回来时活儿已经干完了。它还发现了没人让它去找的真实 bug:

  • Glasser,也就是运行 Jev 调用的那个服务,把单次调用限制在 100 个问题。只有实时 API 会说明这一点,schema 里没有。
  • 一个让测试悄悄取消而不是失败的定时器。
  • 一个测量了错误版本文本的裁剪器。
  • 两个只在真实浏览器里才显现的布局 bug。 最后一个让我意外。AdaL 自己打开了浏览器工具去截图并给页面计时。我从没切换过它。

并非一切都顺利。文件已经写好、所有测试也都通过了之后,AdaL 还在 "Create lib/report.js" 上卡了 22 分钟。只有屏幕卡住了。我这周笔记本风扇转得比过去一年还多。AdaL 里的 Glasser 连接器让每次 Claude 调用都失败,直到我把它关掉并上报。到了第四天,就在我批准了最大的那个块之后,我的每周计划额度用完了。

解决办法就在 AdaL 自己的文档里:自带 API key。我本来就有 Claude API 额度。大约 35 分钟后,AdaL 就用我的 key 重新开始构建了。

AdaL 团队值得单独写一段。我上报 Glasser 连接器的当天他们就修好了。当我告诉他们我撞上了每周限额时,他们给了一笔额度让我能完成。这是我第一次在黑客松里能和主办方的人直接、快速地联系,这让一场五天的冲刺没那么孤单。

吉祥物也体现了这种分工。AdaL 用代码画出了第一个线团,做成 SVG 面孔,然后给出两种线球风格供选择。最终上线的那一个是由 ChatGPT 画的,然后由 Claude 抠图并调整尺寸。一个用路径作画的智能体和一个会绘画的图像模型,擅长的事情不一样。

Clew mascot style sheet. Top row, AdaL's first version: three round faces drawn in thin cyan lines, labeled calm, worried and tangled. Below it, two thread-ball styles AdaL drew to choose from, A thin and B heavier, each in five moods: calm, curious, worried, tangled and tilt, with tiny copies at favicon sizes.

The shipped clew mascot, painted by ChatGPT: a cyan ball of yarn with a loose thread trailing off to the right.

是我,我就是问题所在

除了连接器那个 bug,这次构建里的大部分摩擦都来自我自己。

我很害怕发布粗制滥造的东西,所以我要求每个测试都要先展示一次失败。故意破坏代码,看着测试变红,再恢复。在 Block 1 中,这意味着 102 个测试和 75 次故意破坏。然后它还在继续。

构建中的时间点 测试数
Block 1 102
Block 3 和 4 197
Monorepo 修复 222
UI 打磨之前 353
周六晚上 452
提交 474

其中一些测试非常重要。守护五个检查器、0.8 阈值、散文规则和 monorepo 回归的那些测试,正是防止正确的 README 被误判为错误的关键。其余很多测试只是在重复验证页面接线,而浏览器检查已经覆盖了这些。对于一个五天的构建来说,这太荒谬了。

它还花了真金白银。每一次故意破坏都是一次完整的测试运行,而每次运行都是智能体时间。我的第二个新手错误是从未开启新的 AdaL 会话。每一轮都会重新发送整个对话,所以长会话中越靠后的轮次成本越高。到周六晚上,我在大约三个半小时内花掉了我为密钥设定的 50 美元上限中的 36 美元。

AdaL 完全按照提示词的要求做了。是指导设定了标准,我的和 Claude 的。

解决办法是在每个提示词顶部加一个“精简模式”标头:每个 block 使用全新会话,只读取需要的文件,每个新测试文件只展示一次失败而不是每个测试都展示,浏览器 QA 只在最后运行一次。构建的其余部分,包括加固、扩展、README 和最后的修复,花了大约 4 美元。智能体的最终账单是 40.35 美元。应用每次扫描的成本约为 1 美分。

下次我会在 block 开始前为每个 block 设定测试预算,并让它与失败会给用户带来的成本相匹配,而不是与习惯相匹配。

它犯的第一个错误是我的错

第一次真正的扫描是我自己的 v1 仓库。README Clew 2 把三行标记为 Contradicted,并把四个包标记为 Missing。Claude 打开 v1 的文件进行核对。这七个全是误报。

v1 是一个 pnpm monorepo,其工作区位于工作区查找器不知道的文件夹中。而 pnpm 的--filter选项被当成了脚本名读取。这个工具恰恰以它承诺永远不会出错的方式出错了,而且是在我自己的仓库上,在任何评委看到它之前几个小时。

AdaL 用一个块就修好了。现在它无法解决的任何问题都会返回 Unverifiable,而不再是 Contradicted,v1 也变成了一个保存下来的回归测试。重新扫描时:Contradicted 从 3 降到 0,而那四个 Missing 包被证明是真实存在的。

对 polka 仓库的第二次实时扫描发现了 14 个 Missing 包,它们全都来自一个带有自己包文件的 examples 文件夹。同样的修复,同样的测试类型。

最后两个来自我周六晚些时候问的一个问题:我们是不是把误判矛盾也构建进去了?Claude 重新阅读了每个检查器,又发现了两种会把正确的 README 判为有罪的方式。一个在文件读取上限 20 个之外的文件里使用的环境变量。以及一个指向构建产物(如dist/)的 README,而构建产物从不提交。AdaL 让这两者都返回 Unverifiable。

最后的 bug 来自提出这个工具本就是为了回答的那个问题。

它做不到的事

  • 仅支持 JavaScript 和 TypeScript。在 JS 和 TS 中,一个文件,package.json,同时列出包和命令。Python 把同样的事实分散在几个可选文件里。一个没有package.json的仓库会收到一条清晰的消息,并且不会调用任何模型。
  • 大多数行最终都是 Unverifiable。大多数 README 文本是散文,没有代码检查能测试它。Unverifiable 的意思是“无法判断”,而不是“错误”。
  • Monorepo 支持涵盖简单的工作区模式,最多 30 个工作区。超出这个范围,Missing 就会变成 Unverifiable。
  • 每次扫描最多读取 20 个源文件,并截断超过 50 KB 的 README。
  • 同一个 README 扫描两次,可能会让某条边界行在不同桶之间移动。0.8 的门槛让这种漂移远离 Contradicted。
  • 没有 README 徽章。徽章会重新运行扫描,并且每次有人查看都会向我收费,而且没有存储就没有安全的缓存方式。

有三种使用方式,它们都走同一个扫描:

方式 最适合
在线页面 你想要完整的账本,或者你在手机上。无需安装
Chrome 扩展 你已经在仓库的 GitHub 页面上。一键完成
书签小工具 你无法安装扩展,比如在受限的工作电脑上。从 ABOUT 标签页拖动它

书签小工具的存在是因为我的日常工作。工作电脑会阻止扩展,而一个能打开页面并填好仓库的书签可以绕过这一点。

README Clew 2 home page in a dark cyan terminal style: a repo field with SCAN, CLEAR and USE DEMO REPO buttons, SCAN, KEY and ABOUT tabs, and the clew mascot beside the prompt to enter a public GitHub repo.

The Chrome extension popup with a sample report: 1 contradicted. A red strip reads Drift found. The row shows README line 6, npm start, with evidence that package.json has start:prod but no start script.

没有数据库,也没有账户。扫描结果从不存储,日志只保留计数和耗时。由于什么都不保留,DOWNLOAD JSON 会以文件形式给你报告,并附带一份扫描回执:仓库和提交、README 文本的指纹,以及报告的指纹,这样你之后可以判断它是否被编辑过。这些内容都不是由模型写入的。把它附到 pull request 上,或者留作前后对比。

在我提交之前,README Clew 2 扫描了它自己的 README:285 行,154 行发送给 Jev,5.6 秒。0 条矛盾,0 条缺失,1 条已验证,以及 107 条无法验证。唯一一条已验证的行是npm test,并且package.json确实有一个测试脚本。107 是诚实的数字。README 的大部分内容都是散文。对于“Built for the AdaL 'What Would Jev Do?' hackathon”,Jev 说这不是可核查的声明,确信度 0.52,而这一行从未接近任何检查器。

按下 USE DEMO REPO,然后按下 SCAN,看新版本给旧版本打分。代码、决策日志和每一个错误转折都在仓库里。

如果你是新来的,这里快速交代一下背景。我在加州法院工作,负责该县的法院运营。我在 2025 年 7 月开始用 AI 构建东西,此后一直在公开学习。我不写代码。我指挥,智能体生成,我验证并做决定。

在 2026 年 10 月借助 AI 协助构建,用于 AdaL “What Would Jev Do?” hackathon,其中 Jev 由 TypeSafe 提供、通过 Glasser 调用。这些工具发展很快,所以在引用我的话之前请先核实来源。

AI 辅助。人工批准。由 NLP 驱动。