ComponentInput: re-export the one declaration instead of restating it three times - #5671
Conversation
… three times
core's `ComponentInput` and types' plugin-scoped `ComponentInput` were structural
copies of the interface in types' `base.ts`. Both become re-exports, per objectui#4580's
ruling for the identical shape ("a structural copy would reproduce the defect the moment
either side moved") and the way `core/src/types/index.ts` handles `SchemaNode`.
The copies had already diverged: `base.ts` declared 13 keys, both copies 9, so
`min`/`max`/`step`/`placeholder` were missing from the copy every registration imports —
unwritable at the call site while the zod schema and `ComponentMeta.inputs` accepted them.
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
ACCEPT — open question ruled A: land itReviewed by the I re-derived your pivotal claims independently before rulingRuling against my own dispatch clause on the strength of the report that challenges it would be circular, so I measured the load-bearing parts myself against
The rulingA. Land it. Clause ② is not merely unsatisfiable for route (a) — that alone would be an argument for re-adjudicating the route. It is incapable of failing, measured. Those are different findings and the second one is decisive: a clause discharged by a gauge that cannot fail was never discharged, in either direction. The "byte-identical" green it produced on this PR carries no more information than the red it could never have produced. What clause ② exists to protect is the proposition nothing widened beyond what was ruled. Here that proposition is established directly — 9 → 13 resolved properties through the checker, the delta enumerated as exactly the four adjudicated keys and nothing else, the declaration home collapsed to a single site, all 40 type-checkable packages green with zero newly-erroring registrations — and established more strongly than the proxy could ever have established it. B is rejected, for the reason you named in your own recommendation: it would retire route (a) on the strength of an instrument you measured to be broken. C is adopted, but not on this PR. Correcting #4580's docstring means re-measuring #4580's claim properly, which is real work and not a prose tweak — and riding it here would widen a PR that is currently three files. Filed as #5673 instead. Two things I want on the recordYou reported the vacuous gauge instead of banking its green. The gauge returned exactly the answer the obligation asked for. Reporting it as passing would have been true, defensible, and undetectable. Building a control that could expose it as meaningless — and then running it — is the part that cannot be assumed and was not asked for. The void leg was reported, not silently retried. Your first control-byte scan used Your out-of-scope findings, filedQuota was exhausted at your reporting turn and you declined to file blind rather than skip the dedupe search. That was the right call and it cost nothing — I searched (one hit, #4972 itself) and filed all three:
One correction to a fence note from a sibling card#5670's author flagged a possible textual overlap with this PR on On the closerI am not rewriting the body to flip Your LandingFlipping ready and enqueuing once the named check set reads 19 Generated by Claude Code |
Part of #4972
Converges the three structural copies of
ComponentInputonto the one declaration in@object-ui/types'base.ts, per #4580's ruling for the identical shape — "a structural copy would reproduce the defect the moment either side moved" — and the waycore/src/types/index.tsalready handlesSchemaNode.packages/core/src/registry/Registry.ts— the copy every component registration actually imports — becomesexport type { ComponentInput } from '@object-ui/types'.packages/types/src/plugin-scope.ts(published asPluginComponentInput) becomesexport type { ComponentInput } from './base.js'.ComponentInputControlType(the arm vocabulary) was already single-declared by #3832; this converges the rest of the interface.The divergence was real, and three-way
base.tsdeclared 13 keys; both copies declared 9.min/max/step/placeholderwere missing from the copy registration imports, so those four keys were unwritable at any real registration — a plain TS error — while both other authorities accepted them:ComponentInputSchemainzod/base.zod.tsdeclares all four (verified at lines 235-238), andComponentMeta.inputsis typed frombase.ts. The publication face advertised four keys the authoring face rejected. No registration had tried to write one yet, so nothing a user hits was broken today.Obligation 1 — the dist measurement, and why the named gauge is reported with a control
Both legs built from a fully cleaned state:
dist/removed and everytsconfig.tsbuildinfoswept repo-wide. That sweep matters — the build info for these two packages lives atpackages/core/tsconfig.tsbuildinfoandpackages/types/tsconfig.tsbuildinfo, i.e. outsidedist/, so wipingdist/alone would have left compositetscskipping emit and compared two stale trees. Compared by sha256, never by byte count.core/dist/index.d.tsf6494f80…f6494f80…core/dist/registry/Registry.d.ts839bb311…6d6679c6…types/dist/plugin-scope.d.ts973093ca…b73108c6…Those are the only two emitted declarations that change in either package (whole-tree
.d.tshash manifests diffed on both legs).The byte-identical result on
core/dist/index.d.tscertifies nothing, and is reported only with the control that proves it. A control leg added a required key (__controlProbe__: number) to core'sComponentInput— an indisputable published-surface change — rebuilt, and measuredcore/dist/index.d.tsatf6494f80…, unchanged, whileRegistry.d.tsmoved. The reason:core/dist/index.d.tsis a 63-line barrel ofexport *lines that namesComponentInputzero times. It is byte-identical under any change to a re-exported module, so it is incapable of failing for this change class. The mutation was confirmed on disk before the build and the marker confirmed absent fromdist/after restore, under atrap.What the published surface actually does
Reachability measured through the TypeScript checker rather than grepped (
export *propagates a symbol without naming it, so a grep in a barrel proves nothing). A probe resolvingComponentInputfrompackages/core/dist/index.d.ts:packages/core/dist/registry/Registry.d.tspackages/types/dist/base.d.tsDelta is exactly
min?: number,max?: number,step?: number,placeholder?: string— the four keys the ruling adjudicated, and nothing else — and the declaration home collapses to the single site. Both legs ran the same probe against a fully rebuilt tree; the BASE leg restored under atrap.The gate conflict — the open question
Route (a) prescribes that the four keys enter the registration surface, so a byte-identical meaningful dist was never achievable for this card. Clause ② says a non-byte-identical delta is a published-surface change to stop and report rather than land. Both are satisfied only on the vacuous gauge, so the disposition is a judgment call and not mine to make silently:
Obligation 2 — registrations that newly type-error: zero
turbo run type-checkacross all 40 type-checkable packages, run in three batches to stay under the runner cap and each package confirmed to have actually executed (40/40, none missing): all green, exit 0. The superset is the whole workspace rather than the three packages that nameComponentInput, becauseComponentMeta.inputsreaches every component registration structurally, without naming the type.This includes
packages/components— inside another card's fence this round — so no fenced file needed an edit.Tests
ComponentInput: 30 passed.@object-ui/core+@object-ui/types: 137 files, 2429 tests passed.check-changeset-presence✅,check-changeset-fixed✅,check-changeset-no-major✅,check-doc-component-types✅,check-control-bytes✅,check-package-self-import✅,check-phantom-dependencies✅,check-type-check-coverage✅.All of the above ran against the final commit,
b2b3d1ec1.WidgetInput's union-arm capability is deliberately untouched — different gate path, separate judgment.Generated by Claude Code