mesh: say what the energy figure covers — the served span, not the request #385
3 changed files with 37 additions and 2 deletions
22
mesh/SPEC.md
22
mesh/SPEC.md
|
|
@ -294,6 +294,28 @@ A receipt that violates the coupling MUST NOT be sealable. This is the rule that
|
|||
keeps "measured" honest: a deployment with no hardware meter reports `Estimator`
|
||||
and says so, rather than dressing an estimate up as a measurement.
|
||||
|
||||
**What the figure covers, and what it does not.** The figure is the **served
|
||||
span**: the meter session opens immediately before the engine runs and closes
|
||||
when it returns. Routing (§2) and grant authorisation precede it and are
|
||||
**not** included, and a receipt therefore understates the energy of handling the
|
||||
request by whatever those steps cost.
|
||||
|
||||
An implementation **MUST NOT** present a mesh receipt's energy as the energy of
|
||||
the request. Where a router or an authorisation path itself runs a model — a
|
||||
classifier or an LLM deciding the route — that omission stops being negligible,
|
||||
and the shortfall lands in the direction this family treats as unsafe:
|
||||
**under-reporting is the unsafe direction at a ceiling**, because the grant is
|
||||
debited the served span only and admits further work on the strength of it
|
||||
(`jouleclaw/SPEC.md` §1.3; `jcp/SPEC.md` §5 — named by file, because mesh has
|
||||
a §5 of its own and no §1.3). An implementation that meters a
|
||||
model-running router **SHOULD** seal that span as its own field rather than
|
||||
folding it into this one, so the two remain separable by a verifier.
|
||||
|
||||
This boundary is an ordering invariant in the serving path, not an observable
|
||||
property of the receipt: the meter is snapshot-driven and routing takes no
|
||||
meter samples, so no test pins it today. Putting the router behind a trait, as
|
||||
the engine already is, is what would let one.
|
||||
|
||||
`HwShunt` covers a shunt and a vendor energy counter (RAPL, NVML, Apple
|
||||
IOReport), but a counter counts only while it is live:
|
||||
|
||||
|
|
|
|||
|
|
@ -498,7 +498,11 @@ impl<'m> Mesh<'m> {
|
|||
.expect("a chosen route carries its fidelity");
|
||||
let recipe = route.recipe.clone().unwrap_or_default();
|
||||
|
||||
// 3. Meter the served span. Copy the meter reference out so the engines
|
||||
// 3. Meter the served span — and only that span. Routing (1) and
|
||||
// authorisation (2) already ran, so their energy is outside every
|
||||
// receipt this path seals; SPEC §3.3 states that limit, and says why
|
||||
// it stops being negligible once a router runs a model of its own.
|
||||
// Copy the meter reference out so the engines
|
||||
// borrow and the log borrow stay disjoint from it.
|
||||
let meter = self.meter;
|
||||
let engine = self
|
||||
|
|
|
|||
|
|
@ -108,7 +108,16 @@ pub struct MeshReceipt {
|
|||
/// `fidelity_delivered`: without that field it says the route table promised
|
||||
/// the floor, not that the backend delivered it.
|
||||
pub fidelity_met: bool,
|
||||
/// The honest, provenance-tagged energy span.
|
||||
/// The honest, provenance-tagged energy of the **served span** — the meter
|
||||
/// session around `engine.serve`, and nothing before it.
|
||||
///
|
||||
/// Routing and grant authorisation run first and are **not** in this
|
||||
/// figure, so it understates the energy of handling the request by
|
||||
/// whatever they cost (SPEC §3.3). Negligible for a table-driven router;
|
||||
/// not negligible where the router itself runs a model, and the shortfall
|
||||
/// falls in the unsafe direction, because the grant is debited this figure
|
||||
/// and admits further work on it. Do not present it as the request's
|
||||
/// energy.
|
||||
pub energy: Energy,
|
||||
/// The JCP denial label when debiting the metered joules against the grant
|
||||
/// breached it (SPEC §2): a per-call cost caveat the measured cost
|
||||
|
|
|
|||
Loading…
Reference in a new issue