Filed unassigned and ungraded by the domain:ui dev seat while implementing objectui#6955 (session session_01YBWFb5YgMU5dw8p2VKj16S). Out of that card's scope, which is one input's value vocabulary. Recording it rather than repairing it on that branch — no assignee, left for triage.
What was observed, on origin/main at b1a14f28e
packages/plugin-detail/src/index.tsx:325 registers the block against the component directly:
ComponentRegistry.register('detail-section', DetailSection, {
namespace: 'plugin-detail',
inputs: [
{ name: 'title', type: 'string' },
{ name: 'description', type: 'string' },
{ name: 'fields', type: 'array', required: true },
{ name: 'collapsible', type: 'boolean' },
{ name: 'defaultCollapsed', type: 'boolean' },
{ name: 'columns', type: 'number' },
{ name: 'showBorder', type: 'boolean' },
{ name: 'headerColor', ... },
],
});
Those eight names are a FLAT authoring surface. DetailSection does not have one. Its props interface (packages/plugin-detail/src/DetailSection.tsx:102) declares a single section object plus render-context props, and the component destructures section and reads section.title, section.fields, section.defaultCollapsed, section.headerColor and the rest off it. Not one of the eight declared names is a prop this component reads.
The two are joined by SchemaRenderer, which spreads a node's non-metadata keys as React props (packages/react/src/SchemaRenderer.tsx:1574, createElement(Component, { schema, ...componentProps, … })). So a node authored exactly as the registration prescribes arrives as title / fields / headerColor props, and section arrives as undefined.
Why it is worth a card
The eight inputs are not inert documentation. packages/components/src/renderers/layout/page.tsx builds the JSX-page compiler's manifest from getKnownTypes() plus these same inputs, and sdui-parser's validateTree judges an authored page against it — the same reach apps/console/src/__tests__/registry-inputs-spec-parity.test.ts records for element:record_picker, which is likewise outside PUBLIC_BLOCKS. So the platform's own validator tells an author these eight props are the correct and complete way to write this block, on the one surface where the answer is machine-read.
⚠️ And the failure looks WORSE than inert, though this half is a reading and not an execution — stated separately for that reason. DetailSection's first statement is React.useState(section.defaultCollapsed ?? false). With section undefined that is a property read on undefined, i.e. a throw at first render rather than a section that renders empty. Whoever picks this up should execute it before believing that sentence; what IS measured here is only the declaration-versus-props mismatch above, by reading both files.
Reproduction of the measured half
git grep -n "register('detail-section'" packages/plugin-detail/src/index.tsx — read the eight inputs names.
- Read
DetailSectionProps at packages/plugin-detail/src/DetailSection.tsx:102 and the destructure at :129.
- Intersect the two name sets. It is empty.
Not pre-judged
At least three dispositions look plausible and this card picks none:
- Adapt at the seam — register an adapter that folds the flat props into a
section object, which makes the eight declared names true.
- Declare what the component takes — replace the eight with a
section input of type: 'object', which makes the declaration true instead.
- Retire the tag — the block has no in-repo authoring site (the only
detail-section references outside the registration are packages/cli/src/utils/known-schema-types.ts and a comment), so ADR-0049 enforce-or-remove may point at removal rather than either repair.
The choice turns on whether detail-section is meant to be authorable as a standalone SDUI block at all, which is a product question rather than a mechanical one.
Scope note
Not touched by the objectui#6955 branch, which narrows the VALUE vocabulary of one of the eight (headerColor) and leaves the flat-versus-section shape question exactly where it found it. Narrowing that one input neither creates nor worsens this; it is visible from there because the same eight lines had to be read.
Generated by Claude Code, session session_01YBWFb5YgMU5dw8p2VKj16S — https://claude.ai/code
Filed unassigned and ungraded by the
domain:uidev seat while implementing objectui#6955 (sessionsession_01YBWFb5YgMU5dw8p2VKj16S). Out of that card's scope, which is one input's value vocabulary. Recording it rather than repairing it on that branch — no assignee, left for triage.What was observed, on
origin/mainatb1a14f28epackages/plugin-detail/src/index.tsx:325registers the block against the component directly:Those eight names are a FLAT authoring surface.
DetailSectiondoes not have one. Its props interface (packages/plugin-detail/src/DetailSection.tsx:102) declares a singlesectionobject plus render-context props, and the component destructuressectionand readssection.title,section.fields,section.defaultCollapsed,section.headerColorand the rest off it. Not one of the eight declared names is a prop this component reads.The two are joined by
SchemaRenderer, which spreads a node's non-metadata keys as React props (packages/react/src/SchemaRenderer.tsx:1574,createElement(Component, { schema, ...componentProps, … })). So a node authored exactly as the registration prescribes arrives astitle/fields/headerColorprops, andsectionarrives asundefined.Why it is worth a card
The eight inputs are not inert documentation.
packages/components/src/renderers/layout/page.tsxbuilds the JSX-page compiler's manifest fromgetKnownTypes()plus these sameinputs, andsdui-parser'svalidateTreejudges an authored page against it — the same reachapps/console/src/__tests__/registry-inputs-spec-parity.test.tsrecords forelement:record_picker, which is likewise outsidePUBLIC_BLOCKS. So the platform's own validator tells an author these eight props are the correct and complete way to write this block, on the one surface where the answer is machine-read.DetailSection's first statement isReact.useState(section.defaultCollapsed ?? false). Withsectionundefined that is a property read onundefined, i.e. a throw at first render rather than a section that renders empty. Whoever picks this up should execute it before believing that sentence; what IS measured here is only the declaration-versus-props mismatch above, by reading both files.Reproduction of the measured half
git grep -n "register('detail-section'" packages/plugin-detail/src/index.tsx— read the eightinputsnames.DetailSectionPropsatpackages/plugin-detail/src/DetailSection.tsx:102and the destructure at:129.Not pre-judged
At least three dispositions look plausible and this card picks none:
sectionobject, which makes the eight declared names true.sectioninput oftype: 'object', which makes the declaration true instead.detail-sectionreferences outside the registration arepackages/cli/src/utils/known-schema-types.tsand a comment), so ADR-0049 enforce-or-remove may point at removal rather than either repair.The choice turns on whether
detail-sectionis meant to be authorable as a standalone SDUI block at all, which is a product question rather than a mechanical one.Scope note
Not touched by the objectui#6955 branch, which narrows the VALUE vocabulary of one of the eight (
headerColor) and leaves the flat-versus-sectionshape question exactly where it found it. Narrowing that one input neither creates nor worsens this; it is visible from there because the same eight lines had to be read.Generated by Claude Code, session
session_01YBWFb5YgMU5dw8p2VKj16S— https://claude.ai/code