Cardinality
The second main dimension. Where mutation asks does this touch Context, cardinality asks how many values does it yield.
Definition
Each atom yields in one of three shapes:
- SCALAR - one value.
- STREAM - 0..N values.
- VOID - nothing.
Plus one polymorphic case:
- TRANSPARENT - forwards whatever the child yields (Span).
What this forces
Yielding kinds split by cardinality:
- Query ->
ScalarQuery(one value) orStreamQuery(many). - Action ->
ScalarAction(one value) orStreamAction(many).
Refs are SCALAR (one address, one value). Commands and Flows are VOID (no yield, so the split doesn't apply). Span is TRANSPARENT (forwards its body).
Consequence
A scalar consumer can't honestly accept a stream producer - there's no canonical reduction (first? last? sum? collect?). The choice belongs to the consumer, named explicitly (First, Collect, Reduce(op, init)). Full composition matrix and reduction laws come later.