test(scripts): 把 restatement 从记账升级成断言——每条 README peer 重述逐字钉住自家清单 (#3717) - #3751
Merged
Merged
Conversation
…ifest (#3717) #3710 ruling B was "keep and pin": narrow the prose, then ADD A TEST asserting each README's peer restatement equals its own `peerDependencies` verbatim. Only the first half landed — the `why` strings kept saying "re-verify with a one-line read of the manifest", i.e. a human. This replaces that sentence with a run. For every `restatement` entry the assertion resolves the literal back to its line via the same scan the ratchet judges, parses the dep and the FULL range off that line, reads the manifest beside the README, and demands the ranges match. 12 comparisons today: 11 bullet-spelled READMEs plus react-runtime's prose sentence. The hole this closes is structural, not laziness. The inventory key is the matched literal and a match stops at the FIRST version token, so a key recorded for `^18.0.0 || ^19.0.0` is only `^18.0.0`. Widen a manifest to a third arm and the literal, the entry and both directions of the ratchet are untouched and green over a README that now misstates the range. Reverse-verified in that exact direction: perturbing a README's SECOND arm fails this assertion alone (1 failed, 9 passed, both ratchet tests green), and perturbing the manifest instead fails it identically — #3690's shape, which the ratchet could only record as `stale` after a human noticed. Two boundaries, each pinned by its own test: - Peer lines only. plugin-chatbot restates the MAJOR of its own dependencies["@ai-sdk/react"], not a peer range, so it carries `notAPeerRestatement` and is skipped BY NAME — one rule judges one kind of fact. The opt-out is not an escape hatch: deleting it turns the assertion red ("NOTHING was compared"), and attaching it to a live peer entry turns the closure test red as a stale opt-out suppressing a real check. Both verified. - Equality is verbatim up to whitespace INSIDE the range, because react-runtime's README writes `react >= 18` where its manifest writes `>=18` — the same single comparator, so byte-strict equality would demand a cosmetic edit or lost coverage in exchange for nothing. Every drift shape survives the normalisation and is pinned negatively. No changeset: scripts-test-only, same as PR #3711 which added this file. Out-of-scope finding filed as #3750 — the peer BLOCK is wider than the ledger, and 9 of its other 16 lines disagree with their manifests, including a live drift (`components` README says tailwindcss `^3.0.0`, manifest says `^4.2.1`) that neither the ratchet nor this assertion can see. No README or manifest touched here. Fixes #3717 Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Collaborator
Author
|
补一条零命中纪律的反向验证(派发要求「字面量找不到就该红,但别和现有棘轮重复报」,这是那条的证据): 预判:删掉 实测: 如预判:红的是棘轮那条,新断言没有跟着报第二遍。这也是断言经 已 Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3717
#3710 裁决 B 是「保留并钉住」两步:先收窄散文,再加一条测试断言每个 README 的 peer 重述与本包
peerDependencies逐字一致。只落地了前半——ledger 里那句why一直写着 "re-verify with a one-line read of the manifest",也就是靠人。本 PR 用一次运行替掉那句话。做了什么
对每条
restatement条目:经棘轮用的同一份扫描结果(flaggedClaims)把字面量还原成行号 → 从该行解析 dep 与完整区间 → 读 README 旁边的packages/NAME/package.json→ 要求两个区间相等。今天实比 12 行(11 个 bullet 拼写的 README + react-runtime 那句散文)。只改一个文件:
scripts/__tests__/doc-version-claims.test.ts。没有碰任何 README 或清单。KNOWN_CLAIMS 的行改动被压到最小(只给 plugin-chatbot 加了一个字段、共享why常量改了一句话),以便 #3715(create-plugin.mdx route B,已按同文件纪律排在本单之后)后续合并干净。它补的是棘轮结构上看不见的洞
清单键就是被匹配的字面量,而匹配停在第一个版本 token:
^18.0.0 || ^19.0.0这行记下来的键只有^18.0.0。所以把清单加宽出第三个 arm(或收掉一个),字面量没变、条目没变、棘轮两个方向全绿,而 README 已经在说错话。#3690 就是这个形状,当时只能靠人普查发现、门禁只能事后记成stale。反向验证(先预判方向,再跑)
^19.0.0→^20.0.0(packages/layout/README.md)1 failed | 9 passed,红的只有新断言:packages/layout/README.md:20 react: README says "^18.0.0 || ^20.0.0", manifest says "^18.0.0 || ^19.0.0"packages/auth的 peer react 加|| ^20.0.0)1 failed | 9 passed:packages/auth/README.md:23 react: README says "^18.0.0 || ^19.0.0", manifest says "^18.0.0 || ^19.0.0 || ^20.0.0"notAPeerRestatementnotAPeerRestatement挂到一条活的 peer 条目(layout)上the opt-out is stale and is suppressing a real check两次改动均已
git checkout --还原,git status只剩测试文件一个。第一行是关键:棘轮全绿而新断言单独红,说明补的洞是真的,不是把同一件事测两遍。两条边界,各有自己的钉子
dependencies["@ai-sdk/react"]的主版本(v4对^4.0.47),既不是 peer 也不逐字,故加notAPeerRestatement字段指名跳过并保留kind: 'restatement'。字段带的是理由字符串而非布尔,豁免和条目一样要写清楚;断言不允许「豁免」与「真被覆盖」并存,所以将来新增一条没有 peer 锚的 restatement 不能靠「解析不到」悄悄溜出覆盖面——它会红到有人把那句话写下来。顺带说明:那一条的why里「人工复核」一句故意保留,因为它恰好是机器唯一没覆盖到的地方,留着才是实话。packages/react-runtime/README.md写react >= 18,清单写>=18——同一个比较符、npm 解析完全相同,这里没有任何漂移。若按字节严格比,只会在一棵什么都没错的树上标红,而能回答这个红的只有两条:为门禁改一处纯装饰的拼写,或把这条判成不覆盖(丢掉真覆盖面)——两条都是白付代价。归一化只丢空白,所以要抓的形状全都活着:主版本变、||arm 增删、^变~、上界消失,一律仍不相等,并且以反向断言钉住(否则一个悄悄长成「连操作符也剥掉」的归一化,会让整条断言变空转而其余测试全绿)。另外
RANGE_OPENS(区间必须以操作符或数字开头)是承重的:没有它,bullet 形状会把任何以 backtick 标识符开头的列表项吞进来(- \useChat()` returns a stream会被读成 dep =useChat()`),然后清单查不到而报红——为错误的理由报红,会教会所有人忽略这道门禁。验证
控制字节另做了超出门禁扫描面的自查(
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]'),无命中。注意本仓的门禁叫check-control-bytes.mjs,没有check-nul-bytes.mjs(那是 objectstack 仓的名字)。无 changeset
纯
scripts/测试改动,不属于任何发布包、消费者装不到。与 PR #3711(新建本文件)、PR #3726(文档 + ledger)一致均不带 changeset;只有 PR #3727 因改了已发布清单才写。越界发现:#3750
全量普查 README 的 Peer Dependencies 区块时发现:28 行 peer 陈述里只有 12 行是 ledger 登记的
react行(本断言正好覆盖这 12 行),其余 16 行中9 行与自家清单不符,包括一处用户今天就会踩的实错——packages/components/README.md:41写tailwindcss ^3.0.0,清单是^4.2.1。棘轮看不见它是因为TOOLCHAIN里的\bTailwind\b在tailwindcss上没有词边界;本断言看不见它是因为断言由 ledger 驱动。修法要动文档/清单并加宽门禁,两头都在本单文件面之外,故据实另立 #3750 未认领,不在本 PR 修。另可对照 #3741(react-runtime 清单侧
>=18无上界):它一旦被收窄,本断言会立刻红到那份 README 跟上——正是这条断言要买的东西。Generated by Claude Code