You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
finding(examples): a catalog menu item authors variant: "destructive", a key no arm of MenuItem declares and no menu renderer reads — but the repair has a real fork #7101
Filed unassigned by the os-dev seat while implementing #7072 (session session_012wwHa4aaFybxXrfmfHioDM). Grading and domain:* are the triage seat's. ⛔ Deliberately NOT folded into #7072's PR — different key, and unlike value this one is not a mechanical delete.
The defect
Measured on origin/main2c3cd1b:
examples/schema-catalog/src/schemas/components-overlay-dropdown-menu/with-icons.json authors one menu item as
value is #7072's population and is being deleted there. variant is a separate, still-live instance of the same class: 1 occurrence, and no card covers it.
packages/components/src/renderers/overlay/dropdown-menu.tsx:47-80 maps items reading exactly item.separator, item.icon, item.children, item.label, item.disabled, item.onClick, item.shortcut. There is no spread (no {...item}), so an undeclared key cannot reach the DOM by accident.
The only variant token in the three menu renderers is dropdown-menu.tsx:130, inside a trigger button default ({ type: 'button', label: 'Menu', variant: 'outline' }) — a button's variant, not a menu item's.
#7072 was ruled "delete, do not declare" because nothing wantedvalue. That reasoning does not transfer:
shadcn/ui's DropdownMenuItem genuinely ships a variant="destructive", which renders the row in the destructive colour. So the fixture is not spelling a nonsense key — it is asking for a real, upstream-supported affordance that this wrapper has not surfaced.
The demo is named with-icons and its third row is Delete. A red Delete row is very plausibly the intended teaching, and the catalog is a declared AI few-shot retrieval source.
This is the #6829 shape — the class rediscovering itself on a key whose fix is not uniquely determined — so it needs a decision, not a hand edit. I did not guess.
Class context
#6810's second ruling (2026-08-30, maintainer, verbatim「同意」) adopted the middle state: ⛔ no general extractor; for keys not seen before, accept option C — 人手撞见、逐例修 + 补钉. This is exactly such a hand rediscovery, and it is the seventh instance of the class on a fifth distinct key (content → children → type → value → variant).
Refs: #7072 (the value half, same fixture) · #6810 (class decision + ruling) · #6523 (narrowed this union) · #6249 (declined a comparable capability expansion) · #6829 (the two-defensible-fixes precedent) · #5250 · #6902.
Filed unassigned by the
os-devseat while implementing #7072 (sessionsession_012wwHa4aaFybxXrfmfHioDM). Grading anddomain:*are the triage seat's. ⛔ Deliberately NOT folded into #7072's PR — different key, and unlikevaluethis one is not a mechanical delete.The defect
Measured on
origin/main2c3cd1b:examples/schema-catalog/src/schemas/components-overlay-dropdown-menu/with-icons.jsonauthors one menu item as{ "label": "Delete", "value": "delete", "icon": "trash", "variant": "destructive" }valueis #7072's population and is being deleted there.variantis a separate, still-live instance of the same class: 1 occurrence, and no card covers it.The authority
MenuCommandItem(packages/types/src/overlay.ts:363-401) declareslabel,icon,disabled,onClick,shortcut,children,separator?: false,type?: never. Novariant.MenuDividerItem(:409-419) declaresseparator: true,type?: never. Novariant.MenuItemSchema(packages/types/src/zod/overlay.zod.ts:147-168) declares novarianton either arm, and builds both from bare non-strictz.objects, so it strips the key and reports success — the finding: JSON doc snippets are checked by nothing — the ts/tsx gate cannot see them, andBaseSchema.passthrough()makesobjectui validateaccept arbitrary undeclared keys #5250 blindness.packages/components/src/renderers/overlay/dropdown-menu.tsx:47-80maps items reading exactlyitem.separator,item.icon,item.children,item.label,item.disabled,item.onClick,item.shortcut. There is no spread (no{...item}), so an undeclared key cannot reach the DOM by accident.The only
varianttoken in the three menu renderers isdropdown-menu.tsx:130, inside a trigger button default ({ type: 'button', label: 'Menu', variant: 'outline' }) — a button's variant, not a menu item's.#7072 was ruled "delete, do not declare" because nothing wanted
value. That reasoning does not transfer:DropdownMenuItemgenuinely ships avariant="destructive", which renders the row in the destructive colour. So the fixture is not spelling a nonsense key — it is asking for a real, upstream-supported affordance that this wrapper has not surfaced.with-iconsand its third row is Delete. A red Delete row is very plausibly the intended teaching, and the catalog is a declared AI few-shot retrieval source.⇒ Two defensible, opposite repairs:
value, a key no arm of the shippedMenuItemunion declares and no menu renderer reads #7072 and with The three menu renderers run two different separator dialects against oneMenuItem, and the declared one cannot parse green #6523's narrowing; costs the affordance.variant?: 'default' | 'destructive'onMenuCommandItem(+ zod mirror) and pass it through in the three renderers. Restores an upstream capability the fixture already asks for; is a capability expansion, which finding(examples): the live menubar demo teaches ashortcutarray against astringslot, and its separator renders as a blank menu item #6249's triage explicitly declined forshortcut(⛔ wideningMenuItem.shortcutwas ruled OUT).This is the #6829 shape — the class rediscovering itself on a key whose fix is not uniquely determined — so it needs a decision, not a hand edit. I did not guess.
Class context
#6810's second ruling (2026-08-30, maintainer, verbatim「同意」) adopted the middle state: ⛔ no general extractor; for keys not seen before, accept option C —
人手撞见、逐例修 + 补钉. This is exactly such a hand rediscovery, and it is the seventh instance of the class on a fifth distinct key (content→children→type→value→variant).Refs: #7072 (the
valuehalf, same fixture) · #6810 (class decision + ruling) · #6523 (narrowed this union) · #6249 (declined a comparable capability expansion) · #6829 (the two-defensible-fixes precedent) · #5250 · #6902.