Found during the bare-key census asked for by #6353 (report-only there, so filed separately, unassigned).
The fact
plugin-report and the console disagree about the namespace for all three of the plugin's component keys.
packages/plugin-report/src/index.tsx registers under namespace report:
| site | key | namespace | resulting full type |
|---|
src/index.tsx:41 | report | report | report:report |
src/index.tsx:57 | spec-report | report | report:spec-report |
src/index.tsx:72 | report-viewer | report | report:report-viewer |
apps/console/src/register-plugins.ts registers the lazy stubs for the same three keys under namespace plugin-report:
| site | key | namespace | resulting full type |
|---|
register-plugins.ts:135 | report | plugin-report | plugin-report:report |
register-plugins.ts:140 (loop) | report-viewer, spec-report | plugin-report | plugin-report:* |
Every sibling plugin agrees with the console instead — plugin-calendar registers object-calendar under plugin-calendar and calendar under view, matching register-plugins.ts:107 / :113. plugin-report is the only one that invents a third spelling.
Two consequences
1. The bare report key is double-claimed, order-dependently — the same shape as #6353. Neither registration passes skipFallback, so both also claim the bare report key (Registry.register, the meta?.namespace && !meta?.skipFallback branch; registerLazy has the same branch at Registry.ts:315). Which one owns it depends on whether the lazy chunk has loaded yet.
2. The plugin-report:* keys are never satisfied by a real registration.register() clears the lazy stub for the type it is registering — lazyEntries.delete(fullType) with fullType = 'report:report' — so the plugin-report:report stub is never cleared and no component is ever stored under that key. After the chunk loads:
ComponentRegistry.get('report', 'plugin-report') // undefined
ComponentRegistry.getConfig('report', 'plugin-report') // undefined
ComponentRegistry.hasLazy('report', 'plugin-report') // true, forever
That is not only theoretical: packages/cli/src/utils/known-schema-types.ts:345-347 lists exactly the three keys that do not exist —
'plugin-report:report',
'plugin-report:report-viewer',
'plugin-report:spec-report',
so the CLI's known-type whitelist declares three namespaced types that nothing can ever render, and a schema authored with any of them resolves to nothing.
Reproduce
grep -n "namespace" packages/plugin-report/src/index.tsx
sed -n '133,145p' apps/console/src/register-plugins.ts
sed -n '343,349p' packages/cli/src/utils/known-schema-types.ts
sed -n '285,320p' packages/core/src/registry/Registry.ts
Not decided here
Which spelling is canonical is a judgement call with consumer-visible consequences either way, so this is filed rather than fixed:
- A — move the package to
plugin-report. Matches every sibling plugin, the console, and the CLI whitelist. Retires the report:* spellings, which may be authored in stored metadata. - B — move the console and the CLI whitelist to
report. Smaller blast radius on stored schemas; leaves plugin-report as the one plugin whose namespace does not match its package name.
Either way the bare-report claim wants the same skipFallback treatment #6353 applies to timeline, so one registration owns it by declaration.
Related: #6353 (the timeline instance of consequence 1), #5106 (the doc-types gate never judges the namespace half of a registration row — the gate that would have caught this class).
Generated by Claude Code
Found during the bare-key census asked for by #6353 (report-only there, so filed separately, unassigned).
The fact
plugin-reportand the console disagree about the namespace for all three of the plugin's component keys.packages/plugin-report/src/index.tsxregisters under namespacereport:src/index.tsx:41reportreportreport:reportsrc/index.tsx:57spec-reportreportreport:spec-reportsrc/index.tsx:72report-viewerreportreport:report-viewerapps/console/src/register-plugins.tsregisters the lazy stubs for the same three keys under namespaceplugin-report:register-plugins.ts:135reportplugin-reportplugin-report:reportregister-plugins.ts:140(loop)report-viewer,spec-reportplugin-reportplugin-report:*Every sibling plugin agrees with the console instead —
plugin-calendarregistersobject-calendarunderplugin-calendarandcalendarunderview, matchingregister-plugins.ts:107/:113.plugin-reportis the only one that invents a third spelling.Two consequences
1. The bare
reportkey is double-claimed, order-dependently — the same shape as #6353. Neither registration passesskipFallback, so both also claim the barereportkey (Registry.register, themeta?.namespace && !meta?.skipFallbackbranch;registerLazyhas the same branch atRegistry.ts:315). Which one owns it depends on whether the lazy chunk has loaded yet.2. The
plugin-report:*keys are never satisfied by a real registration.register()clears the lazy stub for the type it is registering —lazyEntries.delete(fullType)withfullType = 'report:report'— so theplugin-report:reportstub is never cleared and no component is ever stored under that key. After the chunk loads:That is not only theoretical:
packages/cli/src/utils/known-schema-types.ts:345-347lists exactly the three keys that do not exist —so the CLI's known-type whitelist declares three namespaced types that nothing can ever render, and a schema authored with any of them resolves to nothing.
Reproduce
Not decided here
Which spelling is canonical is a judgement call with consumer-visible consequences either way, so this is filed rather than fixed:
plugin-report. Matches every sibling plugin, the console, and the CLI whitelist. Retires thereport:*spellings, which may be authored in stored metadata.report. Smaller blast radius on stored schemas; leavesplugin-reportas the one plugin whose namespace does not match its package name.Either way the bare-
reportclaim wants the sameskipFallbacktreatment #6353 applies totimeline, so one registration owns it by declaration.Related: #6353 (the
timelineinstance of consequence 1), #5106 (the doc-types gate never judges the namespace half of a registration row — the gate that would have caught this class).Generated by Claude Code