Skip to content

test(schema-catalog): derive the own-plugin pin and generalize it to all 13 plugin-* categories - #6174

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-6024-catalog-own-plugin-pin
Aug 24, 2026
Merged

test(schema-catalog): derive the own-plugin pin and generalize it to all 13 plugin-* categories#6174
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-6024-catalog-own-plugin-pin

Conversation

@yinlianghui-tw

Copy link
Copy Markdown
Collaborator

Fixes#6024

Tests and test-config only. All gate output below was measured on 7ef59ccd1, which is this branch's head.

What changed

examples/schema-catalog/test/catalog-gallery-render.test.tsx's "entries use their own plugin" pin ran over a hand-enumerated two-row table (plugin-view, plugin-grid). It now runs over every plugin-* catalog category — thirteen of them — with the category/type map derived from the register() calls.

1. The map is a derivation, not a literal

deriveRegistryKeys from scripts/check-doc-component-types.mjs — the same derivation scripts/regenerate-known-schema-types.mjs already consumes — returns key -> registration sites. Joining those sites on the packages/DIR that owns them gives category -> key set, because catalog category and package directory are the same string. The value is a set, which plugin-charts requires (chart and bar-chart), and the rule stays per entry: every entry authors a node whose type is in the set its own package registers. Not "the category authors at least one".

The derivation earned its keep on its first run. The filing's hand-written table read plugin-form form. Measured against the register calls that is wrong — form is registered by packages/components/src/renderers/form/form.tsx:962, not by @object-ui/plugin-form, whose own keys are object-form, embeddable-form, form-analytics, object-master-detail-form. Both plugin-form entries are therefore the third instance of #5113's class. Filed as #6167, ledgered in OWN_PLUGIN_DEBT with a case asserting they still fail, so the ledger cannot rot green.

2. The RENDER half generalizes as MOUNT — it did not degrade to STRUCTURE

#5113's render half (a record that exists only in the gallery data source reaches the screen) cannot transfer to the eleven categories that author their data inline: there is no record they could not have supplied themselves. Rather than record them structure-only, they get a different formulation of "this really rendered through the plugin":

MOUNT — substitute every own-plugin node with an inert probe and re-render; the probe's marker must reach the DOM.

A stray type that is not a node, a node under a branch the parent never renders, and a node behind a satisfied hidden all satisfy STRUCTURE and all fail MOUNT. It also costs plugin-editor and plugin-map nothing: the probe replaces the renderer that wants Monaco / WebGL2, so their EXCLUSIONS entries buy them no reduction in this pin.

Data provenance is kept unweakened where it applies, and which entries those are is derived from each entry's own objectName against the fixture's object names — not declared, so a category that becomes object-bound picks the half up with no edit here.

3. The gate states its own split

it('states its own coverage split ...') pins the classification as a literal:

tiercategoriesentries
structure + mount + dataplugin-grid, plugin-view5
structure + mountthe other ten that render34
ledgered debt (#6167)plugin-form2

A new category, a new entry, or an entry changing tier turns that case red for review.

4. Two weaker render formulations were built, measured and rejected

Both as "the live tile shows content the probe-substituted tile does not":

  • by TEXTplugin-charts renders recharts into a container happy-dom gives zero size, so advanced-line-chart and simple-bar-chart paint 0 new text tokens against the probe render.
  • by ELEMENT COUNT — the same two tiles measured 3 live elements against 3 probe-substituted: no margin at all. The React.lazy categories (kanban, markdown, code-editor) additionally make the count depend on whether the dynamic import has landed.

A discriminator that is red on correct entries gets the gate deleted, so the honest claim is the one asserted and the split says how far it goes.

Verification

The derivation probe — the map FOLLOWS a rename

packages/plugin-markdown/src/index.tsx, one register() call renamed in a throwaway probe (restore trap on EXIT INT TERM; on-disk mutation confirmed by counting the deleted anchor and the injected text, not by the editor's exit code):

=== LEG 1 - as committed
plugin-markdown own set: markdown plugin-markdown:markdown
=== mutating the register call: markdown -> markdown-renamed-probe
on-disk proof - deleted-text anchor [ 'markdown',] before=1 after=0
on-disk proof - injected-text [ 'markdown-renamed-probe',] count=1
=== LEG 2 - with the register call renamed
plugin-markdown own set: markdown-renamed-probe plugin-markdown:markdown-renamed-probe
=== LEG 3 - restored
restore proof - anchor count: 1 restore proof - injected count: 0
plugin-markdown own set: markdown plugin-markdown:markdown

A first attempt on plugin-markdown used a single-line anchor that does not match its multi-line register( call. The mutation guard refused the reading (MUTATION DID NOT LAND - reading below is VOID) rather than reporting a green no-op.

Non-vacuity — two instruments blind, one not, over one tree

plugin-markdown/basic-markdown (a newly covered category, not plugin-view/plugin-grid) reverted to a hand-built card / h1 / text picture of the component:

=== INSTRUMENT 1: check-doc-component-types
exit=0
Scanned 184 doc file(s) ... 755 registered, 134 exempted.
✅ Every documented component type is registered.
=== INSTRUMENT 2+3: the #4616 sweep and the #6024 pin, one run
vitest exit=1
FAIL ... plugin-markdown/basic-markdown authors a node whose type its own package registers
FAIL ... plugin-markdown/basic-markdown mounts that node where the tile actually paints
#4616 sweep cases for this entry, occurrences in failure output: 0 and 0
Tests 2 failed | 562 passed (564)

The #4616 sweep still reports basic-markdown renders without a red tile and puts its authored content on screen as green. That contrast is the case for this pin existing.

The load-bearing half — MOUNT catches what STRUCTURE cannot

The same picture, plus a straymarkdown node parked inside props where no renderer reads it:

 on-disk proof - stray ["type": "markdown"] before=1 after=1
on-disk proof - picture ["type": "card"] count=1
vitest exit=1
FAIL ... plugin-markdown/basic-markdown mounts that node where the tile actually paints
STRUCTURE-case occurrences in failure output: 0
Tests 1 failed | 563 passed (564)

STRUCTURE passes on this tree. MOUNT is the only thing that goes red. That is the measurement behind the claim that the eleven newly covered categories did not quietly get the cheap half.

A fact the pin found while being written

no plugin-* entry authors Alice Johnson was first written corpus-wide and turned red immediately: components-layout-card/profile-detail-card and components-layout-card/user-list-card do author the string. They are hand-built cards, they carry no data half, and a corpus-wide assertion would have been red on two correct entries — so the case is scoped to this pin's own universe, with the two named in the comment.

Gates per this diff, each quoting its OWN verdict line

Exit codes captured before any pipe; three files changed (.changeset/*.md, the test, tsconfig.test.json).

gateexitits own verdict line
vitest run examples/schema-catalog/test/catalog-gallery-render.test.tsx0Test Files 1 passed (1) / Tests 564 passed (564)
vitest run examples/schema-catalog/0Test Files 12 passed (12) / Tests 1768 passed (1768)
vitest run scripts/__tests__/{check-doc-component-types,known-schema-types-derivation-5115,scripts-type-check,vitest-invocation-guard}.test.ts0Test Files 4 passed (4) / Tests 89 passed (89)
pnpm --filter @object-ui/example-schema-catalog type-check0(both tsc projects, no diagnostics)
pnpm turbo run lint --concurrency=20Tasks: 47 successful, 47 total — 0 errors repo-wide
node scripts/check-type-check-coverage.mjs0✅ test type-check coverage: 41/41 packages compile their tests, 0 declared debt
node scripts/check-lint-coverage.mjs0✅ lint coverage: 46/46 packages linted, 0 with outstanding errors (0 total).
node scripts/check-control-bytes.mjs0✅ check-control-bytes: OK (scanned 5099 tracked text file(s); skipped 85 binary).
node scripts/check-doc-component-types.mjs0✅ Every documented component type is registered.
node scripts/check-changeset-no-major.mjs0✅ No changeset declares a major bump.
node scripts/check-changeset-presence.mjs0✅ No source of a released package changed in this range, so no changeset is owed.
pnpm type-check:scripts0(no diagnostics)

Vitest was run from the repo root throughout (objectui#3378). The repo-wide lint farm ran in full, so no narrowing is claimed.

Note on tsconfig.test.json

examples/schema-catalog/tsconfig.test.json gains allowJs (with checkJs off) and a repo-root rootDir. That is the same answer tsconfig.scripts.json reached in objectui#3494 for importing a plain-JS CI helper into a typed pin test: the alternative, a hand-written .d.mts beside the .mjs, is a second source of truth free to drift, whereas inferred types mean changing the helper's exported signature turns this test red. rootDir is checked against every file in the program (TS6059) even under noEmit, and nothing else reads it here.


Generated by Claude Code

…all 13 plugin-* categories
`catalog-gallery-render.test.tsx`'s "entries use their own plugin" pin ran over a
hand-enumerated two-entry `CATEGORY_OWN_TYPE` table. Replace it with a map derived from
the `register()` calls (`deriveRegistryKeys`, joined on the `packages/<dir>` registration
site) and turn the pin on for every `plugin-*` catalog category.
The value is a set, because `plugin-charts` entries author `chart` and `bar-chart`, and
the rule stays per entry. objectui#5113's RENDER half only applies where a record can
exist that the entry's own JSON could not supply, so rather than degrade to STRUCTURE for
the eleven categories that author their data inline, add a MOUNT half that applies to all
of them: replacing every own-plugin node with an inert probe must put the probe's marker
on screen. Data provenance is unchanged for the entries that bind to a fixture object,
derived per entry from `objectName`. The gate prints and pins its own coverage split.
The derivation immediately falsified the filing's hand-written table: `form` is registered
by `packages/components`, not `@object-ui/plugin-form`, so both `plugin-form` entries are
the third instance of objectui#5113's class. They are ledgered against objectui#6167 with
a case asserting they still fail.
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.

Generalize the catalog "entries use their own plugin" pin to every plugin-* category — #5856 removed its last obstacle

2 participants

@yinlianghui-tw@claude