From dc44f49d9e2260110481659a5ac8bd384360f00f Mon Sep 17 00:00:00 2001 From: os-sales Date: Fri, 28 Aug 2026 07:16:40 +0000 Subject: [PATCH] docs(types): record that `field` is excluded from the form-field pin ON PURPOSE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `packages/types/src/__tests__/form-field-zod-coverage.test.ts` introduced its pinned key list as "Every key `FormField` (../form.ts) declares by name". The interface declares one key the list deliberately omits — `field`, the resolved object-field metadata stash (objectui#3090) — so the sentence overclaimed, and the pin's own rule ("any schema edit must touch the list here in the same PR") read as an invitation to close the gap by adding `field` to `DECLARED_KEYS` and to `FormFieldSchema`. That would make `objectui validate` accept and type a runtime-only stash on authored documents, re-opening the spec-vocabulary pun objectui#3090 closed at the `normalizeSectionField` chokepoint — a contract widening arriving disguised as housekeeping. The list header now says what the list is (the authorable key surface) and records the exclusion as deliberate, with the reason. The `FormFieldSchema` doc comment in `packages/types/src/zod/form.zod.ts` carried the same "keys mirror the interface" overclaim and is corrected the same way. Prose only: no schema change, no test-logic change, no behaviour change. Every changed line in both files is a comment line. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_8ca04858-ea8e-5b85-9182-de59aa49e00c --- .../6609-declared-keys-header-honesty.md | 22 +++++++++++++++ .../__tests__/form-field-zod-coverage.test.ts | 27 +++++++++++++++++-- packages/types/src/zod/form.zod.ts | 16 +++++++---- 3 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 .changeset/6609-declared-keys-header-honesty.md diff --git a/.changeset/6609-declared-keys-header-honesty.md b/.changeset/6609-declared-keys-header-honesty.md new file mode 100644 index 0000000000..3fd873d9a3 --- /dev/null +++ b/.changeset/6609-declared-keys-header-honesty.md @@ -0,0 +1,22 @@ +--- +--- + +Comment-only truthfulness fix in `@object-ui/types`; no published behaviour changes, no +schema change, no test-logic change. + +`packages/types/src/__tests__/form-field-zod-coverage.test.ts` introduced its pinned key +list as "Every key `FormField` (../form.ts) declares by name". The interface declares one +key the list deliberately omits — `field`, the resolved object-field metadata stash +(objectui#3090) — so the sentence overclaimed, and the pin's own rule ("any schema edit +must touch the list here in the same PR") read as an invitation to close the gap by adding +`field` to `DECLARED_KEYS` and to `FormFieldSchema`. Doing that would make +`objectui validate` accept and type a runtime-only stash on authored documents, +re-opening the spec-vocabulary pun objectui#3090 closed at the `normalizeSectionField` +chokepoint — a contract widening arriving disguised as housekeeping. + +The list header now says what the list is (the AUTHORABLE key surface) and records the +exclusion as deliberate, with the reason: the stash is runtime-only, and the same key +name in the authored spec form-view vocabulary is a string naming the referenced object +field. The `FormFieldSchema` doc comment in `packages/types/src/zod/form.zod.ts` carried +the same "keys mirror the interface" overclaim and is corrected the same way +(objectui#6609). diff --git a/packages/types/src/__tests__/form-field-zod-coverage.test.ts b/packages/types/src/__tests__/form-field-zod-coverage.test.ts index e055e068cb..850d3f557e 100644 --- a/packages/types/src/__tests__/form-field-zod-coverage.test.ts +++ b/packages/types/src/__tests__/form-field-zod-coverage.test.ts @@ -22,13 +22,36 @@ * objectstack#4075 mechanism — see check-spec-symbol-derivation.mjs, lie #3). * A set-coverage assertion is the #3017 fallback for exactly this case: the * zod side stays deliberate and reviewed, and any schema edit must touch the - * list here in the same PR. + * list here in the same PR. That list is the AUTHORABLE key surface, not every + * key the interface declares — one declared key sits outside it on purpose, for + * the reason its own note records (objectui#6609). */ import { describe, it, expect } from 'vitest'; import { FieldConstraintsSchema, FormFieldSchema } from '../zod/form.zod.js'; -/** Every key `FormField` (../form.ts) declares by name, in declaration order. */ +/** + * The AUTHORABLE key surface of `FormField` (../form.ts) — the keys a DOCUMENT + * may itself carry, and so the keys `objectui validate` parses through this + * schema. Ordered to follow the interface loosely, as a reading aid only: the + * assertion sorts both sides, so the order here carries no claim (`visibleOn` + * precedes `hidden`/`readonly` in the interface and follows them here). + * + * ⚠️ NOT "every key the interface declares by name", and the gap is DELIBERATE. + * `FormField` also declares `field` — the resolved object-field metadata stash + * (#3090), which the object-bound form paths fill at RUNTIME with a + * server-served field definition so widgets can read `precision`, `currency`, + * `reference_to`, … No document ever writes it. And on the SPEC form-view side + * — the other authoring surface, the one #3090 keeps separate — that same key + * name means something else entirely: a STRING naming the referenced object + * field. Admitting `field` here and to `FormFieldSchema` would therefore make + * `objectui validate` accept and type a runtime-only stash on authored + * documents, re-opening the exact spec-vocabulary pun #3090 closed at the + * `normalizeSectionField` chokepoint. The refusal is pinned below by the + * `still rejects the SPEC form-field vocabulary` case: `{ field: 'email' }` + * must not parse. So a `field` entry here is a contract widening to be ruled + * on — never housekeeping that restores consistency (objectui#6609). + */ const DECLARED_KEYS = [ 'id', 'name', diff --git a/packages/types/src/zod/form.zod.ts b/packages/types/src/zod/form.zod.ts index 0276c9046e..1ba4d41409 100644 --- a/packages/types/src/zod/form.zod.ts +++ b/packages/types/src/zod/form.zod.ts @@ -444,11 +444,17 @@ export const CommandSchema = BaseSchema.extend({ * different layers, and `normalizeSectionField` in `@object-ui/plugin-form` is * the translation chokepoint between them (#3090). * - * Keys mirror the `FormField` interface in `../form.ts`. Until #3090 this - * schema validated only 13 of the interface's declared keys and *required* - * `type` (the interface says optional) — so `objectui validate` silently - * ignored typos in `visibleWhen`/`widget`/`dependsOn`/… (strip mode) and - * rejected metadata the renderer accepts. The pinned key list lives in + * Keys mirror the AUTHORABLE surface of the `FormField` interface in + * `../form.ts` — not every key that interface declares. `FormField.field` (the + * resolved object-field metadata stash) is runtime-only and stays OUT of this + * schema on purpose: in the authored vocabulary that same key name carries a + * different meaning — a string naming the referenced object field — so + * validating it here would re-open the pun #3090 closed (objectui#6609). + * + * Until #3090 this schema validated only 13 of the interface's declared keys + * and *required* `type` (the interface says optional) — so `objectui validate` + * silently ignored typos in `visibleWhen`/`widget`/`dependsOn`/… (strip mode) + * and rejected metadata the renderer accepts. The pinned key list lives in * `__tests__/form-field-zod-coverage.test.ts`. */ /**