Two related, pre-existing correctness problems in the JSON Schema generator (scripts/generate-json-schema.ts). Both are repo-wide (not specific to any one type) and were surfaced by review on #298. The generated schemas are reference/documentation artifacts today — there is no CI gate that resolves $refs or runs strict oneOf validation, which is why these have gone unnoticed — but any consumer that validates payloads against them will hit both.
1. Spurious empty {} branch in oneOf for union type aliases
Every union type alias is emitted with a leading empty-schema branch, e.g.:
"CanvasProviderSource": {
"oneOf": [
{},
{ "$ref": "#/$defs/CanvasServerProviderSource" },
{ "$ref": "#/$defs/CanvasClientProviderSource" }
]
}
Because {} matches any value, every instance matches ≥2 oneOf branches, so strict oneOf validation always fails.
Root cause: a union type alias's getTypeNode().getText() includes the leading | (i.e. | A\n | B). splitUnionType then produces an empty-string first element, and typeTextToSchema('') falls through to return {}. The union handler filters out 'undefined' parts but not empty-string parts.
Scope: state.schema.json (15 $defs — 14 on main before the canvas addition) and actions.schema.json (17 $defs). Affected unions include ToolCallState, ToolCallConfirmationState, SessionInputRequest, JsonPrimitive, ChatOrigin, MessageAttachment, ResponsePart, ToolResultContent, Customization, McpServerState, TerminalContentPart, CanvasProviderSource, …
Likely fix: drop empty parts in the union branch, e.g. parts.filter(p => p !== 'undefined' && p !== '') (or strip a leading | before splitting).
2. Dangling $refs in notifications.schema.json
notifications.schema.json references ~95 $defs it never defines (e.g. ToolCallState, SessionInputRequest, MessageAttachment, URI, JsonPrimitive, ChatOrigin, every *Kind/status enum member, and now CanvasProviderSource), leaving unresolved $refs and making the file non-self-contained / invalid for standalone validation.
Root cause: the notifications schema generator only inlines a subset of $defs (the interfaces it directly walks) and does not transitively pull in referenced type aliases/enums the way the state/actions generators do.
Likely fix: transitively collect and inline every referenced $def, or $ref them into a shared/base schema document.
Note
Discovered while reviewing #298 (Canvas channel). The canvas types (CanvasProviderSource, CanvasState) reproduce the identical pre-existing pattern, so they are intentionally left following the established convention in that PR and tracked here for a focused, generator-wide fix.
Two related, pre-existing correctness problems in the JSON Schema generator (
scripts/generate-json-schema.ts). Both are repo-wide (not specific to any one type) and were surfaced by review on #298. The generated schemas are reference/documentation artifacts today — there is no CI gate that resolves$refs or runs strictoneOfvalidation, which is why these have gone unnoticed — but any consumer that validates payloads against them will hit both.1. Spurious empty
{}branch inoneOffor union type aliasesEvery union type alias is emitted with a leading empty-schema branch, e.g.:
Because
{}matches any value, every instance matches ≥2oneOfbranches, so strictoneOfvalidation always fails.Root cause: a union type alias's
getTypeNode().getText()includes the leading|(i.e.| A\n | B).splitUnionTypethen produces an empty-string first element, andtypeTextToSchema('')falls through toreturn {}. The union handler filters out'undefined'parts but not empty-string parts.Scope:
state.schema.json(15$defs— 14 onmainbefore the canvas addition) andactions.schema.json(17$defs). Affected unions includeToolCallState,ToolCallConfirmationState,SessionInputRequest,JsonPrimitive,ChatOrigin,MessageAttachment,ResponsePart,ToolResultContent,Customization,McpServerState,TerminalContentPart,CanvasProviderSource, …Likely fix: drop empty parts in the union branch, e.g.
parts.filter(p => p !== 'undefined' && p !== '')(or strip a leading|before splitting).2. Dangling
$refs innotifications.schema.jsonnotifications.schema.jsonreferences ~95$defsit never defines (e.g.ToolCallState,SessionInputRequest,MessageAttachment,URI,JsonPrimitive,ChatOrigin, every*Kind/status enum member, and nowCanvasProviderSource), leaving unresolved$refs and making the file non-self-contained / invalid for standalone validation.Root cause: the notifications schema generator only inlines a subset of
$defs(the interfaces it directly walks) and does not transitively pull in referenced type aliases/enums the way the state/actions generators do.Likely fix: transitively collect and inline every referenced
$def, or$refthem into a shared/base schema document.Note
Discovered while reviewing #298 (Canvas channel). The canvas types (
CanvasProviderSource,CanvasState) reproduce the identical pre-existing pattern, so they are intentionally left following the established convention in that PR and tracked here for a focused, generator-wide fix.