--- id: SG-7 family: RT-SG level: core profiles: [runtime] posture: normative-target added: "1.0" changed: "1.0" source: https://flowdrop.io/spec/rules/rt-sg/sg-7 specification: FlowDrop Workflow Specification 1.0-draft licence: CC BY 4.0 --- # SG-7 — A loop's budget counts rounds of the loop, not executions of a node *RT-SG (Part II) · level: core · profiles: runtime · added in 1.0* ## The rule > **Normative.** This is the rule. > > 1. 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. > > 2. That bound is per loop, keyed by the loop's head, and counts rounds rather than executions of any one node in the body. > > 3. 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. > > 4. 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: ```json title="The paused run's jobs, each carrying the round it ran under" [ {"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": {}} ] ``` ```json title="What the resumed run restores the loop's round count to" verdict="restored" {"reason": 3} ``` The job with no stamp at all contributes nothing and resets nothing. ## Related rules - Names: SG-16, SG-17, SG-14 - Referenced by: ORC-10, SG-4, SG-10, SG-14 --- Rule identifiers are permanent and are never renumbered. This specification carries no implementation status: each implementation publishes its own standing against these rules. Licensed CC BY 4.0.