A workload holding accelerators while consuming almost no energy is holding
capacity it is not using. A device ledger cannot see that — a held device is a
held device, saturated or parked at a prompt — so idle reclamation is a question
only an energy-denominated scheduler can ask.
It is also the most dangerous question in this standard, because the obvious
implementation destroys running work. "This workload spent 0 µJ" arrives
identically from a parked workload and from a meter that is not there:
meter unavailable → 0 µJ → "idle" → reclaim → running work destroyed
That is this family's "unknown conflated with a value" defect in its most
destructive form, so the module is built around refusing it:
- **Unknown is not idle.** An `Estimator` figure cannot establish idleness
whatever its value, and the grade is tested **before** the value meets any
threshold — so no threshold setting lets a guess through, including one high
enough to catch everything. A workload is reclaimed on evidence that it is
idle, never on the absence of evidence that it is busy.
- **Idleness is a rate over a stated window, never an instant.** Any workload
is momentarily between steps. An observation shorter than the policy's window
yields no verdict: startup is not idleness. An empty window yields no rate —
`mean_uw()` returns `None`, not zero, because zero is the one value that
reads as idle.
- **Nothing held, nothing to reclaim.**
- **Four verdicts, and only one permits reclamation.** A workload with no
verdict is *absent* from `reclamation_order`, not ranked last in it: it is not
a worse candidate than an idle workload, it is not a candidate.
Check order is normative: nothing held, then the window, then the grade, then
the rate. A later check never rescues an earlier refusal.
`IdlePolicy::default()` reclaims **nothing**. A threshold must sit above the
hardware's idle draw or nothing is ever idle, and below its working draw or
everything is, and both are properties of the device rather than of this
standard — so §2.7 declines to guess and makes the unconfigured failure "nobody
reclaimed" rather than "everybody reclaimed".
This is not preemption. §5.2 ranks who is spending badly under contention; this
asks who is not spending at all. A workload burning energy while completing
nothing is thrashing, not idle, and §5.2 is what catches it.
Conformance gains §7.25–28. Also fixes three broken intra-doc links left by
earlier slices (`WitnessReceipt`, the `derive` function/attribute ambiguity, and
a public doc linking the private first pass), so `cargo doc` is clean.
Co-Authored-By: Claude Opus 5 <[email protected]>
25 KiB
Pool v0.1 — A Standard for Energy-Accounted Multi-Tenant Scheduling
| Standard | pool |
| Status | v0.1.0 draft for review |
| Profile | pool/1 |
| Licence | Specification text CC-BY-4.0 (LICENSE-SPEC); reference code Apache-2.0 (LICENSE) |
| Reference | pool-rs/ |
A vendor-neutral standard for deciding who gets contended compute, on a budget denominated in energy. Pool specifies an entitlement tree whose guarantees are microjoules and devices together, an admission rule for all-or-nothing gangs, and a preemption order derived from what workloads have actually delivered per joule.
Pool is one of the Transaction Science open standards. Transaction Science is the steward, not the proprietor.
1. Scope and doctrine
1.1 What Pool decides
Pool decides three questions and no others: may this claim start, what is reserved against whom, and if capacity must be reclaimed, in what order. It does not place workloads on hosts, does not read counters, and does not execute anything. Placement is the caller's; energy figures arrive already graded from whatever meter produced them (§2.3).
1.2 Energy is the unit of entitlement
A device count is a proxy for the thing consumed. The quantity that is paid for, drawn from a grid, and reported under an energy-disclosure regime is energy. A guarantee of "eight accelerators" cannot express "this team may spend 40 MJ this window", so under a device-denominated quota the energy budget is enforced nowhere and reconciled, if at all, after the fact.
In pool/1 an entitlement carries both a microjoule guarantee and a device
guarantee, and both bind (§2.1). Devices describe what is occupied; joules
describe what is spent. A claim that fits one and not the other does not fit.
1.3 A figure's grade is part of the decision
Every energy figure in pool/1 carries the grade of whatever produced it
(§2.3). The grade is not a label attached after the decision; it changes the
decision (§4.3). An estimate nobody measured is the figure most likely to be
wrong in the direction that overcommits, and a scheduler that cannot tell a
reading from a guess cannot bound that error.
1.4 Unknown is not an extreme
Where pool/1 lacks a figure it says so, and never substitutes a best or worst
value for it. A ratio with no denominator is undefined (§5.1); a claim that
cannot be satisfied today is distinct from one that can never be satisfied
(§4.5). Both substitutions change outcomes: an undefined cost read as zero
makes a workload unreclaimable, and read as infinity makes it the first victim.
2. Objects
2.1 The entitlement
An entitlement is a node of a tree — a department, a project, a team. It carries:
| field | meaning |
|---|---|
id |
the node's name |
parent |
its parent, or absent for a root |
guarantee_uj |
microjoules it is owed and may always spend |
guarantee_devices |
devices it is owed and may always occupy |
over_quota_weight |
its relative share of a parent's surplus; 0 never borrows |
limit_uj |
a hard ceiling including anything borrowed; absent means the only ceiling is available surplus |
priority |
declared ordering, used only where evidence is absent (§5.2) |
Both guarantees bind. An implementation MUST refuse a claim that exceeds either (§4).
2.2 Surplus and borrowing
Surplus is the part of a sibling's guarantee it has not spent. Siblings are nodes sharing one parent; surplus MUST NOT cross roots.
A borrower's share is its over_quota_weight against the summed weight of
every node under that parent, rounded down. A borrower MUST NOT receive
more than its weighted share merely by claiming first: the share is a property
of the tree, not of arrival order.
2.3 Energy and its grade
An energy figure is a microjoule count and a provenance, one of:
| grade | meaning |
|---|---|
HwShunt |
a counter read for this work, at its honest resolution |
ModelBased |
a model the host calibrated — a real curve, not a reading |
Estimator |
a default-power guess; nobody measured or modelled this host |
HwShunt and ModelBased are observed. Estimator is not. The grade
never silently improves.
2.4 The claim
A claim requests capacity for a gang — one or more members that must
start together. Its figures describe the whole gang, never a member:
gang_size, devices_per_member, and an estimate for the gang's total
energy at its grade.
2.5 Shared devices, and what division does to a figure
Fractional accelerators are how a scheduler stops stranding capacity: several workloads on one device, each bounded by a memory fence. The fence is enforceable because memory is partitioned. Energy is not. A device-level counter reports one figure for the whole device and has no notion of which tenant caused which joule.
An attributed per-tenant figure is therefore a split of a measurement, not a measurement, and two rules follow.
Provenance degrades on division. A HwShunt device total becomes
ModelBased the moment it is divided between two or more occupants, because
the division is a model however good the counter was. It degrades no further
and never improves: an Estimator total stays Estimator, since dividing a
guess does not make it a model. Dividing by one is not a division, so a sole
occupant keeps the device's own grade.
An implementation MUST NOT report a per-tenant figure from a shared device
as HwShunt. That grade asserts a counter was read for this work, and on a
shared device none was.
The shares sum to the measurement, exactly. Attribution is integer microjoules and MUST conserve the total: no joule invented, none lost. The remainder left by flooring is distributed by a deterministic rule — largest remainder first, ties broken on a stable key — so two implementations divide the same device the same way. Conservation is what makes a tenant's figure reconcilable against the device that produced it.
A weight basis is the operator's to choose (allotted memory, time slices,
partitions). pool/1 requires only that one basis is used for every occupant
of one device, and that the result is graded as the model it is.
An implementation MUST refuse to attribute a device with no occupants, or one whose occupants all carry zero weight: there is then no basis to divide on, and discarding the figure would lose energy the counter really read.
2.6 Earning an observed estimate
§4.4 refuses a guess the right to spend a neighbour's capacity. That rule is only fair if a guess can stop being a guess. On its own it is a permanent penalty with no exit: a tenant nobody has measured can never be measured, because it can never run against surplus.
The evidence already exists. Every completed claim appended a Released
carrying what it actually consumed, at the grade of whatever read it (§6.2).
An implementation MAY derive a claim's estimate from that history, and
where it does, four rules bind.
A guess is not evidence. An observation whose own figure is Estimator is
excluded, not averaged in. Nobody measured or modelled it, so it says
nothing about what the work costs, and counting it would launder guesses into a
grade asserting they were observed. This is what makes the exit real rather
than circular: a tenant earns an observed estimate by being measured, not by
having run.
A derived estimate is a model, never a reading. Its grade MUST be
capped at ModelBased, even where every observation was read by a hardware
counter, because a figure for the next run is a prediction. The cap is a
ceiling and not a floor: modelled inputs give a modelled output.
One run is not a sample. Below a required count of evidence an
implementation MUST NOT derive an estimate, and MUST report what it
had — how many observations of the class it saw, and how many of those were
evidence. The two say different things to an operator: plenty of history that
is all guesses needs a meter, while little history needs patience. The required
count is a policy value, not a derived one; pool/1 states a default of
three and does not pretend to know the right number for a workload it has never
seen.
The absence of a class is not a class. Comparability is the operator's assertion (§2.4), and an empty class asserts nothing. Deriving across an empty class, or across differing classes, MUST be refused rather than pooling unlike work into one figure.
A derived reservation SHOULD take the upper end of the observed figures rather than their mean. Under-reserving is the failure §4.4 exists to prevent — a reservation below what the work costs is admitted and then overspends, and the joules it overspends may be a sibling's — and a mean under-reserves roughly half the time by construction. The spread SHOULD be reported beside the reservation so a reader can see how thin the evidence is.
The limit. The maximum of a small sample is itself an underestimate of the
true tail. A derived reservation is better evidence than a guess; it is not a
bound on what the work can cost, and pool/1 does not claim it is one.
2.7 Reclaiming capacity from work that is not working
A workload holding accelerators while consuming almost no energy is holding
capacity it is not using. A device ledger cannot see this: a held device is a
held device, whether it is saturated or parked at an interactive prompt. Energy
can, which makes idle reclamation a question pool/1 can ask at all.
It is also the most dangerous question in this standard, because the obvious implementation destroys running work. The reading "this workload spent 0 µJ" arrives identically from a workload that is genuinely parked and from a meter that is not there:
meter unavailable → 0 µJ → "idle" → reclaim → running work destroyed
Unknown is not idle. A figure nobody measured or modelled (Estimator)
MUST NOT establish idleness, whatever its value. A workload is reclaimed on
evidence that it is idle, never on the absence of evidence that it is busy.
An implementation MUST test the grade before comparing the value to any
threshold, so that no threshold setting can let a guess through.
Idleness is a rate over a stated window, never an instant. Any workload is momentarily between steps. An implementation MUST state the window a verdict rests on, and MUST NOT reach a verdict from an observation shorter than the window it requires: startup is not idleness. A window of zero yields no rate — not a rate of zero, which is the one value that reads as idle.
A workload holding no devices is not a candidate. It occupies no contended capacity, so there is nothing to reclaim.
The verdicts are distinct. Idle, working, no verdict and nothing held are four answers, and only the first permits reclamation. A workload with no verdict MUST be absent from a reclamation ordering rather than ranked last in it: it is not a worse candidate than an idle workload, it is not a candidate.
The check order is therefore normative: nothing held, then the window, then the grade, then the rate. A later check never rescues an earlier refusal.
Why there is no default threshold. A parked accelerator still draws power.
A threshold has to sit above the hardware's idle draw or nothing is ever
idle, and below its working draw or everything is — and both are properties
of the device, not of this standard. pool/1 does not guess them. An
unconfigured policy MUST reclaim nothing: the failure of an unconfigured
destructive action should be a missed optimisation, not destroyed work.
This is not preemption. §5.2 answers who is spending badly under contention, ranking by cost per completed unit. This answers who is not spending at all. A workload burning energy while completing nothing is thrashing, not idle, and §5.2 is the question that catches it.
3. Reservation
On admission the claim's whole estimated energy is reserved against the entitlement before the work runs. Two claims decided in the same window therefore cannot both spend the same joule.
A reservation is only as sound as the figure behind it, so the verdict carries that figure's grade (§4.6). An implementation MUST NOT report a reservation without it.
4. Admission
An implementation MUST evaluate a claim in the order below. The order is normative because a different order yields a different verdict.
4.1 Resolution and shape
A claim naming an entitlement the pool does not hold is refused. A gang of no members, or members occupying no devices, is refused: it is not a claim on anything.
4.2 Impossibility before pendency
A claim whose devices exceed guarantee_devices, or whose energy exceeds
limit_uj, is refused before any test that could queue it. Queueing a
claim that can never be satisfied fills a queue with work that will never run
and reports it as pending.
4.3 Inside the guarantee
If the entitlement's spent energy plus the claim's estimate is within
guarantee_uj, and its held devices plus the claim's devices are within
guarantee_devices, the claim is admitted — at any grade. A tenant may
spend its own guarantee on a guess.
4.4 Past the guarantee: an unobserved estimate does not borrow
A claim exceeding guarantee_uj may be admitted only against borrowed surplus,
and only if all hold:
- its estimate is observed (§2.3) — an
Estimatorfigure MUST NOT draw on surplus; - its entitlement's
over_quota_weightis non-zero; - the total after admission is within
limit_uj, where one is set; - the borrowed part is within the entitlement's weighted share (§2.2).
Rule 1 is the substance of §1.3. Inside its own guarantee a tenant bears its own mis-estimate. Surplus belongs to a sibling that has not spent it, and an unobserved estimate is not a sound basis for spending it.
4.5 Pending and refused are different verdicts
A claim that does not fit now is Queue, with the reason: the guarantee is
exhausted and it may not borrow, the surplus is insufficient, or the devices
are held. A claim that can never fit as written is Deny, with the reason.
An implementation MUST NOT report the second as the first.
4.6 The verdict
An admission carries the reserved microjoules, the devices, how much of the reservation was borrowed, and the grade of the estimate it rests on.
5. Preemption
5.1 Realised cost
A running workload's realised cost is its spent microjoules divided by the units it has completed — not attempted. Where nothing has completed the ratio is undefined, and an implementation MUST represent it as such (§1.4).
Completion is what makes the ratio meaningful: energy spent on work that was abandoned is waste, and a denominator of attempts would score a workload well for failing quickly.
5.2 The order
Capacity is reclaimed in this order:
- Workloads with a defined realised cost, most expensive first. There is evidence they are spending badly.
- Workloads with an undefined realised cost, lowest
priorityfirst. They are unmeasured, not wasteful.
Ties MUST break on a stable key so the order is total and a replay reproduces it.
An implementation MUST NOT rank an unmeasured workload as though its cost were known. Reclaiming unmeasured work first destroys the work that would have produced the measurement, so the scheduler never learns anything about it.
6. The entitlement ledger
6.1 Usage is derived, not stored
A scheduler that restarts with empty usage hands every tenant its whole guarantee back, and admits the next claim against a budget already spent. A quota that refills on every deploy, crash or config reload is not a quota.
An implementation MUST be able to rebuild every entitlement's usage by replaying its own ledger. The ledger is the durable state; there is no second store to drift from it.
6.2 What moves the ledger
Two events, and only two:
| event | effect |
|---|---|
Admitted |
the claim's estimate is reserved against its entitlement, and the class it declared is recorded beside it |
Released |
the reservation is lifted and the actual figure charged in its place |
The class is recorded in the Admitted entry rather than kept by the
scheduler. §6.1 makes the ledger the only durable state, and a caller-side map
from claim to class would be exactly the second store that can drift from it.
Without it the history cannot be read back as evidence about a kind of work,
which is what §2.6 needs.
A Queue or a Deny reserves nothing and changes no tenant's usage, so it is
not a ledger event. Recording it would make the ledger a decision log — a
different artifact, with a different retention story.
On release the actual figure replaces the reservation; it is not added to it. The reservation was a hold on capacity, and what the tenant spent is what it spent. An admission still open at the end of a stream keeps its reservation, because the work is still running and the capacity is still held.
6.3 Overrun
A workload that exceeds its estimate is charged what it cost (§6.2). The reservation bounded what could start, not what was ultimately spent (§8). Attribution of the overrun is what the grade on each figure is for.
6.4 The chain
Entries are hash-chained: each records the hash of the entry before it, from a genesis sentinel. Replay MUST verify the chain before deriving any usage, and MUST report the index of the first broken link rather than a shorter history.
A release naming a claim that was never admitted, or was released already, is an inconsistent stream and MUST be refused at its index. It is not a shorter history; it is a history that did not happen.
6.5 The sealed entry
Each entry is a pool/1 JCR-1 receipt: a canonical det-CBOR signed core
(RFC 8949 §4.2.1 — length-first key order, shortest integer form, no floats,
bools or nulls) inside a COSE_Sign1 envelope (RFC 9052, EdDSA/Ed25519,
alg = -8), with the steward's identifier as kid. The core carries
pool_receipt, seq, prev, steward, and the event's own fields.
This is the wire format the rest of this family seals with, so a pool/1
receipt verifies under a tool that has never heard of Pool.
Two properties, kept distinct because they fail separately, and an implementation MUST check both:
- Authenticity. Every entry verifies under the steward's key. An entry this steward did not seal is refused, whoever wrote the file.
- Sequence. Every entry's
seqis its position and itsprevis the content address of the entry before it, from a genesis sentinel.
Neither alone suffices. Signatures without a chain admit a bag of valid receipts in any order with any subset removed; a chain without signatures admits a consistent stream written by anyone.
6.6 Canonicity is checked, not assumed
A signature covers exact bytes. A verifier that accepted a non-canonical encoding of the same document would let two distinct byte strings share one signature, so an implementation MUST refuse a core that decodes but does not re-encode to the bytes it arrived as.
6.7 Witnessing
A steward seals its own decisions, so a ledger alone establishes that this steward wrote this sequence — nothing more. A steward able to rewrite its whole stream can rewrite a consistent one, because it holds the only key involved.
A witness is a party holding a key the steward does not. It signs the
ledger's head at a stated length, producing a pool-witness/1 receipt: a
statement that the chain reached exactly that head at exactly that length. A
steward that later rewrites its history produces a different head, and the
receipt no longer covers it.
An implementation MUST refuse a witness whose key is the steward's. A countersignature from the party being countersigned establishes nothing, and reporting it as a witnessed ledger would be the most misleading reading of the word available.
6.8 Attestation is a grade, not a gate
An unwitnessed ledger is still a ledger. An implementation MUST grade it
self-attested rather than refuse it, and MUST NOT report a self-attested
ledger and a witnessed one as the same thing. The reader weighs the
difference; the standard's duty is to make it legible.
A receipt that verifies but covers a different head or length is distinct from one that does not verify at all, and an implementation MUST distinguish them. The second is a bad signature; the first is what a rewritten history looks like from the outside, and it is the more interesting of the two.
7. Conformance
A conforming implementation MUST:
- Enforce both guarantees of §2.1, refusing a claim that exceeds either.
- Confine surplus to siblings under one parent, and bound a borrower by its weighted share (§2.2).
- Carry a grade with every energy figure, and never improve it silently (§2.3).
- Evaluate admission in the order of §4, refusing the impossible before queueing anything (§4.2).
- Refuse surplus to an unobserved estimate (§4.4).
- Distinguish
QueuefromDeny, with a reason on each (§4.5). - Report a reservation together with the grade it rests on (§3, §4.6).
- Represent an undefined realised cost as undefined (§5.1).
- Order preemption by evidence before declaration (§5.2).
- Rebuild usage by replaying its own ledger (§6.1), verifying the chain before deriving anything from it (§6.4).
- Charge the actual figure in place of the reservation on release, not in addition to it (§6.2).
- Refuse an inconsistent stream at its index rather than treating it as a shorter history (§6.4).
- Seal every ledger entry as a
pool/1JCR-1 receipt, and verify both its authenticity and its place in the chain before deriving anything from it (§6.5). - Refuse a signed core that is not canonical (§6.6).
- Refuse a witness whose key is the steward's (§6.7).
- Grade an unwitnessed ledger
self-attestedrather than refusing it, and never report it as witnessed (§6.8). - Distinguish a witness receipt that does not verify from one that verifies and covers a different head (§6.8).
- Degrade a divided figure's provenance, never report a shared device's
per-tenant figure as
HwShunt, and never improve a grade by dividing it (§2.5). - Conserve a device total exactly across its occupants, distributing the remainder by a deterministic rule (§2.5).
- Refuse to attribute a device with no occupants or no weight (§2.5).
An implementation that derives estimates from history MUST also:
- Exclude
Estimatorobservations from the evidence rather than averaging them in, and report the two counts separately when it declines (§2.6). - Cap a derived estimate's grade at
ModelBased, however the observations were read (§2.6). - Derive nothing below the required count of evidence, and treat a required count of zero as one (§2.6).
- Refuse an empty class, and never pool observations of differing classes into one figure (§2.6).
An implementation that reclaims idle capacity MUST also:
- Refuse to establish idleness from an
Estimatorfigure, testing the grade before comparing any value to a threshold (§2.7). - Require a stated window, reach no verdict below it, and treat an empty window as no rate rather than a rate of zero (§2.7).
- Omit a workload with no verdict from a reclamation ordering rather than ranking it last (§2.7).
- Reclaim nothing under an unconfigured policy (§2.7).
8. The honest limit
pool/1 decides. It does not measure, place or execute, and a verdict is only
as sound as the figures handed to it: a mis-graded estimate produces a sound
decision about an unsound number. The grade travels with every figure (§2.3) so
that a reader of a verdict can see which it was, but nothing here can detect a
meter that lies about its own provenance.
Reservation (§3) bounds what may be started, not what is ultimately spent.
A workload that overruns its estimate is a reconciliation problem for the
accounting layer, not an admission problem; pool/1 reserves the estimate and
records its grade so that the overrun is attributable.
A witness is available, and nothing compels one. §6.7 gives a second party
a way to sign the ledger's head, so a rewritten history stops being covered.
What pool/1 does not do is require it: an unwitnessed ledger is graded
self-attested and still verifies (§6.8). So the guarantee a reader actually
holds depends on a deployment choice the standard makes legible rather than
makes for them.
A witness attests the sequence, not the decisions. A countersigned head establishes that the steward did not rewrite what it had already published. It does not establish that an admission was correct, that an estimate was honest, or that the witness examined anything beyond the head it signed. A witness is evidence against revision, not a second opinion on the scheduling.