open-standards/jouleclaw/jouleclaw-rs/crates/jouleclaw-hydra-client/conformance/README.md
Transaction Science 0c14dc33c8 jouleclaw-hydra-client: a transport's joule figure carries its grade; ungraded is an estimate
The client sealed any transport-supplied joules figure as HwShunt, in
all three clients (Rust lib.rs, Go jclaw_hydra.go, Python client.py),
though TransportResponse.joules_uj carries no grade: a transport with an
estimate, or a figure of unknown origin, had it sealed as a hardware
reading.

TransportResponse now carries the grade of the meter that produced the
figure (Rust joules_provenance: Option<Provenance>, plus with_joules;
Go JoulesProvenance string; Python joules_provenance), and one rule,
graded_joules / GradedJoules, decides what is sealed in every client:
the figure at its stated grade; an ungraded figure (or, in Go/Python, a
grade that is not HwShunt/ModelBased/Estimator) as Estimator; no figure
as a zero Estimator. The conformance vectors carry no touch and are
unchanged; Go and Python still verify 9/9.

Tests (each fails before on HwShunt): Rust an_ungraded_transport_figure_
is_sealed_as_an_estimate, a_graded_transport_figure_keeps_its_grade;
Go TestUngradedJoulesAreSealedAsEstimates, TestGradedJoulesKeepTheirGrade;
Python tests/test_energy_grade.py (pytest).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 18:03:10 -04:00

61 lines
2.6 KiB
Markdown

# JouleClaw Hydra-Client conformance
Cross-language conformance for the third-generation Hydra client.
Rust + Python + Go reference implementations all produce
byte-for-byte identical BLAKE3 input/output hashes against the
vectors below.
## Files
| File | What |
|------|------|
| [`call-reports.json`](call-reports.json) | 5 dispatch vectors + 4 SHACL-validation vectors. Each pairs an input (Hydra API doc + operation name + payload) with the canonical expected CallReport (tool_id, status, input_hash, output_hash, status_matches_contract, body). |
## How the three implementations agree
Every implementation:
1. Parses the Hydra `ApiDocumentation` from the JSON-LD in the vector.
2. Looks up the operation by `jc_tool_id`.
3. Validates the input against the embedded SHACL shapes for `https://example.com/Tool#AppendInput` (open-world default elsewhere).
4. Dispatches via an echo-mode `MockTransport` — the same canonical form: `{ "echo": <input> }`, status 200, no measured energy.
5. Computes BLAKE3 over lexically-sorted, no-whitespace canonical JSON of input and output.
6. Returns a `CallReport` with the hex BLAKE3 digests.
The three implementations live at:
| Language | Path |
|----------|------|
| Rust | [`crates/jouleclaw-hydra-client/src/lib.rs`](../src/lib.rs) |
| Python | [`crates/jouleclaw-hydra-client/clients/python/jclaw_hydra/`](../clients/python/jclaw_hydra/) |
| Go | [`crates/jouleclaw-hydra-client/clients/go/`](../clients/go/) |
## Running
```bash
# Rust (regenerator; also the oracle)
cargo run -p jouleclaw-hydra-client --example gen_conformance_vectors
# Python (requires `pip install blake3`; the energy-grade tests also pytest)
python3 crates/jouleclaw-hydra-client/clients/python/tests/test_conformance.py
python3 -m pytest crates/jouleclaw-hydra-client/clients/python/tests/
# Go (uses lukechampine.com/blake3 via go.mod)
cd crates/jouleclaw-hydra-client/clients/go && go test -v ./...
```
All three MUST print `PASS` for every vector. A mismatch on ANY
implementation is a divergence to fix on that side — the canonical
oracle is the Rust producer (which is what generates the vectors).
## Scope
- **In:** the cross-language Hydra-client surface — Hydra parse,
SHACL validate, dispatch via Transport, BLAKE3 hash over
canonical JSON, CallReport emission.
- **Out:** the wire form of cascade receipts and policy receipts
is covered by separate conformance suites at
`crates/jouleclaw-jcr1/conformance/` and
`crates/jouleclaw-policy-receipt/conformance/`. The Hydra client
produces `ToolTouch`-shaped touches that drop into those streams;
it does not itself produce signed receipts.