mirror-magi-meta-agent
Version:
AI-powered development planning and execution system with Supabase integration
354 lines (293 loc) ⢠10.9 kB
JavaScript
const fs = require('fs').promises;
const path = require('path');
/**
* Complete Plan Viewer
* Shows the entire plan with all tasks, validation steps, and implementation details
*/
class CompletePlanViewer {
constructor() {
this.plan = null;
}
async start() {
console.log('š Complete Plan Viewer');
console.log('ā'.repeat(50));
console.log('View your entire development plan with all details\n');
try {
await this.loadPlan();
await this.displayCompletePlan();
} catch (error) {
console.error('ā Error:', error.message);
}
}
async loadPlan() {
try {
const planPath = path.join('state', 'master-plan.json');
const planData = await fs.readFile(planPath, 'utf8');
this.plan = JSON.parse(planData);
console.log('ā
Plan loaded successfully\n');
} catch (error) {
throw new Error('No plan found. Create a plan first with "npm run plan:interactive"');
}
}
async displayCompletePlan() {
this.displayPlanHeader();
this.displayPlanContext();
await this.displayAllPhases();
this.displayPlanSummary();
this.displayValidationChecklist();
}
displayPlanHeader() {
console.log('šÆ PROJECT PLAN OVERVIEW');
console.log('ā'.repeat(60));
console.log(`š Goal: ${this.plan.goal}`);
console.log(`š Status: ${this.plan.status}`);
console.log(`š
Created: ${new Date(this.plan.created).toLocaleString()}`);
if (this.plan.lastModified) {
console.log(`āļø Last Modified: ${new Date(this.plan.lastModified).toLocaleString()}`);
}
console.log();
}
displayPlanContext() {
if (this.plan.context) {
console.log('š§ PROJECT CONTEXT');
console.log('ā'.repeat(30));
if (this.plan.context.requiredFeatures?.length > 0) {
console.log(`š Required Features: ${this.plan.context.requiredFeatures.join(', ')}`);
}
if (this.plan.context.designSystem) {
console.log(`šØ Design System: ${this.plan.context.designSystem}`);
}
if (this.plan.context.dataSource) {
console.log(`š¾ Data Source: ${this.plan.context.dataSource}`);
}
if (this.plan.context.userRequirements?.length > 0) {
console.log(`š„ User Requirements: ${this.plan.context.userRequirements.join(', ')}`);
}
console.log();
}
}
async displayAllPhases() {
console.log('š COMPLETE DEVELOPMENT PLAN');
console.log('ā'.repeat(60));
let totalTasks = 0;
for (let i = 0; i < this.plan.phases.length; i++) {
const phase = this.plan.phases[i];
console.log(`\n${i + 1}. ${phase.name.toUpperCase()}`);
console.log('ā'.repeat(50));
console.log(`š Description: ${phase.description}`);
if (phase.tasks && phase.tasks.length > 0) {
console.log(`š Tasks (${phase.tasks.length}):`);
for (let j = 0; j < phase.tasks.length; j++) {
const task = phase.tasks[j];
totalTasks++;
console.log(`\n ${j + 1}. ${task.description}`);
console.log(` š·ļø Type: ${task.type}`);
console.log(` š ID: ${task.id}`);
// Show task specifics if they exist
if (task.specifics && Object.keys(task.specifics).length > 0) {
console.log(` š Specifics:`);
Object.entries(task.specifics).forEach(([key, value]) => {
console.log(` ${key}: ${JSON.stringify(value)}`);
});
}
// Show dependencies
if (task.dependencies && task.dependencies.length > 0) {
console.log(` š Dependencies: ${task.dependencies.join(', ')}`);
}
// Generate and show validation steps for this task
const validationSteps = this.generateValidationSteps(task);
if (validationSteps.length > 0) {
console.log(` ā
Validation Steps:`);
validationSteps.forEach((step, idx) => {
console.log(` ${idx + 1}. ${step}`);
});
}
// Generate and show success criteria
const successCriteria = this.generateSuccessCriteria(task);
if (successCriteria.length > 0) {
console.log(` šÆ Success Criteria:`);
successCriteria.forEach((criteria, idx) => {
console.log(` ${idx + 1}. ${criteria}`);
});
}
}
} else {
console.log(`š Tasks: No tasks defined yet`);
}
}
console.log(`\nš TOTAL TASKS: ${totalTasks}`);
}
displayPlanSummary() {
console.log('\nš PLAN SUMMARY');
console.log('ā'.repeat(30));
const phaseCount = this.plan.phases.length;
const totalTasks = this.plan.phases.reduce((sum, phase) =>
sum + (phase.tasks ? phase.tasks.length : 0), 0
);
console.log(`š Phases: ${phaseCount}`);
console.log(`š Total Tasks: ${totalTasks}`);
// Task type breakdown
const taskTypes = {};
this.plan.phases.forEach(phase => {
if (phase.tasks) {
phase.tasks.forEach(task => {
taskTypes[task.type] = (taskTypes[task.type] || 0) + 1;
});
}
});
if (Object.keys(taskTypes).length > 0) {
console.log('\nš·ļø Task Types:');
Object.entries(taskTypes).forEach(([type, count]) => {
console.log(` ${type}: ${count}`);
});
}
}
displayValidationChecklist() {
console.log('\nā
PLAN STRUCTURE VALIDATION');
console.log('ā'.repeat(40));
const checks = this.validatePlanStructure();
checks.forEach(check => {
const icon = check.passed ? 'ā
' : 'ā';
console.log(`${icon} ${check.description}`);
if (!check.passed && check.suggestion) {
console.log(` š” Suggestion: ${check.suggestion}`);
}
});
const allPassed = checks.every(check => check.passed);
console.log(`\n${allPassed ? 'š' : 'ā ļø'} Plan Structure: ${allPassed ? 'VALID' : 'NEEDS ATTENTION'}`);
if (allPassed) {
console.log('\nš” Your plan is ready for execution!');
console.log(' Run: npm run plan:continue');
} else {
console.log('\nš” Fix structure issues before execution:');
console.log(' Run: npm run plan:edit');
}
}
generateValidationSteps(task) {
const steps = [];
// Common validation steps
steps.push('Verify code compiles without errors');
steps.push('Check that implementation matches requirements');
// Type-specific validation
switch (task.type) {
case 'component_creation':
steps.push('Component renders without errors');
steps.push('Props are properly typed');
steps.push('Component follows design system');
break;
case 'api_integration':
steps.push('API endpoints respond correctly');
steps.push('Error handling works properly');
steps.push('Data validation is in place');
break;
case 'configuration':
steps.push('Configuration files are valid');
steps.push('Settings are properly applied');
break;
case 'testing_implementation':
steps.push('All tests pass');
steps.push('Coverage meets requirements');
break;
}
return steps;
}
generateSuccessCriteria(task) {
const criteria = [];
// Common success criteria
criteria.push('Implementation is complete and functional');
criteria.push('Code follows project standards');
// Type-specific criteria
switch (task.type) {
case 'component_creation':
criteria.push('Component is reusable and well-documented');
criteria.push('Responsive design works correctly');
break;
case 'api_integration':
criteria.push('Integration is secure and performant');
criteria.push('All edge cases are handled');
break;
case 'configuration':
criteria.push('Configuration enhances project functionality');
criteria.push('No conflicts with existing settings');
break;
}
return criteria;
}
validatePlanStructure() {
const checks = [];
// Check required top-level fields
checks.push({
description: 'Plan has required ID',
passed: !!this.plan.id,
suggestion: 'Add unique plan ID'
});
checks.push({
description: 'Plan has goal defined',
passed: !!this.plan.goal && this.plan.goal.trim().length > 0,
suggestion: 'Define clear project goal'
});
checks.push({
description: 'Plan has phases array',
passed: Array.isArray(this.plan.phases),
suggestion: 'Ensure phases is an array'
});
checks.push({
description: 'Plan has at least one phase',
passed: this.plan.phases && this.plan.phases.length > 0,
suggestion: 'Add at least one development phase'
});
// Check phase structure
if (this.plan.phases) {
let allPhasesValid = true;
this.plan.phases.forEach((phase, index) => {
if (!phase.id || !phase.name || !phase.description) {
allPhasesValid = false;
}
});
checks.push({
description: 'All phases have required fields (id, name, description)',
passed: allPhasesValid,
suggestion: 'Ensure each phase has id, name, and description'
});
}
// Check task structure
let allTasksValid = true;
let hasTasksWithIds = false;
if (this.plan.phases) {
this.plan.phases.forEach(phase => {
if (phase.tasks) {
phase.tasks.forEach(task => {
if (!task.id || !task.description || !task.type) {
allTasksValid = false;
}
if (task.id) {
hasTasksWithIds = true;
}
});
}
});
}
checks.push({
description: 'All tasks have required fields (id, description, type)',
passed: allTasksValid,
suggestion: 'Ensure each task has id, description, and type'
});
// Check for execution readiness
const totalTasks = this.plan.phases.reduce((sum, phase) =>
sum + (phase.tasks ? phase.tasks.length : 0), 0
);
checks.push({
description: 'Plan has tasks ready for execution',
passed: totalTasks > 0,
suggestion: 'Add specific tasks to phases before execution'
});
return checks;
}
}
// Run the complete plan viewer
if (require.main === module) {
const viewer = new CompletePlanViewer();
viewer.start().catch(console.error);
}
module.exports = CompletePlanViewer;