Skip to content

Commit 3fa1938

Browse files
docs(plugin-form): object-master-detail-form's fields description says it bounds what is drawn; Save also writes seeded initialValues (objectui#11114) (#11149)
Fixes #11114 Clause-②: no The `object-master-detail-form` registration called its `fields` input "the submitted set". Save writes more than that: a parent value seeded through `initialValues` (or `initialData`) that `fields` does not list is written too. The triage ruling on the card (comment 5893817922) keeps the behaviour and corrects the text, so that is what this PR does. ⛔ No behaviour changes; the parent leg is not filtered to `fields`. ## What changed - `packages/plugin-form/src/index.tsx`: the `fields` input's description. Only the clause "this key is also the parent pool for values, create defaults and the submitted set" is replaced; the rest of the sentence is byte-identical. It now says `fields` bounds what the form DRAWS and edits, and that on a create the submitted set is the drawn fields plus any parent value seeded through `initialValues` (or its alternate spelling `initialData`), drawn or not. It adds one qualifier the probes below measured: a seed for an undeclared, server-owned, computed or read-only field is still stripped, as on any save. - `packages/plugin-form/src/__tests__/topLevelFieldsWarnCoverage-8847.test.tsx`: the pin 「the key bounds what is DRAWN, not what the parent leg WRITES」 keeps its direction, its title and its assertion. Its header bullet and the inline comment above the assertion now cite the ruled behaviour instead of describing it as "handed back". - `packages/plugin-form/src/ObjectForm.tsx`: comment only, see the surface note below. - `.changeset/11114-master-detail-fields-text.md`: `@object-ui/plugin-form` patch. ## Measured at `385ebc5c6` (the dispatch's mechanism assumptions) 1. Premise holds: the clause and the pin were both present as the card says. 2. Real `MasterDetailForm` mounted in create mode, `fields: ['status']`, the create Save clicked, the batch's parent leg read from `dataSource.batchTransaction` (throwaway probe file, deleted; not committed): - `initialValues: { status, note }` gives a parent leg carrying `note`, which is not drawn. Same with `initialData` as the seed. - A seed for a key the object does not declare is dropped. Seeds for a `readonly` field, a `formula` field and `owner_id` are dropped. - `details[].totalField` writes its rollup onto the parent whatever `fields` lists (`total: 0` in the probe). - An object field `memo` with a static `defaultValue` that `fields` does not list, and that nobody seeded, is written (`memo: 'object-default'`). This is the dispatch's "different defect" question; it is reported on the card, not changed or described here. 3. Published: `object-master-detail-form` is in the public block tier, and `manifestFromConfigs` copies each input's `description` verbatim. A throwaway probe over the real registry read the plugin-form manifest entry after this change: the new sentence present, the old clause absent, and an unchanged phrase of the same description ("the two INTERSECT") present as the positive control. No generated file in this repo carries the text (`git grep` for the description's opening words finds `index.tsx` only), so nothing here is regenerated. The pinned `sdui.manifest.json` copy that objectstack holds follows at its own sync. ## Surface note The claimed file surface was `index.tsx`, the 8847 pin and a changeset. One file is beyond it: the comment in `ObjectForm.tsx` beside the sections/fields intersection said `fields` is "the parent field pool for values, create defaults and the submitted set". That is the same false claim in the implementation, and the description's own wording derives from it. It is corrected in place under the bounded exemption, with all four conditions checked: same defect class; a mechanical comment rewording; no open PR touches `ObjectForm.tsx` (the open PR list's file sets were read); no gate family beyond this PR's. The surface is supplemented here rather than in a new claim. ## Not touched (Acceptance notes) - `apps/console/src/__tests__/registry-inputs-spec-parity.test.ts`: the ledger row `pins:` for `object-master-detail-form.fields` still says "the registration calls this key the parent pool for 'the submitted set'", which is now stale, and so does the historical slice-18 docblock. Left alone because open PR objectui#11086 holds that file. Both belong to whoever next edits it. - `sectionEntryOverrides-10475.test.tsx` quotes the earlier card wording "values, create defaults and the submitted set stay pool-driven" inside a quotation; not edited. - Pending changeset `8738-object-form-fields-description.md` names `ObjectForm.tsx` (flagged by `check-changeset-claims`, report-only); read, still true. - The `initialValues` input's own description ("Values to prefill on the PARENT record in `create` mode.") is unchanged; the `fields` description now carries the fact. ## Verification - `pnpm exec vitest run` on the 8847 pin plus the three sibling master-detail member files: 4 files, 29 tests passed. - `pnpm exec vitest run` on the console's registry consumers (`registry-inputs-spec-parity`, `masterDetailFormTypeManifest`, `masterDetailFormI18nLabelManifest`, `public-contract`, `public-block-binding-reach`): 5 files, 257 tests passed. - `pnpm --filter @object-ui/plugin-form type-check` after `pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-form^...' build` (the dependency closure): exit 0. - `pnpm exec eslint --no-inline-config` on the three changed source files: 3 files linted, 0 errors, 86 warnings, none on a changed line. - `check-changeset-presence`, `check-control-bytes`, `check:new-line-citations`, `changeset:check`: exit 0 each, re-run at `813b8826f` for the first three. - No reverse verification or ablation: the change is text only and no behaviour moved, so there is nothing that could turn red. --- _Generated by [Claude Code](https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3f61eef commit 3fa1938

4 files changed

Lines changed: 24 additions & 12 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@object-ui/plugin-form': patch
3+
---
4+
5+
The `object-master-detail-form` registration's `fields` description no longer calls that key "the submitted set" (objectui#11114).
6+
7+
The sentence told an author, or an AI authoring metadata, that the parent field pool bounds what Save writes. It does not, and it was never meant to: `fields` bounds what the parent form DRAWS and edits, and on a create the parent leg of the atomic batch is the drawn fields plus any parent value seeded through `initialValues` (or its alternate spelling `initialData`), drawn or not. The description now says exactly that, and adds that a seed for an undeclared, server-owned, computed or read-only field is still stripped, as on any save.
8+
9+
Text only. The description is a declared input of a public-tier block, so it reaches the published `sdui.manifest.json`; no input, type, default or accepted value moves, and no runtime behaviour changes. The parent leg is deliberately not filtered to `fields`: that would silently drop author-seeded values, which is how a hidden parent key reaches a record.

‎packages/plugin-form/src/ObjectForm.tsx‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,9 +1650,11 @@ const SimpleObjectForm: React.FC<{ schema: LocalizedObjectFormSchema; dataSource
16501650
// section whole, heading included.
16511651
//
16521652
// ⛔ The intersection itself is NOT the defect and is deliberately left
1653-
// standing: `fields` is the parent field pool for values, create
1654-
// defaults and the submitted set as well as for layout, so resolving
1655-
// these members here would change what a landed schema writes. What WAS
1653+
// standing: `fields` is the parent field pool that bounds what this form
1654+
// DRAWS and edits, so resolving these members here would change what a
1655+
// landed schema draws and lets a user edit. It does not bound the write
1656+
// itself: a value seeded through `initialValues` is written whether or
1657+
// not it is drawn (objectui#11114). What WAS
16561658
// the defect is that the loss was silent, plus this block's registration
16571659
// claiming `fields` is "Ignored when `sections` is given" — a claim its
16581660
// three sibling `fields` registrations never made and the one shared

‎packages/plugin-form/src/__tests__/topLevelFieldsWarnCoverage-8847.test.tsx‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@
5353
* - `{ name }` is tolerated as the same member as the bare name;
5454
* - ⚠️ the key bounds what is DRAWN, not what the PARENT leg of the atomic
5555
* batch WRITES: a seeded parent field it does not list is still written.
56-
* That is pinned as behaviour and handed back, not changed here, because
57-
* the registration's description calls this key the parent pool for "the
58-
* submitted set". Changing it is a decision about the renderer or the
59-
* declaration, and this card writes pins only.
56+
* That is the ruled behaviour (objectui#11114), not a defect: the
57+
* registration's `fields` description says that, on a create, the submitted
58+
* set is the drawn fields plus any seeded `initialValues`, and this row is
59+
* what keeps that sentence true.
6060
*
6161
* `MasterDetailForm` reads none of this itself. The `parentSchema` memo copies
6262
* `fields` onto an `object-form`-shaped node rendered through a DIRECTLY
@@ -268,10 +268,11 @@ describe('object-master-detail-form `fields` — the member shape (objectui#8071
268268
const ops = dataSource.batchTransaction.mock.calls[0][0] as Array<Record<string, any>>;
269269
expect(ops).toHaveLength(1);
270270
expect(ops[0]).toMatchObject({ object: 'invoice', action: 'create' });
271-
// Pinned as BEHAVIOUR and handed back rather than changed here: the
272-
// registration's `fields` description calls this key the parent pool for
273-
// "the submitted set", and a seeded field outside it is written all the
274-
// same. Hiding a field with `fields` does not stop its seed being saved.
271+
// The ruled behaviour, not an accident (objectui#11114): the registration's
272+
// `fields` description says that, on a create, the submitted set is the
273+
// drawn fields plus any seeded `initialValues`, so a seeded field outside
274+
// `fields` is written all the same. Hiding a field with `fields` does not
275+
// stop its seed being saved.
275276
expect(ops[0].data).toEqual({ status: 'draft', memo: 'seeded' });
276277
});
277278
});

