From 175d2a06da937d590ce24268bffeb1c43d2cb09e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 17 Sep 2026 10:38:06 +0000 Subject: [PATCH] docs(types): SchemaRegistry's docblock owns its key set, not its values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The interface documented itself as "the Single Source of Truth for component type lookups" without qualification. The key-set half of that is true and load-bearing — `keyof SchemaRegistry` IS the published `ComponentType` union. The value half is structurally unachievable for a component whose renderer lives in a plugin package: `check:phantom-deps` judges `import type` exactly as it judges a value import and refuses the undeclared specifier, and declaring the dependency closes a cycle through the plugin, which already depends on this package. The claim is split rather than weakened: the key set keeps the wording, a value is documented as the strongest type this layer can reach for that key, and objectui#7645 is named as the worked example in the citation style this file already uses. Prose inside one comment. No member of `SchemaRegistry` is added, removed, renamed or retyped, so `ComponentType` is byte-identical. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_012EpHzwH4wTy5sd7ibkD2yq --- .../7665-schema-registry-key-set-vs-values.md | 22 +++++++++++++ packages/types/src/registry.ts | 33 ++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 .changeset/7665-schema-registry-key-set-vs-values.md diff --git a/.changeset/7665-schema-registry-key-set-vs-values.md b/.changeset/7665-schema-registry-key-set-vs-values.md new file mode 100644 index 0000000000..b826a3055f --- /dev/null +++ b/.changeset/7665-schema-registry-key-set-vs-values.md @@ -0,0 +1,22 @@ +--- +--- + +Docblock-only split in `@object-ui/types`: `SchemaRegistry` now states which half of its +promise it can keep. The interface documented itself as "the Single Source of Truth for +component type lookups" without qualification, and for a component whose renderer lives in +a plugin package that is structurally unachievable on the value side — this package cannot +name the type such a renderer honours, because `pnpm check:phantom-deps` judges +`import type` exactly as it judges a value import and refuses the undeclared specifier, +while declaring the dependency closes a cycle through the plugin that already depends on +this package. objectui#7645 is the worked example the docblock now points at, and the +sentence that made that divergence a finding is what this change repairs. + +The claim is split rather than weakened: the **key set** keeps the Single-Source-of-Truth +wording, because `keyof SchemaRegistry` IS the published `ComponentType` union and that +half is load-bearing; a **value** is now documented as the strongest type this layer can +reach for that key, which for a plugin-rendered component may be narrower than the type the +renderer honours — a limit of this layer's reach, not a licence for an entry to over-claim. + +No member of `SchemaRegistry` is added, removed, renamed or retyped, so `ComponentType` is +byte-identical and no published behaviour changes. Comments do reach the published +`.d.ts`, which is why this is declared rather than skipped. diff --git a/packages/types/src/registry.ts b/packages/types/src/registry.ts index d52e465588..6f9e25063d 100644 --- a/packages/types/src/registry.ts +++ b/packages/types/src/registry.ts @@ -102,7 +102,38 @@ import type { /** * Registry mapping component types to their schema definitions. - * This interface is the Single Source of Truth for component type lookups. + * + * Two halves with different standing, split deliberately (objectui#7665), + * because one of them is reachable from this package and the other is not: + * + * **The KEY SET is the Single Source of Truth for component type lookups.** + * `keyof SchemaRegistry` IS the published `ComponentType` union (declared at the + * end of this file), so whether a key is declared here is the whole answer to + * whether a component type is registered — and a consumer discriminating on + * `ComponentType` is entitled to that answer. + * + * **A VALUE is the strongest type THIS LAYER can reach for that key**, which for + * a component whose renderer lives in a plugin package may be NARROWER than the + * type that renderer honours. Structural, not an oversight: such a component's + * authoring face is declared in the plugin, and this package cannot name it — + * + * - `pnpm check:phantom-deps` (`scripts/check-phantom-dependencies.mjs`) + * judges `import type` exactly as it judges a value import, so importing a + * specifier `@object-ui/types` does not declare is refused; and + * - declaring the dependency instead closes a cycle — a plugin package depends + * on this one, directly or through what it depends on — and the build graph + * is then rejected as cyclic. + * + * Both are re-derived by those two tools; this paragraph is not the evidence. + * + * ⇒ The limit is this layer's reach, ⛔ not a licence for an entry to describe a + * type it cannot name: an entry states what it can prove from here, and closing + * the gap is a move in the plugin, not a wider claim here (objectui#7664 closed + * the kanban one by moving the dialect down into this package). + * + * Worked example: objectui#7645, where the type the registered kanban renderer + * honoured lived in `@object-ui/plugin-kanban` — unreachable from here for both + * reasons above, while the entry described it anyway. */ export interface SchemaRegistry { // Layout