You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat(spec)!: declare RecordDetailsProps.sections in its real object form + declare hideFields (#5611)
`record:details` declared a `sections` shape nothing produced and nothing
consumed, and omitted a key a published platform page depends on.
- `sections`: `z.array(z.string())` (section IDs) -> an object array
`{ name?, label?, columns?, fields }`. Measured: zero ID-list producers and
zero ID-list read paths. objectui's RecordDetailsRenderer maps every entry as
an object with no string branch, `@object-ui/types` already mirrored the
object form, the Studio block designer can only author it, and all four real
pages (3 showcase + sys_user) author it. Per the maintainer ruling on #5611:
no union with string, no ADR-0087 conversion layer.
- `hideFields`: declared `z.array(z.string()).optional()`. Authored by
sys-user.page.ts and read by the renderer; undeclared, so a non-strict
z.object silently stripped it.
- `name` is declared because `packages/lint`'s translation-section-name-missing
rule tells authors to add it — a key one rule demands must not be a key the
schema rejects.
- Section `columns` uses an int range, not a literal union: same accepted set,
but the docs generator renders numeric literals as quoted strings (filed as
a separate finding), which would misdocument the key.
Aligns the two now-stale `packages/lint` comments that described these keys as
undeclared. Regenerated references/ui/component.mdx, authorable-surface.json and
the strictness-ledger counts (component.zod.ts gains one nested object site).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018fxLGQdatPbBUvCgiVxg6D
* chore(spec): 合并 main 后重生成 strictness-ledger counts 与 authorable-surface
合并 origin/main 后按 os-regen 纪律整体重生成(生成物不做文本合并):
- counts.md: 456 sites = 本分支 component.zod.ts 的 30 + main 新增
action-params.zod.ts 的 1。文本合并给不出这个联合结果,故由
gen:strictness-ledger 重算。
- authorable-surface.json: 重出后同时含本分支的
ui/RecordDetailsProps:hideFields 与 main 的 ui/ActionSession:* 三键。
- authorable-surface.base.json 的重锚(baseRev 前移 + api/Discovery:scoping)
与本 PR 无关,已剔除。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018fxLGQdatPbBUvCgiVxg6D
---------
Co-authored-by: Claude <noreply@anthropic.com>
|**sections**|`string[]`| optional |Section IDs to show (required when layout is "custom")|
294
+
|**sections**|`{ name?: string; label?: string; columns?: integer; fields: string[] }[]`| optional |Field groups rendered as the detail body, in order. Object form: `{ name?, label?, columns?, fields }`.|
295
295
|**fields**|`string[]`| optional | Explicit field list to display (optional, overrides highlightFields) |
296
+
|**hideFields**|`string[]`| optional | Field names to omit from the body — applied to `fields` and to every section's `fields` (used to dedupe fields already shown in `record:highlights` or as the page title) |
sections: z.array(z.string()).optional().describe('Section IDs to show (required when layout is "custom")'),
163
+
/**
164
+
* Field groups rendered as the detail body, IN ORDER.
165
+
*
166
+
* Declared as the object form because that is the only form anything
167
+
* delivers or authors (#5611). Until 17.x this key was `z.array(z.string())`
168
+
* — "section IDs" — which no page in this repo, and no read path in
169
+
* `objectui`, has ever used: `RecordDetailsRenderer` maps every entry as an
170
+
* object (`s.name` / `s.label` / `s.fields`) with no string branch anywhere,
171
+
* `@object-ui/types`' `RecordDetailsComponentProps` mirror declares the
172
+
* object form, and the Studio block designer can only author
173
+
* `{label, columns, fields}`. The ID-list spelling was a declaration with no
174
+
* producer and no consumer, so it is gone rather than unioned in: one shape,
175
+
* not two de-facto contracts (Prime Directive #12).
176
+
*/
177
+
sections: z.array(z.object({
178
+
/**
179
+
* Stable section identifier, snake_case. This is the i18n anchor: the
180
+
* heading resolves through `objects.<object>._sections.<name>.label`, so a
181
+
* section WITHOUT a name renders its authored `label` in every locale.
182
+
* `packages/lint`'s `translation-section-name-missing` rule exists to tell
183
+
* authors to add it, which is why it is declared here — a key one rule
184
+
* demands must not be a key the schema rejects.
185
+
*/
186
+
name: z.string().optional().describe('Stable section identifier for i18n lookup (snake_case) — resolves `objects.<object>._sections.<name>.label`; a nameless section renders its authored label in every locale'),
187
+
/** Heading text. Omit for an untitled section, which renders borderless. */
188
+
label: I18nLabelSchema.optional().describe('Section heading (omit for an untitled, borderless section)'),
189
+
/**
190
+
* Field-grid width for THIS section; falls back to the renderer's own
191
+
* derivation when omitted.
192
+
*
193
+
* An int range rather than `z.union([z.literal(1), …])` — same accepted set
194
+
* (1-4), but the docs generator renders numeric literals as QUOTED strings
195
+
* (`'1' | '2'`, see `FormSectionSchema.columns` in `references/ui/view.mdx`),
196
+
* which would tell an author to write `columns: '2'` where this key requires
197
+
* `2`. Shipping a reference that misdocuments the key is the exact harm
198
+
* #5611 is fixing, so the shape that documents itself truthfully wins.
199
+
*/
200
+
columns: z.number().int().min(1).max(4).optional().describe('Field-grid columns for this section (1-4). Omitted → the renderer derives the width.'),
201
+
/** Field names shown in this section, in order. */
202
+
fields: z.array(z.string()).describe('Field names rendered in this section, in order'),
203
+
})).optional().describe('Field groups rendered as the detail body, in order. Object form: `{ name?, label?, columns?, fields }`.'),
161
204
fields: z.array(z.string()).optional().describe('Explicit field list to display (optional, overrides highlightFields)'),
205
+
/**
206
+
* Field names to omit from the body, applied to both `fields` and every
207
+
* section's `fields`. Authored by the published `sys_user` platform page and
208
+
* read by `RecordDetailsRenderer`; it was simply never declared, so the
209
+
* (unvalidated) props bag carried it. Declared now so the enforcement to come
210
+
* does not silently strip a live platform page's hidden-field list.
211
+
*/
212
+
hideFields: z.array(z.string()).optional().describe('Field names to omit from the body — applied to `fields` and to every section\'s `fields` (used to dedupe fields already shown in `record:highlights` or as the page title)'),
0 commit comments