Skip to main content

run_loop

Function run_loop 

Source
pub fn run_loop(
    queue: &mut dyn Queue,
    dispatcher: &dyn Dispatcher,
    budget: &LoopBudget,
    journal: &Journal,
    cancel: &dyn Fn() -> bool,
    per_unit_max_dispatches: Option<u64>,
) -> Result<LoopOutcome, LoopError>
Expand description

Run a walk over the queue until the queue is empty, the budget is exhausted, or the cancel sentinel fires.

§Algorithm

loop:
  check cancel -> Interrupted
  unit = queue.next()  -> None: NoWork
  resume guard: if journal has a termination event for unit.session_key,
    close the unit without dispatching, journal node_closed, and continue.
  inner dispatch loop:
    check budget -> Budget
    check cancel -> Interrupted
    iterations_used += 1
    per_unit_cap check: if unit_dispatches >= cap, synthesize NoProgress park
    emit loop_unit_dispatched
    run session, wait
    if journal has termination event: close unit, journal node_closed, break
    if exit is claude's bg-guard refusal: close unit (NoProgress) + node_closed,
      break -- do NOT re-dispatch (x-4504, AC1-ERR)
    else: emit node_failed, continue inner loop (re-dispatch)

§Journal invariant

Every journal.append call for project events is fatal on failure. An unobservable walk must not continue spending.

§per_unit_max_dispatches

When Some(N), a unit that accumulates N dispatches without a termination event is synthesized a NoProgress Evidence and parked via queue.close(). The walk continues to the next unit. None means no per-unit cap (the walk-level budget is the only ceiling, as in the original degenerate policy).