Compile multiple programs into an ensemble program.
Each child program is called independently. size: nil and size: 0 both
execute every child, matching DSPy's public subset-selection behavior. A
positive :size selects that many children. A failed child contributes an
{:error, reason} entry to the ensemble outputs instead of crashing the whole
ensemble. When a :reduce_fn is supplied, it receives only successful
predictions; reducer exceptions or invalid reducer returns become structured
{:error, reason} results. When :size selects a random subset, :seed
drives a pure per-input RNG stream, so the same saved ensemble and inputs
replay the same selection without depending on process-global random state.