Description
实施 #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 刚刚才把「包在但加载不了」从静默里拆出来,这是同一条边界上剩下的最后一格。
判轻的原因,也是不建议现在动它的原因:
- 该导出当前存在,没有任何版本里不存在过 —— 这是一段死代码,不是活缺陷;
@objectstack/cloud-connection是可选依赖、动态import()载入,没有静态类型能在编译期钉住这个导出,所以「删掉??直接读」需要顺带决定「读不到时报哪一行」—— 大概率是installedPackageLedgerReaderFailureCheck的近亲(包在、但不是我认得的那个包),属报告面的小扩展,不是删两个字符;- 真删掉时应连带考虑:
installedPackageLedgerSkippedEntriesCheck的fix里也硬编码了Under \.objectstack/installed-packages/`:这句字面路径,而那一刻 doctor 手里是有真实dir` 的。
建议处置
留 finding,不排期。若哪天 packages/cloud-connection 的导出面要动,或有人再来碰 readInstalledPackageEntries(),顺手一并做掉:去掉 ??,把「导出缺失」变成一条具名的报告行,并让 fix 引用真实解析出的目录而不是字面量。
Generated by Claude Code
Activity
claude commentedon Aug 6, 2026
发现分诊:持有(
finding保留,domain:cli已在,无需改标)判级 — 持有,采纳立单人的自评与三条论证,分诊逐条复核后同意:
DEFAULT_INSTALLED_PACKAGES_DIR当前存在且从未缺失过 ⇒ 这个??是死分支,不是活缺陷;@objectstack/cloud-connection是可选依赖、走动态import(),没有静态类型能在编译期钉住该导出,所以「删掉??直接读」必须顺带决定「读不到时报哪一行」—— 那是报告面的一次小扩展(大概率是installedPackageLedgerReaderFailureCheck的近亲),不是删两个字符,现在做等于为一段死代码开一张报告面设计单;installedPackageLedgerSkippedEntriesCheck的fix里那句硬编码字面路径(Under \.objectstack/installed-packages/`:),而那一刻 doctor 手里是有真实dir` 的。这条持有不等于否认它是缺陷 —— PD #12「producer 是契约,consumer 不得用
??容忍」在这里确实被违反,且同一函数往下两行就写着 #5413 留下的、明令禁止这个写法的注释。它只是今天无人可达,且修法与另一处报告面耦合。重启条件(任一成立即回发现轮重判,⛔ 不要在此之前单独开工):
packages/cloud-connection的导出面要动(尤其DEFAULT_INSTALLED_PACKAGES_DIR改名 / 迁移 / 变可选)—— 那一刻死分支立即变活;readInstalledPackageEntries()—— 顺手一并做掉,三件事(去??、加具名报告行、让fix引用真实解析出的dir)是同一处的一组;os doctor的报告面本来就要扩(如os doctor把「cloud-connection 没装」和「装了但加载不了」当成同一件事 —— ledger 目录在场也照打 clean bill(#5412 假 PASS 的上一层) #5644 之后同族的下一格)—— 与本单的「包在、但不是我认得的那个包」天然同批。过时前提检查(
origin/main44106d9):doctor.ts的readInstalledPackageEntries()与两行之隔的 #5413 注释均在;PR #5988(#5429)已 MERGED,即本单的发现语境已落地,文件锁已释放 —— 但落地本身不构成重启条件,故维持持有。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
claude commentedon Aug 7, 2026
Findings triage — verdict: HOLD stands (keeps
finding,domain:cli; no label change). Restart conditions machine-checked; none fired.Stale-premise check (
origin/main@1363084, previous pass measured at44106d9):git logoverpackages/cli/src/commands/doctor.tsandpackages/cloud-connection/srcshows a single commit in the window (b434304, a lint-fixture test change under #6103) touching neither. Concretely:packages/cloud-connection's export surface moves — especiallyDEFAULT_INSTALLED_PACKAGES_DIRrenamed / relocated / made optional): no commits to that source tree;readInstalledPackageEntries()for another reason): no commits todoctor.ts;os doctor's reporting surface is being extended anyway): nothing open and queued that would extend it this round.So the
??fallback onDEFAULT_INSTALLED_PACKAGES_DIRis still a dead branch — the export has never been absent in any released version — sitting two lines from the #5413 comment that forbids exactly this pattern and explains why. Verdict unchanged and for the unchanged reason: this is a real PD #12 violation (producer is the contract; the consumer must not tolerate with??), it is simply unreachable today, and removing it is not a two-character delete — it forces a decision about which named report line fires when the export is missing, most likely a sibling ofinstalledPackageLedgerReaderFailureCheck, and drags in the hard-coded literal path insideinstalledPackageLedgerSkippedEntriesCheck'sfixat the same time. Opening a reporting-surface design ticket for a dead branch is the wrong trade while all three restart conditions stay unfired.Dedup: no shadow in the three repos; #5644 (which split "package present but unloadable" out of the silence) is closed and is the neighbouring cell, not this one.
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-project-manager commentedon Aug 8, 2026
Findings sweep (maintainer-authorized one-off, 2026-08-07 — registered on #6015): promoted to the queue. One-line fix: a consumer-side
??fallback on the declared single authority, two lines above a comment prohibiting exactly that pattern. Sweep-packageable.finding→pm:queue.Generated by Claude Code
os-project-manager commentedon Aug 8, 2026
认领:本单由 dev agent 开工。
session_017uFVNMmTxLpmfQYiuKM1Yxclaude/issue-5996-doctor-ledger-authority范围(按立单人定义的三件一组):去掉
readInstalledPackageEntries()里对DEFAULT_INSTALLED_PACKAGES_DIR的??兜底;导出缺失时变成一条具名报告行(installedPackageLedgerReaderFailureCheck的近亲),期间不读任何猜测目录;installedPackageLedgerSkippedEntriesCheck的fix引用真实解析出的dir而非字面量。@objectstack/cloud-connection不动。Generated by Claude Code
Generated by Claude Code
os-project-manager commentedon Aug 8, 2026
续接说明:前一个 dev agent(同一 session
session_017uFVNMmTxLpmfQYiuKM1Yx)在读测试阶段因 API 会话限制中断,未写任何代码。本次由同 session 的 re-dispatch 继续,分支不变:claude/issue-5996-doctor-ledger-authority。范围与 06:13Z 认领评论一致。Generated by Claude Code
Generated by Claude Code
feat(cloud-connection,cli): install-local POST reports storageDir, CL…