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.