open-standards/jouleclaw/jouleclaw-rs/crates/jouleclaw-cone/tests/conformance.rs
Transaction Science 0055f59b3c jouleclaw: conformance vectors for the triangle's four primitives
JCR-1 ships ten conformance vectors with three independent verifier
implementations byte-equal. The triangle primitives (conservation,
cone, oracle, elicitor) had no equivalent — implementers in other
languages had to read the Rust source to know what "compliant" means.

This commit closes that gap. Each primitive gets:

  conformance/vectors.json — the canonical fixture set
  conformance/README.md    — the conformance contract spec
  tests/conformance.rs     — Rust verifier wired into cargo test

Vectors:

  conservation/1  — 5 vectors: conforming, below_spec, hallucination,
                    missing_delta, plus a multi-finding case
  cone/1          — 6 vectors: every datum_default band entry,
                    jouleclaw_cascade_default L0, escalate-lut-to-
                    formulaic, escalate-from-apex (refused)
  oracle/1        — 5 vectors: always_pass, always_fail, composite
                    all-pass with chain dedup, composite short-
                    circuit on first fail, empty-composite trivial-
                    pass
  elicitor/1      — 5 vectors: empty-walker-done, single-required-
                    ask, two-required-fill-first-ask-second, fully-
                    filled-done, optional-slot-never-asked

Each verifier asserts byte-equality between the reference impl's
serde_json output and the vector's `expected_*`. Adding a vector
extends the conformance contract for every implementer.

The Python and Go reference verifiers (the JCR-1 multi-language
pattern) are roadmap, not part of this commit — the vectors are
language-neutral so other-language verifiers can be added without
changing the contract.

4 new tests, one per primitive — all green.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-06-04 03:32:06 -04:00

74 lines
2.9 KiB
Rust

//! Cone conformance — the reference [`BandDispatch`] must select the
//! `entry_tier` listed in `conformance/vectors.json` for every
//! (band, novelty) pair, and must succeed / refuse escalation
//! identically. Any independent implementation is conformant iff it
//! matches every vector.
use jouleclaw_cone::{BandDispatch, ConeCoord, ConeError, NoveltyBand};
use serde_json::Value;
const VECTORS: &str = include_str!("../conformance/vectors.json");
fn build_band(name: &str) -> NoveltyBand {
match name {
"datum_default" => NoveltyBand::datum_default(),
"jouleclaw_cascade_default" => NoveltyBand::jouleclaw_cascade_default(),
other => panic!("unknown band preset: {other}"),
}
}
fn check_vector(v: &Value) {
let n = v["n"].as_i64().expect("n");
let desc = v["description"].as_str().expect("description");
let input = &v["input"];
let expected = &v["expected"];
let band_name = input["band"].as_str().expect("band name");
let dispatch = BandDispatch::new(build_band(band_name)).expect("valid band");
let coord = ConeCoord::new(
input["complexity"].as_f64().expect("complexity") as f32,
input["novelty"].as_f64().expect("novelty") as f32,
);
let entry = dispatch.entry_tier(coord);
let expected_entry = expected["entry_tier"].as_str().expect("entry_tier");
assert_eq!(
entry, expected_entry,
"vector {n} ({desc}): entry_tier mismatch — got {entry}, expected {expected_entry}"
);
if let Some(from) = input.get("escalate_from").and_then(|v| v.as_str()) {
match dispatch.escalate(from) {
Ok(to) => {
let exp_to = expected["escalate_to"].as_str().unwrap_or("");
assert_eq!(
to, exp_to,
"vector {n} ({desc}): escalate({from}) → {to}, expected {exp_to}"
);
}
Err(ConeError::AtApex(_)) => {
let exp_err = expected["escalate_error"].as_str().unwrap_or("");
assert_eq!(
exp_err, "at_apex",
"vector {n} ({desc}): escalate returned AtApex but vector expected {exp_err:?}"
);
assert!(
expected["escalate_to"].is_null(),
"vector {n}: escalate_to must be null when at_apex"
);
}
Err(other) => panic!("vector {n} ({desc}): unexpected cone error: {other}"),
}
}
}
#[test]
fn every_cone_vector_matches_the_reference_dispatcher() {
let suite: Value = serde_json::from_str(VECTORS).expect("vectors.json parses");
let count = suite["vector_count"].as_u64().expect("vector_count") as usize;
let vectors = suite["vectors"].as_array().expect("vectors array");
assert_eq!(vectors.len(), count, "vector_count mismatch");
for v in vectors {
check_vector(v);
}
}