The N-INPUT shape: one row per (input cell, key) across several inputs,
materialised into this node's own table.
union from: [:category_health, :fund_balance, :machine_ownership],
into: [cell_id: :cell, key: :key, status: :status]Its purpose is the graph-wide view. A verdict-shaped node answers one
question about one cell; asking "what is failing ANYWHERE?" today means
scanning every cell's status separately (Insights.summary/1 does exactly
that, one query per cell). A union node makes that roll-up a NODE — so it is
one indexed table, maintained incrementally: a verdict flips, that key
propagates, one row updates.
Why N inputs are safe here, when a cross-node JOIN was not
A join has to CORRELATE its inputs — match a budget row to an actual row — so a claim naming one side leaves the other unread, and the fold writes nulls over good data. That is not a scoping bug to be fixed; it is what correlating independently-claimed inputs means.
A union does not correlate. Each input contributes its rows independently,
so a claim scopes to exactly the input that fired and reads nothing else.
The composite key carries its own provenance ("category_health|travel"),
which is precisely the translation a join could not do.