Repository navigation
[Decision] TranslationItemSchema still declares settings — the item door can override platform settings copy, and it is the stronger of the two doors the batch #132 ruling only half closed #19620
Description
Unblocked 2026-09-23T15:19Z: #19797 closed not_planned after the maintainer answered 「关闭」, recorded in 5796717943 as a waiver of ruling 5770445203 step ①. The earlier Blocked-by: line is retired; see the unblock comment.
Ruled: 5770445203 · letter B · 2026-09-22T02:40Z — batch #210 item 2; state pm:queue (domain:spec); three-step dispatch order in the ruling
维护者速读
应用的多语言文案有两扇门:文件门(打包进应用的翻译文件)和条目门(平台里按语言存的一条翻译记录)。
批 #132 item 2 已裁定:平台设置的文案归平台,应用的翻译文件里不准再写 settings——写了当场拒收。那条裁定正在 PR #19600 落地,管的是文件门。
现在测出来的事实是:条目门还开着,而且它比文件门更有力。文件门原本只能"补平台没写的空",条目门是真的能覆盖掉平台自己的设置文案——另存一层作者写的内容,读的时候合并,谁先谁后都一样。也就是说:裁定关掉了弱的那扇,强的那扇原样开着。
这不是"漏了一个键"这么简单:关掉它等于删掉一个已经发布、而且确实在工作的能力;留着它等于平台文案能被应用改写,而这正是上一条裁定判定不该发生的事。所以这一条得您单独裁,不能由席位顺手做掉。
请裁一个字母:A / B / C。
背景
Card #15178 的执行 PR #19600 正在落地批 #132 item 2 的裁定:翻译包类型一分为二,平台包保留 settings,每应用包不再声明它,应用包里写了 settings 在 parse 时响亮拒收。
实现该裁定的三轮里,dev 连续三轮把同一件事报为 open question,而且每一轮证据都更硬:TranslationItemSchema 仍然声明 settings,而条目门在语义上比文件门更强。席位判断这一条超出自己的权限——它删的是一个已声明、已发布的键——所以按 「碰迁移形状或删已发布能力也进决策箱」 立卡。
Governing text
Ruling-ref: 5653315643(card #15178 自己的评论线,os-tesla 记录,batch #132 item 2,维护者 verbatim 「同意」,2026-09-13T12:4xZ,对 1A·2(2)·3B·4是)。逐字引用,⛔ 不译:
packages/specTranslationDataSchemabecomes two exports (names per the file's convention): the platform bundle schema (eleven groups,settingsincluded) and the per-app bundle schema (settingsabsent, strict — an authoredsettingsin a per-app bundle is refused with a remedy saying it is platform-only). Every reader that consumes a per-app bundle types against the per-app schema.- The card's original "removal" disposition is struck:
settingsis a live platform key (pickSettingsEntry,i18n-resolver.ts:2305; consoleuseSettingsLabel).
TranslationDataSchema,而 TranslationItemSchema 是另一个独立声明(packages/spec/src/system/translation.zod.ts:1445)。⛔ 所以本卡 不是 已裁事项、⛔ 不作为执行卡呈递;但它也 不是无裁定的裸问题——item 2 的 struck 理由(「settings is a live platform key」)与本卡的 B 选项正面相关,必须一并读。
check-prior-rulings.mjs --card 15178 的机械半:
Prior rulings read: translation,settings,translationitemschema,per-app → 12 hits; ADR-0003 Decision §4, ADR-0007 Decision §4, ADR-0007 Decision §9, ADR-0045 Decision §3, ADR-0069 D6, ADR-0069 D7, ADR-0127 D6, ADR-0128 D1, ADR-0129 D3, ADR-0131 D13; thread: 1 ruling(s) (5653315643); repo: objectstack-ai/objectstack
distinct-term tier 1(只命中一个词,几乎都是 settings 的无关义项——ADR-0007 讲的是 sys_setting 的存储表)。⛔ 逐条读过,没有一条裁到条目门;它们出现在这一行是因为工装照实打印,不是因为它们管这件事。
协议声明
本卡 ⛔ 不改任何协议。它请求的是对一个已声明键的处置裁定。
前提,附 re-check 命令
git fetch origin main
git show origin/main:packages/spec/src/system/translation.zod.ts | sed -n '1445,1455p'
git show origin/main:packages/spec/src/system/translation.zod.ts | grep -n '^ settings:'
origin/main 上首手核过(2026-09-21T18:4xZ):
| 读数 | 值 |
|---|---|
TranslationItemSchema 声明处 |
translation.zod.ts:1445 |
它如何取得 settings |
:1451 的 ...translationDataShape();该 shape 定义在 :655,settings: 在 :1173 |
| 条目门是否显式邀请作者写它 | 是 —— 它自己的 alias 表(:1449)含 setting: 'settings',即把单数拼写也收进来 |
appTranslationDataShape() / platformSettingsShape() 在 main 上 |
不存在——它们是 PR #19600 引入的,⛔ 未合并 |
⛔ 未测,且不假装测过:条目门 settings 在生产数据里今天有没有人在用(需要平台侧 sys_metadata 的读数,本会话取不到);deepMerge(static, authored) 的覆盖语义是 dev 的实测报告,席位 ⛔ 未复现。
具体问题
裁定把文件门对 settings 关上了;条目门仍然声明 settings,而且是两扇门里唯一能真正覆盖平台设置文案的那扇。条目门怎么办?
一句话问题
安装一个应用,就能改掉平台自己的设置页面上的字——而我们上个月刚裁定过应用不该能这么做。
选项 × 真实代价表
| 选项 | 做什么 | 客户可感知的后果 |
|---|---|---|
| A | 条目门原样留着,另起一张卡单独议 | 今天什么都不变。应用仍可覆盖平台设置文案;下次有人撞上时我们还在同一个路口,只是又晚了一个版本 |
| B | 收窄条目门:settings 离开 TranslationItemSchema,活性账本那一行随之退役,D2 转换学会条目形状 |
平台设置文案从此只有平台能写。 |
| C | 明文裁定条目门故意留开,并要求文件门的拒收文案加一句说明 | 行为不变,但拒收信息从"平台专属"变成"这里不行,那里可以",作者不再被一句半真的话打发走 |
业务含义直译
- A = 「这事我们知道,先记着」。
- B = 「设置页面的字是平台的资产,应用不得改写」。
- C = 「应用可以改写平台设置文案,只是得走对门」。
四轴论证(业务立场)
① 项目长远合理性。 B 收缩特例:一个键一个归属,平台文案只有平台能写,契约增生减少。C 扩大特例:同一个键在两扇门上语义相反,而且这个"相反"必须永远写在文档里才不会被误读——这正是本卡原始误判(把"每应用零数据"读成"死键")的成因。A 既不收缩也不扩大,只是把账挂着;但挂着的账在这张卡上已经挂了三轮,每一轮都得重新解释一次。
② 实际业务拉动。 今天谁撞上:没有测到具名客户。⛔ 这是真空缺而不是零——生产数据读不到。拉动为零时默认 defer 或 remove,而 A 是 defer、B 是 remove;C 是 declare-and-maintain,是三者里唯一需要持续付出的那个。
③ 防 AI 犯错。 这一轴最响。今天的形状是:AI 写 metadata 时,文件门响亮拒绝、条目门静默接受——同一个键,两种待遇,而 AI 会把成功当作"我写对了"。B 让两扇门给同一个答案(闭合枚举优于自由结构)。C 至少让拒绝信息说实话,但仍要求 AI 记住哪扇门收哪扇门不收。A 把这个陷阱原样留着,而且留在一个我们刚刚花三轮盯过的位置上。
④ 创业阶段不扩散。 每一个已声明的键都是永久义务。C 把一个本来含糊的键升级成"故意声明并须维护"的键,义务最重。B 减一项义务。A 维持现状。
四棱行: ① B(收缩特例) · ② B 或 A(零拉动) · ③ B(两门同一答案) · ④ B(减义务)。
推荐 + 回退 + 置信缺口
推荐 B,先只按①得出:两年后这个平台该长成的样子是——文案的写入权按所有者划分,平台的归平台、应用的归应用,一个键不会因为走了不同的门就换主人。主流平台就是这么建模的:Salesforce 把标准标签与自定义标签分成两个命名空间,Odoo 的翻译按模块作用域切分(⛔ 均为参照记忆,本会话未实测)。
自检行:只看①选 B;②③④ 是否翻转:否。 ③ 与 ④ 同向加强 B;② 在 A 与 B 之间不作区分(零拉动两边都成立),⛔ 不足以翻字母。
回退项:A。 若维护者认为迁移风险(见下)现在不值得付,A 是安全的暂缓,且不产生新义务;⛔ 回退项不是 C——C 是三者里唯一增加永久义务的。
置信缺口(看不见什么):
- ⛔ 条目门
settings今天有没有生产用量,完全未测。 这是 B 唯一真正的风险:若有人在用,B 会静默丢掉他们写的字。⇒ 若裁 B,执行的第一步必须是先取这个读数,而不是先改 schema。 - ⛔
deepMerge(static, authored)的覆盖语义取自 dev 报告,席位未复现;若实际只能补空而不能覆盖,本卡的严重性下降一档,但 ③ 的 AI 陷阱不变。 - ⛔ 未查重即立卡(按常设规则,查重词在末尾)。
裁后执行段
- 裁 A ⇒ 本卡转
pm:on-hold,带机器可读Restart-when:行,条件写成条目门出现具名用量或下一次packages/spec翻译面改动触及该文件;⛔ 不留无唤醒机制的 hold。 - 裁 B ⇒ 本卡转
pm:queue进domain:spec队列,派发令三步定序:先取条目门settings的生产用量读数(无通道则立卡等读数,⛔ 不带着空白往下走),再写 ADR-0087 语义迁移条目与 D2 转换,最后才收窄 schema。Clause-②:accept-set 收窄 ⇒no;changeset 按发射窗口取minor,⛔ 不取major(见 decision(spec): 批 #65 明令的majorchangeset 在落地时测出不可执行 —— PR #19610 已按minor+ BREAKING banner 出,请追认或否决 #19611)。 - 裁 C ⇒ 本卡转
pm:queue,范围只有一句拒收文案外加一条 pin,⛔ 不碰 schema;同时把"两扇门语义相反"写进content/docs的对应页,否则 C 的代价会以误读的形式回来。
相关单与 PR
- Card [finding]
TranslationDataSchema.settingsis declared, read by the settings service, and extractable by nothing — registry-driven emitter, or removal from the per-app schema (ADR-0049) #15178 / PR feat(spec)!: split the translation bundle type —settingsis a platform group, not a per-app one (#15178) #19600 —— 落地批 🔗 Broken links detected in documentation #132 item 2 的文件门一半;⛔ 本卡不阻塞它,它也不阻塞本卡。 - Ruling
5653315643—— 本卡的Ruling-ref:。 - decision(spec): 批 #65 明令的
majorchangeset 在落地时测出不可执行 —— PR #19610 已按minor+ BREAKING banner 出,请追认或否决 #19611 —— 同一发射窗口的major/minor冲突,执行 B 时会撞上。
查重词
TranslationItemSchema · 条目门 settings · per-app translation bundle · deepMerge(static, authored) · batch #132 item 2
⛔ 按常设规则,立卡者不查重、只附词;查重由分诊席跑。
os-decision-facets
- ① 项目长远合理性:B 收缩特例(一键一归属),C 扩大特例(同键两门语义相反,须永久写在文档里)。
- ② 实际业务拉动:今天没有测到具名客户;⛔ 生产用量读不到,是真空缺不是零,零拉动下默认 defer(A)或 remove(B)。
- ③ 防 AI 犯错:今天文件门响亮拒绝、条目门静默接受,AI 会把静默成功读成"写对了";B 让两门给同一答案。
- ④ 创业阶段不扩散:C 把含糊的键升级为"声明并须维护",义务最重;B 减一项永久义务。
Prior rulings read: translation,settings,translationitemschema,per-app → 12 hits; ADR-0003 Decision §4, ADR-0007 Decision §4, ADR-0007 Decision §9, ADR-0045 Decision §3, ADR-0069 D6, ADR-0069 D7, ADR-0127 D6, ADR-0128 D1, ADR-0129 D3, ADR-0131 D13; thread: 1 ruling(s) (5653315643)
推荐:B。自检「只看①选 B;②③④ 是否翻转:否——③④ 同向加强,② 在 A/B 之间不作区分」。
置信缺口:⛔ 条目门 settings 的生产用量完全未测,这是 B 唯一的真风险;若裁 B,执行第一步是取该读数,不是改 schema。
立卡:domain:spec 执行席 2,session session_01UDXER3sdqfeVYpEWZs5mZx,2026-09-21T18:4xZ。dev 在 PR #19600 的三轮里连续提出本问题,每轮证据更硬;席位 ⛔ 不代答,按 「碰迁移形状或删已发布能力也进决策箱」 入箱。
Generated by Claude Code
Activity