pub fn diagnose(events_jsonl: &str, min_occurrences: u32) -> Result<String, String> {
let report = car_eventlog::harness_adapt::diagnose_from_jsonl(
events_jsonl,
min_occurrences.max(1) as usize,
);
serde_json::to_string(&report).map_err(|e| e.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::Value;
#[test]
fn diagnoses_recurring_rejection() {
let jsonl = [
r#"{"kind":"action_rejected","action_id":"a1","data":{},"timestamp":"2026-06-28T00:00:00Z"}"#,
r#"{"kind":"action_rejected","action_id":"a1","data":{},"timestamp":"2026-06-28T00:00:01Z"}"#,
]
.join("\n");
let out = diagnose(&jsonl, 2).unwrap();
let v: Value = serde_json::from_str(&out).unwrap();
assert_eq!(v["interventions"][0]["layer"], "environment_contract");
assert_eq!(v["interventions"][0]["evidence_count"], 2);
}
#[test]
fn one_off_below_threshold_is_empty() {
let jsonl = r#"{"kind":"action_rejected","action_id":"a1","data":{},"timestamp":"2026-06-28T00:00:00Z"}"#;
let out = diagnose(jsonl, 2).unwrap();
let v: Value = serde_json::from_str(&out).unwrap();
assert_eq!(v["interventions"].as_array().unwrap().len(), 0);
}
}