ggen_core/codegen/
swarm_executor_bridge.rs

1use crate::codegen::{SwarmCoordinator, SwarmSummary};
2use crate::manifest::{GenerationRule, GgenManifest};
3use ggen_utils::error::Result;
4
5pub struct SwarmExecutorBridge {
6    coordinator: SwarmCoordinator,
7    high_risk_rules: Vec<String>,
8}
9
10impl SwarmExecutorBridge {
11    pub fn new(agent_count: usize, _manifest: GgenManifest, high_risk_rules: Vec<String>) -> Self {
12        Self {
13            coordinator: SwarmCoordinator::new(agent_count),
14            high_risk_rules,
15        }
16    }
17
18    pub async fn prepare_execution(&self, rules_to_run: Vec<GenerationRule>) -> Result<()> {
19        self.coordinator.enqueue_rules(rules_to_run).await?;
20        self.coordinator.distribute_work().await?;
21        Ok(())
22    }
23
24    pub async fn get_execution_summary(&self) -> Result<SwarmSummary> {
25        self.coordinator.get_swarm_summary().await
26    }
27
28    pub async fn record_rule_completion(&self, rule_name: &str) -> Result<()> {
29        self.coordinator.record_completion(rule_name).await
30    }
31
32    pub async fn record_rule_failure(&self, rule_name: &str) -> Result<()> {
33        self.coordinator.record_failure(rule_name).await
34    }
35
36    pub fn get_agent_prioritization(&self, rule_name: &str) -> u8 {
37        if self.high_risk_rules.contains(&rule_name.to_string()) {
38            10
39        } else {
40            1
41        }
42    }
43
44    pub fn estimate_concurrent_speedup(&self, total_rules: usize) -> f64 {
45        if total_rules == 0 {
46            return 1.0;
47        }
48
49        let agent_count = 4;
50        let parallelizable_ratio = 0.7;
51
52        1.0 / (1.0 - parallelizable_ratio + (parallelizable_ratio / agent_count as f64))
53    }
54}
55
56pub struct ExecutionStrategy {
57    pub use_swarm: bool,
58    pub agent_count: usize,
59    pub prioritize_high_risk: bool,
60    pub estimated_speedup: f64,
61}
62
63pub fn determine_execution_strategy(
64    rule_count: usize, high_risk_count: usize, manifest_changed: bool,
65) -> ExecutionStrategy {
66    let use_swarm = rule_count > 10 && !manifest_changed;
67    let agent_count = if use_swarm { 4 } else { 1 };
68
69    let mut estimated_speedup = 1.0;
70    if use_swarm {
71        estimated_speedup = 1.0 / (1.0 - 0.7 + (0.7 / 4.0));
72    }
73
74    ExecutionStrategy {
75        use_swarm,
76        agent_count,
77        prioritize_high_risk: high_risk_count > 0,
78        estimated_speedup,
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85    use std::collections::BTreeMap;
86
87    fn create_test_manifest() -> GgenManifest {
88        GgenManifest {
89            project: crate::manifest::ProjectConfig {
90                name: "test".to_string(),
91                version: "1.0.0".to_string(),
92                description: None,
93            },
94            ontology: crate::manifest::OntologyConfig {
95                source: "ontology.ttl".into(),
96                imports: vec![],
97                base_iri: None,
98                prefixes: BTreeMap::new(),
99            },
100            inference: crate::manifest::InferenceConfig::default(),
101            generation: crate::manifest::GenerationConfig {
102                rules: vec![],
103                output_dir: "output".into(),
104                require_audit_trail: false,
105                determinism_salt: None,
106                max_sparql_timeout_ms: 5000,
107            },
108            validation: crate::manifest::ValidationConfig::default(),
109        }
110    }
111
112    #[test]
113    fn test_execution_strategy_small_batch() {
114        let strategy = determine_execution_strategy(3, 0, false);
115        assert!(!strategy.use_swarm);
116        assert_eq!(strategy.agent_count, 1);
117    }
118
119    #[test]
120    fn test_execution_strategy_large_batch() {
121        let strategy = determine_execution_strategy(20, 2, false);
122        assert!(strategy.use_swarm);
123        assert_eq!(strategy.agent_count, 4);
124        assert!(strategy.estimated_speedup > 1.0);
125    }
126
127    #[test]
128    fn test_execution_strategy_manifest_changed() {
129        let strategy = determine_execution_strategy(50, 5, true);
130        assert!(!strategy.use_swarm);
131    }
132
133    #[test]
134    fn test_prioritization_high_risk() {
135        let manifest = create_test_manifest();
136        let bridge = SwarmExecutorBridge::new(4, manifest, vec!["high-risk-rule".to_string()]);
137
138        let priority = bridge.get_agent_prioritization("high-risk-rule");
139        assert_eq!(priority, 10);
140    }
141
142    #[test]
143    fn test_prioritization_normal() {
144        let manifest = create_test_manifest();
145        let bridge = SwarmExecutorBridge::new(4, manifest, vec![]);
146
147        let priority = bridge.get_agent_prioritization("normal-rule");
148        assert_eq!(priority, 1);
149    }
150
151    #[test]
152    fn test_speedup_estimation() {
153        let manifest = create_test_manifest();
154        let bridge = SwarmExecutorBridge::new(4, manifest, vec![]);
155
156        let speedup = bridge.estimate_concurrent_speedup(20);
157        assert!(speedup > 1.0);
158        assert!(speedup < 4.0);
159    }
160}