Filed unassigned by the domain:ui execution seat while measuring objectui#5392 (session session_01CSoz9uGhaaSgiq3hshtN7L). Out of scope for that card, which is a measurement of zod→JSON Schema fidelity; this is a separate defect its instrument surfaced.
Dedupe search run before filing: #5250 (BaseSchema.passthrough() accepts undeclared keys) is the opposite direction and does not cover this; #5927 / #5853 / #6058 are the mirror-vs-TypeScript-declaration drift family, which is a different axis — this is mirror-vs-JSON-authorability. No existing card names z.function().
What was measured
@object-ui/types is the protocol layer for a JSON-authored UI vocabulary. Its zod mirrors declare 28 distinct keys as z.function():
cell custom onCancel onCardAdd onCardClick onCardMove onChange onClick
onCollapsedChange onColumnAdd onColumnsReorder onComplete onConfirm onDismiss
onError onExpandChange onOpenChange onPageChange onRowDelete onRowEdit
onSelectChange onSelectionChange onSendMessage onSlideChange onSubmit
onValueChange onViewChange validate
Command (run in packages/types/src/zod/):
grep -hoE "^\s*[A-Za-z]+: z\.function\(" *.ts | sed 's/[[:space:]]*//;s/: z.function($//' | sort -u
60 call sites across 9 files (grep -oF 'z.function(' *.ts | wc -l → 60; grep -lF → base, complex, data-display, disclosure, feedback, form, layout, navigation, overlay).
No JSON value satisfies z.function() — measured, with a positive control in the same run:
null -> REJECT {} -> REJECT
1 -> REJECT [] -> REJECT
"x" -> REJECT true -> REJECT
a real function -> accept <- control: the instrument can say "accept"
Why it matters: 14 in-repo corpus files author these keys and fail
Validating every root-type JSON file in the repo against AnyComponentSchema.safeParse finds 14 files that are rejected today, all for this reason. Example, examples/schema-catalog/src/schemas/components-feedback-toast/destructive.json:
{"type":"button","label":"Destructive Toast","variant":"destructive",
"onClick":{"action":"toast","variant":"destructive","title":"Error","description":"Something went wrong."}}ButtonSchema.safeParse -> false
issue: { code: "invalid_type", expected: "function", path: ["onClick"],
message: "Invalid input: expected function, received object" }
The file is authoring onClick as a declarative action object, which is the only thing JSON can express. The mirror asks for a JS function. The affected files are the components-feedback-toast/ and components-feedback-sonner/ catalogs.
And they are invisible
All 14 sit in objectui#5127's structure-key-less set — they carry no body/children/className/… at the root, so objectui check never judges them. They are invalid and unreported, which is why this has stood.
The question this needs ruled
Two directions, and this is a contract question rather than a mechanical fix:
- Narrow the declaration — if a JSON author can never supply a function,
z.function() is declared != enforceable on a JSON surface and the keys should be removed or demoted to a runtime-only (non-authorable) face under ADR-0049 enforce-or-remove. - Widen the mirror to the declarative form — if
onClick: {action: …} is the intended authored spelling (which the corpus and the renderer's own action plumbing suggest), the mirror should declare that shape, and the 14 corpus files become valid.
⛔ Not fixed here — picking one changes a published contract. Filed for triage.
Related: #5250, #5927, #5853, #6058, #5127, #5392.
Filed unassigned by the
domain:uiexecution seat while measuring objectui#5392 (sessionsession_01CSoz9uGhaaSgiq3hshtN7L). Out of scope for that card, which is a measurement of zod→JSON Schema fidelity; this is a separate defect its instrument surfaced.Dedupe search run before filing: #5250 (
BaseSchema.passthrough()accepts undeclared keys) is the opposite direction and does not cover this; #5927 / #5853 / #6058 are the mirror-vs-TypeScript-declaration drift family, which is a different axis — this is mirror-vs-JSON-authorability. No existing card namesz.function().What was measured
@object-ui/typesis the protocol layer for a JSON-authored UI vocabulary. Its zod mirrors declare 28 distinct keys asz.function():Command (run in
packages/types/src/zod/):60 call sites across 9 files (
grep -oF 'z.function(' *.ts | wc -l→ 60;grep -lF→ base, complex, data-display, disclosure, feedback, form, layout, navigation, overlay).No JSON value satisfies
z.function()— measured, with a positive control in the same run:Why it matters: 14 in-repo corpus files author these keys and fail
Validating every root-
typeJSON file in the repo againstAnyComponentSchema.safeParsefinds 14 files that are rejected today, all for this reason. Example,examples/schema-catalog/src/schemas/components-feedback-toast/destructive.json:{"type":"button","label":"Destructive Toast","variant":"destructive", "onClick":{"action":"toast","variant":"destructive","title":"Error","description":"Something went wrong."}}The file is authoring
onClickas a declarative action object, which is the only thing JSON can express. The mirror asks for a JS function. The affected files are thecomponents-feedback-toast/andcomponents-feedback-sonner/catalogs.And they are invisible
All 14 sit in objectui#5127's structure-key-less set — they carry no
body/children/className/… at the root, soobjectui checknever judges them. They are invalid and unreported, which is why this has stood.The question this needs ruled
Two directions, and this is a contract question rather than a mechanical fix:
z.function()isdeclared != enforceableon a JSON surface and the keys should be removed or demoted to a runtime-only (non-authorable) face under ADR-0049 enforce-or-remove.onClick: {action: …}is the intended authored spelling (which the corpus and the renderer's own action plumbing suggest), the mirror should declare that shape, and the 14 corpus files become valid.⛔ Not fixed here — picking one changes a published contract. Filed for triage.
Related: #5250, #5927, #5853, #6058, #5127, #5392.