open-standards/jcp/README.md
Transaction Science 3f241088d3
All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 22s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 3m39s
standards workspaces build + test / jcp-rs (jcp-conformance, jcp/jcp-rs, -p jcp-energy --features nvml, jcp-rs, linux) (pull_request) Successful in 1m43s
standards workspaces build + test / joule-ui-rs (joule-ui/joule-ui-rs, joule-ui-rs, linux) (pull_request) Successful in 1m17s
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 1m20s
standards workspaces build + test / sandbox-rs (sandbox-conformance, sandbox/sandbox-rs, sandbox-rs, linux) (pull_request) Successful in 2m26s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 12m44s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 5m33s
standards workspaces build + test / jouleclaw-rs (-nodebug, jouleclaw/jouleclaw-rs, -p jouleclaw-energy --features rapl,nvml, jouleclaw-rs, linux-arm64, -C target-feature=+fp16) (pull_request) Successful in 3m59s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 3m10s
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 2m3s
jcp-efficiency: the outcome anchor is not ours alone; the signature is
Three places claimed the outcome anchor as the thing nobody else has:

- `src/lib.rs` — "the four figures that matter, plus the one thing the
  incumbents omit — the **outcome anchor**"
- `MAPPING.md` §0 — "seals all four **with the outcome anchor the rates
  omit**"
- `jcp/README.md` — "with the one thing the rates omit: the **outcome
  anchor**"

That is no longer true. Panigrahy, Tyagi, Abkin, Houngninou and
Mahapatra, *Energy per Successful Goal: Goal-Level Energy Accounting for
Agentic AI Systems* (arXiv:2605.22883, v1 2026-05-20, v2 2026-10-12),
defines EpG as "total workflow energy across all attempts, including
failures and retries, divided by successfully completed goals" — the
same denominator `uj_per_completed_unit()` computes, waste included —
with a measurement framework attributing RAPL and ARM counters to
workflow energy.

