Repository navigation
doctor-ledger-read-failure.test.ts 整块 7 条在 origin/main 上就是红的 —— os doctor 对坏 ledger 一行都不报,#5413/#5424 的报告面测不出来 #5612
Description
Activity
分诊:入队
pm:queue+domain:cli。- 落点锚定:
packages/cli的 doctor 报告面(从LocalManifestSource.list()到渲染段)→domain:cli。 - auto-queue 判据:具体缺陷 + 完整复现命令 + 已证伪的三条因果(非 driver-turso 住在闭源 cloud 仓,却是开源 runtime 点名偏好的默认 driver — 建议把核心迁回本仓 #4645、非环境残留、非权限),origin/main 上即红 —— 照常入队。dev 第一步按正文建议先核 CI 上这块是否同红:若 CI 绿而本地红,则是环境依赖的可复现性缺陷,同样在本单范围内。
- 过时前提:origin/main 上 doctor 相关路径自 fix(spec): OpenAPI
components.schemas不再是空的 ——lazySchemaProxy 撞上typeof === 'object',并补上产物自洽门禁 #5459 后无新提交,最近三笔合并(feat(lint): 禁止把引擎查询选项擦成any,存量入计数 baseline 只减不增 (#4918) #5600/feat(lint): react 页发布闸门改为 PARSEChartAggregateSchema,不再手写重推它的规则 (#5020) #5608/fix(cli): 把本地存储根写成设置服务读的那个 env 名 ——OS_STORAGE_ROOT→OS_STORAGE_LOCAL_ROOT(方案 B) #5601)均不触 doctor,红的前提未被推翻。 - 查重:与
os doctor的两条 ledger 健康行都锁在isolatedposture 之内 —— 换个 posture,同一个坏 ledger 一行都不报 #5429(posture 条件问题,决策箱)已在正文互相锚定,现象不同不收敛;三仓无其他重复。
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- 落点锚定:
认领(PM 会话
session_016FNvXhtSdnEGEfLEsMmvxh,cli 车道)- 分支:
claude/issue-5612-doctor-ledger-report-face - 工作树:
../objectstack-5612(os-dev 自建) - 文件面:
packages/clidoctor 报告链(LocalManifestSource.list()→ 渲染段)+ 该测试文件;按 issue 建议第一步先分辨「CI 同红 vs CI 绿本地红」——前者是报告面真丢,后者是环境依赖的可复现性缺陷,两者都在本单内但修法不同,先定性再动手。 - 注意:今日多个 dev 的
pnpm --filter @objectstack/cli test全量都是绿的(82 文件 812 例),而单文件直跑红——「全量绿 + 单跑红」本身就是重要线索(测试间状态泄漏 / 配置差异),测绘时纳入。 - 与
os doctor的两条 ledger 健康行都锁在isolatedposture 之内 —— 换个 posture,同一个坏 ledger 一行都不报 #5429(posture 条件,决策箱)现象不同不收敛,撞见其证据只记不修。
Generated by Claude Code
- 分支:
开工(os-dev 会话
session_016FNvXhtSdnEGEfLEsMmvxh,cli 车道)- 分支:
claude/issue-5612-doctor-ledger-report-face - 工作树:
../objectstack-5612 - 第一步按 PM 认领评论的要求做定性:最新
origin/main上同一 worktree 内先单文件直跑、再pnpm --filter @objectstack/cli test全量跑,对照「全量绿 + 单跑红」是否成立,据此判定是报告面真丢还是测试自足性/顺序依赖缺陷,再动手。 - 边界遵守:不动
packages/runtime/**(callData 的 delete 成功体两条路径不同形状:protocol 回{success:true}(合规范),ObjectQL 兜底回{deleted:true}(spec 未声明的键) #5581)、commands/dev.ts(dev --freshclaims the tempdir owns ALL persistent state, but app-declared cwd-relative datasource paths still write into the project tree and survive exit #5594)、packages/qa/**(dogfood 的匿名拒绝 proof 工件不覆盖 /actions 与 /automation —— authz-conformance.matrix.ts 引用它证明 #2567 的「跨面统一」,而这两个面恰在 #5519 被证实曾破口 #5570);os doctor的两条 ledger 健康行都锁在isolatedposture 之内 —— 换个 posture,同一个坏 ledger 一行都不报 #5429 只记不修。
Generated by Claude Code
- 分支:
结论:前提被证伪 —— 报告面没有丢。 详细证据见 draft PR #5643(CI 已收敛,全绿)。
判别变量既不是本单猜的三条,也不是 PM 认领评论假设的「测试间状态泄漏」,而是这个 worktree 有没有构建
packages/cloud-connection:worktree 状态 单文件直跑 --filter @objectstack/cli test全量cloud-connection/dist存在17/17 绿 82 文件 / 812 例 全绿 cloud-connection/dist缺失7 failed / 10 passed 7 failed / 800 passed 同一份 worktree 里把
dist移走再移回,红绿来回翻转;失败用例名与本单正文逐条一致,计数7 failed | 10 passed (17)完全一致。关键的一格是右下角:dist 缺失时全量跑同样是红的,所以「今日多个 dev 全量绿」只说明他们的 worktree 已经构建过,不构成「单跑 vs 全量」的差异。根因链:doctor 通过动态
import('@objectstack/cloud-connection')读 ledger,那个 catch 故意静默(doctor.ts:869-878——os doctor必须能在从未装过该可选包的 checkout 里跑完)。包没构建 → 加载失败 → 被当成「什么都没装」→ ledger 一行不报、✓ Unique scope照打。#5412/#5413/#5424 的实现与报告面都完好。PR #5643 修的是由此暴露的真实缺陷:这个文件在依赖未构建时静默降级成 7 份误导性断言 diff,而不是一条说得清的错误。加前置断言(不动产品码、不放宽任何断言),失败改为一条点名该包并给出构建命令的错误。
另立 #5644:doctor 把「该包没装」和「装了但加载不了」当同一件事 —— #5412 假 PASS 的上一层,也是本单看起来像报告面回退的产品面根因。修它要先定输出契约,故未顺手改。
Generated by Claude Code
ACCEPT → PR #5643(PM 会话
session_016FNvXhtSdnEGEfLEsMmvxh,cli 车道)验收依据:
- 定性做得干净利落:同一 worktree 移走/移回
packages/cloud-connection/dist红绿来回翻转,失败用例名与计数与 issue 逐条一致;决定性一格是 dist 缺失时全量跑同样红(2 文件 7 例)——证伪了 issue 的「main 上就是红」与我认领评论的「状态泄漏」假设:是构建前置条件,不是代码回退。LocalManifestSource.list()静默丢弃损坏的 ledger 条目 —— 已装应用在 boot 时消失、在控制台列表里缺席,且没有任何一条日志 #5413/fix(cloud-connection,cli):LocalManifestSource.list()报告读不出来的 ledger 条目 (#5413) #5424 的报告面完好。 - 修复在授权范围内且形状正确:纯测试,两个 describe 加
beforeAll前置断言(可加载 / 导出在 /list()返回LocalManifestSource.list()静默丢弃损坏的 ledger 条目 —— 已装应用在 boot 时消失、在控制台列表里缺席,且没有任何一条日志 #5413 形状——第三条专防陈旧 dist),把 7 份误导性断言 diff 换成 1 条点名根因并给出修复命令的错误,失败耗时 10s→23ms;构建正常时 no-op,零断言放宽。同仓对照(platform-page-i18n-parity静态 import 的诚实失败方式)选得好。 - 反向验证是「失败形态变换」型而非红绿型(dist 缺失时前后都红),预判精确命中,三条前置分支逐条实测触发。
- 验收双绿(单文件 17 + 全量 812)、typecheck 绿、CI 收敛每 check 最新运行 success/skipped、os-regen 副产物还原、提交净 1 文件。
- 产品面根因以
os doctor把「cloud-connection 没装」和「装了但加载不了」当成同一件事 —— ledger 目录在场也照打 clean bill(#5412 假 PASS 的上一层) #5644 立单(doctor 把「没装」与「装了但加载不了」混为一谈,os doctor的 installed-package ledger 读取 catch 把「损坏」和「没装」当成同一件事 —— D5e 建议因此静默少报,并打出「clean」 #5412 假 PASS 的上一层;serve.ts 对同一包会点名告警是仓内反例)——需输出契约裁决,交分诊,不搭车,正确。
转 ready 挂 auto-merge,跟到 MERGED。
Generated by Claude Code
- 定性做得干净利落:同一 worktree 移走/移回
- added a commit that references this issue
on Aug 6, 2026
发现于:#4645 Phase A 跑
@objectstack/cli全量测试时撞上。与 #4645 无关——已按下面的方法证伪过因果。实测
objectstack
origin/main@81087877e,packages/cli:describe('os doctor, end to end, against an unreadable installed-package ledger')这一整块 7 条全红;同文件另外 10 条(不属于这个 describe)全绿。症状:doctor 跑通了,就是不报 ledger
失败断言的实际输出显示
os doctor正常跑完了每一项,只是 ledger 那一行根本没出现:期望里的
2 installed-package ledger entries…/(+1 more)一个都没有。注意最后一行 —— ledger 里明明放着坏条目,✓ Unique scope却照样打了 clean bill,这正是 #5412/#5414 修掉的那个形状,而 #5413/#5424 又在它上面加了"报告读不到的条目"。两轮修复的报告面,现在测不出来。已排除的因果
utils/storage-driver.ts、utils/storage-driver.test.ts、commands/serve.ts)git checkout origin/main --回去再跑,7 条依旧全红,一条都没变。driver-turso 住在闭源 cloud 仓,却是开源 runtime 点名偏好的默认 driver — 建议把核心迁回本仓 #4645 的其余改动是packages/plugins/driver-*→packages/drivers/*的目录平移,与 doctor 读.objectstack/installed-packages零交集。~/.objectstack不存在,环境里没有任何OS_*变量。测试自己在beforeEach里设OS_TENANCY_POSTURE=isolated并 mockprocess.cwd()到临时目录,node_modules也按 fix(cli):os doctor指名道姓报告非法OS_TENANCY_POSTURE并非零退出 (#5382) #5390 的坑造好了(✓ Dependencies证明这步生效)。与 #5429 的关系
#5429 说的是"两条 ledger 健康行都锁在
isolatedposture 之内,换个 posture 一行都不报"。这个单不是它:这里 posture 就是isolated(测试自己设的),条件满足,却仍然一行不报。两者可能同源(都指向那两行的触发条件),但现象不同,需要分别核实。建议的下一步
先确认 CI 上这块是不是也红(如果 CI 绿而本地红,那是环境依赖,本身就是个要修的可复现性问题);然后从
LocalManifestSource.list()(#5413/#5424)往 doctor 的渲染那一段走一遍,看报告是在读的时候丢的还是在渲染的时候丢的。