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
435 lines (370 loc) • 15.4 kB
JavaScript
/**
* Context Preservation Engine
* Anti-compaction system that maintains project state and context
* Ensures project can be fully reconstructed after prompt compaction
*/
const fs = require('fs').promises;
const path = require('path');
class ContextPreservationEngine {
constructor() {
this.projectRoot = path.resolve(__dirname, '../..');
this.stateDir = path.join(this.projectRoot, 'docs/state');
this.decisionsDir = path.join(this.projectRoot, 'docs/decisions');
this.automationDir = path.join(this.projectRoot, 'docs/automation');
}
/**
* Preserve complete project state for compaction resistance
* Creates redundant, comprehensive project documentation
*/
async preserveCurrentState() {
const timestamp = new Date().toISOString();
console.log(`🔄 Preserving project state at ${timestamp}`);
try {
const projectState = {
timestamp,
metadata: await this.captureProjectMetadata(),
phase: await this.getCurrentPhase(),
progress: await this.captureProgress(),
architecture: await this.captureArchitecture(),
codebase: await this.captureCodebaseSnapshot(),
tests: await this.captureTestState(),
dependencies: await this.captureDependencies(),
decisions: await this.captureDecisionHistory(),
automationState: await this.captureAutomationState()
};
// Store in multiple locations for redundancy
await this.storeStateRedundantly(projectState, timestamp);
// Update living documentation
await this.updateLivingDocumentation(projectState);
// Create recovery instructions
await this.generateRecoveryInstructions(projectState);
console.log(`✅ Project state preserved successfully`);
return projectState;
} catch (error) {
console.error(`❌ Error preserving project state:`, error);
throw error;
}
}
/**
* Capture essential project metadata
*/
async captureProjectMetadata() {
const packageJson = JSON.parse(
await fs.readFile(path.join(this.projectRoot, 'package.json'), 'utf8')
);
return {
name: packageJson.name,
version: packageJson.version,
description: packageJson.description,
scripts: packageJson.scripts,
dependencies: packageJson.dependencies,
devDependencies: packageJson.devDependencies,
projectStructure: await this.captureDirectoryStructure()
};
}
/**
* Determine current development phase
*/
async getCurrentPhase() {
// Analyze completed tasks and current state to determine phase
const completedFeatures = await this.analyzeCompletedFeatures();
const testCoverage = await this.getTestCoverage();
const codeComplexity = await this.analyzeCodeComplexity();
return {
currentSprint: this.determineCurrentSprint(completedFeatures),
completedEpics: completedFeatures.epics,
completedStories: completedFeatures.stories,
testCoverage,
codeComplexity,
nextPriorities: this.determineNextPriorities(completedFeatures)
};
}
/**
* Capture current project progress
*/
async captureProgress() {
return {
calculatorModes: await this.analyzeCalculatorModes(),
testingInfrastructure: await this.analyzeTestingState(),
cicdPipeline: await this.analyzeCICDState(),
automationLevel: await this.analyzeAutomationLevel(),
qualityMetrics: await this.captureQualityMetrics()
};
}
/**
* Capture architectural decisions and patterns
*/
async captureArchitecture() {
return {
patterns: await this.identifyArchitecturalPatterns(),
modules: await this.analyzeModuleStructure(),
interfaces: await this.documentInterfaces(),
dataFlow: await this.mapDataFlow(),
designDecisions: await this.captureDesignDecisions()
};
}
/**
* Create snapshot of codebase with analysis
*/
async captureCodebaseSnapshot() {
const snapshot = {
files: {},
statistics: await this.calculateCodeStatistics(),
complexity: await this.analyzeCodeComplexity(),
dependencies: await this.analyzeDependencyGraph()
};
// Capture key files with metadata
const keyFiles = await this.identifyKeyFiles();
for (const file of keyFiles) {
const content = await fs.readFile(file, 'utf8');
snapshot.files[file] = {
content,
size: content.length,
lines: content.split('\n').length,
lastModified: (await fs.stat(file)).mtime,
analysis: await this.analyzeFile(content, file)
};
}
return snapshot;
}
/**
* Store project state with redundancy
*/
async storeStateRedundantly(projectState, timestamp) {
const stateFile = `project-state-${timestamp.replace(/[:.]/g, '-')}.json`;
// Primary storage
await fs.writeFile(
path.join(this.stateDir, stateFile),
JSON.stringify(projectState, null, 2)
);
// Backup storage in multiple locations
const backupLocations = [
path.join(this.projectRoot, '.backup', stateFile),
path.join(this.automationDir, 'latest-state.json')
];
for (const location of backupLocations) {
await fs.mkdir(path.dirname(location), { recursive: true });
await fs.writeFile(location, JSON.stringify(projectState, null, 2));
}
// Create compressed summary for quick reference
const summary = this.createStateSummary(projectState);
await fs.writeFile(
path.join(this.stateDir, 'current-state-summary.json'),
JSON.stringify(summary, null, 2)
);
}
/**
* Update living documentation based on current state
*/
async updateLivingDocumentation(projectState) {
// Update main README with current status
const readme = await this.generateLivingReadme(projectState);
await fs.writeFile(path.join(this.projectRoot, 'README.md'), readme);
// Update technical documentation
const techDoc = await this.generateTechnicalDocumentation(projectState);
await fs.writeFile(
path.join(this.automationDir, 'technical-overview.md'),
techDoc
);
// Update progress documentation
const progressDoc = await this.generateProgressDocumentation(projectState);
await fs.writeFile(
path.join(this.automationDir, 'current-progress.md'),
progressDoc
);
}
/**
* Generate recovery instructions for project reconstruction
*/
async generateRecoveryInstructions(projectState) {
const instructions = `# Project Recovery Instructions
Generated: ${projectState.timestamp}
## Quick Recovery (5 minutes)
1. \`npm install\` - Install dependencies
2. \`npm run test\` - Verify basic functionality
3. \`npm start\` - Launch calculator application
4. Check docs/state/current-state-summary.json for latest status
## Full Context Recovery (15 minutes)
1. Review docs/automation/technical-overview.md for architecture
2. Check docs/automation/current-progress.md for completion status
3. Examine src/ directory structure for implementation details
4. Run scripts/automation/context-analysis.js for full analysis
## Current Phase: ${projectState.phase.currentSprint}
## Next Priority: ${projectState.phase.nextPriorities[0] || 'Analyze current state'}
## Key Files to Examine:
${Object.keys(projectState.codebase.files).map(file => `- ${file}`).join('\n')}
## Automation Status:
- Testing Infrastructure: ${projectState.progress.testingInfrastructure.status}
- CI/CD Pipeline: ${projectState.progress.cicdPipeline.status}
- Calculator Modes: ${projectState.progress.calculatorModes.implemented.length}/12 implemented
## Recovery Verification:
- [ ] Calculator launches without errors
- [ ] All tests pass: \`npm test\`
- [ ] All 12 calculator modes are accessible
- [ ] Context preservation system is functional
For detailed recovery, see docs/recovery/ directory.
`;
await fs.writeFile(
path.join(this.projectRoot, 'docs/recovery', 'RECOVERY.md'),
instructions
);
}
/**
* Helper methods for analysis and data capture
*/
async analyzeCalculatorModes() {
// Analyze which calculator modes are implemented
try {
const modernHtml = await fs.readFile(
path.join(this.projectRoot, 'src/renderer/modern.html'),
'utf8'
);
const modes = [
'basic', 'scientific', 'programmer', 'financial',
'graphing', 'physics', 'chemistry', 'biology',
'health', 'environmental', 'construction', 'astronomy'
];
const implemented = modes.filter(mode =>
modernHtml.includes(`data-mode="${mode}"`)
);
return {
total: modes.length,
implemented: implemented,
pending: modes.filter(mode => !implemented.includes(mode)),
implementationStatus: `${implemented.length}/${modes.length}`
};
} catch (error) {
return { error: error.message, total: 12, implemented: [], pending: [] };
}
}
async analyzeTestingState() {
// Analyze current testing infrastructure
try {
const vitestConfig = await fs.readFile(
path.join(this.projectRoot, 'vitest.config.js'),
'utf8'
);
return {
status: 'configured',
framework: 'vitest',
hasConfig: true,
coverageEnabled: vitestConfig.includes('coverage')
};
} catch (error) {
return { status: 'not-configured', error: error.message };
}
}
async identifyKeyFiles() {
const keyPaths = [
'src/renderer/modern.html',
'src/renderer/modern-calculator.js',
'src/core/ScientificCalculator.js',
'src/core/MathEngine.js',
'src/constants/MathConstants.js',
'package.json',
'CLAUDE.md'
];
const existingFiles = [];
for (const filePath of keyPaths) {
const fullPath = path.join(this.projectRoot, filePath);
try {
await fs.access(fullPath);
existingFiles.push(fullPath);
} catch (error) {
// File doesn't exist, skip it
}
}
return existingFiles;
}
createStateSummary(projectState) {
return {
timestamp: projectState.timestamp,
phase: projectState.phase.currentSprint,
calculatorModes: `${projectState.progress.calculatorModes.implemented.length}/12`,
testCoverage: projectState.phase.testCoverage || 'unknown',
automationLevel: projectState.progress.automationLevel || 'basic',
nextPriority: projectState.phase.nextPriorities[0] || 'analyze-state',
keyMetrics: {
filesAnalyzed: Object.keys(projectState.codebase.files).length,
totalLines: projectState.codebase.statistics?.totalLines || 0,
testFiles: projectState.tests?.testFiles?.length || 0
}
};
}
// Placeholder methods for future implementation
async captureTestState() { return { status: 'pending', testFiles: [] }; }
async captureDependencies() { return { npm: [], dev: [] }; }
async captureDecisionHistory() { return []; }
async captureAutomationState() { return { level: 'basic' }; }
async captureDirectoryStructure() { return {}; }
async analyzeCompletedFeatures() { return { epics: [], stories: [] }; }
async getTestCoverage() { return 'unknown'; }
async analyzeCodeComplexity() { return { average: 'medium' }; }
async analyzeCICDState() { return { status: 'not-configured' }; }
async analyzeAutomationLevel() { return 'basic'; }
async captureQualityMetrics() { return {}; }
async identifyArchitecturalPatterns() { return []; }
async analyzeModuleStructure() { return {}; }
async documentInterfaces() { return {}; }
async mapDataFlow() { return {}; }
async captureDesignDecisions() { return []; }
async calculateCodeStatistics() { return { totalLines: 0 }; }
async analyzeDependencyGraph() { return {}; }
async analyzeFile(content, file) { return { type: 'unknown' }; }
determineCurrentSprint(features) {
// Logic to determine current sprint based on completed features
return 'Sprint 1: Foundation';
}
determineNextPriorities(features) {
return ['Set up testing infrastructure', 'Implement automation'];
}
async generateLivingReadme(state) {
return `# Calculator Suite - Enterprise Grade
Auto-generated: ${state.timestamp}
## Current Status: ${state.phase.currentSprint}
Calculator Modes: ${state.progress.calculatorModes.implementationStatus}
## Quick Start
\`\`\`bash
npm install
npm start
\`\`\`
## Project State
- Phase: ${state.phase.currentSprint}
- Test Coverage: ${state.phase.testCoverage}
- Automation Level: ${state.progress.automationLevel}
For detailed documentation, see docs/automation/
`;
}
async generateTechnicalDocumentation(state) {
return `# Technical Overview
Generated: ${state.timestamp}
## Architecture
Current phase: ${state.phase.currentSprint}
## Implementation Status
${state.progress.calculatorModes.implemented.map(mode => `✅ ${mode}`).join('\n')}
${state.progress.calculatorModes.pending.map(mode => `⏳ ${mode}`).join('\n')}
## Next Steps
${state.phase.nextPriorities.map(priority => `- ${priority}`).join('\n')}
`;
}
async generateProgressDocumentation(state) {
return `# Current Progress
Updated: ${state.timestamp}
## Sprint Progress: ${state.phase.currentSprint}
### Completed
${state.phase.completedStories.map(story => `✅ ${story}`).join('\n') || '- Initial setup'}
### In Progress
- Context preservation system implementation
### Next
${state.phase.nextPriorities.map(priority => `⏳ ${priority}`).join('\n')}
`;
}
}
module.exports = ContextPreservationEngine;
// Auto-execute if run directly
if (require.main === module) {
const engine = new ContextPreservationEngine();
engine.preserveCurrentState()
.then(() => console.log('✅ Context preservation completed'))
.catch(error => console.error('❌ Context preservation failed:', error));
}