UNPKG

alnilam-cli

Version:

Git-native AI career coach that converts multi-year ambitions into weekly execution

415 lines (414 loc) • 19.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.forecastCommand = exports.insightsCommand = exports.trendsCommand = void 0; const commander_1 = require("commander"); const api_js_1 = require("../lib/api.js"); const asciichart_1 = __importDefault(require("asciichart")); // Trends command const trendsCommand = new commander_1.Command('trends'); exports.trendsCommand = trendsCommand; trendsCommand .description('Analyze momentum and activity trends over time') .option('--days <n>', 'Number of days to analyze', '30') .option('--json', 'Output as JSON') .action(async (options) => { try { const days = parseInt(options.days); const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - days); console.log('šŸ“ˆ Momentum & Activity Trends'); console.log('═'.repeat(50)); // Fetch evaluations and summaries const [evaluationsResponse, summariesResponse, goalsResponse] = await Promise.all([ api_js_1.restClient.get('/evaluations', { params: { select: '*', 'created_at': `gte.${cutoffDate.toISOString()}`, order: 'created_at.asc' } }), api_js_1.restClient.get('/summaries', { params: { select: '*', 'created_at': `gte.${cutoffDate.toISOString()}`, order: 'created_at.asc' } }), api_js_1.restClient.get('/goals', { params: { select: '*', 'created_at': `gte.${cutoffDate.toISOString()}`, order: 'created_at.asc' } }) ]); const evaluations = evaluationsResponse.data || []; const summaries = summariesResponse.data || []; const goals = goalsResponse.data || []; if (options.json) { console.log(JSON.stringify({ evaluations, summaries, goals, analysis: { period_days: days } }, null, 2)); return; } // Calculate momentum statistics first let avgMomentum = 0; let momentumData = []; // Momentum trend analysis if (evaluations.length > 0) { console.log('šŸš€ Momentum Score Trends:'); console.log('─'.repeat(30)); momentumData = evaluations.map(evaluation => evaluation.momentum_score || 0); const chart = asciichart_1.default.plot(momentumData, { height: 8, colors: [asciichart_1.default.blue] }); console.log(chart); avgMomentum = Math.round(momentumData.reduce((a, b) => a + b, 0) / momentumData.length); const lastMomentum = momentumData[momentumData.length - 1]; const trend = lastMomentum > avgMomentum ? 'šŸ“ˆ Improving' : 'šŸ“‰ Declining'; console.log(`Average: ${avgMomentum}/100 | Latest: ${lastMomentum}/100 | Trend: ${trend}\n`); } // Activity patterns console.log('šŸ“Š Activity Patterns:'); console.log('─'.repeat(30)); const activityByDay = Array(7).fill(0); const dailySummaries = summaries.reduce((acc, summary) => { const date = new Date(summary.created_at).toDateString(); acc[date] = (acc[date] || 0) + 1; // Track day of week const dayOfWeek = new Date(summary.created_at).getDay(); activityByDay[dayOfWeek]++; return acc; }, {}); const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; const maxActivity = Math.max(...activityByDay); console.log('Activity by day of week:'); activityByDay.forEach((count, index) => { const barLength = Math.round((count / maxActivity) * 20); const bar = 'ā–ˆ'.repeat(barLength) + 'ā–‘'.repeat(20 - barLength); console.log(`${dayNames[index]}: [${bar}] ${count}`); }); // Goal creation trends console.log('\nšŸŽÆ Goal Creation Trends:'); console.log('─'.repeat(30)); const goalsByHorizon = goals.reduce((acc, goal) => { acc[goal.horizon] = (acc[goal.horizon] || 0) + 1; return acc; }, {}); Object.entries(goalsByHorizon).forEach(([horizon, count]) => { const emoji = horizon === 'weekly' ? 'šŸ“…' : horizon === 'quarterly' ? 'šŸ“Š' : horizon === 'annual' ? 'šŸ—“ļø' : 'šŸ”­'; console.log(`${emoji} ${horizon}: ${count} goals`); }); // Productivity insights console.log('\nšŸ’” Key Insights:'); console.log('─'.repeat(30)); const totalDays = Object.keys(dailySummaries).length; const avgDailyActivity = summaries.length / totalDays; const mostActiveDay = dayNames[activityByDay.indexOf(maxActivity)]; console.log(`šŸ“Š Active days: ${totalDays}/${days} (${Math.round((totalDays / days) * 100)}%)`); console.log(`⚔ Average daily summaries: ${avgDailyActivity.toFixed(1)}`); console.log(`šŸ”„ Most active day: ${mostActiveDay}`); if (evaluations.length >= 2) { const recentMomentum = evaluations.slice(-3).map(e => e.momentum_score || 0); const avgRecent = recentMomentum.reduce((a, b) => a + b, 0) / recentMomentum.length; const momentumTrend = avgRecent > avgMomentum ? 'gaining' : 'losing'; console.log(`šŸ“ˆ Momentum trend: ${momentumTrend} steam (${avgRecent.toFixed(0)} recent vs ${avgMomentum.toFixed(0)} average)`); } } catch (error) { console.error('āŒ Trends analysis error:', error.message); process.exit(1); } }); // Insights command const insightsCommand = new commander_1.Command('insights'); exports.insightsCommand = insightsCommand; insightsCommand .description('Generate AI-powered insights from your data patterns') .option('--weeks <n>', 'Number of weeks to analyze', '4') .option('--json', 'Output as JSON') .action(async (options) => { try { const weeks = parseInt(options.weeks); const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - (weeks * 7)); console.log('🧠 AI-Powered Insights'); console.log('═'.repeat(50)); // Fetch recent data const [evaluationsResponse, summariesResponse, goalsResponse, evidenceResponse] = await Promise.all([ api_js_1.restClient.get('/evaluations', { params: { select: '*', 'created_at': `gte.${cutoffDate.toISOString()}`, order: 'created_at.desc', limit: 10 } }), api_js_1.restClient.get('/summaries', { params: { select: '*', 'created_at': `gte.${cutoffDate.toISOString()}`, order: 'created_at.desc' } }), api_js_1.restClient.get('/goals', { params: { select: '*', order: 'created_at.desc' } }), api_js_1.restClient.get('/evidence', { params: { select: '*', 'created_at': `gte.${cutoffDate.toISOString()}`, order: 'created_at.desc' } }) ]); const evaluations = evaluationsResponse.data || []; const summaries = summariesResponse.data || []; const goals = goalsResponse.data || []; const evidence = evidenceResponse.data || []; if (options.json) { console.log(JSON.stringify({ evaluations, summaries, goals, evidence, analysis: { period_weeks: weeks } }, null, 2)); return; } // Momentum patterns console.log('šŸš€ Momentum Patterns:'); console.log('─'.repeat(30)); if (evaluations.length >= 2) { const scores = evaluations.map(e => e.momentum_score || 0); const avgScore = scores.reduce((a, b) => a + b, 0) / scores.length; const volatility = Math.sqrt(scores.reduce((acc, score) => acc + Math.pow(score - avgScore, 2), 0) / scores.length); console.log(`šŸ“Š Average momentum: ${avgScore.toFixed(0)}/100`); console.log(`šŸ“ˆ Consistency: ${volatility < 15 ? 'High' : volatility < 25 ? 'Medium' : 'Low'} (volatility: ${volatility.toFixed(1)})`); if (volatility > 25) { console.log('šŸ’” Consider focusing on consistent daily habits to stabilize momentum'); } } // Goal achievement patterns console.log('\nšŸŽÆ Achievement Patterns:'); console.log('─'.repeat(30)); const completedGoals = goals.filter(g => g.status === 'completed'); const activeGoals = goals.filter(g => g.status === 'active'); const completionRate = goals.length > 0 ? (completedGoals.length / goals.length) * 100 : 0; console.log(`āœ… Completion rate: ${completionRate.toFixed(0)}% (${completedGoals.length}/${goals.length})`); if (completionRate < 30) { console.log('šŸ’” Focus on smaller, more achievable goals to build momentum'); } else if (completionRate > 80) { console.log('šŸš€ Excellent completion rate! Consider setting more ambitious goals'); } // Activity consistency console.log('\nšŸ“… Activity Consistency:'); console.log('─'.repeat(30)); const activeDays = new Set(summaries.map(s => new Date(s.created_at).toDateString())).size; const totalDays = weeks * 7; const consistencyRate = (activeDays / totalDays) * 100; console.log(`šŸ“Š Active days: ${activeDays}/${totalDays} (${consistencyRate.toFixed(0)}%)`); if (consistencyRate < 50) { console.log('šŸ’” Try setting a daily 5-minute reflection habit to increase consistency'); } else if (consistencyRate > 80) { console.log('šŸ”„ Outstanding consistency! You\'re building powerful habits'); } // Evidence collection insights console.log('\nšŸ“ˆ Evidence Collection:'); console.log('─'.repeat(30)); const evidenceByType = evidence.reduce((acc, item) => { acc[item.type] = (acc[item.type] || 0) + 1; return acc; }, {}); const totalEvidence = evidence.length; console.log(`šŸ“Š Total evidence items: ${totalEvidence}`); Object.entries(evidenceByType).forEach(([type, count]) => { console.log(` • ${type}: ${count} items`); }); // Recommendations console.log('\nšŸŽÆ Personalized Recommendations:'); console.log('─'.repeat(30)); const recommendations = []; if (activeGoals.length > 3) { recommendations.push('Focus on 2-3 active goals max to avoid context switching overhead'); } if (summaries.length < (weeks * 3)) { recommendations.push('Increase daily reflection frequency - aim for 4+ summaries per week'); } if (evaluations.length === 0) { recommendations.push('Schedule weekly momentum evaluations to track progress trends'); } if (evidence.length < (summaries.length * 0.5)) { recommendations.push('Collect more evidence - aim for 1-2 evidence items per summary'); } if (recommendations.length === 0) { recommendations.push('Great momentum! Consider setting a stretch goal to push your limits'); } recommendations.forEach((rec, index) => { console.log(`${index + 1}. šŸ’” ${rec}`); }); } catch (error) { console.error('āŒ Insights analysis error:', error.message); process.exit(1); } }); // Forecast command const forecastCommand = new commander_1.Command('forecast'); exports.forecastCommand = forecastCommand; forecastCommand .description('Predict future momentum and goal completion likelihood') .option('--horizon <weeks>', 'Forecast horizon in weeks', '4') .option('--json', 'Output as JSON') .action(async (options) => { try { const horizon = parseInt(options.horizon); console.log('šŸ”® Momentum & Goal Forecast'); console.log('═'.repeat(50)); // Fetch recent data for forecasting const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - 28); // 4 weeks history const [evaluationsResponse, goalsResponse, summariesResponse] = await Promise.all([ api_js_1.restClient.get('/evaluations', { params: { select: '*', 'created_at': `gte.${cutoffDate.toISOString()}`, order: 'created_at.asc' } }), api_js_1.restClient.get('/goals', { params: { select: '*', status: 'eq.active' } }), api_js_1.restClient.get('/summaries', { params: { select: '*', 'created_at': `gte.${cutoffDate.toISOString()}`, order: 'created_at.asc' } }) ]); const evaluations = evaluationsResponse.data || []; const activeGoals = goalsResponse.data || []; const summaries = summariesResponse.data || []; if (options.json) { console.log(JSON.stringify({ evaluations, activeGoals, summaries, forecast: { horizon_weeks: horizon } }, null, 2)); return; } // Momentum forecast console.log('šŸ“ˆ Momentum Forecast:'); console.log('─'.repeat(30)); if (evaluations.length >= 2) { const scores = evaluations.map(e => e.momentum_score || 0); const currentMomentum = scores[scores.length - 1]; // Simple linear trend calculation const trend = scores.length > 1 ? (scores.slice(-3).reduce((a, b) => a + b, 0) / 3) - (scores.slice(-6, -3).reduce((a, b) => a + b, 0) / 3) : 0; const forecastMomentum = Math.max(0, Math.min(100, currentMomentum + (trend * horizon))); console.log(`šŸ”„ Current momentum: ${currentMomentum}/100`); console.log(`šŸ“Š Weekly trend: ${trend > 0 ? '+' : ''}${trend.toFixed(1)} points`); console.log(`šŸ”® Forecast (${horizon} weeks): ${forecastMomentum.toFixed(0)}/100`); const trendEmoji = trend > 5 ? 'šŸš€' : trend > 0 ? 'šŸ“ˆ' : trend > -5 ? 'āž”ļø' : 'šŸ“‰'; console.log(`${trendEmoji} Trajectory: ${trend > 5 ? 'Accelerating' : trend > 0 ? 'Growing' : trend > -5 ? 'Stable' : 'Declining'}`); } else { console.log('šŸ“Š Not enough momentum data for accurate forecasting'); console.log('šŸ’” Complete 2+ weekly evaluations to enable forecasting'); } // Goal completion forecast console.log('\nšŸŽÆ Goal Completion Forecast:'); console.log('─'.repeat(30)); if (activeGoals.length > 0) { activeGoals.forEach((goal, index) => { const createdDate = new Date(goal.created_at); const now = new Date(); const ageWeeks = Math.ceil((now.getTime() - createdDate.getTime()) / (1000 * 60 * 60 * 24 * 7)); // Simple heuristic based on goal age and current momentum const currentMomentum = evaluations.length > 0 ? evaluations[evaluations.length - 1].momentum_score || 50 : 50; let completionProbability = 0; if (goal.horizon === 'weekly') { completionProbability = Math.min(90, currentMomentum + (ageWeeks > 2 ? -20 : 10)); } else if (goal.horizon === 'quarterly') { completionProbability = Math.min(80, currentMomentum - (ageWeeks > 8 ? 15 : 0)); } else if (goal.horizon === 'annual') { completionProbability = Math.min(70, currentMomentum - 10); } else { completionProbability = Math.min(60, currentMomentum - 20); } const probabilityColor = completionProbability > 70 ? '🟢' : completionProbability > 40 ? '🟔' : 'šŸ”“'; console.log(`${index + 1}. ${goal.title.substring(0, 40)}...`); console.log(` ${probabilityColor} Completion likelihood: ${Math.max(0, completionProbability).toFixed(0)}%`); console.log(` šŸ“… Age: ${ageWeeks} weeks | šŸ”­ Horizon: ${goal.horizon}`); }); } else { console.log('šŸŽÆ No active goals to forecast'); console.log('šŸ’” Create goals to see completion predictions'); } // Activity forecast console.log('\nšŸ“Š Activity Forecast:'); console.log('─'.repeat(30)); const recentActivity = summaries.length; const weeklyActivity = recentActivity / 4; // 4 weeks of history const forecastActivity = weeklyActivity * horizon; console.log(`šŸ“ˆ Recent activity: ${recentActivity} summaries in 4 weeks`); console.log(`šŸ“Š Weekly average: ${weeklyActivity.toFixed(1)} summaries`); console.log(`šŸ”® Forecast (${horizon} weeks): ${forecastActivity.toFixed(0)} summaries`); if (weeklyActivity < 3) { console.log('āš ļø Low activity detected - consider setting daily reflection reminders'); } else if (weeklyActivity > 7) { console.log('šŸ”„ High activity! Great momentum building'); } // Risk factors console.log('\nāš ļø Risk Factors:'); console.log('─'.repeat(30)); const risks = []; if (evaluations.length > 0) { const lastMomentum = evaluations[evaluations.length - 1].momentum_score || 0; if (lastMomentum < 40) { risks.push('Low momentum score may impact goal completion'); } } if (activeGoals.length > 5) { risks.push('Too many active goals may lead to scattered focus'); } if (summaries.length < 8) { // Less than 2 per week risks.push('Inconsistent reflection habit may reduce self-awareness'); } if (risks.length === 0) { risks.push('No significant risk factors detected - maintain current trajectory!'); } risks.forEach((risk, index) => { console.log(`${index + 1}. āš ļø ${risk}`); }); } catch (error) { console.error('āŒ Forecast analysis error:', error.message); process.exit(1); } });