feat(types): name InputShorthandSchema and UiCalendarSchema on the root barrel (objectui#9406) - #9525
Conversation
…ot barrel (objectui#9406)
`import type { UiCalendarSchema } from '@object-ui/types'` read TS2724 while
`CalendarSchema`, its neighbour on the very same `./form.js` re-export list,
resolved in the same compilation pass. The compiler's answer was worse than an
absence: it suggested a DIFFERENT component (`CalendarSchema` for
`UiCalendarSchema`, `InputOTPSchema` for `InputShorthandSchema`), and an author
who follows the suggestion writes an import that compiles and means something
else.
Both names were already published on `@object-ui/types/form` and
`@object-ui/types/zod`, so this aligns the third entry point rather than
widening the surface. Purely additive: one hunk on the existing named list,
nothing removed, renamed or narrowed, both subpaths unchanged. Same route
objectui#7697 took for `ComboboxOption` on this same list.
`form-barrel-mirror-9406.test.ts` keeps the class shut and is DERIVED, not a
pair of presence assertions: it reads `form.ts`'s export list against the
barrel's `./form.js` list on every run and names any gap, so the next
declaration that lands in `form.ts` and is forgotten fails it. Names left off
deliberately carry a ledger row with the reason, and a row reds once its name
reaches the barrel or stops being declared. `SemanticElementSchema` /
`HtmlElementSchema` are recorded as out of scope with the objectui#9067 ruling
that settled their zod side, checked so the record cannot rot.
Running it surfaced `CommandItem` and `CommandGroup` in the same state; the
ruling authorises exactly two names, so they are ledgered as undecided and
reported for their own card rather than moved here.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QreXiyMEqKLN4U5daMPVa
✅ 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
|
Contract reviewServed-tier: ① Derived judgmentsThe published delta is +2 names on one entry point, and it was MEASURED on the built artifact rather than read off the source. Three clean builds (clean before each, so no incremental skip made the control vacuous): a same-source control — two builds of byte-identical source — came back byte-identical on
② Semver levelChangeset declares ③ Boundary flagsFour declared departures and three findings, each answered:
Ablation is a two-tree reading, not a claim: reverting
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #9406
Implements decision batch #133 item 2, letter (a) (maintainer 2026-09-14, recorded on the card). Nothing here is a judgement call of this branch's: the ruling names the file, the act, the bump level and the pin.
The exact published delta
Two names join one list: the root barrel
packages/types/src/index.ts, on its existingexport type { ... } from './form.js';clause, from the modulepackages/types/src/form.ts.@object-ui/types/form@object-ui/types/zod@object-ui/typesInputShorthandSchemaform.tsUiCalendarSchemaform.tsNo other export moves. Measured on the published artifact rather than asserted:
packages/typeswas built at the branch point and at this head, anddist/index.d.tsdiffers by exactly one line, which differs by exactly these two names inserted betweenCalendarSchema,andFieldValidationRules,. Nothing else in that file changed, in either direction.The dispatch cautioned that this package's emit is not byte-reproducible (measured on PR objectui#9517), so the comparison carries a same-source control: two consecutive clean builds of byte-identical source, compared before any normalisation. For
dist/index.d.tson this tree they came back byte-identical (raw differing lines 0, sorted differing lines 0), so the delta above is a reading and not emit noise. Reported as measured: the instability that card saw on another emitted file did not appear on this one, which the control establishes rather than assumes.The source diff is one additive hunk, 16 insertions and 0 deletions on
index.ts— two names and the comment that says why they are there. The comment does not reach the published artifact (the emitted clause is one comma-joined line), so the published surface change is exactly the two names.Why it mattered more than a missing name
From the root entry point the compiler did not merely fail, it suggested a different component. Reproduced live on this branch by removing the two lines again and running the package's own
tsc -p tsconfig.test.json:ui:calendarandcalendarresolve to different renderers, andInputOTPSchemais not an input at all. An author who accepts the suggestion writes an import that compiles and means something else.The pin derives the gap; it does not assert a pair
packages/types/src/__tests__/form-barrel-mirror-9406.test.ts. On every run it readsform.ts's own export list and the root barrel's./form.jsre-export list, and the verdict is the set difference — so the declaration that lands inform.tsnext month and is forgotten fails it. A pin asserting "these two names are present" would have passed that day, which is this class reopening a third time.ABSENT_BY_DECISION), names nobody has ruled on carry one saying so (ABSENT_PENDING_DECISION) — the two-ledger shapearm-named-export-8784.test.tssettled for the zod barrel.form.tsno longer declares, or which has since reached the barrel, fails the file and asks to be deleted../form.jsclause, the barrel list is a subset of what the module declares, the four names the card measured all read non-zero, and a star re-export from either module under the pin fails rather than silently shortening the denominator.SemanticElementSchema/HtmlElementSchemaare recorded as the ruling asked, with the reason and the ruling that made them so (objectui#9067, decision batch Fix CI lockfile error by removing @objectstack/spec dependency #121 item 5), and checked — they are declared inlayout.ts, notform.ts, so they sit outside this pin's population by construction, and the block fails the day either reaches the root barrel. They are not added here.One finding, ledgered and reported rather than repaired
Running the derived pin over this list surfaced two more names in the same state:
CommandItemandCommandGroup(the element types ofCommandSchema.groupsand of itsitems), reachable only through the/formsubpath whileCommandSchemasits on the root list. That is objectui#7697's shape exactly. The ruling authorises exactly two names and says "additive, no other line moves", so they are ledgered as undecided with the reason and handed to the dispatching seat for their own card. This PR does not move them.src/form.tsexports", which conflates two populations.form.tsexports 30 interfaces plus 2 type aliases; the barrel's list carried 28 names, of which 26 are interfaces. So the gap was four names, not two — the two this ruling names, plus the pair above. The card's own two-zero reading is confirmed unchanged: both names read 0 on the barrel whileCalendarSchemaandInputSchemaread non-zero in the same pass.Checks run before pushing
pnpm exec vitest run packages/types/src/__tests__/form-barrel-mirror-9406.test.tsindex.tstaken back to the branch pointtsc -p tsconfig.test.jsonpnpm --filter @object-ui/types run type-check(all threetsclegs)pnpm exec vitest run packages/types/pnpm --filter @object-ui/types run lintcheck-changeset-presence.mjs,pnpm changeset:check,pnpm check:changeset-claimspnpm check:new-line-citationspnpm check:control-bytesand a direct sweep of the diffBoth ablation legs restored from
HEADand verified by blob hash against theHEADblob, withgit diff HEADempty afterwards. Repository-scale runs (Lint,Type Check, the test shards,Build & E2E,Build Docs) are CI's.Changeset
.changeset/9406-types-root-barrel-two-names.md,minoron@object-ui/types— the level the ruling sets, on the ground that this is a published surface gaining two names, not on the size of the diff.For the Clause-2 contract review
The reviewed surface is one clause in one file. The published delta is the two names in the table above and nothing else, established against the built
dist/index.d.tswith a same-source control. Both names were already published on two other entry points of this same package, so the third is aligned rather than widened; both subpaths are untouched and every previously published name is still published. Draft, not enqueued, no auto-merge, no labels written by this branch.Generated by Claude Code