//! 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); } }