open-standards/jouleclaw/jouleclaw-rs/crates/jouleclaw-jcr1/conformance/verify_ui_output.py
Transaction Science cfaa983621 jouleclaw: wave-52 — Python verifiers for the six new schemas
Cross-language conformance, matching JCR-1 v1's three-impl pattern.
Each new schema landed since wave-46 had a Rust verifier wired
into cargo test; this drop adds an independent Python verifier
per schema so non-Rust implementers reproduce the PASS results.

Six verifiers shipped (one per schema):

  jouleclaw-jcr1/conformance/
    verify_verified_code.py       (verified-code/1)
    verify_stream_window.py       (stream-window/1)
    verify_ui_output.py           (ui-output/1)
    verify_coding_window.py       (coding-window/1)

  jouleclaw-cross-binding/conformance/
    verify_cross_binding.py             (cross-binding/1)
    verify_streaming_trace_binding.py   (streaming-trace-binding/1)

Each is standalone — no JouleClaw imports, just stdlib + pypi
blake3. Reads its *-vectors.json, recanonicalises every payload
(sorted-key JSON, UTF-8, no whitespace, no float coercion),
BLAKE3-hashes the canonical bytes, asserts byte-equal against
the embedded content_hash / receipt_hash.

A conformant alternate implementation in any language MUST
reproduce these PASS results. Go verifiers (the third leg) are
roadmap — same template, just longer per schema; the README in
jouleclaw-cross-binding/conformance/ records the matrix.

All six verifiers PASS against their respective vectors.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-06-05 10:48:08 -04:00

76 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""
verify_ui_output.py — independent Python verifier for the
JCR-1 `schema_id` schema.
Reads `ui-output-vectors.json`, recanonicalises each receipt under
sorted-key JSON (UTF-8, no whitespace), BLAKE3-hashes the bytes,
and asserts the hex matches the vector's embedded `receipt_hash`.
Deps: blake3 (`pip install blake3`).
Usage:
python3 verify_ui_output.py [ui-output-vectors.json]
"""
import sys, json
from pathlib import Path
try:
import blake3
except ImportError:
sys.stderr.write(
"this verifier requires the blake3 module — `pip install blake3`\n"
)
sys.exit(2)
def canonicalise(value):
if isinstance(value, dict):
return {k: canonicalise(value[k]) for k in sorted(value)}
if isinstance(value, list):
return [canonicalise(v) for v in value]
return value
def canonical_bytes(value) -> bytes:
return json.dumps(
canonicalise(value),
separators=(",", ":"),
ensure_ascii=False,
).encode("utf-8")
def main():
path = (
Path(sys.argv[1])
if len(sys.argv) > 1
else Path(__file__).parent / "ui-output-vectors.json"
)
suite = json.loads(path.read_text())
expected_spec = "JCR-1 ui-output v1"
if suite.get("spec") != expected_spec:
sys.stderr.write(f"spec mismatch: got {suite.get('spec')!r}, want {expected_spec!r}\n")
sys.exit(1)
failed = 0
for vec in suite["vectors"]:
n = vec["n"]
desc = vec["description"]
expected_hash = vec["receipt_hash"]
payload = vec["receipt"]
canon = canonical_bytes(payload)
computed = blake3.blake3(canon).hexdigest()
if computed == expected_hash:
print(f" ✓ vector {n}: {desc}")
else:
print(f" ✗ vector {n}: {desc}")
print(f" expected: {expected_hash}")
print(f" computed: {computed}")
failed += 1
if failed:
sys.stderr.write(f"\n{failed} vector(s) failed verification\n")
sys.exit(1)
print(f"\nverify_ui_output.py — all {len(suite['vectors'])} vectors PASS")
if __name__ == "__main__":
main()