Each seed and snapshot file is consumed at most once. Absorbing a seed also
absorbs its disconnected members: a merge stream must never be split across
independently scheduled outputs.
Attempts seeds in priority order until valid closures fill the output budget.
Returns indices into the original seed list for all attempted/absorbed seeds,
including rejected closures but excluding seeds left behind by the budget.
Expands one seed into its full merge closure: absorb every connected seed
and every overlapping snapshot file, transitively. Growing output.inputs
while iterating is what makes the expansion transitive.