Skip to content

test(cli): make the doctor ledger e2e block fail legibly when cloud-connection is unbuilt (#5612) - #5643

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5612-doctor-ledger-report-face
Aug 5, 2026
Merged

test(cli): make the doctor ledger e2e block fail legibly when cloud-connection is unbuilt (#5612)#5643
baozhoutao merged 1 commit into
mainfrom
claude/issue-5612-doctor-ledger-report-face

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #5612

结论先行:前提被证伪 —— 报告面没有丢

#5413/#5424 的报告面完好,os doctor 对坏 ledger 该报的都在报。issue 里那 7 条红,唯一的因果变量是这个 worktree 里 packages/cloud-connection 没有被构建

定性:三种世界里的哪一种

PM 认领评论给的假设是「全量绿 + 单跑红 → 测试间状态泄漏/顺序依赖」。实测把这个假设也证伪了 —— 判别变量不是跑法(单跑 vs 全量),而是构建状态:

worktree 状态 单文件直跑 --filter @objectstack/cli test 全量
cloud-connection/dist 存在 17/17 绿 82 文件 / 812 例 全绿
cloud-connection/dist 缺失 7 failed / 10 passed 7 failed / 800 passed(82 文件中 2 红)

同一份 worktree 里,只把 packages/cloud-connection/dist 移走再移回,红绿来回翻转,失败用例名与 issue 正文逐条一致、计数 7 failed | 10 passed (17) 完全一致。全量跑在 dist 缺失时同样是红的,所以「全量绿」只是那些 dev 的 worktree 已经构建过而已。

立单者证伪的三条因果(非 #4645、非环境残留、非权限)都对 —— 第四条才是真因,而它恰好是 AGENTS.md §9 / 派单须知里那条「新 worktree 跑测试前先构建依赖」的陷阱:

pnpm --workspace-concurrency=2 --filter '@objectstack/cli^...' build

为什么这个文件会「静默降级」,而它的姐妹文件不会

doctor 通过动态 import('@objectstack/cloud-connection') 读 ledger,那个 catch 是故意静默的(readInstalledPackageEntries(),doctor.ts:869-878):os doctor 必须能在从未装过该可选包的 checkout 里跑完。这个契约是对的,而且本文件最后一个 describe 就在钉它。

代价是:本文件分不清「报告面回退了」和「这个 worktree 没构建那个包」—— 两者都表现为同一种彻底的静默。doctor 照常跑完每一项、照打 ✓ Unique scope,7 条用例以 7 份断言 diff 变红,读起来与 #5412 被回退一模一样。#5612 就是据此立的单。

对照组就在同一个包里:test/platform-page-i18n-parity.test.ts 静态 import 同一个包,于是它以诚实的方式失败 —— 一条点名该包的错误(Failed to resolve entry for package "@objectstack/cloud-connection")。dist 缺失时全量跑的「2 个红文件」,红的正是这一对:一个说人话,一个不说。本 PR 把说人话的能力还给后者。

改动

纯测试改动,不动产品码,不放宽任何断言,构建正常的 worktree 里前置断言是 no-op。两个依赖真实模块的 describe 加 beforeAll 前置断言:

  1. 包能加载 —— 否则一条错误直接给出构建命令;
  2. 导出 LocalManifestSource;
  3. list() 返回 LocalManifestSource.list() 静默丢弃损坏的 ledger 条目 —— 已装应用在 boot 时消失、在控制台列表里缺席,且没有任何一条日志 #5413 引入的 { entries, skipped } 形状。

第 3 条不与第 1 条重复:陈旧的 dist(早于 #5413)能正常解析、返回裸数组,到了 doctor 里 skipped === undefined,拐进目录级失败行 —— 第三种错误报告,也正是本文件最没能力识别的那种陈旧产物陷阱。

第三个 describe 比 e2e 块需要这层保护:它模拟「包加载不了」并断言 doctor 保持静默,在包真的加载不了的 worktree 里会因为同一个原因而变绿 —— PR #5046 记下的空判定假绿(断言通过是因为什么都没产生)。

反向验证(方向先判后跑)

不是 before-green/after-red:dist 缺失时改动前后都是红的。会变的是红成什么样 —— 预测「7 份误导性断言 diff → 1 条点名的前置错误,且 7 条真正的单元用例保持绿」。实测:

FAIL  ... > os doctor, end to end, against an unreadable installed-package ledger
FAIL  ... > the optional package being absent stays completely silent (#5412 does not regress it)
Error: Preflight failed: the end-to-end ledger cases below cannot observe anything.
...
Build the dependency graph first:
    pnpm --workspace-concurrency=2 --filter '@objectstack/cli^...' build
cause: Failed to resolve entry for package "@objectstack/cloud-connection". ...

 Tests  7 passed | 10 skipped (17)

三条分支逐条实测触发(缺失 dist / 缺 LocalManifestSource 导出 / 临时把 list() 打成裸数组模拟陈旧 dist),第三条给出:

cause: LocalManifestSource.list() returned [], not the { entries, skipped } listing #5413 introduced — the built artefact predates it.

顺带:失败从 ~10s 的徒劳 doctor 跑降到 23ms。

验收

  • 单文件直跑:17 passed (17)
  • 全量:pnpm --filter @objectstack/cli test82 passed (82) / 812 passed (812)
  • pnpm --filter @objectstack/cli typecheck 绿
  • node scripts/check-nul-bytes.mjs OK;改动文件另做控制字节自扫,无命中(文件内转义一律写 \x1b 形式)

changeset:纯测试改动,不发布任何东西 → 走 skip-changeset 标签路径。

边界

未动 packages/runtime/**(#5581)、commands/dev.ts(#5594)、packages/qa/**(#5570)。#5429(posture 条件)现象不同,未收敛、未触碰。

界外发现另行立单,见下方评论。


🤖 Generated with Claude Code

https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh


Generated by Claude Code

…onnection is unbuilt (#5612)

`doctor-ledger-read-failure.test.ts` 的 e2e 整块通过 doctor 的动态
`import('@objectstack/cloud-connection')` 观察 ledger 报告面,而那个 catch
是**故意静默**的(`os doctor` 必须能在从未装过该可选包的 checkout 里跑完)。
后果:worktree 里 `packages/cloud-connection/dist` 缺失时,doctor 照常跑完每
一项、照打 `✓ Unique scope`,7 条用例以 7 份断言 diff 变红,读起来与
「#5412/#5413 的报告面被回退了」一模一样 —— #5612 正是据此立单的。

本提交不改产品码、不放宽任何断言,只加一层前置断言:两个依赖真实模块的
describe 在 `beforeAll` 里确认该包可加载、且 `list()` 返回 #5413 引入的
`{ entries, skipped }` 形状(陈旧 dist 会解析成 `skipped === undefined`,
在 doctor 里拐进第三种错误报告 —— AGENTS.md §9 的陈旧产物陷阱)。

第三个 describe 更需要这层保护:它模拟「包加载不了」并断言 doctor 保持静默,
在包真的加载不了的 worktree 里会**因为同一个原因**而变绿 —— PR #5046 记下的
空判定假绿。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh
@vercel

vercel Bot commented Aug 5, 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 5, 2026 9:33pm

Request Review

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

No hand-written docs reference the 0 changed package(s). ✅

Copy link
Copy Markdown
Contributor Author

界外发现已另行立单(查重后无重复,未打标签,交分诊):


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review August 5, 2026 21:46
@baozhoutao
baozhoutao added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit fd0069c Aug 5, 2026
35 of 36 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-5612-doctor-ledger-report-face branch August 5, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain:cli size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants