open-standards/joule-code/examples/l3-jouleclaw/src/lib.rs
Transaction Science a6ee726b2f joule-code L3: receipts priced by the fabric — ModelBased, end to end
The fabric arc reaches the standard's receipts. The hybrid
backend wraps every complete() in an attribution-ledger
window: GFLOPs recorded per fabric member that ACTUALLY ran
each matmul, priced by the machine's IOReport calibration.
The summed figure rides LlmResponse.energy_joules, and the
L3 stage now grades it correctly per SPEC §6:

  backend reports a figure  →  estimated_uj, ModelBased
                               (a calibrated per-operation
                               model — precisely what §6
                               defines ModelBased to mean)
  no figure                 →  catalog constant, Estimator
                               (the honest old behavior,
                               unchanged for Echo/llama.cpp)

Live, real checkpoint (Mellum2, fabric ON):

  "The capital of France is" → " Paris.  \nParis is"
  fabric-priced energy: 113.0 J (ModelBased)

A coding-cascade L3 receipt now carries energy from the
silicon that actually executed the call — attributed per
member, priced by a calibration metered on this machine —
instead of a 1.0 J placeholder. The provenance ladder is
exercised end to end: Estimator (catalog) → ModelBased
(fabric ledger × calibration) → HwShunt (a meter wrapping
the whole call, as the joule-fix harness already does).

Test updated to the new contract: Some(>0) with the fabric
on, honest None without — both branches printed.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-11 12:50:15 -04:00

139 lines
5.4 KiB
Rust

//! 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_llm::{EchoBackend, LlmBackend, LlmRequest};
/// 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).
pub fn jouleclaw_l3_stage(backend: Box<dyn LlmBackend>) -> impl Stage {
FnStage::new(Tier::L3, move |req: &Request| {
let response = backend
.complete(&LlmRequest::from_prompt(req.intent.clone(), 256))
.ok()?;
// 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, by best available provenance: when the
// backend reports a per-call figure (the hybrid
// backend's fabric ledger — GFLOPs attributed per
// member, priced by THIS machine's IOReport
// calibration), that is a calibrated per-operation
// model: ModelBased per SPEC §6. Otherwise the
// catalog constant, honestly tagged Estimator.
let (estimated_uj, provenance) = match response.energy_joules {
Some(j) => ((j * 1_000_000.0) as u64, Provenance::ModelBased),
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);
}
#[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);
}
}