Uh oh!
There was an error while loading. Please reload this page.
fix(metadata-admin): 审计面板锁状态列补齐中文,词表键绑 lockState union (#5004) - #5023
Conversation
…ckState (#5004) `CONSOLE_VALUE_ZH.lock` held a draft-status vocabulary (`draft`/`locked`/ `published`/`none`) rather than the ADR-0010 §3.6 four-state lock, so the alignment with `MetadataAuditEntry.lockState` was total rather than partial: the three entries matched no value the field can hold; `none` — the only match — is excluded by the call site's own guard, which renders an em dash for an unlocked row; and the three values that do reach the helper (`no-overlay`/`no-delete`/`full`) had no entry. Hit rate 0/3, so a zh-CN admin read bare English in a column headed 锁状态. Adds the three missing labels and, following #4982's `LAYER_SCOPE_ZH`, binds the key set to the producer's own union via `Record<NonNullable<MetadataAuditEntry['lockState']>, string>` — a fifth lock state now fails `type-check` naming the missing label instead of shipping a raw token. The union is this repo's hand-written one in `@object-ui/data-objectstack`; whether `@objectstack/spec` should own this vocabulary is left open rather than answered here. The three draft-status entries are deleted after measuring: repo-wide, `translateConsoleValue('lock', …)` has exactly one call site and `CONSOLE_VALUE_ZH` is module-private, so nothing else could read them. `none` is kept so the record stays complete over the producer's type instead of tracking a guard in another file. Unchanged on purpose: `translateConsoleValue` stays zh-only, and the em-dash branch for `none`/`null` renders exactly as before. Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
commented
Aug 17, 2026
PM 验收 ✅ ACCEPT(#5004,批次 21 首单) 实物核验(merge-base CI 亲读:20/20 check runs completed,零失败(两项 path-filter skipped 计绿)。 键集选型采信:选含 'none' 的完整 反向验证读数:变异①刻意不套用 PR5005 的「tsc 红 vitest 绿」先例并说明了为什么(本 PR 写了编译期钉的运行时孪生,两侧都该动)—— 同族先例被引用而不被机械照搬,实测 tsc TS2741 + vitest 2 红精确命中;变异②的「tsc 绿是最有信息量的一半 —— 正是缺陷能出厂的原因」读数到位,死条目复活即红的钉子在位。 open question 处置:四态锁词表的 spec 归属(A 长期 / B 中途站)已按围栏立 #5024(finding,observation-class,两份手写副本 + ResourceEditPage 无穷尽兜底横幅全部 file:line 在案)交维护者,未自行实施 —— 边界守住。undraft + auto-merge(squash)。 Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5004
症状
zh-CN 管理员打开元数据编辑页的「审计」面板,凡是带锁的审计行,标题为「锁状态」的那一列显示裸英文
no-overlay/no-delete/full。根因:不是漏译,是整张词表串了行
CONSOLE_VALUE_ZH.lock里装的是一套草稿状态词表(draft/locked/published/none),而它服务的字段是 ADR-0010 §3.6 的四态锁MetadataAuditEntry.lockState。三者对齐后是完全错位,不是部分缺失:draft/locked/publishedlockState的任何可能值noneAuditPanel.tsx:191的ev.lockState && ev.lockState !== 'none'为假时走—支路,永远不会问它no-overlay/no-delete/fulltranslateConsoleValue的三个值,一条条目都没有命中率 0/3。
translateConsoleValue把value声明为string,所以类型检查对此毫无意见 —— 与 #4982 里overlayScope被声明成string的同一个原因。改动
补三条中文:
no-overlay→ 禁止编辑、no-delete→ 禁止删除、full→ 完全锁定。用词跟随读者在同一屏上会读到的锁定横幅句子(engine.edit.lockNoOverlay不可编辑 /lockNoDelete不可删除 /lockFull不可编辑或删除),压缩成适合窄列的状态名。键绑生产者的 union(仿 objectui: MetadataLayered.overlayScope 词表与 spec 漂移(注释声称 organization/environment/package,生产者只发 org/env),LayeredDiff 把该原值当徽标直出 #4982 / PR fix(metadata-admin): overlayScope 收窄为 spec 派生词表,层徽标过 i18n #5005 落地的
LAYER_SCOPE_ZH):新表LOCK_STATE_ZH的键类型是Record< NonNullable< MetadataAuditEntry['lockState'] >, string >。今后 union 加第五态时,这条记录编译不过并点名缺失的那个标签,而不是让界面静默漏出裸英文。键集选的是完整的
NonNullable(含none),不是按调用点现实剔除none后的Exclude< …, 'none' >。理由两条:一是与 PR fix(metadata-admin): overlayScope 收窄为 spec 派生词表,层徽标过 i18n #5005 已落地的形状一致;二是词表的完备性应当对着生产者的类型,而不是对着另一个文件里 JSX 三元表达式中的一个!==—— 那个守卫是「未锁定显示破折号而非文字」的展示选择,它哪天改了,词表不该需要跟着改。none因此保留一条,并在 docblock 里写明它目前经唯一调用点不可达。删掉三条死条目(先量后删,这正是本卡记录的陷阱):
translateConsoleValue('lock'→ 仅 1 个调用点(AuditPanel.tsx:193);CONSOLE_VALUE_ZH是模块私有const,全仓只有两处引用:定义处与translateConsoleValue内那一次查表;translateConsoleValue调用点的 group 实参全是字面量('op'/'outcome'/'lock'/'layer'),没有变量 group 能间接读到;MetadataLayered['lock'](同一套四态锁的另一个字段)由ResourceEditPage.tsx:1935-1937渲染,走的是t('engine.edit.lockFull'…)整句字符串,不读这张词表。结论:确无第二调用点,三条删除。键绑定本身也强制了这一点 —— 多余键会触发 excess property check。
刻意未改
translateConsoleValue仍是 zh-only(其余九个 locale pack 返回原值是既有设计);是否扩出去是独立决定,不搭车。none/null的—支路渲染与改前逐字一致。@objectstack/spec拥有这套锁词表:本仓今天手写这个 union,按分诊围栏不伸手 spec,问题留给维护者(见下)。测试
新增
AuditPanel.lockState.test.tsx(9 例)。状态清单不是自由手写的,而是用satisfies Record< LockState, 0 >校验过的键集反推 —— 双向穷尽(少一个键报缺失,改名报多余),所以清单无法与 union 漂移。这里没有@objectstack/spec的z.enum可在运行时读.options(union 是本仓手写的),故用satisfies技巧代替 #4982 的.options数组。反向验证(先书面预判,再变异)
变异①:从
LOCK_STATE_ZH删掉'no-delete'一条。 预判 tsc 红 + vitest 红(2 例)。这里刻意不同于 PR #5005 变异① 的「tsc 红、vitest 绿」先例:本 PR 的测试里写了那个编译期钉的运行时孪生(穷尽循环 + 逐状态渲染例),所以两侧都该动。实测与预判一致:变异②:把
i18n.ts整体退回origin/main(保留测试)。 预判 vitest 红 5 例、tsc 绿。tsc 绿是这里最有信息量的一半:改前那个状态编译得干干净净,这正是缺陷能出厂的原因。实测与预判一致,红的是穷尽例 + 三个渲染例 + 死条目例,绿的 4 例恰好是三条不回归钉(none破折号、null破折号、override 星号)与 en-US 原值钉:留给维护者的开放问题(未自行决定)
这套四态锁词表是否应归
@objectstack/spec拥有?现状是MetadataLayered['lock']与MetadataAuditEntry['lockState']在本仓packages/data-objectstack/src/metadata-client.ts手写两遍同一个 union(第 298 行与第 340 行,字面重复)。若 spec 出z.enum,两处可派生、词表键可像LAYER_SCOPE_ZH一样绑到 spec,跨仓漂移也一并关闭。本 PR 按围栏不伸手 spec,绑到本仓 union;如维护者认可归属 spec,这里的键类型换一行即可。Generated by Claude Code