chore: align slurp config and scaffolding

This commit is contained in:
anthonyrawlins
2025-09-27 21:03:12 +10:00
parent acc4361463
commit 4a77862289
47 changed files with 5133 additions and 4274 deletions

View File

@@ -11,8 +11,8 @@ import (
"strings"
"time"
"chorus/pkg/ucxl"
slurpContext "chorus/pkg/slurp/context"
"chorus/pkg/ucxl"
)
// DefaultDirectoryAnalyzer provides comprehensive directory structure analysis
@@ -268,11 +268,11 @@ func NewRelationshipAnalyzer() *RelationshipAnalyzer {
// AnalyzeStructure analyzes directory organization patterns
func (da *DefaultDirectoryAnalyzer) AnalyzeStructure(ctx context.Context, dirPath string) (*DirectoryStructure, error) {
structure := &DirectoryStructure{
Path: dirPath,
FileTypes: make(map[string]int),
Languages: make(map[string]int),
Dependencies: []string{},
AnalyzedAt: time.Now(),
Path: dirPath,
FileTypes: make(map[string]int),
Languages: make(map[string]int),
Dependencies: []string{},
AnalyzedAt: time.Now(),
}
// Walk the directory tree
@@ -340,9 +340,9 @@ func (da *DefaultDirectoryAnalyzer) DetectConventions(ctx context.Context, dirPa
OrganizationalPatterns: []*OrganizationalPattern{},
Consistency: 0.0,
Violations: []*Violation{},
Recommendations: []*Recommendation{},
Recommendations: []*BasicRecommendation{},
AppliedStandards: []string{},
AnalyzedAt: time.Now(),
AnalyzedAt: time.Now(),
}
// Collect all files and directories
@@ -385,39 +385,39 @@ func (da *DefaultDirectoryAnalyzer) IdentifyPurpose(ctx context.Context, structu
purpose string
confidence float64
}{
"src": {"Source code repository", 0.9},
"source": {"Source code repository", 0.9},
"lib": {"Library code", 0.8},
"libs": {"Library code", 0.8},
"vendor": {"Third-party dependencies", 0.9},
"node_modules": {"Node.js dependencies", 0.95},
"build": {"Build artifacts", 0.9},
"dist": {"Distribution files", 0.9},
"bin": {"Binary executables", 0.9},
"test": {"Test code", 0.9},
"tests": {"Test code", 0.9},
"docs": {"Documentation", 0.9},
"doc": {"Documentation", 0.9},
"config": {"Configuration files", 0.9},
"configs": {"Configuration files", 0.9},
"scripts": {"Utility scripts", 0.8},
"tools": {"Development tools", 0.8},
"assets": {"Static assets", 0.8},
"public": {"Public web assets", 0.8},
"static": {"Static files", 0.8},
"templates": {"Template files", 0.8},
"migrations": {"Database migrations", 0.9},
"models": {"Data models", 0.8},
"views": {"View layer", 0.8},
"controllers": {"Controller layer", 0.8},
"services": {"Service layer", 0.8},
"components": {"Reusable components", 0.8},
"modules": {"Modular components", 0.8},
"packages": {"Package organization", 0.7},
"internal": {"Internal implementation", 0.8},
"cmd": {"Command-line applications", 0.9},
"api": {"API implementation", 0.8},
"pkg": {"Go package directory", 0.8},
"src": {"Source code repository", 0.9},
"source": {"Source code repository", 0.9},
"lib": {"Library code", 0.8},
"libs": {"Library code", 0.8},
"vendor": {"Third-party dependencies", 0.9},
"node_modules": {"Node.js dependencies", 0.95},
"build": {"Build artifacts", 0.9},
"dist": {"Distribution files", 0.9},
"bin": {"Binary executables", 0.9},
"test": {"Test code", 0.9},
"tests": {"Test code", 0.9},
"docs": {"Documentation", 0.9},
"doc": {"Documentation", 0.9},
"config": {"Configuration files", 0.9},
"configs": {"Configuration files", 0.9},
"scripts": {"Utility scripts", 0.8},
"tools": {"Development tools", 0.8},
"assets": {"Static assets", 0.8},
"public": {"Public web assets", 0.8},
"static": {"Static files", 0.8},
"templates": {"Template files", 0.8},
"migrations": {"Database migrations", 0.9},
"models": {"Data models", 0.8},
"views": {"View layer", 0.8},
"controllers": {"Controller layer", 0.8},
"services": {"Service layer", 0.8},
"components": {"Reusable components", 0.8},
"modules": {"Modular components", 0.8},
"packages": {"Package organization", 0.7},
"internal": {"Internal implementation", 0.8},
"cmd": {"Command-line applications", 0.9},
"api": {"API implementation", 0.8},
"pkg": {"Go package directory", 0.8},
}
if p, exists := purposes[dirName]; exists {
@@ -459,12 +459,12 @@ func (da *DefaultDirectoryAnalyzer) IdentifyPurpose(ctx context.Context, structu
// AnalyzeRelationships analyzes relationships between subdirectories
func (da *DefaultDirectoryAnalyzer) AnalyzeRelationships(ctx context.Context, dirPath string) (*RelationshipAnalysis, error) {
analysis := &RelationshipAnalysis{
Dependencies: []*DirectoryDependency{},
Relationships: []*DirectoryRelation{},
CouplingMetrics: &CouplingMetrics{},
ModularityScore: 0.0,
Dependencies: []*DirectoryDependency{},
Relationships: []*DirectoryRelation{},
CouplingMetrics: &CouplingMetrics{},
ModularityScore: 0.0,
ArchitecturalStyle: "unknown",
AnalyzedAt: time.Now(),
AnalyzedAt: time.Now(),
}
// Find subdirectories
@@ -568,20 +568,20 @@ func (da *DefaultDirectoryAnalyzer) GenerateHierarchy(ctx context.Context, rootP
func (da *DefaultDirectoryAnalyzer) mapExtensionToLanguage(ext string) string {
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",
".kt": "kotlin",
".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",
".kt": "kotlin",
".swift": "swift",
}
@@ -604,7 +604,7 @@ func (da *DefaultDirectoryAnalyzer) analyzeOrganization(dirPath string) (*Organi
// Detect organizational pattern
pattern := da.detectOrganizationalPattern(subdirs)
// Calculate metrics
fanOut := len(subdirs)
consistency := da.calculateOrganizationalConsistency(subdirs)
@@ -672,7 +672,7 @@ func (da *DefaultDirectoryAnalyzer) allAreDomainLike(subdirs []string) bool {
// Simple heuristic: if directories don't look like technical layers,
// they might be domain/feature based
technicalTerms := []string{"api", "service", "repository", "model", "dto", "util", "config", "test", "lib"}
for _, subdir := range subdirs {
lowerDir := strings.ToLower(subdir)
for _, term := range technicalTerms {
@@ -733,7 +733,7 @@ func (da *DefaultDirectoryAnalyzer) isSnakeCase(s string) bool {
func (da *DefaultDirectoryAnalyzer) calculateMaxDepth(dirPath string) int {
maxDepth := 0
filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil
@@ -747,7 +747,7 @@ func (da *DefaultDirectoryAnalyzer) calculateMaxDepth(dirPath string) int {
}
return nil
})
return maxDepth
}
@@ -756,7 +756,7 @@ func (da *DefaultDirectoryAnalyzer) calculateModularity(subdirs []string) float6
if len(subdirs) == 0 {
return 0.0
}
// More subdirectories with clear separation indicates higher modularity
if len(subdirs) > 5 {
return 0.8
@@ -786,7 +786,7 @@ func (da *DefaultDirectoryAnalyzer) analyzeConventions(ctx context.Context, dirP
// Detect dominant naming style
namingStyle := da.detectDominantNamingStyle(append(fileNames, dirNames...))
// Calculate consistency
consistency := da.calculateNamingConsistency(append(fileNames, dirNames...), namingStyle)
@@ -988,7 +988,7 @@ func (da *DefaultDirectoryAnalyzer) analyzeNamingPattern(paths []string, scope s
// Detect the dominant convention
convention := da.detectDominantNamingStyle(names)
return &NamingPattern{
Pattern: Pattern{
ID: fmt.Sprintf("%s_naming", scope),
@@ -996,7 +996,7 @@ func (da *DefaultDirectoryAnalyzer) analyzeNamingPattern(paths []string, scope s
Type: "naming",
Description: fmt.Sprintf("Naming convention for %ss", scope),
Confidence: da.calculateNamingConsistency(names, convention),
Examples: names[:min(5, len(names))],
Examples: names[:minInt(5, len(names))],
},
Convention: convention,
Scope: scope,
@@ -1100,12 +1100,12 @@ func (da *DefaultDirectoryAnalyzer) detectNamingStyle(name string) string {
return "unknown"
}
func (da *DefaultDirectoryAnalyzer) generateConventionRecommendations(analysis *ConventionAnalysis) []*Recommendation {
recommendations := []*Recommendation{}
func (da *DefaultDirectoryAnalyzer) generateConventionRecommendations(analysis *ConventionAnalysis) []*BasicRecommendation {
recommendations := []*BasicRecommendation{}
// Recommend consistency improvements
if analysis.Consistency < 0.8 {
recommendations = append(recommendations, &Recommendation{
recommendations = append(recommendations, &BasicRecommendation{
Type: "consistency",
Title: "Improve naming consistency",
Description: "Consider standardizing naming conventions across the project",
@@ -1118,7 +1118,7 @@ func (da *DefaultDirectoryAnalyzer) generateConventionRecommendations(analysis *
// Recommend architectural improvements
if len(analysis.OrganizationalPatterns) == 0 {
recommendations = append(recommendations, &Recommendation{
recommendations = append(recommendations, &BasicRecommendation{
Type: "architecture",
Title: "Consider architectural patterns",
Description: "Project structure could benefit from established architectural patterns",
@@ -1185,7 +1185,7 @@ func (da *DefaultDirectoryAnalyzer) findDirectoryDependencies(ctx context.Contex
if detector, exists := da.relationshipAnalyzer.dependencyDetectors[language]; exists {
imports := da.extractImports(string(content), detector.importPatterns)
// Check which imports refer to other directories
for _, imp := range imports {
for _, otherDir := range allDirs {
@@ -1210,7 +1210,7 @@ func (da *DefaultDirectoryAnalyzer) findDirectoryDependencies(ctx context.Contex
func (da *DefaultDirectoryAnalyzer) extractImports(content string, patterns []*regexp.Regexp) []string {
imports := []string{}
for _, pattern := range patterns {
matches := pattern.FindAllStringSubmatch(content, -1)
for _, match := range matches {
@@ -1225,12 +1225,11 @@ func (da *DefaultDirectoryAnalyzer) extractImports(content string, patterns []*r
func (da *DefaultDirectoryAnalyzer) isLocalDependency(importPath, fromDir, toDir string) bool {
// Simple heuristic: check if import path references the target directory
fromBase := filepath.Base(fromDir)
toBase := filepath.Base(toDir)
return strings.Contains(importPath, toBase) ||
strings.Contains(importPath, "../"+toBase) ||
strings.Contains(importPath, "./"+toBase)
return strings.Contains(importPath, toBase) ||
strings.Contains(importPath, "../"+toBase) ||
strings.Contains(importPath, "./"+toBase)
}
func (da *DefaultDirectoryAnalyzer) analyzeDirectoryRelationships(subdirs []string, dependencies []*DirectoryDependency) []*DirectoryRelation {
@@ -1399,7 +1398,7 @@ func (da *DefaultDirectoryAnalyzer) walkDirectoryHierarchy(rootPath string, curr
func (da *DefaultDirectoryAnalyzer) generateUCXLAddress(path string) (*ucxl.Address, error) {
cleanPath := filepath.Clean(path)
addr, err := ucxl.ParseAddress(fmt.Sprintf("dir://%s", cleanPath))
addr, err := ucxl.Parse(fmt.Sprintf("dir://%s", cleanPath))
if err != nil {
return nil, fmt.Errorf("failed to generate UCXL address: %w", err)
}
@@ -1407,7 +1406,7 @@ func (da *DefaultDirectoryAnalyzer) generateUCXLAddress(path string) (*ucxl.Addr
}
func (da *DefaultDirectoryAnalyzer) generateDirectorySummary(structure *DirectoryStructure) string {
summary := fmt.Sprintf("Directory with %d files and %d subdirectories",
summary := fmt.Sprintf("Directory with %d files and %d subdirectories",
structure.FileCount, structure.DirectoryCount)
// Add language information
@@ -1417,7 +1416,7 @@ func (da *DefaultDirectoryAnalyzer) generateDirectorySummary(structure *Director
langs = append(langs, fmt.Sprintf("%s (%d)", lang, count))
}
sort.Strings(langs)
summary += fmt.Sprintf(", containing: %s", strings.Join(langs[:min(3, len(langs))], ", "))
summary += fmt.Sprintf(", containing: %s", strings.Join(langs[:minInt(3, len(langs))], ", "))
}
return summary
@@ -1497,9 +1496,9 @@ func (da *DefaultDirectoryAnalyzer) calculateDirectorySpecificity(structure *Dir
return specificity
}
func min(a, b int) int {
func minInt(a, b int) int {
if a < b {
return a
}
return b
}
}