agent_rules_tool/
schema.rs1use crate::error::Error;
4use crate::spec::{EMBEDDED_SCHEMA, SCHEMA_URL};
5use crate::{Severity, Violation};
6use jsonschema::Validator;
7use serde_json::Value;
8use std::sync::LazyLock;
9
10static VALIDATOR: LazyLock<Validator> = LazyLock::new(|| {
11 let schema: Value =
12 serde_json::from_str(EMBEDDED_SCHEMA).expect("embedded schema is valid JSON");
13 Validator::new(&schema).expect("embedded schema compiles")
14});
15
16pub fn validate_frontmatter(frontmatter: &Value) -> Result<Vec<Violation>, Error> {
20 if matches!(frontmatter, Value::Null) {
21 return Ok(Vec::new());
22 }
23 if let Value::Object(map) = frontmatter
24 && map.is_empty()
25 {
26 return Ok(Vec::new());
27 }
28
29 let violations: Vec<Violation> = VALIDATOR
30 .iter_errors(frontmatter)
31 .map(|err| {
32 let instance_path = err.instance_path().to_string();
33 let field = if instance_path.is_empty() {
34 "frontmatter".to_string()
35 } else {
36 instance_path.trim_start_matches('/').to_string()
37 };
38 Violation {
39 severity: Severity::Error,
40 field,
41 message: err.to_string(),
42 spec_ref: SCHEMA_URL,
43 }
44 })
45 .collect();
46 Ok(violations)
47}