Skip to content

[finding] enableOnInstall is declared in three schemas and honoured by no handler — an author sets it and the runtime silently ignores it #18605

Description

@os-litant

os-decision-facets

维护者速读 —— 这是一张执行卡,不是未裁卡

Ruling-ref: 5724940709(批次 #153 item 5 · letter 1,维护者「其他同意」)。⛔ 本块不重新呈递这张卡为未裁,方向早已裁定。回箱的唯一原因是:裁决的处方按字面写不出来,而这一点是实测出来的,不是意见。

裁决 letter 1 的第一颗子弹已经兑现(安装门按 enableOnInstall ?? true 写 registry 行的 enabled),由 PR #18752 落地并带钉子,本轮对着已合并 diff 重取确认过。⇒ 卡面原话「honoured by no handler」在今天的 main 上对权威那道门而言已经是假的。PR #19130(draft · mergeable_state: clean · 全绿)只带第二颗子弹。

要你裁的那一件事:裁决写「a copy of the request key is folded to a reference」。最自然的写法 enableOnInstall: PackageInstallRequestSchema.shape.enableOnInstall 在这个方向上不存在 —— 权威在模块图里位于两份副本之上,引用即成环,而且不是 lazySchema 能吸收的环:在 OS_EAGER_SCHEMAS=1(gen:schema / check:authorable-surface 跑的模式)下工厂体在加载期求值,环就死。两侧都带对照实测:

结果
对照 · kernel(未改) exit 0
处理 · kernel(照裁决写法) exit 1 Cannot access 'InstalledPackageSchema' before initialization
对照 · marketplace(未改) exit 0
处理 · marketplace(同写法) exit 1 Cannot access 'ArtifactReferenceSchema' before initialization

⚠️ 危险的那一半:默认 lazy 模式下两个处理都加载正常 —— 运行时是绿的,死的是生成器。

⛔ 裁决的两个括号猜测双双被证伪,原样记下不绕开:kernel 那处不是「a stored-row field」(存储行字段是同文件里的 InstalledPackage.enabled,另一个键);marketplace 那处不是「a marketplace listing attribute」(MarketplaceListingSchema 根本不带它,它坐在 install 请求上,挨着 listingId)。

选项

做什么 客户/产品可感知的后果
A(#19130 现在的形状) 权威留在 package-api.zod.ts 自己的字面量,副本靠一份机械钉子跨矩阵(缺省 / false / true / 字符串 / null)锁死,任一格不一致即红 三处声明的描述文字说清谁是权威、谁是副本、谁是另一回事;键、默认值、接受集一个字节不动。副本仍是两份字面量,靠钉子维持一致
B 把键的字面量下沉到两份副本之下的模块,权威反过来 import 它 全仓只剩一份 Zod 字面量,钉子可退休;⛔ 但声明搬出了 package-api.zod.ts —— 而那正是裁决点名的「one authority」所在文件,⇒ 这改的是裁决自己的措辞

业务含义直译:A = 「权威是那扇门的合同,副本贴上标签并上锁」;B = 「权威是那个键本身,文件位置让位给唯一性」。

四棱

① 项目长远合理性:A 让特例 +1(一份钉子要长期维护),B 让特例 −1(一份字面量,无可漂移),但 B 动了裁决点名的文件归属 ⇒ 长远看 B 更小,代价是改措辞
② 实际业务拉动:今天撞上的人 = 任何读参考页想知道三行 enableOnInstall 哪一行才作数的作者(含 AI);两案同等消除该困惑,⇒ 此轴不分胜负
③ 防 AI 犯错:A 的错法是两份字面量漂移 —— 但钉子会响亮拒绝;B 无可漂移。⛔ 两案都不会静默,⇒ B 略优,A 不失格
④ 创业阶段不扩散:两案都不新增已声明的键;A 新增一份测试义务,B 新增一次模块搬迁。⇒ A 的永久义务略多

Prior rulings read: enableoninstall,one-authority,import-cycle,declare-or-retire → 0 hits; none; thread: 1 ruling(s) (5724940709)

推荐:A —— 只看①本该选 B(唯一字面量长远更干净),但 ⛔ 本席不替你改裁决的措辞:「one authority = package-api.zod.ts」是你亲口裁的,而 B 恰恰把声明搬出那个文件。A 是不改变裁决任何说法的那一个,且已经绿着躺在 PR #19130 里。
自检:只看①选 B;②③④ 是否翻转:是 —— ④(搬迁是一次性、钉子是永久义务)本该加固 B,但它们都敌不过「不擅自改裁决措辞」这条,所以字母停在 A,理由是权限归属而非技术优劣。
置信缺口:⛔ 本席没有测过 B 那条路 —— 下沉模块之后 check:export-originscheck:declaration-map 与参考页锚点会不会动,NOT MEASURED。裁 B 就等于同时授权一次未测量的搬迁。

第二问,与上面独立,也需要你一句话:副本自己的那道门 ObjectStackProtocol.installPackage 至今不兑现这个键。让它兑现是裁决没点名的那道门上的新运行时行为 —— 今天安全(现存调用方无一设置该键,⇒ 行为零变化),⛔ 但不是这张卡能自行授权的。


Split out of #18058's dispatch round (report 5711356635). ⛔ Not folded into that card, which is now a decision card on a different question.

Measured

enableOnInstall is declared in three places:

  • packages/spec/src/api/package-api.zod.ts:261
  • packages/spec/src/kernel/package-registry.zod.ts:283
  • packages/spec/src/marketplace/marketplace.zod.ts:494

It is sent by the first-party SDK (packages/client/src/index.ts:2525) and pinned by packages/client/src/client.test.ts:2666.

It is read by no server-side handler — zero hits across packages/runtime, packages/metadata-protocol and packages/objectql.

⚠️ Line numbers rot. Re-derive every one of them before acting, and re-establish the zero with a same-subject control that hits (a sibling option key the handlers DO read).

Why it is class (c)

This is the metadata-authoring trap in its purest form: a key stored by one party and re-authored by another, declared on the published surface, accepted at the door, pinned by the first-party client — and dropped on the floor. An author (human or AI) reads the schema, sets the option, sees it accepted, and gets nothing. ⛔ Nothing fails loudly.

The project's standing position is that a declaration the runtime does not honour is an implementation gap: enforce it or retire it, and ⛔ never narrow at the consumer.

⛔ Note on scope

Three declarations for one key is itself suspicious — see the sibling note on near-duplicate install-request declarations in #18058's report. Whoever takes this should decide whether one authority survives, ⛔ but should not silently unify three published declarations without a ruling.

Dedupe words: enableOnInstall inert option, declared three places honoured none, packages.install client SDK, install door silently ignores, ADR-0049 enforce or remove enableOnInstall.


Blocked-by: #18058

分诊席 R+293 落此行(SKILL.md :112 / :137 的机器可 grep 反向索引)。现读:PR #18752(#18058 的交付,assignee os-litant)是开着的草稿(state=open · merged=false · draft=true),它碰本卡三个声明面里的一个(packages/spec/src/api/package-api.zod.ts);另两个(marketplace.zod.ts · package-registry.zod.ts)在它的 15 个文件之外。⇒ ① pm:blocked 让选择期跳过本卡,消掉「下一个读板面的席位派出一个重复」的风险;② #18058 关闭之时正是那份 merged diff 存在之时,而对着它重取本卡范围的请求那一刻才第一次可做。理由见 5725404365。


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions