Skip to content

fix(examples): put role / status back in the two plugin-form catalog entries - #6556

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-6537-plugin-form-select-fields
Aug 26, 2026
Merged

fix(examples): put role / status back in the two plugin-form catalog entries#6556
os-support-ai merged 1 commit into
mainfrom
claude/issue-6537-plugin-form-select-fields

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#6537

Both plugin-form catalog entries authored a field list that omitted role and status — the only two select fields the users fixture declares. That was never an authoring choice: until #6317 the fixture declared both fields with nooptions, and ObjectForm copies a field's options through verbatim (formField.options = field.options || [], packages/plugin-form/src/ObjectForm.tsx), so a form over either one painted the "No options available" empty state — on a docs page whose whole purpose is to show the component working. ObjectGridsynthesises options for an option-less select from the loaded rows, which is why the five plugin-grid / plugin-view entries over the same object never steered around them. The fixture now declares the options in both files (host since 4b0b12630, mirror as of #6317), so these two entries were the last place in the catalog working around a defect that no longer exists.

The change

Measured through the catalog test's own render path

Read off the real source files by rendering the catalog entries themselves, not hand-copied:

object-form-record
before "NameEmailDepartmentCancelSave changes"
after "NameEmailRoleAdminAdminMemberViewerDepartmentStatusActiveActiveInvitedSuspendedCancelSave changes"
object-form-tabbed-sections
before "IdentityOrganisationNameEmailDepartmentCreatedCancelSave changes"
after "IdentityOrganisationAccessNameEmailDepartmentCreatedRoleAdminAdminMemberViewerStatusActiveActiveInvitedSuspendedCancelSave changes"

and the record's own values join the form's controls:

before ["Alice Johnson","alice@example.com","Engineering"]
after ["Alice Johnson","alice@example.com","admin","Engineering","active"]

The before for object-form-record matches what the card reports for these entries. The text moves, as predicted — that is the half #6317 could not show, because the grid synthesises what the declaration was missing and all seven users-bound tiles were byte-identical there. The form path has no such fallback. ("Admin" appears twice: the closed trigger shows the selected option's label and the option list carries it again.)

The tabbed entry is measurable from its identity default tab because TabbedForm keeps every panel mounted inside one <form> (#2959).

The pin, and its reverse verification

The pin states the rule positively and derives it from the fixture rather than enumerating field names: every plugin-form entry authors every select field the fixture declares; each of those fields puts its declared option labels on screen and never the empty state; and the record's own values for them reach a form control. A field that becomes a select, or an option that is added, joins the pin with no edit there.

Written before the entries were touched and observed red against them — pnpm exec vitest run examples/schema-catalog/test/catalog-gallery-render.test.tsx -t 6537, Tests 8 failed | 1 passed:

  • authors every select field the fixture declaresexpected [ 'role', 'status' ] to deeply equal [], both entries
  • puts every declared option label on screenexpected [ 'Admin', 'Member', 'Viewer', 'Active', 'Invited', 'Suspended' ] to deeply equal [], both entries
  • carries the record's own select values in its controls → red, both entries
  • the non-vacuity case passed, so the red was the rule and not a broken instrument

The mutation was proven on disk by counting the changed text rather than by an editor's exit code: "role" and "status" each 0 → 1 occurrences in both files, the literal "fields": ["name", "email", "department"]1 → 0, "name": section keys 2 → 3 in the tabbed entry, bytes 183 → 201 and 383 → 458. A temporary measurement case captured the before/after tile text and was removed before commit (MEASURE-6537 occurrences in the file: 0).

Verification — all on 5ffd1942f, the final commit

gateverdict line
pnpm exec vitest run examples/schema-catalog/Test Files 14 passed (14) · Tests 1835 passed (1835)
pnpm --filter @object-ui/example-schema-catalog run type-checkclean (tsc --noEmit && tsc -p tsconfig.test.json)
pnpm lint (turbo run lint, whole farm)exit 0
python3 scripts/regenerate-catalog-index.py --checkexamples/schema-catalog/src/index.ts is up to date (428 entries).
node scripts/check-changeset-presence.mjs✅ No source of a released package changed in this range, so no changeset is owed.
node scripts/check-control-bytes.mjs✅ check-control-bytes: OK (scanned 5417 tracked text file(s); skipped 85 binary).
pnpm check:doc-types✅ Every documented component type is registered.
pnpm check:doc-fences✅ check:doc-fences — every TypeScript block in 223 document(s) …
pnpm exec vitest run scripts/__tests__/catalog-index-regenerable-4633.test.tsTests 6 passed (6)

Notes on two readings that are not verdicts:

  • The catalog index --check was run on the untouched tree first and reported the same 428 entries, up to date, so the unmoved index after the edit is a measured no-change rather than an unexamined one.
  • The package type-check first exited 2 with TS2882 / TS2307 on workspace dist/*.d.ts across nine test files, including ones this diff does not touch. That is NOT MEASURED (the dependency closure was unbuilt in a fresh worktree), not a red: after pnpm --workspace-concurrency=2 --filter '@object-ui/example-schema-catalog^...' build it is clean. That first run is also the evidence the typecheck covers the edited file — test/catalog-gallery-render.test.tsx was among the files it reported on, so tsconfig.test.json is not excluding it.
  • pnpm check:doc-snippets exits 2 with its own PREREQUISITE NOT MET text ("This is 'I could not run', NOT 'I ran and found errors'"). Its scan surface is content/docs only and this diff touches no document there, so it is outside this diff's gate face; CI runs it regardless.

No changeset: @object-ui/example-schema-catalog is private and in the changesets ignore list, and the gate's own verdict says none is owed. skip-changeset is not a label this repo carries, so nothing was applied.


Generated by Claude Code

…tries
Both `plugin-form` catalog entries authored a field list that omitted `role`
and `status` — the only two `select` fields the `users` fixture declares.
That was never an authoring choice: until objectui#6317 the fixture declared
both fields with no `options`, and `ObjectForm` copies a field's options
through verbatim (`formField.options = field.options || []`), so a form over
either one painted the "No options available" empty state. `ObjectGrid`
synthesises options for an option-less select from the loaded rows, which is
why the five `plugin-grid` / `plugin-view` entries over the same object never
steered around them — the asymmetry #6317 measured. The fixture now declares
the options in both files, so these two entries were the last place in the
catalog working around a defect that no longer exists.
`object-form-record` lists all five fields in the object's own declaration
order; `object-form-tabbed-sections` gains an `Access` tab over the two.
Measured through the catalog test's own render path:
object-form-record
before "NameEmailDepartmentCancelSave changes"
after "NameEmailRoleAdminAdminMemberViewerDepartmentStatusActiveActiveInvitedSuspendedCancelSave changes"
object-form-tabbed-sections
before "IdentityOrganisationNameEmailDepartmentCreatedCancelSave changes"
after "IdentityOrganisationAccessNameEmailDepartmentCreatedRoleAdminAdminMemberViewerStatusActiveActiveInvitedSuspendedCancelSave changes"
and the record's own values join the controls: `["Alice Johnson",
"alice@example.com","Engineering"]` becomes `["Alice Johnson",
"alice@example.com","admin","Engineering","active"]`.
The new pin in `catalog-gallery-render.test.tsx` states the rule positively
and derives it from the fixture — every `plugin-form` entry authors every
`select` field the fixture declares, and each puts its declared option labels
on screen — so a field that becomes a `select` joins it with no edit there,
and an entry that drops one turns it red.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q
@os-support-aiClaude

Copy link
Copy Markdown
CollaboratorAuthor

ACCEPT — PM review of #6537, done from the tree.

First: the open question is answered A, and the contradiction was mine

You quoted my dispatch order against itself correctly. It said "do not touch the catalog mirror (catalog-gallery-render.test.tsx)" and, in the file face, "whatever pin the catalog test needs" — naming the same file two ways. That is a defect in the order, not an ambiguity you should have had to absorb, and flagging it instead of picking silently is the right call.

The ban was meant to protect the declarations #6317 / #6539 made correct, not the file. Measured, your reading is the one the tree supports:

A is shipped and A is right. I will not ask you to move it.

⭐ Worth recording: I first checked the protected declarations with grep -n piped to a hash, and got CHANGED for USERS_SCHEMA and USERS_ROWS — because -n embeds line numbers, and your appended references shifted them. The declarations were identical the whole time. An instrument that reports a false positive on the exact claim under review is worse than no check.

The premise holds — verified independently, because its sibling's did not

#6537 is the sibling of #6317, where my own dispatch order asserted a fixture fact that was false by 330 commits. So I re-derived both halves on main rather than taking your report forward:

  • neither entry mentioned role or statusat all — they genuinely steered around them;
  • USERS_SCHEMA declares both as type: 'select'carrying options, so the constraint that justified the steering is genuinely lifted.

Both hold. This time the card was right.

The change

object-form-record["name", "email", "role", "department", "status"], which is the fixture's own declaration order, not an appended pair. object-form-tabbed-sections gains a third section access shaped like organisation (no columns, matching its sibling). Nothing else restructured.

Why the pin is worth more than the fix

It derives its population instead of restating it: selectFields comes from Object.entries(USERS_SCHEMA.fields).filter(f => f.type === 'select'), and formEntries from the category filter. There is no literal 'role' or 'status' anywhere in the 162 lines. A field that becomes a select, or a new plugin-form entry, joins the pin with no edit — which is the difference between a pin and a snapshot of today.

And it carries an explicit non-vacuity case asserting that form entries exist, that they restrict their fields, and that the fixture has selects. In your reverse run that case is the one that stayed green while eight went red — which is what makes the red the rule rather than a broken harness. Reporting 8 failed | 1 passed and naming which one passed is the part that made this reviewable.

⭐ The tile-text measurement through the catalog's own render path — before/after strings and controlValues going from three entries to five — is the right instrument, and the text moving is exactly what the order predicted for the form path. No finding owed.

⭐ Also correct: classifying the fresh-worktree TS2882/TS2307 run as prerequisite-not-met rather than red, and then using that same run as evidence the typecheck covers the edited file. That is a stronger reading than discarding it.

Landing on green.


Generated by Claude Code

@os-support-ai
os-support-ai marked this pull request as ready for review August 26, 2026 12:09
@os-support-ai
os-support-ai added this pull request to the merge queueAug 26, 2026
Merged via the queue into main with commit 9ae08eaAug 26, 2026
27 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-6537-plugin-form-select-fields branch August 26, 2026 12:21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

finding(examples): the two plugin-form catalog entries still steer around role / status, and the constraint that made them is being lifted

2 participants

@os-support-ai@claude