1use crate::analytics_engine::AnalyticsEngine;
3use crate::conflict_resolver::ConflictResolver;
4use crate::decision_logger::DecisionLogger;
5use crate::error::{LearningError, Result};
6use crate::models::{Decision, DecisionContext, LearnedPattern, LearningConfig, Rule, RuleScope};
7use crate::pattern_capturer::PatternCapturer;
8use crate::pattern_validator::PatternValidator;
9use crate::rule_promoter::RulePromoter;
10use crate::rule_storage::RuleStorage;
11use crate::rule_validator::RuleValidator;
12use crate::scope_config::{ScopeConfiguration, ScopeConfigurationLoader, ScopeFilter};
13use std::collections::HashMap;
14use std::path::PathBuf;
15use std::sync::Arc;
16use tokio::sync::RwLock;
17
18pub struct LearningManager {
20 config: Arc<RwLock<LearningConfig>>,
22 scope_config: Arc<RwLock<ScopeConfiguration>>,
24 decision_logger: Arc<DecisionLogger>,
26 rule_storage: Arc<RuleStorage>,
28 rule_validator: Arc<RuleValidator>,
30 pattern_capturer: Arc<PatternCapturer>,
32 pattern_validator: Arc<PatternValidator>,
34 rule_promoter: Arc<RwLock<RulePromoter>>,
36 patterns: Arc<RwLock<HashMap<String, LearnedPattern>>>,
38 analytics_engine: Arc<AnalyticsEngine>,
40}
41
42impl LearningManager {
43 pub fn new(scope: RuleScope) -> Self {
45 let config = LearningConfig::new(scope);
46 let scope_config = ScopeConfiguration::new(scope);
47 Self {
48 config: Arc::new(RwLock::new(config.clone())),
49 scope_config: Arc::new(RwLock::new(scope_config)),
50 decision_logger: Arc::new(DecisionLogger::new()),
51 rule_storage: Arc::new(RuleStorage::new(scope)),
52 rule_validator: Arc::new(RuleValidator::new()),
53 pattern_capturer: Arc::new(PatternCapturer::new()),
54 pattern_validator: Arc::new(PatternValidator::new()),
55 rule_promoter: Arc::new(RwLock::new(RulePromoter::new())),
56 patterns: Arc::new(RwLock::new(HashMap::new())),
57 analytics_engine: Arc::new(AnalyticsEngine::new()),
58 }
59 }
60
61 pub fn with_config(config: LearningConfig) -> Result<Self> {
63 config.validate()?;
64 let scope = config.scope;
65 let scope_config = ScopeConfiguration::new(scope);
66 Ok(Self {
67 config: Arc::new(RwLock::new(config)),
68 scope_config: Arc::new(RwLock::new(scope_config)),
69 decision_logger: Arc::new(DecisionLogger::new()),
70 rule_storage: Arc::new(RuleStorage::new(scope)),
71 rule_validator: Arc::new(RuleValidator::new()),
72 pattern_capturer: Arc::new(PatternCapturer::new()),
73 pattern_validator: Arc::new(PatternValidator::new()),
74 rule_promoter: Arc::new(RwLock::new(RulePromoter::new())),
75 patterns: Arc::new(RwLock::new(HashMap::new())),
76 analytics_engine: Arc::new(AnalyticsEngine::new()),
77 })
78 }
79
80 pub async fn get_config(&self) -> LearningConfig {
82 self.config.read().await.clone()
83 }
84
85 pub async fn set_config(&self, config: LearningConfig) -> Result<()> {
87 config.validate()?;
88 *self.config.write().await = config;
89 Ok(())
90 }
91
92 pub async fn get_scope(&self) -> RuleScope {
94 self.config.read().await.scope
95 }
96
97 pub async fn is_enabled(&self) -> bool {
99 self.config.read().await.enabled
100 }
101
102 pub async fn set_enabled(&self, enabled: bool) {
104 let mut config = self.config.write().await;
105 config.enabled = enabled;
106 }
107
108 pub async fn load_scope_configuration(&self) -> Result<ScopeConfiguration> {
114 let scope = self.get_scope().await;
115 let config = ScopeConfigurationLoader::load_configuration(scope).await?;
116 *self.scope_config.write().await = config.clone();
117 Ok(config)
118 }
119
120 pub async fn get_scope_configuration(&self) -> ScopeConfiguration {
122 self.scope_config.read().await.clone()
123 }
124
125 pub async fn set_scope_configuration(&self, config: ScopeConfiguration) -> Result<()> {
127 config.validate()?;
128 *self.scope_config.write().await = config;
129 Ok(())
130 }
131
132 pub async fn is_scope_learning_enabled(&self) -> bool {
134 self.scope_config.read().await.learning_enabled
135 }
136
137 pub async fn set_scope_learning_enabled(&self, enabled: bool) {
139 let mut config = self.scope_config.write().await;
140 config.learning_enabled = enabled;
141 }
142
143 pub async fn is_project_only_learning(&self) -> bool {
145 self.scope_config.read().await.project_only
146 }
147
148 pub async fn set_project_only_learning(&self, project_only: bool) {
150 let mut config = self.scope_config.write().await;
151 config.project_only = project_only;
152 }
153
154 pub async fn is_approval_required(&self) -> bool {
156 self.scope_config.read().await.approval_required
157 }
158
159 pub async fn set_approval_required(&self, required: bool) {
161 let mut config = self.scope_config.write().await;
162 config.approval_required = required;
163 }
164
165 pub async fn get_max_rules(&self) -> usize {
167 self.scope_config.read().await.max_rules
168 }
169
170 pub async fn set_max_rules(&self, max_rules: usize) -> Result<()> {
172 if max_rules == 0 {
173 return Err(LearningError::ConfigurationError(
174 "max_rules must be greater than 0".to_string(),
175 ));
176 }
177 let mut config = self.scope_config.write().await;
178 config.max_rules = max_rules;
179 Ok(())
180 }
181
182 pub async fn get_retention_days(&self) -> u32 {
184 self.scope_config.read().await.retention_days
185 }
186
187 pub async fn set_retention_days(&self, retention_days: u32) -> Result<()> {
189 if retention_days == 0 {
190 return Err(LearningError::ConfigurationError(
191 "retention_days must be greater than 0".to_string(),
192 ));
193 }
194 let mut config = self.scope_config.write().await;
195 config.retention_days = retention_days;
196 Ok(())
197 }
198
199 pub async fn save_scope_configuration_to_project(&self) -> Result<()> {
201 let config = self.scope_config.read().await.clone();
202 ScopeConfigurationLoader::save_project_config(&config).await
203 }
204
205 pub async fn save_scope_configuration_to_user(&self) -> Result<()> {
207 let config = self.scope_config.read().await.clone();
208 ScopeConfigurationLoader::save_user_config(&config).await
209 }
210
211 pub async fn get_rules_for_scope(&self) -> Result<Vec<Rule>> {
213 let scope = self.get_scope().await;
214 let all_rules = self.get_rules().await?;
215 Ok(ScopeFilter::get_rules_with_precedence(&all_rules, scope))
216 }
217
218 pub async fn get_rules_by_scope(&self, scope: RuleScope) -> Result<Vec<Rule>> {
220 let all_rules = self.get_rules().await?;
221 Ok(ScopeFilter::filter_by_scope(&all_rules, scope))
222 }
223
224 pub async fn check_scope_interference(
226 &self,
227 scope1: RuleScope,
228 scope2: RuleScope,
229 ) -> Result<bool> {
230 let all_rules = self.get_rules().await?;
231 let rules1 = ScopeFilter::filter_by_scope(&all_rules, scope1);
232 let rules2 = ScopeFilter::filter_by_scope(&all_rules, scope2);
233 Ok(ScopeFilter::check_scope_interference(&rules1, &rules2))
234 }
235
236 pub async fn capture_decision(&self, decision: Decision) -> Result<String> {
238 if !self.is_enabled().await {
239 return Err(LearningError::DecisionCaptureFailed(
240 "Learning is disabled".to_string(),
241 ));
242 }
243
244 self.decision_logger.log_decision(decision).await
245 }
246
247 pub async fn get_decisions(&self) -> Vec<Decision> {
249 self.decision_logger.get_history().await
250 }
251
252 pub async fn get_decisions_by_type(&self, decision_type: &str) -> Vec<Decision> {
254 self.decision_logger.get_history_by_type(decision_type).await
255 }
256
257 pub async fn get_decisions_by_context(&self, context: &DecisionContext) -> Vec<Decision> {
259 self.decision_logger.get_history_by_context(context).await
260 }
261
262 pub async fn get_decision(&self, decision_id: &str) -> Result<Decision> {
264 self.decision_logger.get_decision(decision_id).await
265 }
266
267 pub async fn replay_decisions(&self) -> Vec<Decision> {
269 self.decision_logger.replay_decisions().await
270 }
271
272 pub async fn replay_decisions_for_context(&self, context: &DecisionContext) -> Vec<Decision> {
274 self.decision_logger.replay_decisions_for_context(context).await
275 }
276
277 pub async fn decision_count(&self) -> usize {
279 self.decision_logger.decision_count().await
280 }
281
282 pub async fn clear_decisions(&self) {
284 self.decision_logger.clear().await;
285 }
286
287 pub async fn get_decision_statistics(&self) -> crate::decision_logger::DecisionStatistics {
289 self.decision_logger.get_statistics().await
290 }
291
292 pub async fn store_rule(&self, rule: Rule) -> Result<String> {
294 self.rule_validator.validate(&rule)?;
296
297 let existing_rules = self.rule_storage.list_rules().await?;
299 self.rule_validator.check_conflicts(&rule, &existing_rules)?;
300
301 self.rule_storage.store_rule(rule).await
303 }
304
305 pub async fn get_rule(&self, rule_id: &str) -> Result<Rule> {
307 self.rule_storage.get_rule(rule_id).await
308 }
309
310 pub async fn get_rules(&self) -> Result<Vec<Rule>> {
312 self.rule_storage.list_rules().await
313 }
314
315 pub async fn delete_rule(&self, rule_id: &str) -> Result<()> {
317 self.rule_storage.delete_rule(rule_id).await
318 }
319
320 pub async fn update_rule(&self, rule: Rule) -> Result<String> {
322 self.rule_validator.validate(&rule)?;
324
325 self.rule_storage.update_rule(rule).await
327 }
328
329 pub fn validate_rule(&self, rule: &Rule) -> Result<()> {
331 self.rule_validator.validate(rule)
332 }
333
334 pub fn validate_rule_with_report(&self, rule: &Rule) -> crate::rule_validator::ValidationReport {
336 self.rule_validator.validate_with_report(rule)
337 }
338
339 pub async fn check_rule_conflicts(&self, rule: &Rule) -> Result<()> {
341 let existing_rules = self.rule_storage.list_rules().await?;
342 self.rule_validator.check_conflicts(rule, &existing_rules)
343 }
344
345 pub async fn get_rules_by_pattern(&self, pattern: &str) -> Result<Vec<Rule>> {
347 self.rule_storage.get_rules_by_pattern(pattern).await
348 }
349
350 pub async fn get_rules_by_source(&self, source: crate::models::RuleSource) -> Result<Vec<Rule>> {
352 self.rule_storage.get_rules_by_source(source).await
353 }
354
355 pub async fn get_rules_by_confidence(&self, min_confidence: f32) -> Result<Vec<Rule>> {
357 self.rule_storage.get_rules_by_confidence(min_confidence).await
358 }
359
360 pub async fn get_rules_by_usage(&self) -> Result<Vec<Rule>> {
362 self.rule_storage.get_rules_by_usage().await
363 }
364
365 pub async fn get_rules_by_usage_count(&self, min_usage: u64) -> Result<Vec<Rule>> {
367 self.rule_storage.get_rules_by_usage_count(min_usage).await
368 }
369
370 pub async fn get_rules_by_success_rate(&self, min_success_rate: f32) -> Result<Vec<Rule>> {
372 self.rule_storage.get_rules_by_success_rate(min_success_rate).await
373 }
374
375 pub async fn rule_count(&self) -> Result<usize> {
377 self.rule_storage.rule_count().await
378 }
379
380 pub async fn clear_rules(&self) -> Result<()> {
382 self.rule_storage.clear_all().await
383 }
384
385 pub async fn load_rules(&self) -> Result<()> {
387 self.rule_storage.load_all().await
388 }
389
390 pub fn detect_rule_conflict(rule1: &Rule, rule2: &Rule) -> bool {
392 ConflictResolver::detect_conflict(rule1, rule2)
393 }
394
395 pub async fn find_rule_conflicts(&self) -> Result<Vec<(Rule, Rule)>> {
397 let rules = self.get_rules().await?;
398 Ok(ConflictResolver::find_conflicts(&rules))
399 }
400
401 pub async fn check_rule_conflicts_before_storage(&self, rule: &Rule) -> Result<()> {
403 let existing_rules = self.get_rules().await?;
404 ConflictResolver::check_conflicts(rule, &existing_rules)
405 }
406
407 pub async fn get_rule_by_pattern_with_precedence(&self, pattern: &str) -> Result<Option<Rule>> {
409 let rules = self.get_rules().await?;
410 Ok(ConflictResolver::get_highest_priority_rule(&rules, pattern))
411 }
412
413 pub async fn get_rules_by_pattern_with_precedence(&self, pattern: &str) -> Result<Vec<Rule>> {
415 let rules = self.get_rules().await?;
416 Ok(ConflictResolver::get_rules_by_pattern_with_precedence(&rules, pattern))
417 }
418
419 pub async fn resolve_all_conflicts(&self) -> Result<Vec<Rule>> {
421 let rules = self.get_rules().await?;
422 ConflictResolver::resolve_conflicts(&rules)
423 }
424
425 pub async fn check_cross_scope_conflicts(
427 &self,
428 project_rules: &[Rule],
429 global_rules: &[Rule],
430 ) -> Vec<(Rule, Rule)> {
431 ConflictResolver::check_cross_scope_conflicts(project_rules, global_rules)
432 }
433
434 pub fn log_conflict_resolution(selected_rule: &Rule, conflicting_rules: &[Rule]) -> String {
436 ConflictResolver::log_conflict_resolution(selected_rule, conflicting_rules)
437 }
438
439 pub async fn store_pattern(&self, pattern: LearnedPattern) -> Result<String> {
441 let pattern_id = pattern.id.clone();
442 let mut patterns = self.patterns.write().await;
443 patterns.insert(pattern_id.clone(), pattern);
444
445 Ok(pattern_id)
446 }
447
448 pub async fn get_pattern(&self, pattern_id: &str) -> Result<LearnedPattern> {
450 let patterns = self.patterns.read().await;
451 patterns
452 .get(pattern_id)
453 .cloned()
454 .ok_or_else(|| LearningError::PatternNotFound(pattern_id.to_string()))
455 }
456
457 pub async fn get_patterns(&self) -> Vec<LearnedPattern> {
459 self.patterns
460 .read()
461 .await
462 .values()
463 .cloned()
464 .collect()
465 }
466
467 pub async fn get_patterns_by_type(&self, pattern_type: &str) -> Vec<LearnedPattern> {
469 self.patterns
470 .read()
471 .await
472 .values()
473 .filter(|p| p.pattern_type == pattern_type)
474 .cloned()
475 .collect()
476 }
477
478 pub async fn delete_pattern(&self, pattern_id: &str) -> Result<()> {
480 let mut patterns = self.patterns.write().await;
481 patterns
482 .remove(pattern_id)
483 .ok_or_else(|| LearningError::PatternNotFound(pattern_id.to_string()))?;
484 Ok(())
485 }
486
487 pub fn get_scope_path(&self, scope: RuleScope) -> Result<PathBuf> {
489 match scope {
490 RuleScope::Global => {
491 let home = dirs::home_dir()
492 .ok_or_else(|| LearningError::PathResolutionFailed("Home directory not found".to_string()))?;
493 Ok(home.join(".ricecoder").join("rules"))
494 }
495 RuleScope::Project => Ok(PathBuf::from(".ricecoder/rules")),
496 RuleScope::Session => Err(LearningError::PathResolutionFailed(
497 "Session scope has no persistent path".to_string(),
498 )),
499 }
500 }
501
502 pub async fn extract_patterns(&self) -> Result<Vec<LearnedPattern>> {
504 let decisions = self.get_decisions().await;
505 let patterns = self.pattern_capturer.extract_patterns(&decisions)?;
506 Ok(patterns)
507 }
508
509 pub async fn extract_patterns_with_analysis(
511 &self,
512 ) -> Result<Vec<(LearnedPattern, crate::pattern_capturer::PatternAnalysis)>> {
513 let decisions = self.get_decisions().await;
514 let results = self.pattern_capturer.extract_patterns_with_analysis(&decisions)?;
515 Ok(results)
516 }
517
518 pub async fn validate_pattern(&self, pattern: &LearnedPattern) -> Result<f32> {
520 let decisions = self.get_decisions().await;
521 let validation_score = self.pattern_capturer.validate_pattern(pattern, &decisions)?;
522 Ok(validation_score)
523 }
524
525 pub async fn update_pattern_confidence(
527 &self,
528 pattern_id: &str,
529 validation_score: f32,
530 ) -> Result<()> {
531 let mut patterns = self.patterns.write().await;
532 if let Some(pattern) = patterns.get_mut(pattern_id) {
533 self.pattern_capturer.update_confidence(pattern, validation_score)?;
534 Ok(())
535 } else {
536 Err(LearningError::PatternNotFound(pattern_id.to_string()))
537 }
538 }
539
540 pub async fn validate_pattern_comprehensive(
542 &self,
543 pattern: &LearnedPattern,
544 ) -> Result<crate::pattern_validator::ValidationResult> {
545 let decisions = self.get_decisions().await;
546 let validation_result = self.pattern_validator.validate_pattern(pattern, &decisions)?;
547 Ok(validation_result)
548 }
549
550 pub async fn validate_patterns(
552 &self,
553 patterns: &[LearnedPattern],
554 ) -> Result<Vec<crate::pattern_validator::ValidationResult>> {
555 let decisions = self.get_decisions().await;
556 let validation_results = self.pattern_validator.validate_patterns(patterns, &decisions)?;
557 Ok(validation_results)
558 }
559
560 pub async fn get_pattern_validation_statistics(
562 &self,
563 ) -> Result<crate::pattern_validator::ValidationStatistics> {
564 let patterns: Vec<_> = self.patterns.read().await.values().cloned().collect();
565 let validation_results = self.validate_patterns(&patterns).await?;
566 let stats = self.pattern_validator.get_validation_statistics(&validation_results);
567 Ok(stats)
568 }
569
570 pub async fn validate_and_update_pattern(
572 &self,
573 pattern_id: &str,
574 ) -> Result<crate::pattern_validator::ValidationResult> {
575 let pattern = self.get_pattern(pattern_id).await?;
576 let validation_result = self.validate_pattern_comprehensive(&pattern).await?;
577
578 self.update_pattern_confidence(pattern_id, validation_result.confidence_recommendation)
580 .await?;
581
582 Ok(validation_result)
583 }
584
585 pub async fn capture_and_store_patterns(&self) -> Result<Vec<String>> {
587 let patterns = self.extract_patterns().await?;
588 let mut pattern_ids = Vec::new();
589
590 for pattern in patterns {
591 let pattern_id = pattern.id.clone();
592 self.store_pattern(pattern).await?;
593 pattern_ids.push(pattern_id);
594 }
595
596 Ok(pattern_ids)
597 }
598
599 pub async fn get_patterns_by_confidence(&self, min_confidence: f32) -> Vec<LearnedPattern> {
601 self.patterns
602 .read()
603 .await
604 .values()
605 .filter(|p| p.confidence >= min_confidence)
606 .cloned()
607 .collect()
608 }
609
610 pub async fn get_patterns_by_confidence_sorted(&self) -> Vec<LearnedPattern> {
612 let mut patterns: Vec<_> = self.patterns.read().await.values().cloned().collect();
613 patterns.sort_by(|a, b| b.confidence.partial_cmp(&a.confidence).unwrap_or(std::cmp::Ordering::Equal));
614 patterns
615 }
616
617 pub async fn get_patterns_by_occurrences(&self) -> Vec<LearnedPattern> {
619 let mut patterns: Vec<_> = self.patterns.read().await.values().cloned().collect();
620 patterns.sort_by(|a, b| b.occurrences.cmp(&a.occurrences));
621 patterns
622 }
623
624 pub async fn pattern_count(&self) -> usize {
626 self.patterns.read().await.len()
627 }
628
629 pub async fn clear_patterns(&self) {
631 self.patterns.write().await.clear();
632 }
633
634 pub async fn request_rule_promotion(&self, rule: Rule) -> Result<crate::rule_promoter::RuleReview> {
636 let global_rules = self.rule_storage.list_rules().await?;
638
639 let mut promoter = self.rule_promoter.write().await;
641 promoter.request_promotion(rule, &global_rules)
642 }
643
644 pub async fn get_pending_promotion(&self, rule_id: &str) -> Result<crate::rule_promoter::RuleReview> {
646 let promoter = self.rule_promoter.read().await;
647 promoter.get_pending_promotion(rule_id)
648 }
649
650 pub async fn get_pending_promotions(&self) -> Vec<crate::rule_promoter::RuleReview> {
652 let promoter = self.rule_promoter.read().await;
653 promoter.get_pending_promotions()
654 }
655
656 pub async fn pending_promotion_count(&self) -> usize {
658 let promoter = self.rule_promoter.read().await;
659 promoter.pending_promotion_count()
660 }
661
662 pub async fn approve_promotion(
664 &self,
665 rule_id: &str,
666 reason: Option<String>,
667 ) -> Result<Rule> {
668 let mut promoter = self.rule_promoter.write().await;
670 let promoted_rule = promoter.approve_promotion(rule_id, reason)?;
671
672 promoter.validate_promotion(&promoted_rule, &self.rule_storage.list_rules().await?)?;
674
675 if promoted_rule.scope == RuleScope::Global {
678 let global_storage = RuleStorage::new(RuleScope::Global);
679 global_storage.store_rule(promoted_rule.clone()).await?;
680 } else {
681 self.rule_storage.store_rule(promoted_rule.clone()).await?;
682 }
683
684 Ok(promoted_rule)
685 }
686
687 pub async fn reject_promotion(
689 &self,
690 rule_id: &str,
691 reason: Option<String>,
692 ) -> Result<()> {
693 let mut promoter = self.rule_promoter.write().await;
694 promoter.reject_promotion(rule_id, reason)
695 }
696
697 pub async fn get_promotion_history(&self) -> Vec<crate::rule_promoter::PromotionHistoryEntry> {
699 let promoter = self.rule_promoter.read().await;
700 promoter.get_promotion_history()
701 }
702
703 pub async fn get_promotion_history_for_rule(
705 &self,
706 rule_id: &str,
707 ) -> Vec<crate::rule_promoter::PromotionHistoryEntry> {
708 let promoter = self.rule_promoter.read().await;
709 promoter.get_promotion_history_for_rule(rule_id)
710 }
711
712 pub async fn get_approved_promotions(&self) -> Vec<crate::rule_promoter::PromotionHistoryEntry> {
714 let promoter = self.rule_promoter.read().await;
715 promoter.get_approved_promotions()
716 }
717
718 pub async fn get_rejected_promotions(&self) -> Vec<crate::rule_promoter::PromotionHistoryEntry> {
720 let promoter = self.rule_promoter.read().await;
721 promoter.get_rejected_promotions()
722 }
723
724 pub async fn clear_pending_promotions(&self) {
726 let mut promoter = self.rule_promoter.write().await;
727 promoter.clear_pending_promotions();
728 }
729
730 pub async fn clear_promotion_history(&self) {
732 let mut promoter = self.rule_promoter.write().await;
733 promoter.clear_promotion_history();
734 }
735
736 pub async fn apply_rule_to_context(
742 &self,
743 rule: &Rule,
744 context: &crate::rule_application::GenerationContext,
745 ) -> crate::rule_application::RuleApplicationResult {
746 crate::rule_application::RuleApplicationEngine::apply_rule(rule, context)
747 }
748
749 pub async fn apply_rules_to_context(
751 &self,
752 rules: &[Rule],
753 context: &crate::rule_application::GenerationContext,
754 ) -> Vec<crate::rule_application::RuleApplicationResult> {
755 crate::rule_application::RuleApplicationEngine::apply_rules(rules, context)
756 }
757
758 pub async fn apply_rules_with_precedence(
760 &self,
761 rules: &[Rule],
762 context: &crate::rule_application::GenerationContext,
763 ) -> Option<crate::rule_application::RuleApplicationResult> {
764 crate::rule_application::RuleApplicationEngine::apply_rules_with_precedence(rules, context)
765 }
766
767 pub async fn chain_rules(
769 &self,
770 rules: &[Rule],
771 context: &crate::rule_application::GenerationContext,
772 ) -> Result<Vec<crate::rule_application::RuleApplicationResult>> {
773 crate::rule_application::RuleApplicationEngine::chain_rules(rules, context)
774 }
775
776 pub async fn compose_rules(
778 &self,
779 rules: &[Rule],
780 context: &crate::rule_application::GenerationContext,
781 ) -> Result<Option<String>> {
782 crate::rule_application::RuleApplicationEngine::compose_rules(rules, context)
783 }
784
785 pub async fn validate_rule_application(
787 &self,
788 rule: &Rule,
789 context: &crate::rule_application::GenerationContext,
790 ) -> Result<()> {
791 crate::rule_application::RuleApplicationEngine::validate_rule_application(rule, context)
792 }
793
794 pub async fn get_matching_rules(
796 &self,
797 context: &crate::rule_application::GenerationContext,
798 ) -> Result<Vec<Rule>> {
799 let rules = self.get_rules().await?;
800 Ok(crate::rule_application::RuleApplicationEngine::get_matching_rules(&rules, context))
801 }
802
803 pub async fn get_matching_rules_sorted(
805 &self,
806 context: &crate::rule_application::GenerationContext,
807 ) -> Result<Vec<Rule>> {
808 let rules = self.get_rules().await?;
809 Ok(crate::rule_application::RuleApplicationEngine::get_matching_rules_sorted(&rules, context))
810 }
811
812 pub async fn get_matching_rules_by_usage(
814 &self,
815 context: &crate::rule_application::GenerationContext,
816 ) -> Result<Vec<Rule>> {
817 let rules = self.get_rules().await?;
818 Ok(crate::rule_application::RuleApplicationEngine::get_matching_rules_by_usage(&rules, context))
819 }
820
821 pub async fn get_matching_rules_by_success(
823 &self,
824 context: &crate::rule_application::GenerationContext,
825 ) -> Result<Vec<Rule>> {
826 let rules = self.get_rules().await?;
827 Ok(crate::rule_application::RuleApplicationEngine::get_matching_rules_by_success(&rules, context))
828 }
829
830 pub async fn apply_learned_rules_to_generation(
832 &self,
833 context: &crate::rule_application::GenerationContext,
834 ) -> Result<Option<String>> {
835 let rules = self.get_rules_for_scope().await?;
837
838 if let Some(result) = crate::rule_application::RuleApplicationEngine::apply_rules_with_precedence(&rules, context) {
840 Ok(result.action)
841 } else {
842 Ok(None)
843 }
844 }
845
846 pub async fn apply_learned_rules_get_all(
848 &self,
849 context: &crate::rule_application::GenerationContext,
850 ) -> Result<Vec<String>> {
851 let rules = self.get_rules_for_scope().await?;
853
854 let results = crate::rule_application::RuleApplicationEngine::apply_rules(&rules, context);
856 let actions: Vec<String> = results
857 .iter()
858 .filter(|r| r.matched)
859 .filter_map(|r| r.action.clone())
860 .collect();
861
862 Ok(actions)
863 }
864
865 pub async fn apply_learned_rules_with_context(
867 &self,
868 generation_type: String,
869 language: String,
870 input: String,
871 ) -> Result<Option<String>> {
872 let context = crate::rule_application::GenerationContext::new(
873 generation_type,
874 language,
875 input,
876 );
877
878 self.apply_learned_rules_to_generation(&context).await
879 }
880
881 pub async fn record_rule_application(
887 &self,
888 rule_id: String,
889 success: bool,
890 application_time_ms: f64,
891 ) -> Result<()> {
892 self.analytics_engine
893 .record_application(rule_id, success, application_time_ms)
894 .await
895 }
896
897 pub async fn get_rule_metrics(&self, rule_id: &str) -> Result<Option<crate::analytics_engine::RuleMetrics>> {
899 self.analytics_engine.get_rule_metrics(rule_id).await
900 }
901
902 pub async fn get_all_rule_metrics(&self) -> Result<Vec<crate::analytics_engine::RuleMetrics>> {
904 self.analytics_engine.get_all_metrics().await
905 }
906
907 pub async fn update_rule_confidence(&self, rule_id: &str, new_confidence: f32) -> Result<()> {
909 self.analytics_engine.update_confidence(rule_id, new_confidence).await
910 }
911
912 pub async fn generate_analytics_insights(&self) -> Result<crate::analytics_engine::AnalyticsInsights> {
914 self.analytics_engine.generate_insights().await
915 }
916
917 pub async fn clear_analytics_metrics(&self) -> Result<()> {
919 self.analytics_engine.clear_metrics().await
920 }
921
922 pub async fn get_metrics_for_scope(
924 &self,
925 scope: RuleScope,
926 ) -> Result<Vec<crate::analytics_engine::RuleMetrics>> {
927 let rules = self.get_rules().await?;
928 self.analytics_engine.get_metrics_by_scope(&rules, scope).await
929 }
930
931 pub async fn export_rules_with_metrics(&self, description: Option<String>) -> Result<String> {
933 let rules = self.get_rules().await?;
934 crate::rule_exchange::RuleExporter::export_to_json(rules, description)
935 }
936
937 pub async fn export_rules_to_file(
939 &self,
940 path: &std::path::Path,
941 description: Option<String>,
942 ) -> Result<()> {
943 let rules = self.get_rules().await?;
944 crate::rule_exchange::RuleExporter::export_to_file(rules, path, description)
945 }
946
947 pub async fn import_rules_from_json(&self, json: &str) -> Result<Vec<Rule>> {
949 crate::rule_exchange::RuleImporter::import_from_json(json)
950 }
951
952 pub async fn import_rules_from_file(&self, path: &std::path::Path) -> Result<Vec<Rule>> {
954 crate::rule_exchange::RuleImporter::import_from_file(path)
955 }
956
957 pub async fn import_and_validate_rules(
959 &self,
960 json: &str,
961 ) -> Result<(Vec<Rule>, Vec<String>)> {
962 crate::rule_exchange::RuleImporter::import_and_validate(json)
963 }
964
965 pub async fn store_imported_rules(&self, rules: Vec<Rule>) -> Result<Vec<String>> {
967 let mut stored_ids = Vec::new();
968 for rule in rules {
969 let id = self.store_rule(rule).await?;
970 stored_ids.push(id);
971 }
972 Ok(stored_ids)
973 }
974}
975
976#[cfg(test)]
977mod tests {
978 use super::*;
979 use crate::models::{DecisionContext, RuleSource};
980
981 #[tokio::test]
982 async fn test_learning_manager_creation() {
983 let manager = LearningManager::new(RuleScope::Global);
984 assert_eq!(manager.get_scope().await, RuleScope::Global);
985 assert!(manager.is_enabled().await);
986 }
987
988 #[tokio::test]
989 async fn test_learning_manager_with_config() {
990 let config = LearningConfig::new(RuleScope::Project);
991 let manager = LearningManager::with_config(config).expect("Failed to create manager");
992 assert_eq!(manager.get_scope().await, RuleScope::Project);
993 }
994
995 #[tokio::test]
996 async fn test_capture_decision() {
997 let manager = LearningManager::new(RuleScope::Session);
998
999 let context = DecisionContext {
1000 project_path: PathBuf::from("/project"),
1001 file_path: PathBuf::from("/project/src/main.rs"),
1002 line_number: 10,
1003 agent_type: "test_agent".to_string(),
1004 };
1005
1006 let decision = Decision::new(
1007 context,
1008 "test_type".to_string(),
1009 serde_json::json!({}),
1010 serde_json::json!({}),
1011 );
1012
1013 let decision_id = decision.id.clone();
1014 let result = manager.capture_decision(decision).await;
1015
1016 assert!(result.is_ok());
1017 assert_eq!(result.unwrap(), decision_id);
1018
1019 let decisions = manager.get_decisions().await;
1020 assert_eq!(decisions.len(), 1);
1021 }
1022
1023 #[tokio::test]
1024 async fn test_capture_decision_disabled() {
1025 let manager = LearningManager::new(RuleScope::Session);
1026 manager.set_enabled(false).await;
1027
1028 let context = DecisionContext {
1029 project_path: PathBuf::from("/project"),
1030 file_path: PathBuf::from("/project/src/main.rs"),
1031 line_number: 10,
1032 agent_type: "test_agent".to_string(),
1033 };
1034
1035 let decision = Decision::new(
1036 context,
1037 "test_type".to_string(),
1038 serde_json::json!({}),
1039 serde_json::json!({}),
1040 );
1041
1042 let result = manager.capture_decision(decision).await;
1043 assert!(result.is_err());
1044 }
1045
1046 #[tokio::test]
1047 async fn test_get_decisions_by_type() {
1048 let manager = LearningManager::new(RuleScope::Session);
1049
1050 let context = DecisionContext {
1051 project_path: PathBuf::from("/project"),
1052 file_path: PathBuf::from("/project/src/main.rs"),
1053 line_number: 10,
1054 agent_type: "test_agent".to_string(),
1055 };
1056
1057 let decision1 = Decision::new(
1058 context.clone(),
1059 "type_a".to_string(),
1060 serde_json::json!({}),
1061 serde_json::json!({}),
1062 );
1063
1064 let decision2 = Decision::new(
1065 context.clone(),
1066 "type_b".to_string(),
1067 serde_json::json!({}),
1068 serde_json::json!({}),
1069 );
1070
1071 let decision3 = Decision::new(
1072 context,
1073 "type_a".to_string(),
1074 serde_json::json!({}),
1075 serde_json::json!({}),
1076 );
1077
1078 manager.capture_decision(decision1).await.unwrap();
1079 manager.capture_decision(decision2).await.unwrap();
1080 manager.capture_decision(decision3).await.unwrap();
1081
1082 let type_a_decisions = manager.get_decisions_by_type("type_a").await;
1083 assert_eq!(type_a_decisions.len(), 2);
1084
1085 let type_b_decisions = manager.get_decisions_by_type("type_b").await;
1086 assert_eq!(type_b_decisions.len(), 1);
1087 }
1088
1089 #[tokio::test]
1090 async fn test_store_rule() {
1091 let manager = LearningManager::new(RuleScope::Session);
1092
1093 let rule = Rule::new(
1094 RuleScope::Session,
1095 "pattern".to_string(),
1096 "action".to_string(),
1097 RuleSource::Learned,
1098 );
1099
1100 let rule_id = rule.id.clone();
1101 let result = manager.store_rule(rule).await;
1102
1103 assert!(result.is_ok());
1104 assert_eq!(result.unwrap(), rule_id);
1105
1106 let retrieved = manager.get_rule(&rule_id).await;
1107 assert!(retrieved.is_ok());
1108 }
1109
1110 #[tokio::test]
1111 async fn test_store_pattern() {
1112 let manager = LearningManager::new(RuleScope::Session);
1113
1114 let pattern = LearnedPattern::new(
1115 "code_generation".to_string(),
1116 "Test pattern".to_string(),
1117 );
1118
1119 let pattern_id = pattern.id.clone();
1120 let result = manager.store_pattern(pattern).await;
1121
1122 assert!(result.is_ok());
1123 assert_eq!(result.unwrap(), pattern_id);
1124
1125 let retrieved = manager.get_pattern(&pattern_id).await;
1126 assert!(retrieved.is_ok());
1127 }
1128
1129 #[tokio::test]
1130 async fn test_get_patterns_by_type() {
1131 let manager = LearningManager::new(RuleScope::Session);
1132
1133 let pattern1 = LearnedPattern::new(
1134 "code_generation".to_string(),
1135 "Pattern 1".to_string(),
1136 );
1137
1138 let pattern2 = LearnedPattern::new(
1139 "refactoring".to_string(),
1140 "Pattern 2".to_string(),
1141 );
1142
1143 let pattern3 = LearnedPattern::new(
1144 "code_generation".to_string(),
1145 "Pattern 3".to_string(),
1146 );
1147
1148 manager.store_pattern(pattern1).await.unwrap();
1149 manager.store_pattern(pattern2).await.unwrap();
1150 manager.store_pattern(pattern3).await.unwrap();
1151
1152 let code_gen_patterns = manager.get_patterns_by_type("code_generation").await;
1153 assert_eq!(code_gen_patterns.len(), 2);
1154
1155 let refactoring_patterns = manager.get_patterns_by_type("refactoring").await;
1156 assert_eq!(refactoring_patterns.len(), 1);
1157 }
1158
1159 #[tokio::test]
1160 async fn test_get_scope_path() {
1161 let manager = LearningManager::new(RuleScope::Global);
1162
1163 let global_path = manager.get_scope_path(RuleScope::Global);
1164 assert!(global_path.is_ok());
1165 let path = global_path.unwrap();
1166 assert!(path.to_string_lossy().contains(".ricecoder"));
1167
1168 let project_path = manager.get_scope_path(RuleScope::Project);
1169 assert!(project_path.is_ok());
1170 assert_eq!(project_path.unwrap(), PathBuf::from(".ricecoder/rules"));
1171
1172 let session_path = manager.get_scope_path(RuleScope::Session);
1173 assert!(session_path.is_err());
1174 }
1175
1176 #[tokio::test]
1177 async fn test_enable_disable_learning() {
1178 let manager = LearningManager::new(RuleScope::Session);
1179
1180 assert!(manager.is_enabled().await);
1181
1182 manager.set_enabled(false).await;
1183 assert!(!manager.is_enabled().await);
1184
1185 manager.set_enabled(true).await;
1186 assert!(manager.is_enabled().await);
1187 }
1188
1189 #[tokio::test]
1190 async fn test_clear_decisions() {
1191 let manager = LearningManager::new(RuleScope::Session);
1192
1193 let context = DecisionContext {
1194 project_path: PathBuf::from("/project"),
1195 file_path: PathBuf::from("/project/src/main.rs"),
1196 line_number: 10,
1197 agent_type: "test_agent".to_string(),
1198 };
1199
1200 let decision = Decision::new(
1201 context,
1202 "test_type".to_string(),
1203 serde_json::json!({}),
1204 serde_json::json!({}),
1205 );
1206
1207 manager.capture_decision(decision).await.unwrap();
1208 assert_eq!(manager.get_decisions().await.len(), 1);
1209
1210 manager.clear_decisions().await;
1211 assert_eq!(manager.get_decisions().await.len(), 0);
1212 }
1213
1214 #[tokio::test]
1215 async fn test_get_decisions_by_context() {
1216 let manager = LearningManager::new(RuleScope::Session);
1217
1218 let context1 = DecisionContext {
1219 project_path: PathBuf::from("/project1"),
1220 file_path: PathBuf::from("/project1/src/main.rs"),
1221 line_number: 10,
1222 agent_type: "agent1".to_string(),
1223 };
1224
1225 let context2 = DecisionContext {
1226 project_path: PathBuf::from("/project2"),
1227 file_path: PathBuf::from("/project2/src/main.rs"),
1228 line_number: 20,
1229 agent_type: "agent2".to_string(),
1230 };
1231
1232 let decision1 = Decision::new(
1233 context1.clone(),
1234 "type_a".to_string(),
1235 serde_json::json!({}),
1236 serde_json::json!({}),
1237 );
1238
1239 let decision2 = Decision::new(
1240 context2.clone(),
1241 "type_b".to_string(),
1242 serde_json::json!({}),
1243 serde_json::json!({}),
1244 );
1245
1246 let decision3 = Decision::new(
1247 context1.clone(),
1248 "type_a".to_string(),
1249 serde_json::json!({}),
1250 serde_json::json!({}),
1251 );
1252
1253 manager.capture_decision(decision1).await.unwrap();
1254 manager.capture_decision(decision2).await.unwrap();
1255 manager.capture_decision(decision3).await.unwrap();
1256
1257 let context1_decisions = manager.get_decisions_by_context(&context1).await;
1258 assert_eq!(context1_decisions.len(), 2);
1259
1260 let context2_decisions = manager.get_decisions_by_context(&context2).await;
1261 assert_eq!(context2_decisions.len(), 1);
1262 }
1263
1264 #[tokio::test]
1265 async fn test_get_decision() {
1266 let manager = LearningManager::new(RuleScope::Session);
1267
1268 let context = DecisionContext {
1269 project_path: PathBuf::from("/project"),
1270 file_path: PathBuf::from("/project/src/main.rs"),
1271 line_number: 10,
1272 agent_type: "test_agent".to_string(),
1273 };
1274
1275 let decision = Decision::new(
1276 context,
1277 "test_type".to_string(),
1278 serde_json::json!({}),
1279 serde_json::json!({}),
1280 );
1281
1282 let decision_id = decision.id.clone();
1283 manager.capture_decision(decision).await.unwrap();
1284
1285 let retrieved = manager.get_decision(&decision_id).await;
1286 assert!(retrieved.is_ok());
1287 assert_eq!(retrieved.unwrap().id, decision_id);
1288 }
1289
1290 #[tokio::test]
1291 async fn test_replay_decisions() {
1292 let manager = LearningManager::new(RuleScope::Session);
1293
1294 let context = DecisionContext {
1295 project_path: PathBuf::from("/project"),
1296 file_path: PathBuf::from("/project/src/main.rs"),
1297 line_number: 10,
1298 agent_type: "test_agent".to_string(),
1299 };
1300
1301 let decision1 = Decision::new(
1302 context.clone(),
1303 "type_a".to_string(),
1304 serde_json::json!({}),
1305 serde_json::json!({}),
1306 );
1307
1308 let decision2 = Decision::new(
1309 context.clone(),
1310 "type_b".to_string(),
1311 serde_json::json!({}),
1312 serde_json::json!({}),
1313 );
1314
1315 manager.capture_decision(decision1).await.unwrap();
1316 manager.capture_decision(decision2).await.unwrap();
1317
1318 let replayed = manager.replay_decisions().await;
1319 assert_eq!(replayed.len(), 2);
1320 assert_eq!(replayed[0].decision_type, "type_a");
1321 assert_eq!(replayed[1].decision_type, "type_b");
1322 }
1323
1324 #[tokio::test]
1325 async fn test_replay_decisions_for_context() {
1326 let manager = LearningManager::new(RuleScope::Session);
1327
1328 let context = DecisionContext {
1329 project_path: PathBuf::from("/project"),
1330 file_path: PathBuf::from("/project/src/main.rs"),
1331 line_number: 10,
1332 agent_type: "test_agent".to_string(),
1333 };
1334
1335 let decision1 = Decision::new(
1336 context.clone(),
1337 "type_a".to_string(),
1338 serde_json::json!({}),
1339 serde_json::json!({}),
1340 );
1341
1342 let decision2 = Decision::new(
1343 context.clone(),
1344 "type_b".to_string(),
1345 serde_json::json!({}),
1346 serde_json::json!({}),
1347 );
1348
1349 manager.capture_decision(decision1).await.unwrap();
1350 manager.capture_decision(decision2).await.unwrap();
1351
1352 let replayed = manager.replay_decisions_for_context(&context).await;
1353 assert_eq!(replayed.len(), 2);
1354 }
1355
1356 #[tokio::test]
1357 async fn test_decision_count() {
1358 let manager = LearningManager::new(RuleScope::Session);
1359
1360 assert_eq!(manager.decision_count().await, 0);
1361
1362 let context = DecisionContext {
1363 project_path: PathBuf::from("/project"),
1364 file_path: PathBuf::from("/project/src/main.rs"),
1365 line_number: 10,
1366 agent_type: "test_agent".to_string(),
1367 };
1368
1369 let decision = Decision::new(
1370 context,
1371 "test_type".to_string(),
1372 serde_json::json!({}),
1373 serde_json::json!({}),
1374 );
1375
1376 manager.capture_decision(decision).await.unwrap();
1377 assert_eq!(manager.decision_count().await, 1);
1378 }
1379
1380 #[tokio::test]
1381 async fn test_get_decision_statistics() {
1382 let manager = LearningManager::new(RuleScope::Session);
1383
1384 let context = DecisionContext {
1385 project_path: PathBuf::from("/project"),
1386 file_path: PathBuf::from("/project/src/main.rs"),
1387 line_number: 10,
1388 agent_type: "agent1".to_string(),
1389 };
1390
1391 let decision1 = Decision::new(
1392 context.clone(),
1393 "type_a".to_string(),
1394 serde_json::json!({}),
1395 serde_json::json!({}),
1396 );
1397
1398 let decision2 = Decision::new(
1399 context.clone(),
1400 "type_b".to_string(),
1401 serde_json::json!({}),
1402 serde_json::json!({}),
1403 );
1404
1405 let decision3 = Decision::new(
1406 context,
1407 "type_a".to_string(),
1408 serde_json::json!({}),
1409 serde_json::json!({}),
1410 );
1411
1412 manager.capture_decision(decision1).await.unwrap();
1413 manager.capture_decision(decision2).await.unwrap();
1414 manager.capture_decision(decision3).await.unwrap();
1415
1416 let stats = manager.get_decision_statistics().await;
1417
1418 assert_eq!(stats.total_decisions, 3);
1419 assert_eq!(stats.decision_types.get("type_a"), Some(&2));
1420 assert_eq!(stats.decision_types.get("type_b"), Some(&1));
1421 assert_eq!(stats.agent_types.get("agent1"), Some(&3));
1422 }
1423
1424 #[tokio::test]
1425 async fn test_extract_patterns() {
1426 let manager = LearningManager::new(RuleScope::Session);
1427
1428 let context = DecisionContext {
1429 project_path: PathBuf::from("/project"),
1430 file_path: PathBuf::from("/project/src/main.rs"),
1431 line_number: 10,
1432 agent_type: "test_agent".to_string(),
1433 };
1434
1435 let decision1 = Decision::new(
1436 context.clone(),
1437 "code_generation".to_string(),
1438 serde_json::json!({"input": "test"}),
1439 serde_json::json!({"output": "result"}),
1440 );
1441
1442 let decision2 = Decision::new(
1443 context,
1444 "code_generation".to_string(),
1445 serde_json::json!({"input": "test"}),
1446 serde_json::json!({"output": "result"}),
1447 );
1448
1449 manager.capture_decision(decision1).await.unwrap();
1450 manager.capture_decision(decision2).await.unwrap();
1451
1452 let patterns = manager.extract_patterns().await.unwrap();
1453 assert_eq!(patterns.len(), 1);
1454 assert_eq!(patterns[0].pattern_type, "code_generation");
1455 }
1456
1457 #[tokio::test]
1458 async fn test_capture_and_store_patterns() {
1459 let manager = LearningManager::new(RuleScope::Session);
1460
1461 let context = DecisionContext {
1462 project_path: PathBuf::from("/project"),
1463 file_path: PathBuf::from("/project/src/main.rs"),
1464 line_number: 10,
1465 agent_type: "test_agent".to_string(),
1466 };
1467
1468 let decision1 = Decision::new(
1469 context.clone(),
1470 "code_generation".to_string(),
1471 serde_json::json!({"input": "test"}),
1472 serde_json::json!({"output": "result"}),
1473 );
1474
1475 let decision2 = Decision::new(
1476 context,
1477 "code_generation".to_string(),
1478 serde_json::json!({"input": "test"}),
1479 serde_json::json!({"output": "result"}),
1480 );
1481
1482 manager.capture_decision(decision1).await.unwrap();
1483 manager.capture_decision(decision2).await.unwrap();
1484
1485 let pattern_ids = manager.capture_and_store_patterns().await.unwrap();
1486 assert_eq!(pattern_ids.len(), 1);
1487
1488 let patterns = manager.get_patterns().await;
1489 assert_eq!(patterns.len(), 1);
1490 }
1491
1492 #[tokio::test]
1493 async fn test_validate_pattern() {
1494 let manager = LearningManager::new(RuleScope::Session);
1495
1496 let context = DecisionContext {
1497 project_path: PathBuf::from("/project"),
1498 file_path: PathBuf::from("/project/src/main.rs"),
1499 line_number: 10,
1500 agent_type: "test_agent".to_string(),
1501 };
1502
1503 let decision1 = Decision::new(
1504 context.clone(),
1505 "code_generation".to_string(),
1506 serde_json::json!({"input": "test"}),
1507 serde_json::json!({"output": "result"}),
1508 );
1509
1510 let decision2 = Decision::new(
1511 context,
1512 "code_generation".to_string(),
1513 serde_json::json!({"input": "test"}),
1514 serde_json::json!({"output": "result"}),
1515 );
1516
1517 manager.capture_decision(decision1).await.unwrap();
1518 manager.capture_decision(decision2).await.unwrap();
1519
1520 let patterns = manager.extract_patterns().await.unwrap();
1521 assert_eq!(patterns.len(), 1);
1522
1523 let validation_score = manager.validate_pattern(&patterns[0]).await.unwrap();
1524 assert!(validation_score >= 0.0);
1525 assert!(validation_score <= 1.0);
1526 }
1527
1528 #[tokio::test]
1529 async fn test_update_pattern_confidence() {
1530 let manager = LearningManager::new(RuleScope::Session);
1531
1532 let context = DecisionContext {
1533 project_path: PathBuf::from("/project"),
1534 file_path: PathBuf::from("/project/src/main.rs"),
1535 line_number: 10,
1536 agent_type: "test_agent".to_string(),
1537 };
1538
1539 let decision1 = Decision::new(
1540 context.clone(),
1541 "code_generation".to_string(),
1542 serde_json::json!({"input": "test"}),
1543 serde_json::json!({"output": "result"}),
1544 );
1545
1546 let decision2 = Decision::new(
1547 context,
1548 "code_generation".to_string(),
1549 serde_json::json!({"input": "test"}),
1550 serde_json::json!({"output": "result"}),
1551 );
1552
1553 manager.capture_decision(decision1).await.unwrap();
1554 manager.capture_decision(decision2).await.unwrap();
1555
1556 let patterns = manager.extract_patterns().await.unwrap();
1557 assert!(!patterns.is_empty(), "Should extract at least one pattern");
1558
1559 let pattern_id = patterns[0].id.clone();
1560
1561 manager.store_pattern(patterns[0].clone()).await.unwrap();
1563
1564 let result = manager.update_pattern_confidence(&pattern_id, 0.9).await;
1565 assert!(result.is_ok());
1566
1567 let updated_pattern = manager.get_pattern(&pattern_id).await.unwrap();
1568 assert!(updated_pattern.confidence > 0.0);
1569 }
1570
1571 #[tokio::test]
1572 async fn test_get_patterns_by_confidence() {
1573 let manager = LearningManager::new(RuleScope::Session);
1574
1575 let mut pattern1 = LearnedPattern::new(
1576 "code_generation".to_string(),
1577 "Pattern 1".to_string(),
1578 );
1579 pattern1.confidence = 0.8;
1580
1581 let mut pattern2 = LearnedPattern::new(
1582 "refactoring".to_string(),
1583 "Pattern 2".to_string(),
1584 );
1585 pattern2.confidence = 0.3;
1586
1587 manager.store_pattern(pattern1).await.unwrap();
1588 manager.store_pattern(pattern2).await.unwrap();
1589
1590 let high_confidence = manager.get_patterns_by_confidence(0.5).await;
1591 assert_eq!(high_confidence.len(), 1);
1592 assert!(high_confidence[0].confidence >= 0.5);
1593 }
1594
1595 #[tokio::test]
1596 async fn test_get_patterns_by_confidence_sorted() {
1597 let manager = LearningManager::new(RuleScope::Session);
1598
1599 let mut pattern1 = LearnedPattern::new(
1600 "code_generation".to_string(),
1601 "Pattern 1".to_string(),
1602 );
1603 pattern1.confidence = 0.5;
1604
1605 let mut pattern2 = LearnedPattern::new(
1606 "refactoring".to_string(),
1607 "Pattern 2".to_string(),
1608 );
1609 pattern2.confidence = 0.9;
1610
1611 let mut pattern3 = LearnedPattern::new(
1612 "analysis".to_string(),
1613 "Pattern 3".to_string(),
1614 );
1615 pattern3.confidence = 0.7;
1616
1617 manager.store_pattern(pattern1).await.unwrap();
1618 manager.store_pattern(pattern2).await.unwrap();
1619 manager.store_pattern(pattern3).await.unwrap();
1620
1621 let sorted = manager.get_patterns_by_confidence_sorted().await;
1622 assert_eq!(sorted.len(), 3);
1623 assert!(sorted[0].confidence >= sorted[1].confidence);
1624 assert!(sorted[1].confidence >= sorted[2].confidence);
1625 }
1626
1627 #[tokio::test]
1628 async fn test_get_patterns_by_occurrences() {
1629 let manager = LearningManager::new(RuleScope::Session);
1630
1631 let mut pattern1 = LearnedPattern::new(
1632 "code_generation".to_string(),
1633 "Pattern 1".to_string(),
1634 );
1635 pattern1.occurrences = 5;
1636
1637 let mut pattern2 = LearnedPattern::new(
1638 "refactoring".to_string(),
1639 "Pattern 2".to_string(),
1640 );
1641 pattern2.occurrences = 10;
1642
1643 let mut pattern3 = LearnedPattern::new(
1644 "analysis".to_string(),
1645 "Pattern 3".to_string(),
1646 );
1647 pattern3.occurrences = 3;
1648
1649 manager.store_pattern(pattern1).await.unwrap();
1650 manager.store_pattern(pattern2).await.unwrap();
1651 manager.store_pattern(pattern3).await.unwrap();
1652
1653 let sorted = manager.get_patterns_by_occurrences().await;
1654 assert_eq!(sorted.len(), 3);
1655 assert_eq!(sorted[0].occurrences, 10);
1656 assert_eq!(sorted[1].occurrences, 5);
1657 assert_eq!(sorted[2].occurrences, 3);
1658 }
1659
1660 #[tokio::test]
1661 async fn test_pattern_count() {
1662 let manager = LearningManager::new(RuleScope::Session);
1663
1664 assert_eq!(manager.pattern_count().await, 0);
1665
1666 let pattern1 = LearnedPattern::new(
1667 "code_generation".to_string(),
1668 "Pattern 1".to_string(),
1669 );
1670
1671 let pattern2 = LearnedPattern::new(
1672 "refactoring".to_string(),
1673 "Pattern 2".to_string(),
1674 );
1675
1676 manager.store_pattern(pattern1).await.unwrap();
1677 manager.store_pattern(pattern2).await.unwrap();
1678
1679 assert_eq!(manager.pattern_count().await, 2);
1680 }
1681
1682 #[tokio::test]
1683 async fn test_clear_patterns() {
1684 let manager = LearningManager::new(RuleScope::Session);
1685
1686 let pattern = LearnedPattern::new(
1687 "code_generation".to_string(),
1688 "Pattern".to_string(),
1689 );
1690
1691 manager.store_pattern(pattern).await.unwrap();
1692 assert_eq!(manager.pattern_count().await, 1);
1693
1694 manager.clear_patterns().await;
1695 assert_eq!(manager.pattern_count().await, 0);
1696 }
1697
1698 #[tokio::test]
1699 async fn test_request_rule_promotion() {
1700 let manager = LearningManager::new(RuleScope::Session);
1701
1702 let rule = Rule::new(
1703 RuleScope::Project,
1704 "pattern".to_string(),
1705 "action".to_string(),
1706 crate::models::RuleSource::Learned,
1707 );
1708
1709 let result = manager.request_rule_promotion(rule).await;
1710 assert!(result.is_ok());
1711
1712 let review = result.unwrap();
1713 assert_eq!(manager.pending_promotion_count().await, 1);
1714 }
1715
1716 #[tokio::test]
1717 async fn test_get_pending_promotions() {
1718 let manager = LearningManager::new(RuleScope::Session);
1719
1720 let rule1 = Rule::new(
1721 RuleScope::Project,
1722 "pattern1".to_string(),
1723 "action1".to_string(),
1724 crate::models::RuleSource::Learned,
1725 );
1726
1727 let rule2 = Rule::new(
1728 RuleScope::Project,
1729 "pattern2".to_string(),
1730 "action2".to_string(),
1731 crate::models::RuleSource::Learned,
1732 );
1733
1734 manager.request_rule_promotion(rule1).await.unwrap();
1735 manager.request_rule_promotion(rule2).await.unwrap();
1736
1737 let pending = manager.get_pending_promotions().await;
1738 assert_eq!(pending.len(), 2);
1739 }
1740
1741 #[tokio::test]
1742 async fn test_approve_promotion() {
1743 let manager = LearningManager::new(RuleScope::Session);
1744
1745 let rule = Rule::new(
1746 RuleScope::Project,
1747 "pattern".to_string(),
1748 "action".to_string(),
1749 crate::models::RuleSource::Learned,
1750 );
1751
1752 let rule_id = rule.id.clone();
1753 manager.request_rule_promotion(rule).await.unwrap();
1754
1755 let result = manager.approve_promotion(&rule_id, Some("Looks good".to_string())).await;
1756 assert!(result.is_ok());
1757
1758 let promoted_rule = result.unwrap();
1759 assert_eq!(promoted_rule.scope, RuleScope::Global);
1760 assert_eq!(promoted_rule.source, crate::models::RuleSource::Promoted);
1761
1762 assert_eq!(manager.pending_promotion_count().await, 0);
1763 }
1764
1765 #[tokio::test]
1766 async fn test_reject_promotion() {
1767 let manager = LearningManager::new(RuleScope::Session);
1768
1769 let rule = Rule::new(
1770 RuleScope::Project,
1771 "pattern".to_string(),
1772 "action".to_string(),
1773 crate::models::RuleSource::Learned,
1774 );
1775
1776 let rule_id = rule.id.clone();
1777 manager.request_rule_promotion(rule).await.unwrap();
1778
1779 let result = manager.reject_promotion(&rule_id, Some("Not ready".to_string())).await;
1780 assert!(result.is_ok());
1781
1782 assert_eq!(manager.pending_promotion_count().await, 0);
1783 }
1784
1785 #[tokio::test]
1786 async fn test_promotion_history() {
1787 let manager = LearningManager::new(RuleScope::Session);
1788
1789 let rule = Rule::new(
1790 RuleScope::Project,
1791 "pattern".to_string(),
1792 "action".to_string(),
1793 crate::models::RuleSource::Learned,
1794 );
1795
1796 let rule_id = rule.id.clone();
1797 manager.request_rule_promotion(rule).await.unwrap();
1798 manager.approve_promotion(&rule_id, None).await.unwrap();
1799
1800 let history = manager.get_promotion_history().await;
1801 assert_eq!(history.len(), 1);
1802 assert!(history[0].approved);
1803
1804 let rule_history = manager.get_promotion_history_for_rule(&rule_id).await;
1805 assert_eq!(rule_history.len(), 1);
1806 }
1807
1808 #[tokio::test]
1809 async fn test_get_approved_promotions() {
1810 let manager = LearningManager::new(RuleScope::Session);
1811
1812 let rule1 = Rule::new(
1813 RuleScope::Project,
1814 "pattern1".to_string(),
1815 "action1".to_string(),
1816 crate::models::RuleSource::Learned,
1817 );
1818
1819 let rule2 = Rule::new(
1820 RuleScope::Project,
1821 "pattern2".to_string(),
1822 "action2".to_string(),
1823 crate::models::RuleSource::Learned,
1824 );
1825
1826 let rule1_id = rule1.id.clone();
1827 let rule2_id = rule2.id.clone();
1828
1829 manager.request_rule_promotion(rule1).await.unwrap();
1830 manager.request_rule_promotion(rule2).await.unwrap();
1831
1832 manager.approve_promotion(&rule1_id, None).await.unwrap();
1833 manager.reject_promotion(&rule2_id, None).await.unwrap();
1834
1835 let approved = manager.get_approved_promotions().await;
1836 assert_eq!(approved.len(), 1);
1837 assert!(approved[0].approved);
1838
1839 let rejected = manager.get_rejected_promotions().await;
1840 assert_eq!(rejected.len(), 1);
1841 assert!(!rejected[0].approved);
1842 }
1843
1844 #[tokio::test]
1845 async fn test_clear_pending_promotions() {
1846 let manager = LearningManager::new(RuleScope::Session);
1847
1848 let rule = Rule::new(
1849 RuleScope::Project,
1850 "pattern".to_string(),
1851 "action".to_string(),
1852 crate::models::RuleSource::Learned,
1853 );
1854
1855 manager.request_rule_promotion(rule).await.unwrap();
1856 assert_eq!(manager.pending_promotion_count().await, 1);
1857
1858 manager.clear_pending_promotions().await;
1859 assert_eq!(manager.pending_promotion_count().await, 0);
1860 }
1861
1862 #[tokio::test]
1863 async fn test_clear_promotion_history() {
1864 let manager = LearningManager::new(RuleScope::Session);
1865
1866 let rule = Rule::new(
1867 RuleScope::Project,
1868 "pattern".to_string(),
1869 "action".to_string(),
1870 crate::models::RuleSource::Learned,
1871 );
1872
1873 let rule_id = rule.id.clone();
1874 manager.request_rule_promotion(rule).await.unwrap();
1875 manager.approve_promotion(&rule_id, None).await.unwrap();
1876
1877 assert_eq!(manager.get_promotion_history().await.len(), 1);
1878
1879 manager.clear_promotion_history().await;
1880 assert_eq!(manager.get_promotion_history().await.len(), 0);
1881 }
1882}