syncable_cli/analyzer/
framework_detector.rs

1use crate::analyzer::{AnalysisConfig, DetectedTechnology, DetectedLanguage, TechnologyCategory, LibraryType};
2use crate::error::Result;
3// Remove unused import
4use std::path::Path;
5use std::collections::HashMap;
6
7/// Technology detection rules with proper classification and relationships
8struct TechnologyRule {
9    name: String,
10    category: TechnologyCategory,
11    confidence: f32,
12    dependency_patterns: Vec<String>,
13    /// Dependencies this technology requires (e.g., Next.js requires React)
14    requires: Vec<String>,
15    /// Technologies that conflict with this one (mutually exclusive)
16    conflicts_with: Vec<String>,
17    /// Whether this technology typically drives the architecture
18    is_primary_indicator: bool,
19    /// Alternative names for this technology
20    alternative_names: Vec<String>,
21}
22
23/// Detects technologies (frameworks, libraries, tools) with proper classification
24pub fn detect_frameworks(
25    _project_root: &Path,
26    languages: &[DetectedLanguage],
27    _config: &AnalysisConfig,
28) -> Result<Vec<DetectedTechnology>> {
29    let mut all_technologies = Vec::new();
30    
31    for language in languages {
32        let lang_technologies = match language.name.as_str() {
33            "Rust" => detect_rust_technologies(language),
34            "JavaScript" | "TypeScript" | "JavaScript/TypeScript" => detect_js_technologies(language),
35            "Python" => detect_python_technologies(language),
36            "Go" => detect_go_technologies(language),
37            "Java" | "Kotlin" | "Java/Kotlin" => detect_jvm_technologies(language),
38            _ => Vec::new(),
39        };
40        all_technologies.extend(lang_technologies);
41    }
42    
43    // Apply exclusivity rules and resolve conflicts
44    let resolved_technologies = resolve_technology_conflicts(all_technologies);
45    
46    // Mark primary technologies
47    let final_technologies = mark_primary_technologies(resolved_technologies);
48    
49    // Sort by confidence and remove exact duplicates
50    let mut result = final_technologies;
51    result.sort_by(|a, b| b.confidence.partial_cmp(&a.confidence).unwrap_or(std::cmp::Ordering::Equal));
52    result.dedup_by(|a, b| a.name == b.name);
53    
54    Ok(result)
55}
56
57/// Detect Rust technologies with proper classification
58fn detect_rust_technologies(language: &DetectedLanguage) -> Vec<DetectedTechnology> {
59    let rules = get_rust_technology_rules();
60    
61    // Combine main and dev dependencies for comprehensive detection
62    let all_deps: Vec<String> = language.main_dependencies.iter()
63        .chain(language.dev_dependencies.iter())
64        .cloned()
65        .collect();
66    
67    detect_technologies_by_dependencies(&rules, &all_deps, language.confidence)
68}
69
70/// Detect JavaScript/TypeScript technologies with proper classification
71fn detect_js_technologies(language: &DetectedLanguage) -> Vec<DetectedTechnology> {
72    let rules = get_js_technology_rules();
73    
74    // Combine main and dev dependencies for comprehensive detection
75    let all_deps: Vec<String> = language.main_dependencies.iter()
76        .chain(language.dev_dependencies.iter())
77        .cloned()
78        .collect();
79    
80    let mut technologies = detect_technologies_by_dependencies(&rules, &all_deps, language.confidence);
81    
82    // Enhanced detection: analyze actual source files for usage patterns
83    if let Some(enhanced_techs) = detect_technologies_from_source_files(language, &rules) {
84        // Merge with dependency-based detection, preferring higher confidence scores
85        for enhanced_tech in enhanced_techs {
86            if let Some(existing) = technologies.iter_mut().find(|t| t.name == enhanced_tech.name) {
87                // Use higher confidence between dependency and source file analysis
88                if enhanced_tech.confidence > existing.confidence {
89                    existing.confidence = enhanced_tech.confidence;
90                }
91            } else {
92                // Add new technology found in source files
93                technologies.push(enhanced_tech);
94            }
95        }
96    }
97    
98    technologies
99}
100
101/// Detect Python technologies with proper classification
102fn detect_python_technologies(language: &DetectedLanguage) -> Vec<DetectedTechnology> {
103    let rules = get_python_technology_rules();
104    
105    // Combine main and dev dependencies for comprehensive detection
106    let all_deps: Vec<String> = language.main_dependencies.iter()
107        .chain(language.dev_dependencies.iter())
108        .cloned()
109        .collect();
110    
111    detect_technologies_by_dependencies(&rules, &all_deps, language.confidence)
112}
113
114/// Detect Go technologies with proper classification
115fn detect_go_technologies(language: &DetectedLanguage) -> Vec<DetectedTechnology> {
116    let rules = get_go_technology_rules();
117    
118    // Combine main and dev dependencies for comprehensive detection
119    let all_deps: Vec<String> = language.main_dependencies.iter()
120        .chain(language.dev_dependencies.iter())
121        .cloned()
122        .collect();
123    
124    detect_technologies_by_dependencies(&rules, &all_deps, language.confidence)
125}
126
127/// Detect JVM technologies with proper classification
128fn detect_jvm_technologies(language: &DetectedLanguage) -> Vec<DetectedTechnology> {
129    let rules = get_jvm_technology_rules();
130    
131    // Combine main and dev dependencies for comprehensive detection
132    let all_deps: Vec<String> = language.main_dependencies.iter()
133        .chain(language.dev_dependencies.iter())
134        .cloned()
135        .collect();
136    
137    detect_technologies_by_dependencies(&rules, &all_deps, language.confidence)
138}
139
140/// Generic technology detection based on dependency patterns
141fn detect_technologies_by_dependencies(
142    rules: &[TechnologyRule],
143    dependencies: &[String],
144    base_confidence: f32,
145) -> Vec<DetectedTechnology> {
146    let mut technologies = Vec::new();
147    
148    // Debug logging for Tanstack Start detection
149    let tanstack_deps: Vec<_> = dependencies.iter()
150        .filter(|dep| dep.contains("tanstack") || dep.contains("vinxi"))
151        .collect();
152    if !tanstack_deps.is_empty() {
153        log::debug!("Found potential Tanstack dependencies: {:?}", tanstack_deps);
154    }
155    
156    for rule in rules {
157        let mut matches = 0;
158        let total_patterns = rule.dependency_patterns.len();
159        
160        if total_patterns == 0 {
161            continue;
162        }
163        
164        for pattern in &rule.dependency_patterns {
165            let matching_deps: Vec<_> = dependencies.iter()
166                .filter(|dep| matches_pattern(dep, pattern))
167                .collect();
168                
169            if !matching_deps.is_empty() {
170                matches += 1;
171                
172                // Debug logging for Tanstack Start specifically
173                if rule.name.contains("Tanstack") {
174                    log::debug!("Tanstack Start: Pattern '{}' matched dependencies: {:?}", pattern, matching_deps);
175                }
176            }
177        }
178        
179        // Calculate confidence based on pattern matches and base language confidence
180        if matches > 0 {
181            let pattern_confidence = matches as f32 / total_patterns as f32;
182            let final_confidence = (rule.confidence * pattern_confidence * base_confidence).min(1.0);
183            
184            // Debug logging for Tanstack Start detection
185            if rule.name.contains("Tanstack") {
186                log::debug!("Tanstack Start detected with {} matches out of {} patterns, confidence: {:.2}", 
187                          matches, total_patterns, final_confidence);
188            }
189            
190            technologies.push(DetectedTechnology {
191                name: rule.name.clone(),
192                version: None, // TODO: Extract version from dependencies
193                category: rule.category.clone(),
194                confidence: final_confidence,
195                requires: rule.requires.clone(),
196                conflicts_with: rule.conflicts_with.clone(),
197                is_primary: rule.is_primary_indicator,
198            });
199        } else if rule.name.contains("Tanstack") {
200            // Debug logging when Tanstack Start is not detected
201            log::debug!("Tanstack Start not detected - no patterns matched. Available dependencies: {:?}", 
202                      dependencies.iter().take(10).collect::<Vec<_>>());
203        }
204    }
205    
206    technologies
207}
208
209/// Resolves conflicts between mutually exclusive technologies
210fn resolve_technology_conflicts(technologies: Vec<DetectedTechnology>) -> Vec<DetectedTechnology> {
211    let mut resolved = Vec::new();
212    let mut name_to_tech: HashMap<String, DetectedTechnology> = HashMap::new();
213    
214    // First pass: collect all technologies
215    for tech in technologies {
216        if let Some(existing) = name_to_tech.get(&tech.name) {
217            // Keep the one with higher confidence
218            if tech.confidence > existing.confidence {
219                name_to_tech.insert(tech.name.clone(), tech);
220            }
221        } else {
222            name_to_tech.insert(tech.name.clone(), tech);
223        }
224    }
225    
226    // Second pass: resolve conflicts
227    let all_techs: Vec<_> = name_to_tech.values().collect();
228    let mut excluded_names = std::collections::HashSet::new();
229    
230    for tech in &all_techs {
231        if excluded_names.contains(&tech.name) {
232            continue;
233        }
234        
235        // Check for conflicts
236        for conflict in &tech.conflicts_with {
237            if let Some(conflicting_tech) = name_to_tech.get(conflict) {
238                if tech.confidence > conflicting_tech.confidence {
239                    excluded_names.insert(conflict.clone());
240                    log::info!("Excluding {} (confidence: {}) in favor of {} (confidence: {})", 
241                              conflict, conflicting_tech.confidence, tech.name, tech.confidence);
242                } else {
243                    excluded_names.insert(tech.name.clone());
244                    log::info!("Excluding {} (confidence: {}) in favor of {} (confidence: {})", 
245                              tech.name, tech.confidence, conflict, conflicting_tech.confidence);
246                    break;
247                }
248            }
249        }
250    }
251    
252    // Collect non-excluded technologies
253    for tech in name_to_tech.into_values() {
254        if !excluded_names.contains(&tech.name) {
255            resolved.push(tech);
256        }
257    }
258    
259    resolved
260}
261
262/// Marks technologies that are primary drivers of the application architecture
263fn mark_primary_technologies(mut technologies: Vec<DetectedTechnology>) -> Vec<DetectedTechnology> {
264    // Meta-frameworks are always primary
265    let mut has_meta_framework = false;
266    for tech in &mut technologies {
267        if matches!(tech.category, TechnologyCategory::MetaFramework) {
268            tech.is_primary = true;
269            has_meta_framework = true;
270        }
271    }
272    
273    // If no meta-framework, mark the highest confidence backend or frontend framework as primary
274    if !has_meta_framework {
275        let mut best_framework: Option<usize> = None;
276        let mut best_confidence = 0.0;
277        
278        for (i, tech) in technologies.iter().enumerate() {
279            if matches!(tech.category, TechnologyCategory::BackendFramework | TechnologyCategory::FrontendFramework) {
280                if tech.confidence > best_confidence {
281                    best_confidence = tech.confidence;
282                    best_framework = Some(i);
283                }
284            }
285        }
286        
287        if let Some(index) = best_framework {
288            technologies[index].is_primary = true;
289        }
290    }
291    
292    technologies
293}
294
295/// Check if a dependency matches a pattern (supports wildcards)
296fn matches_pattern(dependency: &str, pattern: &str) -> bool {
297    if pattern.contains('*') {
298        // Simple wildcard matching
299        let parts: Vec<&str> = pattern.split('*').collect();
300        if parts.len() == 2 {
301            dependency.starts_with(parts[0]) && dependency.ends_with(parts[1])
302        } else {
303            dependency.contains(&pattern.replace('*', ""))
304        }
305    } else {
306        dependency == pattern || dependency.contains(pattern)
307    }
308}
309
310/// Enhanced detection that analyzes actual source files for technology usage patterns
311fn detect_technologies_from_source_files(language: &DetectedLanguage, rules: &[TechnologyRule]) -> Option<Vec<DetectedTechnology>> {
312    use std::fs;
313    
314    let mut detected = Vec::new();
315    
316    // Analyze files for usage patterns
317    for file_path in &language.files {
318        if let Ok(content) = fs::read_to_string(file_path) {
319            // Analyze Drizzle ORM usage patterns
320            if let Some(drizzle_confidence) = analyze_drizzle_usage(&content, file_path) {
321                detected.push(DetectedTechnology {
322                    name: "Drizzle ORM".to_string(),
323                    version: None,
324                    category: TechnologyCategory::Database,
325                    confidence: drizzle_confidence,
326                    requires: vec![],
327                    conflicts_with: vec![],
328                    is_primary: false,
329                });
330            }
331            
332            // Analyze Prisma usage patterns
333            if let Some(prisma_confidence) = analyze_prisma_usage(&content, file_path) {
334                detected.push(DetectedTechnology {
335                    name: "Prisma".to_string(),
336                    version: None,
337                    category: TechnologyCategory::Database,
338                    confidence: prisma_confidence,
339                    requires: vec![],
340                    conflicts_with: vec![],
341                    is_primary: false,
342                });
343            }
344            
345            // Analyze Encore usage patterns
346            if let Some(encore_confidence) = analyze_encore_usage(&content, file_path) {
347                detected.push(DetectedTechnology {
348                    name: "Encore".to_string(),
349                    version: None,
350                    category: TechnologyCategory::BackendFramework,
351                    confidence: encore_confidence,
352                    requires: vec![],
353                    conflicts_with: vec![],
354                    is_primary: true,
355                });
356            }
357            
358            // Analyze Tanstack Start usage patterns
359            if let Some(tanstack_confidence) = analyze_tanstack_start_usage(&content, file_path) {
360                detected.push(DetectedTechnology {
361                    name: "Tanstack Start".to_string(),
362                    version: None,
363                    category: TechnologyCategory::MetaFramework,
364                    confidence: tanstack_confidence,
365                    requires: vec!["React".to_string()],
366                    conflicts_with: vec!["Next.js".to_string(), "React Router v7".to_string(), "SvelteKit".to_string(), "Nuxt.js".to_string()],
367                    is_primary: true,
368                });
369            }
370        }
371    }
372    
373    if detected.is_empty() {
374        None
375    } else {
376        Some(detected)
377    }
378}
379
380/// Analyzes Drizzle ORM usage patterns in source files
381fn analyze_drizzle_usage(content: &str, file_path: &std::path::Path) -> Option<f32> {
382    let file_name = file_path.file_name()?.to_string_lossy();
383    let mut confidence: f32 = 0.0;
384    
385    // High confidence indicators
386    if content.contains("drizzle-orm") {
387        confidence += 0.3;
388    }
389    
390    // Schema file patterns (very high confidence)
391    if file_name.contains("schema") || file_name.contains("db.ts") || file_name.contains("database") {
392        if content.contains("pgTable") || content.contains("mysqlTable") || content.contains("sqliteTable") {
393            confidence += 0.4;
394        }
395        if content.contains("pgEnum") || content.contains("relations") {
396            confidence += 0.3;
397        }
398    }
399    
400    // Drizzle-specific imports
401    if content.contains("from 'drizzle-orm/pg-core'") || 
402       content.contains("from 'drizzle-orm/mysql-core'") ||
403       content.contains("from 'drizzle-orm/sqlite-core'") {
404        confidence += 0.3;
405    }
406    
407    // Drizzle query patterns
408    if content.contains("db.select()") || content.contains("db.insert()") || 
409       content.contains("db.update()") || content.contains("db.delete()") {
410        confidence += 0.2;
411    }
412    
413    // Configuration patterns
414    if content.contains("drizzle(") && (content.contains("connectionString") || content.contains("postgres(")) {
415        confidence += 0.2;
416    }
417    
418    // Migration patterns
419    if content.contains("drizzle.config") || file_name.contains("migrate") {
420        confidence += 0.2;
421    }
422    
423    // Prepared statements
424    if content.contains(".prepare()") && content.contains("drizzle") {
425        confidence += 0.1;
426    }
427    
428    if confidence > 0.0 {
429        Some(confidence.min(1.0_f32))
430    } else {
431        None
432    }
433}
434
435/// Analyzes Prisma usage patterns in source files
436fn analyze_prisma_usage(content: &str, file_path: &std::path::Path) -> Option<f32> {
437    let file_name = file_path.file_name()?.to_string_lossy();
438    let mut confidence: f32 = 0.0;
439    let mut has_prisma_import = false;
440    
441    // Only detect Prisma if there are actual Prisma-specific imports
442    if content.contains("@prisma/client") || content.contains("from '@prisma/client'") {
443        confidence += 0.4;
444        has_prisma_import = true;
445    }
446    
447    // Prisma schema files (very specific)
448    if file_name == "schema.prisma" {
449        if content.contains("model ") || content.contains("generator ") || content.contains("datasource ") {
450            confidence += 0.6;
451            has_prisma_import = true;
452        }
453    }
454    
455    // Only check for client usage if we have confirmed Prisma imports
456    if has_prisma_import {
457        // Prisma client instantiation (very specific)
458        if content.contains("new PrismaClient") || content.contains("PrismaClient()") {
459            confidence += 0.3;
460        }
461        
462        // Prisma-specific query patterns (only if we know it's Prisma)
463        if content.contains("prisma.") && (
464            content.contains(".findUnique(") || 
465            content.contains(".findFirst(") || 
466            content.contains(".upsert(") ||
467            content.contains(".$connect()") ||
468            content.contains(".$disconnect()")
469        ) {
470            confidence += 0.2;
471        }
472    }
473    
474    // Only return confidence if we have actual Prisma indicators
475    if confidence > 0.0 && has_prisma_import {
476        Some(confidence.min(1.0_f32))
477    } else {
478        None
479    }
480}
481
482/// Analyzes Encore usage patterns in source files
483fn analyze_encore_usage(content: &str, file_path: &std::path::Path) -> Option<f32> {
484    let file_name = file_path.file_name()?.to_string_lossy();
485    let mut confidence: f32 = 0.0;
486    
487    // Skip generated files (like Encore client code)
488    if content.contains("// Code generated by the Encore") || content.contains("DO NOT EDIT") {
489        return None;
490    }
491    
492    // Skip client-only files (generated or consumption only)
493    if file_name.contains("client.ts") || file_name.contains("client.js") {
494        return None;
495    }
496    
497    // Only detect Encore when there are actual service development patterns
498    let mut has_service_patterns = false;
499    
500    // Service definition files (high confidence for actual Encore development)
501    if file_name.contains("encore.service") || file_name.contains("service.ts") {
502        confidence += 0.4;
503        has_service_patterns = true;
504    }
505    
506    // API endpoint definitions (indicates actual Encore service development)
507    if content.contains("encore.dev/api") && (content.contains("export") || content.contains("api.")) {
508        confidence += 0.4;
509        has_service_patterns = true;
510    }
511    
512    // Database service patterns (actual Encore service code)
513    if content.contains("SQLDatabase") && content.contains("encore.dev") {
514        confidence += 0.3;
515        has_service_patterns = true;
516    }
517    
518    // Secret configuration (actual Encore service code)
519    if content.contains("secret(") && content.contains("encore.dev/config") {
520        confidence += 0.3;
521        has_service_patterns = true;
522    }
523    
524    // PubSub service patterns (actual Encore service code)
525    if content.contains("Topic") && content.contains("encore.dev/pubsub") {
526        confidence += 0.3;
527        has_service_patterns = true;
528    }
529    
530    // Cron job patterns (actual Encore service code)
531    if content.contains("cron") && content.contains("encore.dev") {
532        confidence += 0.2;
533        has_service_patterns = true;
534    }
535    
536    // Only return confidence if we have actual service development patterns
537    if confidence > 0.0 && has_service_patterns {
538        Some(confidence.min(1.0_f32))
539    } else {
540        None
541    }
542}
543
544/// Analyzes Tanstack Start usage patterns in source files
545fn analyze_tanstack_start_usage(content: &str, file_path: &std::path::Path) -> Option<f32> {
546    let file_name = file_path.file_name()?.to_string_lossy();
547    let mut confidence: f32 = 0.0;
548    let mut has_start_patterns = false;
549    
550    // Configuration files (high confidence)
551    if file_name == "app.config.ts" || file_name == "app.config.js" {
552        if content.contains("@tanstack/react-start") || content.contains("tanstack") {
553            confidence += 0.5;
554            has_start_patterns = true;
555        }
556    }
557    
558    // Router configuration patterns (very high confidence)
559    if file_name.contains("router.") && (file_name.ends_with(".ts") || file_name.ends_with(".tsx")) {
560        if content.contains("createRouter") && content.contains("@tanstack/react-router") {
561            confidence += 0.4;
562            has_start_patterns = true;
563        }
564        if content.contains("routeTree") {
565            confidence += 0.2;
566            has_start_patterns = true;
567        }
568    }
569    
570    // Server entry point patterns
571    if file_name == "ssr.tsx" || file_name == "ssr.ts" {
572        if content.contains("createStartHandler") || content.contains("@tanstack/react-start/server") {
573            confidence += 0.5;
574            has_start_patterns = true;
575        }
576    }
577    
578    // Client entry point patterns
579    if file_name == "client.tsx" || file_name == "client.ts" {
580        if content.contains("StartClient") && content.contains("@tanstack/react-start") {
581            confidence += 0.5;
582            has_start_patterns = true;
583        }
584        if content.contains("hydrateRoot") && content.contains("createRouter") {
585            confidence += 0.3;
586            has_start_patterns = true;
587        }
588    }
589    
590    // Root route patterns (in app/routes/__root.tsx)
591    if file_name == "__root.tsx" || file_name == "__root.ts" {
592        if content.contains("createRootRoute") && content.contains("@tanstack/react-router") {
593            confidence += 0.4;
594            has_start_patterns = true;
595        }
596        if content.contains("HeadContent") && content.contains("Scripts") {
597            confidence += 0.3;
598            has_start_patterns = true;
599        }
600    }
601    
602    // Route files with createFileRoute
603    if file_path.to_string_lossy().contains("routes/") {
604        if content.contains("createFileRoute") && content.contains("@tanstack/react-router") {
605            confidence += 0.3;
606            has_start_patterns = true;
607        }
608    }
609    
610    // Server functions (key Tanstack Start feature)
611    if content.contains("createServerFn") && content.contains("@tanstack/react-start") {
612        confidence += 0.4;
613        has_start_patterns = true;
614    }
615    
616    // Import patterns specific to Tanstack Start
617    if content.contains("from '@tanstack/react-start'") {
618        confidence += 0.3;
619        has_start_patterns = true;
620    }
621    
622    // Vinxi configuration patterns
623    if file_name == "vinxi.config.ts" || file_name == "vinxi.config.js" {
624        confidence += 0.2;
625        has_start_patterns = true;
626    }
627    
628    // Only return confidence if we have actual Tanstack Start patterns
629    if confidence > 0.0 && has_start_patterns {
630        Some(confidence.min(1.0_f32))
631    } else {
632        None
633    }
634}
635
636/// JavaScript/TypeScript technology detection rules with proper classification
637fn get_js_technology_rules() -> Vec<TechnologyRule> {
638    vec![
639        // META-FRAMEWORKS (Mutually Exclusive)
640        TechnologyRule {
641            name: "Next.js".to_string(),
642            category: TechnologyCategory::MetaFramework,
643            confidence: 0.95,
644            dependency_patterns: vec!["next".to_string()],
645            requires: vec!["React".to_string()],
646            conflicts_with: vec!["Tanstack Start".to_string(), "React Router v7".to_string(), "SvelteKit".to_string(), "Nuxt.js".to_string()],
647            is_primary_indicator: true,
648            alternative_names: vec!["nextjs".to_string()],
649        },
650        TechnologyRule {
651            name: "Tanstack Start".to_string(),
652            category: TechnologyCategory::MetaFramework,
653            confidence: 0.95,
654            dependency_patterns: vec!["@tanstack/react-start".to_string()],
655            requires: vec!["React".to_string()],
656            conflicts_with: vec!["Next.js".to_string(), "React Router v7".to_string(), "SvelteKit".to_string(), "Nuxt.js".to_string()],
657            is_primary_indicator: true,
658            alternative_names: vec!["tanstack-start".to_string(), "TanStack Start".to_string()],
659        },
660        TechnologyRule {
661            name: "React Router v7".to_string(),
662            category: TechnologyCategory::MetaFramework,
663            confidence: 0.95,
664            dependency_patterns: vec!["react-router".to_string(), "@remix-run/react".to_string()],
665            requires: vec!["React".to_string()],
666            conflicts_with: vec!["Next.js".to_string(), "Tanstack Start".to_string(), "SvelteKit".to_string(), "Nuxt.js".to_string()],
667            is_primary_indicator: true,
668            alternative_names: vec!["remix".to_string(), "react-router".to_string()],
669        },
670        TechnologyRule {
671            name: "SvelteKit".to_string(),
672            category: TechnologyCategory::MetaFramework,
673            confidence: 0.95,
674            dependency_patterns: vec!["@sveltejs/kit".to_string()],
675            requires: vec!["Svelte".to_string()],
676            conflicts_with: vec!["Next.js".to_string(), "Tanstack Start".to_string(), "React Router v7".to_string(), "Nuxt.js".to_string()],
677            is_primary_indicator: true,
678            alternative_names: vec!["svelte-kit".to_string()],
679        },
680        TechnologyRule {
681            name: "Nuxt.js".to_string(),
682            category: TechnologyCategory::MetaFramework,
683            confidence: 0.95,
684            dependency_patterns: vec!["nuxt".to_string(), "@nuxt/core".to_string()],
685            requires: vec!["Vue.js".to_string()],
686            conflicts_with: vec!["Next.js".to_string(), "Tanstack Start".to_string(), "React Router v7".to_string(), "SvelteKit".to_string()],
687            is_primary_indicator: true,
688            alternative_names: vec!["nuxtjs".to_string()],
689        },
690        TechnologyRule {
691            name: "Astro".to_string(),
692            category: TechnologyCategory::MetaFramework,
693            confidence: 0.95,
694            dependency_patterns: vec!["astro".to_string()],
695            requires: vec![],
696            conflicts_with: vec![],
697            is_primary_indicator: true,
698            alternative_names: vec![],
699        },
700        TechnologyRule {
701            name: "SolidStart".to_string(),
702            category: TechnologyCategory::MetaFramework,
703            confidence: 0.95,
704            dependency_patterns: vec!["solid-start".to_string()],
705            requires: vec!["SolidJS".to_string()],
706            conflicts_with: vec!["Next.js".to_string(), "Tanstack Start".to_string(), "React Router v7".to_string(), "SvelteKit".to_string()],
707            is_primary_indicator: true,
708            alternative_names: vec![],
709        },
710        
711        // FRONTEND FRAMEWORKS (Provide structure)
712        TechnologyRule {
713            name: "Angular".to_string(),
714            category: TechnologyCategory::FrontendFramework,
715            confidence: 0.90,
716            dependency_patterns: vec!["@angular/core".to_string()],
717            requires: vec![],
718            conflicts_with: vec![],
719            is_primary_indicator: true,
720            alternative_names: vec!["angular".to_string()],
721        },
722        TechnologyRule {
723            name: "Svelte".to_string(),
724            category: TechnologyCategory::FrontendFramework,
725            confidence: 0.95,
726            dependency_patterns: vec!["svelte".to_string()],
727            requires: vec![],
728            conflicts_with: vec![],
729            is_primary_indicator: false, // SvelteKit would be primary
730            alternative_names: vec![],
731        },
732        
733        // UI LIBRARIES (Not frameworks!)
734        TechnologyRule {
735            name: "React".to_string(),
736            category: TechnologyCategory::Library(LibraryType::UI),
737            confidence: 0.90,
738            dependency_patterns: vec!["react".to_string()],
739            requires: vec![],
740            conflicts_with: vec![],
741            is_primary_indicator: false, // Meta-frameworks using React would be primary
742            alternative_names: vec!["reactjs".to_string()],
743        },
744        TechnologyRule {
745            name: "Vue.js".to_string(),
746            category: TechnologyCategory::Library(LibraryType::UI),
747            confidence: 0.90,
748            dependency_patterns: vec!["vue".to_string()],
749            requires: vec![],
750            conflicts_with: vec![],
751            is_primary_indicator: false,
752            alternative_names: vec!["vuejs".to_string()],
753        },
754        TechnologyRule {
755            name: "SolidJS".to_string(),
756            category: TechnologyCategory::Library(LibraryType::UI),
757            confidence: 0.95,
758            dependency_patterns: vec!["solid-js".to_string()],
759            requires: vec![],
760            conflicts_with: vec![],
761            is_primary_indicator: false,
762            alternative_names: vec!["solid".to_string()],
763        },
764        TechnologyRule {
765            name: "HTMX".to_string(),
766            category: TechnologyCategory::Library(LibraryType::UI),
767            confidence: 0.95,
768            dependency_patterns: vec!["htmx.org".to_string()],
769            requires: vec![],
770            conflicts_with: vec![],
771            is_primary_indicator: false,
772            alternative_names: vec!["htmx".to_string()],
773        },
774        
775        // Note: Removed utility libraries (Tanstack Query, Tanstack Router, state management)
776        // as they don't provide value for IaC generation decisions
777        
778        // BACKEND FRAMEWORKS
779        TechnologyRule {
780            name: "Express.js".to_string(),
781            category: TechnologyCategory::BackendFramework,
782            confidence: 0.95,
783            dependency_patterns: vec!["express".to_string()],
784            requires: vec![],
785            conflicts_with: vec![],
786            is_primary_indicator: true,
787            alternative_names: vec!["express".to_string()],
788        },
789        TechnologyRule {
790            name: "Fastify".to_string(),
791            category: TechnologyCategory::BackendFramework,
792            confidence: 0.95,
793            dependency_patterns: vec!["fastify".to_string()],
794            requires: vec![],
795            conflicts_with: vec![],
796            is_primary_indicator: true,
797            alternative_names: vec![],
798        },
799        TechnologyRule {
800            name: "Nest.js".to_string(),
801            category: TechnologyCategory::BackendFramework,
802            confidence: 0.95,
803            dependency_patterns: vec!["@nestjs/core".to_string()],
804            requires: vec![],
805            conflicts_with: vec![],
806            is_primary_indicator: true,
807            alternative_names: vec!["nestjs".to_string()],
808        },
809        TechnologyRule {
810            name: "Hono".to_string(),
811            category: TechnologyCategory::BackendFramework,
812            confidence: 0.95,
813            dependency_patterns: vec!["hono".to_string()],
814            requires: vec![],
815            conflicts_with: vec![],
816            is_primary_indicator: true,
817            alternative_names: vec![],
818        },
819        TechnologyRule {
820            name: "Elysia".to_string(),
821            category: TechnologyCategory::BackendFramework,
822            confidence: 0.95,
823            dependency_patterns: vec!["elysia".to_string()],
824            requires: vec![],
825            conflicts_with: vec![],
826            is_primary_indicator: true,
827            alternative_names: vec![],
828        },
829        TechnologyRule {
830            name: "Encore".to_string(),
831            category: TechnologyCategory::BackendFramework,
832            confidence: 0.95,
833            dependency_patterns: vec!["encore.dev".to_string(), "encore".to_string()],
834            requires: vec![],
835            conflicts_with: vec![],
836            is_primary_indicator: true,
837            alternative_names: vec!["encore-ts-starter".to_string()],
838        },
839        
840        // BUILD TOOLS (Not frameworks!)
841        TechnologyRule {
842            name: "Vite".to_string(),
843            category: TechnologyCategory::BuildTool,
844            confidence: 0.80,
845            dependency_patterns: vec!["vite".to_string()],
846            requires: vec![],
847            conflicts_with: vec![],
848            is_primary_indicator: false,
849            alternative_names: vec![],
850        },
851        TechnologyRule {
852            name: "Webpack".to_string(),
853            category: TechnologyCategory::BuildTool,
854            confidence: 0.80,
855            dependency_patterns: vec!["webpack".to_string()],
856            requires: vec![],
857            conflicts_with: vec![],
858            is_primary_indicator: false,
859            alternative_names: vec![],
860        },
861        
862        // DATABASE/ORM (Important for Docker/infrastructure setup, migrations, etc.)
863        TechnologyRule {
864            name: "Prisma".to_string(),
865            category: TechnologyCategory::Database,
866            confidence: 0.90,
867            dependency_patterns: vec!["prisma".to_string(), "@prisma/client".to_string()],
868            requires: vec![],
869            conflicts_with: vec![],
870            is_primary_indicator: false,
871            alternative_names: vec![],
872        },
873        TechnologyRule {
874            name: "Drizzle ORM".to_string(),
875            category: TechnologyCategory::Database,
876            confidence: 0.90,
877            dependency_patterns: vec!["drizzle-orm".to_string(), "drizzle-kit".to_string()],
878            requires: vec![],
879            conflicts_with: vec![],
880            is_primary_indicator: false,
881            alternative_names: vec!["drizzle".to_string()],
882        },
883        
884        // RUNTIMES (Important for IaC - determines base images, package managers)
885        TechnologyRule {
886            name: "Node.js".to_string(),
887            category: TechnologyCategory::Runtime,
888            confidence: 0.90,
889            dependency_patterns: vec!["node".to_string()], // This will need file-based detection
890            requires: vec![],
891            conflicts_with: vec![],
892            is_primary_indicator: false,
893            alternative_names: vec!["nodejs".to_string()],
894        },
895        TechnologyRule {
896            name: "Bun".to_string(),
897            category: TechnologyCategory::Runtime,
898            confidence: 0.95,
899            dependency_patterns: vec!["bun".to_string()], // Look for bun in devDependencies or bun.lockb file
900            requires: vec![],
901            conflicts_with: vec![],
902            is_primary_indicator: false,
903            alternative_names: vec![],
904        },
905        TechnologyRule {
906            name: "Deno".to_string(),
907            category: TechnologyCategory::Runtime,
908            confidence: 0.95,
909            dependency_patterns: vec!["@deno/core".to_string(), "deno".to_string()],
910            requires: vec![],
911            conflicts_with: vec![],
912            is_primary_indicator: false,
913            alternative_names: vec![],
914        },
915        
916        // TESTING (Keep minimal - only major frameworks that affect build process)
917        TechnologyRule {
918            name: "Jest".to_string(),
919            category: TechnologyCategory::Testing,
920            confidence: 0.85,
921            dependency_patterns: vec!["jest".to_string()],
922            requires: vec![],
923            conflicts_with: vec![],
924            is_primary_indicator: false,
925            alternative_names: vec![],
926        },
927        TechnologyRule {
928            name: "Vitest".to_string(),
929            category: TechnologyCategory::Testing,
930            confidence: 0.85,
931            dependency_patterns: vec!["vitest".to_string()],
932            requires: vec![],
933            conflicts_with: vec![],
934            is_primary_indicator: false,
935            alternative_names: vec![],
936        },
937    ]
938}
939
940/// Rust technology detection rules with comprehensive framework coverage
941fn get_rust_technology_rules() -> Vec<TechnologyRule> {
942    vec![
943        // WEB FRAMEWORKS
944        TechnologyRule {
945            name: "Actix Web".to_string(),
946            category: TechnologyCategory::BackendFramework,
947            confidence: 0.95,
948            dependency_patterns: vec!["actix-web".to_string()],
949            requires: vec![],
950            conflicts_with: vec![],
951            is_primary_indicator: true,
952            alternative_names: vec!["actix".to_string()],
953        },
954        TechnologyRule {
955            name: "Axum".to_string(),
956            category: TechnologyCategory::BackendFramework,
957            confidence: 0.95,
958            dependency_patterns: vec!["axum".to_string()],
959            requires: vec!["Tokio".to_string()],
960            conflicts_with: vec![],
961            is_primary_indicator: true,
962            alternative_names: vec![],
963        },
964        TechnologyRule {
965            name: "Rocket".to_string(),
966            category: TechnologyCategory::BackendFramework,
967            confidence: 0.95,
968            dependency_patterns: vec!["rocket".to_string()],
969            requires: vec![],
970            conflicts_with: vec![],
971            is_primary_indicator: true,
972            alternative_names: vec![],
973        },
974        TechnologyRule {
975            name: "Warp".to_string(),
976            category: TechnologyCategory::BackendFramework,
977            confidence: 0.95,
978            dependency_patterns: vec!["warp".to_string()],
979            requires: vec!["Tokio".to_string()],
980            conflicts_with: vec![],
981            is_primary_indicator: true,
982            alternative_names: vec![],
983        },
984        TechnologyRule {
985            name: "Loco".to_string(),
986            category: TechnologyCategory::BackendFramework,
987            confidence: 0.95,
988            dependency_patterns: vec!["loco-rs".to_string()],
989            requires: vec![],
990            conflicts_with: vec![],
991            is_primary_indicator: true,
992            alternative_names: vec!["loco".to_string()],
993        },
994        TechnologyRule {
995            name: "Poem".to_string(),
996            category: TechnologyCategory::BackendFramework,
997            confidence: 0.95,
998            dependency_patterns: vec!["poem".to_string()],
999            requires: vec![],
1000            conflicts_with: vec![],
1001            is_primary_indicator: true,
1002            alternative_names: vec![],
1003        },
1004        TechnologyRule {
1005            name: "Salvo".to_string(),
1006            category: TechnologyCategory::BackendFramework,
1007            confidence: 0.95,
1008            dependency_patterns: vec!["salvo".to_string()],
1009            requires: vec![],
1010            conflicts_with: vec![],
1011            is_primary_indicator: true,
1012            alternative_names: vec![],
1013        },
1014        TechnologyRule {
1015            name: "Trillium".to_string(),
1016            category: TechnologyCategory::BackendFramework,
1017            confidence: 0.95,
1018            dependency_patterns: vec!["trillium".to_string()],
1019            requires: vec!["Tokio".to_string()],
1020            conflicts_with: vec![],
1021            is_primary_indicator: true,
1022            alternative_names: vec![],
1023        },
1024        
1025        // ASYNC RUNTIMES
1026        TechnologyRule {
1027            name: "Tokio".to_string(),
1028            category: TechnologyCategory::Runtime,
1029            confidence: 0.90,
1030            dependency_patterns: vec!["tokio".to_string()],
1031            requires: vec![],
1032            conflicts_with: vec!["async-std".to_string()],
1033            is_primary_indicator: false,
1034            alternative_names: vec![],
1035        },
1036        TechnologyRule {
1037            name: "async-std".to_string(),
1038            category: TechnologyCategory::Runtime,
1039            confidence: 0.90,
1040            dependency_patterns: vec!["async-std".to_string()],
1041            requires: vec![],
1042            conflicts_with: vec!["Tokio".to_string()],
1043            is_primary_indicator: false,
1044            alternative_names: vec![],
1045        },
1046        
1047        // DATABASE/ORM
1048        TechnologyRule {
1049            name: "SeaORM".to_string(),
1050            category: TechnologyCategory::Database,
1051            confidence: 0.90,
1052            dependency_patterns: vec!["sea-orm".to_string()],
1053            requires: vec![],
1054            conflicts_with: vec![],
1055            is_primary_indicator: false,
1056            alternative_names: vec!["sea_orm".to_string()],
1057        },
1058        TechnologyRule {
1059            name: "Diesel".to_string(),
1060            category: TechnologyCategory::Database,
1061            confidence: 0.90,
1062            dependency_patterns: vec!["diesel".to_string()],
1063            requires: vec![],
1064            conflicts_with: vec![],
1065            is_primary_indicator: false,
1066            alternative_names: vec![],
1067        },
1068        TechnologyRule {
1069            name: "SQLx".to_string(),
1070            category: TechnologyCategory::Database,
1071            confidence: 0.90,
1072            dependency_patterns: vec!["sqlx".to_string()],
1073            requires: vec![],
1074            conflicts_with: vec![],
1075            is_primary_indicator: false,
1076            alternative_names: vec![],
1077        },
1078        
1079        // SERIALIZATION
1080        TechnologyRule {
1081            name: "Serde".to_string(),
1082            category: TechnologyCategory::Library(LibraryType::Utility),
1083            confidence: 0.85,
1084            dependency_patterns: vec!["serde".to_string()],
1085            requires: vec![],
1086            conflicts_with: vec![],
1087            is_primary_indicator: false,
1088            alternative_names: vec![],
1089        },
1090        
1091        // TESTING
1092        TechnologyRule {
1093            name: "Criterion".to_string(),
1094            category: TechnologyCategory::Testing,
1095            confidence: 0.85,
1096            dependency_patterns: vec!["criterion".to_string()],
1097            requires: vec![],
1098            conflicts_with: vec![],
1099            is_primary_indicator: false,
1100            alternative_names: vec![],
1101        },
1102        
1103        // GUI FRAMEWORKS (WASM/Desktop)
1104        TechnologyRule {
1105            name: "Leptos".to_string(),
1106            category: TechnologyCategory::FrontendFramework,
1107            confidence: 0.95,
1108            dependency_patterns: vec!["leptos".to_string()],
1109            requires: vec![],
1110            conflicts_with: vec!["Yew".to_string(), "Dioxus".to_string()],
1111            is_primary_indicator: true,
1112            alternative_names: vec![],
1113        },
1114        TechnologyRule {
1115            name: "Yew".to_string(),
1116            category: TechnologyCategory::FrontendFramework,
1117            confidence: 0.95,
1118            dependency_patterns: vec!["yew".to_string()],
1119            requires: vec![],
1120            conflicts_with: vec!["Leptos".to_string(), "Dioxus".to_string()],
1121            is_primary_indicator: true,
1122            alternative_names: vec![],
1123        },
1124        TechnologyRule {
1125            name: "Dioxus".to_string(),
1126            category: TechnologyCategory::FrontendFramework,
1127            confidence: 0.95,
1128            dependency_patterns: vec!["dioxus".to_string()],
1129            requires: vec![],
1130            conflicts_with: vec!["Leptos".to_string(), "Yew".to_string()],
1131            is_primary_indicator: true,
1132            alternative_names: vec![],
1133        },
1134        TechnologyRule {
1135            name: "Tauri".to_string(),
1136            category: TechnologyCategory::Library(LibraryType::UI),
1137            confidence: 0.95,
1138            dependency_patterns: vec!["tauri".to_string()],
1139            requires: vec![],
1140            conflicts_with: vec![],
1141            is_primary_indicator: true,
1142            alternative_names: vec![],
1143        },
1144        TechnologyRule {
1145            name: "egui".to_string(),
1146            category: TechnologyCategory::Library(LibraryType::UI),
1147            confidence: 0.95,
1148            dependency_patterns: vec!["egui".to_string()],
1149            requires: vec![],
1150            conflicts_with: vec![],
1151            is_primary_indicator: false,
1152            alternative_names: vec![],
1153        },
1154    ]
1155}
1156
1157/// Python technology detection rules with comprehensive framework coverage
1158fn get_python_technology_rules() -> Vec<TechnologyRule> {
1159    vec![
1160        // WEB FRAMEWORKS - Full Stack
1161        TechnologyRule {
1162            name: "Django".to_string(),
1163            category: TechnologyCategory::BackendFramework,
1164            confidence: 0.95,
1165            dependency_patterns: vec!["django".to_string(), "Django".to_string()],
1166            requires: vec![],
1167            conflicts_with: vec![],
1168            is_primary_indicator: true,
1169            alternative_names: vec![],
1170        },
1171        TechnologyRule {
1172            name: "Django REST Framework".to_string(),
1173            category: TechnologyCategory::BackendFramework,
1174            confidence: 0.90,
1175            dependency_patterns: vec!["djangorestframework".to_string(), "rest_framework".to_string()],
1176            requires: vec!["Django".to_string()],
1177            conflicts_with: vec![],
1178            is_primary_indicator: false,
1179            alternative_names: vec!["DRF".to_string()],
1180        },
1181        
1182        // MICRO FRAMEWORKS
1183        TechnologyRule {
1184            name: "Flask".to_string(),
1185            category: TechnologyCategory::BackendFramework,
1186            confidence: 0.95,
1187            dependency_patterns: vec!["flask".to_string(), "Flask".to_string()],
1188            requires: vec![],
1189            conflicts_with: vec![],
1190            is_primary_indicator: true,
1191            alternative_names: vec![],
1192        },
1193        TechnologyRule {
1194            name: "FastAPI".to_string(),
1195            category: TechnologyCategory::BackendFramework,
1196            confidence: 0.95,
1197            dependency_patterns: vec!["fastapi".to_string()],
1198            requires: vec![],
1199            conflicts_with: vec![],
1200            is_primary_indicator: true,
1201            alternative_names: vec![],
1202        },
1203        TechnologyRule {
1204            name: "Starlette".to_string(),
1205            category: TechnologyCategory::BackendFramework,
1206            confidence: 0.90,
1207            dependency_patterns: vec!["starlette".to_string()],
1208            requires: vec![],
1209            conflicts_with: vec![],
1210            is_primary_indicator: true,
1211            alternative_names: vec![],
1212        },
1213        TechnologyRule {
1214            name: "Quart".to_string(),
1215            category: TechnologyCategory::BackendFramework,
1216            confidence: 0.90,
1217            dependency_patterns: vec!["quart".to_string()],
1218            requires: vec![],
1219            conflicts_with: vec![],
1220            is_primary_indicator: true,
1221            alternative_names: vec![],
1222        },
1223        TechnologyRule {
1224            name: "Sanic".to_string(),
1225            category: TechnologyCategory::BackendFramework,
1226            confidence: 0.90,
1227            dependency_patterns: vec!["sanic".to_string()],
1228            requires: vec![],
1229            conflicts_with: vec![],
1230            is_primary_indicator: true,
1231            alternative_names: vec![],
1232        },
1233        TechnologyRule {
1234            name: "Tornado".to_string(),
1235            category: TechnologyCategory::BackendFramework,
1236            confidence: 0.90,
1237            dependency_patterns: vec!["tornado".to_string()],
1238            requires: vec![],
1239            conflicts_with: vec![],
1240            is_primary_indicator: true,
1241            alternative_names: vec![],
1242        },
1243        TechnologyRule {
1244            name: "Falcon".to_string(),
1245            category: TechnologyCategory::BackendFramework,
1246            confidence: 0.90,
1247            dependency_patterns: vec!["falcon".to_string()],
1248            requires: vec![],
1249            conflicts_with: vec![],
1250            is_primary_indicator: true,
1251            alternative_names: vec![],
1252        },
1253        TechnologyRule {
1254            name: "Bottle".to_string(),
1255            category: TechnologyCategory::BackendFramework,
1256            confidence: 0.90,
1257            dependency_patterns: vec!["bottle".to_string()],
1258            requires: vec![],
1259            conflicts_with: vec![],
1260            is_primary_indicator: true,
1261            alternative_names: vec![],
1262        },
1263        TechnologyRule {
1264            name: "aiohttp".to_string(),
1265            category: TechnologyCategory::BackendFramework,
1266            confidence: 0.90,
1267            dependency_patterns: vec!["aiohttp".to_string()],
1268            requires: vec![],
1269            conflicts_with: vec![],
1270            is_primary_indicator: true,
1271            alternative_names: vec![],
1272        },
1273        
1274        // DATABASE/ORM
1275        TechnologyRule {
1276            name: "SQLAlchemy".to_string(),
1277            category: TechnologyCategory::Database,
1278            confidence: 0.90,
1279            dependency_patterns: vec!["sqlalchemy".to_string(), "SQLAlchemy".to_string()],
1280            requires: vec![],
1281            conflicts_with: vec![],
1282            is_primary_indicator: false,
1283            alternative_names: vec![],
1284        },
1285        TechnologyRule {
1286            name: "Peewee".to_string(),
1287            category: TechnologyCategory::Database,
1288            confidence: 0.90,
1289            dependency_patterns: vec!["peewee".to_string()],
1290            requires: vec![],
1291            conflicts_with: vec![],
1292            is_primary_indicator: false,
1293            alternative_names: vec![],
1294        },
1295        TechnologyRule {
1296            name: "Tortoise ORM".to_string(),
1297            category: TechnologyCategory::Database,
1298            confidence: 0.90,
1299            dependency_patterns: vec!["tortoise-orm".to_string()],
1300            requires: vec![],
1301            conflicts_with: vec![],
1302            is_primary_indicator: false,
1303            alternative_names: vec!["tortoise".to_string()],
1304        },
1305        TechnologyRule {
1306            name: "Django ORM".to_string(),
1307            category: TechnologyCategory::Database,
1308            confidence: 0.95,
1309            dependency_patterns: vec!["django.db".to_string()],
1310            requires: vec!["Django".to_string()],
1311            conflicts_with: vec![],
1312            is_primary_indicator: false,
1313            alternative_names: vec![],
1314        },
1315        
1316        // ASYNC FRAMEWORKS
1317        TechnologyRule {
1318            name: "asyncio".to_string(),
1319            category: TechnologyCategory::Runtime,
1320            confidence: 0.85,
1321            dependency_patterns: vec!["asyncio".to_string()],
1322            requires: vec![],
1323            conflicts_with: vec![],
1324            is_primary_indicator: false,
1325            alternative_names: vec![],
1326        },
1327        
1328        // DATA SCIENCE FRAMEWORKS (Important for containerization/deployment)
1329        TechnologyRule {
1330            name: "NumPy".to_string(),
1331            category: TechnologyCategory::Library(LibraryType::Utility),
1332            confidence: 0.85,
1333            dependency_patterns: vec!["numpy".to_string()],
1334            requires: vec![],
1335            conflicts_with: vec![],
1336            is_primary_indicator: false,
1337            alternative_names: vec![],
1338        },
1339        TechnologyRule {
1340            name: "Pandas".to_string(),
1341            category: TechnologyCategory::Library(LibraryType::Utility),
1342            confidence: 0.85,
1343            dependency_patterns: vec!["pandas".to_string()],
1344            requires: vec![],
1345            conflicts_with: vec![],
1346            is_primary_indicator: false,
1347            alternative_names: vec![],
1348        },
1349        TechnologyRule {
1350            name: "Scikit-learn".to_string(),
1351            category: TechnologyCategory::Library(LibraryType::Utility),
1352            confidence: 0.85,
1353            dependency_patterns: vec!["scikit-learn".to_string(), "sklearn".to_string()],
1354            requires: vec![],
1355            conflicts_with: vec![],
1356            is_primary_indicator: false,
1357            alternative_names: vec!["sklearn".to_string()],
1358        },
1359        TechnologyRule {
1360            name: "TensorFlow".to_string(),
1361            category: TechnologyCategory::Library(LibraryType::Utility),
1362            confidence: 0.90,
1363            dependency_patterns: vec!["tensorflow".to_string()],
1364            requires: vec![],
1365            conflicts_with: vec![],
1366            is_primary_indicator: false,
1367            alternative_names: vec![],
1368        },
1369        TechnologyRule {
1370            name: "PyTorch".to_string(),
1371            category: TechnologyCategory::Library(LibraryType::Utility),
1372            confidence: 0.90,
1373            dependency_patterns: vec!["torch".to_string(), "pytorch".to_string()],
1374            requires: vec![],
1375            conflicts_with: vec![],
1376            is_primary_indicator: false,
1377            alternative_names: vec!["torch".to_string()],
1378        },
1379        
1380        // TASK QUEUES
1381        TechnologyRule {
1382            name: "Celery".to_string(),
1383            category: TechnologyCategory::Library(LibraryType::Utility),
1384            confidence: 0.90,
1385            dependency_patterns: vec!["celery".to_string()],
1386            requires: vec![],
1387            conflicts_with: vec![],
1388            is_primary_indicator: false,
1389            alternative_names: vec![],
1390        },
1391        
1392        // TESTING
1393        TechnologyRule {
1394            name: "pytest".to_string(),
1395            category: TechnologyCategory::Testing,
1396            confidence: 0.85,
1397            dependency_patterns: vec!["pytest".to_string()],
1398            requires: vec![],
1399            conflicts_with: vec![],
1400            is_primary_indicator: false,
1401            alternative_names: vec![],
1402        },
1403        TechnologyRule {
1404            name: "unittest".to_string(),
1405            category: TechnologyCategory::Testing,
1406            confidence: 0.80,
1407            dependency_patterns: vec!["unittest".to_string()],
1408            requires: vec![],
1409            conflicts_with: vec![],
1410            is_primary_indicator: false,
1411            alternative_names: vec![],
1412        },
1413        
1414        // WSGI/ASGI SERVERS
1415        TechnologyRule {
1416            name: "Gunicorn".to_string(),
1417            category: TechnologyCategory::Runtime,
1418            confidence: 0.85,
1419            dependency_patterns: vec!["gunicorn".to_string()],
1420            requires: vec![],
1421            conflicts_with: vec![],
1422            is_primary_indicator: false,
1423            alternative_names: vec![],
1424        },
1425        TechnologyRule {
1426            name: "Uvicorn".to_string(),
1427            category: TechnologyCategory::Runtime,
1428            confidence: 0.85,
1429            dependency_patterns: vec!["uvicorn".to_string()],
1430            requires: vec![],
1431            conflicts_with: vec![],
1432            is_primary_indicator: false,
1433            alternative_names: vec![],
1434        },
1435    ]
1436}
1437
1438/// Go technology detection rules with comprehensive framework coverage
1439fn get_go_technology_rules() -> Vec<TechnologyRule> {
1440    vec![
1441        // WEB FRAMEWORKS
1442        TechnologyRule {
1443            name: "Gin".to_string(),
1444            category: TechnologyCategory::BackendFramework,
1445            confidence: 0.95,
1446            dependency_patterns: vec!["github.com/gin-gonic/gin".to_string(), "gin-gonic".to_string()],
1447            requires: vec![],
1448            conflicts_with: vec![],
1449            is_primary_indicator: true,
1450            alternative_names: vec!["gin-gonic".to_string()],
1451        },
1452        TechnologyRule {
1453            name: "Echo".to_string(),
1454            category: TechnologyCategory::BackendFramework,
1455            confidence: 0.95,
1456            dependency_patterns: vec!["github.com/labstack/echo".to_string(), "labstack/echo".to_string()],
1457            requires: vec![],
1458            conflicts_with: vec![],
1459            is_primary_indicator: true,
1460            alternative_names: vec!["labstack/echo".to_string()],
1461        },
1462        TechnologyRule {
1463            name: "Fiber".to_string(),
1464            category: TechnologyCategory::BackendFramework,
1465            confidence: 0.95,
1466            dependency_patterns: vec!["github.com/gofiber/fiber".to_string(), "gofiber".to_string()],
1467            requires: vec![],
1468            conflicts_with: vec![],
1469            is_primary_indicator: true,
1470            alternative_names: vec!["gofiber".to_string()],
1471        },
1472        TechnologyRule {
1473            name: "Beego".to_string(),
1474            category: TechnologyCategory::BackendFramework,
1475            confidence: 0.95,
1476            dependency_patterns: vec!["github.com/beego/beego".to_string(), "beego".to_string()],
1477            requires: vec![],
1478            conflicts_with: vec![],
1479            is_primary_indicator: true,
1480            alternative_names: vec![],
1481        },
1482        TechnologyRule {
1483            name: "Chi".to_string(),
1484            category: TechnologyCategory::BackendFramework,
1485            confidence: 0.90,
1486            dependency_patterns: vec!["github.com/go-chi/chi".to_string(), "go-chi".to_string()],
1487            requires: vec![],
1488            conflicts_with: vec![],
1489            is_primary_indicator: true,
1490            alternative_names: vec!["go-chi".to_string()],
1491        },
1492        TechnologyRule {
1493            name: "Gorilla Mux".to_string(),
1494            category: TechnologyCategory::BackendFramework,
1495            confidence: 0.90,
1496            dependency_patterns: vec!["github.com/gorilla/mux".to_string(), "gorilla/mux".to_string()],
1497            requires: vec![],
1498            conflicts_with: vec![],
1499            is_primary_indicator: true,
1500            alternative_names: vec!["mux".to_string(), "gorilla".to_string()],
1501        },
1502        TechnologyRule {
1503            name: "Revel".to_string(),
1504            category: TechnologyCategory::BackendFramework,
1505            confidence: 0.90,
1506            dependency_patterns: vec!["github.com/revel/revel".to_string(), "revel".to_string()],
1507            requires: vec![],
1508            conflicts_with: vec![],
1509            is_primary_indicator: true,
1510            alternative_names: vec![],
1511        },
1512        TechnologyRule {
1513            name: "Buffalo".to_string(),
1514            category: TechnologyCategory::BackendFramework,
1515            confidence: 0.90,
1516            dependency_patterns: vec!["github.com/gobuffalo/buffalo".to_string(), "gobuffalo".to_string()],
1517            requires: vec![],
1518            conflicts_with: vec![],
1519            is_primary_indicator: true,
1520            alternative_names: vec!["gobuffalo".to_string()],
1521        },
1522        TechnologyRule {
1523            name: "Iris".to_string(),
1524            category: TechnologyCategory::BackendFramework,
1525            confidence: 0.90,
1526            dependency_patterns: vec!["github.com/kataras/iris".to_string(), "kataras/iris".to_string()],
1527            requires: vec![],
1528            conflicts_with: vec![],
1529            is_primary_indicator: true,
1530            alternative_names: vec![],
1531        },
1532        TechnologyRule {
1533            name: "FastHTTP".to_string(),
1534            category: TechnologyCategory::BackendFramework,
1535            confidence: 0.95,
1536            dependency_patterns: vec!["github.com/valyala/fasthttp".to_string(), "fasthttp".to_string()],
1537            requires: vec![],
1538            conflicts_with: vec![],
1539            is_primary_indicator: true,
1540            alternative_names: vec!["valyala/fasthttp".to_string()],
1541        },
1542        TechnologyRule {
1543            name: "Hertz".to_string(),
1544            category: TechnologyCategory::BackendFramework,
1545            confidence: 0.95,
1546            dependency_patterns: vec!["github.com/cloudwego/hertz".to_string(), "cloudwego/hertz".to_string()],
1547            requires: vec![],
1548            conflicts_with: vec![],
1549            is_primary_indicator: true,
1550            alternative_names: vec!["cloudwego".to_string()],
1551        },
1552        
1553        // DATABASE/ORM
1554        TechnologyRule {
1555            name: "GORM".to_string(),
1556            category: TechnologyCategory::Database,
1557            confidence: 0.90,
1558            dependency_patterns: vec!["gorm.io/gorm".to_string(), "gorm".to_string()],
1559            requires: vec![],
1560            conflicts_with: vec![],
1561            is_primary_indicator: false,
1562            alternative_names: vec![],
1563        },
1564        TechnologyRule {
1565            name: "Ent".to_string(),
1566            category: TechnologyCategory::Database,
1567            confidence: 0.90,
1568            dependency_patterns: vec!["entgo.io/ent".to_string(), "facebook/ent".to_string()],
1569            requires: vec![],
1570            conflicts_with: vec![],
1571            is_primary_indicator: false,
1572            alternative_names: vec!["entgo".to_string()],
1573        },
1574        TechnologyRule {
1575            name: "Xorm".to_string(),
1576            category: TechnologyCategory::Database,
1577            confidence: 0.85,
1578            dependency_patterns: vec!["xorm.io/xorm".to_string(), "xorm".to_string()],
1579            requires: vec![],
1580            conflicts_with: vec![],
1581            is_primary_indicator: false,
1582            alternative_names: vec![],
1583        },
1584        
1585        // MICROSERVICES
1586        TechnologyRule {
1587            name: "Go Kit".to_string(),
1588            category: TechnologyCategory::Library(LibraryType::Utility),
1589            confidence: 0.90,
1590            dependency_patterns: vec!["github.com/go-kit/kit".to_string(), "go-kit".to_string()],
1591            requires: vec![],
1592            conflicts_with: vec![],
1593            is_primary_indicator: false,
1594            alternative_names: vec!["kit".to_string()],
1595        },
1596        TechnologyRule {
1597            name: "Kratos".to_string(),
1598            category: TechnologyCategory::BackendFramework,
1599            confidence: 0.90,
1600            dependency_patterns: vec!["github.com/go-kratos/kratos".to_string(), "go-kratos".to_string()],
1601            requires: vec![],
1602            conflicts_with: vec![],
1603            is_primary_indicator: true,
1604            alternative_names: vec!["go-kratos".to_string()],
1605        },
1606        
1607        // MESSAGE QUEUES
1608        TechnologyRule {
1609            name: "Sarama".to_string(),
1610            category: TechnologyCategory::Library(LibraryType::Utility),
1611            confidence: 0.85,
1612            dependency_patterns: vec!["github.com/shopify/sarama".to_string(), "sarama".to_string()],
1613            requires: vec![],
1614            conflicts_with: vec![],
1615            is_primary_indicator: false,
1616            alternative_names: vec!["shopify/sarama".to_string()],
1617        },
1618        
1619        // TESTING
1620        TechnologyRule {
1621            name: "Testify".to_string(),
1622            category: TechnologyCategory::Testing,
1623            confidence: 0.85,
1624            dependency_patterns: vec!["github.com/stretchr/testify".to_string(), "testify".to_string()],
1625            requires: vec![],
1626            conflicts_with: vec![],
1627            is_primary_indicator: false,
1628            alternative_names: vec!["stretchr/testify".to_string()],
1629        },
1630        TechnologyRule {
1631            name: "Ginkgo".to_string(),
1632            category: TechnologyCategory::Testing,
1633            confidence: 0.85,
1634            dependency_patterns: vec!["github.com/onsi/ginkgo".to_string(), "ginkgo".to_string()],
1635            requires: vec![],
1636            conflicts_with: vec![],
1637            is_primary_indicator: false,
1638            alternative_names: vec!["onsi/ginkgo".to_string()],
1639        },
1640        
1641        // CLI FRAMEWORKS
1642        TechnologyRule {
1643            name: "Cobra".to_string(),
1644            category: TechnologyCategory::Library(LibraryType::Utility),
1645            confidence: 0.85,
1646            dependency_patterns: vec!["github.com/spf13/cobra".to_string(), "cobra".to_string()],
1647            requires: vec![],
1648            conflicts_with: vec![],
1649            is_primary_indicator: false,
1650            alternative_names: vec!["spf13/cobra".to_string()],
1651        },
1652        
1653        // CONFIG MANAGEMENT
1654        TechnologyRule {
1655            name: "Viper".to_string(),
1656            category: TechnologyCategory::Library(LibraryType::Utility),
1657            confidence: 0.80,
1658            dependency_patterns: vec!["github.com/spf13/viper".to_string(), "viper".to_string()],
1659            requires: vec![],
1660            conflicts_with: vec![],
1661            is_primary_indicator: false,
1662            alternative_names: vec!["spf13/viper".to_string()],
1663        },
1664    ]
1665}
1666
1667/// Java/JVM technology detection rules with comprehensive framework coverage
1668fn get_jvm_technology_rules() -> Vec<TechnologyRule> {
1669    vec![
1670        // SPRING ECOSYSTEM
1671        TechnologyRule {
1672            name: "Spring Boot".to_string(),
1673            category: TechnologyCategory::BackendFramework,
1674            confidence: 0.95,
1675            dependency_patterns: vec!["spring-boot".to_string(), "org.springframework.boot".to_string()],
1676            requires: vec![],
1677            conflicts_with: vec![],
1678            is_primary_indicator: true,
1679            alternative_names: vec!["spring".to_string()],
1680        },
1681        TechnologyRule {
1682            name: "Spring Framework".to_string(),
1683            category: TechnologyCategory::BackendFramework,
1684            confidence: 0.90,
1685            dependency_patterns: vec!["spring-context".to_string(), "org.springframework".to_string()],
1686            requires: vec![],
1687            conflicts_with: vec![],
1688            is_primary_indicator: true,
1689            alternative_names: vec!["spring".to_string()],
1690        },
1691        TechnologyRule {
1692            name: "Spring Data".to_string(),
1693            category: TechnologyCategory::Database,
1694            confidence: 0.90,
1695            dependency_patterns: vec!["spring-data".to_string(), "org.springframework.data".to_string()],
1696            requires: vec!["Spring Framework".to_string()],
1697            conflicts_with: vec![],
1698            is_primary_indicator: false,
1699            alternative_names: vec![],
1700        },
1701        TechnologyRule {
1702            name: "Spring Security".to_string(),
1703            category: TechnologyCategory::Library(LibraryType::Utility),
1704            confidence: 0.90,
1705            dependency_patterns: vec!["spring-security".to_string(), "org.springframework.security".to_string()],
1706            requires: vec!["Spring Framework".to_string()],
1707            conflicts_with: vec![],
1708            is_primary_indicator: false,
1709            alternative_names: vec![],
1710        },
1711        TechnologyRule {
1712            name: "Spring Cloud".to_string(),
1713            category: TechnologyCategory::Library(LibraryType::Utility),
1714            confidence: 0.90,
1715            dependency_patterns: vec!["spring-cloud".to_string(), "org.springframework.cloud".to_string()],
1716            requires: vec!["Spring Boot".to_string()],
1717            conflicts_with: vec![],
1718            is_primary_indicator: false,
1719            alternative_names: vec![],
1720        },
1721        
1722        // MICROSERVICES FRAMEWORKS
1723        TechnologyRule {
1724            name: "Quarkus".to_string(),
1725            category: TechnologyCategory::BackendFramework,
1726            confidence: 0.95,
1727            dependency_patterns: vec!["quarkus".to_string(), "io.quarkus".to_string()],
1728            requires: vec![],
1729            conflicts_with: vec![],
1730            is_primary_indicator: true,
1731            alternative_names: vec![],
1732        },
1733        TechnologyRule {
1734            name: "Micronaut".to_string(),
1735            category: TechnologyCategory::BackendFramework,
1736            confidence: 0.95,
1737            dependency_patterns: vec!["micronaut".to_string(), "io.micronaut".to_string()],
1738            requires: vec![],
1739            conflicts_with: vec![],
1740            is_primary_indicator: true,
1741            alternative_names: vec![],
1742        },
1743        TechnologyRule {
1744            name: "Helidon".to_string(),
1745            category: TechnologyCategory::BackendFramework,
1746            confidence: 0.95,
1747            dependency_patterns: vec!["helidon".to_string(), "io.helidon".to_string()],
1748            requires: vec![],
1749            conflicts_with: vec![],
1750            is_primary_indicator: true,
1751            alternative_names: vec![],
1752        },
1753        TechnologyRule {
1754            name: "Vert.x".to_string(),
1755            category: TechnologyCategory::BackendFramework,
1756            confidence: 0.95,
1757            dependency_patterns: vec!["vertx".to_string(), "io.vertx".to_string()],
1758            requires: vec![],
1759            conflicts_with: vec![],
1760            is_primary_indicator: true,
1761            alternative_names: vec!["eclipse vert.x".to_string(), "vertx".to_string()],
1762        },
1763        
1764        // TRADITIONAL FRAMEWORKS
1765        TechnologyRule {
1766            name: "Struts".to_string(),
1767            category: TechnologyCategory::BackendFramework,
1768            confidence: 0.90,
1769            dependency_patterns: vec!["struts".to_string(), "org.apache.struts".to_string()],
1770            requires: vec![],
1771            conflicts_with: vec![],
1772            is_primary_indicator: true,
1773            alternative_names: vec!["apache struts".to_string()],
1774        },
1775        TechnologyRule {
1776            name: "JSF".to_string(),
1777            category: TechnologyCategory::BackendFramework,
1778            confidence: 0.85,
1779            dependency_patterns: vec!["jsf".to_string(), "javax.faces".to_string(), "jakarta.faces".to_string()],
1780            requires: vec![],
1781            conflicts_with: vec![],
1782            is_primary_indicator: true,
1783            alternative_names: vec!["javaserver faces".to_string()],
1784        },
1785        
1786        // LIGHTWEIGHT FRAMEWORKS
1787        TechnologyRule {
1788            name: "Dropwizard".to_string(),
1789            category: TechnologyCategory::BackendFramework,
1790            confidence: 0.90,
1791            dependency_patterns: vec!["dropwizard".to_string(), "io.dropwizard".to_string()],
1792            requires: vec![],
1793            conflicts_with: vec![],
1794            is_primary_indicator: true,
1795            alternative_names: vec![],
1796        },
1797        TechnologyRule {
1798            name: "Spark Java".to_string(),
1799            category: TechnologyCategory::BackendFramework,
1800            confidence: 0.90,
1801            dependency_patterns: vec!["spark-core".to_string(), "com.sparkjava".to_string()],
1802            requires: vec![],
1803            conflicts_with: vec![],
1804            is_primary_indicator: true,
1805            alternative_names: vec!["spark".to_string()],
1806        },
1807        TechnologyRule {
1808            name: "Javalin".to_string(),
1809            category: TechnologyCategory::BackendFramework,
1810            confidence: 0.90,
1811            dependency_patterns: vec!["javalin".to_string(), "io.javalin".to_string()],
1812            requires: vec![],
1813            conflicts_with: vec![],
1814            is_primary_indicator: true,
1815            alternative_names: vec![],
1816        },
1817        TechnologyRule {
1818            name: "Ratpack".to_string(),
1819            category: TechnologyCategory::BackendFramework,
1820            confidence: 0.90,
1821            dependency_patterns: vec!["ratpack".to_string(), "io.ratpack".to_string()],
1822            requires: vec![],
1823            conflicts_with: vec![],
1824            is_primary_indicator: true,
1825            alternative_names: vec![],
1826        },
1827        
1828        // PLAY FRAMEWORK
1829        TechnologyRule {
1830            name: "Play Framework".to_string(),
1831            category: TechnologyCategory::BackendFramework,
1832            confidence: 0.95,
1833            dependency_patterns: vec!["play".to_string(), "com.typesafe.play".to_string()],
1834            requires: vec![],
1835            conflicts_with: vec![],
1836            is_primary_indicator: true,
1837            alternative_names: vec!["play".to_string()],
1838        },
1839        
1840        // ORM/DATABASE
1841        TechnologyRule {
1842            name: "Hibernate".to_string(),
1843            category: TechnologyCategory::Database,
1844            confidence: 0.90,
1845            dependency_patterns: vec!["hibernate".to_string(), "org.hibernate".to_string()],
1846            requires: vec![],
1847            conflicts_with: vec![],
1848            is_primary_indicator: false,
1849            alternative_names: vec!["hibernate orm".to_string()],
1850        },
1851        TechnologyRule {
1852            name: "MyBatis".to_string(),
1853            category: TechnologyCategory::Database,
1854            confidence: 0.90,
1855            dependency_patterns: vec!["mybatis".to_string(), "org.mybatis".to_string()],
1856            requires: vec![],
1857            conflicts_with: vec![],
1858            is_primary_indicator: false,
1859            alternative_names: vec![],
1860        },
1861        TechnologyRule {
1862            name: "JOOQ".to_string(),
1863            category: TechnologyCategory::Database,
1864            confidence: 0.85,
1865            dependency_patterns: vec!["jooq".to_string(), "org.jooq".to_string()],
1866            requires: vec![],
1867            conflicts_with: vec![],
1868            is_primary_indicator: false,
1869            alternative_names: vec![],
1870        },
1871        
1872        // ENTERPRISE JAVA
1873        TechnologyRule {
1874            name: "Jakarta EE".to_string(),
1875            category: TechnologyCategory::BackendFramework,
1876            confidence: 0.90,
1877            dependency_patterns: vec!["jakarta.".to_string(), "jakarta-ee".to_string()],
1878            requires: vec![],
1879            conflicts_with: vec![],
1880            is_primary_indicator: true,
1881            alternative_names: vec!["java ee".to_string()],
1882        },
1883        
1884        // BUILD TOOLS
1885        TechnologyRule {
1886            name: "Maven".to_string(),
1887            category: TechnologyCategory::BuildTool,
1888            confidence: 0.80,
1889            dependency_patterns: vec!["maven".to_string(), "org.apache.maven".to_string()],
1890            requires: vec![],
1891            conflicts_with: vec![],
1892            is_primary_indicator: false,
1893            alternative_names: vec!["apache maven".to_string()],
1894        },
1895        TechnologyRule {
1896            name: "Gradle".to_string(),
1897            category: TechnologyCategory::BuildTool,
1898            confidence: 0.80,
1899            dependency_patterns: vec!["gradle".to_string(), "org.gradle".to_string()],
1900            requires: vec![],
1901            conflicts_with: vec![],
1902            is_primary_indicator: false,
1903            alternative_names: vec![],
1904        },
1905        
1906        // TESTING
1907        TechnologyRule {
1908            name: "JUnit".to_string(),
1909            category: TechnologyCategory::Testing,
1910            confidence: 0.85,
1911            dependency_patterns: vec!["junit".to_string(), "org.junit".to_string()],
1912            requires: vec![],
1913            conflicts_with: vec![],
1914            is_primary_indicator: false,
1915            alternative_names: vec![],
1916        },
1917        TechnologyRule {
1918            name: "TestNG".to_string(),
1919            category: TechnologyCategory::Testing,
1920            confidence: 0.85,
1921            dependency_patterns: vec!["testng".to_string(), "org.testng".to_string()],
1922            requires: vec![],
1923            conflicts_with: vec![],
1924            is_primary_indicator: false,
1925            alternative_names: vec![],
1926        },
1927        TechnologyRule {
1928            name: "Mockito".to_string(),
1929            category: TechnologyCategory::Testing,
1930            confidence: 0.80,
1931            dependency_patterns: vec!["mockito".to_string(), "org.mockito".to_string()],
1932            requires: vec![],
1933            conflicts_with: vec![],
1934            is_primary_indicator: false,
1935            alternative_names: vec![],
1936        },
1937        
1938        // REACTIVE FRAMEWORKS
1939        TechnologyRule {
1940            name: "Reactor".to_string(),
1941            category: TechnologyCategory::Library(LibraryType::Utility),
1942            confidence: 0.85,
1943            dependency_patterns: vec!["reactor".to_string(), "io.projectreactor".to_string()],
1944            requires: vec![],
1945            conflicts_with: vec![],
1946            is_primary_indicator: false,
1947            alternative_names: vec!["project reactor".to_string()],
1948        },
1949        TechnologyRule {
1950            name: "RxJava".to_string(),
1951            category: TechnologyCategory::Library(LibraryType::Utility),
1952            confidence: 0.85,
1953            dependency_patterns: vec!["rxjava".to_string(), "io.reactivex".to_string()],
1954            requires: vec![],
1955            conflicts_with: vec![],
1956            is_primary_indicator: false,
1957            alternative_names: vec![],
1958        },
1959        
1960        // KOTLIN SPECIFIC
1961        TechnologyRule {
1962            name: "Ktor".to_string(),
1963            category: TechnologyCategory::BackendFramework,
1964            confidence: 0.95,
1965            dependency_patterns: vec!["ktor".to_string(), "io.ktor".to_string()],
1966            requires: vec![],
1967            conflicts_with: vec![],
1968            is_primary_indicator: true,
1969            alternative_names: vec![],
1970        },
1971    ]
1972}
1973
1974#[cfg(test)]
1975mod tests {
1976    use super::*;
1977    use std::path::PathBuf;
1978    
1979    #[test]
1980    fn test_rust_actix_web_detection() {
1981        let language = DetectedLanguage {
1982            name: "Rust".to_string(),
1983            version: Some("1.70.0".to_string()),
1984            confidence: 0.9,
1985            files: vec![PathBuf::from("src/main.rs")],
1986            main_dependencies: vec!["actix-web".to_string(), "tokio".to_string()],
1987            dev_dependencies: vec!["assert_cmd".to_string()],
1988            package_manager: Some("cargo".to_string()),
1989        };
1990        
1991        let technologies = detect_rust_technologies(&language);
1992        
1993        // This is a simplified test - in real implementation, we'd need access to dependencies
1994        assert!(technologies.is_empty() || technologies.iter().any(|f| f.name.contains("Actix")));
1995    }
1996    
1997    #[test]
1998    fn test_framework_pattern_matching() {
1999        assert!(matches_pattern("express", "express"));
2000        assert!(matches_pattern("@nestjs/core", "@nestjs/*"));
2001        assert!(matches_pattern("spring-boot-starter-web", "spring-boot-starter*"));
2002        assert!(!matches_pattern("react", "vue"));
2003    }
2004    
2005    #[test]
2006    fn test_framework_categories() {
2007        let rules = get_js_technology_rules();
2008        
2009        let express_rule = rules.iter().find(|r| r.name == "Express.js").unwrap();
2010        assert!(matches!(express_rule.category, TechnologyCategory::BackendFramework));
2011        
2012        let jest_rule = rules.iter().find(|r| r.name == "Jest").unwrap();
2013        assert!(matches!(jest_rule.category, TechnologyCategory::Testing));
2014        
2015        // Test new frameworks
2016        let drizzle_rule = rules.iter().find(|r| r.name == "Drizzle ORM").unwrap();
2017        assert!(matches!(drizzle_rule.category, TechnologyCategory::Database));
2018        
2019        let svelte_rule = rules.iter().find(|r| r.name == "Svelte").unwrap();
2020        assert!(matches!(svelte_rule.category, TechnologyCategory::FrontendFramework));
2021        
2022        let encore_rule = rules.iter().find(|r| r.name == "Encore").unwrap();
2023        assert!(matches!(encore_rule.category, TechnologyCategory::BackendFramework));
2024        
2025        let hono_rule = rules.iter().find(|r| r.name == "Hono").unwrap();
2026        assert!(matches!(hono_rule.category, TechnologyCategory::BackendFramework));
2027    }
2028    
2029    #[test]
2030    fn test_modern_framework_detection() {
2031        let rules = get_js_technology_rules();
2032        
2033        // Test that we have all the new frameworks
2034        let framework_names: Vec<&str> = rules.iter().map(|r| r.name.as_str()).collect();
2035        
2036        assert!(framework_names.contains(&"Svelte"));
2037        assert!(framework_names.contains(&"SvelteKit"));
2038        assert!(framework_names.contains(&"Astro"));
2039        assert!(framework_names.contains(&"SolidJS"));
2040        assert!(framework_names.contains(&"Encore"));
2041        assert!(framework_names.contains(&"Hono"));
2042        assert!(framework_names.contains(&"Elysia"));
2043        assert!(framework_names.contains(&"Drizzle ORM"));
2044        assert!(framework_names.contains(&"React Router v7"));
2045        assert!(framework_names.contains(&"Tanstack Start"));
2046    }
2047    
2048    #[test]
2049    fn test_tanstack_start_detection() {
2050        let language = DetectedLanguage {
2051            name: "TypeScript".to_string(),
2052            version: Some("5.0.0".to_string()),
2053            confidence: 0.925,
2054            files: vec![PathBuf::from("src/routes/index.tsx")],
2055            main_dependencies: vec![
2056                "@tanstack/react-start".to_string(),
2057                "@tanstack/react-router".to_string(),
2058                "react".to_string(),
2059                "react-dom".to_string(),
2060            ],
2061            dev_dependencies: vec![
2062                "vinxi".to_string(),
2063                "typescript".to_string(),
2064            ],
2065            package_manager: Some("npm".to_string()),
2066        };
2067        
2068        let technologies = detect_js_technologies(&language);
2069        
2070        // Should detect Tanstack Start
2071        let tanstack_start = technologies.iter().find(|t| t.name == "Tanstack Start");
2072        assert!(tanstack_start.is_some(), "Tanstack Start should be detected");
2073        
2074        let tanstack_start = tanstack_start.unwrap();
2075        assert!(matches!(tanstack_start.category, TechnologyCategory::MetaFramework));
2076        assert!(tanstack_start.is_primary, "Tanstack Start should be marked as primary");
2077        assert!(tanstack_start.confidence > 0.8, "Tanstack Start detection confidence should be high");
2078        
2079        // Should also detect React
2080        let react = technologies.iter().find(|t| t.name == "React");
2081        assert!(react.is_some(), "React should be detected as a dependency");
2082    }
2083
2084    #[test]
2085    fn test_comprehensive_python_detection() {
2086        let language = DetectedLanguage {
2087            name: "Python".to_string(),
2088            version: Some("3.11.0".to_string()),
2089            confidence: 0.95,
2090            files: vec![PathBuf::from("app.py")],
2091            main_dependencies: vec![
2092                "fastapi".to_string(),
2093                "sqlalchemy".to_string(),
2094                "pandas".to_string(),
2095                "torch".to_string(),
2096                "gunicorn".to_string(),
2097            ],
2098            dev_dependencies: vec!["pytest".to_string()],
2099            package_manager: Some("pip".to_string()),
2100        };
2101        
2102        let technologies = detect_python_technologies(&language);
2103        let tech_names: Vec<&str> = technologies.iter().map(|t| t.name.as_str()).collect();
2104        
2105        // Should detect FastAPI as primary backend framework
2106        assert!(tech_names.contains(&"FastAPI"));
2107        assert!(tech_names.contains(&"SQLAlchemy"));
2108        assert!(tech_names.contains(&"Pandas"));
2109        assert!(tech_names.contains(&"PyTorch"));
2110        assert!(tech_names.contains(&"Gunicorn"));
2111        assert!(tech_names.contains(&"pytest"));
2112        
2113        // FastAPI should be marked as primary
2114        let fastapi = technologies.iter().find(|t| t.name == "FastAPI").unwrap();
2115        assert!(fastapi.is_primary);
2116        assert!(matches!(fastapi.category, TechnologyCategory::BackendFramework));
2117    }
2118
2119    #[test]
2120    fn test_comprehensive_go_detection() {
2121        let language = DetectedLanguage {
2122            name: "Go".to_string(),
2123            version: Some("1.21.0".to_string()),
2124            confidence: 0.95,
2125            files: vec![PathBuf::from("main.go")],
2126            main_dependencies: vec![
2127                "github.com/gin-gonic/gin".to_string(),
2128                "gorm.io/gorm".to_string(),
2129                "github.com/spf13/cobra".to_string(),
2130                "github.com/spf13/viper".to_string(),
2131            ],
2132            dev_dependencies: vec!["github.com/stretchr/testify".to_string()],
2133            package_manager: Some("go mod".to_string()),
2134        };
2135        
2136        let technologies = detect_go_technologies(&language);
2137        let tech_names: Vec<&str> = technologies.iter().map(|t| t.name.as_str()).collect();
2138        
2139        // Should detect Gin as primary backend framework
2140        assert!(tech_names.contains(&"Gin"));
2141        assert!(tech_names.contains(&"GORM"));
2142        assert!(tech_names.contains(&"Cobra"));
2143        assert!(tech_names.contains(&"Viper"));
2144        assert!(tech_names.contains(&"Testify"));
2145        
2146        // Gin should be marked as primary
2147        let gin = technologies.iter().find(|t| t.name == "Gin").unwrap();
2148        assert!(gin.is_primary);
2149        assert!(matches!(gin.category, TechnologyCategory::BackendFramework));
2150    }
2151
2152    #[test]
2153    fn test_comprehensive_jvm_detection() {
2154        let language = DetectedLanguage {
2155            name: "Java".to_string(),
2156            version: Some("17.0.0".to_string()),
2157            confidence: 0.95,
2158            files: vec![PathBuf::from("src/main/java/Application.java")],
2159            main_dependencies: vec![
2160                "spring-boot".to_string(),
2161                "spring-data".to_string(),
2162                "hibernate".to_string(),
2163                "io.projectreactor".to_string(),
2164            ],
2165            dev_dependencies: vec!["junit".to_string(), "mockito".to_string()],
2166            package_manager: Some("maven".to_string()),
2167        };
2168        
2169        let technologies = detect_jvm_technologies(&language);
2170        let tech_names: Vec<&str> = technologies.iter().map(|t| t.name.as_str()).collect();
2171        
2172        // Should detect Spring Boot as primary backend framework
2173        assert!(tech_names.contains(&"Spring Boot"));
2174        assert!(tech_names.contains(&"Spring Data"));
2175        assert!(tech_names.contains(&"Hibernate"));
2176        assert!(tech_names.contains(&"Reactor"));
2177        assert!(tech_names.contains(&"JUnit"));
2178        assert!(tech_names.contains(&"Mockito"));
2179        
2180        // Spring Boot should be marked as primary
2181        let spring_boot = technologies.iter().find(|t| t.name == "Spring Boot").unwrap();
2182        assert!(spring_boot.is_primary);
2183        assert!(matches!(spring_boot.category, TechnologyCategory::BackendFramework));
2184    }
2185
2186    #[test]
2187    fn test_comprehensive_rust_detection() {
2188        let language = DetectedLanguage {
2189            name: "Rust".to_string(),
2190            version: Some("1.70.0".to_string()),
2191            confidence: 0.95,
2192            files: vec![PathBuf::from("src/main.rs")],
2193            main_dependencies: vec![
2194                "axum".to_string(),
2195                "tokio".to_string(),
2196                "sqlx".to_string(),
2197                "serde".to_string(),
2198                "tauri".to_string(),
2199            ],
2200            dev_dependencies: vec!["criterion".to_string()],
2201            package_manager: Some("cargo".to_string()),
2202        };
2203        
2204        let technologies = detect_rust_technologies(&language);
2205        let tech_names: Vec<&str> = technologies.iter().map(|t| t.name.as_str()).collect();
2206        
2207        // Should detect Axum as primary backend framework
2208        assert!(tech_names.contains(&"Axum"));
2209        assert!(tech_names.contains(&"Tokio"));
2210        assert!(tech_names.contains(&"SQLx"));
2211        assert!(tech_names.contains(&"Serde"));
2212        assert!(tech_names.contains(&"Tauri"));
2213        assert!(tech_names.contains(&"Criterion"));
2214        
2215        // Axum should be marked as primary
2216        let axum = technologies.iter().find(|t| t.name == "Axum").unwrap();
2217        assert!(axum.is_primary);
2218        assert!(matches!(axum.category, TechnologyCategory::BackendFramework));
2219        
2220        // Axum should require Tokio
2221        assert!(axum.requires.contains(&"Tokio".to_string()));
2222    }
2223
2224    #[test]
2225    fn test_technology_conflicts_resolution() {
2226        use crate::analyzer::AnalysisConfig;
2227        use std::path::Path;
2228        
2229        let language = DetectedLanguage {
2230            name: "Rust".to_string(),
2231            version: Some("1.70.0".to_string()),
2232            confidence: 0.95,
2233            files: vec![PathBuf::from("src/main.rs")],
2234            main_dependencies: vec![
2235                "tokio".to_string(),
2236                "async-std".to_string(), // These should conflict
2237            ],
2238            dev_dependencies: vec![],
2239            package_manager: Some("cargo".to_string()),
2240        };
2241        
2242        let config = AnalysisConfig::default();
2243        let project_root = Path::new(".");
2244        
2245        // Use the main detection function which includes conflict resolution
2246        let technologies = detect_frameworks(project_root, &[language], &config).unwrap();
2247        let _tech_names: Vec<&str> = technologies.iter().map(|t| t.name.as_str()).collect();
2248        
2249        // Should only have one async runtime (higher confidence wins)
2250        let async_runtimes: Vec<_> = technologies.iter()
2251            .filter(|t| matches!(t.category, TechnologyCategory::Runtime))
2252            .collect();
2253        
2254        assert!(async_runtimes.len() <= 1, "Should resolve conflicting async runtimes: found {:?}", 
2255               async_runtimes.iter().map(|t| &t.name).collect::<Vec<_>>());
2256    }
2257}