UNPKG

claude-code-automation

Version:

šŸš€ Generic project automation system with anti-compaction protection and recovery capabilities. Automatically detects project type (React, Node.js, Python, Rust, Go, Java) and provides intelligent analysis. Claude Code optimized - run 'welcome' after inst

658 lines (570 loc) • 24.3 kB
/** * Generic Context Analysis Script * Quick analysis of current project state and next recommended actions * Works with any codebase - automatically detects project type and provides relevant analysis * Used for rapid context reconstruction and progress assessment */ const fs = require('fs').promises; const path = require('path'); class ContextAnalyzer { constructor(projectRoot = null) { this.projectRoot = projectRoot || path.resolve(__dirname, '../..'); this.projectType = null; this.framework = null; } /** * Perform rapid context analysis */ async analyzeCurrentContext() { console.log('šŸ” Analyzing current project context...\n'); const analysis = { timestamp: new Date().toISOString(), project: await this.analyzeProjectStatus(), implementation: await this.analyzeImplementationStatus(), quality: await this.analyzeQualityStatus(), automation: await this.analyzeAutomationStatus(), nextActions: [] }; // Determine next actions based on analysis analysis.nextActions = this.determineNextActions(analysis); // Display results this.displayAnalysisResults(analysis); return analysis; } /** * Analyze overall project status */ async analyzeProjectStatus() { // Detect project type and framework first await this.detectProjectType(); const packageInfo = await this.getPackageInfo(); const status = { name: packageInfo.name || 'Unknown Project', type: this.projectType, framework: this.framework, version: packageInfo.version || '0.0.0', description: packageInfo.description || 'No description available', structure: await this.analyzeProjectStructure(), dependencies: await this.analyzeDependencyStatus(), canRun: await this.testBasicFunctionality() }; return status; } /** * Analyze implementation completeness based on project type */ async analyzeImplementationStatus() { const features = await this.analyzeFeatures(); const components = await this.analyzeCoreComponents(); return { features: features, components: components, overallCompletion: this.calculateOverallCompletion(features, components) }; } /** * Analyze code and test quality */ async analyzeQualityStatus() { return { testFramework: await this.checkTestFramework(), codeStructure: await this.analyzeCodeStructure(), automation: await this.checkAutomationScripts(), documentation: await this.checkDocumentation() }; } /** * Analyze automation system status */ async analyzeAutomationStatus() { return { scripts: await this.checkAutomationScripts(), preservation: await this.checkContextPreservation(), recovery: await this.checkRecoveryCapability(), scheduling: await this.checkScheduledTasks() }; } /** * Detect project type and framework automatically */ async detectProjectType() { const packageInfo = await this.getPackageInfo(); // Check for framework-specific dependencies and files if (packageInfo.dependencies || packageInfo.devDependencies) { const allDeps = { ...packageInfo.dependencies, ...packageInfo.devDependencies }; // Detect framework if (allDeps.react) { this.framework = 'React'; this.projectType = 'Frontend'; } else if (allDeps.vue) { this.framework = 'Vue'; this.projectType = 'Frontend'; } else if (allDeps.angular) { this.framework = 'Angular'; this.projectType = 'Frontend'; } else if (allDeps.express) { this.framework = 'Express'; this.projectType = 'Backend'; } else if (allDeps.electron) { this.framework = 'Electron'; this.projectType = 'Desktop Application'; } else if (allDeps.fastify) { this.framework = 'Fastify'; this.projectType = 'Backend'; } else if (allDeps.next) { this.framework = 'Next.js'; this.projectType = 'Full-stack'; } else if (packageInfo.type === 'module' || allDeps['@types/node']) { this.framework = 'Node.js'; this.projectType = 'Backend'; } } // Check for Python projects if (await this.fileExists('requirements.txt') || await this.fileExists('pyproject.toml') || await this.fileExists('setup.py')) { this.projectType = 'Python'; } // Check for other project types if (await this.fileExists('Cargo.toml')) { this.projectType = 'Rust'; } else if (await this.fileExists('go.mod')) { this.projectType = 'Go'; } else if (await this.fileExists('pom.xml') || await this.fileExists('build.gradle')) { this.projectType = 'Java'; } // Default fallback if (!this.projectType) { if (await this.fileExists('package.json')) { this.projectType = 'Node.js'; this.framework = 'Vanilla JavaScript'; } else { this.projectType = 'Unknown'; this.framework = 'Unknown'; } } } /** * Analyze project features based on detected type */ async analyzeFeatures() { switch (this.projectType) { case 'Frontend': return await this.analyzeFrontendFeatures(); case 'Backend': return await this.analyzeBackendFeatures(); case 'Desktop Application': return await this.analyzeDesktopFeatures(); case 'Python': return await this.analyzePythonFeatures(); default: return await this.analyzeGenericFeatures(); } } /** * Analyze frontend project features */ async analyzeFrontendFeatures() { const components = await this.countFilesByPattern(['src/components/**/*', 'components/**/*', 'src/**/*.tsx', 'src/**/*.jsx']); const pages = await this.countFilesByPattern(['src/pages/**/*', 'pages/**/*', 'src/views/**/*']); return { type: 'Frontend Application', components: components, pages: pages, status: `${components} components, ${pages} pages/views` }; } /** * Analyze backend project features */ async analyzeBackendFeatures() { const routes = await this.countFilesByPattern(['src/routes/**/*', 'routes/**/*', 'src/**/*route*']); const models = await this.countFilesByPattern(['src/models/**/*', 'models/**/*', 'src/**/*model*']); return { type: 'Backend Application', routes: routes, models: models, status: `${routes} routes, ${models} models` }; } /** * Analyze desktop application features */ async analyzeDesktopFeatures() { const mainProcess = await this.fileExists('src/main.js') || await this.fileExists('main.js'); const rendererProcess = await this.fileExists('src/renderer'); return { type: 'Desktop Application', mainProcess: mainProcess, rendererProcess: rendererProcess, status: `Main: ${mainProcess ? 'āœ…' : 'āŒ'}, Renderer: ${rendererProcess ? 'āœ…' : 'āŒ'}` }; } /** * Analyze Python project features */ async analyzePythonFeatures() { const modules = await this.countFilesByPattern(['**/*.py']); return { type: 'Python Application', modules: modules, status: `${modules} Python modules` }; } /** * Analyze generic project features */ async analyzeGenericFeatures() { const sourceFiles = await this.countSourceFiles(); const testFiles = await this.countTestFiles(); return { type: 'Generic Project', sourceFiles: sourceFiles, testFiles: testFiles, status: `${sourceFiles} source files, ${testFiles} test files` }; } /** * Analyze core component status based on project type */ async analyzeCoreComponents() { const components = await this.getProjectSpecificComponents(); const implemented = Object.values(components).filter(exists => exists).length; const total = Object.keys(components).length; return { components: components, status: `${implemented}/${total} core components`, completion: implemented / total }; } /** * Get project-specific core components to check */ async getProjectSpecificComponents() { switch (this.projectType) { case 'Frontend': return { entryPoint: await this.checkFile('src/index.js') || await this.checkFile('src/index.ts') || await this.checkFile('src/main.js'), appComponent: await this.checkFile('src/App.js') || await this.checkFile('src/App.tsx') || await this.checkFile('src/App.vue'), packageJson: await this.checkFile('package.json'), bundlerConfig: await this.checkFile('webpack.config.js') || await this.checkFile('vite.config.js') || await this.checkFile('rollup.config.js') }; case 'Backend': return { entryPoint: await this.checkFile('src/index.js') || await this.checkFile('src/server.js') || await this.checkFile('src/app.js'), routes: await this.directoryExists('src/routes') || await this.directoryExists('routes'), models: await this.directoryExists('src/models') || await this.directoryExists('models'), packageJson: await this.checkFile('package.json') }; case 'Desktop Application': return { mainProcess: await this.checkFile('src/main.js') || await this.checkFile('main.js') || await this.checkFile('src/main/main.js'), renderer: await this.directoryExists('src/renderer') || await this.checkFile('src/renderer.js'), packageJson: await this.checkFile('package.json'), electronConfig: await this.checkFile('electron-builder.json') || await this.checkFile('forge.config.js') }; case 'Python': return { mainModule: await this.checkFile('main.py') || await this.checkFile('app.py') || await this.checkFile('src/main.py'), requirements: await this.checkFile('requirements.txt') || await this.checkFile('pyproject.toml'), srcDirectory: await this.directoryExists('src'), setupFile: await this.checkFile('setup.py') || await this.checkFile('pyproject.toml') }; default: return { packageJson: await this.checkFile('package.json'), srcDirectory: await this.directoryExists('src'), readmeFile: await this.checkFile('README.md') || await this.checkFile('readme.md'), gitIgnore: await this.checkFile('.gitignore') }; } } /** * Check if a file exists */ async checkFile(relativePath) { try { await fs.access(path.join(this.projectRoot, relativePath)); return true; } catch { return false; } } /** * Determine next recommended actions based on project analysis */ determineNextActions(analysis) { const actions = []; // Based on core component completion if (analysis.implementation.components.completion < 0.8) { actions.push({ priority: 'HIGH', category: 'Infrastructure', action: 'Complete core project structure and essential files', command: this.getInfrastructureCommand(analysis.project.type), timeEstimate: '1-2 hours' }); } // Based on testing if (!analysis.quality.testFramework.configured) { actions.push({ priority: 'HIGH', category: 'Quality', action: 'Set up comprehensive testing framework', command: this.getTestingCommand(analysis.project.type), timeEstimate: '1-2 hours' }); } // Based on feature completion if (analysis.implementation.features.status.includes('0 ')) { actions.push({ priority: 'HIGH', category: 'Development', action: 'Implement core features and functionality', command: this.getFeatureCommand(analysis.project.type), timeEstimate: '2-4 hours' }); } // Based on automation if (analysis.automation.scripts.count < 3) { actions.push({ priority: 'MEDIUM', category: 'Automation', action: 'Complete automation infrastructure setup', command: 'npm run automation:daily', timeEstimate: '1 hour' }); } // Based on documentation if (!analysis.quality.documentation.hasReadme) { actions.push({ priority: 'LOW', category: 'Documentation', action: 'Create comprehensive project documentation', command: 'Add README.md and project documentation', timeEstimate: '30-60 minutes' }); } return actions.slice(0, 5); // Return top 5 actions } /** * Display analysis results in a formatted way */ displayAnalysisResults(analysis) { console.log('šŸ“Š PROJECT STATUS ANALYSIS'); console.log('=' .repeat(50)); console.log(`\nšŸ—ļø PROJECT: ${analysis.project.name}`); console.log(` Version: ${analysis.project.version}`); console.log(` Can Run: ${analysis.project.canRun ? 'āœ… Yes' : 'āŒ No'}`); console.log(`\nšŸŽÆ PROJECT TYPE: ${analysis.project.type}`); console.log(` Framework: ${analysis.project.framework}`); console.log(` Features: ${analysis.implementation.features.status}`); console.log(`\nšŸ› ļø CORE COMPONENTS: ${analysis.implementation.components.status}`); Object.entries(analysis.implementation.components.components).forEach(([name, exists]) => { console.log(` ${name}: ${exists ? 'āœ…' : 'āŒ'}`); }); console.log(`\nšŸ”§ AUTOMATION STATUS:`); console.log(` Scripts Available: ${analysis.automation.scripts.count}`); console.log(` Context Preservation: ${analysis.automation.preservation ? 'āœ…' : 'āŒ'}`); console.log(` Recovery Capability: ${analysis.automation.recovery ? 'āœ…' : 'āŒ'}`); console.log(`\nšŸŽÆ NEXT PRIORITY ACTIONS:`); analysis.nextActions.forEach((action, index) => { console.log(`\n ${index + 1}. [${action.priority}] ${action.action}`); console.log(` Category: ${action.category}`); console.log(` Command: ${action.command}`); console.log(` Time: ${action.timeEstimate}`); }); console.log('\n' + '='.repeat(50)); console.log(`Analysis completed at ${analysis.timestamp}`); console.log('šŸ’” Run specific commands above to continue development'); } // Helper methods for command generation getInfrastructureCommand(projectType) { switch (projectType) { case 'Frontend': return 'Create src/index.js, src/App.js, and configure bundler'; case 'Backend': return 'Set up server entry point, routes, and database models'; case 'Desktop Application': return 'Configure Electron main process and renderer'; case 'Python': return 'Create main.py, requirements.txt, and src/ directory'; default: return 'Set up basic project structure'; } } getTestingCommand(projectType) { if (projectType === 'Python') { return 'pip install pytest && setup pytest configuration'; } else { return 'npm install testing framework (Jest/Vitest) && configure'; } } getFeatureCommand(projectType) { switch (projectType) { case 'Frontend': return 'Implement components, pages, and user interface'; case 'Backend': return 'Build API endpoints, database integration, and business logic'; case 'Desktop Application': return 'Develop application features and user interface'; case 'Python': return 'Implement core functionality and modules'; default: return 'Implement core project functionality'; } } // Helper methods async getPackageInfo() { try { const packageJson = JSON.parse( await fs.readFile(path.join(this.projectRoot, 'package.json'), 'utf8') ); return packageJson; } catch { return { name: 'Unknown Project', version: '0.0.0' }; } } async getProjectVersion() { const packageInfo = await this.getPackageInfo(); return packageInfo.version || 'unknown'; } async analyzeProjectStructure() { const structure = {}; const keyPaths = ['src', 'docs', 'scripts', 'package.json', 'CLAUDE.md']; for (const pathName of keyPaths) { structure[pathName] = await this.checkFile(pathName); } return structure; } async analyzeDependencyStatus() { try { const packageJson = JSON.parse( await fs.readFile(path.join(this.projectRoot, 'package.json'), 'utf8') ); return { production: Object.keys(packageJson.dependencies || {}).length, development: Object.keys(packageJson.devDependencies || {}).length, hasElectron: !!packageJson.devDependencies?.electron, hasVitest: !!packageJson.devDependencies?.vitest }; } catch { return { production: 0, development: 0, hasElectron: false, hasVitest: false }; } } async testBasicFunctionality() { // Test if the main entry point exists and is valid return await this.checkFile('src/main/main.js') && await this.checkFile('package.json'); } async checkTestFramework() { const hasVitestConfig = await this.checkFile('vitest.config.js'); const hasTestScripts = await this.checkFile('package.json'); return { framework: 'vitest', configured: hasVitestConfig, hasScripts: hasTestScripts }; } async analyzeCodeStructure() { const structure = { modular: await this.checkFile('src/core') && await this.checkFile('src/renderer'), separation: await this.checkFile('src/main') && await this.checkFile('src/renderer'), constants: await this.checkFile('src/constants'), utils: await this.checkFile('src/utils') }; const score = Object.values(structure).filter(Boolean).length / Object.keys(structure).length; return { ...structure, score: score, rating: score > 0.8 ? 'excellent' : score > 0.6 ? 'good' : 'needs improvement' }; } async checkAutomationScripts() { const scripts = { contextPreservation: await this.checkFile('scripts/automation/context-preservation.js'), autoRecovery: await this.checkFile('scripts/automation/auto-recovery.js'), dailyCycle: await this.checkFile('scripts/automation/daily-automation-cycle.js'), contextAnalysis: await this.checkFile('scripts/automation/context-analysis.js') }; const count = Object.values(scripts).filter(Boolean).length; return { ...scripts, count: count, level: count / 4 }; } async checkDocumentation() { return { hasReadme: await this.checkFile('README.md'), hasClaude: await this.checkFile('CLAUDE.md'), hasDocs: await this.checkFile('docs'), hasAutomationDocs: await this.checkFile('docs/automation') }; } async checkContextPreservation() { return await this.checkFile('scripts/automation/context-preservation.js'); } async checkRecoveryCapability() { return await this.checkFile('scripts/automation/auto-recovery.js'); } async checkScheduledTasks() { return await this.checkFile('scripts/automation/daily-automation-cycle.js'); } calculateOverallCompletion(features, components) { // Calculate feature completion based on whether any features were detected const featureProgress = features.status.includes('0 ') ? 0.3 : 0.8; const compProgress = components.completion; return (featureProgress + compProgress) / 2; } // Utility methods for file pattern matching and counting async countFilesByPattern(patterns) { let count = 0; for (const pattern of patterns) { try { const { execSync } = require('child_process'); const result = execSync(`find ${this.projectRoot} -name "${pattern}" 2>/dev/null | wc -l`, { encoding: 'utf8' }); count += parseInt(result.trim()); } catch (error) { // Pattern not found or error - continue } } return count; } async directoryExists(dirPath) { try { const fullPath = path.join(this.projectRoot, dirPath); const stat = await fs.stat(fullPath); return stat.isDirectory(); } catch { return false; } } async fileExists(filePath) { try { await fs.access(path.join(this.projectRoot, filePath)); return true; } catch { return false; } } async countSourceFiles() { const jsFiles = await this.countFilesByPattern(['**/*.js', '**/*.ts', '**/*.jsx', '**/*.tsx']); const pyFiles = await this.countFilesByPattern(['**/*.py']); return jsFiles + pyFiles; } async countTestFiles() { return await this.countFilesByPattern(['**/*test*', '**/*spec*', '**/test_*']); } } // Auto-execute if run directly if (require.main === module) { const analyzer = new ContextAnalyzer(); analyzer.analyzeCurrentContext() .then(() => console.log('\nāœ… Context analysis completed')) .catch(error => { console.error('āŒ Context analysis failed:', error); process.exit(1); }); } module.exports = ContextAnalyzer;