What survives the finding, and is now stated as the claim rather than
assumed inside a broader one: the paper is a *calculation and reporting*
convention. It describes measurement, attribution and a reproducibility
protocol; no part of it signs or attests the figure. So `efficiency/1`
adds not the anchor but the **artifact** — a signed, honest-provenance,
verifiable receipt carrying it. MAPPING.md already said exactly that in
its opening ("supplies the one thing that standard, and every deployed
disclosure regime, lacks: a signed, honest-provenance, verifiable
receipt carrying an outcome-anchored figure"), which is why that
sentence needed no change: it was scoped correctly and the three
downstream restatements were not.

MAPPING.md §0 now cites the prior art in the same ingest-not-compete
form §1 already uses for GSF SCI-for-AI, including the licence
constraint (arXiv non-exclusive — cited and briefly quoted, never
reproduced). Naming it is within the naming rule, which permits
standards, bodies, protocols, papers and open-source projects to be
named factually; `check-public-names.sh` scopes to `wai/` in any case.

Guards run locally before pushing, since this is public text:
comparative-prose clean (2307 files), no vanity metrics (277 Markdown
files), check-spec-refs 1613 citations all resolving.
`cargo test -p jcp-efficiency`: 54 + 6 pass.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-18 08:32:52 -04:00

106 lines
21 KiB
Markdown
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.

# JCP — The Joule Context Protocol
A unified, energy-native, capability-secured protocol for agentic systems. Where
today's stack splits across MCP (tools), A2A/ACP (agent-to-agent), an identity
layer, and an authorization layer — and standardizes energy nowhere — JCP is one
spec, built on one idea:
> **A capability and an energy budget are the same object: a signed, bounded,
> debited grant. A capability you can't pay for is denied; an expenditure you're
> not capable of is denied. One check, made outside the model, sealed in a
> receipt.**
The design answers the documented failure modes of the current agentic
ecosystem, not hypotheticals. Tool descriptions are untrusted input → JCP refuses
to take control from a tool's *output*. Prompts can't enforce access control (and
a more capable model only follows injected instructions *better*) → JCP decides
every action in the runtime, never in the LLM. Agent loops have no cost ceiling →
every grant carries a joule budget that's debited and enforced before the side
effect. Audit is a mutable telemetry span → JCP seals every decision, allow and
deny, as a non-repudiable signed receipt.
- **Licence:** Apache-2.0 for reference code (see [`LICENSE`](LICENSE)); CC-BY-4.0 for specification text (see [`LICENSE-SPEC`](LICENSE-SPEC)).
- **Status:** v0.3.0 draft. Specification core published ([`SPEC.md`](SPEC.md) + [`conformance/v1/`](conformance/v1/)); reference workspace `jcp-rs/`.
## What's here
```
jcp/
├── SPEC.md — the normative standard (§1–§12)
├── conformance/v1/ — published vectors (a signed grant + allow/deny receipts)
└── jcp-rs/ — the Apache-2.0 reference implementation
```
### The reference implementation (`jcp-rs/`)
- **`jcp-schema`** — the wire objects: the `did:key` actor, the **Grant** (the metered capability — capability ⊗ joule budget, content-addressed and signed), the **Frame** (every message, with its `control`/`data` trust tag), the family `Energy`/`Provenance` model, canonical det-CBOR content addressing.
- **`jcp-grant`** — issuance, signature verification, **attenuation** (object-capability delegation where a child grant can only narrow — capability ⊆, budget ≤, expiry no later, delegation depth − 1), **chain verification** (root-first, hop-by-hop: parent links, holder-issued hops, narrowing, signatures, depth bounds), **revocation** (issuer-only, signed, admitted into a `RevocationSet` only after authority checks), **sharding** (`shard()` splits a grant into siblings whose budgets must sum within the parent — distributed enforcement with no consensus, SPEC §4.5), and **identity continuity** (`KeyLog`: KERI-style pre-committed rotation, SPEC §2.1 — a thief with the current key can't rotate, an owner who lost it still can).
- **`jcp-runtime`** — the deterministic enforcer. One ordered check fuses authorization and energy, decided **outside any model**: untrusted-control, revocation, **configured trust roots** (an enforcement point honors only the root-issuer keys it was configured with — `authorized_keys` shape, no CA), audience binding, signature, expiry, capability, and budget — then debit. The first failure names the reason. `decide_chained` enforces full delegation chains: a revoked ancestor kills the subtree, and the cost must fit — and is debited from — **every** link, so sibling delegations share their root's budget and delegation can never mint joules.
- **`jcp-receipt`** — the `jcp/1` JCR-1 receipt: canonical det-CBOR + COSE_Sign1/EdDSA, byte-compatible with the family verifiers. Allow and deny both seal. The receipt stream is the write-ahead log (SPEC §8.1): a chained receipt records `chain_ids` — every link the decision debited — so `replay_spend` rebuilds an enforcement point's budget state, **ancestors included**, from its own verified output with no external index; `aggregate` keys a team's receipts by `(grant, subject)` for per-worker cost attribution computed from evidence (SPEC §8.2).
- **`jcp-bridge`** — a reference gateway that wraps **existing MCP tool calls and A2A tasks** in Grants and Frames without rewriting the endpoint. It maps each outbound call to a Frame (the tool/method is the action; the `(server, tool)` identity is the content-addressed resource), decides it against the caller's grant *before* the call reaches the endpoint, and seals a receipt — so an existing server keeps its transport while every call becomes capability-scoped, joule-budgeted, decided outside the model, and sealed. Inbound results are framed as untrusted `data`.
- **`jcp-a2a`** — the **A2A + AP2 profile**: ingests an open [A2A](https://a2a-protocol.org) **Agent Card** (each advertised `skill` becomes a content-addressed JCP capability, bound to the `a2a:<agent>:<skill>` audience) and an [AP2](https://ap2-protocol.org) payment **mandate** (its authorization, read in **joules**, becomes the grant's budget — a currency mandate yields no budget, because the profile invents no exchange rate), mints one capability-scoped joule-budgeted grant per skill, and gates every A2A task against them through the bridge. A `message/send` targeting a skill the card never advertised — or one past the AP2 budget — is denied **before** it reaches the peer, and the denial seals like an allow. The open agent-interop wire keeps its transport; JCP adds the capability, the energy budget, and the cryptographic audit it lacks.
- **`jcp-policy`** — **contextual service policies**: the content-keyed, require-approval layer a static grant audience can't express. A `Policy` matches a call on its action, **content** (a secret marker, a sensitive path, a forbidden recipient), or resource and either **denies** it or **requires approval** — a human consent resolved by an Ed25519 signature over the call's context digest (which binds the **content hash**, never the content, so consent is to one exact call). The verdict composes with the grant decision — the policy is the second, content-aware gate after the capability allows — and seals as a hash-chained **`policy/1`** receipt: the allow, the deny, and the held/approved consent in one audited ledger. The "service policy" shape — allow / deny / require-approval over tool+args+identity, decided outside the model — with the joule budget (on the grant) and the cryptographic audit the incumbent's table-row log lacks.
- **`jcp-orchestrate`** — a **cross-harness orchestration profile**: a deterministic reconcile loop (poll → route → dispatch → reconcile → retry) that runs work items across a *heterogeneous* fleet of `Harness` backends, where every dispatch is **capability-gated** (a harness is granted only the task kinds it may handle), **joule-budgeted** (an exhausted harness fails over to the next one with capacity), and **sealed** as a JCR-1 decision receipt *before* it runs. A task whose kind no harness is granted is denied; a flaky harness retries up to a bound; the whole run is an ordered, verifiable ledger of sealed decisions. The compose-many-harnesses shape a meta-harness offers — with the capability, energy budget, and audit it leaves to the platform.
- **`jcp-prompt`** — a **signed, content-addressed prompt registry**: immutable prompt **versions** (double-brace `{{ variable }}` templates) with mutable **aliases** (`dev` / `staging` / `production`) resolved by `prompts:/<name>@<alias>` (or `prompts:/<name>/<version>`) URIs — the registry shape the serving ecosystem already uses. The difference: each registered version and each alias **promotion** seals as a hash-chained **`prompt/1`** receipt, and a version's id *is* its template, so swapping the text under a name changes the id and re-pointing an alias is a signed entry in an ordered log. The exact instructions an agent ran under — and which version was live when — become tamper-evident artifacts, not a row someone with write access can edit.
- **`jcp-trace`** — ingests an agent run's **OpenTelemetry GenAI trace** (`gen_ai.*` semantic conventions: `chat` / `tool` / `retriever` spans with token usage) and its **evaluation assessments** (judge / human / code feedback), attaches **per-span joules** (measured where a meter is present, else `Estimator` from token counts — provenance never silently upgrades), and seals one **`eval/1` JCR-1 receipt**: the per-span token + joule breakdown with the headline `uj_per_accepted_token` at the **weakest** provenance present, the assessments, a deterministic **quality-gate** verdict (the sealed, declarative analog of a CI assert), and a **readiness projection** an ARL validation-axis claim consumes. The observability stacks *record* a trace and *log* a judge score in a table; this is the interop projection that **seals** the same trace, puts a joule on it, and hash-chains it via `EvalLog` — no new cryptography. The **gate is content-addressed**, so the sealed receipt commits to exactly which bar it was judged against (a tamper-evident artifact, not a mutable in-code `assert`), and **`align_threshold` / `Judge`** calibrate a judge's decision threshold to human pass/fail labels — judge alignment as a reproducible number, not a UI click. Behind the `server` feature, a std-only **OTLP `/v1/traces` receiver** lets any OpenTelemetry exporter POST a `gen_ai.*` trace (with its assessments) and get the sealed `eval/1` receipt back the instant the run ends.
- **`jcp-intercept`** — **attested interceptor chains**: a composable, ordered pipeline of transforms *around* each model and tool call — the `before_model` / `after_model` / `before_tool` seams an agent's middleware stack runs, composed onion-order (forward in, reverse out) and stopping at the first refusal or human-approval hold. An interceptor may inspect or **rewrite** the request (redact a secret before it reaches the model, trim stale context), **refuse** it, or **hold** it for a human. The difference from the incumbent's arbitrary in-process hooks: every step seals an **`intercept/1`** JCR-1 receipt carrying the request digest **before and after** the step (so a redaction or a trim is provable — the content itself never sealed, only its hash), the seam, the outcome, and the **metered joules** at their honest provenance (where the meter reads a counter, a seam pass is one reading divided among its steps by each step's thread CPU time, so the steps sum to it exactly and each share is graded `ModelBased`), hash-chained — the exact transform pipeline that produced a model request becomes reconstructable and verifiable by anyone, and a step cannot run un-sealed. Three reference interceptors — `Redact` (a content transform), `CallLimit` (a guardrail), `Approve` (a human-in-the-loop hold) — each reuse a primitive the family already holds rather than reinventing it.
- **`jcp-efficiency`** — the **energy-efficiency spec**, surfaced as a sealed receipt. The dark-factory economics turn on four figures — **joules per accepted token, tokens per second, value per token, and the tokens/joules/dollars spent per COMPLETED, VERIFIED unit of work** — and the incumbents publish, at best, a *rate* (cost per token) that can't tell you whether the spend bought a result. An **`efficiency/1`** JCR-1 receipt records all four at honest provenance, hash-chained, and sealed against an **outcome anchor** (`completed` + a verdict) — goal-denominated energy accounting is a live line of work (`jcp-efficiency/MAPPING.md` §0 cites it); what the receipt adds is that the anchor is signed and verifiable rather than reported. A measurement that didn't complete is spend that bought nothing, and the receipt says so. `aggregate` then splits value-delivered from total spend across a chain — charging *every* attempt (including the failed ones) against the results actually delivered — so `tokens_per_completed_unit` / `uj_per_completed_unit` / `value_per_joule` become the honest efficiency a "cost per token" number is designed to hide. Integers and strings only (JCR-1 forbids bools/floats); the rate figures recompute from the sealed inputs on read.
- **`jcp-energy`** — the metering ladder (SPEC §5.1): RAPL package counters (Linux powercap, wraparound-corrected, `HwShunt`, only while every package counter is live — `rapl_status()`), NVML GPU energy behind the `nvml` feature (`HwShunt` and `Partial`, since it does not read the CPU's share; only while live — `nvml_status()`), the macOS kernel's per-process CPU energy count (`proc_pid_rusage`'s `ri_energy_nj`; `HwShunt`, whole for in-process CPU work, only while live — `process_energy_status()`; it covers this process's threads, not children, the GPU or DRAM, so a span that reaps a child process or ends with one is `Partial`; each end of a span is read only once the metering thread is seen to have left its core, because the kernel counts a thread's energy into its process's only then, and a span with an end not so checked is the estimate, never a reading; it is live on macOS 27.0.1 where IOReport's CPU rails are not), Apple Silicon IOReport (`HwShunt`, only while every CPU energy rail, each die's on a multi-die part, is live — on macOS 27.0.1 that rail is republished in lumps, so there the rung is declined and `ioreport_status()` says why; `Meter::detect_explained()` names the rung selected and why each one above it was declined), a time×power model at a power the host calibrated (`ModelBased`, `Meter::time_power`), and estimates no host calibrated (`Estimator`): time × the documented default power — the rung `Meter::detect()` falls to, always available — and a constant per-op figure. A vendor counter's reading is real but vendor-opaque and relayed by the platform, and it counts as a reading only while the counter is live (SPEC §5). Measured when the platform exposes it, estimated when it doesn't — and the provenance always says which; a hardware backend that fails mid-reading degrades honestly to the default-power estimate.
- **`jcp-gateway`** — the **energy-native MCP gateway**: a JCP enforcement point that sits in front of an MCP server so an existing client/server pair keeps its transport while every `tools/call` becomes capability-scoped, joule-budgeted, and sealed. The novel mechanic is two-phase metered enforcement: the call is *authorized* before it runs (no debit, because the cost isn't yet known), the upstream call is **metered** by the sibling Sandbox standard's energy probe (Apple Silicon IOReport, RAPL, NVML — vendor energy counters, whose readings are real but vendor-opaque and relayed by the platform, and which count as readings only while the counter is live for the work, SPEC §5; otherwise the figure is an estimate and is graded as one), and the metered joules are debited from the grant — so the budget that stops a runaway agent is denominated in joules, not a token estimate. Where the upstream server is a local process whose CPU energy the host's kernel counts live (macOS `proc_pid_rusage`), each call is read on that server's own process tree, the work's own process rather than the machine (SPEC §5.1, rung 3): sealed `HwShunt`, and `Whole` only when nothing was seen missing from the tree (no descendant reaped or exited in the span, no GPU client held, no in-process Neural Engine memory, every member read and quiet at both ends) and the operator has declared, with `--upstream-self-contained`, that the server hands no work to a process outside its tree; otherwise `Partial`, with the response's `_meta` naming why. Every decision, allow and deny, seals into a **hash-chained receipt log**: excise, reorder, or splice a receipt and the chain breaks at that point. A denied call never reaches the server (the live 2025–26 MCP exploits land on tool *output*, which the gateway frames as untrusted `data` that can never exercise a capability), and the `jcp-gateway` binary runs it over stdio in front of any MCP-server subprocess. This is the chokepoint the AI-gateway field occupies, on the two axes nobody there holds: the unit of account is the joule, and the audit is cryptographic and tamper-evident rather than a dollar figure and a span.
- **`jcp-wire`** — the `jcp/1` wire binding (SPEC §11): 4-byte length prefix + canonical det-CBOR over any byte stream, with TCP and Unix-socket endpoints and a client. The decoder rejects non-canonical bodies, so a message has exactly one wire form. Requests carry the full delegation chain and are **caller-signed** — the endpoint authenticates from the request itself and denies an impersonation `bad-signature`, sealed like any other decision. Responses carry the deterministic decision and the sealed receipt.
- **`jcp-threshold`** — threshold actors (SPEC §2.2): a `did:key` whose private key is split k-of-n with FROST (RFC 9591); the group key is an ordinary Ed25519 key, so a 2-of-3 team issues, holds, and signs wire requests with nothing else in JCP changing. Shares come from a trusted dealer or **distributed key generation** — with DKG the group's private key never exists anywhere, not even momentarily. The two-agent rule for irreversible actions, refused by arithmetic rather than policy.
- **`jcp-channel`** — receipt-settled budget channels (SPEC §4.5, the OPTIONAL profile): N enforcement points spend optimistically against one grant and settle by exchanging signed statements of cumulative spend — forged, stale, and regressing statements refused; between settlements the exposure is bounded by the window, and after settlement any overdraft is provable from the signed statements. Where bounded overdraft is unacceptable, `shard()` remains the baseline.
- **`jcp-conformance`** — C1–C18 + a negative pack, all checks real (C8 decides over a live socket; C13 drives a FROST 2-of-3 caller; C16 replays ancestor debits from a chained receipt; C17 settles a budget channel by signed statement; C18 mints a dealer-free group via DKG), published vectors in `conformance/v1/`.
- **`jcp-cli`** — the `jcp` demo: one metered grant driven through an agent loop — legitimate calls allowed and debited, a poisoned tool-result refused structurally, out-of-scope actions and resources denied, the budget stopping a runaway loop, a sub-agent getting a strictly-weaker delegated grant, a signed receipt verified, the detected meter's rung metering a probe of work at the grade it gave that probe, and the issuer revoking the grant — after which the runtime goes dark.
`cargo test --workspace` green; `cargo clippy --workspace --all-targets`
warning-free.
## The demo, abbreviated
```
costs scripted, no tool runs: sealed as estimates
frame verdict reason rem µJ
read the db (legit) allow −20000 µJ 80000
tool-result says 'delete db' (poison) DENY untrusted-control 80000
try to delete (not granted) DENY action-not-granted 80000
read prod-secrets (wrong audience) DENY wrong-resource 80000
read again (legit) allow −50000 µJ 30000
read again — budget runs out DENY budget-exceeded 30000
amplification refused: capability exceeds parent
receipt allow · 50000 µJ · Estimator · verified true
```
The model never gates itself; the runtime does, and the receipt proves it.
The loop's costs are scripted — no tool runs — so they are fixed, to run the
budget out at the same row every time, and each receipt grades its cost
`Estimator`: a figure nothing read is never sealed as a reading. The demo's
`meter` line is the one figure it takes: the detected meter's rung, and a small
probe of work at the grade the meter gave that probe — a hardware reading only
where the rung's counter read it, otherwise an estimate graded as one.
## Consumers in this repository
JCP is not only specified — it is consumed. Three sibling standards gate their
real dispatch through it, each with its own adapter crate and tests:
- **JouleClaw** (`jouleclaw-rs/crates/jouleclaw-jcp`) — every MCP tool dispatch
is decided against a Grant before a byte reaches the tool; an ungranted tool
named by an injected instruction is refused and the refusal sealed.
- **Sandbox** (`sandbox-rs/crates/sandbox-jcp`) — a unit's execution is
authorized against a Grant bound to its image **by content address**; one
flipped image byte is a different audience and is denied before the executor
is ever invoked. Two receipts per run: the JCP authorization and the
sandbox's metered, attested execution.
- **Joule Code** (`joule-code-rs/crates/joule-code-jcp`) — every cascade-stage
consultation is decided pre-dispatch; the L4 escape hatch to a remote
frontier agent exists only when a signed grant names it and can pay for it.
## Relationship to the family
JCP composes the primitives the Transaction Science family already proved:
`did:key`/Ed25519 identity, capability-gated execution (`sandbox`), the honest
`Energy`/`Provenance` model (`proof`), and JCR-1 signed receipts (family-wide).
It is where they stop being per-tool adapters and become the protocol.