fix(spec,runtime): functions: [{ name, handler }] 数组形扛得住 objectstack build (#6238) - #6651
Merged
Merged
Conversation
…ck build` (#6238) 顶层 `functions` 的数组形通不过它自己的 build。`lowerCallables` 一直在降级数组 分支(把 `handler` 和 `name` 双双改写成 ref),但 `stack.zod.ts` 里 `functions` union 的数组成员仍然只收 `handler: z.function()`。于是 `objectstack build` 亲手 产出 `[{ name: 'syncBilling', handler: 'syncBilling', effect: 'writes' }]`,再由 自己拒收:`invalid_union: Invalid input`,路径止步于 `functions`,不点名条目、 不点名键、不给原因。 同一条缝第三次裂开,前两次修复正是这次看着小的原因。#4343 教会 union 认裸 lowered ref;#4976 教会它认 lowered *declaration*。两次都只动了 **map** 成员 —— 数组成员是另一条内联记录(数组条目自带 `name`,还有可选 `packageId`,因此不可能 是 `FlowFunctionEntrySchema` 装进列表),加宽其一从不加宽其二。 ## 前提复核(实测,非推断) 分诊的机制假设「对称加宽 `handler` 即足」**实测证实**。改动前跑真实流水线 (`defineStack` → `normalizeStackInput` → `lowerCallables` → parse)的四格读数: | 格 | 降级产出 | parse | |---|---|---| | map / bare | `{"scoreLead":"scoreLead"}` | ACCEPT | | map / declared | `{"syncBilling":{handler,effect}}` | ACCEPT | | array / bare | `[{"name","handler":"scoreLead"}]` | **REJECT** `invalid_union` @ `functions` | | array / declared | `[{name,handler,effect}]` | **REJECT** | 两个数组格栽在**同一个**成员上,所以一次加宽同时收两种拼写 —— 这点与 map 形不同: 数组条目的 `effect` 本就 optional,bare 与 declared 只差这个键在不在,不需要 #4976 那样的第二个成员。未照抄 #4976 的派生模式,因为两者结构确实不同。 ## 改动 1. **`packages/spec/src/stack.zod.ts`** —— 数组成员的 `handler` 在原有 callable 之外收下 lowered 字符串 ref。四格全部 round-trip。 2. **`packages/runtime/src/load-artifact-bundle.ts`** —— 本次加宽**让其可达**的装载 缝。`mergeRuntimeModule` 的数组分支会掉进 map 重建(`bundle.functions` 是数组时 `existing` 恒为 `{}`),于是合并后的 bundle 变成裸 `{ name: callable }` map, `effect: 'writes'` 被丢弃。函数照样注册、照样运行,写入却被计为零 —— 正是 #4396 修掉的静默 un-declaring 换了扇门进来,也正是让 #4354 broken-sweep 告警对最需要它 的那次 run 保持沉默的状态。实测读数: 改前 [ARRAY] collected: {"syncBilling":{handler, effect:"pure"}} ← 声明丢失 改后 [ARRAY] collected: {"syncBilling":{handler, effect:"writes"}} ← 与 map 形一致 数组形在 parse 这关被拒之前,没有任何构建产物到过这条分支;与其把它当作活陷阱 一起发布,不如同一次改掉。保留数组形状、按条目 `name` 挂回 callable;产物未声明 条目的模块函数照旧注册(map 分支就是这么做的,数组分支不该比 bundle 构建时少发 函数)。⚠️ 这一处越出 issue 字面范围,PM 若要拆分可单独摘出该 hunk 与其两条测试。 ## 验收(= 扩展 #4976 的跨界 round-trip pin) `packages/cli/src/utils/lower-callables.test.ts` 的参数化正是 #4976 预留的槽位 (原文:「SCOPE: the map form … Filed as #6238; extend the parametrisation below when it lands」)。现覆盖 map/array × bare/declared 全四格,外加 packageId 与多条目: **24 passed(原 18)**。数组格由整栈 parse 钉住(数组成员内联于 `ObjectStackDefinitionSchema`,无导出的单条目 schema),与 build 实际做的断言一致。 ## 逆向验证(方向先判后跑,真实读数) - 撤回 union 新成员 → 预判「恰好 6 条数组行转红」→ 实测 **6 failed | 18 passed**, 红的正是 5 条数组整栈 parse + 1 条数组产物断言;map 行全绿。恢复后 24/24 绿。 - 撤回 runtime 数组分支 → 预判「恰好 2 条新增 #6238 runtime 测试转红」→ 实测 **2 failed | 2 passed**,既有两条不受影响。恢复后 4/4 绿。 ## 验证读数 - `@objectstack/spec` 测试 **8808 passed / 343 files**;`@objectstack/cli` **983 / 94**;`@objectstack/runtime` **1613 / 111**。 - typecheck:spec、cli、runtime 三包干净。 - `check:generated` **✓ All 10 generated artifacts are up to date**(10/10,无生成物漂移)。 - `check:spec-parsed-alias` 通过(18 self-test + 1443 别名核对)。 - `pnpm lint` 干净。 - 三个示例应用 `validate` 全部 **exit=0**(crm / showcase / todo;输出中的告警为既有, 与 `functions` 无关)。 - 已 merge 最新 origin/main(82397b6)后重跑 pin、runtime 测试与 check:generated,均绿。 ## 未做 / 留给裁决 数组形在本仓库**零作者**(examples/apps/packages 无一处以数组形书写)。但它是 spec 里第一等的公开形状 —— `stack.zod.ts` 文档注释明列、`lowerCallables` 与 `collectBundleFunctionEntries` 都专门支持、`composeStacks` 还为 map/array 冲突 报错,且 #4976 的测试文件亲自预留了本次修复的槽位。因此按「修」而非「退役」处理; 退役属 ADR-0087 全套,另一个 program,未在此静默删除。 changeset:`@objectstack/spec` minor(接受面加宽)+ `@objectstack/runtime` patch。
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 118 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
qq9340100
enabled auto-merge
August 8, 2026 08:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6238
同一条缝第三次裂开(#4343 教 union 认裸 lowered ref、#4976 认 lowered declaration,都只动了 map 成员)。完整叙事与读数见分支 head commit;要点:
前提复核 —— 分诊机制假设实测证实
真实流水线四格读数(
defineStack→normalizeStackInput→lowerCallables→ parse):map 两格 ACCEPT,数组两格同栽在同一个 union 成员上 —— 一次加宽同收 bare/declared 两种拼写(数组条目effect本就 optional),不需要 #4976 式的第二成员,故未照抄其派生模式。改动
stack.zod.ts数组成员的handler收下 lowered 字符串 ref —— 四格全部 round-trip;runtime/load-artifact-bundle.ts):本次加宽让数组形 bundle 首次可达mergeRuntimeModule,其数组分支掉进 map 重建丢effect: 'writes'—— Ascriptnode's function is contractually pure, but nothing enforces it — a function that writes makes its run under-report #4396 修掉的静默 un-declaring 换门重进。改前/改后读数在 commit;验收与逆向
functions: { fn: { handler, effect: 'writes' } }cannot surviveobjectstack build— lowering emits a shape FlowFunctionEntrySchema rejects #4976 在lower-callables.test.ts预留的参数化槽位("extend the parametrisation below when it lands"—— 原文点名本单)扩至全四格 + packageId + 多条目:24 passed(原 18);check:generated10/10;三示例 validate exit 0;已 merge 最新 main 复跑。functions: { fn: { handler, effect: 'writes' } }cannot surviveobjectstack build— lowering emits a shape FlowFunctionEntrySchema rejects #4976 测试亲自预留修复槽位 —— 按修不按退(退役属 ADR-0087 全套另立)。changeset:spec minor + runtime patch。
交付通道注记
云端工头 G(
session_01QBmSqXovE79wARsbwc2Kib)无 GitHub 工具,走交付降级通道:dev push 分支,PM(session_011M7UwH25Unfi73UHim7ajY)代开本 PR 并跟进 CI 至合并。Generated by Claude Code