 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			1147 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1147 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package intelligence
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"path/filepath"
 | |
| 	"regexp"
 | |
| 	"sort"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	slurpContext "chorus/pkg/slurp/context"
 | |
| )
 | |
| 
 | |
| // DefaultPatternDetector provides comprehensive pattern detection capabilities
 | |
| type DefaultPatternDetector struct {
 | |
| 	config           *EngineConfig
 | |
| 	codeAnalyzer     *CodePatternAnalyzer
 | |
| 	namingAnalyzer   *NamingPatternAnalyzer
 | |
| 	orgAnalyzer      *OrganizationalPatternAnalyzer
 | |
| 	designAnalyzer   *DesignPatternAnalyzer
 | |
| }
 | |
| 
 | |
| // CodePatternAnalyzer detects code-level patterns and anti-patterns
 | |
| type CodePatternAnalyzer struct {
 | |
| 	languagePatterns map[string]*LanguageCodePatterns
 | |
| }
 | |
| 
 | |
| // LanguageCodePatterns contains patterns specific to a programming language
 | |
| type LanguageCodePatterns struct {
 | |
| 	DesignPatterns    []*DesignPatternMatcher
 | |
| 	AntiPatterns      []*AntiPatternMatcher
 | |
| 	ArchPatterns      []*ArchitecturalPatternMatcher
 | |
| 	BestPractices     []*BestPracticeMatcher
 | |
| }
 | |
| 
 | |
| // DesignPatternMatcher detects specific design patterns
 | |
| type DesignPatternMatcher struct {
 | |
| 	PatternName     string
 | |
| 	Description     string
 | |
| 	Signatures      []*regexp.Regexp
 | |
| 	StructuralCues  []string
 | |
| 	Confidence      func(matches int, totalLines int) float64
 | |
| }
 | |
| 
 | |
| // AntiPatternMatcher detects anti-patterns and code smells
 | |
| type AntiPatternMatcher struct {
 | |
| 	PatternName     string
 | |
| 	Description     string
 | |
| 	Signatures      []*regexp.Regexp
 | |
| 	Severity        string // critical, high, medium, low
 | |
| 	Recommendation  string
 | |
| }
 | |
| 
 | |
| // ArchitecturalPatternMatcher detects architectural patterns
 | |
| type ArchitecturalPatternMatcher struct {
 | |
| 	PatternName     string
 | |
| 	Description     string
 | |
| 	FilePatterns    []*regexp.Regexp
 | |
| 	DirectoryHints  []string
 | |
| 	Dependencies    []string
 | |
| }
 | |
| 
 | |
| // BestPracticeMatcher detects adherence to best practices
 | |
| type BestPracticeMatcher struct {
 | |
| 	PracticeName    string
 | |
| 	Description     string
 | |
| 	Indicators      []*regexp.Regexp
 | |
| 	Violations      []*regexp.Regexp
 | |
| 	Impact          string
 | |
| }
 | |
| 
 | |
| // NamingPatternAnalyzer analyzes naming conventions and patterns
 | |
| type NamingPatternAnalyzer struct {
 | |
| 	conventionRules map[string]*NamingConventionRule
 | |
| }
 | |
| 
 | |
| // NamingConventionRule defines a naming convention rule
 | |
| type NamingConventionRule struct {
 | |
| 	Language      string
 | |
| 	Scope         string // function, variable, class, file, etc.
 | |
| 	Pattern       *regexp.Regexp
 | |
| 	Description   string
 | |
| 	Examples      []string
 | |
| 	Violations    []*regexp.Regexp
 | |
| }
 | |
| 
 | |
| // OrganizationalPatternAnalyzer detects organizational and structural patterns
 | |
| type OrganizationalPatternAnalyzer struct {
 | |
| 	structuralPatterns []*StructuralPatternMatcher
 | |
| }
 | |
| 
 | |
| // StructuralPatternMatcher detects structural organization patterns
 | |
| type StructuralPatternMatcher struct {
 | |
| 	PatternName       string
 | |
| 	Description       string
 | |
| 	DirectoryPatterns []*regexp.Regexp
 | |
| 	FilePatterns      []*regexp.Regexp
 | |
| 	RequiredFiles     []string
 | |
| 	OptionalFiles     []string
 | |
| 	Depth             int
 | |
| 	Characteristics   []string
 | |
| }
 | |
| 
 | |
| // DesignPatternAnalyzer detects software design patterns
 | |
| type DesignPatternAnalyzer struct {
 | |
| 	patternLibrary map[string]*DesignPatternDefinition
 | |
| }
 | |
| 
 | |
| // DesignPatternDefinition defines a comprehensive design pattern
 | |
| type DesignPatternDefinition struct {
 | |
| 	Name              string
 | |
| 	Category          string // creational, structural, behavioral
 | |
| 	Intent            string
 | |
| 	Applicability     []string
 | |
| 	Structure         *PatternStructure
 | |
| 	Participants      []string
 | |
| 	Collaborations    []string
 | |
| 	Consequences      []string
 | |
| 	Implementation    *PatternImplementation
 | |
| }
 | |
| 
 | |
| // PatternStructure defines the structural elements of a pattern
 | |
| type PatternStructure struct {
 | |
| 	Classes         []string
 | |
| 	Interfaces      []string
 | |
| 	Relationships   []string
 | |
| 	KeyComponents   []string
 | |
| }
 | |
| 
 | |
| // PatternImplementation contains implementation-specific details
 | |
| type PatternImplementation struct {
 | |
| 	Languages       []string
 | |
| 	CodeSignatures  []*regexp.Regexp
 | |
| 	FileStructure   []string
 | |
| 	Dependencies    []string
 | |
| }
 | |
| 
 | |
| // NewDefaultPatternDetector creates a comprehensive pattern detector
 | |
