A loop's budget counts rounds of the loop, not executions of a node
The rule
- Re-entry over a loopback edge happens only while the edge's branch is active and the loop still has budget: either its iterator has more items, or the number of rounds the loop has run is below the configured maximum.
- That bound is per loop, keyed by the loop's head, and counts rounds rather than executions of any one node in the body.
- The two coincide only on a body where every node runs every round; on a body with a conditional arm, a node that runs on some rounds only lags behind, and counting its executions would let the loop keep re-entering after the author's budget was spent.
- The round counters are restored when a paused run resumes, so the bound holds across a pause.
What it means
The budget belongs to the loop, not to any node inside it. A loop with a conditional arm can have a node that only runs on some rounds; counting that node's own executions would under-count the rounds actually spent, and the loop would keep re-entering after the budget the author set was gone. The round count is kept per loop, identified by the loop's head, precisely so a lagging node inside it cannot buy the loop extra rounds.
That count has to survive a pause. A run paused mid-loop and resumed later does not start the loop's counter over: the round each loop had reached is recovered, so the same budget that would have applied without the pause still applies after it.
Example
A loop paused mid-run has left five jobs behind for its one loop head, each carrying the round it was stamped with — one carrying no stamp:
[
{"id": 11, "metadata": {"loops": {"reason": 2}}},
{"id": 1, "metadata": {"loops": {"reason": 0}}},
{"id": 12, "metadata": {"loops": {"reason": 3}}},
{"id": 2, "metadata": {"loops": {"reason": 0}}},
{"id": 3, "metadata": {}}
]{"reason": 3}The job with no stamp at all contributes nothing and resets nothing.