acs-framework-cli
Version:
🚀 CLI inteligente para configurar automáticamente el Augmented Context Standard (ACS) Framework. Context-as-Code que convierte tu conocimiento en un activo versionado.
376 lines (318 loc) • 13.4 kB
JavaScript
const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
const inquirer = require('inquirer');
/**
* NUEVO ONBOARDING SIMPLIFICADO
* Máximo 3 preguntas, enfoque en valor inmediato
*
* Filosofía ACS: "Context-as-Code" - no interrogatorios, sino valor directo
*/
class StreamlinedOnboarding {
constructor(targetDir) {
this.targetDir = targetDir;
this.projectInsights = null;
}
async run() {
console.clear();
await this.showWelcome();
// Cargar preferencias del usuario
const UserPreferences = require('./user-preferences');
this.userPrefs = new UserPreferences();
await this.userPrefs.load();
// Análisis automático primero
await this.analyzeProject();
// Solo preguntar si es necesario
const userPreferences = await this.getSmartPreferences();
// Recomendación directa basada en contexto
const recommendation = this.generateRecommendation(userPreferences);
return {
insights: this.projectInsights,
preferences: userPreferences,
recommendation
};
}
async showWelcome() {
console.log(chalk.cyan(`
█████╗ ██████╗ ███████╗
██╔══██╗██╔════╝ ██╔════╝
███████║██║ ███████╗
██╔══██║██║ ╚════██║
██║ ██║╚██████╗ ███████║
╚═╝ ╚═╝ ╚═════╝ ╚══════╝
${chalk.white.bold('ACS FRAMEWORK')} - ${chalk.gray('Hub Central de Control')}
`));
}
async analyzeProject() {
console.log(chalk.yellow('🔍 Analizando tu proyecto...'));
const SmartComplexityAnalyzer = require('./smart-complexity-analyzer');
const complexityAnalyzer = new SmartComplexityAnalyzer(this.targetDir);
const complexityAnalysis = await complexityAnalyzer.analyze();
// Detectar tipo de proyecto de manera inteligente
const projectType = await this.detectProjectType();
// Detectar si ya tiene ACS
const hasACS = await fs.pathExists(path.join(this.targetDir, '.context'));
this.projectInsights = {
projectType,
complexity: complexityAnalysis,
hasACS,
directory: path.basename(this.targetDir)
};
// Mostrar resumen conciso
this.showProjectSummary();
}
showProjectSummary() {
const { projectType, complexity, hasACS, directory } = this.projectInsights;
console.log(chalk.magenta('\n📊 Tu proyecto:'));
console.log(` 📁 ${chalk.cyan(directory)} - ${chalk.yellow(projectType)}`);
console.log(` ${complexity.icon} Complejidad: ${complexity.description}`);
console.log(` ⏱️ Setup estimado: ${chalk.cyan(complexity.estimatedSetupTime)}`);
if (hasACS) {
console.log(` ✅ ACS ya configurado`);
} else {
console.log(` 💡 ACS no configurado - ${chalk.green('¡perfecto para empezar!')}`);
}
// Mostrar valor específico para este proyecto
this.showProjectSpecificValue();
}
showProjectSpecificValue() {
const { projectType, complexity } = this.projectInsights;
console.log(chalk.cyan('\n🎁 ACS te ayudará con:'));
// Beneficios centrados en el desarrollador, no en riesgos empresariales
console.log(chalk.green(' ✨ IA que respeta tu arquitectura y no alucina'));
console.log(chalk.green(' � Eliminar las "cajas negras" que frenan la innovación'));
console.log(chalk.green(' 🧠 Convertir tu conocimiento en un activo del equipo'));
console.log(chalk.green(' ⚡ Onboarding instantáneo sin interrumpir a seniors'));
// Solo agregar beneficio específico si es relevante
if (complexity.level === 'complex') {
console.log(chalk.green(' 🎯 Navegación inteligente en proyectos complejos'));
} else {
console.log(chalk.green(' 🎯 Base sólida que escala con tu proyecto'));
}
}
async getSmartPreferences() {
// Si ya tenemos preferencias recientes, usarlas SIN PREGUNTAR
if (this.userPrefs.hasPreferences() && this.userPrefs.isRecentUser()) {
const savedPrefs = this.userPrefs.getPreferences();
console.log(chalk.blue(`👋 Usando tus preferencias guardadas (${savedPrefs.comfortLevel})`));
console.log(chalk.gray(' Tip: usa "acs-master --reset-prefs" para cambiarlas\n'));
return {
comfortLevel: savedPrefs.comfortLevel,
priority: savedPrefs.defaultPriority || 'fast-setup',
teamContext: savedPrefs.teamContext || 'solo'
};
}
// SOLO SI ES PRIMERA VEZ - hacer onboarding
console.log(chalk.cyan('\n🤔 Primera vez usando ACS - configuración rápida:'));
const preferences = await this.askEssentialQuestions();
// Guardar para NO preguntar otra vez
await this.userPrefs.save({
comfortLevel: preferences.comfortLevel,
defaultPriority: preferences.priority,
teamContext: preferences.teamContext
});
console.log(chalk.green('✅ Preferencias guardadas - no se preguntarán de nuevo'));
return preferences;
}
async askEssentialQuestions() {
console.log(chalk.yellow('⚡ 3 preguntas rápidas para optimizar tu experiencia:\n'));
// PREGUNTA 1: Estilo de trabajo real con diferencias claras
const { workStyle } = await inquirer.prompt([{
type: 'list',
name: 'workStyle',
message: '¿Cómo prefieres trabajar con herramientas CLI?',
choices: [
{
name: '🚀 Directo - mínimas preguntas, máxima velocidad',
value: 'direct',
short: 'Directo'
},
{
name: '🎯 Balanceado - algunas opciones, explicaciones concisas',
value: 'guided',
short: 'Balanceado'
},
{
name: '📚 Educativo - explicaciones detalladas, tutoriales',
value: 'educational',
short: 'Educativo'
}
],
default: 'guided'
}]);
// PREGUNTA 2: Solo si proyecto complejo O usuario educativo
let priority = 'fast-setup';
if (this.projectInsights.complexity.level === 'complex' || workStyle === 'educational') {
const { priorityChoice } = await inquirer.prompt([{
type: 'list',
name: 'priorityChoice',
message: this.projectInsights.complexity.level === 'complex'
? 'Proyecto complejo detectado. ¿Tu estrategia?'
: '¿Prefieres setup rápido o completo?',
choices: [
{ name: '⚡ Setup básico ahora, optimizar después', value: 'fast-setup' },
{ name: '🎯 Setup completo desde el inicio', value: 'thorough-setup' }
],
default: workStyle === 'direct' ? 'fast-setup' : 'thorough-setup'
}]);
priority = priorityChoice;
} else {
// Auto-asignar basado en estilo
priority = workStyle === 'direct' ? 'fast-setup' : 'standard-setup';
}
// PREGUNTA 3: Solo si no tiene ACS
let teamContext = 'solo';
if (!this.projectInsights.hasACS) {
const { teamChoice } = await inquirer.prompt([{
type: 'list',
name: 'teamChoice',
message: '¿Contexto de este proyecto?',
choices: [
{ name: '👤 Personal/Solo', value: 'solo' },
{ name: '👥 Equipo pequeño (2-5 devs)', value: 'team' },
{ name: '🏢 Empresarial (6+ devs)', value: 'enterprise' }
],
default: 'solo'
}]);
teamContext = teamChoice;
}
return {
comfortLevel: workStyle,
priority,
teamContext
};
}
generateRecommendation(preferences) {
const { complexity, hasACS, projectType } = this.projectInsights;
const { comfortLevel, priority, teamContext } = preferences;
const recommendation = {
action: '',
explanation: '',
estimatedTime: complexity.estimatedSetupTime,
nextSteps: []
};
// Lógica de recomendación basada en contexto
if (hasACS) {
recommendation.action = 'optimize';
recommendation.explanation = 'Tu proyecto ya tiene ACS. Te ayudo a optimizarlo.';
recommendation.nextSteps = [
'🔍 Validar documentación existente',
'🤖 Ejecutar agente para actualizaciones',
'📊 Generar reporte de completitud'
];
} else if (priority === 'fast-setup' && complexity.level === 'simple') {
recommendation.action = 'auto-setup';
recommendation.explanation = 'Setup automático perfecto para tu proyecto.';
recommendation.nextSteps = [
'🚀 Configuración automática (2 min)',
'🧠 IA extrae contexto del código',
'✅ Validación automática'
];
} else if (complexity.level === 'complex' && teamContext === 'enterprise') {
recommendation.action = 'guided-enterprise';
recommendation.explanation = 'Setup enterprise guiado para proyecto complejo.';
recommendation.nextSteps = [
'📋 Configuración por módulos',
'👥 Setup multi-usuario',
'🔒 Validaciones de calidad enterprise'
];
} else {
recommendation.action = 'standard-setup';
recommendation.explanation = 'Setup estándar con opciones personalizadas.';
recommendation.nextSteps = [
'🎯 Configuración guiada paso a paso',
'🔧 Personalización según tu stack',
'📚 Documentación progresiva'
];
}
// Ajustar tiempo basado en preferencias
if (comfortLevel === 'expert' && priority === 'fast-setup') {
recommendation.estimatedTime = this.reduceTime(recommendation.estimatedTime);
} else if (comfortLevel === 'guided') {
recommendation.estimatedTime = this.increaseTime(recommendation.estimatedTime);
}
return recommendation;
}
async detectProjectType() {
// Detección inteligente mejorada
const detectors = [
{ files: ['package.json'], check: this.analyzePackageJson.bind(this) },
{ files: ['composer.json'], type: 'PHP' },
{ files: ['requirements.txt', 'pyproject.toml'], check: this.analyzePython.bind(this) },
{ files: ['go.mod'], type: 'Go' },
{ files: ['Cargo.toml'], type: 'Rust' },
{ files: ['pom.xml'], type: 'Java (Maven)' },
{ files: ['build.gradle'], type: 'Java (Gradle)' },
{ files: ['pubspec.yaml'], type: 'Flutter/Dart' }
];
for (const detector of detectors) {
for (const file of detector.files) {
const filePath = path.join(this.targetDir, file);
if (await fs.pathExists(filePath)) {
if (detector.check) {
return await detector.check(filePath);
}
return detector.type;
}
}
}
return 'Proyecto genérico';
}
async analyzePackageJson(packagePath) {
try {
const pkg = JSON.parse(await fs.readFile(packagePath, 'utf8'));
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
// Detectar framework específico
if (deps.next) return 'Next.js';
if (deps.nuxt) return 'Nuxt.js';
if (deps.react || deps['@types/react']) return 'React';
if (deps.vue) return 'Vue.js';
if (deps['@angular/core']) return 'Angular';
if (deps.express) return 'Node.js/Express API';
if (deps.fastify) return 'Node.js/Fastify API';
if (deps['@nestjs/core']) return 'NestJS API';
return 'Node.js/JavaScript';
} catch (error) {
return 'Node.js';
}
}
async analyzePython(reqPath) {
try {
const content = await fs.readFile(reqPath, 'utf8');
if (content.includes('django')) return 'Python/Django';
if (content.includes('flask')) return 'Python/Flask';
if (content.includes('fastapi')) return 'Python/FastAPI';
if (content.includes('pandas') || content.includes('numpy')) return 'Python/Data Science';
return 'Python';
} catch (error) {
return 'Python';
}
}
reduceTime(timeStr) {
// Lógica simple para reducir tiempo estimado
if (timeStr.includes('10-20')) return '5-10 min';
if (timeStr.includes('5-10')) return '3-5 min';
if (timeStr.includes('2-5')) return '2-3 min';
return timeStr;
}
increaseTime(timeStr) {
// Lógica simple para aumentar tiempo estimado
if (timeStr.includes('2-5')) return '5-8 min';
if (timeStr.includes('5-10')) return '8-15 min';
if (timeStr.includes('10-20')) return '15-25 min';
return timeStr;
}
showRecommendation(recommendation) {
console.log(chalk.green(`\n✨ RECOMENDACIÓN PERSONALIZADA`));
console.log(chalk.gray('═══════════════════════════════════════'));
console.log(`🎯 ${chalk.cyan(recommendation.explanation)}`);
console.log(`⏱️ Tiempo estimado: ${chalk.yellow(recommendation.estimatedTime)}`);
console.log(chalk.cyan('\n📋 Próximos pasos:'));
recommendation.nextSteps.forEach(step => {
console.log(` ${step}`);
});
// Eliminar el "Presiona Enter" duplicado
console.log('');
}
}
module.exports = StreamlinedOnboarding;