fix(types): SchemaRegistry's kanban entry stops describing a component it cannot name - #7662
Draft
os-sam wants to merge 1 commit into
Draft
fix(types): SchemaRegistry's kanban entry stops describing a component it cannot name#7662os-sam wants to merge 1 commit into
os-sam wants to merge 1 commit into
Conversation
…t it cannot name
`SchemaRegistry` advertises itself as the Single Source of Truth for component
type lookups, but its `'kanban'` entry named `DeclarativeKanbanSchema` — this
package's authoring/validation face — while the renderer registered for that
key is `ObjectKanbanRenderer` in `@object-ui/plugin-kanban`, which consumes
that package's own `KanbanSchema`. Unrelated dialects, so for this one key the
map's value did not describe the component the key names (objectui#7645).
Correcting the value is not reachable from this layer, measured rather than
assumed: importing the plugin is a phantom dependency (`check:phantom-deps`
rejects the pair, type-only included), and declaring the dependency closes the
cycle `@object-ui/types` -> `@object-ui/plugin-kanban` -> `@object-ui/types`.
objectui#6172's ruling kept the plugin's bare names rather than relocating the
dialect into this zero-workspace-dependency layer, so the gap is by decision.
The entry therefore asserts only what this layer can prove and what both
dialects satisfy: `BaseSchema & { type: 'kanban' }`. `keyof SchemaRegistry` is
unchanged — removing the key would silently narrow the published
`ComponentType` union — and two compile-time pins hold that shape: one here
(the key survives; the value no longer claims the declarative face) and one in
`@object-ui/plugin-kanban`, the only package that can name both sides, proving
the renderer's own `KanbanSchema` satisfies what the entry now asserts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
Contributor
✅ 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
|
This was referenced Sep 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7645
SchemaRegistrydocuments itself as "the Single Source of Truth for componenttype lookups". Its
'kanban'entry namedDeclarativeKanbanSchema, while therenderer registered for that key is
ObjectKanbanRendererin@object-ui/plugin-kanban, which consumes that package's ownKanbanSchema.For this one key the map's value did not describe the component the key names.
Option taken: B — the value stops asserting; the key is untouched. The
entry is now
BaseSchema & { type: 'kanban' }: the strongest claim this layercan prove, and one that is true of both dialects.
Why A was unreachable — three routes, all measured
A1 — import the honest type.
check:phantom-deps, exit 1:Baseline for that reading, same gate, unmutated tree:
✅ Every in-scope import is declared by the package that publishes it.(exit 0). Type-onlyimports are not exempt — the gate names the pair explicitly.
A2 — declare the dependency instead. Read off the manifests:
@object-ui/typeshas 0 workspace runtime deps, and
@object-ui/plugin-kanbandeclares@object-ui/types. Adding the edge closes the cycle@object-ui/types -> @object-ui/plugin-kanban -> @object-ui/types. (Readerproven live by the same pass returning 7 workspace deps for plugin-kanban.)
A3 — name a proxy this layer can already reach.
@objectstack/spec/uiis adeclared dependency of
@object-ui/typesand does exportObjectKanbanProps,mirroring the same renderer. It is not the same type: of the plugin
KanbanSchema's 19 members it shares 11, cannot express 8 (allowCollapse,cardTemplates,className,columnWidths,limit,onCardMove,onQuickAdd, and thetypediscriminant every other registry value carries),and adds 2 the plugin does not have (
filter,titleField). Pointing thereswaps one false claim for a differently false one, so it was rejected.
Relocating the plugin dialect into this layer is the remaining route, and it is
the one objectui#6172's ruling declined; it would also widen the published
surface, which the dispatch ruled out for a latent defect.
Latency re-verified, with a lit control
The card's claim that nothing indexes the value side was re-measured, not
inherited. Repo-wide, excluding
node_modulesanddist,SchemaRegistry[returns exactly 1 hit — prose in
.changeset/3965-mint-box-neutral-container.md,not a TypeScript indexed access. Control for the query shape, same command,
same file set:
ComponentPropsMap[returns 39. An earlier control for thismeasurement read zero; it was discarded as a dark instrument and rebuilt rather
than published. Also measured: 0 gate scripts mention
SchemaRegistry(control: 36 hits for
packages/types/srcin the same corpus), and the@object-ui/typesComponentTypehas no in-repo consumer but its owndeclaration.
The pins, and proof they are lit
Type-level assertions are erased at runtime, so vitest says nothing about them.
The instruments are
tsc -p packages/types/tsconfig.test.jsonandtsc -p packages/plugin-kanban/tsconfig.test.json, both chained off theirpackages'
type-checkscripts. Program membership proved with--listFiles:each pin file appears once; the plugin project resolves
@object-ui/typestopackages/types/dist/index.d.ts(0 hits for the source path), so@object-ui/typeswas rebuilt before every reading on that side.Three ablation legs, prediction written before each run:
'kanban': DeclarativeKanbanSchema)_ValueIsNotTheDeclarativeFace…test.ts(77,7): error TS2344— that pin, only that pin'kanban'key_KeyKept_KeyKept) plus TS2339 at 77/83/89types_PluginFaceSatisfiesTheEntry…test.ts(69,7): error TS2344No prediction missed. Every mutation was proved on disk by anchored
before/after counts and
git hash-objectmovement off the HEAD blob; everyrestore by blob equality and an empty
git diff HEAD. Leg 4's restore legalso rebuilt and re-checked, confirming the marker left
dist(1 -> 0) and theplugin project returned to 0 errors — an unrebuilt restore would have left
every later reading measuring the wrong tree. One earlier attempt at leg 1
mutated only half of its target; the count-based guard caught it, the trap
restored, and it was re-run rather than quietly repeated.
Leg 3 is the one that matters most for the published surface: it is the proof
that
keyof SchemaRegistrystill yields'kanban', and that deleting the key— which also removes the false claim and leaves every runtime suite green — is
now a loud compile error.
Verification, at commit
41ff58ffUnion re-run after the final commit, on a clean tree. Each gate's own verdict
line:
check:phantom-deps—✅ Every in-scope import is declared by the package that publishes it.check:control-bytes—✅ check-control-bytes: OK (scanned 6255 tracked text file(s); skipped 85 binary).check:changeset-presence—✅ 3 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)check:changeset-no-major— verdict: no changeset declares a major bumpcheck:doc-types—✅ Every documented component type is registered.check:readme-exports—✅ check-readme-exports: OK (… 0 unbuilt …)check:dist-completeness—✓ dist completeness: 12 package(s) complete (1609 emitted files verified)check:spec-symbols—✅ spec symbol derivation: 1344 files scanned against 4959 spec export namescheck:node-esm-load,check:published-dist,check:entry-guard— exit 0pnpm --filter @object-ui/types run type-checkand the same for@object-ui/plugin-kanban— exit 0pnpm exec vitest run packages/types/ packages/plugin-kanban/— 126 files,1844 tests passed
eslinton the three touched files — exit 0check:readme-exportsfirst reportedthe population COLLAPSED -- this run proves nothing(24 of 40 packages unbuilt locally). That is a preconditionfailure, not a red: all packages were built and it was re-run, which is the
green quoted above (
0 unbuilt, 421 self-imports judged, up from 312unjudgeable).
Declared narrowing.
check:sdui-registration-pinsis not measured here— it reads the built console bundle and refuses to judge without one
(
a run with nothing to read has measured nothing). It is not implicated: thediff changes no registration. The full repo-wide lint and the remaining gate
farm are left to CI, which runs them unfiltered. Exit codes throughout were
captured by redirect before any pipe.
Contract review
Clause-②: yes.
SchemaRegistryis published, and this changes the type ofone of its members — a falsifiable contract-semantics claim, not a spelling. It
adds no exported symbol and no key (the diff contains 0 changed
exportlines), so
keyof SchemaRegistryand the publishedComponentTypeunion arebyte-identical; what moves is the value side of one key.
needs:contract-reviewis on both carriers and this stays a draft — notready, not enqueued.
Semver:
minor, per this repo's version-alignment rule that objectui neverdeclares
major, with the consumer-visible effect spelled out in thechangeset.
Scope
Untouched, as fenced:
packages/plugin-kanban's ownKanbanSchema(the faceobjectui#6172 kept — the new file there only reads it),
KanbanSchema.data(#7651, open maintainer decision),
scripts/check-doc-links.mjsandscripts/github-slug.mjs(#7644), and thegetDataConfigproducers (#7632).One question is left for the PM rather than answered here: the card also asks
whether the one-authority family rule should be extended so that every
SchemaRegistryvalue must be the type its registered renderer honours. ThisPR settles the
'kanban'key; the generalization is a contract decision, andwhether other keys diverge the same way is an unmeasured sweep.
🤖 Generated with Claude Code
https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
Generated by Claude Code