‎packages/plugin-form/src/index.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ ComponentRegistry.register('object-master-detail-form', MasterDetailFormRenderer
479479
// Declaring them would mint choices an authoring UI offers and this block
480480
// cannot honour.
481481
{ name: 'formType', type: 'enum', enum: ['simple', 'tabbed'], description: 'How the PARENT half of the form is presented. The detail grids below it are unaffected.' },
482-
{ name: 'fields', type: 'array', description: 'Which parent fields to show, in order — and it is NOT ignored when `sections` is given: the two INTERSECT. The parent field pool is built from this key first and every section then resolves its own members against that pool, so a section member this key does not list is dropped from the rendered form, and a section that loses EVERY member that way disappears with its heading. Each such drop is reported once via `console.warn` (objectui#9884); it is not repaired, because this key is also the parent pool for values, create defaults and the submitted set. Author one or the other, or list every section member here too. Members are bare field names (`{ name }` tolerated); NOT the spec `FormFieldSchema` object `sections[].fields` accepts (identity key `field`) — that shape resolves to no name here and is silently skipped (the parent form renders through the same `ObjectForm` / `SimpleObjectForm` as `object-form` — see its `fields` description).' },
482+
{ name: 'fields', type: 'array', description: 'Which parent fields to show, in order — and it is NOT ignored when `sections` is given: the two INTERSECT. The parent field pool is built from this key first and every section then resolves its own members against that pool, so a section member this key does not list is dropped from the rendered form, and a section that loses EVERY member that way disappears with its heading. Each such drop is reported once via `console.warn` (objectui#9884); it is not repaired, because this key bounds what the form DRAWS and edits, not what Save writes: on a create, the submitted set is the drawn fields plus any parent value seeded through `initialValues` (or its alternate spelling `initialData`), drawn or not. A seed for an undeclared, server-owned, computed or read-only field is still stripped, as on any save. Author one or the other, or list every section member here too. Members are bare field names (`{ name }` tolerated); NOT the spec `FormFieldSchema` object `sections[].fields` accepts (identity key `field`) — that shape resolves to no name here and is silently skipped (the parent form renders through the same `ObjectForm` / `SimpleObjectForm` as `object-form` — see its `fields` description).' },
483483
// The three labels are the spec's `I18nLabel` (`ComponentPropsMap
484484
// ['object-master-detail-form']`), and `MasterDetailForm` resolves a map
485485
// with `pickLocalized` against the active UI language (objectui#10935). So

0 commit comments

Comments
 (0)