diff --git a/.changeset/24047-action-param-options-comments.md b/.changeset/24047-action-param-options-comments.md new file mode 100644 index 00000000000..0c6bf95ea44 --- /dev/null +++ b/.changeset/24047-action-param-options-comments.md @@ -0,0 +1,14 @@ +--- +'@objectstack/spec': patch +--- + +Clause-②: no + +The `ActionParam` `options` docblock in `src/ui/action.zod.ts`, and the comment above that option +shape's `guidance` table, no longer say that objectui's `normaliseOptions` rebuilds each option a +field-backed param inherits as a bare `{ label, value }` pair. At the console pin (`.objectui-sha` +`f8267df93aba`) it keeps every key of an inherited option by spread +(`packages/fields/src/resolveActionParams.ts:515` in objectui). The comments now give the reason +that remains for the `guidance` texts not telling an author to make a param field-backed and +inherit `color`, `icon` or `disabled`: the keys survive, but no reader of them on that path is +measured. No key, schema, export, accepted value or message text changes. diff --git a/packages/spec/src/ui/action.test.ts b/packages/spec/src/ui/action.test.ts index b5fbdba12f8..aff2f715863 100644 --- a/packages/spec/src/ui/action.test.ts +++ b/packages/spec/src/ui/action.test.ts @@ -1754,8 +1754,9 @@ describe('action param option vocabulary — declared only where a renderer deli // `color`: real one layer down, on the STORED-value display path. The // sentence must no longer defer to #5016 as an open question — it is - // decided — and must not promise the field-backed inheritance route, which - // `normaliseOptions` still drops (ledger finding 18). + // decided — and must not promise the field-backed inheritance route: + // objectui's `normaliseOptions` keeps the key by spread, but no reader of + // it on that route is measured (ledger finding 18). const color = messageFor({ label: 'A', value: 'a', color: 'red' }); expect(color).toContain('SelectOptionSchema'); expect(color).not.toContain('do not rely on it today'); diff --git a/packages/spec/src/ui/action.zod.ts b/packages/spec/src/ui/action.zod.ts index a3270bbbcfb..1652173322c 100644 --- a/packages/spec/src/ui/action.zod.ts +++ b/packages/spec/src/ui/action.zod.ts @@ -265,15 +265,18 @@ export const ActionParamSchema = lazySchema(() => strictObject( * `default` it would actively mislead, since a dialog param defaults * through `defaultValue` one level up. * - * **What this does NOT fix**, deliberately, because it is objectui's and not - * the spec's: a FIELD-BACKED param that inherits its list instead of declaring - * one still loses the key. `resolveActionParam` reaches - * `param.options ?? normaliseOptions(field.options, …)`, and `normaliseOptions` - * rebuilds every inherited entry as `{ label, value }`. That drop predates - * this change, is invisible to it (an authored `options` array wins over the - * inherited one), and is tracked in objectui — so the guidance below still - * refuses to prescribe "make it field-backed and inherit" (ledger finding 18: - * a confidently wrong prescription is worse than none). + * **A FIELD-BACKED param that inherits its list** instead of declaring one + * takes objectui's path, not the spec's. At the console pin (`.objectui-sha` + * `f8267df93aba`), objectui's `packages/fields/src/resolveActionParams.ts` + * resolves it as `authoredOptions ?? normaliseOptions(field.options, …)` + * (`:650`–`:651`), and `normaliseOptions` returns + * `{ ...raw, label, value: raw.value }` per entry (`:515`), so every key of an + * inherited entry survives the resolver. An authored `options` array still + * wins over the inherited one. Surviving is not being read: no reader of + * `color` / `icon` / `disabled` on an inherited option is measured from this + * repo, so the guidance below still refuses to prescribe "make it + * field-backed and inherit" (ledger finding 18: a confidently wrong + * prescription is worse than none, and an unmeasured one is no cure for it). * * The aliases are anchored on `SelectOptionSchema`'s own curated table (the * same idea, one layer down) rather than on edit distance, and deliberately @@ -307,9 +310,11 @@ export const ActionParamSchema = lazySchema(() => strictObject( // The per-option keys that are real one layer down but have no reader on // THIS path, plus the two that no spec shape declares at all. Each says // where the vocabulary lives and — critically — does NOT promise that a - // field-backed param inherits it: `resolveActionParams`' `normaliseOptions` - // rebuilds each inherited entry as `{ label, value }`, so that promise - // would be false in exactly the way ledger finding 18 warns about. + // field-backed param inherits it. objectui's `normaliseOptions` keeps an + // inherited entry's keys by spread (the `options` docblock above cites the + // pin and line), but no reader of them on the inherited path is measured + // from this repo, so that promise would be an unmeasured one in exactly + // the way ledger finding 18 warns about. // // `visibleWhen` is deliberately absent: it is a declared key now, and // `guidance` is consulted only from the `unrecognized_keys` path, so an