| func NewDefaultPatternDetector(config *EngineConfig) *DefaultPatternDetector {
 | |
| 	return &DefaultPatternDetector{
 | |
| 		config:         config,
 | |
| 		codeAnalyzer:   NewCodePatternAnalyzer(),
 | |
| 		namingAnalyzer: NewNamingPatternAnalyzer(),
 | |
| 		orgAnalyzer:    NewOrganizationalPatternAnalyzer(),
 | |
| 		designAnalyzer: NewDesignPatternAnalyzer(),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewCodePatternAnalyzer creates a code pattern analyzer
 | |
| func NewCodePatternAnalyzer() *CodePatternAnalyzer {
 | |
| 	analyzer := &CodePatternAnalyzer{
 | |
| 		languagePatterns: make(map[string]*LanguageCodePatterns),
 | |
| 	}
 | |
| 
 | |
| 	// Initialize Go patterns
 | |
| 	goPatterns := &LanguageCodePatterns{
 | |
| 		DesignPatterns: []*DesignPatternMatcher{
 | |
| 			{
 | |
| 				PatternName: "Singleton",
 | |
| 				Description: "Ensures a class has only one instance",
 | |
| 				Signatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`var\s+instance\s+\*\w+`),
 | |
| 					regexp.MustCompile(`sync\.Once`),
 | |
| 					regexp.MustCompile(`func\s+GetInstance\s*\(\s*\)\s*\*\w+`),
 | |
| 				},
 | |
| 				StructuralCues: []string{"sync.Once", "private constructor", "static instance"},
 | |
| 				Confidence: func(matches, totalLines int) float64 {
 | |
| 					return float64(matches) / 3.0
 | |
| 				},
 | |
| 			},
 | |
| 			{
 | |
| 				PatternName: "Factory",
 | |
| 				Description: "Creates objects without specifying exact class",
 | |
| 				Signatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`func\s+New\w+\s*\(`),
 | |
| 					regexp.MustCompile(`func\s+Create\w+\s*\(`),
 | |
| 					regexp.MustCompile(`func\s+Make\w+\s*\(`),
 | |
| 				},
 | |
| 				StructuralCues: []string{"factory method", "object creation"},
 | |
| 			},
 | |
| 			{
 | |
| 				PatternName: "Builder",
 | |
| 				Description: "Constructs complex objects step by step",
 | |
| 				Signatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`func\s+\(\w+\s+\*\w+\)\s+With\w+\(`),
 | |
| 					regexp.MustCompile(`func\s+\(\w+\s+\*\w+\)\s+Set\w+\(`),
 | |
| 					regexp.MustCompile(`func\s+\(\w+\s+\*\w+\)\s+Build\s*\(\s*\)`),
 | |
| 				},
 | |
| 				StructuralCues: []string{"fluent interface", "method chaining", "build method"},
 | |
| 			},
 | |
| 			{
 | |
| 				PatternName: "Observer",
 | |
| 				Description: "Notifies multiple objects about state changes",
 | |
| 				Signatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`type\s+\w*Observer\w*\s+interface`),
 | |
| 					regexp.MustCompile(`func\s+\w*Subscribe\w*\s*\(`),
 | |
| 					regexp.MustCompile(`func\s+\w*Notify\w*\s*\(`),
 | |
| 				},
 | |
| 				StructuralCues: []string{"observer interface", "subscription", "notification"},
 | |
| 			},
 | |
| 		},
 | |
| 		AntiPatterns: []*AntiPatternMatcher{
 | |
| 			{
 | |
| 				PatternName:    "God Object",
 | |
| 				Description:    "Class that does too much",
 | |
| 				Signatures:     []*regexp.Regexp{regexp.MustCompile(`func\s+\(\w+\s+\*\w+\)\s+\w+`)},
 | |
| 				Severity:       "high",
 | |
| 				Recommendation: "Split responsibilities into smaller, focused types",
 | |
| 			},
 | |
| 			{
 | |
| 				PatternName:    "Magic Numbers",
 | |
| 				Description:    "Unexplained numeric literals",
 | |
| 				Signatures:     []*regexp.Regexp{regexp.MustCompile(`\b\d{2,}\b`)},
 | |
| 				Severity:       "medium",
 | |
| 				Recommendation: "Replace with named constants",
 | |
| 			},
 | |
| 		},
 | |
| 		ArchPatterns: []*ArchitecturalPatternMatcher{
 | |
| 			{
 | |
| 				PatternName:    "Repository Pattern",
 | |
| 				Description:    "Encapsulates data access logic",
 | |
| 				FilePatterns:   []*regexp.Regexp{regexp.MustCompile(`.*repository.*\.go$`)},
 | |
| 				DirectoryHints: []string{"repository", "repo", "storage"},
 | |
| 				Dependencies:   []string{"database", "storage"},
 | |
| 			},
 | |
| 		},
 | |
| 		BestPractices: []*BestPracticeMatcher{
 | |
| 			{
 | |
| 				PracticeName: "Error Handling",
 | |
| 				Description:  "Proper error handling patterns",
 | |
| 				Indicators: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`if\s+err\s*!=\s*nil`),
 | |
| 					regexp.MustCompile(`return.*,\s*err`),
 | |
| 				},
 | |
| 				Violations: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`_\s*,\s*_\s*:=`),
 | |
| 				},
 | |
| 				Impact: "high",
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Initialize JavaScript/TypeScript patterns
 | |
| 	jsPatterns := &LanguageCodePatterns{
 | |
| 		DesignPatterns: []*DesignPatternMatcher{
 | |
| 			{
 | |
| 				PatternName: "Module Pattern",
 | |
| 				Description: "Encapsulates functionality in modules",
 | |
| 				Signatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`export\s+default`),
 | |
| 					regexp.MustCompile(`module\.exports\s*=`),
 | |
| 					regexp.MustCompile(`export\s+\{.*\}`),
 | |
| 				},
 | |
| 			},
 | |
| 			{
 | |
| 				PatternName: "Singleton",
 | |
| 				Description: "Single instance pattern in JavaScript",
 | |
| 				Signatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`class\s+\w+\s*\{[\s\S]*static\s+instance`),
 | |
| 					regexp.MustCompile(`getInstance\s*\(\s*\)`),
 | |
| 				},
 | |
| 			},
 | |
