Skip to main content

agnix_rules/
lib.rs

1//! Validation rules for agnix - agent configuration linter.
2//!
3//! This crate provides the rule definitions used by agnix to validate
4//! agent configurations including Skills, Hooks, MCP servers, Memory files,
5//! and Plugins.
6//!
7//! # Usage
8//!
9//! ```
10//! use agnix_rules::RULES_DATA;
11//!
12//! // RULES_DATA is a static array of (rule_id, rule_name) tuples
13//! for (id, name) in RULES_DATA {
14//!     println!("{}: {}", id, name);
15//! }
16//! ```
17//!
18//! # Rule Categories
19//!
20//! - **AS-xxx**: Agent Skills
21//! - **CC-xxx**: Claude Code (Hooks, Skills, Memory, etc.)
22//! - **MCP-xxx**: Model Context Protocol
23//! - **COP-xxx**: GitHub Copilot
24//! - **CUR-xxx**: Cursor
25//! - **XML-xxx**: XML/XSLT based configs
26//! - **XP-xxx**: Cross-platform rules
27
28// Include the auto-generated rules data from build.rs
29include!(concat!(env!("OUT_DIR"), "/rules_data.rs"));
30
31/// Returns the total number of rules.
32pub fn rule_count() -> usize {
33    RULES_DATA.len()
34}
35
36/// Looks up a rule by ID, returning the name if found.
37pub fn get_rule_name(id: &str) -> Option<&'static str> {
38    RULES_DATA
39        .iter()
40        .find(|(rule_id, _)| *rule_id == id)
41        .map(|(_, name)| *name)
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn test_rules_data_not_empty() {
50        assert!(!RULES_DATA.is_empty(), "RULES_DATA should not be empty");
51    }
52
53    #[test]
54    fn test_rule_count() {
55        assert_eq!(rule_count(), RULES_DATA.len());
56    }
57
58    #[test]
59    fn test_get_rule_name_exists() {
60        // AS-001 should always exist
61        let name = get_rule_name("AS-001");
62        assert!(name.is_some(), "AS-001 should exist");
63    }
64
65    #[test]
66    fn test_get_rule_name_not_exists() {
67        let name = get_rule_name("NONEXISTENT-999");
68        assert!(name.is_none(), "Nonexistent rule should return None");
69    }
70
71    #[test]
72    fn test_no_duplicate_ids() {
73        let mut ids: Vec<&str> = RULES_DATA.iter().map(|(id, _)| *id).collect();
74        let original_len = ids.len();
75        ids.sort();
76        ids.dedup();
77        assert_eq!(ids.len(), original_len, "Should have no duplicate rule IDs");
78    }
79}