The meter seam's deployable form (SPEC §4 Proxy): point a host's model base_url at joulehook-proxy and every call is capped + sealed. Per request it injects the configured joule ceiling (inject_ceiling), forwards to the Mesh upstream, and seals the response's usage.energy as an efficiency/1 receipt (bridge_receipt_default). tiny_http server + ureq client. Integration-tested against a localhost mock upstream: the mock echoes the injected ceiling (7mJ) and the proxy seals the efficiency receipt; an unreachable upstream is a 502, not a panic. Also dedups the meter steward into joulehook-meter (METER_STEWARD + bridge_receipt_default). 24 tests; clippy-clean. Co-Authored-By: Claude Opus 4.8 <[email protected]>
84 lines
4.7 KiB
Markdown
84 lines
4.7 KiB
Markdown
# JouleHook — Metered, Gated, Attested Agent Work in Any Host
|
||
|
||
*Provisional name — the steward may rename; the profile string `joulehook/1` and the
|
||
seam names are the stable surface.*
|
||
|
||
The energy-accounting and methodology-gating you build for one coding agent is worth
|
||
little if it's trapped in that one agent. JouleHook carries it into the editors
|
||
developers already use — **Claude Code, Cursor, Windsurf, Antigravity, Zed, JetBrains,
|
||
OpenCode** — without forking any of them.
|
||
|
||
It rests on one finding: **no host lets an extension observe its agent's tokens or
|
||
intercept its native tools** — but every host exposes the same three seams, and
|
||
JouleHook is the normative contract over them:
|
||
|
||
> **A per-action *gate*, a model-call *meter*, and a *receipt* surface. Bind those
|
||
> three to a decide-outside-the-model grant check, an honest energy meter, and a
|
||
> sealed receipt, and any agent's work becomes a metered, gated transaction — from
|
||
> one core.**
|
||
|
||
JouleHook does not replace the host's agent. It is the **host-binding layer** for the
|
||
sibling standards: **JCP** decides and grants, **Mesh** meters at the model front
|
||
door, **`jcp-efficiency`** is the receipt. JouleHook adds the seam contract and the
|
||
per-host conformance profiles that make them portable.
|
||
|
||
- **Licence:** Apache-2.0 for reference code ([`LICENSE`](LICENSE)); CC-BY-4.0 for
|
||
specification text ([`LICENSE-SPEC`](LICENSE-SPEC)).
|
||
- **Status:** v0.1.0 draft. Specification published ([`SPEC.md`](SPEC.md)); reference
|
||
workspace `joulehook-rs/` ships the **gate binding** (`joulehook-hook`) for the
|
||
`claude-code` **and** `hooks-family` profiles — one PreToolUse hook that gates by
|
||
JCP capability (decided outside the model, every decision sealed) and speaks the
|
||
native decision format of Claude Code, Cursor, Windsurf, and Antigravity behind a
|
||
`--host` selector; `joulehook-statusline`, the in-editor joule meter (honest `est`
|
||
from Claude Code's own tokens); and `joulehook-mcp`, an MCP server that surfaces
|
||
the sealed decisions as **verified, human-readable** resources in any MCP-speaking
|
||
editor. The `claude-code` `full` profile installs today
|
||
([`joulehook-rs/INSTALL.md`](joulehook-rs/INSTALL.md)); the enforcing Mesh-proxy
|
||
meter + a site land next.
|
||
|
||
## The three seams
|
||
|
||
| Seam | Host mechanisms | What rides it |
|
||
|---|---|---|
|
||
| **Gate** | `PreToolUse`-hook family; ACP `request_permission` | allow / deny / rewrite, decided outside the model, sealed |
|
||
| **Meter** | `base_url` proxy; OTel `gen_ai.*` | tokens→joules, honest provenance, enforceable joule ceiling |
|
||
| **Receipt** | MCP resources; status line; panel | hash-chained, verifiable `efficiency/1` + decision receipts |
|
||
|
||
## Conformance profiles
|
||
|
||
`claude-code` (reference) · `hooks-family` (Cursor / Windsurf / Antigravity) · `acp`
|
||
(Zed / JetBrains / Neovim) · `opencode` · `cline` · `vscode` (Open-VSX) · `meter-only`
|
||
(Continue, any OTel host). See [`SPEC.md §6`](SPEC.md).
|
||
|
||
## The honest limit
|
||
|
||
A host-side adapter alone cannot meter the host agent's own tokens; a complete energy
|
||
figure requires the Meter seam (proxy or OTel). An adapter that claims whole-session
|
||
energy without a bound meter is non-conformant ([`SPEC.md §7`](SPEC.md)).
|
||
|
||
## What's here
|
||
|
||
```
|
||
joulehook/
|
||
├── SPEC.md — the normative standard (§1–§9)
|
||
├── README.md — this file
|
||
├── joulehook-rs/ — reference implementation
|
||
│ └── crates/
|
||
│ ├── joulehook-hook — ✅ the PreToolUse gate CLI for the hook family
|
||
│ │ (Claude Code / Cursor / Windsurf / Antigravity via --host;
|
||
│ │ wraps jcp-bridge::LocalToolGate for the JCP check + seal)
|
||
│ │ + joulehook-statusline — ✅ the in-editor joule meter
|
||
│ ├── joulehook-mcp — ✅ the receipt-surface MCP server (sealed decisions →
|
||
│ │ verified MCP resources, any MCP-speaking editor)
|
||
│ ├── joulehook-meter — ✅ the meter-seam binding: inject a grant's budget as
|
||
│ │ the Mesh joule ceiling (enforce) + bridge Mesh's
|
||
│ │ usage.energy into an efficiency/1 receipt
|
||
│ └── joulehook-proxy — ✅ the deployable meter: an OpenAI-shaped base_url
|
||
│ proxy that caps + seals every model call
|
||
└── conformance/v1/ — ✅ reproducible vectors: per-host decision encodings
|
||
(decisions.json) + a byte-deterministic sealed deny receipt
|
||
(deny-receipt.hex + receipt.json, verified-decode)
|
||
```
|
||
|
||
JouleHook is one of the [Transaction Science open standards](../README.md).
|
||
Transaction Science is the steward, not the proprietor.
|