UNPKG

@aaswe/codebase-ai

Version:

AI-Assisted Software Engineering (AASWE) - Rich codebase context for IDE LLMs

1,302 lines 63.9 kB
"use strict";
/**
 * Auto Analysis Workflow
 *
 * Enhanced workflow for automatic project analysis with comprehensive
 * codebase understanding, TTL generation, and knowledge graph population.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutoAnalysisWorkflow = void 0;
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const events_1 = require("events");
const logger_1 = __importDefault(require("../../utils/logger"));
const ProjectAnalysisService_1 = require("./ProjectAnalysisService");
const RDFService_1 = require("../layer1/rdf-generator/RDFService");
const EnhancedRDFGenerator_1 = require("../layer1/rdf-generator/EnhancedRDFGenerator");
const ModuleKnowledgeManager_1 = require("../layer1/module-knowledge/ModuleKnowledgeManager");
const TypeScriptAnalyzer_1 = require("../layer1/ast-analyzer/TypeScriptAnalyzer");
const PythonAnalyzer_1 = require("../layer1/ast-analyzer/PythonAnalyzer");
const JavaAnalyzer_1 = require("../layer1/ast-analyzer/JavaAnalyzer");
const BusinessContextPreserver_1 = require("./BusinessContextPreserver");
/**
 * Auto Analysis Workflow
 *
 * Provides enhanced automatic analysis with concrete information extraction,
 * comprehensive TTL generation, and knowledge graph population.
 */
