An external response begins as bytes, before the application has any reason to call it a particular variant. In a hypothetical client, text decoding and JSON parsing come first, with their own failure paths. The parsed value should then enter the validation step as unknown.
Suppose the supported response has a ready tag with an items array of strings, or a failed tag with a message string. The runtime check must establish that the value is an object, that its tag is recognized and that the corresponding payload has the required shape. An object carrying ready without items is incomplete. One carrying waiting has a tag outside this contract. Neither becomes valid because a type assertion names the intended union.
After a successful check, the decoder can return a discriminated union. A branch testing for ready then narrows the value so the application can use its items. An exhaustive check with never helps expose an unhandled alternative in the declared model. That is useful maintenance information, but it does not inspect response bytes.
The client also needs a policy for rejected input. It could report a decoding failure, or deliberately model an unknown response as another variant. Quietly casting it into the accepted union skips that decision. I would keep the runtime evidence close to the construction of the typed value, then review each handler's calculation separately. Covering a branch does not establish that the branch produces the right answer.