Repository navigation
Closed
Labels
bugSomething isn't workingSomething isn't workingdomain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch looptarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA
Description
发现自 #4813 的实现过程(PR 见下)。未认领。 与 #4813 是不同的 bug —— 修好 #4813 之后它照旧复现。
现象
一条成功的 os migrate 子命令(JSON 正常输出、✅ Graceful shutdown complete 正常打印、stderr 全空)退出码是一个每次都不一样的非零值:
cd examples/app-crm
for i in 1 2 3; do
rm -f /tmp/t.db*
OS_DATABASE_URL="file:/tmp/t.db" node ../../packages/cli/bin/run.js migrate recorded-by --json >/dev/null 2>&1
echo "run $i exit=$?"
done
# run 1 exit=208
# run 2 exit=171
# run 3 exit=176同一条命令在其它时刻还观察到 62、163、169。#4813 的正文里记录的 214 / 238 也是同一个现象。
对照组 —— 同一个 bin/run.js,不走 schema stack 的子命令干净退出 0:
node ../../packages/cli/bin/run.js --version → exit=0
node ../../packages/cli/bin/run.js --help → exit=0
所以问题不在 CLI 框架本身,而在 bootSchemaStack 系子命令的退出路径上。
与 #4813 的关系(重要,别合并成一条)
#4813 是「内核的 init/start 超时守卫定时器不清除,进程干完活还空转 120 秒」。它不是这条的原因:
| 挂起时长 | 退出码 | |
|---|---|---|
| #4813 修复前 | 122.4s | 163 |
| #4813 修复后 | 3.1s | 62 / 169 / 208 / 171 / 176 |
两次都是同一个构建链、同一条命令,唯一差别是 packages/core/src/kernel.ts 的守卫改动。时长被修好了,退出码没有。
这一点值得单独强调,因为 #4813 的正文把不稳定退出码归因于「进程挂太久被外部杀掉」。现在证明不是 —— 没有任何东西杀它,它自己在 3 秒后退出,退出码依旧随机非零。那个归因是错的,修好挂起并不会顺带修好退出码。
为什么值得修
一条成功的命令返回非零码,对任何按退出码判断成败的调用方都是直接的假失败:CI 步骤、set -e 脚本、Makefile、容器 entrypoint。而且它是随机的,所以「特判某个码」这种兜底也做不了。
--json 的存在说明这条命令本来就是设计给程序消费的;程序消费的第一件事就是退出码。
线索(未定位到根因)
- 值域看着像 0–255 的随机数,而不是某个有意义的错误码 —— 更像原生层异常退出(退出时的 native addon 崩溃 / abort),而不是某处
process.exit(n)传了业务数字。 - stderr 全空,没有堆栈、没有
unhandledRejection、没有Warning:,Node 侧看起来一切正常 —— 这也支持「JS 之后的阶段出的事」。 packages/core/src/utils/env.ts有safeExit(code = 0),但 CLI 的 migrate 路径里没有直接调用点,值得从那里往下追。- 数据源是 libsql/sqlite(
OS_DATABASE_URL="file:…"),teardown 时关连接池的原生句柄是一个值得先看的嫌疑点。
复现
cd examples/app-crm
rm -f /tmp/t.db*
OS_DATABASE_URL="file:/tmp/t.db" node ../../packages/cli/bin/run.js migrate recorded-by --json
echo "exit=$?"Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingdomain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch looptarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA
Activity
os-zhuang commentedon Aug 6, 2026
存量裁决轮(维护者 2026-08-06 委托,session_01LeEfA7CFwbJb7JJmXm2KM3):裁定入队,并按落点锚定改标
domain:engine-core→domain:cli(修复落点 packages/cli / safeExit)。前提经 origin/main 核实仍成立:无任何退出码修复提交,成功的os migrate返回随机非零码——对一切按退出码判成败的调用方(CI /set -e/ 容器)都是假失败,且该命令有--json本就供程序消费。分诊座位如认为锚定有误请改回。维护者可否决。Generated by Claude Code
fix(cli): reserve stdout for the `--json` payload across the bootSche…
docs(qa): refresh cli dev-boot DB clause to unified objectstack.db; n…
docs(cli): drop stale family counts from json-stdout-purity docblock
docs(cli): drop stale family counts from json-stdout-purity docblock (o…
docs(qa): re-point the cli / platform-core / records-forms bad-citati…
fix(cli,runtime): os migrate resume, recorded-by and value-shapes ans…