fix(devx): check:i18n 把 unknown-authoring-key 判为失败,不再只判 bundle drift (#4804) - #4847
Merged
xuyushun441-sys merged 1 commit intoAug 3, 2026
Merged
Conversation
…t on bundle drift (#4804) The #4167 unknown-authoring-key lint saw all nine offending `scripts/i18n-extract.config.ts` files that #4736 later cleaned. It printed `stack.name: 'name' is not a declared stack key, so its value is dropped at load` once per package, on every run — inside a fully green `check:i18n`, so it read as noise nine times running. #4736 removed the symptom; nothing stopped the tenth copy. Two things made the warning unenforceable, and both are fixed here: 1. The lint writes to **stderr**, and the gate used `execFileSync`, which surfaces stderr only on the throw path. On a zero-exit run the stream went straight to the terminal — seen by nobody, judged by nothing. Now `spawnSync`, so both streams are read on both paths; stderr lines that are not the lint signature are re-emitted, so capturing costs no diagnostics. 2. The gate judged bundle drift only. It now also fails on the unknown-authoring-key signature, in its own verdict. Option A per the issue: the failure lands in the gate script. `os i18n extract` keeps its exit code (B would write an internal hygiene rule into the public CLI contract) and `ObjectStackDefinitionSchema` stays non-strict (C would silence the lint itself — see `metadata-authoring-lint.ts`). The two verdicts never merge. Drift keeps its section and its remedy (`--write`); the new class gets its own, naming the package, the config path, the key, and the consequence that matters — the value is dropped at load, so whatever it was meant to configure is not in effect and never was. Regenerating bundles does not fix it, and the message says so. Coverage needs no manifest: `findConfigs` walks `packages/`, so the tenth config is gated the day it lands. Proven able to go red, not merely observed green — the failure mode of #4690. `--self-test` (now wired into `check:i18n` ahead of the real run) drives both classifiers over recorded CLI output, asserts the drift text produces no key finding and the key text produces no drift finding, and pins the exact ffab803^ stderr line so a reworded message breaks the test rather than disarming the gate. A reworded signature that still matches the weak pattern fails as `unattributed` instead of passing. Reverse-verified against the nine configs restored from ffab803^: all nine reported, exit 1. Fixes #4804 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018iARDqtrhQgz6fVHDeDkbQ
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
xuyushun441-sys
marked this pull request as ready for review
August 3, 2026 10:13
xuyushun441-sys
deleted the
claude/issue-4804-i18n-unknown-key-gate-fails
branch
August 3, 2026 10:25
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 #4804
采纳 issue 裁定的方案 A:失败判定落在
scripts/check-i18n-bundles.mjs。不碰os i18n extract的公开退出码(B),不碰ObjectStackDefinitionSchema(C)。packages/**一行未改。问题不是「lint 没看见」,是「看见了也拦不住」
#4167 的 unknown-authoring-key lint 把九处全看见了。它在每次运行里逐包打印:
但它出现在一次全绿的
check:i18n里,于是被人眼过滤了九次。#4736 清的是症状。实施中发现了一个 issue 正文没写到、但决定成败的事实:这条 lint 写的是 stderr,不是 stdout(
defineStack走console.warn)。而门禁用的是execFileSync,它只在抛错路径上交出 stderr —— 退出码为 0 时那条流直接透传到终端,没有任何代码读过它。所以当时不是「读了但没判」,是压根没读。这也解释了为什么它能安稳待在绿色运行里。两处都修了:
execFileSync→spawnSync,两条路径都拿到两条流。不属于 lint 签名的 stderr 行原样回吐,捕获不吞任何诊断信息。覆盖面不需要维护清单:
findConfigs遍历packages/,第十份配置落地当天就在保护里。两类失败不合并(验收第 3 条)
drift 保留原有小节和原有解法(
--write);新的一类自己一节,指名哪个包、哪个配置文件、哪个键,以及那个真正要紧的后果 —— 它在 load 时被丢弃,所以它想配置的东西从来没生效过。重新生成 bundle 修不好它,错误信息也这么写了。逐包状态行还带← UNDECLARED KEY标记,扫一眼就能分辨,不用读到底下的报告。两类同时命中时的真实输出(把 plugin-audit 的配置还原到
ffab8033b^再破坏它的一份 bundle):反向验证(验收第 4 条)—— 这条是本 PR 的核心证据
一个只在 main 上绿过的门禁,和一个什么都匹配不到的门禁无法区分(#4690 就是那样:无 MANIFEST 时静默 skip 退 0,永远不可能红)。所以两头都跑了。
红:把九份配置还原到
ffab8033b^(#4803 删掉name:之前的那个 commit),pnpm check:i18n退出 1,九处全部报出:顺带纠正 issue 正文的一处描述:dedupe 是按进程内的 path 去重的,而门禁对每份配置各起一个进程,所以九个包实实在在打印九条(上面这次「合并前」运行,以及用未改动的旧门禁跑同一份语料,都能看到九条 —— 旧门禁看到九条仍然退出 0)。判定挂在每一份被发现的配置上,不是只看全局出现过一次。
绿:当前
main(即本分支的基线),干净、无新增噪音(验收第 2 条):测试:
--self-test(仓库既有惯例)按
check:route-envelope/check:published-files等的惯例加了--self-test,并接进check:i18n(先自检、再真跑),所以「门禁能不能红」这件事本身进了 CI,而不是只在这个 PR 的描述里被断言过一次。它不需要 build、不需要 CLI —— 纯粹拿录下来的 CLI 输出喂两个分类器。用例覆盖:ffab8033b^上那条真实 stderr,断言解析出path/key/surface/ hint。CLI 措辞一改,自检先红,而不是门禁悄悄失灵;os compile的 stdout 变体(•项目符号、无defineStack:前缀);unattributed桶(明说「解析不出是哪个键」),绝不退化成「干净」 —— 这条直接冲 check:react-declaration-parity 是唯一没接进任何 workflow 的源码审计门禁,且无 MANIFEST 时静默 skip 退出 0 —— 它现在永远不可能红 #4690 那个形状去的;另外验过:
--write路径仍然把 40 份 bundle 逐字节重新生成(git status对所有src/translations/**干净);单独破坏一份 bundle 时 drift 判定行为不变(验收第 3 条);npx eslint scripts/check-i18n-bundles.mjs干净;check:release-notes/check:doc-authoring/check:nul-bytes均绿。gate 语义变宽这件事,写在了脚本自己身上(A 的诚实代价)
脚本头部注释重写了:开篇就列出它现在判的两类,以及各自的修法;并写明为什么这一类落在门禁层而不是 CLI 退出码。
check:i18n此前只判 drift —— 有人被它拦下时,不该需要读源码才知道它现在管什么。最终成功行也改成all bundles in sync, no undeclared authoring keys。修法始终指向生产者:把键从配置里删掉。如果那个键是真需要,就在
packages/spec里郑重地声明它 —— 不靠消费侧 fallback,也不靠把 schema 改 strict 来堵嘴(那会连 lint 本身一起静音,metadata-authoring-lint.ts里写明了)。改动面
scripts/check-i18n-bundles.mjspackage.json(check:i18n前置一次--self-test).changeset/check-i18n-fails-on-undeclared-authoring-key.md(不发布任何包)未触碰
packages/**、content/docs/releases/,以及本会话另两位 dev 在飞的scripts/check-durability-degradation-log-level.mjs、scripts/durability-degradation.baseline.json、scripts/bump-objectui.sh。🤖 Generated with Claude Code
https://claude.ai/code/session_018iARDqtrhQgz6fVHDeDkbQ
Generated by Claude Code