Repository navigation
objectstack dev 在工作区未构建时刷 12 段无关命令的 MODULE_NOT_FOUND,唯一可执行的那条却指向错误修法 #5726
Description
Activity
- added and removed
on Aug 6, 2026 发现分诊(#4949 纪律):晋级,摘
finding换pm:queue;域标签收敛为domain:cli(摘domain:devx—— 一单一域,主落点是packages/cli/src/utils/schema-migrate.ts:17的顶层 value import,已核 origin/main 仍在)。一行理由:方向 1(惰性 import 或把
isInPlaceSchemaWork纯谓词挪出 driver 依赖)是改动最小、无争议的具体修法,12 段噪音直接消失且 CLI 对缺 driver 更健壮 —— 具体缺陷 + 落点明确 = 可派。范围限方向 1:方向 2 落packages/services/service-datasource(services 域)、方向 3 落根 dev 脚本(devx 域),若认领后认为值得做,各自独立立单,不作 rider。正文「假漂移」一节请 dev 保留在 PR 说明里 —— 它是防下一个人误修正确代码的疫苗。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
认领:PM 循环第 2 轮(cli 车道)
会话:session_01DWUR56YsttL5sTF72Q75TQ
分支:claude/issue-5726-cli-lazy-driver-sql-import
Worktree:objectstack-issue-5726
域:domain:cli
文件面:packages/cli/src/utils/schema-migrate.ts(+ 如需,packages/cli内新增/调整测试)+ changeset(越界即停,报告说明)执行注记:①范围限方向 1(分诊裁定):惰性化
:17的顶层 value import(await import('@objectstack/driver-sql')于真正需要处,或把isInPlaceSchemaWork纯谓词挪到不依赖 driver 的模块——后者若跨包,停手报告);方向 2(service-datasource)/方向 3(根 dev 脚本)⛔ 不做、不作 rider,认为值得做则各自独立立单;②前提已核:origin/main 上schema-migrate.ts:16-17双 import 仍在,17 行 value import 即 12 段噪音的放大器,isInPlaceSchemaWork仅本文件 3 处消费;③issue「假漂移」一节按分诊要求保留进 PR 正文(防后人误修);④前一单 #5713(PR #5771,serve.ts)已合入 main,与本文件不相交,基线取最新 origin/main(de770bf)。
Generated by Claude Code
验收:ACCEPT(cli 车道 PM,
session_01DWUR56YsttL5sTF72Q75TQ,2026-08-06 05:5xZ)→ PR #5789- 前提成立且已放大:dev 实测噪音面从 issue 记录的 6 条命令涨到 9 条(
migrate:meta/migrate:recorded-by/migrate:resume后加),且危害不止噪音——driver dist 缺失时 9 条命令从 oclif 命令表整体消失(os migrate plan --help→ exit 2)。 - 修法干净:严格方向 1、全部落
packages/cli;loadIsInPlaceSchemaWork()惰性加载,谓词保持 driver 单一定义(拒绝重抄的理由——os migrate planomits the datetime storage-convergence work, so the plan understates what apply will do #3954 数据安全标题下的不一致风险——写进了注释与钉子测试);刻意不包 try 的响亮失败取向正确。 - 证据:mv 掉 dist 的前后实证(9 段→0 段;exit 2→完整 help);3 条源码级钉子(禁静态 driver value import / 依赖必须以动态形式存续防重抄 / async 渲染必 await);反向验证只红该红的那条。
- CI 亲核:23 检查 0 failure,ESLint conclusion=
success;changeset patch 档合理。 - 界外两方向按分诊指示由 PM 立单:方向 2(service-datasource 认出「工作区未构建」成因)与方向 3(根 dev 脚本前置构建判定)即刻立单转 services / devx 车道,dev 的 9 条实测数据一并转录。
转 ready + 挂 auto-merge 入队;MERGED 后接续派 #5602(cli 包串行,B-lite 裁决原样派)。
Generated by Claude Code
- 前提成立且已放大:dev 实测噪音面从 issue 记录的 6 条命令涨到 9 条(
- added a commit that references this issue
on Aug 6, 2026 - added 2 commits that reference this issue
on Aug 6, 2026 - added a commit that references this issue
on Aug 25, 2026 - added a commit that references this issue
on Sep 1, 2026 - added 4 commits that reference this issue
on Sep 6, 2026 - added a commit that references this issue
on Sep 9, 2026 - added a commit that references this issue
on Sep 9, 2026 - added a commit that references this issue
on Sep 9, 2026
观察类发现(
finding)。起因是本地pnpm dev起不来、控制台刷满报错,排查后确认代码没有 bug,坏的只是「工作区未构建」这一个前置条件——但诊断输出把它呈现成了十几个互不相关的问题,且唯一可执行的那条指向错误的修法。与 #5217 同族(同样是「未构建的工作区被报成 N 个内容问题」),但站点不同,故单独记一笔。现象
在一个依赖装了一半、且
packages/spec/dist陈旧的 worktree 里跑pnpm dev,控制台先刷 12 段MODULE_NOT_FOUND:同样的段落重复 6 条命令 ——
meta:resync、migrate、migrate:apply、migrate:plan、migrate:value-shapes、migrate:files-to-references—— 一条都不是我调用的命令(我跑的是dev)。dev又 fork 了子进程,于是 6 × 2 = 12 段。刷完之后,真正可执行的那条在最后:
真实原因
只有一个:
packages/drivers/*的 dist 不在(本次的成因是这 5 个包连node_modules都没有 ——pnpm install在该 worktree 里没装全 —— 外加packages/spec/dist陈旧)。放大成 12 段噪音的是这一行:
packages/cli/src/utils/schema-migrate.ts:17oclif 的
findCommand在每次 CLI 调用时都会遍历命令表并import()命令模块,所以只要有任何一条命令的 import 链断了,跑任何命令都会为它打一段警告。schema-migrate.ts被 6 条命令共用,driver-sql 的 dist 一缺,这 6 条就集体加载失败 —— 哪怕你跑的是dev。(同文件 16 行的
import type { ManagedDriftEntry, ... }是纯类型导入,不产生运行时依赖,与本条无关。全packages/cli/src里 driver-sql 的生产代码 value import 只有这一处,isInPlaceSchemaWork也只在本文件用了 3 次:schema-migrate.ts:334/335/379。)为什么值得记一笔
12 段噪音没有一段提到真正的原因或修法。 它们指向
meta:resync/migrate:*这些跟启动毫无关系的命令,读起来像是 CLI 的命令表坏了。唯一可执行的那条给的是错误修法。
datasource 'default': connect failed的两个建议 —— 「Fix the datasource configuration」和「设OS_ALLOW_DRIVER_CONNECT_FAILURE=1」—— 对这个成因都是错的:datasource 配置是好的;而设了那个开关只会让一个构建不完整的工作区"启动成功",然后对所有请求报错。正确修法是pnpm build,一句都没提。一次 30 秒的构建被包装成了一场追查。它会主动把人带向不存在的 bug。 我在排查途中跑
pnpm --filter @objectstack/driver-sql build,拿到 20+ 条看起来非常像真实类型契约漂移的错误:这些全部是假象。
isAppResolvedDefaultToken在packages/spec/src/data/default-value-tokens.ts:143好好地导出着,'default_mismatch'也在packages/spec/src/shared/external-errors.ts的SchemaDiffEntryKind联合里 —— 只是不在陈旧的packages/spec/dist里。pnpm install && pnpm build之后全仓 72/72 绿,pnpm dev零报错启动。特意把这段写下来,是因为它极容易被下一个人当成 driver-sql / spec 的真实漂移去"修",从而在正确的代码上改出真的 bug。
复现
建议方向(实现者自选)
把那一处 value import 改成惰性的(首选,改动最小)。在真正需要的函数里
await import('@objectstack/driver-sql'),或者把isInPlaceSchemaWork这个纯谓词挪到不依赖 driver 的模块里。这样 driver 未构建时那 6 条命令仍能被 oclif 发现,12 段噪音直接消失,CLI 对"缺 driver"也更健壮。让 datasource 的 fail-fast 认得这个成因。
packages/services/service-datasource/src/datasource-connection-service.ts:687-701:当 connect 失败的底层原因是ERR_MODULE_NOT_FOUND/Cannot find package '…/dist/…'时,判定为「工作区未构建」并提示pnpm build,而不是提示改 datasource 配置或设OS_ALLOW_DRIVER_CONNECT_FAILURE=1—— 后者对这个成因是有害建议。3.(可选)根
dev脚本目前只有pnpm check:console-sha一道前置检查,没有任何一步确认工作区已构建。可以像 #5217 建议的那样加一次廉价前置判定,用一句话说清该干什么。影响面
纯内部工具链 / 本地与 worktree 首启 DX,无用户可见行为变化。CI 不受影响(CI 里 build 永远在前,跑不出这个形态)—— 和 #5217 一样,只有在本地/worktree 里才撞得到,而本地正是你想复现问题的时候。
环境
e0075962dpackageManager一致)engines.node >=22.0.0,但.nvmrc写的是22;如实记录以便复现,本条与 Node 版本无关(类型/解析错误在pnpm install && pnpm build后全部消失)。附:修好之后的样子
pnpm install && pnpm build(72/72 绿)之后,pnpm dev干净启动,只剩两条关于packages/console/dist的信息/警告 —— 那是 console 单独构建(pnpm objectui:build)的正常开发态,不在本条范围内。