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
JavaScript
/**
* 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;