| 			{
 | |
| 				PatternName: "Observer",
 | |
| 				Description: "Event-driven programming pattern",
 | |
| 				Signatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`addEventListener\s*\(`),
 | |
| 					regexp.MustCompile(`on\s*\(`),
 | |
| 					regexp.MustCompile(`subscribe\s*\(`),
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		AntiPatterns: []*AntiPatternMatcher{
 | |
| 			{
 | |
| 				PatternName:    "Callback Hell",
 | |
| 				Description:    "Deeply nested callbacks",
 | |
| 				Signatures:     []*regexp.Regexp{regexp.MustCompile(`function\s*\([^)]*\)\s*\{[\s\S]*function\s*\([^)]*\)\s*\{[\s\S]*function`)},
 | |
| 				Severity:       "high",
 | |
| 				Recommendation: "Use Promises or async/await",
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Initialize Python patterns
 | |
| 	pythonPatterns := &LanguageCodePatterns{
 | |
| 		DesignPatterns: []*DesignPatternMatcher{
 | |
| 			{
 | |
| 				PatternName: "Decorator Pattern",
 | |
| 				Description: "Adds behavior to objects dynamically",
 | |
| 				Signatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`@\w+`),
 | |
| 					regexp.MustCompile(`def\s+\w+\s*\([^)]*\)\s*->\s*callable`),
 | |
| 				},
 | |
| 			},
 | |
| 			{
 | |
| 				PatternName: "Context Manager",
 | |
| 				Description: "Resource management pattern",
 | |
| 				Signatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`def\s+__enter__\s*\(`),
 | |
| 					regexp.MustCompile(`def\s+__exit__\s*\(`),
 | |
| 					regexp.MustCompile(`with\s+\w+`),
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	analyzer.languagePatterns["go"] = goPatterns
 | |
| 	analyzer.languagePatterns["javascript"] = jsPatterns
 | |
| 	analyzer.languagePatterns["typescript"] = jsPatterns
 | |
| 	analyzer.languagePatterns["python"] = pythonPatterns
 | |
| 
 | |
| 	return analyzer
 | |
| }
 | |
| 
 | |
| // NewNamingPatternAnalyzer creates a naming pattern analyzer
 | |
| func NewNamingPatternAnalyzer() *NamingPatternAnalyzer {
 | |
| 	analyzer := &NamingPatternAnalyzer{
 | |
| 		conventionRules: make(map[string]*NamingConventionRule),
 | |
| 	}
 | |
| 
 | |
| 	// Go naming conventions
 | |
| 	goRules := []*NamingConventionRule{
 | |
| 		{
 | |
| 			Language:    "go",
 | |
| 			Scope:       "function",
 | |
| 			Pattern:     regexp.MustCompile(`^[A-Z][a-zA-Z0-9]*$`),
 | |
| 			Description: "Exported functions use PascalCase",
 | |
| 			Examples:    []string{"GetUser", "ProcessData"},
 | |
| 		},
 | |
| 		{
 | |
| 			Language:    "go",
 | |
| 			Scope:       "variable",
 | |
| 			Pattern:     regexp.MustCompile(`^[a-z][a-zA-Z0-9]*$`),
 | |
| 			Description: "Variables use camelCase",
 | |
| 			Examples:    []string{"userName", "totalCount"},
 | |
| 		},
 | |
| 		{
 | |
| 			Language:    "go",
 | |
| 			Scope:       "constant",
 | |
| 			Pattern:     regexp.MustCompile(`^[A-Z][A-Z0-9_]*$`),
 | |
| 			Description: "Constants use SCREAMING_SNAKE_CASE",
 | |
| 			Examples:    []string{"MAX_SIZE", "DEFAULT_TIMEOUT"},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// JavaScript/TypeScript naming conventions
 | |
| 	jsRules := []*NamingConventionRule{
 | |
| 		{
 | |
| 			Language:    "javascript",
 | |
| 			Scope:       "function",
 | |
| 			Pattern:     regexp.MustCompile(`^[a-z][a-zA-Z0-9]*$`),
 | |
| 			Description: "Functions use camelCase",
 | |
| 			Examples:    []string{"getUserData", "processResults"},
 | |
| 		},
 | |
| 		{
 | |
| 			Language:    "javascript",
 | |
| 			Scope:       "class",
 | |
| 			Pattern:     regexp.MustCompile(`^[A-Z][a-zA-Z0-9]*$`),
 | |
| 			Description: "Classes use PascalCase",
 | |
| 			Examples:    []string{"UserManager", "DataProcessor"},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Python naming conventions
 | |
| 	pythonRules := []*NamingConventionRule{
 | |
| 		{
 | |
| 			Language:    "python",
 | |
| 			Scope:       "function",
 | |
| 			Pattern:     regexp.MustCompile(`^[a-z][a-z0-9_]*$`),
 | |
| 			Description: "Functions use snake_case",
 | |
| 			Examples:    []string{"get_user_data", "process_results"},
 | |
| 		},
 | |
| 		{
 | |
| 			Language:    "python",
 | |
| 			Scope:       "class",
 | |
| 			Pattern:     regexp.MustCompile(`^[A-Z][a-zA-Z0-9]*$`),
 | |
| 			Description: "Classes use PascalCase",
 | |
| 			Examples:    []string{"UserManager", "DataProcessor"},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Register all rules
 | |
| 	for _, rule := range append(append(goRules, jsRules...), pythonRules...) {
 | |
| 		key := fmt.Sprintf("%s_%s", rule.Language, rule.Scope)
 | |
| 		analyzer.conventionRules[key] = rule
 | |
| 	}
 | |
| 
 | |
| 	return analyzer
 | |
| }
 | |
| 
 | |
| // NewOrganizationalPatternAnalyzer creates an organizational pattern analyzer
 | |
| func NewOrganizationalPatternAnalyzer() *OrganizationalPatternAnalyzer {
 | |
| 	analyzer := &OrganizationalPatternAnalyzer{
 | |
| 		structuralPatterns: []*StructuralPatternMatcher{},
 | |
| 	}
 | |
| 
 | |
| 	// Define common structural patterns
 | |
| 	patterns := []*StructuralPatternMatcher{
 | |
| 		{
 | |
| 			PatternName:   "Hexagonal Architecture",
 | |
| 			Description:   "Ports and adapters architecture",
 | |
| 			DirectoryPatterns: []*regexp.Regexp{
 | |
| 				regexp.MustCompile(`.*/(domain|core)/.*`),
 | |
| 				regexp.MustCompile(`.*/adapters?/.*`),
 | |
| 				regexp.MustCompile(`.*/ports?/.*`),
 | |
| 			},
 | |
| 			RequiredFiles:   []string{"domain", "adapters"},
 | |
| 			Characteristics: []string{"dependency_inversion", "testable", "framework_independent"},
 | |
| 		},
 | |
| 		{
 | |
| 			PatternName: "Clean Architecture",
 | |
| 			Description: "Uncle Bob's clean architecture",
 | |
| 			DirectoryPatterns: []*regexp.Regexp{
 | |
| 				regexp.MustCompile(`.*/entities/.*`),
 | |
| 				regexp.MustCompile(`.*/usecases/.*`),
 | |
| 				regexp.MustCompile(`.*/adapters/.*`),
 | |
| 				regexp.MustCompile(`.*/frameworks?/.*`),
 | |
| 			},
 | |
| 			RequiredFiles:   []string{"entities", "usecases"},
 | |
| 			Characteristics: []string{"dependency_rule", "testable", "ui_independent"},
 | |
| 		},
 | |
| 		{
 | |
| 			PatternName: "Microservices",
 | |
| 			Description: "Service-oriented architecture",
 | |
| 			DirectoryPatterns: []*regexp.Regexp{
 | |
| 				regexp.MustCompile(`.*/services?/.*`),
 | |
| 				regexp.MustCompile(`.*/api-gateway/.*`),
 | |
| 			},
 | |
| 			RequiredFiles:   []string{"services"},
 | |
| 			Characteristics: []string{"distributed", "autonomous", "scalable"},
 | |
| 		},
 | |
| 		{
 | |
| 			PatternName: "Monorepo",
 | |
| 			Description: "Multiple projects in single repository",
 | |
| 			DirectoryPatterns: []*regexp.Regexp{
 | |
| 				regexp.MustCompile(`.*/packages?/.*`),
 | |
| 				regexp.MustCompile(`.*/apps?/.*`),
 | |
| 				regexp.MustCompile(`.*/libs?/.*`),
 | |
| 			},
 | |
| 			RequiredFiles:   []string{"packages", "apps"},
 | |
| 			Characteristics: []string{"shared_dependencies", "atomic_commits", "unified_tooling"},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	analyzer.structuralPatterns = patterns
 | |
| 	return analyzer
 | |
| }
 | |
| 
 | |
| // NewDesignPatternAnalyzer creates a design pattern analyzer
 | |
| func NewDesignPatternAnalyzer() *DesignPatternAnalyzer {
 | |
| 	analyzer := &DesignPatternAnalyzer{
 | |
| 		patternLibrary: make(map[string]*DesignPatternDefinition),
 | |
| 	}
 | |
| 
 | |
| 	// Define comprehensive design patterns
 | |
| 	patterns := []*DesignPatternDefinition{
 | |
| 		{
 | |
| 			Name:     "Singleton",
 | |
| 			Category: "creational",
 | |
| 			Intent:   "Ensure a class has only one instance and provide global point of access",
 | |
| 			Applicability: []string{
 | |
| 				"exactly one instance needed",
 | |
| 				"instance must be accessible from well-known access point",
 | |
| 				"sole instance should be extensible by subclassing",
 | |
| 			},
 | |
| 			Structure: &PatternStructure{
 | |
| 				Classes:       []string{"Singleton"},
 | |
| 				Interfaces:    []string{},
 | |
| 				Relationships: []string{"self-reference"},
 | |
| 				KeyComponents: []string{"private constructor", "static instance", "getInstance method"},
 | |
| 			},
 | |
| 			Implementation: &PatternImplementation{
 | |
| 				Languages: []string{"go", "java", "javascript", "python"},
 | |
| 				CodeSignatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`getInstance|GetInstance`),
 | |
| 					regexp.MustCompile(`static.*instance|var.*instance`),
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			Name:     "Factory Method",
 | |
| 			Category: "creational",
 | |
| 			Intent:   "Create objects without specifying their concrete classes",
 | |
| 			Structure: &PatternStructure{
 | |
| 				Classes:       []string{"Creator", "ConcreteCreator", "Product", "ConcreteProduct"},
 | |
| 				Interfaces:    []string{"Product"},
 | |
| 				Relationships: []string{"creator uses product"},
 | |
| 				KeyComponents: []string{"factory method", "product hierarchy"},
 | |
| 			},
 | |
| 			Implementation: &PatternImplementation{
 | |
| 				Languages: []string{"go", "java", "javascript", "python"},
 | |
| 				CodeSignatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`New\w+|Create\w+|Make\w+`),
 | |
| 					regexp.MustCompile(`factory|Factory`),
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			Name:     "Observer",
 | |
| 			Category: "behavioral",
 | |
| 			Intent:   "Define a one-to-many dependency between objects",
 | |
| 			Structure: &PatternStructure{
 | |
| 				Classes:       []string{"Subject", "Observer", "ConcreteSubject", "ConcreteObserver"},
 | |
| 				Interfaces:    []string{"Observer", "Subject"},
 | |
| 				Relationships: []string{"subject notifies observers"},
 | |
| 				KeyComponents: []string{"subscribe", "unsubscribe", "notify"},
 | |
| 			},
 | |
| 			Implementation: &PatternImplementation{
 | |
| 				Languages: []string{"go", "java", "javascript", "python"},
 | |
| 				CodeSignatures: []*regexp.Regexp{
 | |
| 					regexp.MustCompile(`Subscribe|Unsubscribe|Notify`),
 | |
| 					regexp.MustCompile(`Observer|Subject`),
 | |
| 					regexp.MustCompile(`addEventListener|on\(`),
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, pattern := range patterns {
 | |
| 		analyzer.patternLibrary[pattern.Name] = pattern
 | |
| 	}
 | |
| 
 | |
| 	return analyzer
 | |
| }
 | |
| 
 | |
| // DetectCodePatterns identifies code patterns and architectural styles
 | |
| func (pd *DefaultPatternDetector) DetectCodePatterns(ctx context.Context, filePath string, content []byte) ([]*CodePattern, error) {
 | |
| 	patterns := []*CodePattern{}
 | |
| 	
 | |
| 	// Detect language
 | |
| 	language := pd.detectLanguageFromPath(filePath)
 | |
| 	if language == "" {
 | |
| 		return patterns, nil
 | |
| 	}
 | |
| 
 | |
| 	// Get language-specific patterns
 | |
| 	langPatterns, exists := pd.codeAnalyzer.languagePatterns[language]
 | |
| 	if !exists {
 | |
| 		return patterns, nil
 | |
| 	}
 | |
| 
 | |
| 	contentStr := string(content)
 | |
| 	
 | |
| 	// Detect design patterns
 | |
| 	for _, designPattern := range langPatterns.DesignPatterns {
 | |
| 		if pattern := pd.analyzeDesignPattern(contentStr, designPattern, language); pattern != nil {
 | |
| 			patterns = append(patterns, pattern)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Detect architectural patterns
 | |
| 	for _, archPattern := range langPatterns.ArchPatterns {
 | |
| 		if pattern := pd.analyzeArchitecturalPattern(filePath, contentStr, archPattern, language); pattern != nil {
 | |
| 			patterns = append(patterns, pattern)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Detect anti-patterns
 | |
| 	for _, antiPattern := range langPatterns.AntiPatterns {
 | |
| 		if pattern := pd.analyzeAntiPattern(contentStr, antiPattern, language); pattern != nil {
 | |
| 			patterns = append(patterns, pattern)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return patterns, nil
 | |
| }
 | |
| 
 | |
| // DetectNamingPatterns identifies naming conventions and patterns
 | |
| func (pd *DefaultPatternDetector) DetectNamingPatterns(ctx context.Context, contexts []*slurpContext.ContextNode) ([]*NamingPattern, error) {
 | |
| 	patterns := []*NamingPattern{}
 | |
| 	
 | |
| 	// Group contexts by language
 | |
| 	langGroups := make(map[string][]*slurpContext.ContextNode)
 | |
| 	for _, context := range contexts {
 | |
| 		if analysis, ok := context.Metadata["analysis"].(*FileAnalysis); ok {
 | |
| 			lang := analysis.Language
 | |
| 			if lang != "" {
 | |
| 				langGroups[lang] = append(langGroups[lang], context)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Analyze naming patterns for each language
 | |
| 	for language, langContexts := range langGroups {
 | |
| 		langPatterns := pd.analyzeLanguageNamingPatterns(language, langContexts)
 | |
| 		patterns = append(patterns, langPatterns...)
 | |
| 	}
 | |
| 
 | |
| 	return patterns, nil
 | |
| }
 | |
| 
 | |
| // DetectOrganizationalPatterns identifies organizational patterns
 | |
| func (pd *DefaultPatternDetector) DetectOrganizationalPatterns(ctx context.Context, rootPath string) ([]*OrganizationalPattern, error) {
 | |
| 	patterns := []*OrganizationalPattern{}
 | |
| 
 | |
| 	for _, matcher := range pd.orgAnalyzer.structuralPatterns {
 | |
| 		if pattern := pd.analyzeStructuralPattern(rootPath, matcher); pattern != nil {
 | |
| 			patterns = append(patterns, pattern)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return patterns, nil
 | |
| }
 | |
| 
 | |
| // MatchPatterns matches context against known patterns
 | |
| func (pd *DefaultPatternDetector) MatchPatterns(ctx context.Context, node *slurpContext.ContextNode, patterns []*Pattern) ([]*PatternMatch, error) {
 | |
| 	matches := []*PatternMatch{}
 | |
| 
 | |
| 	for _, pattern := range patterns {
 | |
| 		if match := pd.calculatePatternMatch(node, pattern); match != nil {
 | |
| 			matches = append(matches, match)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Sort by match score
 | |
| 	sort.Slice(matches, func(i, j int) bool {
 | |
| 		return matches[i].MatchScore > matches[j].MatchScore
 | |
| 	})
 | |
| 
 | |
| 	return matches, nil
 | |
| }
 | |
| 
 | |
| // LearnPatterns learns new patterns from context examples
 | |
| func (pd *DefaultPatternDetector) LearnPatterns(ctx context.Context, examples []*slurpContext.ContextNode) ([]*Pattern, error) {
 | |
| 	patterns := []*Pattern{}
 | |
| 
 | |
| 	// Group examples by similarity
 | |
| 	groups := pd.groupSimilarContexts(examples)
 | |
| 
 | |
| 	// Extract patterns from each group
 | |
| 	for groupID, group := range groups {
 | |
| 		if len(group) >= 2 { // Need at least 2 examples to form a pattern
 | |
| 			pattern := pd.extractPatternFromGroup(groupID, group)
 | |
| 			if pattern != nil {
 | |
| 				patterns = append(patterns, pattern)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return patterns, nil
 | |
| }
 | |
| 
 | |
| // Helper methods
 | |
| 
 | |
| func (pd *DefaultPatternDetector) detectLanguageFromPath(filePath string) string {
 | |
| 	ext := strings.ToLower(filepath.Ext(filePath))
 | |
| 	langMap := map[string]string{
 | |
| 		".go":   "go",
 | |
| 		".py":   "python",
 | |
| 		".js":   "javascript",
 | |
| 		".jsx":  "javascript",
 | |
| 		".ts":   "typescript",
 | |
| 		".tsx":  "typescript",
 | |
| 		".java": "java",
 | |
| 		".c":    "c",
 | |
| 		".cpp":  "cpp",
 | |
| 		".cs":   "csharp",
 | |
| 		".php":  "php",
 | |
| 		".rb":   "ruby",
 | |
| 		".rs":   "rust",
 | |
| 	}
 | |
| 	return langMap[ext]
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) analyzeDesignPattern(content string, matcher *DesignPatternMatcher, language string) *CodePattern {
 | |
| 	matches := 0
 | |
| 	matchedSignatures := []string{}
 | |
| 
 | |
| 	for _, signature := range matcher.Signatures {
 | |
| 		if signature.MatchString(content) {
 | |
| 			matches++
 | |
| 			matchedSignatures = append(matchedSignatures, signature.String())
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if matches == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	confidence := 0.0
 | |
| 	if matcher.Confidence != nil {
 | |
| 		lines := strings.Count(content, "\n") + 1
 | |
| 		confidence = matcher.Confidence(matches, lines)
 | |
| 	} else {
 | |
| 		confidence = float64(matches) / float64(len(matcher.Signatures))
 | |
| 	}
 | |
| 
 | |
| 	if confidence < 0.3 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return &CodePattern{
 | |
| 		Pattern: Pattern{
 | |
| 			ID:          fmt.Sprintf("%s_%s", language, strings.ToLower(matcher.PatternName)),
 | |
| 			Name:        matcher.PatternName,
 | |
| 			Type:        "design_pattern",
 | |
| 			Description: matcher.Description,
 | |
| 			Confidence:  confidence,
 | |
| 			Examples:    matchedSignatures,
 | |
| 			DetectedAt:  time.Now(),
 | |
| 		},
 | |
| 		Language:   language,
 | |
| 		Complexity: pd.calculatePatternComplexity(matcher.PatternName),
 | |
| 		Usage: &UsagePattern{
 | |
| 			Frequency: pd.determinePatternFrequency(matches),
 | |
| 			Context:   matcher.StructuralCues,
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) analyzeArchitecturalPattern(filePath, content string, matcher *ArchitecturalPatternMatcher, language string) *CodePattern {
 | |
| 	// Check file path patterns
 | |
| 	pathMatches := false
 | |
| 	for _, pattern := range matcher.FilePatterns {
 | |
| 		if pattern.MatchString(filePath) {
 | |
| 			pathMatches = true
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !pathMatches {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	// Check for dependencies if specified
 | |
| 	hasRequiredDeps := len(matcher.Dependencies) == 0
 | |
| 	if len(matcher.Dependencies) > 0 {
 | |
| 		for _, dep := range matcher.Dependencies {
 | |
| 			if strings.Contains(strings.ToLower(content), strings.ToLower(dep)) {
 | |
| 				hasRequiredDeps = true
 | |
| 				break
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !hasRequiredDeps {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return &CodePattern{
 | |
| 		Pattern: Pattern{
 | |
| 			ID:          fmt.Sprintf("%s_%s_arch", language, strings.ToLower(matcher.PatternName)),
 | |
| 			Name:        matcher.PatternName,
 | |
| 			Type:        "architectural_pattern",
 | |
| 			Description: matcher.Description,
 | |
| 			Confidence:  0.8,
 | |
| 			Examples:    []string{filepath.Base(filePath)},
 | |
| 			DetectedAt:  time.Now(),
 | |
| 		},
 | |
| 		Language:   language,
 | |
| 		Complexity: 0.7,
 | |
| 		Usage: &UsagePattern{
 | |
| 			Frequency: "common",
 | |
| 			Context:   matcher.DirectoryHints,
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) analyzeAntiPattern(content string, matcher *AntiPatternMatcher, language string) *CodePattern {
 | |
| 	matches := 0
 | |
| 	for _, signature := range matcher.Signatures {
 | |
| 		matches += len(signature.FindAllString(content, -1))
 | |
| 	}
 | |
| 
 | |
| 	if matches == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	severity := 0.5
 | |
| 	switch matcher.Severity {
 | |
| 	case "critical":
 | |
| 		severity = 1.0
 | |
| 	case "high":
 | |
| 		severity = 0.8
 | |
| 	case "medium":
 | |
| 		severity = 0.6
 | |
| 	case "low":
 | |
| 		severity = 0.4
 | |
| 	}
 | |
| 
 | |
| 	return &CodePattern{
 | |
| 		Pattern: Pattern{
 | |
| 			ID:          fmt.Sprintf("%s_%s_anti", language, strings.ToLower(matcher.PatternName)),
 | |
| 			Name:        matcher.PatternName,
 | |
| 			Type:        "anti_pattern",
 | |
| 			Description: matcher.Description,
 | |
| 			Confidence:  severity,
 | |
| 			Frequency:   matches,
 | |
| 			Drawbacks:   []string{matcher.Recommendation},
 | |
| 			DetectedAt:  time.Now(),
 | |
| 		},
 | |
| 		Language:   language,
 | |
| 		Complexity: severity,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) analyzeLanguageNamingPatterns(language string, contexts []*slurpContext.ContextNode) []*NamingPattern {
 | |
| 	patterns := []*NamingPattern{}
 | |
| 
 | |
| 	// Collect all identifiers from contexts
 | |
| 	identifiers := pd.collectIdentifiers(contexts)
 | |
| 
 | |
| 	// Analyze patterns for different scopes
 | |
| 	scopes := []string{"function", "variable", "class", "file"}
 | |
| 	for _, scope := range scopes {
 | |
| 		if pattern := pd.analyzeNamingPatternForScope(language, scope, identifiers[scope]); pattern != nil {
 | |
| 			patterns = append(patterns, pattern)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return patterns
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) collectIdentifiers(contexts []*slurpContext.ContextNode) map[string][]string {
 | |
| 	identifiers := make(map[string][]string)
 | |
| 
 | |
| 	for _, context := range contexts {
 | |
| 		if analysis, ok := context.Metadata["analysis"].(*FileAnalysis); ok {
 | |
| 			identifiers["function"] = append(identifiers["function"], analysis.Functions...)
 | |
| 			identifiers["variable"] = append(identifiers["variable"], analysis.Variables...)
 | |
| 			identifiers["class"] = append(identifiers["class"], analysis.Classes...)
 | |
| 			identifiers["file"] = append(identifiers["file"], filepath.Base(context.Path))
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return identifiers
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) analyzeNamingPatternForScope(language, scope string, identifiers []string) *NamingPattern {
 | |
| 	if len(identifiers) < 2 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	// Detect dominant convention
 | |
| 	conventions := map[string]int{
 | |
| 		"camelCase":  0,
 | |
| 		"PascalCase": 0,
 | |
| 		"snake_case": 0,
 | |
| 		"kebab-case": 0,
 | |
| 	}
 | |
| 
 | |
| 	for _, identifier := range identifiers {
 | |
| 		if matched, _ := regexp.MatchString(`^[a-z][a-zA-Z0-9]*$`, identifier); matched {
 | |
| 			conventions["camelCase"]++
 | |
| 		} else if matched, _ := regexp.MatchString(`^[A-Z][a-zA-Z0-9]*$`, identifier); matched {
 | |
| 			conventions["PascalCase"]++
 | |
| 		} else if matched, _ := regexp.MatchString(`^[a-z][a-z0-9_]*$`, identifier); matched {
 | |
| 			conventions["snake_case"]++
 | |
| 		} else if matched, _ := regexp.MatchString(`^[a-z][a-z0-9-]*$`, identifier); matched {
 | |
| 			conventions["kebab-case"]++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Find dominant convention
 | |
| 	maxCount := 0
 | |
| 	dominantConvention := "mixed"
 | |
| 	for convention, count := range conventions {
 | |
| 		if count > maxCount {
 | |
| 			maxCount = count
 | |
| 			dominantConvention = convention
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	confidence := float64(maxCount) / float64(len(identifiers))
 | |
| 	if confidence < 0.5 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return &NamingPattern{
 | |
| 		Pattern: Pattern{
 | |
| 			ID:          fmt.Sprintf("%s_%s_naming", language, scope),
 | |
| 			Name:        fmt.Sprintf("%s %s Naming", strings.Title(language), strings.Title(scope)),
 | |
| 			Type:        "naming_convention",
 | |
| 			Description: fmt.Sprintf("Naming convention for %s %ss", language, scope),
 | |
| 			Confidence:  confidence,
 | |
| 			Examples:    identifiers[:min(5, len(identifiers))],
 | |
| 			DetectedAt:  time.Now(),
 | |
| 		},
 | |
| 		Convention: dominantConvention,
 | |
| 		Scope:      scope,
 | |
| 		CaseStyle:  dominantConvention,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) analyzeStructuralPattern(rootPath string, matcher *StructuralPatternMatcher) *OrganizationalPattern {
 | |
| 	// Check if pattern directory structure exists
 | |
| 	matchCount := 0
 | |
| 	totalRequired := len(matcher.RequiredFiles)
 | |
| 
 | |
| 	for _, required := range matcher.RequiredFiles {
 | |
| 		checkPath := filepath.Join(rootPath, required)
 | |
| 		if pd.pathExists(checkPath) {
 | |
| 			matchCount++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if matchCount < totalRequired {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	confidence := float64(matchCount) / float64(totalRequired)
 | |
| 
 | |
| 	return &OrganizationalPattern{
 | |
| 		Pattern: Pattern{
 | |
| 			ID:          strings.ToLower(strings.ReplaceAll(matcher.PatternName, " ", "_")),
 | |
| 			Name:        matcher.PatternName,
 | |
| 			Type:        "organizational",
 | |
| 			Description: matcher.Description,
 | |
| 			Confidence:  confidence,
 | |
| 			Examples:    matcher.RequiredFiles,
 | |
| 			Benefits:    matcher.Characteristics,
 | |
| 			DetectedAt:  time.Now(),
 | |
| 		},
 | |
| 		Structure:   "hierarchical",
 | |
| 		Depth:       matcher.Depth,
 | |
| 		FanOut:      len(matcher.RequiredFiles),
 | |
| 		Modularity:  confidence,
 | |
| 		Scalability: pd.assessScalability(matcher.Characteristics),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) calculatePatternMatch(node *slurpContext.ContextNode, pattern *Pattern) *PatternMatch {
 | |
| 	score := 0.0
 | |
| 	matchedFields := []string{}
 | |
| 
 | |
| 	// Check summary match
 | |
| 	if pd.textContainsKeywords(node.Summary, pattern.Examples) {
 | |
| 		score += 0.3
 | |
| 		matchedFields = append(matchedFields, "summary")
 | |
| 	}
 | |
| 
 | |
| 	// Check purpose match
 | |
| 	if pd.textContainsKeywords(node.Purpose, pattern.Examples) {
 | |
| 		score += 0.3
 | |
| 		matchedFields = append(matchedFields, "purpose")
 | |
| 	}
 | |
| 
 | |
| 	// Check technology match
 | |
| 	for _, tech := range node.Technologies {
 | |
| 		if pd.containsIgnoreCase(pattern.Examples, tech) {
 | |
| 			score += 0.2
 | |
| 			matchedFields = append(matchedFields, "technologies")
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Check tag match
 | |
| 	for _, tag := range node.Tags {
 | |
| 		if pd.containsIgnoreCase(pattern.Examples, tag) {
 | |
| 			score += 0.2
 | |
| 			matchedFields = append(matchedFields, "tags")
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if score < 0.3 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return &PatternMatch{
 | |
| 		PatternID:     pattern.ID,
 | |
| 		MatchScore:    score,
 | |
| 		Confidence:    pattern.Confidence * score,
 | |
| 		MatchedFields: matchedFields,
 | |
| 		Explanation:   fmt.Sprintf("Pattern %s matched with score %.2f", pattern.Name, score),
 | |
| 		Suggestions:   pd.generatePatternSuggestions(pattern),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) groupSimilarContexts(contexts []*slurpContext.ContextNode) map[string][]*slurpContext.ContextNode {
 | |
| 	groups := make(map[string][]*slurpContext.ContextNode)
 | |
| 
 | |
| 	for _, context := range contexts {
 | |
| 		// Simple grouping by primary technology
 | |
| 		groupKey := "unknown"
 | |
| 		if len(context.Technologies) > 0 {
 | |
| 			groupKey = context.Technologies[0]
 | |
| 		}
 | |
| 
 | |
| 		groups[groupKey] = append(groups[groupKey], context)
 | |
| 	}
 | |
| 
 | |
| 	return groups
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) extractPatternFromGroup(groupID string, group []*slurpContext.ContextNode) *Pattern {
 | |
| 	// Find common characteristics
 | |
| 	commonTechs := pd.findCommonTechnologies(group)
 | |
| 	commonTags := pd.findCommonTags(group)
 | |
| 
 | |
| 	if len(commonTechs) == 0 && len(commonTags) == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return &Pattern{
 | |
| 		ID:          fmt.Sprintf("learned_%s_%d", groupID, time.Now().Unix()),
 | |
| 		Name:        fmt.Sprintf("Learned %s Pattern", strings.Title(groupID)),
 | |
| 		Type:        "learned",
 | |
| 		Description: fmt.Sprintf("Pattern extracted from %d similar contexts", len(group)),
 | |
| 		Confidence:  pd.calculateLearningConfidence(group),
 | |
| 		Examples:    append(commonTechs, commonTags...),
 | |
| 		DetectedAt:  time.Now(),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Additional helper methods
 | |
| 
 | |
| func (pd *DefaultPatternDetector) calculatePatternComplexity(patternName string) float64 {
 | |
| 	complexityMap := map[string]float64{
 | |
| 		"Singleton":         0.3,
 | |
| 		"Factory":          0.5,
 | |
| 		"Builder":          0.7,
 | |
| 		"Observer":         0.6,
 | |
| 		"Strategy":         0.5,
 | |
| 		"Command":          0.6,
 | |
| 		"Decorator":        0.8,
 | |
| 		"Composite":        0.9,
 | |
| 		"Abstract Factory": 0.9,
 | |
| 		"Prototype":        0.4,
 | |
| 	}
 | |
| 
 | |
| 	if complexity, exists := complexityMap[patternName]; exists {
 | |
| 		return complexity
 | |
| 	}
 | |
| 	return 0.5 // Default complexity
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) determinePatternFrequency(matches int) string {
 | |
| 	if matches > 5 {
 | |
| 		return "frequent"
 | |
| 	} else if matches > 2 {
 | |
| 		return "common"
 | |
| 	} else {
 | |
| 		return "rare"
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) pathExists(path string) bool {
 | |
| 	_, err := filepath.Abs(path)
 | |
| 	return err == nil
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) assessScalability(characteristics []string) string {
 | |
| 	for _, char := range characteristics {
 | |
| 		if strings.Contains(char, "scalable") {
 | |
| 			return "excellent"
 | |
| 		}
 | |
| 	}
 | |
| 	return "good"
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) textContainsKeywords(text string, keywords []string) bool {
 | |
| 	lowerText := strings.ToLower(text)
 | |
| 	for _, keyword := range keywords {
 | |
| 		if strings.Contains(lowerText, strings.ToLower(keyword)) {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) containsIgnoreCase(slice []string, item string) bool {
 | |
| 	lowerItem := strings.ToLower(item)
 | |
| 	for _, s := range slice {
 | |
| 		if strings.ToLower(s) == lowerItem {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) generatePatternSuggestions(pattern *Pattern) []string {
 | |
| 	suggestions := []string{}
 | |
| 
 | |
| 	switch pattern.Type {
 | |
| 	case "design_pattern":
 | |
| 		suggestions = append(suggestions, "Consider documenting the pattern usage")
 | |
| 		suggestions = append(suggestions, "Ensure pattern implementation follows best practices")
 | |
| 	case "anti_pattern":
 | |
| 		suggestions = append(suggestions, "Refactor to eliminate anti-pattern")
 | |
| 		suggestions = append(suggestions, "Consider alternative design approaches")
 | |
| 	case "architectural_pattern":
 | |
| 		suggestions = append(suggestions, "Document architectural decisions")
 | |
| 		suggestions = append(suggestions, "Ensure pattern consistency across project")
 | |
| 	}
 | |
| 
 | |
| 	return suggestions
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) findCommonTechnologies(contexts []*slurpContext.ContextNode) []string {
 | |
| 	techCount := make(map[string]int)
 | |
| 	
 | |
| 	for _, context := range contexts {
 | |
| 		for _, tech := range context.Technologies {
 | |
| 			techCount[tech]++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	common := []string{}
 | |
| 	threshold := len(contexts) / 2 // At least half should have the technology
 | |
| 	for tech, count := range techCount {
 | |
| 		if count >= threshold {
 | |
| 			common = append(common, tech)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return common
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) findCommonTags(contexts []*slurpContext.ContextNode) []string {
 | |
| 	tagCount := make(map[string]int)
 | |
| 	
 | |
| 	for _, context := range contexts {
 | |
| 		for _, tag := range context.Tags {
 | |
| 			tagCount[tag]++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	common := []string{}
 | |
| 	threshold := len(contexts) / 2
 | |
| 	for tag, count := range tagCount {
 | |
| 		if count >= threshold {
 | |
| 			common = append(common, tag)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return common
 | |
| }
 | |
| 
 | |
| func (pd *DefaultPatternDetector) calculateLearningConfidence(group []*slurpContext.ContextNode) float64 {
 | |
| 	// Simple confidence based on group size and consistency
 | |
| 	baseConfidence := 0.5
 | |
| 	groupBonus := float64(len(group)) * 0.1
 | |
| 	if groupBonus > 0.3 {
 | |
| 		groupBonus = 0.3
 | |
| 	}
 | |
| 
 | |
| 	return baseConfidence + groupBonus
 | |
| }
 | |
| 
 | |
| func min(a, b int) int {
 | |
| 	if a < b {
 | |
| 		return a
 | |
| 	}
 | |
| 	return b
 | |
| } |