Summary
MetadataPluginConfig.additionalTypes is a declared, authorable, documented surface with no consumer anywhere in the repo. A plugin author who follows the published instructions writes it, gets no error, and nothing happens.
Found while measuring #8421 (which needs a live registered-type set at the /meta boundary). It is not that card's defect, so it is filed separately.
Measured
Grepped every file type across packages, apps, examples, docs, content. Every occurrence of additionalTypes is a declaration or a mention — never a read:
| site | what it is |
|---|
packages/spec/src/kernel/metadata-plugin.zod.ts:479 | the Zod declaration |
packages/spec/authorable-surface/kernel.json:397 | kernel/MetadataPluginConfig:additionalTypes — on the authorable surface |
packages/spec/authorable-surface.base.json:4507 | same, in the anchor |
content/docs/plugins/adding-a-metadata-type.mdx (lines 18, 71, 133, 235) | documents it as the plugin's type-declaration path, including a release checklist item |
content/docs/references/kernel/metadata-plugin.mdx:98 | reference table entry |
packages/metadata/src/metadata-manager.ts:2470 | a comment claiming the live registry "covers built-ins AND plugin-contributed additionalTypes" |
packages/metadata-protocol/src/protocol.ts:4266 | a comment claiming the type set "grows later (artifact load, additionalTypes)" |
The only production writer of the manager's type registry is packages/metadata/src/plugin.ts:272:
this.manager.setTypeRegistry(DEFAULT_METADATA_TYPE_REGISTRY);
setTypeRegistry (metadata-manager.ts:585) replaces the array outright and is called exactly once outside tests. Nothing ever merges additionalTypes into it.
Measured against the real MetadataManager (vitest, real class, MemoryLoader):
declared count = 27 | live count = 27
getRegisteredTypes() sorted === DEFAULT_METADATA_TYPE_REGISTRY types sorted → true
So typeRegistry in production is exactly DEFAULT_METADATA_TYPE_REGISTRY, always.
Why the two source comments are wrong, not just stale
Both comments above are load-bearing for readers reasoning about the metadata type set — one of them is the doc comment a future author will read when deciding whether a live type check is safe. They assert a growth path that does not exist. (artifact load in the protocol.ts comment is real; additionalTypes is not.)
Corroborating evidence that no kind-declaration channel exists
registerMetadataTypeSchema's own doc comment (packages/spec/src/kernel/metadata-type-schemas.ts) says it plainly:
NOTE — registering a schema alone does not make a type appear in the listing. getMetaTypes() enumerates types from the engine registry and the metadata service, then decorates each with its schema; a type present here but in neither of those is not reached. Register the type as well as its schema.
"Register the type as well" points at additionalTypes — the inert key. #6245 then bound schemas for webhook / connector / sharing_rulewithout registering the kinds, which is consistent with there being no working channel to register them through.
There is prior art for this exact failure shape on this exact surface: #4212 found these same docs telling plugins to use onInstall, a hook with no invocation site, so plugins "registered nothing and got no error". This is the same silence one level down.
Consequence
A plugin can only get its kind into the live type set as a side effect of registering an item of that kind (SchemaRegistry.registerItem / MetadataManager.register). There is no way to say "this kind exists but has no items yet". That is what blocks #8421: every candidate live registered-type set is an item-population set rather than a declared-kind set.
Disposition
ADR-0049 enforce-or-remove: either wire additionalTypes into setTypeRegistry (making it the real plugin kind-declaration channel, which also unblocks #8421), or remove it and correct the four docs pages plus the two source comments. Not a judgement call this seat should make.
Related: #8421 (blocked by this), #6245, #4212.
Generated by Claude Code
Summary
MetadataPluginConfig.additionalTypesis a declared, authorable, documented surface with no consumer anywhere in the repo. A plugin author who follows the published instructions writes it, gets no error, and nothing happens.Found while measuring #8421 (which needs a live registered-type set at the
/metaboundary). It is not that card's defect, so it is filed separately.Measured
Grepped every file type across
packages,apps,examples,docs,content. Every occurrence ofadditionalTypesis a declaration or a mention — never a read:packages/spec/src/kernel/metadata-plugin.zod.ts:479packages/spec/authorable-surface/kernel.json:397kernel/MetadataPluginConfig:additionalTypes— on the authorable surfacepackages/spec/authorable-surface.base.json:4507content/docs/plugins/adding-a-metadata-type.mdx(lines 18, 71, 133, 235)content/docs/references/kernel/metadata-plugin.mdx:98packages/metadata/src/metadata-manager.ts:2470additionalTypes"packages/metadata-protocol/src/protocol.ts:4266additionalTypes)"The only production writer of the manager's type registry is
packages/metadata/src/plugin.ts:272:setTypeRegistry(metadata-manager.ts:585) replaces the array outright and is called exactly once outside tests. Nothing ever mergesadditionalTypesinto it.Measured against the real
MetadataManager(vitest, real class,MemoryLoader):So
typeRegistryin production is exactlyDEFAULT_METADATA_TYPE_REGISTRY, always.Why the two source comments are wrong, not just stale
Both comments above are load-bearing for readers reasoning about the metadata type set — one of them is the doc comment a future author will read when deciding whether a live type check is safe. They assert a growth path that does not exist. (
artifact loadin the protocol.ts comment is real;additionalTypesis not.)Corroborating evidence that no kind-declaration channel exists
registerMetadataTypeSchema's own doc comment (packages/spec/src/kernel/metadata-type-schemas.ts) says it plainly:"Register the type as well" points at
additionalTypes— the inert key. #6245 then bound schemas forwebhook/connector/sharing_rulewithout registering the kinds, which is consistent with there being no working channel to register them through.There is prior art for this exact failure shape on this exact surface: #4212 found these same docs telling plugins to use
onInstall, a hook with no invocation site, so plugins "registered nothing and got no error". This is the same silence one level down.Consequence
A plugin can only get its kind into the live type set as a side effect of registering an item of that kind (
SchemaRegistry.registerItem/MetadataManager.register). There is no way to say "this kind exists but has no items yet". That is what blocks #8421: every candidate live registered-type set is an item-population set rather than a declared-kind set.Disposition
ADR-0049 enforce-or-remove: either wire
additionalTypesintosetTypeRegistry(making it the real plugin kind-declaration channel, which also unblocks #8421), or remove it and correct the four docs pages plus the two source comments. Not a judgement call this seat should make.Related: #8421 (blocked by this), #6245, #4212.
Generated by Claude Code