ca5cd0c0dc
`SwitchStep.validate` requires `expression` and type-checks `cases`, but
never checks that `cases` is PRESENT. It is the only control-flow step whose
branch payload is optional:
if -> requires 'then'
fan-out -> requires 'items' and 'step'
fan-in -> requires a non-empty 'wait_for'
gate -> requires 'message'
switch -> cases optional
So a switch whose branch table is absent or mistyped — `case:` for `cases:`
is the obvious slip — passes validation with zero errors:
if missing then : ["If step 'x' is missing 'then' field."]
fanout missing all: ["Fan-out step 'y' is missing 'items' field.", ...]
switch typo case: : []
switch no cases : []
and then at run time reports COMPLETED with
`matched_case: "__default__"` — a default it does not even declare — having
dispatched nothing, so the whole run "succeeds". That is the "silent empty
result + COMPLETED" wiring bug the fan-in guard exists to prevent.
An explicitly declared but empty `cases: {}` is still a declaration and
stays valid, pinned by a test.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>