Skip to content

fix(cli): ledger 可读性提为 posture 无关的独立健康检查,D5e 只留 unique-scope 判断 (#5429) - #5988

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5429-doctor-ledger-posture-independent
Aug 6, 2026
Merged

fix(cli): ledger 可读性提为 posture 无关的独立健康检查,D5e 只留 unique-scope 判断 (#5429)#5988
baozhoutao merged 1 commit into
mainfrom
claude/issue-5429-doctor-ledger-posture-independent

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #5429

按维护者 2026-08-06 裁定的 方向 A 实施:把「installed-package ledger 可读性」提成一条 posture 无关的独立健康检查,ADR-0120 D5e 块只保留 unique-scope 判断本身。

前提复核(以 origin/main 5582e1821 为准)

前提成立,且比 issue 描述的更宽:

改了什么

  1. 可读性检查独立、无条件执行。 ledger 每次 os doctor 只读一次,读在 run() 里、posture 门之外、configExists() 块之外。installedPackageLedgerChecks(reading) 把这一次读的结果翻成 0~2 行(reader 级与另外两级互斥),推进既有 results 表,由同一个 renderHealthCheckResult 渲染。
  2. 去重是结构性的,不是标志位。 findUnscopedGlobalUniques() 不再自己读 ledger、也不再回传三个失败事实,改为接收已读好的 entries。没有第二次读、没有第二个报告者,isolated 下同一个坏 ledger 只可能出现一次。
  3. D5e 保留的唯一后果:仍然扣住 ✓ 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 在这里活下来的部分只剩这一条。
  4. name 列改名 Unique scopeInstalled packages 原名在「只可能出现在 D5e 块内」时是对的(让操作者扫的那一行在场而不是缺席);检查一旦 posture 无关,single/group 下压根没有 unique-scope 检查,用它命名就是在报一个当下不存在的检查。message 的括号同步去掉 for installation-wide uniques 四个词,其余原文一字未动(installed packages NOT checked 保留,操作者 grep 的就是它)。Unique scope 这个名字仍在,仍归 D5e 的 unique-scope 判定独有。
  5. 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() 每条损坏条目 warn os doctorInstalled packages
何时 启动那一刻,被动 人主动问「这环境哪里不对」,可以从不启动
说什么 我刚刚丢掉了这个包 这个 ledger 现在读不动 / 这些文件读不动,连带 isolated 下 D5e 少看了一半

boot 侧本来就与 posture 无关,所以操作者不是全无信号 —— 缺的是诊断命令这一路。两面口径不一致正是 #4801 / cloud#1020 那一族;#5429 前它们确实不一致。

验证 / 反向验证

方向事先预测,两个扰动分别打在两条验收线上,结果与预测一致:

  • 扰动 A(把门装回去):预测 blind-posture 钉子红。实测在未改动的 main 上先跑过一次新测试文件,红的正是这 8 条(single/group 各 3 条 + 未设 posture + 无 config),失败输出显示整张报告里没有任何 ledger 行 —— 不是文案不符,是这条检查根本没发生。改完后同样 8 条转绿。
  • 扰动 B(把去重拆掉,让 D5e 再渲染一遍):预测 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 记过这个坑。
  • 两个扰动下,「健康 ledger 零噪音」8 条始终绿 —— 它们不该被这两处影响,也确实没有。

验收对照

  • single/group(以及未设 posture、无 config)下,目录级与条目级各有其行 —— describe.each(BLIND_POSTURES) 六条 + 两条单独用例;
  • isolated 下同一个坏 ledger 只报一次 —— 出现次数计数钉住,且 ✓ Unique scope 仍被扣住;
  • ③ 健康 ledger / 从未安装过,在三种 posture 下都零噪音(含 --verbose);
  • ④ changeset:@objectstack/cli patch;
  • ⑤ 反向验证见上。

doctor-ledger-read-failure.test.ts(#5412/#5413/#5644 的既有钉子)全部保留、逐条复核:除 name 列 5 处随改名更新外,isolated 下的报告面一字未变 —— 这一点是刻意的,新检查可达不等于旧报告可以漂。

一处需要下游知道的事

已合并待发布的 changeset quiet-ledgers-speak-up.md 里写着「os doctor reports unparseable entries as a Unique scope warning row」。发布时该句已被本 PR 取代,我没有去改别人的 changeset,而是在本 PR 的 changeset 里显式写明「supersedes」,由发布流程合并两条时择取。

🤖 Generated with Claude Code

https://claude.ai/code/session_01DWUR56YsttL5sTF72Q75TQ


Generated by Claude Code

…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
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 6, 2026 1:58pm

Request Review

@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling labels Aug 6, 2026
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/cli.

21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/skills-reference.mdx (via packages/cli)
  • content/docs/api/client-sdk.mdx (via @objectstack/cli)
  • content/docs/api/data-flow.mdx (via @objectstack/cli)
  • content/docs/api/environment-routing.mdx (via @objectstack/cli)
  • content/docs/api/error-catalog.mdx (via @objectstack/cli)
  • content/docs/automation/hook-bodies.mdx (via packages/cli)
  • content/docs/deployment/backup-restore.mdx (via @objectstack/cli)
  • content/docs/deployment/cli.mdx (via @objectstack/cli)
  • content/docs/deployment/self-hosting.mdx (via @objectstack/cli)
  • content/docs/deployment/validating-metadata.mdx (via packages/cli)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/cli)
  • content/docs/kernel/runtime-services/data-service.mdx (via packages/cli)
  • content/docs/kernel/runtime-services/index.mdx (via packages/cli)
  • content/docs/permissions/authentication.mdx (via @objectstack/cli)
  • content/docs/plugins/index.mdx (via @objectstack/cli)
  • content/docs/plugins/packages.mdx (via @objectstack/cli)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/cli)
  • content/docs/protocol/kernel/realtime-protocol.mdx (via @objectstack/cli)
  • content/docs/releases/implementation-status.mdx (via @objectstack/cli)
  • content/docs/releases/v16.mdx (via @objectstack/cli)
  • content/docs/releases/v17.mdx (via @objectstack/cli)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Copy link
Copy Markdown
Contributor Author

越界发现,已另开、未修:#5996(观察类,finding,不排期)—— readInstalledPackageEntries()mod.DEFAULT_INSTALLED_PACKAGES_DIR ?? '.objectstack/installed-packages' 是一处消费端 ?? 兜底,而同一函数往下两行的注释(#5413 留下)正好写着「这里刻意不写 ??,消费端容忍就是当初那种沉默的来源」。当前该导出存在,是死代码,不是活缺陷;真要拆需顺带决定「导出缺失时报哪一行」,属报告面的小扩展,不塞进本 PR。


Generated by Claude Code


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review August 6, 2026 14:12
@baozhoutao
baozhoutao added this pull request to the merge queue Aug 6, 2026
Merged via the queue into main with commit dd98cba Aug 6, 2026
24 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-5429-doctor-ledger-posture-independent branch August 6, 2026 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

os doctor 的两条 ledger 健康行都锁在 isolated posture 之内 —— 换个 posture,同一个坏 ledger 一行都不报

2 participants