ricecoder_agents/domain/
knowledge_properties.rs

1//! Property-based tests for domain knowledge relevance
2//!
3//! **Feature: ricecoder-domain-agents, Property 4: Knowledge Application Relevance**
4//! **Validates: Requirements 1.2-1.6, 2.2-2.6, 3.2-3.6**
5
6#[cfg(test)]
7mod tests {
8    use crate::domain::{KnowledgeBase, AgentFactory};
9    use crate::domain::factory::{
10        AgentConfig, CapabilityConfig, BestPracticeConfig, TechRecommendationConfig,
11        PatternConfig, AntiPatternConfig,
12    };
13
14    /// Helper function to create a test agent configuration with knowledge
15    fn create_agent_config_with_knowledge(
16        domain: &str,
17        name: &str,
18        capabilities: Vec<(&str, Vec<&str>)>,
19        tech_recommendations: Vec<(&str, Vec<&str>)>,
20        best_practices: Vec<(&str, Vec<&str>)>,
21        patterns: Vec<(&str, Vec<&str>)>,
22        anti_patterns: Vec<(&str, &str)>,
23    ) -> AgentConfig {
24        AgentConfig {
25            domain: domain.to_string(),
26            name: name.to_string(),
27            description: format!("Agent for {} development", domain),
28            capabilities: capabilities
29                .into_iter()
30                .map(|(cap_name, techs)| CapabilityConfig {
31                    name: cap_name.to_string(),
32                    description: format!("Capability: {}", cap_name),
33                    technologies: techs.into_iter().map(|t| t.to_string()).collect(),
34                })
35                .collect(),
36            best_practices: best_practices
37                .into_iter()
38                .map(|(title, techs)| BestPracticeConfig {
39                    title: title.to_string(),
40                    description: format!("Best practice: {}", title),
41                    technologies: techs.into_iter().map(|t| t.to_string()).collect(),
42                    implementation: "Implementation guidance".to_string(),
43                })
44                .collect(),
45            technology_recommendations: tech_recommendations
46                .into_iter()
47                .map(|(tech, use_cases)| TechRecommendationConfig {
48                    technology: tech.to_string(),
49                    use_cases: use_cases.into_iter().map(|u| u.to_string()).collect(),
50                    pros: vec!["Pro 1".to_string()],
51                    cons: vec!["Con 1".to_string()],
52                    alternatives: vec![],
53                })
54                .collect(),
55            patterns: patterns
56                .into_iter()
57                .map(|(name, techs)| PatternConfig {
58                    name: name.to_string(),
59                    description: format!("Pattern: {}", name),
60                    technologies: techs.into_iter().map(|t| t.to_string()).collect(),
61                    use_cases: vec!["Use case 1".to_string()],
62                })
63                .collect(),
64            anti_patterns: anti_patterns
65                .into_iter()
66                .map(|(name, reason)| AntiPatternConfig {
67                    name: name.to_string(),
68                    description: format!("Anti-pattern: {}", name),
69                    why_avoid: reason.to_string(),
70                    better_alternative: "Better approach".to_string(),
71                })
72                .collect(),
73        }
74    }
75
76    /// Property 4: Knowledge Application Relevance - Web Domain
77    /// For any web domain agent, all recommendations SHALL be relevant to web development
78    /// and include appropriate web technologies (React, Vue, Angular, CSS, Tailwind, Vite, Webpack, Jest, Vitest, Playwright).
79    ///
80    /// This property tests that:
81    /// 1. Web agent knowledge contains only web-relevant technologies
82    /// 2. Best practices are applicable to web development
83    /// 3. Technology recommendations include web technologies
84    /// 4. Patterns are relevant to web development
85    /// 5. Anti-patterns are relevant to web development
86    #[test]
87    fn property_knowledge_relevance_web_domain() {
88        let factory = AgentFactory::new();
89        let kb = KnowledgeBase::new();
90
91        // Create web agent configuration with comprehensive knowledge
92        let web_config = create_agent_config_with_knowledge(
93            "web",
94            "Web Development Agent",
95            vec![
96                ("Frontend Framework Selection", vec!["React", "Vue", "Angular"]),
97                ("Styling Guidance", vec!["CSS", "Tailwind CSS", "styled-components"]),
98                ("Build Configuration", vec!["Vite", "Webpack"]),
99                ("Testing Strategy", vec!["Jest", "Vitest", "Playwright"]),
100            ],
101            vec![
102                ("React", vec!["Single Page Applications", "Complex UIs"]),
103                ("Vue", vec!["Progressive enhancement", "Rapid prototyping"]),
104                ("Angular", vec!["Enterprise applications"]),
105                ("Vite", vec!["Modern web development"]),
106                ("Webpack", vec!["Complex bundling scenarios"]),
107                ("Jest", vec!["JavaScript testing"]),
108                ("Vitest", vec!["Vite projects"]),
109                ("Playwright", vec!["E2E testing"]),
110            ],
111            vec![
112                ("Component-Based Architecture", vec!["React", "Vue"]),
113                ("Performance Optimization", vec!["React", "Vue", "Angular"]),
114            ],
115            vec![
116                ("MVC Pattern", vec!["React", "Vue"]),
117                ("Singleton Pattern", vec!["JavaScript"]),
118            ],
119            vec![
120                ("God Component", "Component that does too much"),
121                ("Tight Coupling", "Components tightly coupled"),
122            ],
123        );
124
125        // Create web agent
126        let web_agent = factory.create_agent("web", &web_config).unwrap();
127
128        // Load knowledge into knowledge base
129        for practice in &web_agent.knowledge.best_practices {
130            kb.add_best_practice("web", practice.clone()).unwrap();
131        }
132
133        for recommendation in &web_agent.knowledge.technology_recommendations {
134            kb.add_tech_recommendation("web", recommendation.clone()).unwrap();
135        }
136
137        for pattern in &web_agent.knowledge.patterns {
138            kb.add_pattern("web", pattern.clone()).unwrap();
139        }
140
141        for anti_pattern in &web_agent.knowledge.anti_patterns {
142            kb.add_anti_pattern("web", anti_pattern.clone()).unwrap();
143        }
144
145        // Property 1: All best practices are for web domain
146        let practices = kb.get_best_practices("web").unwrap();
147        assert!(!practices.is_empty());
148        for practice in &practices {
149            assert_eq!(practice.domain, "web");
150            // All technologies should be web-related
151            for tech in &practice.technologies {
152                assert!(
153                    vec!["React", "Vue", "Angular", "CSS", "Tailwind CSS", "styled-components"]
154                        .contains(&tech.as_str()),
155                    "Technology {} is not web-related",
156                    tech
157                );
158            }
159        }
160
161        // Property 2: All technology recommendations are for web domain
162        let tech_recs = kb.get_tech_recommendations("web").unwrap();
163        assert!(!tech_recs.is_empty());
164        for rec in &tech_recs {
165            assert_eq!(rec.domain, "web");
166            // All technologies should be web-related
167            assert!(
168                vec!["React", "Vue", "Angular", "Vite", "Webpack", "Jest", "Vitest", "Playwright"]
169                    .contains(&rec.technology.as_str()),
170                "Technology {} is not web-related",
171                rec.technology
172            );
173            // All recommendations should have use cases
174            assert!(!rec.use_cases.is_empty());
175            // All recommendations should have pros and cons
176            assert!(!rec.pros.is_empty());
177            assert!(!rec.cons.is_empty());
178        }
179
180        // Property 3: All patterns are for web domain
181        let patterns = kb.get_patterns("web").unwrap();
182        assert!(!patterns.is_empty());
183        for pattern in &patterns {
184            assert_eq!(pattern.domain, "web");
185            // All technologies should be web-related
186            for tech in &pattern.technologies {
187                assert!(
188                    vec!["React", "Vue", "Angular", "JavaScript"]
189                        .contains(&tech.as_str()),
190                    "Technology {} is not web-related",
191                    tech
192                );
193            }
194        }
195
196        // Property 4: All anti-patterns are for web domain
197        let anti_patterns = kb.get_anti_patterns("web").unwrap();
198        assert!(!anti_patterns.is_empty());
199        for anti_pattern in &anti_patterns {
200            assert_eq!(anti_pattern.domain, "web");
201            // Anti-patterns should have rationale
202            assert!(!anti_pattern.why_avoid.is_empty());
203            // Anti-patterns should have alternatives
204            assert!(!anti_pattern.better_alternative.is_empty());
205        }
206
207        // Property 5: Web technologies are present in recommendations
208        let tech_names: Vec<_> = tech_recs.iter().map(|t| &t.technology).collect();
209        assert!(tech_names.contains(&&"React".to_string()));
210        assert!(tech_names.contains(&&"Vue".to_string()));
211        assert!(tech_names.contains(&&"Vite".to_string()));
212        assert!(tech_names.contains(&&"Jest".to_string()));
213    }
214
215    /// Property 4: Knowledge Application Relevance - Backend Domain
216    /// For any backend domain agent, all recommendations SHALL be relevant to backend development
217    /// and include appropriate backend technologies (REST, GraphQL, gRPC, PostgreSQL, MongoDB, Redis, OAuth, JWT).
218    ///
219    /// This property tests that:
220    /// 1. Backend agent knowledge contains only backend-relevant technologies
221    /// 2. Best practices are applicable to backend development
222    /// 3. Technology recommendations include backend technologies
223    /// 4. Patterns are relevant to backend development
224    /// 5. Anti-patterns are relevant to backend development
225    #[test]
226    fn property_knowledge_relevance_backend_domain() {
227        let factory = AgentFactory::new();
228        let kb = KnowledgeBase::new();
229
230        // Create backend agent configuration with comprehensive knowledge
231        let backend_config = create_agent_config_with_knowledge(
232            "backend",
233            "Backend Development Agent",
234            vec![
235                ("API Design", vec!["REST", "GraphQL", "gRPC"]),
236                ("Architecture Guidance", vec!["Microservices", "Monolithic", "Serverless"]),
237                ("Database Design", vec!["PostgreSQL", "MongoDB", "Neo4j"]),
238                ("Scalability", vec!["Redis", "Memcached", "Load Balancers"]),
239                ("Security", vec!["OAuth 2.0", "JWT", "TLS"]),
240                ("Observability", vec!["ELK Stack", "Prometheus", "Jaeger"]),
241            ],
242            vec![
243                ("REST", vec!["Web APIs", "Microservices"]),
244                ("GraphQL", vec!["Flexible APIs", "Real-time data"]),
245                ("gRPC", vec!["High-performance APIs"]),
246                ("PostgreSQL", vec!["Relational data", "ACID transactions"]),
247                ("MongoDB", vec!["Document storage", "Flexible schema"]),
248                ("Redis", vec!["Caching", "Session storage"]),
249                ("OAuth 2.0", vec!["Authentication"]),
250                ("JWT", vec!["Token-based auth"]),
251            ],
252            vec![
253                ("API Versioning", vec!["REST", "GraphQL"]),
254                ("Database Indexing", vec!["PostgreSQL", "MongoDB"]),
255            ],
256            vec![
257                ("MVC Pattern", vec!["Django", "Rails"]),
258                ("Repository Pattern", vec!["Java", "C#"]),
259            ],
260            vec![
261                ("God Object", "Class that does too much"),
262                ("Tight Coupling", "Services tightly coupled"),
263            ],
264        );
265
266        // Create backend agent
267        let backend_agent = factory.create_agent("backend", &backend_config).unwrap();
268
269        // Load knowledge into knowledge base
270        for practice in &backend_agent.knowledge.best_practices {
271            kb.add_best_practice("backend", practice.clone()).unwrap();
272        }
273
274        for recommendation in &backend_agent.knowledge.technology_recommendations {
275            kb.add_tech_recommendation("backend", recommendation.clone()).unwrap();
276        }
277
278        for pattern in &backend_agent.knowledge.patterns {
279            kb.add_pattern("backend", pattern.clone()).unwrap();
280        }
281
282        for anti_pattern in &backend_agent.knowledge.anti_patterns {
283            kb.add_anti_pattern("backend", anti_pattern.clone()).unwrap();
284        }
285
286        // Property 1: All best practices are for backend domain
287        let practices = kb.get_best_practices("backend").unwrap();
288        assert!(!practices.is_empty());
289        for practice in &practices {
290            assert_eq!(practice.domain, "backend");
291            // All technologies should be backend-related
292            for tech in &practice.technologies {
293                assert!(
294                    vec!["REST", "GraphQL", "PostgreSQL", "MongoDB"]
295                        .contains(&tech.as_str()),
296                    "Technology {} is not backend-related",
297                    tech
298                );
299            }
300        }
301
302        // Property 2: All technology recommendations are for backend domain
303        let tech_recs = kb.get_tech_recommendations("backend").unwrap();
304        assert!(!tech_recs.is_empty());
305        for rec in &tech_recs {
306            assert_eq!(rec.domain, "backend");
307            // All technologies should be backend-related
308            assert!(
309                vec!["REST", "GraphQL", "gRPC", "PostgreSQL", "MongoDB", "Redis", "OAuth 2.0", "JWT"]
310                    .contains(&rec.technology.as_str()),
311                "Technology {} is not backend-related",
312                rec.technology
313            );
314            // All recommendations should have use cases
315            assert!(!rec.use_cases.is_empty());
316            // All recommendations should have pros and cons
317            assert!(!rec.pros.is_empty());
318            assert!(!rec.cons.is_empty());
319        }
320
321        // Property 3: All patterns are for backend domain
322        let patterns = kb.get_patterns("backend").unwrap();
323        assert!(!patterns.is_empty());
324        for pattern in &patterns {
325            assert_eq!(pattern.domain, "backend");
326            // All technologies should be backend-related
327            for tech in &pattern.technologies {
328                assert!(
329                    vec!["Django", "Rails", "Java", "C#"]
330                        .contains(&tech.as_str()),
331                    "Technology {} is not backend-related",
332                    tech
333                );
334            }
335        }
336
337        // Property 4: All anti-patterns are for backend domain
338        let anti_patterns = kb.get_anti_patterns("backend").unwrap();
339        assert!(!anti_patterns.is_empty());
340        for anti_pattern in &anti_patterns {
341            assert_eq!(anti_pattern.domain, "backend");
342            // Anti-patterns should have rationale
343            assert!(!anti_pattern.why_avoid.is_empty());
344            // Anti-patterns should have alternatives
345            assert!(!anti_pattern.better_alternative.is_empty());
346        }
347
348        // Property 5: Backend technologies are present in recommendations
349        let tech_names: Vec<_> = tech_recs.iter().map(|t| &t.technology).collect();
350        assert!(tech_names.contains(&&"REST".to_string()));
351        assert!(tech_names.contains(&&"GraphQL".to_string()));
352        assert!(tech_names.contains(&&"PostgreSQL".to_string()));
353        assert!(tech_names.contains(&&"MongoDB".to_string()));
354    }
355
356    /// Property 4: Knowledge Application Relevance - DevOps Domain
357    /// For any DevOps domain agent, all recommendations SHALL be relevant to DevOps
358    /// and include appropriate DevOps technologies (GitHub Actions, GitLab CI, Jenkins, Terraform,
359    /// CloudFormation, Ansible, Docker, Kubernetes, Prometheus, Grafana).
360    ///
361    /// This property tests that:
362    /// 1. DevOps agent knowledge contains only DevOps-relevant technologies
363    /// 2. Best practices are applicable to DevOps
364    /// 3. Technology recommendations include DevOps technologies
365    /// 4. Patterns are relevant to DevOps
366    /// 5. Anti-patterns are relevant to DevOps
367    #[test]
368    fn property_knowledge_relevance_devops_domain() {
369        let factory = AgentFactory::new();
370        let kb = KnowledgeBase::new();
371
372        // Create DevOps agent configuration with comprehensive knowledge
373        let devops_config = create_agent_config_with_knowledge(
374            "devops",
375            "DevOps Agent",
376            vec![
377                ("CI/CD Pipeline Setup", vec!["GitHub Actions", "GitLab CI", "Jenkins"]),
378                ("Infrastructure as Code", vec!["Terraform", "CloudFormation", "Ansible"]),
379                ("Containerization", vec!["Docker", "Kubernetes"]),
380                ("Observability Infrastructure", vec!["Prometheus", "Grafana", "ELK Stack"]),
381                ("Security Scanning", vec!["Trivy", "Snyk", "SonarQube"]),
382                ("Auto-Scaling", vec!["Kubernetes", "AWS Auto Scaling", "Docker Swarm"]),
383            ],
384            vec![
385                ("GitHub Actions", vec!["CI/CD pipelines"]),
386                ("GitLab CI", vec!["CI/CD pipelines"]),
387                ("Jenkins", vec!["CI/CD pipelines"]),
388                ("Terraform", vec!["Infrastructure as Code"]),
389                ("CloudFormation", vec!["Infrastructure as Code"]),
390                ("Ansible", vec!["Infrastructure as Code"]),
391                ("Docker", vec!["Containerization"]),
392                ("Kubernetes", vec!["Container orchestration"]),
393                ("Prometheus", vec!["Monitoring"]),
394                ("Grafana", vec!["Visualization"]),
395            ],
396            vec![
397                ("Infrastructure as Code", vec!["Terraform", "CloudFormation"]),
398                ("Monitoring and Alerting", vec!["Prometheus", "Grafana"]),
399            ],
400            vec![
401                ("Blue-Green Deployment", vec!["Kubernetes", "Docker"]),
402                ("Canary Deployment", vec!["Kubernetes"]),
403            ],
404            vec![
405                ("Manual Infrastructure", "Infrastructure managed manually"),
406                ("No Monitoring", "No monitoring or alerting"),
407            ],
408        );
409
410        // Create DevOps agent
411        let devops_agent = factory.create_agent("devops", &devops_config).unwrap();
412
413        // Load knowledge into knowledge base
414        for practice in &devops_agent.knowledge.best_practices {
415            kb.add_best_practice("devops", practice.clone()).unwrap();
416        }
417
418        for recommendation in &devops_agent.knowledge.technology_recommendations {
419            kb.add_tech_recommendation("devops", recommendation.clone()).unwrap();
420        }
421
422        for pattern in &devops_agent.knowledge.patterns {
423            kb.add_pattern("devops", pattern.clone()).unwrap();
424        }
425
426        for anti_pattern in &devops_agent.knowledge.anti_patterns {
427            kb.add_anti_pattern("devops", anti_pattern.clone()).unwrap();
428        }
429
430        // Property 1: All best practices are for DevOps domain
431        let practices = kb.get_best_practices("devops").unwrap();
432        assert!(!practices.is_empty());
433        for practice in &practices {
434            assert_eq!(practice.domain, "devops");
435            // All technologies should be DevOps-related
436            for tech in &practice.technologies {
437                assert!(
438                    vec!["Terraform", "CloudFormation", "Prometheus", "Grafana"]
439                        .contains(&tech.as_str()),
440                    "Technology {} is not DevOps-related",
441                    tech
442                );
443            }
444        }
445
446        // Property 2: All technology recommendations are for DevOps domain
447        let tech_recs = kb.get_tech_recommendations("devops").unwrap();
448        assert!(!tech_recs.is_empty());
449        for rec in &tech_recs {
450            assert_eq!(rec.domain, "devops");
451            // All technologies should be DevOps-related
452            assert!(
453                vec!["GitHub Actions", "GitLab CI", "Jenkins", "Terraform", "CloudFormation", "Ansible", "Docker", "Kubernetes", "Prometheus", "Grafana"]
454                    .contains(&rec.technology.as_str()),
455                "Technology {} is not DevOps-related",
456                rec.technology
457            );
458            // All recommendations should have use cases
459            assert!(!rec.use_cases.is_empty());
460            // All recommendations should have pros and cons
461            assert!(!rec.pros.is_empty());
462            assert!(!rec.cons.is_empty());
463        }
464
465        // Property 3: All patterns are for DevOps domain
466        let patterns = kb.get_patterns("devops").unwrap();
467        assert!(!patterns.is_empty());
468        for pattern in &patterns {
469            assert_eq!(pattern.domain, "devops");
470            // All technologies should be DevOps-related
471            for tech in &pattern.technologies {
472                assert!(
473                    vec!["Kubernetes", "Docker"]
474                        .contains(&tech.as_str()),
475                    "Technology {} is not DevOps-related",
476                    tech
477                );
478            }
479        }
480
481        // Property 4: All anti-patterns are for DevOps domain
482        let anti_patterns = kb.get_anti_patterns("devops").unwrap();
483        assert!(!anti_patterns.is_empty());
484        for anti_pattern in &anti_patterns {
485            assert_eq!(anti_pattern.domain, "devops");
486            // Anti-patterns should have rationale
487            assert!(!anti_pattern.why_avoid.is_empty());
488            // Anti-patterns should have alternatives
489            assert!(!anti_pattern.better_alternative.is_empty());
490        }
491
492        // Property 5: DevOps technologies are present in recommendations
493        let tech_names: Vec<_> = tech_recs.iter().map(|t| &t.technology).collect();
494        assert!(tech_names.contains(&&"GitHub Actions".to_string()));
495        assert!(tech_names.contains(&&"Terraform".to_string()));
496        assert!(tech_names.contains(&&"Docker".to_string()));
497        assert!(tech_names.contains(&&"Kubernetes".to_string()));
498    }
499
500    /// Property 4: Knowledge Retrieval Accuracy
501    /// For any domain with loaded knowledge, retrieving knowledge by domain SHALL return
502    /// only knowledge for that domain
503    #[test]
504    fn property_knowledge_retrieval_accuracy() {
505        let factory = AgentFactory::new();
506        let kb = KnowledgeBase::new();
507
508        // Create and load knowledge for multiple domains
509        let domains = vec!["web", "backend", "devops"];
510
511        for domain in &domains {
512            let config = create_agent_config_with_knowledge(
513                domain,
514                &format!("{} Agent", domain),
515                vec![("Capability", vec!["Tech"])],
516                vec![("Tech", vec!["Use case"])],
517                vec![("Practice", vec!["Tech"])],
518                vec![("Pattern", vec!["Tech"])],
519                vec![("Anti-pattern", "Reason")],
520            );
521
522            let agent = factory.create_agent(domain, &config).unwrap();
523
524            for practice in &agent.knowledge.best_practices {
525                kb.add_best_practice(domain, practice.clone()).unwrap();
526            }
527
528            for recommendation in &agent.knowledge.technology_recommendations {
529                kb.add_tech_recommendation(domain, recommendation.clone()).unwrap();
530            }
531
532            for pattern in &agent.knowledge.patterns {
533                kb.add_pattern(domain, pattern.clone()).unwrap();
534            }
535
536            for anti_pattern in &agent.knowledge.anti_patterns {
537                kb.add_anti_pattern(domain, anti_pattern.clone()).unwrap();
538            }
539        }
540
541        // Property: Each domain should only return its own knowledge
542        for domain in &domains {
543            let practices = kb.get_best_practices(domain).unwrap();
544            for practice in &practices {
545                assert_eq!(practice.domain, *domain);
546            }
547
548            let tech_recs = kb.get_tech_recommendations(domain).unwrap();
549            for rec in &tech_recs {
550                assert_eq!(rec.domain, *domain);
551            }
552
553            let patterns = kb.get_patterns(domain).unwrap();
554            for pattern in &patterns {
555                assert_eq!(pattern.domain, *domain);
556            }
557
558            let anti_patterns = kb.get_anti_patterns(domain).unwrap();
559            for anti_pattern in &anti_patterns {
560                assert_eq!(anti_pattern.domain, *domain);
561            }
562        }
563    }
564
565    /// Property 4: Technology Recommendation Completeness
566    /// For any technology recommendation, it SHALL include use cases, pros, and cons
567    #[test]
568    fn property_technology_recommendation_completeness() {
569        let factory = AgentFactory::new();
570        let kb = KnowledgeBase::new();
571
572        // Create agent with technology recommendations
573        let config = create_agent_config_with_knowledge(
574            "web",
575            "Web Agent",
576            vec![("Framework", vec!["React", "Vue"])],
577            vec![
578                ("React", vec!["SPAs", "Complex UIs"]),
579                ("Vue", vec!["Progressive enhancement"]),
580            ],
581            vec![],
582            vec![],
583            vec![],
584        );
585
586        let agent = factory.create_agent("web", &config).unwrap();
587
588        for recommendation in &agent.knowledge.technology_recommendations {
589            kb.add_tech_recommendation("web", recommendation.clone()).unwrap();
590        }
591
592        // Property: All recommendations should be complete
593        let tech_recs = kb.get_tech_recommendations("web").unwrap();
594        for rec in &tech_recs {
595            // Must have use cases
596            assert!(!rec.use_cases.is_empty(), "Technology {} has no use cases", rec.technology);
597            // Must have pros
598            assert!(!rec.pros.is_empty(), "Technology {} has no pros", rec.technology);
599            // Must have cons
600            assert!(!rec.cons.is_empty(), "Technology {} has no cons", rec.technology);
601        }
602    }
603
604    /// Property 4: Best Practice Applicability
605    /// For any best practice, it SHALL be applicable to at least one technology
606    #[test]
607    fn property_best_practice_applicability() {
608        let factory = AgentFactory::new();
609        let kb = KnowledgeBase::new();
610
611        // Create agent with best practices
612        let config = create_agent_config_with_knowledge(
613            "web",
614            "Web Agent",
615            vec![("Framework", vec!["React"])],
616            vec![],
617            vec![
618                ("Component-Based Architecture", vec!["React", "Vue"]),
619                ("Performance Optimization", vec!["React"]),
620            ],
621            vec![],
622            vec![],
623        );
624
625        let agent = factory.create_agent("web", &config).unwrap();
626
627        for practice in &agent.knowledge.best_practices {
628            kb.add_best_practice("web", practice.clone()).unwrap();
629        }
630
631        // Property: All best practices should be applicable to at least one technology
632        let practices = kb.get_best_practices("web").unwrap();
633        for practice in &practices {
634            assert!(
635                !practice.technologies.is_empty(),
636                "Best practice {} has no applicable technologies",
637                practice.title
638            );
639        }
640    }
641
642    /// Property 4: Anti-Pattern Guidance
643    /// For any anti-pattern, it SHALL include why to avoid it and a better alternative
644    #[test]
645    fn property_anti_pattern_guidance() {
646        let factory = AgentFactory::new();
647        let kb = KnowledgeBase::new();
648
649        // Create agent with anti-patterns
650        let config = create_agent_config_with_knowledge(
651            "web",
652            "Web Agent",
653            vec![("Framework", vec!["React"])],
654            vec![],
655            vec![],
656            vec![],
657            vec![
658                ("God Component", "Component does too much"),
659                ("Tight Coupling", "Components are tightly coupled"),
660            ],
661        );
662
663        let agent = factory.create_agent("web", &config).unwrap();
664
665        for anti_pattern in &agent.knowledge.anti_patterns {
666            kb.add_anti_pattern("web", anti_pattern.clone()).unwrap();
667        }
668
669        // Property: All anti-patterns should have guidance
670        let anti_patterns = kb.get_anti_patterns("web").unwrap();
671        for anti_pattern in &anti_patterns {
672            assert!(
673                !anti_pattern.why_avoid.is_empty(),
674                "Anti-pattern {} has no guidance on why to avoid it",
675                anti_pattern.name
676            );
677            assert!(
678                !anti_pattern.better_alternative.is_empty(),
679                "Anti-pattern {} has no better alternative",
680                anti_pattern.name
681            );
682        }
683    }
684}