结论
本仓当前 lockfile 把 @objectstack/spec 解析到 17.0.0-rc.0,而 registry 上 rc tag 已经是 17.0.0-rc.1。升级不是改个 range 就完事 —— 实测有两个硬阻塞。
现状
package.json 里的 range 是 ^17.0.0-rc.0(root + 24 个包),本身已经允许 rc.1,只是 lockfile 钉在 rc.0:
$ ls node_modules/.pnpm | grep '^@objectstack'
@objectstack+client@17.0.0-rc.0
@objectstack+core@17.0.0-rc.0
@objectstack+formula@17.0.0-rc.0
@objectstack+lint@17.0.0-rc.0
@objectstack+sdui-parser@17.0.0-rc.0
@objectstack+spec@17.0.0-rc.0
阻塞 1 —— 双版本 spec 图
client / core / formula / lint 对 spec 的依赖是精确版本,不是 caret:
@objectstack/client@17.0.0-rc.0 -> spec "17.0.0-rc.0"
@objectstack/core@17.0.0-rc.0 -> spec "17.0.0-rc.0"
@objectstack/formula@17.0.0-rc.0 -> spec "17.0.0-rc.0"
@objectstack/lint@17.0.0-rc.0 -> spec "17.0.0-rc.0"
所以只升 spec 之后:
$ pnpm update -r @objectstack/spec@17.0.0-rc.1
$ # 图里同时存在两份 spec:
spec copies in graph: @objectstack+spec@17.0.0-rc.0, @objectstack+spec@17.0.0-rc.1
client -> sees spec 17.0.0-rc.0
core -> sees spec 17.0.0-rc.0
formula-> sees spec 17.0.0-rc.0
lint -> sees spec 17.0.0-rc.0
即 objectui 自己的代码看 rc.1,@objectstack/* 内部看 rc.0。这对本仓特别危险,因为多处 guard 依赖 引用同一性 / 同一份 .d.ts:
scripts/check-spec-symbol-derivation.mjs 和 spec-symbol-parity.test.ts 都用 createRequire 去解析 spec 的 .d.ts 再过 TS checker —— 拿到哪一份取决于解析顺序。
spec-subschema-parity.test.ts 明确以引用同一性区分 re-export 与 fork(见 check-spec-symbol-derivation.mjs 头部关于 objectui#3003 的说明);两份 spec 会让 zod schema 对象不再是同一个引用。
结论:spec 不能单独升,必须整个 @objectstack 家族 rc.0 → rc.1 同步升(client / core / formula / lint / sdui-parser 的 rc tag 都已是 17.0.0-rc.1)。
阻塞 2 —— check:spec-symbols 由绿转红
baseline(rc.0):
$ pnpm check:spec-symbols
✅ spec symbol derivation: 1200 files scanned against 4231 spec export names;
6 declared dialects, 77 untriaged collisions in 18 packages.
$ echo $?
0
升到 rc.1 后:
$ pnpm check:spec-symbols
❌ a spec-named symbol is hand-written, not derived:
• @object-ui/app-shell declares 1 spec-named symbol the spec already owns:
interface `InboxNotification` packages/app-shell/src/layout/inboxGrouping.ts:16
(exported by `@objectstack/spec/contracts`)
• @object-ui/types declares 1 spec-named symbol the spec already owns:
interface `FieldNode` packages/types/src/data-protocol.ts:226
(exported by `@objectstack/spec/data`)
• @object-ui/types lists 1 symbol in DEBT that no longer collide — `JoinNode`.
• @object-ui/react lists 1 symbol in DEBT that no longer collide — `PerformanceConfig`.
$ echo $?
1
也就是 rc.1 新增了 InboxNotification(contracts)、FieldNode(data)两个导出名,同时移除/改名了 JoinNode、PerformanceConfig。四处都得对账(前两个 import/derive/rename/ALLOW 四选一,后两个从 DEBT 台账删除,--ledger 可重生成)。
另需注意 —— rc.1 收紧了 schema 严格性
rc.1 把一批 zod schema 从 $strip 翻成 $strict(strict 会拒绝未知键,而不是静默丢弃):
| subpath |
rc.0 |
rc.1 |
automation |
$strict=0 $strip=160 |
$strict=19 $strip=152 |
ui |
$strict=3 $strip=286 |
$strict=6 $strip=287 |
共约 22 个 schema 变严。以前能通过的元数据现在可能直接抛错 —— 升级 PR 里需要专门验证 automation / ui 侧的解析路径,不能只看编译通过。
建议
单独开一个「@objectstack 家族 rc.0 → rc.1 同步升级」PR,内容至少包括:
client / core / formula / lint / sdui-parser / spec 一并升到 17.0.0-rc.1,确认 node_modules/.pnpm 里只剩一份 spec。
- 处理
check:spec-symbols 的四处对账。
- 针对
$strip → $strict 的 22 个 schema 做解析回归验证。
- 按 AGENTS.md「版本号策略」,changeset 标
minor(不要标 major,fixed 组会整组被推走)。
影响
objectstack-ai/objectstack#4562(把 DecisionOutputDef 收敛成 spec 的纯 re-export)被本 issue 阻塞:required 只在 spec rc.1 才被建模,rc.0 没有。在当前解析的 rc.0 下收敛会直接编译失败:
src/utils/decisionOutputParams.ts(128,50): error TS2339:
Property 'required' does not exist on type
'{ key: string; label?: string; type?: "text" | "position" | "user" | "department" | "team"; multiple?: boolean; }'.
已备好的改动在分支 claude/issue-4562-decision-output-collapse(在 rc.1 下实测 app-shell tsc --noEmit 全绿),等本 issue 落地后即可开 PR。
发现于 objectstack-ai/objectstack#4562 的实施过程中,属于该 issue 范围外,故单独记录,未指派。
🤖 Generated with Claude Code
结论
本仓当前 lockfile 把
@objectstack/spec解析到 17.0.0-rc.0,而 registry 上rctag 已经是 17.0.0-rc.1。升级不是改个 range 就完事 —— 实测有两个硬阻塞。现状
package.json里的 range 是^17.0.0-rc.0(root + 24 个包),本身已经允许 rc.1,只是 lockfile 钉在 rc.0:阻塞 1 —— 双版本 spec 图
client/core/formula/lint对 spec 的依赖是精确版本,不是 caret:所以只升 spec 之后:
即 objectui 自己的代码看 rc.1,
@objectstack/*内部看 rc.0。这对本仓特别危险,因为多处 guard 依赖 引用同一性 / 同一份.d.ts:scripts/check-spec-symbol-derivation.mjs和spec-symbol-parity.test.ts都用createRequire去解析 spec 的.d.ts再过 TS checker —— 拿到哪一份取决于解析顺序。spec-subschema-parity.test.ts明确以引用同一性区分 re-export 与 fork(见check-spec-symbol-derivation.mjs头部关于 objectui#3003 的说明);两份 spec 会让 zod schema 对象不再是同一个引用。结论:spec 不能单独升,必须整个
@objectstack家族 rc.0 → rc.1 同步升(client / core / formula / lint / sdui-parser 的rctag 都已是 17.0.0-rc.1)。阻塞 2 ——
check:spec-symbols由绿转红baseline(rc.0):
升到 rc.1 后:
也就是 rc.1 新增了
InboxNotification(contracts)、FieldNode(data)两个导出名,同时移除/改名了JoinNode、PerformanceConfig。四处都得对账(前两个 import/derive/rename/ALLOW 四选一,后两个从 DEBT 台账删除,--ledger可重生成)。另需注意 —— rc.1 收紧了 schema 严格性
rc.1 把一批 zod schema 从
$strip翻成$strict(strict 会拒绝未知键,而不是静默丢弃):automation$strict=0$strip=160$strict=19$strip=152ui$strict=3$strip=286$strict=6$strip=287共约 22 个 schema 变严。以前能通过的元数据现在可能直接抛错 —— 升级 PR 里需要专门验证 automation / ui 侧的解析路径,不能只看编译通过。
建议
单独开一个「
@objectstack家族 rc.0 → rc.1 同步升级」PR,内容至少包括:client/core/formula/lint/sdui-parser/spec一并升到 17.0.0-rc.1,确认node_modules/.pnpm里只剩一份 spec。check:spec-symbols的四处对账。$strip → $strict的 22 个 schema 做解析回归验证。minor(不要标major,fixed 组会整组被推走)。影响
objectstack-ai/objectstack#4562(把
DecisionOutputDef收敛成 spec 的纯 re-export)被本 issue 阻塞:required只在 spec rc.1 才被建模,rc.0 没有。在当前解析的 rc.0 下收敛会直接编译失败:已备好的改动在分支
claude/issue-4562-decision-output-collapse(在 rc.1 下实测 app-shelltsc --noEmit全绿),等本 issue 落地后即可开 PR。发现于 objectstack-ai/objectstack#4562 的实施过程中,属于该 issue 范围外,故单独记录,未指派。
🤖 Generated with Claude Code