Skip to main content

Module budget

Module budget 

Source
Expand description

Declared spending limits, as data.

A Budget is a declaration, not a meter. It says what a node is allowed to consume; it does not track what has been consumed, reserve anything, or decide whether a child fits inside its parent. Those are feature 11’s job (US-1101 onward) and the runtime’s (US-0504). The type lives here because the Flow IR needs to carry a budget on every node long before anything can enforce one.

§Why four units and not one

Different owners bound different things. Finance bounds currency, SRE bounds wall time, a provider contract bounds call count, and a context engineer bounds tokens. Collapsing them into one number would force a conversion rate that nobody agrees on, so all four are carried and each is optional.

§Why unbounded is spelled out

Budget::UNBOUNDED exists and is the Default, but it is a value you have to write down rather than an absence you can overlook — the same reasoning that makes GrantSet::EMPTY the default grant. A reviewer reading a flow sees budget: unbounded and can object to it; they cannot object to a field that was never there.

§How budgets compose

Budgets nest, because nodes do, and the rule is tightening: a node’s effective ceiling in a unit is the smallest bound declared anywhere on the path from the flow root down to it (Budget::clamped_to). A child that declares less than its parent is narrowing its own allowance, which is always fine. A child that declares more is claiming authority its parent does not have to give, which is not (Budget::fits_within).

Two asymmetries in that rule are deliberate:

  • A child may leave a unit unbounded that its parent bounds. It is not escaping anything — it inherits the parent’s bound and spends against it, which is exactly what the runtime’s buckets do (US-0504): a node that reserves nothing charges upward until it reaches something that has a limit.
  • A child may bound a unit its parent leaves unbounded. Tightening below an unbounded parent is still tightening.

So the only thing that fails is a unit both of them bound, where the child asks for more. Budget::excesses reports every such unit at once rather than the first, because a flow that overruns on both tokens and money has two things wrong with it and a budget owner should see both.

§Comparing units that are not numbers

The four units have four types — a count, a decimal, a duration, a count — and comparing them needs one space to compare in. Budget::amount normalises each to a u64: currency to micro-dollars, time to milliseconds. That is the same space BoundGraphError::BudgetExceeded reports in and the same one the runtime meters in, so a figure never changes meaning as it moves between them.

Structs§

Budget
What a node is permitted to spend, in whichever units were declared.
Excess
A unit in which a budget asks for more than it may have.

Enums§

Unit
Which of a budget’s four limits is being talked about.

Constants§

MICROS_PER_USD
Micro-dollars per dollar. Six places is more than any provider prices to.

Functions§

micros_of_usd
A decimal amount of dollars as whole micro-dollars.