Correcting my own framing. The modules are a graph, not a flat set: several build
from one repository, and some are the base another compiles on. Firing a build per
changed module starts work that cannot succeed yet and reports one cause as a
failure per dependent.
Observed catching the mesh up by hand today — a compiler base had to move first,
and when it failed the right behaviour was for its fifteen dependents to wait, not
to fail identically. So what reacts to the forge's event has to resolve what changed
into an order and hold a dependent while its base is unbuilt. That is a bigger thing
than "rebuild what the commit touched", and cheaper to know now.