class AutoAnalysisWorkflow extends events_1.EventEmitter {
    config;
    projectAnalysisService;
    rdfService;
    businessContextPreserver;
    moduleKnowledgeManager;
    analyzers;
    isInitialized = false;
    constructor(config = {}) {
        super();
        this.config = {
            projectRoot: process.cwd(),
            outputDirectory: '.aaswe/knowledge',
            enableConcreteExtraction: true,
            enableBusinessContextPlaceholders: true,
            enableKnowledgeGraphPopulation: true,
            enableMCPContextLoading: true,
            preserveBusinessContext: true,
            analysisDepth: 'comprehensive',
            languages: ['typescript', 'javascript', 'python', 'java'],
            includePatterns: ['**/*.ts', '**/*.js', '**/*.py', '**/*.java'],
            excludePatterns: [
                // General build/dependency directories
                '**/node_modules/**',
                '**/.git/**',
                '**/dist/**',
                '**/build/**',
                '**/out/**',
                '**/target/**',
                '**/bin/**',
                '**/obj/**',
                '**/lib/**',
                '**/libs/**',
                // Python
                '**/venv/**',
                '**/env/**',
                '**/.venv/**',
                '**/.env/**',
                '**/site-packages/**',
                '**/__pycache__/**',
                '**/*.pyc',
                '**/*.pyo',
                '**/*.pyd',
                '**/pip-log.txt',
                '**/pip-delete-this-directory.txt',
                // Java
                '**/target/**',
                '**/.m2/**',
                '**/.gradle/**',
                '**/gradle/**',
                '**/gradlew*',
                '**/*.class',
                '**/*.jar',
                '**/*.war',
                '**/*.ear',
                // .NET/C#
                '**/bin/**',
                '**/obj/**',
                '**/packages/**',
                '**/*.dll',
                '**/*.exe',
                '**/*.pdb',
                // Go
                '**/vendor/**',
                '**/*.exe',
                // Rust
                '**/target/**',
                '**/Cargo.lock',
                // C/C++
                '**/*.o',
                '**/*.so',
                '**/*.dylib',
                '**/*.a',
                // IDE and editor files
                '**/.vscode/**',
                '**/.idea/**',
                '**/*.swp',
                '**/*.swo',
                '**/*~',
                // Test and coverage
                '**/*.test.*',
                '**/*.spec.*',
                '**/test/**',
                '**/tests/**',
                '**/coverage/**',
                '**/.nyc_output/**',
                // Temporary and cache
                '**/tmp/**',
                '**/temp/**',
                '**/.cache/**',
                '**/cache/**',
                // OS files
                '**/.DS_Store',
                '**/Thumbs.db',
                // Logs
                '**/*.log',
                '**/logs/**'
            ],
            ...config
        };
        // Initialize services
        this.projectAnalysisService = new ProjectAnalysisService_1.ProjectAnalysisService({
            rootPath: this.config.projectRoot,
            outputDirectory: this.config.outputDirectory,
            languages: this.config.languages,
            includePatterns: this.config.includePatterns,
            excludePatterns: this.config.excludePatterns,
            generateTTL: true,
            enableWatching: false, // Controlled by trigger system
            preserveBusinessContext: this.config.preserveBusinessContext,
            analysisDepth: this.config.analysisDepth
        });
        this.rdfService = new RDFService_1.RDFService({
            includeBusinessContext: this.config.enableBusinessContextPlaceholders,
            generatePlaceholders: this.config.enableBusinessContextPlaceholders,
            optimizeForLLM: true,
            optimizeForNeo4j: this.config.enableKnowledgeGraphPopulation
        });
        this.moduleKnowledgeManager = new ModuleKnowledgeManager_1.ModuleKnowledgeManager({
            preserveBusinessContext: this.config.preserveBusinessContext,
            enableConflictResolution: true,
            enableLLMPreview: this.config.enableMCPContextLoading
        });
        // Initialize business context preserver
        this.businessContextPreserver = new BusinessContextPreserver_1.BusinessContextPreserver({
            preservationEnabled: this.config.preserveBusinessContext,
            backupEnabled: true,
            backupDirectory: path.join(this.config.projectRoot, '.aaswe', 'backups', 'business-context'),
            conflictResolution: 'merge',
            maxBackupVersions: 10
        });
        // Initialize analyzers
        this.analyzers = new Map();
        this.setupAnalyzers();
    }
    /**
     * Initialize the workflow
     */
    async initialize() {
        if (this.isInitialized) {
            return;
        }
        try {
            logger_1.default.info('Initializing Auto Analysis Workflow', {
                projectRoot: this.config.projectRoot,
                analysisDepth: this.config.analysisDepth,
                enableConcreteExtraction: this.config.enableConcreteExtraction
            });
            // Initialize all services
            await this.projectAnalysisService.initialize();
            await this.moduleKnowledgeManager.initialize();
            await this.businessContextPreserver.initialize();
            // Ensure output directory exists
            await fs.mkdir(path.resolve(this.config.projectRoot, this.config.outputDirectory), {
                recursive: true
            });
            this.isInitialized = true;
            logger_1.default.info('Auto Analysis Workflow initialized successfully');
        }
        catch (error) {
            logger_1.default.error('Failed to initialize Auto Analysis Workflow', { error });
            throw error;
        }
    }
    /**
     * Execute comprehensive automatic analysis
     */
    async executeComprehensiveAnalysis() {
        if (!this.isInitialized) {
            await this.initialize();
        }
        const startTime = Date.now();
        logger_1.default.info('Starting comprehensive automatic analysis');
        try {
            // Phase 1: Standard project analysis
            logger_1.default.info('Phase 1: Executing standard project analysis');
            const standardResult = await this.projectAnalysisService.analyzeProject();
            // Phase 2: Extract concrete information
            logger_1.default.info('Phase 2: Extracting concrete information');
            const concreteInformation = await this.extractConcreteInformation(standardResult);
            // Phase 3: Generate enhanced TTL files
            logger_1.default.info('Phase 3: Generating enhanced TTL files');
            const ttlResults = await this.generateEnhancedTTLFiles(standardResult, concreteInformation);
            // Phase 4: Populate knowledge graph
            let knowledgeGraphStats = { nodes: 0, relationships: 0 };
            if (this.config.enableKnowledgeGraphPopulation) {
                logger_1.default.info('Phase 4: Populating knowledge graph');
                try {
                    // Check if Neo4j is available before attempting population
                    const neo4jAvailable = await this.checkNeo4jAvailability();
                    if (neo4jAvailable) {
                        knowledgeGraphStats = await this.populateKnowledgeGraph(ttlResults);
                        logger_1.default.info('✅ Knowledge graph populated successfully');
                    }
                    else {
                        logger_1.default.warn('⚠️  Neo4j not available - skipping knowledge graph population');
                        logger_1.default.info('💡 To enable Neo4j: Set NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD in .env.aaswe');
                        // Still count entities for statistics from TTL files
                        knowledgeGraphStats = await this.populateKnowledgeGraph(ttlResults);
                    }
                }
                catch (error) {
                    logger_1.default.error('❌ Knowledge graph population failed', { error });
                    logger_1.default.info('💡 TTL files generated successfully - knowledge graph population is optional');
                    // Don't fail the entire workflow for Neo4j issues
                }
            }
            // Phase 5: Load MCP context
            let mcpContextSize = 0;
            if (this.config.enableMCPContextLoading) {
                logger_1.default.info('Phase 5: Loading MCP context');
                mcpContextSize = await this.loadMCPContext(ttlResults);
            }
            // Phase 6: Preserve and restore business context
            let preservationResult;
            if (this.config.preserveBusinessContext) {
                logger_1.default.info('Phase 6: Preserving business context');
                preservationResult = await this.businessContextPreserver.preserveBusinessContext(Array.from(ttlResults.keys()));
                // Restore business context to the newly generated TTL files
                if (preservationResult.success) {
                    logger_1.default.info('Phase 6b: Restoring business context to TTL files');
                    const restorationResult = await this.businessContextPreserver.restoreContext(Array.from(ttlResults.keys()));
                    // Update preservation result with restoration stats
                    if (restorationResult.success) {
                        preservationResult.statistics.enhancementsPreserved += restorationResult.statistics.enhancementsPreserved;
                        preservationResult.conflictsResolved += restorationResult.conflictsResolved;
                    }
                }
            }
            const endTime = Date.now();
            const totalDuration = endTime - startTime;
            // Create enhanced result
            const enhancedResult = {
                ...standardResult,
                duration: totalDuration,
                concreteInformation,
                knowledgeGraphNodes: knowledgeGraphStats.nodes,
                knowledgeGraphRelationships: knowledgeGraphStats.relationships,
                mcpContextSize,
                businessContextPreserved: preservationResult?.success || false,
                enhancementsPreserved: preservationResult?.preservedEnhancements || 0,
                ...(preservationResult && { preservationResult }),
                summary: {
                    ...standardResult.summary,
                    ttlFilesGenerated: ttlResults.size
                }
            };
            logger_1.default.info('Comprehensive analysis completed successfully', {
                duration: totalDuration,
                analyzedFiles: enhancedResult.summary.analyzedFiles,
                ttlFilesGenerated: enhancedResult.summary.ttlFilesGenerated,
                knowledgeGraphNodes: knowledgeGraphStats.nodes,
                mcpContextSize,
                businessContextPreserved: preservationResult?.success || false,
                enhancementsPreserved: preservationResult?.preservedEnhancements || 0
            });
            this.emit('analysis_completed', enhancedResult);
            return enhancedResult;
        }
        catch (error) {
            logger_1.default.error('Comprehensive analysis failed', { error });
            this.emit('analysis_failed', { error });
            throw error;
        }
    }
    /**
     * Execute incremental analysis for changed files
     */
    async executeIncrementalAnalysis(changedFiles) {
        if (!this.isInitialized) {
            await this.initialize();
        }
        logger_1.default.info('Starting incremental analysis', {
            changedFiles: changedFiles.length
        });
        try {
            // Analyze only changed files
            const standardResult = await this.projectAnalysisService.analyzeFiles(changedFiles);
            // Extract concrete information for changed files only
            const concreteInformation = await this.extractConcreteInformation(standardResult);
            // Update TTL files for changed modules
            const ttlResults = await this.updateTTLFiles(changedFiles, concreteInformation);
            // Update knowledge graph incrementally
            let knowledgeGraphStats = { nodes: 0, relationships: 0 };
            if (this.config.enableKnowledgeGraphPopulation) {
                knowledgeGraphStats = await this.updateKnowledgeGraph(ttlResults);
            }
            // Update MCP context
            let mcpContextSize = 0;
            if (this.config.enableMCPContextLoading) {
                mcpContextSize = await this.updateMCPContext(ttlResults);
            }
            // Phase 6: Preserve and restore business context for incremental analysis
            let preservationResult;
            if (this.config.preserveBusinessContext) {
                preservationResult = await this.businessContextPreserver.preserveBusinessContext(Array.from(ttlResults.keys()));
                // Restore business context to the updated TTL files
                if (preservationResult && preservationResult.success) {
                    const restorationResult = await this.businessContextPreserver.restoreContext(Array.from(ttlResults.keys()));
                    // Update preservation result with restoration stats
                    if (restorationResult.success) {
                        preservationResult.statistics.enhancementsPreserved += restorationResult.statistics.enhancementsPreserved;
                        preservationResult.conflictsResolved += restorationResult.conflictsResolved;
                    }
                }
            }
            const enhancedResult = {
                ...standardResult,
                concreteInformation,
                knowledgeGraphNodes: knowledgeGraphStats.nodes,
                knowledgeGraphRelationships: knowledgeGraphStats.relationships,
                mcpContextSize,
                businessContextPreserved: preservationResult?.success || false,
                enhancementsPreserved: preservationResult?.preservedEnhancements || 0,
                ...(preservationResult && { preservationResult })
            };
            logger_1.default.info('Incremental analysis completed', {
                changedFiles: changedFiles.length,
                duration: enhancedResult.duration
            });
            this.emit('incremental_analysis_completed', enhancedResult);
            return enhancedResult;
        }
        catch (error) {
            logger_1.default.error('Incremental analysis failed', { error });
            throw error;
        }
    }
    // Private methods
    setupAnalyzers() {
        this.analyzers.set('typescript', new TypeScriptAnalyzer_1.TypeScriptAnalyzer());
        this.analyzers.set('javascript', new TypeScriptAnalyzer_1.TypeScriptAnalyzer());
        this.analyzers.set('python', new PythonAnalyzer_1.PythonAnalyzer());
        this.analyzers.set('java', new JavaAnalyzer_1.JavaAnalyzer());
    }
    async extractConcreteInformation(analysisResult) {
        const concreteInfo = new Map();
        if (!this.config.enableConcreteExtraction) {
            return concreteInfo;
        }
        logger_1.default.debug('Extracting concrete information using MultiLanguageCodeGraphAnalyzer');
        try {
            // Use MultiLanguageCodeGraphAnalyzer for reliable multi-language analysis
            const { MultiLanguageCodeGraphAnalyzer } = await Promise.resolve().then(() => __importStar(require('./MultiLanguageCodeGraphAnalyzer')));
            const { Neo4jDatabaseService } = await Promise.resolve().then(() => __importStar(require('../layer2/neo4j-database/Neo4jDatabaseService')));
            // Create and connect Neo4j service
            const neo4jService = new Neo4jDatabaseService();
            // Try to connect to Neo4j if credentials are available
            const neo4jUri = process.env.NEO4J_URI || 'bolt://localhost:7687';
            const neo4jUsername = process.env.NEO4J_USERNAME || 'neo4j';
            const neo4jPassword = process.env.NEO4J_PASSWORD || 'aaswe-password';
            const config = {
                uri: neo4jUri,
                username: neo4jUsername,
                password: neo4jPassword,
                database: 'neo4j',
                encrypted: false
            };
            await neo4jService.connect(config);
            const analyzer = new MultiLanguageCodeGraphAnalyzer(neo4jService);
            // Analyze the project using the enhanced analyzer
            const analysisResult = await analyzer.analyzeMultiLanguageCodebase(this.config.projectRoot);
            // Disconnect after analysis
            await neo4jService.disconnect();
            // Convert MultiLanguageCodeGraphAnalyzer results to ConcreteInformation format
            for (const entity of analysisResult.entities) {
                if (entity.type === 'File') {
                    const filePath = entity.filePath;
                    // Get all entities for this file
                    const fileEntities = analysisResult.entities.filter(e => e.filePath === filePath);
                    const classes = fileEntities.filter(e => e.type === 'Class');
                    const methods = fileEntities.filter(e => e.type === 'Method' || e.type === 'Function');
                    const concrete = {
                        actualClassNames: classes.map(c => c.name),
                        actualMethodSignatures: methods.map(m => `${m.name}()`), // Simplified signature
                        actualDependencies: [], // Would need relationship analysis
                        actualExports: classes.filter(c => c.metadata?.visibility === 'public').map(c => c.name),
                        actualImports: [], // Would need import analysis
                        architecturalPatterns: this.detectArchitecturalPatternsFromNames([...classes.map(c => c.name), ...methods.map(m => m.name)]),
                        businessDomainIndicators: this.detectBusinessDomainFromNames([...classes.map(c => c.name), ...methods.map(m => m.name)]),
                        qualityMetrics: {
                            complexity: entity.metadata?.complexity || 1,
                            maintainability: 80, // Default value
                            testCoverage: 0,
                            documentation: 0
                        }
                    };
                    concreteInfo.set(filePath, concrete);
                }
            }
            logger_1.default.info('✅ Concrete information extracted using MultiLanguageCodeGraphAnalyzer', {
                filesProcessed: concreteInfo.size,
                totalEntities: analysisResult.entities.length,
                languages: analysisResult.languages.join(', ')
            });
        }
        catch (error) {
            logger_1.default.warn('⚠️ MultiLanguageCodeGraphAnalyzer failed, falling back to old analyzers', { error });
            // Fallback to old analyzer approach
            for (const fileResult of analysisResult.files) {
                if (fileResult.status !== 'success') {
                    continue;
                }
                try {
                    const analyzer = this.analyzers.get(fileResult.language);
                    if (!analyzer) {
                        continue;
                    }
                    const detailedAnalysis = await analyzer.analyzeFile(fileResult.filePath);
                    const concrete = await this.buildConcreteInformation(detailedAnalysis);
                    concreteInfo.set(fileResult.filePath, concrete);
                }
                catch (error) {
                    logger_1.default.warn('Failed to extract concrete information', {
                        filePath: fileResult.filePath,
                        error
                    });
                }
            }
        }
        logger_1.default.debug('Concrete information extraction completed', {
            filesProcessed: concreteInfo.size
        });
        return concreteInfo;
    }
    async buildConcreteInformation(analysis) {
        return {
            actualClassNames: analysis.classes.map(cls => cls.name),
            actualMethodSignatures: [
                ...analysis.classes.flatMap(cls => cls.methods.map(method => `${cls.name}.${method.name}(${method.parameters.map(p => p.name).join(', ')})`)),
                ...analysis.functions.map(func => `${func.name}(${func.parameters.map(p => p.name).join(', ')})`)
            ],
            actualDependencies: analysis.dependencies,
            actualExports: analysis.exports.map(exp => exp.name),
            actualImports: analysis.imports.map(imp => imp.source),
            architecturalPatterns: this.detectArchitecturalPatterns(analysis),
            businessDomainIndicators: this.detectBusinessDomainIndicators(analysis),
            qualityMetrics: {
                complexity: analysis.complexity.cyclomaticComplexity,
                maintainability: analysis.complexity.maintainabilityIndex,
                testCoverage: 0, // Would need test analysis
                documentation: this.calculateDocumentationScore(analysis)
            }
        };
    }
    detectArchitecturalPatterns(analysis) {
        const patterns = [];
        // Detect common patterns based on class and method names
        const classNames = analysis.classes.map(cls => cls.name.toLowerCase());
        const methodNames = analysis.functions.map(func => func.name.toLowerCase());
        if (classNames.some(name => name.includes('factory'))) {
            patterns.push('Factory Pattern');
        }
        if (classNames.some(name => name.includes('singleton'))) {
            patterns.push('Singleton Pattern');
        }
        if (classNames.some(name => name.includes('observer'))) {
            patterns.push('Observer Pattern');
        }
        if (classNames.some(name => name.includes('builder'))) {
            patterns.push('Builder Pattern');
        }
        if (methodNames.some(name => name.includes('middleware'))) {
            patterns.push('Middleware Pattern');
        }
        if (analysis.classes.some(cls => cls.methods.some(m => m.name === 'execute'))) {
            patterns.push('Command Pattern');
        }
        return patterns;
    }
    detectBusinessDomainIndicators(analysis) {
        const indicators = [];
        // Analyze class and method names for business domain clues
        const allNames = [
            ...analysis.classes.map(cls => cls.name),
            ...analysis.functions.map(func => func.name),
            ...analysis.classes.flatMap(cls => cls.methods.map(m => m.name))
        ].map(name => name.toLowerCase());
        const domainKeywords = {
            'E-commerce': ['order', 'cart', 'payment', 'product', 'customer', 'checkout'],
            'Finance': ['account', 'transaction', 'balance', 'payment', 'invoice', 'billing'],
            'Healthcare': ['patient', 'medical', 'diagnosis', 'treatment', 'doctor', 'appointment'],
            'Education': ['student', 'course', 'grade', 'assignment', 'teacher', 'class'],
            'HR': ['employee', 'payroll', 'attendance', 'performance', 'recruitment'],
            'CRM': ['lead', 'contact', 'opportunity', 'pipeline', 'sales'],
            'Content Management': ['article', 'post', 'content', 'publish', 'editor'],
            'Authentication': ['user', 'login', 'auth', 'token', 'session', 'permission']
        };
        for (const [domain, keywords] of Object.entries(domainKeywords)) {
            const matches = keywords.filter(keyword => allNames.some(name => name.includes(keyword)));
            if (matches.length >= 2) {
                indicators.push(domain);
            }
        }
        return indicators;
    }
    calculateDocumentationScore(analysis) {
        const totalElements = analysis.classes.length + analysis.functions.length;
        if (totalElements === 0)
            return 0;
        // Since documentation property doesn't exist in the types,
        // we'll use a heuristic based on naming conventions and comments
        const documentedElements = [
            ...analysis.classes.filter(cls => cls.name.length > 3 && // Meaningful names
                cls.methods.some(method => method.name.startsWith('get') || method.name.startsWith('set'))),
            ...analysis.functions.filter(func => func.name.length > 3 && // Meaningful names
                func.parameters.length > 0 // Has parameters (likely documented)
            )
        ].length;
        return Math.round((documentedElements / totalElements) * 100);
    }
    async generateEnhancedTTLFiles(analysisResult, concreteInfo) {
        const ttlResults = new Map();
        const enhancedRdfGenerator = new EnhancedRDFGenerator_1.EnhancedRDFGenerator({
            includeBusinessContext: this.config.enableBusinessContextPlaceholders,
            optimizeForLLM: this.config.enableMCPContextLoading,
            optimizeForNeo4j: this.config.enableKnowledgeGraphPopulation
        });
        // Group files by module/directory for TTL generation
        const moduleGroups = this.groupFilesByModule(analysisResult.files);
        for (const [modulePath, files] of moduleGroups) {
            try {
                // Create combined analysis result for the module
                const moduleAnalysis = await this.createModuleAnalysis(files, concreteInfo);
                // Generate enhanced RDF with concrete information
                const rdfResult = await enhancedRdfGenerator.generateEnhancedRDF(moduleAnalysis, modulePath);
                // Write TTL file to the specified output directory
                await this.writeTTLToOutputDirectory(modulePath, rdfResult);
                ttlResults.set(modulePath, rdfResult);
                logger_1.default.info('Enhanced TTL generated for module', {
                    modulePath,
                    size: rdfResult.size,
                    classCount: rdfResult.statistics.classCount,
                    methodCount: rdfResult.statistics.methodCount
                });
            }
            catch (error) {
                logger_1.default.error('Failed to generate enhanced TTL for module', { modulePath, error });
            }
        }
        return ttlResults;
    }
    groupFilesByModule(files) {
        const groups = new Map();
        for (const file of files) {
            const moduleDir = path.dirname(file.filePath);
            const ttlPath = path.join(moduleDir, '.module-knowledge.ttl');
            if (!groups.has(ttlPath)) {
                groups.set(ttlPath, []);
            }
            groups.get(ttlPath).push(file);
        }
        return groups;
    }
    async createModuleAnalysis(files, concreteInfo) {
        // Get the module directory path
        const fullModuleDir = path.dirname(files[0]?.filePath || '');
        const moduleName = path.basename(fullModuleDir);
        // Convert to relative path for Neo4j query since Neo4j stores relative paths
        // Remove the project root to get the relative path that matches Neo4j storage
        const relativePath = path.relative(this.config.projectRoot, fullModuleDir);
        const moduleDir = relativePath.replace(/\\/g, '/'); // Normalize path separators for cross-platform compatibility
        logger_1.default.info('Creating module analysis with Neo4j data', {
            fullModuleDir,
            moduleDir,
            moduleName,
            filesCount: files.length,
            projectRoot: this.config.projectRoot,
            pathConversion: `${fullModuleDir} -> ${moduleDir}`
        });
        // Initialize combined analysis
        const combinedAnalysis = {
            filePath: fullModuleDir,
            language: files[0]?.language || 'java',
            nodes: [],
            functions: [],
            classes: [],
            imports: [],
            exports: [],
            dependencies: [],
            complexity: {
                cyclomaticComplexity: 0,
                cognitiveComplexity: 0,
                linesOfCode: 0,
                maintainabilityIndex: 100,
                technicalDebt: 0
            },
            errors: [],
            timestamp: new Date()
        };
        try {
            // Query Neo4j directly for concrete information about all files in this module
            const { Neo4jDatabaseService } = await Promise.resolve().then(() => __importStar(require('../layer2/neo4j-database/Neo4jDatabaseService')));
            const neo4jService = new Neo4jDatabaseService();
            const config = {
                uri: process.env.NEO4J_URI || 'bolt://localhost:7687',
                username: process.env.NEO4J_USERNAME || 'neo4j',
                password: process.env.NEO4J_PASSWORD || 'aaswe-password',
                database: 'neo4j',
                encrypted: false
            };
            await neo4jService.connect(config);
            // Query for all entities in this module directory
            // Handle both absolute and relative paths by using CONTAINS instead of STARTS WITH
            const moduleQuery = `
        MATCH (f:File)-[:CONTAINS]->(entity)
        WHERE f.filePath CONTAINS $moduleDir OR f.filePath STARTS WITH $moduleDir
        RETURN f.filePath as filePath, f.name as fileName,
               collect({
                 type: labels(entity)[0],
                 name: entity.name,
                 id: entity.id,
                 startLine: entity.startLine,
                 endLine: entity.endLine,
                 complexity: entity.complexity,
                 visibility: entity.visibility,
                 isExported: entity.isExported,
                 parameters: entity.parameters,
                 returnType: entity.returnType
               }) as entities
      `;
            const session = neo4jService.getSession();
            logger_1.default.info('🔍 Neo4j Query Debug Info', {
                query: moduleQuery.replace(/\s+/g, ' ').trim(),
                moduleDir: moduleDir,
                queryParams: { moduleDir },
                moduleDirLength: moduleDir.length
            });
            const result = await session.run(moduleQuery, { moduleDir });
            logger_1.default.info('📊 Neo4j Query Results', {
                recordCount: result.records.length,
                moduleDir: moduleDir,
                queryExecuted: moduleQuery.replace(/\s+/g, ' ').trim(),
                sampleRecords: result.records.slice(0, 3).map(record => ({
                    filePath: record.get('filePath'),
                    fileName: record.get('fileName'),
                    entitiesCount: record.get('entities')?.length || 0,
                    firstEntity: record.get('entities')?.[0] || null
                }))
            });
            // If no records found, let's debug what's actually in Neo4j
            if (result.records.length === 0) {
                logger_1.default.warn('No records found for module, debugging Neo4j content', { moduleDir });
                // Query to see what files are actually in Neo4j
                const debugQuery = `
          MATCH (f:File)
          WHERE f.filePath CONTAINS "properties"
          RETURN f.filePath as filePath, f.name as fileName
          LIMIT 10
        `;
                const debugResult = await session.run(debugQuery);
                const propertiesFiles = debugResult.records.map(record => ({
                    filePath: record.get('filePath'),
                    fileName: record.get('fileName')
                }));
                logger_1.default.info('🔍 Files in Neo4j containing "properties"', {
                    query: debugQuery.replace(/\s+/g, ' ').trim(),
                    foundFilesCount: propertiesFiles.length,
                    foundFiles: propertiesFiles
                });
                // Additional debug: Show what the moduleDir looks like vs actual stored paths
                const allFilesQuery = `
          MATCH (f:File)
          RETURN f.filePath as filePath
          LIMIT 5
        `;
                const allFilesResult = await session.run(allFilesQuery);
                const samplePaths = allFilesResult.records.map(record => record.get('filePath'));
                logger_1.default.info('🔍 Sample file paths in Neo4j vs moduleDir', {
                    moduleDir: moduleDir,
                    moduleDir_length: moduleDir.length,
                    sampleStoredPaths: samplePaths,
                    pathComparison: samplePaths.map(path => ({
                        storedPath: path,
                        startsWithModuleDir: path.startsWith(moduleDir),
                        pathLength: path.length,
                        moduleDir: moduleDir
                    }))
                });
            }
            let totalClasses = 0;
            let totalMethods = 0;
            let totalComplexity = 0;
            let totalLines = 0;
            // Process each file's entities
            for (const record of result.records) {
                const filePath = record.get('filePath');
                const entities = record.get('entities');
                totalLines += 50; // Estimate lines per file
                for (const entity of entities) {
                    if (entity.type === 'Class') {
                        totalClasses++;
                        const classId = `class_${entity.name}_${entity.id}`;
                        // Query for methods in this class
                        const methodQuery = `
              MATCH (c:Class {id: $classId})-[:HAS_METHOD]->(m:Method)
              RETURN m.name as name, m.id as id, m.parameters as parameters,
                     m.returnType as returnType, m.complexity as complexity,
                     m.startLine as startLine, m.endLine as endLine,
                     m.visibility as visibility, m.isExported as isExported
            `;
                        const methodResult = await session.run(methodQuery, { classId: entity.id });
                        const methods = methodResult.records.map(methodRecord => {
                            totalMethods++;
                            totalComplexity += methodRecord.get('complexity') || 1;
                            return {
                                id: `method_${methodRecord.get('name')}_${methodRecord.get('id')}`,
                                name: methodRecord.get('name'),
                                parameters: JSON.parse(methodRecord.get('parameters') || '[]'),
                                returnType: methodRecord.get('returnType') || 'void',
                                complexity: methodRecord.get('complexity') || 1,
                                startLine: methodRecord.get('startLine') || 1,
                                endLine: methodRecord.get('endLine') || 1,
                                filePath: filePath,
                                isAsync: false,
                                isExported: methodRecord.get('isExported') || false,
                                visibility: methodRecord.get('visibility') || 'public',
                                dependencies: [],
                                calls: []
                            };
                        });
                        combinedAnalysis.classes.push({
                            id: classId,
                            name: entity.name,
                            methods: methods,
                            properties: [],
                            extends: undefined,
                            implements: [],
                            startLine: entity.startLine || 1,
                            endLine: entity.endLine || 1,
                            filePath: filePath,
                            isExported: entity.isExported || false,
                            visibility: entity.visibility || 'public',
                            isAbstract: false
                        });
                    }
                    if (entity.type === 'Method' || entity.type === 'Function') {
                        totalMethods++;
                        totalComplexity += entity.complexity || 1;
                        combinedAnalysis.functions.push({
                            id: `func_${entity.name}_${entity.id}`,
                            name: entity.name,
                            parameters: JSON.parse(entity.parameters || '[]'),
                            returnType: entity.returnType || 'void',
                            complexity: entity.complexity || 1,
                            startLine: entity.startLine || 1,
                            endLine: entity.endLine || 1,
                            filePath: filePath,
                            isAsync: false,
                            isExported: entity.isExported || false,
                            visibility: entity.visibility || 'public',
                            dependencies: [],
                            calls: []
                        });
                    }
                }
            }
            // Query for dependencies and imports
            const dependencyQuery = `
        MATCH (f:File)-[:IMPORTS]->(dep)
        WHERE f.filePath CONTAINS $moduleDir OR f.filePath STARTS WITH $moduleDir
        RETURN collect(DISTINCT dep.name) as dependencies
      `;
            const depResult = await session.run(dependencyQuery, { moduleDir });
            if (depResult.records.length > 0) {
                const deps = depResult.records[0].get('dependencies') || [];
                combinedAnalysis.dependencies = deps;
                // Create import declarations
                for (const dep of deps) {
                    combinedAnalysis.imports.push({
                        id: `import_${dep}_${Math.random().toString(36).substr(2, 9)}`,
                        source: dep,
                        imports: [],
                        filePath: moduleDir,
                        startLine: 1,
                        endLine: 1
                    });
                }
            }
            // Update complexity metrics
            combinedAnalysis.complexity.cyclomaticComplexity = totalComplexity;
            combinedAnalysis.complexity.linesOfCode = totalLines;
            combinedAnalysis.complexity.maintainabilityIndex = Math.max(20, 100 - (totalComplexity / totalMethods || 1) * 10);
            await session.close();
            await neo4jService.disconnect();
            logger_1.default.info('✅ Module analysis created with concrete Neo4j data', {
                moduleDir,
                filesCount: files.length,
                classesCount: totalClasses,
                methodsCount: totalMethods,
                dependenciesCount: combinedAnalysis.dependencies.length,
                totalComplexity,
                totalLines
            });
        }
        catch (error) {
            logger_1.default.warn('⚠️ Failed to query Neo4j for concrete data, falling back to file-based analysis', { error });
            // Fallback to the original approach if Neo4j is not available
            for (const file of files) {
                const concrete = concreteInfo.get(file.filePath);
                if (concrete) {
                    // Use the concrete information from the map
                    for (const className of concrete.actualClassNames) {
                        const classId = `class_${className}_${Math.random().toString(36).substr(2, 9)}`;
                        combinedAnalysis.classes.push({
                            id: classId,
                            name: className,
                            methods: [],
                            properties: [],
                            extends: undefined,
                            implements: [],
                            startLine: 1,
                            endLine: 1,
                            filePath: file.filePath,
                            isExported: concrete.actualExports.includes(className),
                            visibility: 'public',
                            isAbstract: false
                        });
                    }
                    combinedAnalysis.dependencies.push(...concrete.actualDependencies);
                    combinedAnalysis.complexity.cyclomaticComplexity += concrete.qualityMetrics.complexity;
                }
            }
        }
        return combinedAnalysis;
    }
    async populateKnowledgeGraph(ttlResults) {
        let totalNodes = 0;
        let totalRelationships = 0;
        // Check if Neo4j is available before attempting population
        const neo4jAvailable = await this.checkNeo4jAvailability();
        if (!neo4jAvailable) {
            logger_1.default.info('Neo4j not available, skipping knowledge graph population');
            logger_1.default.info('TTL files generated successfully and can be used by MCP servers');
            // Still count entities for statistics
            for (const [ttlPath, result] of ttlResults) {
                try {
                    const content = result.rdfContent;
                    const classMatches = content.match(/aide:Class/g) || [];
                    const methodMatches = content.match(/aide:Method/g) || [];
                    const functionMatches = content.match(/aide:Function/g) || [];
                    const dependencyMatches = content.match(/aide:dependsOn/g) || [];
                    const extendsMatches = content.match(/aide:extends/g) || [];
                    const nodes = classMatches.length + methodMatches.length + functionMatches.length;
                    const relationships = dependencyMatches.length + extendsMatches.length;
                    totalNodes += nodes;
                    totalRelationships += relationships;
                    logger_1.default.debug('Counted entities in TTL', { ttlPath, nodes, relationships });
                }
                catch (error) {
                    logger_1.default.warn('Failed to count entities in TTL', { ttlPath, error });
                }
            }
            return { nodes: totalNodes, relationships: totalRelationships };
        }
        // Neo4j is available, use MultiLanguageCodeGraphAnalyzer for actual source code analysis
        try {
            logger_1.default.info('🔍 Using MultiLanguageCodeGraphAnalyzer for comprehensive source code analysis');
            const { Neo4jDatabaseService } = await Promise.resolve().then(() => __importStar(require('../layer2/neo4j-database/Neo4jDatabaseService')));
            const { MultiLanguageCodeGraphAnalyzer } = await Promise.resolve().then(() => __importStar(require('./MultiLanguageCodeGraphAnalyzer')));
            const neo4jService = new Neo4jDatabaseService();
            const config = {
                uri: process.env.NEO4J_URI,
                username: process.env.NEO4J_USERNAME,
                password: process.env.NEO4J_PASSWORD,
                database: 'neo4j',
                encrypted: false
            };
            await neo4jService.connect(config);
            const analyzer = new MultiLanguageCodeGraphAnalyzer(neo4jService);
            // Analyze the entire project with multi-language support
            logger_1.default.info('🚀 Starting multi-language codebase analysis...');
            const analysisResult = await analyzer.analyzeMultiLanguageCodebase(this.config.projectRoot);
            totalNodes = analysisResult.entities.length;
            totalRelationships = analysisResult.relationships.length;
            logger_1.default.info('✅ Multi-language analysis completed successfully', {
                languages: analysisResult.languages.join(', '),
                totalFiles: analysisResult.statistics.totalFiles,
                totalClasses: analysisResult.statistics.totalClasses,
                totalMethods: analysisResult.statistics.totalMethods,
                totalLines: analysisResult.statistics.totalLines,
                totalNodes,
                totalRelationships
            });
            await neo4jService.disconnect();
        }
        catch (error) {
            logger_1.default.error('❌ Multi-language analysis failed, falling back to TTL-based population', { error });
            // Fallback to TTL-based population
            for (const [ttlPath, result] of ttlResults) {
                try {
                    const content = result.rdfContent;
                    const classMatches = content.match(/aide:Class/g) || [];
                    const methodMatches = content.match(/aide:Method/g) || [];
                    const functionMatches = content.match(/aide:Function/g) || [];
                    const dependencyMatches = content.match(/aide:dependsOn/g) || [];
                    const extendsMatches = content.match(/aide:extends/g) || [];
                    const nodes = classMatches.length + methodMatches.length + functionMatches.length;
                    const relationships = dependencyMatches.length + extendsMatches.length;
                    totalNodes += nodes;
                    totalRelationships += relationships;
                    // Create Neo4j nodes and relationships
                    await this.createKnowledgeGraphEntities(ttlPath, content, nodes, relationships);
                }
                catch (error) {
                    logger_1.default.error('Failed to populate knowledge graph for TTL', { ttlPath, error });
                }
            }
        }
        logger_1.default.info('Knowledge graph population completed', {
            totalNodes,
            totalRelationships,
            ttlFiles: ttlResults.size
        });
        return { nodes: totalNodes, relationships: totalRelationships };
    }
    async loadMCPContext(ttlResults) {
        let totalSize = 0;
        for (const [ttlPath, result] of ttlResults) {
            try {
                // Format content for MCP consumption
                const mcpContext = {
                    moduleId: path.basename(ttlPath, '.module-knowledge.ttl'),
                    filePath: ttlPath,
                    content: result.rdfContent,
                    timestamp: new Date().toISOString(),
                    size: result.size,
                    businessContext: this.extractBusinessContextFromTTL(result.rdfContent),
                    technicalSummary: this.extractTechnicalSummaryFromTTL(result.rdfContent)
                };
                // Store in MCP context cache
                await this.storeMCPContext(ttlPath, mcpContext);
                totalSize += result.size;
            }
            catch (error) {
                logger_1.default.error('Failed to load MCP context', { ttlPath, error });
            }
        }
        logger_1.default.info('MCP context loading completed', {
            totalSize,
            ttlFiles: ttlResults.size
        });
        return totalSize;
    }
    async updateTTLFiles(changedFiles, concreteInfo) {
        const ttlResults = new Map();
        for (const filePath of changedFiles) {
            try {
                const ttlPath = path.join(path.dirname(filePath), '.module-knowledge.ttl');
                const concrete = concreteInfo.get(filePath);
                if (concrete) {
                    // Create analysis result for RDF generation
                    const analysisResult = {
                        filePath,
                        language: this.getLanguageFromFile(filePath),
                        nodes: [],
                        functions: [],
                        classes: [],
                        imports: [],
                        exports: [],
                        dependencies: concrete.actualDependencies,
                        complexity: {
                            cyclomaticComplexity: concrete.qualityMetrics.complexity,
                            cognitiveComplexity: concrete.qualityMetrics.complexity,
                            linesOfCode: 100,
                            maintainabilityIndex: concrete.qualityMetrics.maintainability,
                            technicalDebt: 0
                        },
                        errors: [],
                        timestamp: new Date()
                    };
                    // Update TTL file with preservation of business context
                    const rdfResult = await this.rdfService.updateTTLFile(ttlPath, analysisResult, true);
                    ttlResults.set(ttlPath, rdfResult);
                    logger_1.default.debug('Updated TTL file', { filePath, ttlPath });
                }
            }
            catch (error) {
                logger_1.default.error('Failed to update TTL file', { filePath, error });
            }
        }
        return ttlResults;
    }
    async updateKnowledgeGraph(ttlResults) {
        let totalNodes = 0;
        let totalRelationships = 0;
        for (const [ttlPath, result] of ttlResults) {
            try {
                // Parse TTL content and extract entities for incremental update
                const content = result.rdfContent;
                const moduleId = this.extractModuleIdFromTTL(content);
                // Count entities
                const classMatches = content.match(/aide:Class/g) || [];
                const methodMatches = content.match(/aide:Method/g) || [];
                const dependencyMatches = content.match(/aide:dependsOn/g) || [];
                const nodes = classMatches.length + methodMatches.length;
                const relationships = dependencyMatches.length;
                totalNodes += nodes;
                totalRelationships += relationships;
                // Update specific module in knowledge graph
                await this.updateModuleInKnowledgeGraph(moduleId, content);
            }
            catch (error) {
                logger_1.default.error('Failed to update knowledge graph incrementally', { ttlPath, error });
            }
        }
        return { nodes: totalNodes, relationships: totalRelationships };
    }
    async updateMCPContext(ttlResults) {
        let totalSize = 0;
        for (const [ttlPath, result] of ttlResults) {
            try {
                const moduleId = this.extractModuleIdFromTTL(result.rdfContent);
                // Update MCP context for specific module
                const mcpContext = {
                    moduleId,
                    filePath: ttlPath,
                    content: result.rdfContent,
                    timestamp: new Date().toISOString(),
                    size: result.size,
                    lastUpdated: new Date().toISOString()
                };
                await this.updateMCPContextForModule(moduleId, mcpContext);
                totalSize += result.size;
            }
            catch (error) {
                logger_1.default.error('Failed to update MCP context incrementally', { ttlPath, error });
            }
        }
        return totalSize;
    }
    // Helper methods for the implemented functionality
    /**
     * Check if Neo4j is available for knowledge graph operations
     */
    async checkNeo4jAvailability() {
        try {
            // Check if Neo4j environment variables are set
            const neo4jUri = process.env.NEO4J_URI;
            const neo4jUsername = process.env.NEO4J_USERNAME;
            const neo4jPassword = process.env.NEO4J_PASSWORD;
            if (!neo4jUri || !neo4jUsername || !neo4jPassword) {
                logger_1.default.debug('Neo4j credentials not configured');
                return false;
            }
            // Try to connect to Neo4j directly
            const { Neo4jDatabaseService } = await Promise.resolve().then(() => __importStar(require('../layer2/neo4j-database/Neo4jDatabaseService')));
            const neo4jService = new Neo4jDatabaseService();
            const config = {
                uri: neo4jUri,
                username: neo4jUsername,
                password: neo4jPassword,
                database: 'neo4j'
            };
            await neo4jService.connect(config);
            const isHealthy = await neo4jService.testConnection();
            await neo4jService.disconnect();
            return isHealthy;
        }
        catch (error) {
            logger_1.default.debug('Neo4j availability check failed', { error: error instanceof Error ? error.message : 'Unknown error' });
            return false;
        }
    }
    async createKnowledgeGraphEntities(_ttlPath, content, nodes, relationships) {
        const moduleId = this.extractModuleIdFromTTL(content);
        // Create module node in Neo4j
        const moduleQuery = `
      MERGE (m:Module {id: $moduleId})
      SET m.filePath = $filePath,
          m.lastUpdated = datetime(),
          m.nodeCount = $nodes,
          m.relationshipCount = $relationships
    `;
        logger_1.default.debug('Would execute Neo4j query for module', { moduleId, nodes, relationships, query: moduleQuery });
        logger_1.default.debug('Would execute Neo4j query for module', { moduleId, nodes, relationships });
        // Extract and create class nodes
        const classMatches = content.match(/aide:(\w+)\s+a\s+aide:Class/g) || [];
        for (const match of classMatches) {
            const classNameMatch = match.match(/aide:(\w+)/);
            if (classNameMatch) {
                const className = classNameMatch[1];
                logger_1.default.debug('Would create class node', { moduleId, className });
            }
        }
    }
    async storeMCPContext(_ttlPath, context) {
        // Store in file system cache
        const cacheDir = path.join(this.config.projectRoot, '.aaswe', 'mcp-cache');
        await fs.mkdir(cacheDir, { recursive: true });
        const cacheFile = path.join(cacheDir, `${context.moduleId}.json`);
        await fs.writeFile(cacheFile, JSON.stringify(context, null, 2), 'utf8');
        logger_1.default.debug('Stored MCP context', { moduleId: context.moduleId, cacheFile });
    }
    extractBusinessContextFromTTL(content) {
        const businessContext = {};
        // Extract business domain
        const domainMatch = content.match(/aide:businessDomain\s+"([^"]+)"/);
        if (domainMatch) {
            businessContext.domain = domainMatch[1];
        }
        // Extract business rules
        const rulesMatches = content.match(/aide:businessRule\s+"([^"]+)"/g) || [];
        businessContext.rules = rulesMatches.map(match => match.replace(/aide:businessRule\s+"([^"]+)"/, '$1'));
        return businessContext;
    }
    extractTechnicalSummaryFromTTL(content) {
        const summary = {};
        // Count technical elements
        summary.classes = (content.match(/aide:Class/g) || []).length;
        summary.methods = (content.match(/aide:Method/g) || []).length;
        summary.functions = (content.match(/aide:Function/g) || []).length;
        summary.dependencies = (content.match(/aide:dependsOn/g) || []).length;
        return summary;
    }
    extractModuleIdFromTTL(content) {
        const moduleMatch = content.match(/aide:(\w+)\s+a\s+aide:Module/);
        return moduleMatch ? moduleMatch[1] : 'unknown_module';
    }
    async updateModuleInKnowledgeGraph(moduleId, content) {
        // Update specific module in Neo4j
        logger_1.default.debug('Would update module in knowledge graph', { moduleId });
        // Extract updated information and sync to graph
        const classes = (content.match(/aide:Class/g) || []).length;
        const methods = (content.match(/aide:Method/g) || []).length;
        logger_1.default.debug('Module update stats', { moduleId, classes, methods });
    }
    async updateMCPContextForModule(moduleId, context) {
        // Update specific module context
        const cacheDir = path.join(this.config.projectRoot, '.aaswe', 'mcp-cache');
        await fs.mkdir(cacheDir, { recursive: true });
        const cacheFile = path.join(cacheDir, `${moduleId}.json`);
        await fs.writeFile(cacheFile, JSON.stringify(context, null, 2), 'utf8');
        logger_1.default.debug('Updated MCP context for module', { moduleId });
    }
    /**
     * Write TTL content to the specified output directory
     */
    async writeTTLToOutputDirectory(modulePath, rdfResult) {
        try {
            // Create output directory if it doesn't exist
            await fs.mkdir(this.config.outputDirectory, { recursive: true });
            // Generate output file name based on module path
            // modulePath is like "src/services/.module-knowledge.ttl"
            const moduleDir = path.dirname(modulePath);
            const moduleDirName = path.basename(moduleDir);
            const outputFileName = `${moduleDirName}.module-knowledge.ttl`;
            const outputPath = path.join(this.config.outputDirectory, outputFileName);
            // Write TTL content to output file
            await fs.writeFile(outputPath, rdfResult.rdfContent, 'utf8');
            logger_1.default.info('TTL file written to output directory', {
                modulePath,
                outputPath,
                moduleDir,
                moduleDirName,
                size: rdfResult.size
            });
        }
        catch (error) {
            logger_1.default.error('Failed to write TTL to output directory', { modulePath, error });
            throw error;
        }
    }
    getLanguageFromFile(filePath) {
        const ext = path.extname(filePath).toLowerCase();
        const languageMap = {
            '.ts': 'typescript',
            '.tsx': 'typescript',
            '.js': 'javascript',
            '.jsx': 'javascript',
            '.py': 'python',
            '.java': 'java',
            '.go': 'go',
            '.rs': 'rust',
            '.cpp': 'cpp',
            '.hpp': 'cpp'
        };
        return languageMap[ext] || 'typescript';
    }
    /**
     * Detect architectural patterns from class and method names
     */
    detectArchitecturalPatternsFromNames(names) {
        const patterns = [];
        const lowerNames = names.map(name => name.toLowerCase());
        if (lowerNames.some(name => name.includes('factory'))) {
            patterns.push('Factory Pattern');
        }
        if (lowerNames.some(name => name.includes('singleton'))) {
            patterns.push('Singleton Pattern');
        }
        if (lowerNames.some(name => name.includes('observer'))) {
            patterns.push('Observer Pattern');
        }
        if (lowerNames.some(name => name.includes('builder'))) {
            patterns.push('Builder Pattern');
        }
        if (lowerNames.some(name => name.includes('middleware'))) {
            patterns.push('Middleware Pattern');
        }
        if (lowerNames.some(name => name.includes('command'))) {
            patterns.push('Command Pattern');
        }
        if (lowerNames.some(name => name.includes('strategy'))) {
            patterns.push('Strategy Pattern');
        }
        if (lowerNames.some(name => name.includes('adapter'))) {
            patterns.push('Adapter Pattern');
        }
        return patterns;
    }
    /**
     * Detect business domain indicators from class and method names
     */
    detectBusinessDomainFromNames(names) {
        const indicators = [];
        const lowerNames = names.map(name => name.toLowerCase());
        const domainKeywords = {
            'E-commerce': ['order', 'cart', 'payment', 'product', 'customer', 'checkout'],
            'Finance': ['account', 'transaction', 'balance', 'payment', 'invoice', 'billing'],
            'Healthcare': ['patient', 'medical', 'diagnosis', 'treatment', 'doctor', 'appointment'],
            'Education': ['student', 'course', 'grade', 'assignment', 'teacher', 'class'],
            'HR': ['employee', 'payroll', 'attendance', 'performance', 'recruitment'],
            'CRM': ['lead', 'contact', 'opportunity', 'pipeline', 'sales'],
            'Content Management': ['article', 'post', 'content', 'publish', 'editor'],
            'Authentication': ['user', 'login', 'auth', 'token', 'session', 'permission'],
            'Configuration Management': ['config', 'properties', 'settings', 'environment']
        };
        for (const [domain, keywords] of Object.entries(domainKeywords)) {
            const matches = keywords.filter(keyword => lowerNames.some(name => name.includes(keyword)));
            if (matches.length >= 1) {
                indicators.push(domain);
            }
        }
        return indicators;
    }
}
exports.AutoAnalysisWorkflow = AutoAnalysisWorkflow;
//# sourceMappingURL=AutoAnalysisWorkflow.js.map