KrillApp.Avatar.processor() and MenuCommand.*.processor() would throw a
misleading Exception("Krill App had a null processor interface") rather than a
clear IllegalStateException explaining why those types have no processor.
More critically: the when in KrillAppEmit.kt silently diverged from
KrillAppMeta.kt — Avatar and MenuCommand were handled in meta but not in emit,
meaning a future call site that dispatched on either type would crash at runtime
with no compile-time warning.
Commit 5810b427f (“fixing bugs from avatar”) added KrillApp.Avatar ->
AvatarMetadata() to KrillAppMeta.kt but omitted the corresponding arm in
KrillAppEmit.kt. MenuCommand was never added to either file’s exhaustive when
as an explicit arm (it relied on else). The else branch previously returned
null (no-op); a later refactor changed it to throw, but left the comment
describing the old null behavior and neither added Avatar nor MenuCommand as
explicit arms. The two files were structurally divergent with no compile-time
guard.
KrillApp.Avatar -> arm to KrillAppEmit.kt (throws IllegalStateException with reason: UI-only type).is MenuCommand -> arm to KrillAppEmit.kt (throws IllegalStateException with reason: SSE command discriminator, not a processable node).else branch, making the when fully exhaustive — a future missing arm is now a compile error.when over sealed hierarchies exhaustive in both sidecars at the same time. KrillAppEmit.kt and KrillAppMeta.kt are a pair; any new KrillApp subtype must get an arm in both, and the when in each should be else-free so the compiler enforces completeness.KrillApp type. Types that legitimately have no processor (UI-only, command discriminators) should have a test asserting processor() throws IllegalStateException, confirming the explicit intent rather than silent fallthrough.KrillAppMeta.kt changes, always open KrillAppEmit.kt side-by-side and verify the arm sets match.