Runs a flow node whose fan-out collection is only knowable at run time.
Baton.Flow.Compiler emits this worker in place of a node declaring a
$steps.-rooted Baton.Flow.FanOutSpec. It holds the node's logical id and
its declared deps, so everything downstream compiles against it exactly as it
would against a static fan-out.
It performs no work of its own — no model call, no host action. It reads the
upstream collection, creates one job per item running the node's real
worker, and then waits for them. Both halves are Baton.Expansion's; this
module only supplies the flow-specific parts: which list to read, what to
call each expansion, and what args to give it.
Failure handling
Everything this worker can get wrong is a property of the definition or of
the upstream result, and no retry can change either: a collection that
resolved to a map, an item_id that yielded something unusable or too long
to fit a step_name, two items claiming the same id, or more items than
max_items allows. All of them discard immediately rather than spending the
node's retry budget — the collection comes from a step that has already
completed, so asking again resolves the identical items and fails
identically. A reader that set ignore_discarded: true still proceeds,
which is the same latitude it has when a single expansion exhausts its own
retries.