11 月 8 号那批任务上,Antigravity CLI 的通过率从 58% 涨到 94%,Codex CLI 从 54% 到 82%,Claude Code 从 57% 到 88%。同一批任务、同一批模型,唯一变量是装没装一个 npm 包。
这三个数字的第一反应应该是怀疑。一个不提供模型、不提供工具、不提供运行时,只提供一堆 Markdown 指南和两个检索命令的东西,把通过率抬了三十几个点——如果这是真的,那说明病因一直找错了地方;如果是假的,那说明评测集被有意无意地挑成了"平台能力可解、但 agent 不知道平台有此能力"这一类,干预正好打在病灶上,涨多少都不奇怪。这两件事后面都要说,因为它们是同一件事的两面。
先说这个包是什么。GoogleChrome/modern-web-guidance,一个明确以"把编码 agent 拉回当前 Web 平台实践"为目标的知识仓库(repo README)。它的自我定位里有一句话是整份材料的钥匙:agent 之所以反复写出旧模式,是因为训练语料里旧代码的密度远高于新代码,于是模型会用一大堆 JavaScript 去手搓浏览器本来就有的能力。这不是抱怨,是一个技术判断——它把"agent 代码质量差"这个问题,从模型能力问题重新归类成了语料的时间错位问题。
归类一换,解法就换了。你没法靠再训一轮模型去修时间错位,但你可以给 agent 一份索引。
地图的四层,大部分人只画第一层
给 agent 供知识的工程,结构上永远是四层,缺一层就残:
给 agent 的平台知识
├── 1 知识层 指南正文:什么能力存在、什么场景该用哪个
├── 2 检索层 agent 怎么在几万 token 之外按需取到那一条
├── 3 接线层 怎么塞进 agent 的上下文而不挤爆预算
└── 4 验证层 怎么证明塞进去之后真的变好了
└── 治理层(横切):谁保证这四层不腐坏
现代 Web 这个领域的特殊之处在于,第一层是最不缺的——MDN 在那里躺了十几年。缺的永远是后三层。所以绝大多数"给 agent 的知识包"做完第一层就发 npm 了,然后死在第二层:指南写了三万行,agent 一条也取不到,等于没写。
modern-web-guidance 值得单独摊开讲,恰恰因为它四层都动过手,而且第四层做得比我认为它该有的水准还认真一点——同时也就更值得挑刺。
知识层:250 条 feature 和 203 条 use case 是两套索引,不是一套
仓库页面给的数字是 250 条现代 Web 特性和 203 条开发者用例,横跨 CSS、HTML、JavaScript API、表单、无障碍、性能、安全、PWA、built-in AI、UI 组件、视觉设计、WebAssembly、WebMCP 这些区(repo 索引页)。
数字本身不重要,两个数字分开报这件事才重要。
特性是按 API 面组织的,用例是按任务面组织的。这两套索引的查询方向完全相反:特性索引的入口是"这个 API 存在吗、怎么用",用例索引的入口是"我要做一个滚动时固定表头的东西,现在该用 CSS 的哪一招而不是监听 scroll"。而 agent 从用户那里拿到的 query 永远是任务面的——没人会对着 agent 说"请使用 position: sticky",人只会说"这个表头跟着滚"。你只给特性索引,agent 就得先做一次从任务到 API 的映射,而这一次映射正是它最容易失手的地方,因为它的训练分布里这个映射的众数解是 2019 年的。
这一步得说重一点:给 agent 的文档,如果只有 API 索引,那它只是在加速 agent 走错路。它检索得越快、越自信,越会用一个过时但命中的 API 把活干完。
同样值得单拎出来的是它对"现代"这个概念的处理方式。指南把改动分成两类:老浏览器可以直接忽略的加法式增强,和必须带轻量兜底的关键行为;兜底代码明着限制了规模,自定义 fallback 卡在 50 行左右,超了就改成条件加载的 polyfill(指南条目)。
这是整份材料里最见功力的一条,因为它承认了一件大多数人嘴上承认、写文档时又忘掉的事——"现代"不是一个布尔值,是一条分布。按最低共同分母写,代码难看但到处能跑;按最新写,好看但在某些环境下直接崩。指南选的是第三条:按能力分层,加法部分不做检测,关键部分给一个写死的、有上限的降级路径。
50 行这个上限不是随手定的。它在防 agent 的一个特定失败模式:一旦允许它"自己写个 polyfill 兜一下",它就会写出第六十个行数不限、边界条件没测、只在它想象的那个浏览器里能跑的 polyfill,然后这个 polyfill 变成整个代码库里最难查的 bug 源。卡死上限,等于强制 agent 回到"要么用平台,要么显式条件加载"这两个选项上,不给它第三条自由发挥的路。
同一层里还有一类内容,是纯给 agent 看的:平台怪癖的备案——fetchLater() 的 64KB 载荷配额、macOS 上滚动条的行为差异(指南条目)。这些不是知识,是踩坑记录,人读一遍就记住了,agent 读一遍能省掉一次调试循环。这类条目在整个索引里占比不高,但我怀疑它对通过率的边际贡献是最高的,因为它恰好补的是"训练语料里没有、但真实浏览器里会发生"的那一小块。
检索层:BM25 和 embedding 同时上,不是选择困难
搜索在本地跑,用一个离线的 embedding 模型加 BM25,全程不发网络请求、不要 API key(repo 文档)。检索有两个命令:search 拿自然语言 query 匹到一条指南,retrieve 按标识符把指南正文取回来。
看到"embedding + BM25"就以为是没想清楚要哪个、干脆都上,这是想反了。这两个东西抓的是两类完全不同的 query,缺一类就有一半的请求落空:
BM25 抓的是名字。agent 经常处于"我知道有这么个 API、大概叫什么、但不确定签名和适用边界"的状态,这种 query 里带着精确 token(某个属性名、某个方法名、某个 HTTP 头),词法匹配一击即中,向量检索反而会因为语义泛化把它匹到隔壁去。
embedding 抓的是意图。开发者说的是"我想让这个弹窗关掉之后焦点回到触发它的按钮上",这句话里一个 API 名都没有,BM25 在这种 query 上几乎是随机命中,但它恰恰是无障碍那一支最需要被检索到的场景。
真正做事的时候,这两类 query 是交替出现的:先按意图搜一轮拿到候选,再按名字搜一轮确认细节。一次任务里 search 被调用十几次是常态,这就牵出了"本地"这个选择的真正理由——不是隐私(虽然也算),是延迟。每一次检索多 200 毫秒的网络往返,十几次就是两三秒,而 agent 的循环里每一步都在等这个结果,延迟会以乘法的方式吃掉整个任务的预算。
本地还有一层隐性好处,设计者未必是冲着它去的,但它确实成立:BM25 的打分是可解释的。agent 拿到检索结果的时候能看到匹配到了哪些词,这比拿到一个 0.83 的余弦相似度有用得多——后者对 agent 来说是一个无法验证的数字,前者它至少能判断"这条指南是不是在讲我要的东西"。让 agent 有能力怀疑检索结果,比让检索结果更准更重要,因为检索永远会错,而一个不会怀疑的 agent 会把错的那条当真理用到底。
接线层:205 个 token 才是这篇里最该盯的数字
两个可选的 skill pack:核心包约 205 tokens,Chrome 扩展包约 175 tokens(repo 文档)。
我看到这两个数字的时候停了一下。205 tokens 意味着这个 pack 里装不下任何一条指南的正文,它只能是索引加调用约定——"有这么个工具、这么调、什么时候该调"。指南正文永远留在磁盘上,按需 retrieve。
这是我要立的中心判断:给 agent 的知识包,正确形态不是知识本身,是指针。
反过来算一下就知道为什么。250 条特性、203 条用例,哪怕每条只写 80 个 token,全塞进 system prompt 也是三万六千 token 起。这个量级的常驻上下文会同时干三件坏事:把真正的任务上下文挤出去、让缓存命中率崩掉、以及最要命的——让 agent 在长上下文里对每一条的注意力都被稀释到几乎为零,塞了等于没塞,还占着地方。
205 tokens 是一种自律。它等于在说:我知道 agent 的上下文是预算,我不抢这笔预算,我只放一个指针进去,剩下的让检索去解决。
配套的还有 npm 包的设计:自包含、零额外依赖(repo 文档)。理由写得很直白,低延迟和供应链安全。零依赖这件事在 agent 工具这个语境下比对普通库更重要一层——agent 装东西是自动的,它不会像人一样看一眼依赖树,一个间接依赖被投毒,整条链上所有装过这个包的 agent 都在无人察觉的情况下跑过一遍。self-contained 在这里不是洁癖,是把攻击面压到一层的工程选择。
安装路径列了七种:Claude Code、OpenAI Codex、GitHub Copilot CLI、Grok Build CLI、Kimi Code、Google Antigravity、Vercel Skills CLI(repo 文档),加上 npx modern-web-guidance@latest install 的交互式安装。这个清单本身是一张 2026 年的地图——agent 的宿主环境在两年里裂成了至少七个互不兼容的生态,谁也没吃掉谁,所以分发层只能一家一家适配。
这里插一句可能不太受欢迎的判断:这七条适配不是七份工程量,是七份维护债。每一家的 skill 格式、加载时机、上下文预算都不一样,而它们的演进节奏不受这个项目控制。适配清单越长,这个仓库越像一份"所有 agent 宿主的兼容层",而兼容层是最容易被上游一次改动打断的活。
验证层:我喜欢它有 eval,也最不信它的数字
评测用的是一套挺完整的装置:Playwright grader 做浏览器里的真实判定,golden solution 当参考解,baseline 应用当起点,再加一个 calibration loop 调任务难度(repo 文档)。
有 grader、有 baseline、有校准环,这个配置在"知识包"这个品类里算是罕见的认真。大部分同类东西发出来的时候只有一句"我们试了一下效果不错"。
但我对它持保留,理由有三条,一条比一条实。
第一条,golden solution 的存在会奖励"和出题人写法一致",而不是"用了现代能力"。现代 Web 这一波特性里有一大堆场景是多种等价解都对的,position: sticky 是一个解,IntersectionObserver 加固定定位也是一个解,两个都能过功能测试。但只要 grader 是拿 golden solution 的产物做对照,第二条路就会被判低分。于是通过率这个指标测的到底是"现代能力用得好不好"还是"猜中了参考实现",是分不清的。我没看到 grader 的判定逻辑,只能按公开材料说话,这条保留意见我留着。
第二条,也是更要紧的:评测设计得越对口,数字越不能外推。
58% 到 94% 这种幅度,五个任务里翻盘四个,在"知识注入"类干预里是偏高的。但它高得合理——如果任务集本来就是从"平台能力可解"这个池子里挑的,而 agent 失败的原因本来就是不知道有这个能力,那么你把能力清单怼到它面前,它当然会做。这是对症下药,涨三十个点是正常的。
不正常的是拿这个数字去说"agent 的代码质量提升了三十六个点"。这两句话差得很远。前一句说的是:在一个被人工划定的、能力可解的、有参考解的任务集上,知识注入消除了信息差。后一句说的是:在开放代码库里,agent 现在写的东西更好了。前者这个项目证明了,后者它没证明,也没打算证明。
第三条是 calibration loop 本身。校准环的作用是让任务难度的分布稳定下来、让数字可比,这是好工程。但校准环也可以被用来把任务调到"装了包就能过、不装就过不了"的那个区间上——我不是说它这么干了,我是说这个装置天然有这个倾向,而外部的人没有手段区分这两种情况。看这类数字的正确姿势是看它的方向而不是幅度:方向是清楚的,装了指南的 agent 确实更少绕路;幅度是不可信的,因为任务集是被设计出来的。
一句话收口这一层:它有 eval,所以它比同类可信;它的 eval 是自建的 golden 任务集,所以它的数字不能拿去和别家比,也不能拿去估真实代码库里的收益。这两句话同时成立。
治理层:三家引擎加文档方一起签字,这不是礼节
这一层最容易被跳过,但它是整张地图上我认为最关键的一个坐标。
项目由 Chrome、Edge、Firefox 三家的团队,加上 MDN,以及社区贡献者共同 oversee(repo 说明)。三家引擎厂商在同一个知识仓库上签字,这件事在 Web 平台史上不常有——各家在特性推进上的节奏和优先级本来就不一致,能坐在一起写一份"给机器看的指南",前提是大家都认同一份共同的可发布标准。
这个前提具体落在 Baseline 数据上:指南接了 Baseline 的兼容性数据,agent 在给建议的时候能按当前的浏览器支持情况调整推荐(repo 文档)。Baseline 这个东西的价值完全取决于它的信誉来源——如果是单一厂商维护的,那它就是"某浏览器现在能跑"的别名,agent 学到的是厂商视角而不是平台现实。三家共同背书之后,Baseline 才勉强能当"现在可发布"的近似。
同样逻辑的另一面是 .mwgrc:Origin Trial 阶段的 API 和只有单一引擎实现的易变特性,默认全部锁住,开发者显式 opt-in 才解锁(repo 文档)。
这个默认值的方向是对的,而且比它看起来更重要。默认锁住意味着这份指南的默认立场是"只教跨引擎共识",把"厂商私有"当成需要签字的例外处理。反过来如果默认全开,agent 会在毫不知情的情况下把一堆只有一家能跑的 API 写进用户代码里,而用户根本不知道自己的项目已经被绑在某个引擎上了——这种伤害在代码 review 阶段几乎发现不了,因为代码看起来完全正常。
不过我在这里也得留一句:跨厂商治理解决的是"共识是什么",解决不了"共识多久更新一次"。这就要说到后面那块空着的地了。
先把已经梳过的压成一张表。这张表是这篇的图例,建议截图。
| 层 | 这一层的核心问题 | 这份 repo 的做法 | 走通的地方 | 付出的代价 |
|---|---|---|---|---|
| 知识层 | 平台现在有什么、什么场景用哪个 | 250 特性 + 203 用例双索引;加法增强与关键行为分级,fallback 卡 50 行 | 承认"现代"是分布不是布尔值,给了可执行的分层 | 条目数本身是负债,越多越难保鲜 |
| 检索层 | 几万 token 里怎么按需取一条 | 本地离线 embedding + BM25,无网络无 key | 词法与语义两类 query 都覆盖,延迟可控 | 检索会错,且 agent 不一定怀疑结果 |
| 接线层 | 怎么塞进上下文而不挤爆预算 | 核心 pack 约 205 tokens,只放指针;npm 包零依赖 | 把上下文当预算而不是仓库 | 七种宿主的适配是持续维护债 |
| 验证层 | 怎么证明真的变好了 | Playwright grader + golden solution + baseline + 校准环 | 有装置,方向可信 | 自建任务集,幅度不可外推 |
| 治理层 | 谁保证上面四层不腐坏 | 三家引擎 + MDN 共同 oversee,接 Baseline,私有特性默认锁 | 默认值站对了边 | 共识的更新周期不受单方控制 |
横向看一条规律:这五层里,越往下越少人做。装机量最大的永远是知识层,因为它最容易显得有产出——写 250 条指南,看上去就是 250 条成果;做检索、做接线、做 eval,产出的是一堆看不见的管道。但我这几年的观察是反过来的:知识层的边际收益最低,接线层的边际收益最高。多写十条指南,agent 可能一辈子检索不到;把 pack 从三千 token 压到两百,每一次调用都受益。
那张收藏数说明的事
7.4k stars、249 forks、32 watchers(repo 页面)。
star 和 fork 的比例不算什么,star 和 watcher 的比例有意思。七千多个收藏,三十二个订阅。翻译成人话:大家把这件事当路标存下来了,没几个人打算跟着它的 issue 走。
249 个 fork 也说明同一件事——几乎没人在改它,都在消费它。这不是一个社区共建项目的样子,这是一个分发工件的样子。而分发工件的成败标准和社区项目完全不同:社区项目靠活跃度活着,分发工件靠版本能不能对上活着。你装的是 2026 年 11 月的指南,你的项目跑在 2026 年 3 月的浏览器上,中间那八个月里被删掉的两个 API 不会有人提醒你。
这个观察直接指向我要落的判断。
落子:现在站在"文档变成工件"这一步,但工件的生命周期还没人管
摊开这张地图,我的落子是这样:这个领域现在站在一个很清楚的位置上——平台知识第一次被当成可分发的软件工件来处理。它有版本、有安装命令、有 token 预算、有 skill pack、有 telemetry、有 eval。这套配置在五年前是不可想象的,那时候"文档"就是一个网页,好坏全看你读得用不用心。
但它同时也暴露了这类工件的通病:造得好,养不起。
地图上还空着三块,一块一块说。
第一块,指南的时效性运维,这是最大的一块空洞。250 条特性会随着平台演进腐坏:被废弃的、语义变了的、从 Origin Trial 转正的、从共识退回单引擎的。calibration loop 校准的是任务难度,它管的是评测,不管内容生命周期。我在材料里看不到任何机制回答"谁负责把一条过时条目降级或删掉"这个问题。而这块空地是有毒的——一份 70% 准确的指南比没有指南更危险,因为它会被 agent 无条件信任。人读文档会带着怀疑,agent 不会。
第二块,负向索引。legacy-scan 命令能扫出代码库里可以被现代化的过时模式(repo 文档),这是往"识别旧"这个方向走了一步。但它和指南正文之间缺一层:为什么这个旧模式不该用。这两件事差得很远。你告诉 agent"别用 document.write",它会换成 innerHTML 拼字符串;你只有告诉它"别在解析阶段同步写 DOM,因为会阻塞解析",它才知道换哪个替代品、以及替代品解决的是不是同一个问题。只给禁令不给原理,agent 会做同构替换,换完还是错的。这块地图我看是空的。
第三块,跨宿主的可迁移性。适配列了七家,eval 只报了三个(Antigravity、Codex、Claude Code)。剩下四家上这套 pack 的实际效果,材料里没有。更根本的问题是:205 tokens 是给谁的分词器算的?同一个 skill pack 在不同宿主的上下文装配逻辑里,占的位置、被裁剪的优先级、和系统提示的相对权重都不一样。这块要么是没测,要么是测了没发,两种情况我都只能标"地图上正在长"。
方向上,下一站最可能从第一块和第二块的交叉口长出来:把指南做成可被机器验证的断言,而不是可被人阅读的散文。一条"position: sticky 在 X 场景下优于 scroll 监听"如果写成能被 grader 自动跑的形式,那它的腐坏就能被自动检测——平台一变,断言失败,条目自动降级。做不到这一步,250 条指南就只是 250 份需要人工巡检的资产,而人工巡检在开源项目里的半衰期你我都清楚。
这是我的判断,不是共识。不同意可以拿论文或者 PR 来挪这块坐标,地图我随时重画。
按规矩交代一下哪儿没画全
这篇有几个地方是故意留白的,说清楚比装看不见强。
多模态和可视化那一块我整支略过了。清单里没给,我也不打算凭印象补——补出来的坐标比空着更害人。
Chrome 扩展那个 175 tokens 的 pack 我只提了数字没展开。我的判断它是核心包的裁剪版,但没有证据,所以停在这里。
那个"11 月 8 号"的 eval 快照,我按最近一次公开数字处理,没有去推它的任务集构成、也没去核 grader 的具体判定逻辑——这两件事是它可信度的关键,但我手上只有快照,所以上面那些保留意见都停在"我没看到"这个层级,不是"我认定它有问题"。这个区别得守住。
还有一处得承认:写着写着推翻了自己一个早先的念头。我本来想说"七种宿主适配说明这个项目太重了",但摊完四层之后发现,重的是分发,轻的是内核——205 tokens 的 pack、离线检索、零依赖的 npm 包,这套东西的内核其实极轻。重的是它必须活在七个互不兼容的生态里,这不是它的问题,是 2026 年 agent 宿主生态的问题。这个坐标我改过来了。
最后:这类文章交稿那天就开始过时。250 条特性在涨,七种宿主在变,Baseline 数据一周一刷。这张图当导航可以,当定稿不行。
真正让我不太放心的是另一件事——如果一年之后,"指南的生命周期"和"负向索引"这两块还是空的,那么今天这 250 条精心写好的现代 Web 特性,会变成 250 条需要人来解释的负债。到那时候,通过率是 94% 还是 58%,就不太重要了。
