Skip to content

additionalTypes on MetadataPluginConfig is authorable, documented as THE way a plugin declares a metadata type, and has no reader — a plugin cannot declare a kind at all #8586

Description

@os-zhuang

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:

sitewhat it is
packages/spec/src/kernel/metadata-plugin.zod.ts:479the Zod declaration
packages/spec/authorable-surface/kernel.json:397kernel/MetadataPluginConfig:additionalTypes — on the authorable surface
packages/spec/authorable-surface.base.json:4507same, 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:98reference table entry
packages/metadata/src/metadata-manager.ts:2470a comment claiming the live registry "covers built-ins AND plugin-contributed additionalTypes"
packages/metadata-protocol/src/protocol.ts:4266a 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

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions