objectui#3222 已按**方向 1(objectui 跟随 spec)**落地(objectui PR #3289):`packages/spec` **一个字未改**——契约本来就是对的,是 objectui 从来没实现它。现在 objectui 侧实现了,`content/docs/protocol/objectui/widget-contract.mdx` 有两处需要跟着收口。 这份协议页本身是**排除方向 3 的关键证据**(`:48` 的「the source of truth is `FieldWidgetPropsSchema`」),所以它的正确性直接关系到那次裁定的价值。 ## 1. 示例教 widget 自己渲染文案 —— 落地后会双份显示 `:83-100` 的 `CustomRatingField` 示例: ```tsx function CustomRatingField({ value, onChange, readonly, required, error }: FieldWidgetProps) { return ( < div className="rating-field" aria-invalid={!!error} > … {error && < span className="error" >{error}< /span >} ← 这一行 ``` objectui 的表单渲染器**已经**用独立的 `< FormMessage / >` 在控件下方渲染这条消息。在 #3222 之前 widget 拿不到 `error`,所以这行永远不执行,问题是隐性的;**现在 widget 真的会拿到了**,照这份文档写出来的第三方 widget 会把同一句话显示两遍。 职责划分(objectui#3222 的裁定,已在 objectui 侧的实现与文档中落地): | 关注点 | 归属 | |---|---| | `aria-invalid`(必须落在 input 元素上) | **widget** | | 校验消息**文案** | **宿主**(`< FormMessage / >`) | | 必填标记 `*` | **宿主**(`< FormLabel >`) | 建议:删掉那一行,并在示例旁写明 `error` 是**布尔信号**,不是待渲染的文案。 ## 2. `required` 的措辞需要限定 `:62-63` 现在写「Indicate the required state visually and validate accordingly」。但在 objectui 里必填标记由外层 `FieldContainer` / `< FormLabel >` 画,widget 再画一个就是同样的双份显示——objectui#3222 正是因此**决定不把 `required` 下沉到 widget props**(见 objectui#3290 的分析:真正需要的是输入控件上的 `aria-required`,而那不需要新增契约键)。 `required` 留在 spec 的 schema 里没有问题(它描述的是**契约**,宿主是否传由宿主定),但文档里的这句祈使需要改成「**不要**自己画必填标记;宿主拥有它。你可以用它设 `aria-required`」之类的表述,否则同一份文档同时教出两个双份显示。 ## 边界 纯 docs:`content/docs/protocol/objectui/widget-contract.mdx`。**不改 `packages/spec/src/ui/widget.zod.ts`**——契约是对的,只有教法要收口。 关联:objectui#3222、objectui PR #3289、objectui#3290、objectstack#4115。
Activity
os-zhuang commentedon Aug 5, 2026
分诊:
pm:queue+domain:devx。content/docs/protocol/objectui/widget-contract.mdx(issue 边界已写死:不改packages/spec/src/ui/widget.zod.ts),content/docs/**归domain:devx。:95的{error && <span className="error">{error}</span>}仍在,前提成立;上游依据 objectui#3222 已按方向 1 落地(objectui PR chore(lint): org-identifier authoring guard for deprecated session.tenantId (#3280 follow-up) #3289),职责划分表(aria-invalid 归 widget、文案归宿主 FormMessage、必填标记归宿主 FormLabel)是既定裁决,本单纯粹跟随收口,无待决项。ctx.session.tenantIdalias in the next major (converge onorganizationId) #3290 均为上游实现与裁决,不是本文档单的影子;三仓无 widget-contract 文档修正影子单。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-zhuang commentedon Aug 6, 2026
Claim(PM devx 车道):本单由本 PM 会话派发实现。
session_01GX3sL71LFq8m2usg6VqTSEclaude/issue-4866-widget-contract-docscontent/docs/protocol/objectui/widget-contract.mdx;⛔ 不动packages/spec/src/ui/widget.zod.ts(issue 明确契约本身是对的)。措辞以 objectui#3222 裁定 + objectui PR chore(lint): org-identifier authoring guard for deprecated session.tenantId (#3280 follow-up) #3289 落地实现为准。Generated by Claude Code