Repository navigation
chore(ui-i18n): the call-site key gate refuses a lazy-namespace key read outside its namespace's frame - #30853
Merged
Merged
Conversation
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxDqYaHT7GBjAY9FzB
…-site gate Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxDqYaHT7GBjAY9FzB
… scripts type-check Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxDqYaHT7GBjAY9FzB
Contributor
Author
|
domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp 维护者速读
席位核对 — ACCEPT · head f4a22f9
|
2 tasks
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.
Requested by Tesla · project thread
Fixes #30645
Clause-②: no
Metadata-protocol: none
维护者速读
check:i18n-keys)新增第 9 类namespace-key-outside-frame:只存在于懒加载命名空间(目前是 marketplace)里的 key,如果在该命名空间的「框」目录之外被t()读取,门禁直接变红。marketplacenamespace #30640 把大部分marketplace.*文案移进了懒加载包,只有两个市场页面会拉取它;别的页面(比如 Studio、Setup)一旦复用其中某个 key,用户会看到原始 key,而原有的各道 i18n 门禁都把命名空间当成常驻包,全部是绿的。ui/scripts/check-i18n-call-site-keys.mjs的PACK_NAMESPACE_FRAMES(命名空间与它的框声明在同一张表里)、analyze()里的judgeFrame三处调用点,以及测试文件里新的 describe。pnpm --dir ui check:i18n-keys,预期退出 0,并打印一行Namespace frames: 1 pack-shaped namespace(s) — packages/i18n/src/namespaces/marketplace/ read 183 time(s) inside its frame。What changes
ui/scripts/check-i18n-call-site-keys.mjs:PACK_NAMESPACE_FRAMESmaps the namespace directory to the source directories that render under the gate fetching it (marketplace:packages/app-shell/src/console/marketplace/).PACK_NAMESPACE_DIRSis derived from its keys, so every existing reader (collectEnKeys,check-i18n-en-drift.mjs,check-i18n-dead-keys.mjs) reads the same list, and a namespace cannot be added without its frame.analyze()throws on a namespace declared with an empty frame.collectEnKeysalso returnsnamespaceOf: which namespace each namespace-defined leaf lives in.namespace-key-outside-frame, HARD from day one (no baseline). A call site outside a namespace's frame is refused when it asks for a key that only that namespace answers: a literal key (plural forms included: refused when every form that resolves is namespace-only), areturnObjectssubtree, or a template head with no resident leaf under it. A key the resident pack answers is never refused.Namespace frames:with how many call-site keys each frame reads, and fails as a collapsed scan when a declared namespace's frame reads none.HINTSentry and its own failure paragraph for the class.Division of labour with
marketplaceNamespaceBoundary.test.ts(unchanged): this gate judges every file OUTSIDE the frame directories; the boundary test keeps judging the files INSIDEconsole/marketplace/that a page outside the frame imports.Tests
ui/scripts/__tests__/check-i18n-call-site-keys.test.ts, new describea key only a namespace defines is refused outside its frame (objectstack#30645), 10 cases on synthetic repos and the real tree:packages/studio/src/page.tsxturns the class red, naming the namespace;framedReads; a resident key outside the frame is silent;returnObjectssubtree;billing) declared with its own frame is judged with no other change;PACK_NAMESPACE_DIRSequals the frame map's keys, every frame non-empty);Real-tree probe (one-off, file removed afterwards, not committed): a file
packages/app-shell/src/console/Probe30645.tsxcallingt('marketplace.title')madenode scripts/check-i18n-call-site-keys.mjsexit 1 with[namespace-key-outside-frame] marketplace.title; with the file removed it exits 0.Acceptance notes
t()as a variable. That is the same blind spot class 1 (missing-key) has; the boundary test's literal scan still reads such spellings insideconsole/marketplace/.Verification
Head
f4a22f9b, treeobjectstack-ai/objectstack.Derived gates: 20 of 20 exit 0
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 20 lines from the 2 changed files. All 20 exited 0, among thempnpm --dir ui exec vitest run scripts/(under the verify lock: Test Files 170 passed, 2 skipped; Tests 4989 passed, 2 skipped;VERDICT command-exit 0).dispatch-gates --ranprinted20 derived famil(ies) accounted for — 20 run, 0 NOT-MEASURED.Run beyond the derivation, all exit 0 on the final head:
node scripts/check-sdui-manifest.mjs,pnpm --dir ui check:i18n-keys,pnpm --dir ui check:new-line-citations,pnpm --dir ui run type-check:scripts. The scripts type-check was red once on an earlier head (the new return field and the frame map were untyped in JSDoc) and is green onf4a22f9b.Not run locally
marketplaceNamespaceBoundary.test.tsis unchanged. Locally it stops at import (@objectstack/spec/uihas no dist in this worktree), so it is NOT MEASURED here and Test UI runs it.No published package changes (
ui/scripts/belongs to the privateobject-ui-monoreporoot), henceskip-changeset.Generated by Claude Code