fix(cli): ledger 可读性提为 posture 无关的独立健康检查,D5e 只留 unique-scope 判断 (#5429) - #5988
Merged
baozhoutao merged 1 commit intoAug 6, 2026
Merged
Conversation
…ancy posture (#5429) The three rows that say `os doctor` could not read `.objectstack/installed-packages/` — the directory could not be enumerated (#5412), a file inside it would not parse (#5413), the ledger reader would not load (#5644) — were all built inside the ADR-0120 D5e unique-scope advisory, whose entry condition is `postureGatesGlobalUniques(posture)`. That is true only for `isolated`, so under `single` and `group` `readInstalledPackageEntries()` was never called and doctor said nothing at all. `OS_TENANCY_POSTURE` unset resolves to `single`, so the blind posture was the default one. Per the maintainer's 2026-08-06 ruling (option A), ledger readability is now its own posture-independent check under the `Installed packages` name, read once per run, outside the posture gate and outside the config-analysis block. The D5e block keeps the unique-scope judgment alone and consumes the same reading, so one bad ledger produces one row under `isolated` too; an incomplete reading still withholds `✓ Unique scope` there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DWUR56YsttL5sTF72Q75TQ
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
Contributor
Author
|
越界发现,已另开、未修:#5996(观察类, Generated by Claude Code Generated by Claude Code |
baozhoutao
marked this pull request as ready for review
August 6, 2026 14:12
baozhoutao
deleted the
claude/issue-5429-doctor-ledger-posture-independent
branch
August 6, 2026 14:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5429
按维护者 2026-08-06 裁定的 方向 A 实施:把「installed-package ledger 可读性」提成一条 posture 无关的独立健康检查,ADR-0120 D5e 块只保留 unique-scope 判断本身。
前提复核(以 origin/main
5582e1821为准)前提成立,且比 issue 描述的更宽:
os doctor的 installed-package ledger 读取 catch 把「损坏」和「没装」当成同一件事 —— D5e 建议因此静默少报,并打出「clean」 #5412 目录级、LocalManifestSource.list()静默丢弃损坏的 ledger 条目 —— 已装应用在 boot 时消失、在控制台列表里缺席,且没有任何一条日志 #5413 条目级)之外,os doctor把「cloud-connection 没装」和「装了但加载不了」当成同一件事 —— ledger 目录在场也照打 clean bill(#5412 假 PASS 的上一层) #5644 之后又多了第三条(reader 级Could not load the installed-package ledger reader,2026-08-05 22:45 UTC 合并,早于裁决评论)。三条同属「ledger 读不动」这一族,同样锁在 D5e 块里,同样只在isolated下存在 —— 裁决口径「无条件执行readInstalledPackageEntries()可读性判定」对三条一体适用,只留一条在门内会把同一族切成两半。resolveTenancyPosture()在OS_TENANCY_POSTURE未设、多租户未开时返回single(packages/types/src/env.ts:161)。也就是说开箱默认的 posture 恰好就是失明的那个 —— 不是「换个 posture 才踩到」,是「不设变量就踩到」。改了什么
os doctor只读一次,读在run()里、posture 门之外、configExists()块之外。installedPackageLedgerChecks(reading)把这一次读的结果翻成 0~2 行(reader 级与另外两级互斥),推进既有results表,由同一个renderHealthCheckResult渲染。configExists():ledger 可读性读的是一个目录,不依赖 config。留在 config 块里等于把 posture 门换成 config 门 —— 同一种沉默换个条件,os doctor对非法OS_TENANCY_POSTURE退出码 0 并报告「环境功能正常」—— 抛错被 config 分析的宽 catch 吞成一句「Could not load config」 #5382 当初给 posture reader 做的加宽正是同一理由。findUnscopedGlobalUniques()不再自己读 ledger、也不再回传三个失败事实,改为接收已读好的entries。没有第二次读、没有第二个报告者,isolated下同一个坏 ledger 只可能出现一次。✓ Unique scope。 那行成功语是对 advisory 两个半边的断言,ledger 半边只要没读全(目录读不动 / 条目读不动 / reader 没加载),它就不能印 ——os doctor的 installed-package ledger 读取 catch 把「损坏」和「没装」当成同一件事 —— D5e 建议因此静默少报,并打出「clean」 #5412/LocalManifestSource.list()静默丢弃损坏的 ledger 条目 —— 已装应用在 boot 时消失、在控制台列表里缺席,且没有任何一条日志 #5413/os doctor把「cloud-connection 没装」和「装了但加载不了」当成同一件事 —— ledger 目录在场也照打 clean bill(#5412 假 PASS 的上一层) #5644 在这里活下来的部分只剩这一条。Unique scope→Installed packages。 原名在「只可能出现在 D5e 块内」时是对的(让操作者扫的那一行在场而不是缺席);检查一旦 posture 无关,single/group下压根没有 unique-scope 检查,用它命名就是在报一个当下不存在的检查。message 的括号同步去掉for installation-wide uniques四个词,其余原文一字未动(installed packages NOT checked保留,操作者 grep 的就是它)。Unique scope这个名字仍在,仍归 D5e 的 unique-scope 判定独有。readInstalledPackageEntries()里path.join(cwd, mod.DEFAULT_INSTALLED_PACKAGES_DIR ?? …)挪进try。它不再跑在别人的try里了,一个非字符串导出以前会被 config 的catch吞成「Could not load config for analysis」的误报,现在只能是它自己那一行。与 boot 侧
rehydrate()warn 的分工(裁决要求写明)两路各自成立,互不替代,本 PR 未动 runtime/metadata-protocol 一行:
rehydrate()每条损坏条目warnos doctor的Installed packages行isolated下 D5e 少看了一半boot 侧本来就与 posture 无关,所以操作者不是全无信号 —— 缺的是诊断命令这一路。两面口径不一致正是 #4801 / cloud#1020 那一族;#5429 前它们确实不一致。
验证 / 反向验证
方向事先预测,两个扰动分别打在两条验收线上,结果与预测一致:
single/group各 3 条 + 未设 posture + 无 config),失败输出显示整张报告里没有任何 ledger 行 —— 不是文案不符,是这条检查根本没发生。改完后同样 8 条转绿。isolated去重钉子红。实测reports an unreadable DIRECTORY exactly once/reports a corrupt ENTRY exactly once两条转红(出现次数 1 变 2)。这一条是特意做的:去重钉子在 main 上本来就是绿的(今天只有一个报告者),不证伪一次就分不清「钉住了」和「恰好为空所以过」—— PR fix(lint): 收敛 validate-expressions / validate-security-posture 的 spec 不声明键??别名读法 (#5017) #5046 记过这个坑。验收对照
single/group(以及未设 posture、无 config)下,目录级与条目级各有其行 ——describe.each(BLIND_POSTURES)六条 + 两条单独用例;isolated下同一个坏 ledger 只报一次 —— 出现次数计数钉住,且✓ Unique scope仍被扣住;--verbose);@objectstack/clipatch;doctor-ledger-read-failure.test.ts(#5412/#5413/#5644 的既有钉子)全部保留、逐条复核:除 name 列 5 处随改名更新外,isolated下的报告面一字未变 —— 这一点是刻意的,新检查可达不等于旧报告可以漂。一处需要下游知道的事
已合并待发布的 changeset
quiet-ledgers-speak-up.md里写着「os doctorreports unparseable entries as aUnique scopewarning row」。发布时该句已被本 PR 取代,我没有去改别人的 changeset,而是在本 PR 的 changeset 里显式写明「supersedes」,由发布流程合并两条时择取。🤖 Generated with Claude Code
https://claude.ai/code/session_01DWUR56YsttL5sTF72Q75TQ
Generated by Claude Code