Repository navigation
Description
#4001 批 14 把 ActionParamSchema.options[] 收成了 strictObject({ label, value }) —— 它一直以来的契约,只是从「靠删除来执行」变成了说出口。收紧本身不删任何能用的东西(见下面的实测),但测量过程暴露出一个独立的能力问题,这里存档,不在批 14 里猜。
现状:同一个概念,仓里有三种拼法
| 位置 | 形状 | posture |
|---|---|---|
data/field.zod.ts SelectOptionSchema |
label / value / color / default / visibleWhen |
strictObject(已关) |
ui/action.zod.ts ActionParamSchema.options[] |
label / value |
strictObject(批 14 关的) |
ui/bulk-action.zod.ts BulkActionParamSchema.options[] |
label / value + 开放 |
.passthrough()(#4909) |
objectui 那侧还有第四份:SelectOptionMetadata(packages/types/src/field-types.ts)—— label / value / color / icon / disabled / visibleWhen。注意 icon / disabled 在 spec 里任何一处都没有声明,只活在 objectui 自己的接口里。
实测(2026-08-03)
1. action 的门今天就在剥。 一个 action 是注册 metadata type,所以作者写的 param 是经 getMetadataTypeSchema('action') 到达 objectui 的。拿真实 payload 过这道门:
options: [{ label: 'Overload', value: 'overload',
color: 'red', visibleWhen: "record.status == 'open'", icon: 'x', disabled: false }]
parse 成功,出来的是:
{"label":"Overload","value":"overload"}四个键在任何 renderer 看到它们之前就没了,而且报告成功。所以批 14 的收紧没有拿走任何在工作的东西,只是把静默变成了响亮。
2. 但渲染侧其实读得懂其中两个。 dialog 走 paramToField -> field.options -> getLazyFieldWidget('select') -> SelectField,而 SelectField 通过 useCascadingOptions -> resolveCascadingOptions 解析逐选项 visibleWhen(ADR-0058 / #2284);color 则被 grid/detail 的展示渲染器读(packages/fields/src/index.tsx 的 option?.color)。也就是说:唯一挡在作者和一个能工作的逐选项门控之间的,就是 spec 的这道剥离。
3. 字段回退那条路也不通。 直觉上的处方「把 param 写成 field-backed,继承字段自己的选项」对这两个键是假的 —— resolveActionParams 的 normaliseOptions 把每个条目重建成 { label, value }。两个方向都丢。批 14 的 guidance 因此刻意没有给出这条建议(账本 finding 18:错误里的文案是行为,自信而错的处方比没有更糟)。
要判的事
action param 的选项列表该不该讲 SelectOptionSchema 已经声明、对象表单已经兑现的那套逐选项词汇?
- A. 维持
{ label, value }(批 14 的落点)。契约最小、最诚实。代价:一个已经接好线的门控能力被合约挡着,而且这个不对称本身就是 AI 作者会踩的坑。 - B. 让它复用
SelectOptionSchema(.extend()覆写label为I18nLabelSchema、value为z.string(),.extend()会继承 strict)。一套词汇,N 个面。代价:normaliseOptions必须同步停止重建条目,否则声明了却不兑现 —— 又是一次 declared != enforced;且要判color/default在这条路上是否真被读,否则是声明惰性键。 - C. B 再加上把
icon/disabled补进SelectOptionSchema,让 spec 和 objectui 的选项词汇彻底对齐。代价最大,但这是唯一让「四份拼法」收敛成一份的选项。
个人倾向 B,并且必须和 normaliseOptions 的修改同一个 PR 落地 —— 单独放开 spec 会造出一个声明了、门也过了、渲染器却收不到的键,正好是 ADR-0078 要消灭的那种。但这跨 framework + objectui 两个仓,且要先做一次 color / default 的逐键 liveness 审计,不适合塞进一个收紧批次。
另注:批 14 之所以没跟 bulk-action 走 .passthrough(),是因为 #4909 的两条理由在这里都不成立 —— 那边的 def 是「left as-authored」逐字到达 grid(没有这道 spec 门),且 objectui 的 BulkActionParam 声明了显式的 [key: string]: unknown 兜底;这边的目标类型 SelectOptionMetadata 是封闭接口。目标词汇封闭,正是「声明」胜过「容忍」的场合。
发现于 #4001 批 14,未指派。
Activity
feat(spec)!: tighten unknown keys on nine ui/ shapes, reclassify two …
os-zhuang commentedon Aug 6, 2026
分诊(spec 车道欠账代扫,维护者 2026-08-05 指令):挂
needs-user-decision。action param 的options[]是否复用SelectOptionSchema逐选项词汇(A 维持最小 / B 复用且必须与normaliseOptions同 PR / C 再补icon/disabled收敛四份拼法)——契约词汇统一问题,填单人倾向 B 并给出了「必须同 PR 否则 declared≠enforced」的硬约束,成立。target:v18在身不急;裁决 B/C 时须先做color/default逐键 liveness 审计再拆单(跨 framework+objectui 两仓)。不构成认领。会话:session_01N3uGFF8teXbpgtbEJ1aYXuGenerated by Claude Code
os-zhuang commentedon Aug 6, 2026
维护者裁决(2026-08-06,经本会话转达):取 B(
options[]复用SelectOptionSchema),硬约束照正文:必须与resolveActionParams的normaliseOptions停止重建条目同一个 PR 落地——单独放开 spec 会造出「声明了、门过了、渲染器收不到」的键。前置:先做color/default的逐键 liveness 审计;C(把icon/disabled收进 spec)仅当审计发现 objectui 真读它们才升级,否则不做。bulk-action的.passthrough()特例维持(#4909 理由不适用于本单,正文已辨析)。执行窗口 = 协议 18(跨 framework+objectui),转pm:on-hold:重启条件 = v18 列车开启时由 spec 座位回捡并按跨仓拆分派发。会话:session_01N3uGFF8teXbpgtbEJ1aYXuGenerated by Claude Code
fix(spec): withdraw the `icon` input from the object.form options rep…
test(spec): the first ui/ file group's test titles state each cited d…