The owner's decision, applied: a vendor energy counter (RAPL, NVML, IOReport) is a real reading, and what separates one such reading from another is provenance, not accuracy. This crate gave RAPL and NVML `HwShunt` and gave the IOReport counter `ModelBased`, on the reasoning that Apple's Energy Model is a vendor model. That reasoning grades accuracy. What the counter could not establish was provenance: on macOS 27.0.1 its CPU rails are frozen for an unprivileged reader, and that is now caught by the liveness probe. A counter that has passed it is as much a reading as RAPL is. The grade. `AppleIoReportCounter` declares `HwShunt`, and stamps it on every reading through one constant, `READING_GRADE`, shared by `provenance()` and `read()`. It earns the grade by being live: the counter exists to read only where `admits()` let it through (CPU rail `Live`), and a declined counter produces no reading to carry any grade, so a frozen host still meters through the load-average estimator at `Estimator`. The rule, written once and shared (jouleclaw SPEC §1.3, §9.4; JCR-1 §2.3; the crate docs; vendor-energy PROTOCOL/README): a vendor counter's reading MAY be graded as a hardware reading only while the counter is demonstrably live for the domain the figure claims; the implementation MUST have observed the counter covering that domain advance under load (for IOReport: the CPU rail itself, in at least 5 intervals, 4 of every 5, over at least 300 ms while the probing thread burns CPU). A counter present but not live MUST NOT produce a hardware-graded figure; the implementation falls back to its estimator or reports the work unmetered, and SHOULD record why. A figure MUST NOT claim coverage of a domain its counter does not read; where the format has a coverage field, such a figure is Partial. No partial reading from the GPU rail. Where the CPU rail is frozen but `GPU Energy` still advances (the M5 Max), the counter stays declined. The GPU rail is machine-wide: every GPU client on the host moves it, display compositing included, with nothing of the metered work running. It does not cover part of the work; it covers other work, so no coverage field makes it honest. The rationale is in the module docs and SPEC §1.3. Docs and data that said otherwise: - SPEC §1.3 table and floors, §9.4; JCR-1 §2.3 and the crate README (toy vectors become measurements only off counters that were live). - JCR-1 vector 6's description said "measured on Apple IOReport". Its joules are toy values like every vector's. Only the `description` changed; it sits outside the signed core, which `verify.py` builds from `receipt` alone. Both verifiers pass 10/10 after the edit: `verify.py` (cbor2 6.1.4, cryptography 50.0.2, exit 0) and the independent `verify.go` (exit 0). `git diff` of the file is that one line; a field-by-field JSON diff finds only (6, description). The conformance README's slot 6 line follows. - vendor-energy conformance: README row 27 names `AppleIoReportCounter` and the `HwShunt` grade, with the liveness condition a filled fixture must meet; `apple-silicon-ioreport.json` is an unsigned, empty stub (`signed_by` null, every workload not run, no hash of it anywhere), so its `impl` and `provenance` are corrected in place. - MEASURED_ENERGY.md: a dated note that the 74.1 J / 25.5 W row was committed 2026-06-12, predates macOS 27, and recorded neither chip nor OS. The "reads CPU/GPU/ANE/DRAM with no sudo" claim is replaced by what macOS 27.0.1 does: the counter opens without sudo, but the CPU rails are frozen (all 645 rails on the M3 Ultra), so those hosts are estimated. - local-index / rerank tier SHOULDs, the CLI's `meter` help, meter.rs, apple.rs, energy_probe, Cargo feature comments, harness-econ docs. - l3-jouleclaw README: it claimed `HwShunt` on RAPL/NVML hosts, but the binding builds jouleclaw-energy with `ioreport` only, so off Apple Silicon the receipt is the token estimate. It now says what happens on each host. - mesh-schema's `HwShunt` definition includes vendor counters subject to liveness; mesh-meter, the mesh README and mesh-engine-gguf no longer say real silicon alone yields `HwShunt`. - The Live-branch assertions in mesh-meter, l3-jouleclaw and jouledesk-github expected `ModelBased` for IOReport; they expect `HwShunt`. jouledesk-github's fixtures that paired `apple-ioreport` with `ModelBased` now pair it with `HwShunt`, and keep a `ModelBased` case under a neutral meter name. Tests. `a_live_counters_readings_are_graded_as_hardware_readings` builds a counter on `Live` directly. That opens the real all-channel subscription, which opens here even though the gate declines this host. It reads it twice and asserts each reading is `HwShunt` over `SocTotal`. On this M5 Max (macOS 27.0.1): "an admitted IOReport counter: opens=true, 2 readings, each graded HwShunt", so the read path is covered on a frozen host. With `--features "ioreport rapl"`, `a_live_ioreport_reading_has_the_grade_of_a_rapl_reading` compares the grade with `RaplCounter`'s own. The used/declined tests assert `HwShunt` in their live branch. This host still takes the declined branch: "ioreport declined (CpuRailFrozen): 154 ms of CPU work metered by `apple-silicon` as 6200000 µJ, provenance estimator". Run on this M5 Max: jouleclaw-energy 24+1+1 (default), 76 lib + 1 + 1 (`ioreport`), 79 lib (`ioreport rapl`); jouleclaw-jcr1 50; harness-econ 14; local-index 41; rerank 37; cli 10; mesh-meter (`hw-meter-apple`) 10; mesh-engine-gguf 1; l3-jouleclaw 2 + 4 (2 ignored, need a model); jouledesk-github 12. All pass. Falsified, each mutant restored with `git checkout` and the tree confirmed clean: - `READING_GRADE` set back to `ModelBased`: the new test fails at the declared grade (left: ModelBased, right: HwShunt), 75 passed / 1 failed. - Only `read()`'s stamp set back to `ModelBased` (the declared grade left at `HwShunt`): the new test fails on the reading itself, "a live counter's reading is not graded as a hardware reading" (ModelBased, SocTotal) vs (HwShunt, SocTotal), 75 / 1. The read path is what the test pins. Co-Authored-By: Claude Opus 5.5 <[email protected]>
46 KiB
JouleClaw v1 — Energy-Optimised AI Runtime
Status: Draft Standard. Reference implementation:
jouleclaw-rs/ (Rust workspace, Apache-2.0).
Spec text: CC-BY-4.0.
Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119.
1. Scope and doctrine
JouleClaw is a runtime + harness + agentic-layer standard for energy-optimised AI. It applies to:
- text and code generation (LLMs, SSMs, state-space hybrids)
- multimodal understanding and generation (vision, audio, video, 3D)
- diffusion-based image / video synthesis (DDPM / LCM / Euler / Heun / DPM++ / CFG++ / Rectified Flow and friends)
- speech recognition (Whisper-class)
- the developer-facing harness that drives the above
The doctrine is one sentence: capability per joule, not capability per parameter.
Three normative consequences follow from the doctrine.
1.1 The cascade
A conforming runtime MUST dispatch every resolution through an explicit energy-tiered cascade and MUST stop at the first tier that closes the query. The tiers are:
| Tier | Wire tag | Named tag | Joule class | What it is |
|---|---|---|---|---|
| L0 | L0 |
Cache | picojoules | content-addressed cache hit |
| L1 | L1 |
Lawful | nanojoules | deterministic primitive (text / code only) |
| L2 | L2 |
Embed | sub-millijoules | embedding + hybrid retrieval |
| L3 | L3 |
Model | joules | local SSM / ternary / multimodal / diffusion |
| L4 | L4 |
Wire | tens of joules | remote frontier RPC (escape hatch) |
L1 (Lawful) is meaningful only for text and code modalities. For image / audio / video / 3D generation the cascade collapses to {L0, L2, L3, L4} — there is no deterministic compute path that produces a high-quality image from "draw me a cat".
A conforming runtime MUST NOT invoke a higher-cost tier before
the lower-cost tiers have returned Unresolvable. Inference is the
last resort, not the entry point.
1.2 Recent knowledge over frozen weights
A conforming runtime MUST prefer fresh, provenance-stamped retrieval over synthesis from frozen model weights whenever:
- the cost of the fetch + extract is below the cost of the inference, AND
- the retrieved source's trust tier is above the operator's configured threshold.
This is the L3.5 stage in the cascade implementation — between L2
(local index) and L3 (local model). The retriever MUST emit a
ClaimProvenance envelope (see §4) for every fact that contributes
to the resolution.
1.3 Honest energy provenance
Every energy reading MUST carry a Provenance tag declaring
how the value was obtained:
| Provenance | Meaning |
|---|---|
HwShunt |
Hardware reading: a shunt / coulomb counter (Jetson INA3221), or a vendor energy counter (RAPL MSR, NVML cumulative-energy counter, Apple IOReport) while it is live for the domain it claims (below) |
ModelBased |
Vendor-provided estimate from freq / voltage / utilisation (ROCm SMI, NVML power.draw) |
Estimator |
JouleClaw static cost model from arch × precision × batch tables |
A vendor energy counter's reading is a real reading. What separates
one such reading from another is provenance — which counter, over
which domain, and whether it was live when read — not accuracy. So a
live vendor counter is graded HwShunt, and liveness is the
condition:
Liveness (MUST). A reading from a vendor energy counter (RAPL, NVML, Apple IOReport, …) MAY be graded as a hardware reading only while the counter is demonstrably live for the domain the figure claims: the implementation MUST have observed the counter covering that domain advance under load (for Apple IOReport: the CPU energy rail itself advancing in at least 5 sample intervals, in at least 4 of every 5, over at least 300 ms while the probing thread burns CPU). A counter that is present but not live — frozen, or republished in lumps — MUST NOT produce a hardware-graded figure; the implementation falls back to its estimator or reports the work unmetered, and SHOULD record why. A figure MUST NOT claim coverage of a domain its counter does not read; where the format has a coverage field, such a figure is Partial.
Apple IOReport's GPU rail is not a partial reading of CPU work. It is
machine-wide — it meters every client of the GPU on the host, display
compositing among them, and moves while nothing of the metered work
runs — so where the CPU rail is frozen and only the GPU rail advances,
the reference implementation declines the counter and estimates the
work rather than reporting the GPU rail as Partial: the rail does
not cover part of the work, it covers other work.
The thermodynamic circuit breaker MUST enforce at the granularity
of the worst counter in the request's span. Implementations
MUST surface resolution_uj() and min_window_ns() so callers
can refuse to claim microjoule accuracy on platforms that cannot
deliver it.
Realistic floors:
- Intel / AMD x86 RAPL: ~1 μJ, ~10 ms window.
HwShunt. - Jetson INA3221: ~10 mW (integrate for energy).
HwShunt. - NVIDIA discrete (NVML cumulative-energy): ~1 mJ, ~50 ms.
HwShunt. - Apple Silicon IOReport: ~1 mJ, ~10 ms.
HwShuntwhile its CPU energy rail is live. On macOS 27.0.1 an unprivileged reader's CPU rails are frozen (observed on an M5 Max and an M3 Ultra), so the counter is declined there and the host is estimated (Estimator). Marketing claims of microjoule precision on Apple Silicon are sales talk; the spec is honest about this. - Consumer AMD GPU, ARM PMU: no usable counter. Use a calibrated
Estimatorand surface the wider tolerance band.
2. The receipt
Every cascade walk MUST produce one Receipt:
{
"jc_receipt": "1",
"id": "<uuid v4>",
"closed_at": "<rfc 3339>",
"input_hash": "<blake3 hex of normalised input>",
"tier": "L3",
"joules_uj": 3500000,
"energy_provenance": "ModelBased",
"tools_touched": [
{
"tool_id": "model:gemma4-9b-q5_k_m",
"joules_uj": 3500000,
"energy_provenance": "ModelBased"
}
],
"claims": [
{
"source": "https://en.wikipedia.org/wiki/Gemma_(model)",
"content_hash": "<blake3 hex>",
"fetched_at": "<rfc 3339>",
"trust_tier": 9
}
],
"eoc_stage": null
}
Receipts are shaped to seal cleanly inside a Smart Byte signed envelope (see the sibling Smart Byte standard). The Smart Byte signature attests to receipt integrity; the receipt itself is the auditable thermodynamic record.
A receipt's energy_provenance is the worst counter seen across
all tools_touched — not the best. This is normative.
3. The .jc.toml sidecar
A model file on disk (GGUF / safetensors / MLX) tells you tensor shapes and quant schemes. It does NOT tell you what one forward pass costs in joules on real hardware. The cascade auction cannot pick the cheapest backend if every backend lies about its cost.
A .jc.toml sidecar travels next to the model file and declares
the energy contract. See jouleclaw-pack for the schema.
Backends loading a model with a .jc.toml are bound to honour the
declared cost within the per-measurement drift_factor tolerance;
the runtime trips CostDrift and down-weights the backend in
future auctions when measured > declared × drift_factor.
Without a declared-cost contract, "energy-optimised inference" is marketing. With one, it is an engineering claim a third party can verify against the published reference-hardware corpus (see §6).
4. Provenance
Every retrieved claim that contributes to a resolution MUST
carry a ClaimProvenance envelope:
{
"source": "<url, did:plc, doi, ...>",
"content_hash": "<blake3 hex of bytes as fetched>",
"fetched_at": "<rfc 3339>",
"trust_tier": 9
}
trust_tier is 0..10. Bootstrap data comes from the Wikipedia
perennial-sources list (machine-readable via the Wikimedia
Enterprise parsed-references endpoint); operators MAY extend the
table.
A retriever MUST NOT present a synthesised fact as a retrieved
claim. If the runtime falls back to model inference because no
retrieval closed the query, the receipt's claims array MUST
remain empty for that tier and the resolution carries the
L3:Model tag, not L2:Embed.
5. The MCP tool surface
The standard tool dispatch protocol is MCP (Model Context Protocol). A conforming runtime SHOULD speak MCP for interop with the Claude Code / Codex / Goose ecosystem.
Every MCP tool call MUST be wrapped in
jouleclaw-mcp::dispatch_metered, which brackets the call with
energy counter reads and pushes a ToolTouch entry onto the
running receipt's tools_touched ledger.
5.1 The joule-mcp profile
Two JouleClaw-aware endpoints MAY opt into a CBOR transport
profile by advertising the capability tag x-jouleclaw/joule-mcp@1
in their handshake. When both sides advertise it, the wire encoding
switches from JSON-RPC to length-prefixed CBOR (~30–50% lower
serialisation tax per call). When either side does not advertise,
the encoding MUST fall back to standard MCP JSON-RPC.
Non-JouleClaw MCP clients (Claude Code, Codex, etc.) see plain JSON-RPC. The CBOR profile is a negotiated extension, never a replacement.
6. Conformance
A conforming runtime MUST produce a Receipt for every published
conformance vector in conformance/v1/ that matches
the canonical receipt's tier, tools_touched[].tool_id, and
claims[].content_hash.
The joules_uj field in a conforming receipt MUST fall within
the platform-specific drift band declared in the .jc.toml sidecar
for each tool / model touched. Drift beyond the band is a
non-conformance signal, not a hard failure — the runtime SHOULD
emit DriftAlert and let the operator decide whether to demote the
backend or pause the deployment.
Conformance vectors are signed at release time. Implementations self-certify by round-tripping the public vectors and publishing their receipts.
7. Wire format versioning
- The cascade tier wire tags (
L0–L4) are stable across versions. A future major version MAY add tiers (e.g.L5:Quantum) but MUST NOT renumber existing ones. - The
jc_receiptfield on a receipt is the schema version. This document defines"1"(the cascade receipt of §2) and"policy/1"(the policy receipt of §10). Unknown major → reject. Unknown minor → accept by ignoring unknown fields. Newjc_receiptschemas are added under their own prefixed namespace ("<name>/<version>"); the bare numeric form"N"is reserved for the cascade-walk receipt. - The
jc_packfield on a.jc.tomlsidecar follows the same rule. - The
jc_workspacefield on a workspace manifest (§11) follows the prefixed-namespace rule ("workspace/1").
8. Agent identity
A long-running JouleClaw agent is identified by a stable handle
bound to an Ed25519 public key. The canonical derivation is W3C
did:key over multicodec Ed25519:
handle = "did:key:z" || base58btc(0xed 0x01 || raw_public_key_32)
A conforming AgentIdentity carries (handle, public_key, optional EAT attestation, optional created_at). A verifier MUST confirm
that handle == did:key_handle(public_key) before accepting any
signed material from that identity. Attestation envelopes
(RATS / EAT per RFC 9711) MAY be bound to the identity by
placing the same handle in the EAT cti claim.
Where this identity flows:
Receipt.steward(§2): the cascade-receipt steward identity is thehandleform when self-describing.PolicyReceipt.steward(§10): same handle, same key.WorkspaceManifest.owner(§11): same handle, same key, with the pubkey embedded so a third-party verifier needs no external mapping.- COSE_Sign1
kidheader on any signed envelope: same handle.
Identity rotation is out of scope for v1. KERI-based AID rotation is the recommended substrate; this spec does not normatively constrain the rotation mechanism.
9. The policy engine
JouleClaw runtimes MAY consult an out-of-process policy engine
before executing an Action. When they do, the engine MUST be
deny-by-default and operate at filesystem / network / process
granularity.
A conforming engine exposes the following surface:
Action—Filesystem { path, mode }|Network { host, port, method }|Process { binary, argv }.Decision—Allow { rule }|Deny { reason }, whereDenyReasonisNoMatchingAllow(deny-by-default) orExplicitDeny { rule }.Policy— ordered list of rules, plus a monotonicversion. ARuleis(effect, agent_scope, action_predicate, name).- Evaluation rule — explicit
Denyrules short-circuit before anyAllow. First matchingAllowwins. No matchingAllow⇒ deny-by-default. MUST record anAuditEventper evaluation. AuditEvent—(sequence, policy_version, agent, action, decision). Sequence is monotonic within the engine instance.- Live policy update —
install_policy(new)accepts only whennew.version > current.version.
A conforming out-of-process transport is line-delimited JSON
over a duplex byte stream. One request per line, one response per
line. Operations: evaluate, audit, audit_since,
policy_version, install_policy. The server treats a malformed
line as an error response and keeps the stream open.
The reference engine is jouleclaw-policy::InMemoryPolicyEngine
(in-process) plus jouleclaw-policy-ipc::PolicyClient /
jclaw-policyd (out-of-process).
10. The policy receipt
A PolicyReceipt is the signed audit record for one policy
decision. It is a sibling of the cascade receipt in §2: same
COSE_Sign1 envelope (alg = -8 EdDSA over canonical det-CBOR), same
steward identity, but its own schema id ("policy/1") and its own
wire shape.
{
"jc_receipt": "policy/1",
"id": "<uuid v4>",
"closed_at": "<rfc 3339>",
"steward": "<did:key handle>",
"engine_id": "<id>",
"audit_sequence": 7,
"policy_version": 2,
"agent": "<did:key handle>",
"action": { "kind": "filesystem", "path": "/workspace/x", "mode": "read" },
"decision": { "kind": "allow", "rule": "read-workspace" }
}
- The canonical signed core is the det-CBOR (RFC 8949 §4.2.1 length-first map ordering) of the receipt as JSON.
- The COSE_Sign1 envelope is identical in shape to the JCR-1 v1
envelope on the cascade receipt:
protected = {1: -8, 4: steward},unprotected = {},payload = canonical signed core,signature = Ed25519(Sig_structure). - Verifiers reject envelopes whose
kid(in the protected header) disagrees with the embeddedsteward. - Conforming implementations MUST byte-match the three reference
vectors in
jouleclaw-rs/crates/jouleclaw-policy-receipt/conformance/vectors-policy.json. Reference verifiers in Rust, Python, and Go ship alongside the vectors; all three produce byte-identical canonical bytes for the same receipt.
Policy receipts and cascade receipts share the same JSONL "unified
log" file format: readers dispatch on the jc_receipt schema tag
("1" → cascade, "policy/1" → policy, unknown → forward-compat
skip).
11. The agent workspace
A persistent, content-addressed workspace MAY be attached to a
long-running agent. The workspace's wire form is a
WorkspaceManifest:
{
"jc_workspace": "workspace/1",
"owner": { "handle": "<did:key>", "public_key": "<hex32>" },
"entries": [
{ "path": "notes/x.md", "content_hash": "<blake3 hex>", "size": 17, "kind": "text" },
...
]
}
- Path normalisation — paths are relative
/-joined segments. Absolute paths, empty paths, empty segments,.and..segments, and NUL bytes are MUST rejected on write. - Content addressing —
content_hashis BLAKE3 hex of the bytes; the underlying backend stores bytes keyed bycontent_hashso identical content is deduplicated. - Entry order — entries in the manifest are sorted lexically
by
path. - Manifest content-address — the manifest's own content hash is BLAKE3 over its canonical JSON serialisation. Identical workspace state → identical manifest hash → identical signature.
- Signing — a
SignedWorkspaceManifestcarries an Ed25519 signature over the canonical manifest bytes. Verifiers MUST check both that the embeddedowner.handlematches the embeddedowner.public_keyunder §8 derivation, AND that the signature verifies.
The workspace deliberately does NOT specify encryption, conflict
resolution, or multi-writer merge. Backends are single-writer; if
multi-writer is needed it composes behind a future
WorkspaceBackend impl with a lock service. Encryption is the
caller's job — the manifest signature covers what is observable,
not what is decrypted.
12. Skill interoperability — SKILL.md
JouleClaw skills are portable to the broader open-skills ecosystem
(Claude Code, OpenAI Codex, Gemini CLI, GitHub Copilot, Cursor, et
al.) via the agentskills.io SKILL.md format. Conformance:
- A JouleClaw-emitted
SKILL.mdMUST carry the agentskills.io required frontmatter (name≤ 64 chars matching^[a-z0-9]([a-z0-9-]*[a-z0-9])?$;description≤ 1024 chars). - The deterministic JouleClaw procedure (the
TemplateandProcedurethat let a JouleClaw cascade resolve the skill at lookup energy) travels undermetadata.jouleclawas a vendor extension. Non-JouleClaw consumers treat the Markdown body as natural-language instructions; JouleClaw-aware consumers reconstruct the typed Skill. - The
bodyis required by emitters — empty bodies are rejected unless the caller opts in explicitly via a_with_default_bodyhelper (intended only for drafts). - Unknown vendor metadata keys are preserved on round-trip.
13. Vocabulary (JSON-LD + Turtle)
JouleClaw publishes a stable IRI vocabulary so a JSON-LD parser, a SPARQL store, or a generic third-generation agent client can read any JouleClaw receipt as RDF without bespoke integration.
- Namespace:
https://jouleclaw.transaction.science/vocab/v1#(prefixjc:by convention). - JSON-LD context:
https://jouleclaw.transaction.science/vocab/v1.jsonld(every field name in §§2, 10, 11 maps to ajc:-prefixed IRI with the typed range below). - Turtle ontology:
https://jouleclaw.transaction.science/vocab/v1.ttl(classes, enumerations, properties, ranges; CC-BY-4.0). - Human index:
https://jouleclaw.transaction.science/vocab/v1. - Canonical source:
jouleclaw/vocab/in this repository.
The vocabulary is purely additive:
- A v1 cascade or policy receipt remains a valid JouleClaw receipt
on the wire with or without an
@contextfield. - Adding
"@context": "https://jouleclaw.transaction.science/vocab/v1.jsonld"to a receipt expands it into typed RDF triples (e.g.tier: "L3"becomes<receipt> jc:tier jc:Model,energy_provenance: "ModelBased"becomes<receipt> jc:energyProvenance jc:ModelBased) without changing any other field. - The canonical signed core of a JCR-1 envelope MUST NOT include
@context— the JSON-LD context is metadata, not payload. Producers that want to publish a JSON-LD form alongside the signed receipt SHOULD do so in a separate field, or fetch the context out-of-band from the published URL.
Production default. Conformant producers SHOULD emit
@context set to the v1 vocabulary URL on every receipt by
default, so any downstream JSON-LD parser treats the document as
typed RDF without configuration. The reference implementations
do this in ReceiptBuilder::seal and
PolicyReceiptBuilder::build; the without_context()
opt-out is reserved for conformance-vector regeneration and
backward-compatible wire-form replay.
The vocabulary subclasses W3C PROV-O where the alignment is exact:
jc:ClaimProvenance &rsubeq; prov:Entityjc:AuditEvent &rsubeq; prov:Activityjc:AgentIdentity &rsubeq; prov:Agent
PROV-O consumers can therefore reason about a JouleClaw deployment as a provenance graph using this one IRI mapping — no JouleClaw-specific code beyond the standard PROV-O semantics.
Versioning. A future major bump publishes under
/vocab/v2#. v1 IRIs remain resolvable forever per the
open-standards "names are final" rule.
14. Hydra ApiDocumentation
A JouleClaw service publishing a tool surface (MCP server, the
out-of-process policy daemon, an HTTP endpoint) SHOULD serve a
Hydra Core Vocabulary hydra:ApiDocumentation document
at a stable discovery endpoint. Hydra is the W3C CG draft that
solved the "tool schemas live in the client's context window"
pathology for the third-generation web: the API describes itself
in a machine-readable form, a generic client reads the description
once, and the client calls every operation without ever loading a
schema into its context.
A conforming ApiDocumentation:
- Is JSON-LD using both the Hydra Core Vocabulary namespace
(
http://www.w3.org/ns/hydra/core#) and the JouleClaw vocabulary namespace from §13 (jc:prefix). - Carries
@type: "ApiDocumentation"at the root, a stable@id, a human-readabletitle+description, and asupportedClasslist. - Each
ClassinsupportedClasscarriessupportedOperation— oneOperationper published verb. AnOperationdeclaresmethod,expects(input class IRI;owl:Nothingfor parameterless),returns(output class IRI), andstatusCodes. - The JouleClaw extension fields
jc_tool_id(stable tool id) andjc_mutating(mirror of MCP's mutation flag) MAY appear on each operation. They reference the JouleClaw vocabulary from §13 so a receipt emitted by that tool cross-links back to its Hydra description.
Default mappings the reference emitter uses:
| Source field | Hydra field | Default value |
|---|---|---|
mutating: false |
method |
"GET" |
mutating: true |
method |
"POST" |
| (none) | expects |
owl:Nothing |
| (none) | returns |
jc:ToolResponse |
| (none) | statusCodes |
200, 400, 500 |
name |
jc_tool_id |
"jouleclaw:<name>" |
The reference emitter is jouleclaw-hydra::ApiDocumentationBuilder
in the workspace; the mcp-adapter feature provides
From<&McpToolSchema> for ToolDescription so an existing MCP
server emits a Hydra doc in one chained call.
A generic third-generation agent client fetches the
ApiDocumentation, validates the @context, and is then free to
call every tool by following the typed contract — no
out-of-band tool prompts, no schema-per-tool context bloat.
This is the structural fix for the generation-2 "72% of context
window on tool schemas" pathology.
15. SHACL shapes
A JouleClaw service SHOULD publish SHACL Core shapes for every input/output class its Hydra ApiDocumentation (§14) references. The shapes let an agent validate a candidate payload before calling a tool — locally, without any model invocation, with deterministic results.
The canonical JouleClaw v1 shape graph lives at
https://jouleclaw.transaction.science/vocab/v1.shapes.ttl
and covers every class in §§2, 8, 10, 11 (Receipt, PolicyReceipt,
WorkspaceManifest, WorkspaceEntry, AgentIdentity, Action with the
three subclasses, Decision with Allow and Deny subclasses,
ToolTouch, ClaimProvenance). The shapes use only SHACL Core
constraints — no SPARQL, no qualified value shapes —
so:
- A full SHACL validator (pyshacl, Apache Jena) accepts the file
directly and produces a
sh:ValidationReportagainst any candidate document. - A lightweight in-tree validator (the reference impl is
jouleclaw-shacl::ShapeGraph::jouleclaw_v1()) covers the same constraints in ~600 lines of Rust with no SPARQL engine. Compiles to WASM so an in-browser agent can validate locally.
Constraints in use: sh:minCount / sh:maxCount, sh:datatype
(xsd:string, xsd:integer, xsd:nonNegativeInteger, xsd:dateTime,
xsd:double, xsd:boolean), sh:nodeKind (sh:IRI, sh:Literal),
sh:in (enumerations), sh:pattern (regex), sh:minInclusive /
sh:maxInclusive, and sh:node (nested shape delegation).
The shape file is the contract a JouleClaw operator publishes alongside their Hydra ApiDocumentation; the lightweight validator is the agent-side counterpart. A tool input that fails validation MUST NOT be sent to the tool.
16. Validation contract
A validation contract is the planning artifact a multi-step JouleClaw run is judged against. It is authored before any implementation work begins, lives independently of the code, and is the only thing that decides whether a mission succeeded.
16.1 Shape
A contract is a JSON document with the fields:
jc_contract:"contract/1"(this version).@context: optional JSON-LD context, defaults tohttps://jouleclaw.transaction.science/vocab/v1.jsonld.title: free-form mission name.authored_by:did:key:…of the agent or person who sealed the contract. May be empty for unsigned drafts.assertions: an ordered list ofAssertion. Ids MUST be unique within the contract.features: an ordered list ofFeature. Ids MUST be unique. Each feature'sclaimsMUST reference only assertion ids that exist in the contract.acceptance: optional metadata controlling ship-gate rules.
The contract's content hash is BLAKE3 over the canonical JSON serialisation; identical contracts → identical hashes. The content hash is what a JCR-1 receipt binds to when it claims to have run against this contract.
16.2 Assertion
Each assertion is one falsifiable claim:
id: stable string (e.g.,"A-001").title: one-line summary.rationale: free-form why. Optional.priority: one ofmust_have|should_have|nice_to_have.check: one of:{ "kind": "tool", "tool_id": "…", "args_hash": "…"? }{ "kind": "artifact", "path": "…", "expected_hash": "…"? }{ "kind": "command", "command_hash": "…", "expected_exit": N }{ "kind": "checker", "checker_id": "…" }
A must_have assertion that does not roll up to verified
MUST block ship. A should_have assertion that does not
roll up to verified MUST NOT block ship unless
acceptance.block_on_should_have is true.
16.3 Feature
Each feature is one unit of work that claims one or more assertion ids it intends to satisfy:
id: stable string (e.g.,"F-001").title+ optionaldescription.claims: list of assertion ids this feature covers.
A worker dispatched against a feature SHOULD emit evidence for every assertion that feature claims; the verifier surfaces missing evidence as a gap.
16.4 Evidence
The verifier consumes a bag of evidence items the run produced:
tool_result { tool_id, args_hash?, passed }artifact_present { path, hash }command_run { command_hash, exit_code }checker_result { checker_id, passed }
An evidence item matches an assertion when its discriminants
match the assertion's check. A matching item with passed: true
(or, for command, exit_code == expected_exit; for artifact,
hash == expected_hash when supplied) raises the assertion to
verified. Any matching failure raises the assertion to
failed; the verifier surfaces the disagreement rather than
silently allowing a later success to mask it.
16.5 Verification
The verifier is a pure function over (contract, evidence). It
emits a ContractVerdict:
jc_verdict:"verdict/1".contract_hash: hex BLAKE3 of the contract.passed: boolean.summary: human-readable one-liner.coverage: a typed matrix with one row per assertion, one column per feature, plus a per-assertion rollup (verified|claimed_unverified|failed|gap).blocking_gaps: must-have assertion ids not rolled up toverified.should_have_gaps: should-have assertion ids not rolled up toverified.
Same inputs → same verdict. The verdict is the artifact a receipt links to when reporting a multi-day run's outcome.
16.6 Conformance
A conforming producer of a contract MUST:
- Set
jc_contractto"contract/1". - Reject duplicate assertion ids and duplicate feature ids.
- Reject features whose
claimsreference unknown assertion ids.
A conforming verifier of a contract MUST:
- Implement the rollup rules in §16.5 exactly: any matching
failure →
failed; otherwise any matching pass →verified; otherwise any claim →claimed_unverified; otherwise →gap. - Block ship on any
must_havenon-verifiedrollup. - Block ship on
should_havenon-verifiedrollups iffacceptance.block_on_should_haveis true.
Reference: crates/jouleclaw-contract.
SHACL shape: jc:ValidationContractShape at
vocab/v1.shapes.ttl.
16.7 Verdict receipt
The §16.5 verifier emits a ContractVerdict
as plain JSON. To land that verdict on the unified auditable log
alongside cascade receipts ("1") and policy receipts
("policy/1"), wrap it in a verdict receipt — sibling
schema "verdict-receipt/1", same canonical det-CBOR +
COSE_Sign1 envelope every other JouleClaw sibling receipt uses,
under the same steward identity.
{
"jc_receipt": "verdict-receipt/1",
"id": "<uuid v4>",
"closed_at": "<rfc 3339>",
"steward": "<did:key handle>",
"engine_id": "<id>",
"audit_sequence": 7,
"contract_hash": "<hex BLAKE3 of the contract>",
"verdict": { /* ContractVerdict, verbatim */ }
}
Wire-format rules:
- The canonical signed core carries the verdict as a
JSON-string field named
verdict_json(not a nested object), with a siblingverdict_hashfield set to hex BLAKE3 of theverdict_jsonbytes. This keeps the signed core inside the JCR-1 canonical-CBOR subset (which forbids bools and nulls) while still binding the verdict to the signature. The wire-form JSON object surfaced to consumers MAY carryverdictas a nested object for ergonomics; the signed core is normative. - The COSE_Sign1 envelope is identical in shape to JCR-1 v1:
protected = {1: -8, 4: steward},unprotected = {},payload = canonical signed core,signature = Ed25519(Sig_structure). contract_hashMUST equal the BLAKE3 content hash of theValidationContractthe verdict was produced against. Verifiers consuming the unified log MAY index bycontract_hashwithout parsing the inner verdict.
Conforming producers + verifiers SHOULD reuse the existing
JCR-1 envelope tooling (verifiers reject envelopes whose kid
disagrees with the embedded steward, etc.).
Reference: crates/jouleclaw-contract-receipt.
17. Worker handoff
A worker handoff is the structured wire form an agent emits at end-of-feature-work. The handoff is what makes a multi-day run readable to the next worker (or the next session of the same worker) — it forces the agent to write down what actually happened rather than relying on conversational context.
17.1 Shape
A handoff is recorded as a RunEvent::HandoffRecorded variant
on the run journal:
worker: stable worker id (typicallydid:key:…).node_id: optional graph node this handoff closes.feature_id: optional contract feature id this handoff claims to satisfy.closed_at: epoch-seconds wall-clock.completed: list of items reported done.undone: list of items reported left undone.commands: list of{ command_hash, argv, exit_code }entries observed during the work window.issues_found: list of issues the worker discovered.procedures_followed: list of skills / runbooks the worker applied.
command_hash MUST be hex BLAKE3 over argv.join("\0"). The
hash, not the argv array, is the command's identity; the argv
is carried for human inspection only.
The handoff hash is part of the journal entry's hash chain, so editing handoff fields after the fact breaks chain verification.
17.2 Conformance
A conforming producer of a handoff MUST:
- Set every field that is non-empty in the run; empty lists are acceptable but the discriminator MUST be present.
- Compute
command_hashas specified.
A conforming consumer of a handoff MUST:
- Accept additive fields (the variant set is open under semver-compatible extension).
- Verify the journal's hash chain before trusting the handoff's contents.
Reference: crates/jouleclaw-graph
(WorkerHandoffEvent, HandoffCommand,
RunEvent::HandoffRecorded). SHACL shape:
jc:WorkerHandoffShape at
vocab/v1.shapes.ttl.
18. Mission orchestrator
The mission primitive composes §16 contracts
- §17 handoffs + the run journal into a three-role pipeline: Orchestrator authors, Worker does, Validator judges.
18.1 Roles
- The Orchestrator authors a
ValidationContractand a feature plan. It does NOT execute work; it composes the plan and the validator's expectation in one artifact. - A Worker is dispatched per feature. It performs whatever
work it does (opaque to this spec) and returns a
WorkerOutcome { handoff, evidence }. Workers MAY be backed by any cascade tier — deterministic tools, models, or humans-in-the-loop. - The Validator runs the §16.5 verifier over the
accumulated evidence and emits a
ContractVerdict. The validator's only input is(contract, evidence)— pure data — so its verdict is reproducible and reviewable.
18.2 Dispatch
Workers MUST be dispatched in feature order, serially, when the features mutate shared state. Read-only fan-out (parallel search, parallel verifiers) MAY be parallel; the implementation is the caller's choice and the spec does not require it.
Each worker's handoff MUST be recorded on the run journal before the next worker is dispatched, so the chain stays chronological.
18.3 Strictness
A strict_workers mode MAY refuse worker outcomes that produce
no evidence for at least one assertion the worker's feature
claims, failing fast rather than letting the validator surface
the gap later. The default behaviour is non-strict (let the
validator rollup decide).
Reference: crates/jouleclaw-mission.
19. Value report
Where a JCR-1 receipt records what happened (the activity), a value report records what landed against the agent's declared intent. The two together close the activity-vs-value gap: activity is easy to count; value is what the user paid for.
19.1 Shape
A value report is a JSON document:
intent: free-form natural-language intent the agent was acting on.tool_id: tool id the call addressed.checks: per-check verdicts, each{ check, passed, reason? }.closure_rate:passed_count / checks.len()∈ [0, 1].0.0whenchecksis empty.fully_closed: true iffchecksis non-empty AND every check passed.
19.2 Check kinds
status { codes }— status code MUST appear incodes.status_matches_contract— status MUST be in the operation's declaredstatusCodesmenu (the Hydra contract).output_hash_equals { hash }— canonical-JSON BLAKE3 of the body MUST equalhash.json_pointer_equals { pointer, expected }— RFC 6901 pointer MUST resolve toexpected.
Implementations MAY define additional check kinds; consumers
MUST tolerate unknown kinds and treat them as passed: false
with a reason that names the unknown kind.
19.3 Aggregation
The mean closure rate across a set of value reports is the system's honest "delivered / attempted" metric — denominated in user intent rather than joules. Reports with no checks declared MUST be skipped in the aggregate (they convey no value information).
Reference: crates/jouleclaw-hydra-client
(ValueReport, ValueCheck, ValueCheckResult,
mean_closure_rate).
20. What this spec deliberately does not say
- How to build the model. That's the model-author's concern. JouleClaw measures and dispatches; it doesn't train.
- Which retrieval API to use. Brave / Tavily / Exa / Serper all
plug in through the
SearchProvidertrait. Pick whichever your deployment permits. - How to ship receipts. The receipt is produced. Transport (HTTP / lockstep / message queue) is the deployer's choice. Smart Byte's signed-envelope replication is the recommended substrate.
- A specific signing key topology. Bring your own. Smart Byte's KERI-based AID rotation is the recommended path.
21. Adjacent techniques
This section names the architectural pattern JouleClaw implements and lists the research communities that have, separately, solved parts of it. The intent is not novelty-claiming. It is to make the assembly visible so an engineer arriving from any one of those communities can locate their work inside the cascade.
9.1 The architectural pattern
An LLM inference call is a render pass. A token is a frame. A reasoning chain is a sequence of frames. A context window is a scene graph. An agent loop is an NPC control loop. RAG is texture streaming. A model checkpoint is a level asset. The pipeline from prompt to response is — structurally — exactly the work a game engine does between input poll and presented frame.
The game-engine industry was forced to solve this problem under a fixed 150–200 W power budget twenty years ago. The five JouleClaw cascade tiers are direct translations of game-engine architectural primitives:
| JouleClaw tier | Game-engine primitive | What the engine actually does |
|---|---|---|
L0:Cache |
texture / asset cache | Content-addressed; cheap to check; valid until invalidated |
L1:Lawful |
pre-baked geometry, LUTs | The work the engine refuses to run because the answer is already in the format |
L2:Embed |
BVH / spatial query | Find the closest match; do not compute from first principles |
L3:Model |
procedural / runtime synthesis | Invoked only when nothing baked or streamed will do |
L4:Wire |
server-streamed asset / CDN | The escape hatch when the local box cannot satisfy |
Each game-engine technique listed below has a near-exact counterpart in modern AI inference that the AI industry has, so far, declined to deploy at the same architectural rigor:
Every lever below now has a shipped JouleClaw realization — the frame is no longer rhetorical; each row points at in-tree code:
| Game-engine technique | AI counterpart | JouleClaw component (shipped) |
|---|---|---|
| Frustum culling | Skip tiers whose estimate_cost returns None |
jouleclaw-cascade::Tier::estimate_cost |
| Level-of-detail (LOD) | Route to the cheapest sufficient model — SLM before frontier | jouleclaw-dispatch::ModelBankTier (cheapest capable slot by measured J) |
| Deferred rendering | Do not forward-pass through 175B parameters for a token a 7B would produce identically | jouleclaw-dispatch cost-table over backends declaring their J/op |
| Physically-based rendering | One foundation model, derive specializations — not 12 full fine-tunes | (consumer concern; the spec doesn't dictate) |
| Virtual texturing | Retrieve only the context this token will attend to, not the whole 128k window | jouleclaw-stack RAG pipeline (retrieve → enrich → rerank → read, top-k only) + jouleclaw-fresh |
| Temporal upsampling | Reuse prior verified work; reconstruct from a small delta, not by re-running | jouleclaw-promote (exact yang→yin) + jouleclaw-skill (whole query class) |
| Nanite-style mesh streaming | Activate only the reasoner the input actually needs | jouleclaw-dispatch routes to the one slot, not the whole bank |
| Hardware ray tracing + denoiser | A few high-quality forward passes plus a verifier beats one large unconstrained pass | jouleclaw-verify (OutputVerifier) + jouleclaw-approve gate before the pass |
| Agent / NPC control loop | Bounded multi-step recursion — fan-out capped, depth bounded by the joule budget | jouleclaw-agent (max_steps + per-branch budget clamp) |
| Frame budget | JouleBudget walks the cascade like a render budget walks the scene graph |
jouleclaw-energy::EnergyQuota + breaker, jouleclaw-governor (global), jouleclaw-agent (nested) |
The pattern is not new. The assembly — and the fact that every lever is a shipped, tested crate rather than a slogan — is.
9.2 Five communities, one architecture
Five research communities currently hold one face each of this architecture. They publish at different venues and do not, by and large, talk to one another. A conforming JouleClaw runtime composes all five of their primitives — that composition is the standard's contribution.
| Community | Representative work | JouleClaw component |
|---|---|---|
| Constrained decoding | Outlines (Willard & Louf), XGrammar (Dong et al. 2024), Guidance, LMQL, Pre³, OpenAI/Anthropic structured-output APIs | jouleclaw-decode (shipped) — pure-Rust regex / CFG / JSON-schema → token-vocabulary mask |
| Compound AI systems / DSPy | DSPy (Khattab et al., Stanford → MIT; CAIS 2026 inaugural ACM conference, May 2026) | jouleclaw-program (shipped) — typed signatures + module compiler — and jouleclaw-skill, its deterministic skill-compilation realization |
| Small / specialist models | NVIDIA Research (Belcak & Heinrich, 2025), Microsoft Phi team, TinyML, llama.cpp | jouleclaw-cascade router + jouleclaw-pack declared-cost contracts |
| Neurosymbolic / verifier-in-the-loop | Lean + LLM provers, BMC + LLM (LaM4Inv), SymCode, ProofNet++, VIRF, Eidoku | jouleclaw-verify (OutputVerifier trait + VerifierChain + receipt integration) |
| Energy measurement / Green Software | Patterson et al., ML.ENERGY Leaderboard, MDPI Sensors edge-computing surveys, GSF SCI specification, AI Energy Score | jouleclaw-energy + the Provenance honesty contract + .jc.toml measured-cost rows |
A conforming runtime SHOULD be able to point at concrete in-tree code or a registered adapter for each of the five primitives above. A runtime that solves only one face is a research project, not a JouleClaw implementation.
9.3 The three-lever ceiling
Energy reduction from a fully-naive monolithic baseline (~10¹⁸ above the Landauer floor for current generative inference per output bit) composes multiplicatively across three independent levers:
| Lever | Reduces by | What does it |
|---|---|---|
| Route to the right cell | 10⁸–10¹⁰× | The cascade itself — L0 / L1 / L2 close most queries without invoking a model |
| Cache the prior work | 10²–10⁴× | Content-addressed cache (L0), prior-resolution history, MRL embeddings (L2) |
| Align silicon to primitive | 10²–10⁴× | The .jc.toml declared-cost contract is the input data hardware co-design needs |
Stacked total: 10¹²–10¹⁸× below the naive baseline. The "90 % reduction" figure quoted on the marketing surface is the conservative floor of what the three levers permit when composed honestly.
The ceiling is not the Landauer bound — reaching the bound requires reversible logic and zero-impedance interconnect that nobody can engineer today. The ceiling is how disciplined the routing and the hardware choices are.
9.4 The receipt is the proof, not the marketing
A runtime that produces lower receipts than the conformance vectors
demand without the per-tool-touch Provenance to back them is
non-conformant. JouleClaw refuses the receipts-as-marketing failure
mode that has accumulated around carbon offsets and software
sustainability claims more broadly. Every joules_uj figure in a
conforming receipt must trace back to either a real hardware
counter (Provenance::HwShunt), a documented vendor model
(Provenance::ModelBased), or a calibrated static estimator
(Provenance::Estimator) with a wider tolerance band.
A hardware counter here means one that was live for the domain the
figure claims (§1.3, Liveness). A counter that is present but not
live — frozen, or republished in lumps — is not a hardware reading
however real the silicon behind it: its span is the estimator's, or
the work is reported unmetered, and the receipt says so. Grading a
frozen counter's figure HwShunt is the receipts-as-marketing
failure mode in its most literal form.
The breaker enforces at the granularity of the worst counter in the span. This is normative.
22. References
- JouleClaw Charter — stewardship pattern (shared across all five open standards)
- Smart Byte open standard — signed envelopes
- EOC open standard — the four-stage memoising cascade pattern JouleClaw embodies
- WAI open standard — media transport + capability dispatch
- OpenPay open standard — the typestate-enforced lifecycle pattern adopted by JouleClaw's cascade
- W3C PROV-O — provenance vocabulary
- RFC 9449 — DPoP (sender-constrained tokens, recommended for ClaimProvenance envelopes that carry a fetch credential)
- Landauer, R. (1961). "Irreversibility and Heat Generation in the Computing Process." The thermodynamic floor under everything in this spec.