Skip to content

docs(ci): 去掉 check-lint-coverage.mjs 头注里的 object-ui 规则点数,并把守卫扩到该文件 (#3279) - #3784

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-3279-lint-coverage-header
Aug 8, 2026
Merged

docs(ci): 去掉 check-lint-coverage.mjs 头注里的 object-ui 规则点数,并把守卫扩到该文件 (#3279)#3784
yinlianghui merged 1 commit into
mainfrom
claude/issue-3279-lint-coverage-header

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#3279

前提复核(先于实施)

issue 的前提在 origin/main 上原样成立,两处读数都显式取自 origin/main:

$ git show origin/main:scripts/check-lint-coverage.mjs | sed -n '11,14p'
* The stakes are concrete: `eslint.config.js` sets three `object-ui/*` rules to
* `error` specifically so a new violation fails CI (ADR-0054 Phase 5, #2879,
* and the objectql.ts type-discipline ratchet). Those ratchets are worthless in
* a package that never runs ESLint.
$ git grep -n 'object-ui/' origin/main -- eslint.config.js
origin/main:eslint.config.js:59: 'object-ui/no-synthetic-event-trigger': 'error',
origin/main:eslint.config.js:65: 'object-ui/no-try-catch-around-hook': 'error',
origin/main:eslint.config.js:98: 'object-ui/no-dynamic-import-in-test-hook': 'error',
origin/main:eslint.config.js:111: 'object-ui/no-inline-spec-config': 'error',

注释说 three,配置里是四条,漏的正是 no-dynamic-import-in-test-hook —— 与 #3261 当初漏掉的是同一条。这不是「将来会错」,是今天就错。

改动一:头注去数字化

#3261 / PR #3273lint.yml 里确立的写法改写:不点数、不在括号里列来源,改成永真表述。这段话本身正确的主张一字未动 —— 没有 lint script 的包不是干净而是没被 lint 过,ratchet 在那里一文不值。

并按 lint.yml 的同构做法补一段,写下为什么这里刻意不点数也不列举、以及唯一诚实的清单是 eslint.config.js 本身(每条规则自己的 ADR/issue 就写在它旁边的注释里)。lint.yml 的对应措辞是「eslint.config.js is the single list of those rules, and this comment deliberately neither counts them nor names them」,本 PR 的措辞与之同构。

改动二:守卫扫描面参数化(issue 正文授权,按判断做了)

scripts/__tests__/lint-workflow.test.ts(#3273 新增)的两条断言 —— 不得点数、不得按名列举 —— 此前只扫 lint.yml,看不见这第二份副本;所以它是被人顺手读到(#3274)而不是被门禁挡下来的。现在扫描面变成一个 prose surface 列表,lint.ymlcheck-lint-coverage.mjs 各出一项,判定逻辑原样复用(点数正则、规则名比对、求值后 flat config 的读法都没动),只按 surface 取注释:

  • 注释块提取按标记参数化:YAML 的 # 行首标记与 docblock 的星号行首标记共用一个 unwrap(block, marker),折行还原照旧 —— lint.yml 的头部注释说「三条 object-ui/* 规则设成 error」,实际已经是四条 #3261 那句话正是断在 "sets three" 与 "object-ui/* rules" 之间,任何跨行匹配都必须先还原折行。
  • 点数正则只读各文件的解释性注释,不读整个文件。 对这个脚本这条限定是必需的而非洁癖:它的 Known gaps 注释合法地在数(「the last two …, 14 errors」),整文件扫描会把它当成规则条数误报出来。这一点写进了测试头注,免得下一个人以为是漏扫。
  • 规则名比对仍读整个文件 —— 规则名出现在这两个文件的任何位置,都是 eslint.config.js 的第二份拷贝。

原来那条「eslint.config.js 确实还有 object-ui/* 规则设成 error」的前提断言现在被两份注释共用,单独提成一个 describe;lint.yml 专属的两条触发器断言(仍跑 pull_request、ignore 列表不吞 .ts/.tsx)留在原处,逻辑未动。

验证

守卫测试(从仓库根跑,invocation guard 拒绝 package-cwd):

$ flock -w 7200 /tmp/os-heavy-verify.lock -c 'NODE_OPTIONS=--max-old-space-size=4096 \
pnpm vitest run scripts/__tests__/lint-workflow.test.ts --maxWorkers=2'
RUN v4.1.10 /home/user/objectui-3279
Test Files 1 passed (1)
Tests 7 passed (7)

7 条 = 2 条守卫 × 2 个 surface + 1 条共用前提 + 2 条 lint.yml 触发器(扩面前为 5 条)。

变异自证(方向在跑之前就定了:应当变红,且只有新增的那一条红)。把 origin/main 的点数句写回 mjs 头注:

 FAIL scripts/__tests__/lint-workflow.test.ts > scripts/check-lint-coverage.mjs — the
object-ui/* ratchet prose (objectui#3261, #3279) > never hand-counts the
object-ui/* rules again
AssertionError: scripts/check-lint-coverage.mjs's explanatory comment counts the
`object-ui/*` error rules again:
- "three `object-ui"
...
Tests 1 failed | 6 passed (7)

命中项正是 "three `object-ui";规则名那条仍绿 —— 原句列举的是 ADR/issue 而非规则名,所以只有点数这一条该红,与预期一致。变异已 git checkout -- 还原,还原后重跑 7 passed,不入 commit

其余门禁:

$ pnpm type-check:scripts # tsc -p tsconfig.scripts.json,无输出即通过
$ node scripts/check-lint-coverage.mjs
✅ lint coverage: 45/45 packages linted, 0 with outstanding errors (0 total).
$ node scripts/check-control-bytes.mjs
✅ check-control-bytes: OK (scanned 3718 tracked text file(s); skipped 85 binary).
$ grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]' scripts/check-lint-coverage.mjs \
scripts/__tests__/lint-workflow.test.ts # 零命中

控制字节除了跑仓库门禁,另对两个改动文件单独自扫了一次(门禁的扫描面之外仍可能藏字节)。

不带 changeset 的依据

scripts/** 不在 scripts/check-changeset-presence.mjs 的守卫面内 —— 那道门禁只看 .changeset/config.jsonfixed 组里各包的 src 目录。先例也一致:PR #3273(lint.yml + 本测试文件)与 PR #3278(lint.yml + 本脚本)改的正是同一批文件,均未带 changeset。这次改的是内部脚本的注释与一个仓库根测试,没有发布产物变化。

顺带记录(不在本 PR 内)

content/docs/guide/ci-cd-pipeline.md:201-202 括号里还有同一事实的第四份手抄清单(而且点了一条规则名)。它今天恰好是完整的,但没有任何门禁钉它,且把它加进本 PR 的 surface 列表会当场变红 —— 需要先做一个文档措辞取舍。已按 Prime Directive #10 单独记为 #3782(finding 标签,未指派),不夹带进本 PR。


Generated by Claude Code

…3279)
`scripts/check-lint-coverage.mjs` 的文件头 docblock 说 `eslint.config.js` 把
**three** 条 `object-ui/*` 规则设成了 `error`,并在括号里手工列举来源(ADR-0054
Phase 5、#2879、objectql.ts ratchet)。这是 #3261 从 `.github/workflows/lint.yml`
里删掉的那句话的逐字副本,连漏掉的规则都是同一条:配置里设成 `error` 的
`object-ui/*` 规则实际有四条 —— L59 no-synthetic-event-trigger、L65
no-try-catch-around-hook、L98 no-dynamic-import-in-test-hook、L111
no-inline-spec-config,漏的是第三条。#3261 只改了 workflow,这份副本原样留着,
所以它今天就是错的,而不是"将来会错"。
## 头注改法
按 #3261 / PR #3273 在 `lint.yml` 里确立的写法去数字化:不点数、不在括号里列
来源,改成「every `object-ui/*` rule that `eslint.config.js` sets to `error`」
这种永真表述。这段话本身正确的主张一字未动 —— 没有 `lint` script 的包不是干净
而是没被 lint 过,ratchet 在那里一文不值。同时按 `lint.yml` 的同构做法补一段,
说明为什么这里刻意不点数也不列举,以及唯一诚实的清单是 `eslint.config.js`
本身(每条规则自己的 ADR/issue 就写在它旁边的注释里)。
## 守卫扩面
`scripts/__tests__/lint-workflow.test.ts`(#3273 新增)的两条断言 —— 不得点数、
不得按名列举 —— 此前只扫 `lint.yml`,看不见这第二份副本,所以它是被人顺手读到
(#3274)而不是被门禁挡下来的。现在把扫描面参数化成一个 prose surface 列表,
`lint.yml` 与 `check-lint-coverage.mjs` 各出一项,判定逻辑(点数正则、规则名
比对)原样复用,只是按 surface 取注释:
- 注释块提取按标记参数化 —— YAML 的 `#` 行首标记与 docblock 的星号行首标记共用
一个 `unwrap(block, marker)`,`\s+` 折行还原照旧,因为 #3261 那句话正是断在
"sets three" 与 "`object-ui/*` rules" 之间的。
- 点数正则只读各文件的解释性注释,不读整个文件。对这个脚本这条限定是必需的而
非洁癖:它的 `Known gaps` 注释合法地在数**包**(「the last two …, 14 errors」),
整文件扫描会把它当成规则条数报出来。
- 规则名比对仍读整个文件 —— 规则名出现在这两个文件的任何位置,都是
`eslint.config.js` 的第二份拷贝。
原来那条「eslint.config.js 确实还有 `object-ui/*` 规则设成 error」的前提断言
现在被两份注释共用,单独提成一个 describe;`lint.yml` 专属的两条触发器断言
(仍跑 pull_request、ignore 列表不吞 .ts/.tsx)留在原处不动。
## 验证
- `grep -n 'object-ui/' eslint.config.js` 确认四条 error 规则现状。
- 仓库根 `pnpm vitest run scripts/__tests__/lint-workflow.test.ts`:7 passed
(扩面前 5:2 条守卫 × 2 个 surface + 1 前提 + 2 触发器)。
- `pnpm type-check:scripts` 干净通过。
- `node scripts/check-control-bytes.mjs` OK;改动文件另做一次
`grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]'` 自扫,零控制字节。
- 变异自证:把原来那句点数写回 mjs 头注,`check-lint-coverage.mjs` 的
never-hand-counts 一条变红(counted 报出 "three `object-ui"),其余六条仍绿;
变异不入 commit。
不带 changeset:`scripts/**` 不在 `check-changeset-presence.mjs` 的守卫面
(`<pkg>/src/**`,取自 `.changeset/config.json` 的 fixed 组)之内,且先例
PR #3273 / #3278 改的正是这两个文件、均未带 changeset。
@vercel

vercelBot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredAug 8, 2026 3:21pm

Request Review

@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

✅ 验收通过(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt)—— undraft + auto-merge。

git 实物核验(c468ff54d vs origin/main):

衍生:dev 立的 #3782(ci-cd-pipeline.md 同一事实第四份手抄,含规则名)为 finding 待分诊 —— A/B 取舍(删括号入守卫 vs 钉名断言)留给判级,本 PR 不夹带是正确边界。


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review August 8, 2026 15:29
@yinlianghui
yinlianghui added this pull request to the merge queueAug 8, 2026
Merged via the queue into main with commit 4028adfAug 8, 2026
18 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-3279-lint-coverage-header branch August 8, 2026 15:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

check-lint-coverage.mjs 的文件头注释是 #3261 那个「三条 object-ui/* 规则」错数的第三份副本(配置里是四条)

2 participants

@yinlianghui@claude