open-standards/joule-code/examples/l3-jouleclaw/src/lib.rs
Transaction Science f521fb17be
Some checks failed
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Has been cancelled
standards workspaces build + test / jouleclaw-rs (pull_request) Has been cancelled
standards workspaces build + test / aac-rs (pull_request) Has been cancelled
standards workspaces build + test / arl-rs (pull_request) Has been cancelled
standards workspaces build + test / eoc-rs (pull_request) Has been cancelled
standards workspaces build + test / jcp-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-ui-rs (pull_request) Has been cancelled
standards workspaces build + test / joulecontract-rs (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (pull_request) Has been cancelled
standards workspaces build + test / joulehook-rs (pull_request) Has been cancelled
standards workspaces build + test / map-rs (pull_request) Has been cancelled
standards workspaces build + test / mesh-rs (pull_request) Has been cancelled
standards workspaces build + test / openpay (pull_request) Has been cancelled
standards workspaces build + test / proof-rs (pull_request) Has been cancelled
standards workspaces build + test / sandbox-rs (pull_request) Has been cancelled
standards workspaces build + test / sense-rs (pull_request) Has been cancelled
standards workspaces build + test / smart-byte-rs (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backend (jcp-energy) (pull_request) Has been cancelled
l3-jouleclaw: a fabric-priced projection is graded by its weakest input
The L3 stage tagged every per-call figure a backend reported as ModelBased, on
the premise that it was "priced by THIS machine's IOReport calibration". It is
priced by whatever matmul figure each fabric member loaded: a calibration row at
the grade its writer declared, or a seeded figure, and the seeded GPU figures are
`Estimated` (a coarse model). A projection priced from an estimate was sealed as
a calibrated per-operation model. Joule-code SPEC §6 keeps those apart:
ModelBased is "computed from a calibrated per-operation model", Estimator "a
coarse constant estimator".

The fix needs each input's grade, which the ledger did not carry.

- jouleclaw-loader-gguf: `LedgerEntry` gains `projected_grade`, the
  `EnergyProvenance` of the cost row that priced `projected_uj`, taken from the
  same row, so the two are present or absent together. Additive; nothing else
  constructs the struct.
- l3-jouleclaw: `projection_grade(window)` grades a projection by its weakest
  input. ModelBased only when every member that ran was priced by a `Measured`
  or `Benchmarked` figure; Estimator when any was priced by an `Estimated`
  figure, when any ran unpriced (its work is missing from the sum), or when the
  window is empty (a figure no priced input accounts for). A projection is never
  a reading, so it is never HwShunt. The stage now opens the attribution window
  around the call itself (reset before, snapshot after), so a figure is graded
  by this call's inputs and not by entries an earlier call left behind.

Tests. The grading table covers Measured, Benchmarked, both, Estimated alone and
beside each calibrated grade, an unpriced member, and no input. In the stage, a
backend that runs a real matmul through the dispatcher with the fabric off, and
one that runs nothing, both report 0.25 J and get Estimator (main: ModelBased).
Two integration tests, each its own process, switch the fabric on with
`JOULECLAW_FABRIC=1` and point `JOULECLAW_FABRIC_CALIBRATION` at a file they
write, pricing `local/cpu-neon`'s matmul at 2.5e8 µJ/GFLOP: declared `Measured`,
the window carries `Measured` and the receipt says ModelBased, 1024 µJ;
declared `Estimated`, the window carries `Estimated` and the receipt says
Estimator, 1024 µJ. The machine's own ~/.jouleclaw/fabric-calibration.json is
neither read nor written by these tests.

Ran: `cargo test` in l3-jouleclaw (the model-backed tests stay #[ignore], no
model was loaded), `cargo test -p jouleclaw-loader-gguf --features fabric-meter
--lib` (304 passed), loader-gguf examples checked; clippy reports nothing new.

Not done: a projection under 1 µJ still truncates to a 0 µJ receipt figure, as
before; real hybrid-model calls are far above that.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 20:48:47 -04:00

268 lines
11 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Example binding — JouleClaw's **L3 (Model)** tier as a Joule Code cascade stage.
//!
//! This shows how a consumer plugs the JouleClaw agent schema's local-model
//! layer ([`jouleclaw_llm::LlmBackend`]) into the Joule Code cascade
//! ([`joule_code_cascade::Stage`]) at tier L3. A coding request that misses the
//! cheaper tiers (L0 cache, L1 lawful, L2 embed) is generated by a local model
//! here, producing a content-addressed [`CodingOp`] and a joules-class L3
//! [`Receipt`].
//!
//! It is verified **model-free** with [`EchoBackend`] (a deterministic backend
//! JouleClaw ships for exactly this). Real backends implement the same
//! `LlmBackend` trait and drop into the same slot:
//!
//! - [`llama_backend::LlamaCompletionBackend`] — shells out to `llama.cpp`.
//! - [`runtime_backend::JouleclawRuntimeBackend`] — runs the model **in-process
//! on JouleClaw's own from-scratch GGUF tensor runtime** (`jouleclaw-runtime`),
//! no external binary and no FFI.
//! - [`hybrid_backend::HybridBackend`] — runs the Mamba2/attention **hybrid**
//! safetensors families (NemotronH, Granite-4.0-H, Falcon-H1) in-process via
//! `jouleclaw_loader_gguf::hybrid_lm`, family auto-detected from
//! `config.json`.
//!
//! In production the cheapest capable backend is chosen by
//! `jouleclaw_dispatch::ModelBank`'s cost table.
pub mod hybrid_backend;
pub mod llama_backend;
pub mod runtime_backend;
use joule_code_cargo::{Anchor, CodingOp, Edit};
use joule_code_cascade::{FnStage, Request, Resolution, Stage};
use joule_code_receipt::{Energy, Provenance, Receipt};
use joule_code_schema::{ContentId, Tier, ALG_ED25519};
use jouleclaw_fabric::EnergyProvenance;
use jouleclaw_llm::{EchoBackend, LlmBackend, LlmRequest};
use jouleclaw_loader_gguf::fabric_dispatch::{ledger_reset, ledger_snapshot, LedgerEntry};
/// The grade of a per-call energy figure projected from the fabric attribution
/// ledger (`window`: the ledger's entries for that call), by its **weakest
/// input**.
///
/// A projection is GFLOPs × each member's µJ/GFLOP; it is never a reading, so
/// at best it is a calibrated per-operation model, `ModelBased` (joule-code
/// SPEC §6). It is that only when every member that ran was priced by a
/// calibrated figure: `Measured` (a calibration row a live meter read) or
/// `Benchmarked` (a recorded run on that member class). One input priced by an
/// `Estimated` figure — a coarse model, such as the fabric's seeded GPU figures —
/// makes the whole projection an estimate, `Estimator`; so does a member that
/// ran unpriced (its work is missing from the sum), and an empty window (a
/// figure that cannot be traced to any priced input).
pub fn projection_grade(window: &[LedgerEntry]) -> Provenance {
if window.is_empty() {
return Provenance::Estimator;
}
let mut grade = Provenance::ModelBased;
for entry in window {
match entry.projected_grade {
Some(EnergyProvenance::Measured | EnergyProvenance::Benchmarked) => {}
Some(EnergyProvenance::Estimated) | None => grade = Provenance::Estimator,
}
}
grade
}
/// Build an L3 cascade [`Stage`] backed by any JouleClaw [`LlmBackend`]. The
/// stage generates a coding operation from the request intent and reports the
/// backend's joule cost as the receipt energy (tier L3, joules class).
///
/// The stage opens the fabric attribution window around the call (it resets
/// the process-wide ledger first), so the figure a backend reports is graded by
/// the inputs this call was priced from ([`projection_grade`]) and by nothing an
/// earlier call left in the ledger. The ledger is process-wide: work another
/// thread dispatches during the call lands in the same window.
pub fn jouleclaw_l3_stage(backend: Box<dyn LlmBackend>) -> impl Stage {
FnStage::new(Tier::L3, move |req: &Request| {
ledger_reset();
let response = backend
.complete(&LlmRequest::from_prompt(req.intent.clone(), 256))
.ok()?;
let window = ledger_snapshot();
// Reference materialization: the model's output becomes one edit. A
// production binding would parse structured edits from the model.
let edit = Edit {
path: "OUTPUT.md".into(),
anchor: Anchor::ByteRange { start: 0, end: 0 },
replacement: response.text.clone().into_bytes(),
};
let op = CodingOp {
alg: ALG_ED25519,
prior: ContentId::of_bytes(req.prior.as_bytes()),
edits: vec![edit],
author: [0u8; 32],
intent: req.intent.clone(),
tier: Tier::L3,
};
let op_id = op.op_id().ok()?;
// L3 energy. When the backend reports a per-call figure
// (the hybrid backend's fabric projection — GFLOPs
// attributed per member, priced by each member's loaded
// matmul figure), it is graded by its weakest input:
// ModelBased only if every member was priced by a
// Measured or Benchmarked figure, Estimator otherwise.
// Without a figure, the catalog constant, Estimator.
let (estimated_uj, provenance) = match response.energy_joules {
Some(j) => ((j * 1_000_000.0) as u64, projection_grade(&window)),
None => (
(backend.typical_joules_per_call() * 1_000_000.0) as u64,
Provenance::Estimator,
),
};
Some(Resolution {
op: Some(op),
answer: Some(response.text),
receipt: Receipt {
op_id,
tier: Tier::L3,
energy: Energy {
measured_uj: None,
estimated_uj,
provenance,
},
sequence: 0,
nonce: [0u8; 8],
},
})
})
}
/// Convenience: an L3 stage backed by the model-free [`EchoBackend`] (for tests
/// and smoke runs without a real model).
pub fn echo_l3_stage() -> impl Stage {
jouleclaw_l3_stage(Box::new(EchoBackend::new()))
}
#[cfg(test)]
mod tests {
use super::*;
use joule_code_cascade::{Cascade, L0Cache};
#[test]
fn l3_stage_generates_op_and_joules_receipt() {
let stage = echo_l3_stage();
let res = stage
.try_resolve(&Request {
prior: "b3:AAAA".into(),
intent: "write a hello function".into(),
})
.expect("L3 resolved");
assert_eq!(res.receipt.tier, Tier::L3);
assert!(res.op.is_some());
// EchoBackend prefixes the prompt; the model output flowed through.
assert!(res.answer.unwrap().contains("hello"));
// Joules-class energy, honestly tagged as an estimate.
assert!(res.receipt.energy.estimated_uj > 0);
assert_eq!(res.receipt.energy.provenance, Provenance::Estimator);
}
/// A ledger entry for `member`, priced at `grade` (`None`: unpriced).
fn entry(member: &str, grade: Option<EnergyProvenance>) -> LedgerEntry {
LedgerEntry {
member_id: member.into(),
ops: 3,
gflops: 1.5,
projected_uj: grade.map(|_| 1.5 * 7_000.0),
projected_grade: grade,
}
}
/// The weakest input decides: calibrated figures (Measured, Benchmarked)
/// make a ModelBased projection; one Estimated or unpriced input, or no input
/// at all, makes it an Estimator figure.
#[test]
fn a_projection_is_graded_by_its_weakest_input() {
use EnergyProvenance::*;
let cases: [(&[Option<EnergyProvenance>], Provenance); 8] = [
(&[Some(Measured)], Provenance::ModelBased),
(&[Some(Benchmarked)], Provenance::ModelBased),
(&[Some(Measured), Some(Benchmarked)], Provenance::ModelBased),
(&[Some(Estimated)], Provenance::Estimator),
(&[Some(Benchmarked), Some(Estimated)], Provenance::Estimator),
(&[Some(Estimated), Some(Measured)], Provenance::Estimator),
(&[Some(Measured), None], Provenance::Estimator),
(&[], Provenance::Estimator),
];
for (grades, want) in cases {
let window: Vec<LedgerEntry> =
grades.iter().enumerate().map(|(i, g)| entry(&format!("local/m{i}"), *g)).collect();
assert_eq!(projection_grade(&window), want, "{grades:?}");
}
}
/// A backend that runs one real matmul through the fabric dispatcher (the
/// path the hybrid models take) and reports a per-call figure, as the hybrid
/// backend does from the ledger.
struct DispatchingBackend {
/// Run the matmul (and so leave a ledger entry), or not.
dispatch: bool,
}
impl LlmBackend for DispatchingBackend {
fn model_name(&self) -> &str {
"dispatching"
}
fn complete(&self, request: &LlmRequest) -> Result<jouleclaw_llm::LlmResponse, jouleclaw_llm::LlmError> {
if self.dispatch {
let (m, n, k) = (1usize, 32usize, 64usize);
let a = vec![0.5f32; m * k];
let w = vec![0u8; 2 * n * k];
let mut out = vec![0f32; m * n];
jouleclaw_loader_gguf::fabric_dispatch::matmul_bf16_auto(&a, &w, &[], m, n, k, &mut out);
}
Ok(jouleclaw_llm::LlmResponse {
text: format!("fn answer() {{}} // {}", request.prompt),
finish_reason: jouleclaw_llm::FinishReason::Stop,
input_tokens: 4,
output_tokens: 4,
energy_joules: Some(0.25),
})
}
fn typical_joules_per_call(&self) -> f64 {
1.0
}
}
fn resolve(backend: DispatchingBackend) -> Energy {
let stage = jouleclaw_l3_stage(Box::new(backend));
let res = stage
.try_resolve(&Request { prior: "b3:AAAA".into(), intent: "write a hello function".into() })
.expect("L3 resolved");
res.receipt.energy
}
/// A per-call figure is no longer ModelBased by default. Here the fabric is
/// off (no `JOULECLAW_FABRIC=1`), so the member that ran was priced by
/// nothing: the figure is reported, as an estimate. A figure with no ledger
/// input at all is an estimate too.
#[test]
fn a_figure_the_ledger_did_not_price_is_an_estimate() {
for dispatch in [true, false] {
let e = resolve(DispatchingBackend { dispatch });
assert_eq!(
(e.measured_uj, e.estimated_uj, e.provenance),
(None, 250_000, Provenance::Estimator),
"dispatch={dispatch}"
);
assert!(e.check_provenance().is_ok());
}
}
#[test]
fn cascade_falls_through_l0_to_l3() {
// Empty L0 cache in front of the L3 model stage: L0 misses, L3 closes.
let cascade = Cascade::new([
Box::new(L0Cache::new()) as Box<dyn Stage>,
Box::new(echo_l3_stage()) as Box<dyn Stage>,
]);
let res = cascade
.resolve(&Request {
prior: "b3:AAAA".into(),
intent: "refactor this".into(),
})
.expect("resolved");
assert_eq!(res.receipt.tier, Tier::L3);
}
}