Skip to content

os doctor?? 兜底 DEFAULT_INSTALLED_PACKAGES_DIR —— 同一函数里两行之隔,一行明令禁止这个写法 #5996

Description

@baozhoutao

实施 #5429(ledger 可读性提为 posture 无关的独立检查,PR #5988)时核验发现。观察类,今日无人踩到,记录以免下次有人照抄。

事实

packages/cli/src/commands/doctor.ts,readInstalledPackageEntries() 里:

const dir = path.join(cwd, mod.DEFAULT_INSTALLED_PACKAGES_DIR ?? '.objectstack/installed-packages');

DEFAULT_INSTALLED_PACKAGES_DIR@objectstack/cloud-connection 的导出,也就是「ledger 目录叫什么」这件事的唯一权威。这里对它做了一次消费端 ?? 兜底。

同一个函数往下两行,读 list() 的返回时写着(#5413 留下的注释,原文):

// #5413 — read BOTH halves of the listing. Destructured with no `??`
// fallback on purpose: `list()` declares this shape, and a tolerant read
// here would be the exact consumer-side accommodation that let the silence
// live in the first place.
const { entries, skipped } = new mod.LocalManifestSource(dir).list();

同一个文件、同一个函数、同一个被读的模块,一处禁止 ?? 兜底并写明了理由,另一处正在用。

为什么这可能是个缺陷(以及为什么判为观察类)

Prime Directive #12:producer 是契约,consumer 不得用 ?? 容忍。这个 ?? 的语义是「模块加载成功了但没有这个导出」—— 真发生时,doctor 会安静地去读一个硬编码路径,而不是报告「我读 ledger 的那个包不认得 ledger 目录了」。运行时(rehydrate() 侧)读的仍是权威常量,于是两侧看的是两个目录、都不作声。#5644 刚刚才把「包在但加载不了」从静默里拆出来,这是同一条边界上剩下的最后一格。

判轻的原因,也是不建议现在动它的原因:

  1. 该导出当前存在,没有任何版本里不存在过 —— 这是一段死代码,不是活缺陷;
  2. @objectstack/cloud-connection 是可选依赖、动态 import() 载入,没有静态类型能在编译期钉住这个导出,所以「删掉 ?? 直接读」需要顺带决定「读不到时报哪一行」—— 大概率是 installedPackageLedgerReaderFailureCheck 的近亲(包在、但不是我认得的那个包),属报告面的小扩展,不是删两个字符;
  3. 真删掉时应连带考虑:installedPackageLedgerSkippedEntriesCheckfix 里也硬编码了 Under \.objectstack/installed-packages/`:这句字面路径,而那一刻 doctor 手里是有真实dir` 的。

建议处置

finding,不排期。若哪天 packages/cloud-connection 的导出面要动,或有人再来碰 readInstalledPackageEntries(),顺手一并做掉:去掉 ??,把「导出缺失」变成一条具名的报告行,并让 fix 引用真实解析出的目录而不是字面量。


Generated by Claude Code

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions