UNPKG

faf-cli

Version:

😽 TURBO-CAT: The Rapid Catalytic Converter • Project DNA ✨ for ANY AI • Fully Integrated with React, Next.js, Svelte, TypeScript, Vite & n8n • FREE FOREVER • 10,000+ developers • Championship Edition

1,048 lines • 43 kB
"use strict"; /** * šŸš€ REAL faf enhance - Actually improves scores with facts, not BS * No placeholders, no mocks - real improvements based on project analysis * RELENTLESS pursuit of highest score through real data or human input */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.realEnhanceFaf = realEnhanceFaf; const colors_1 = require("../fix-once/colors"); const fs_1 = require("fs"); const path = __importStar(require("path")); const yaml_1 = require("../fix-once/yaml"); const inquirer_1 = __importDefault(require("inquirer")); const file_utils_1 = require("../utils/file-utils"); const faf_compiler_1 = require("../compiler/faf-compiler"); const fab_formats_engine_1 = require("../utils/fab-formats-engine"); const child_process_1 = require("child_process"); /** * REAL Enhancement that RELENTLESSLY improves scores * Loops until target score achieved or no more improvements possible */ async function realEnhanceFaf(file, options = {}) { try { const fafPath = file || (await (0, file_utils_1.findFafFile)()); if (!fafPath) { console.log(colors_1.chalk.red("āŒ No .faf file found")); console.log(colors_1.chalk.yellow('šŸ’” Run "faf init" to create one')); process.exit(1); } const projectPath = path.dirname(fafPath); console.log(colors_1.chalk.cyan("⚔ Real Enhancement Starting...")); console.log(colors_1.chalk.gray(" No BS, just facts from your project")); console.log(colors_1.chalk.gray(` Enhancing: ${fafPath}`)); // Read current .faf file const content = await fs_1.promises.readFile(fafPath, "utf-8"); let fafData = (0, yaml_1.parse)(content) || {}; // Get REAL current score with detailed breakdown const compiler = new faf_compiler_1.FafCompiler(); let currentScore = await compiler.compile(fafPath); const targetScore = options.targetScore || 100; // Changed from 80 to 100 console.log(colors_1.chalk.yellow(`šŸ“Š Current Score: ${currentScore.score}%`)); console.log(colors_1.chalk.gray(` Target Score: ${targetScore}%`)); console.log(colors_1.chalk.gray(` Filled: ${currentScore.filled}/${currentScore.total} slots`)); // Show what's missing if (options.verbose) { displayMissingSlots(currentScore); } // RELENTLESS enhancement loop let iteration = 0; const maxIterations = 10; // Safety limit while (currentScore.score < targetScore && iteration < maxIterations) { iteration++; console.log(colors_1.chalk.cyan(`\nšŸ”„ Enhancement Round ${iteration}...`)); // Analyze project for REAL improvements const improvements = await analyzeProjectForRealImprovements(projectPath, fafData, currentScore); if (options.verbose) { console.log(colors_1.chalk.gray(`Found ${Object.keys(improvements).length} automatic improvements`)); if (Object.keys(improvements).length > 0 && Object.keys(improvements).length <= 3) { console.log(colors_1.chalk.gray(` Improvements: ${Object.keys(improvements).join(', ')}`)); } } // If no automatic improvements found and interactive mode, ask human if (Object.keys(improvements).length === 0 && options.interactive !== false) { // Check if we're missing critical human context const missingHuman = !fafData.human_context?.who || !fafData.human_context?.what || !fafData.human_context?.why || !fafData.human_context?.where || !fafData.human_context?.when || !fafData.human_context?.how; if (missingHuman) { console.log(colors_1.chalk.yellow('\nāš ļø Missing critical Human Context (the 6 W\'s)')); console.log(colors_1.chalk.gray(' This is the biggest opportunity to improve your score')); } const humanInput = await askHumanForMissingData(fafData, currentScore); Object.assign(improvements, humanInput); if (options.verbose && Object.keys(humanInput).length > 0) { console.log(colors_1.chalk.gray(`Added ${Object.keys(humanInput).length} improvements from human input`)); } } // If still no improvements, we're done if (Object.keys(improvements).length === 0) { console.log(colors_1.chalk.yellow("\nāš ļø No more improvements possible with available data")); if (options.interactive === false) { console.log(colors_1.chalk.gray(" (Interactive mode disabled - try with -i true to provide missing data)")); } break; } if (options.dryRun) { console.log(colors_1.chalk.cyan("\nšŸ” Improvements Found (Dry Run):")); displayImprovements(improvements); continue; } // Apply REAL improvements fafData = applyRealEnhancements(fafData, improvements); // CRITICAL: Preserve essential fields that should never be removed if (!fafData.project) fafData.project = {}; if (!fafData.project.generated && fafData.generated) { fafData.project.generated = fafData.generated; } // Add meta tracking for enhancement fafData.meta = fafData.meta || {}; fafData.meta.last_enhanced = new Date().toISOString(); fafData.meta.enhanced_by = 'faf-real-enhance'; // Save enhanced file const enhancedYaml = (0, yaml_1.stringify)(fafData); await fs_1.promises.writeFile(fafPath, enhancedYaml); // Calculate new score const newScore = await compiler.compile(fafPath); const improvement = newScore.score - currentScore.score; if (improvement > 0) { console.log(colors_1.chalk.green(`āœ… Improvement: +${improvement}% (${currentScore.score}% → ${newScore.score}%)`)); // Show what was actually added if (options.verbose) { console.log(colors_1.chalk.cyan("šŸ“ Changes Made:")); displayImprovements(improvements); } } currentScore = newScore; } // Final results console.log(colors_1.chalk.cyan("\n" + "=".repeat(60))); if (currentScore.score >= targetScore) { console.log(colors_1.chalk.green(`šŸŽÆ TARGET ACHIEVED! Score: ${currentScore.score}%`)); } else { console.log(colors_1.chalk.yellow(`šŸ“Š Final Score: ${currentScore.score}%`)); console.log(colors_1.chalk.gray(` (Target was ${targetScore}%)`)); } console.log(colors_1.chalk.cyan("=".repeat(60))); } catch (error) { console.log(colors_1.chalk.red("šŸ’„ Enhancement failed:")); console.log(colors_1.chalk.red(error instanceof Error ? error.message : String(error))); process.exit(1); } } /** * Display what slots are missing for transparency */ function displayMissingSlots(score) { const missing = []; // Check project slots if (score.breakdown.project.filled < score.breakdown.project.total) { const projectSlots = score.breakdown.project.slots; projectSlots.forEach((slot) => { if (!slot.filled && slot.id.includes('project')) { const field = slot.id.replace('slot_', '').replace('project.', ''); missing.push(`Project: ${field}`); } }); } // Check stack slots if (score.breakdown.stack.filled < score.breakdown.stack.total) { const stackSlots = score.breakdown.stack.slots; stackSlots.forEach((slot) => { if (!slot.filled && slot.id.includes('stack')) { const field = slot.id.replace('slot_', '').replace('stack.', ''); missing.push(`Stack: ${field}`); } }); } // Check human context slots if (score.breakdown.human.filled < score.breakdown.human.total) { const humanSlots = score.breakdown.human.slots; humanSlots.forEach((slot) => { if (!slot.filled && slot.id.includes('human')) { const field = slot.id.replace('slot_', '').replace('human.', ''); missing.push(`Human Context: ${field}`); } }); } if (missing.length > 0) { console.log(colors_1.chalk.yellow('\nāš ļø Missing Context (affecting score):')); missing.forEach(m => console.log(colors_1.chalk.gray(` • ${m}`))); } } /** * Ask human for missing critical data via inquirer * RELENTLESS 1-6 questionnaire for the 6 W's of Human Context */ async function askHumanForMissingData(currentFaf, score) { // Check if we're in an interactive terminal if (!process.stdin.isTTY) { console.log(colors_1.chalk.yellow('\nāš ļø Interactive questions require a terminal (TTY)')); console.log(colors_1.chalk.gray(' Skipping interactive questionnaire...')); console.log(colors_1.chalk.cyan('\nšŸ’” When using AI assistants or CI/CD:')); console.log(colors_1.chalk.gray(' faf auto - Automatically enhance context')); console.log(colors_1.chalk.gray(' faf chat - Interactive mode (terminal only)')); console.log(colors_1.chalk.gray(' Run in a real terminal for full interactive enhancement\n')); return {}; // Return empty improvements } const improvements = {}; const questions = []; // Priority 1: Project data (most critical for AI) if (!currentFaf.project?.name) { questions.push({ type: 'input', name: 'projectName', message: 'šŸŽÆ What is your project name?', validate: (input) => input.trim().length > 0 || 'Project name is required for AI context' }); } if (!currentFaf.project?.goal) { questions.push({ type: 'input', name: 'projectGoal', message: 'šŸŽÆ What does your project do? (one sentence)', validate: (input) => input.trim().length > 10 || 'Please provide a meaningful description' }); } // Priority 2: The 6 W's - RELENTLESS Human Context Collection // These are CRITICAL for AI understanding and score improvement console.log(colors_1.chalk.cyan('\n🧠 Human Context - The 6 W\'s (Critical for AI Understanding)')); console.log(colors_1.chalk.gray(' These 6 questions dramatically improve AI\'s ability to help you')); // 1. WHO - Target audience/users if (!currentFaf.human_context?.who) { questions.push({ type: 'input', name: 'who', message: colors_1.chalk.yellow('1/6 šŸ‘¤ WHO will use this? (developers, data scientists, designers, etc.)'), default: getSmartDefault('who', currentFaf), transformer: (input) => colors_1.chalk.green(input), validate: (input) => { if (input.trim().length < 3) return 'Please specify your target users'; if (genericAnswers.who.includes(input.toLowerCase())) { return 'Please be more specific than "' + input + '"'; } return true; } }); } // 2. WHAT - Core problem being solved if (!currentFaf.human_context?.what) { questions.push({ type: 'input', name: 'what', message: colors_1.chalk.yellow('2/6 šŸ“¦ WHAT problem does it solve? (be specific)'), default: getSmartDefault('what', currentFaf), transformer: (input) => colors_1.chalk.green(input), validate: (input) => { if (input.trim().length < 10) return 'Please describe the specific problem'; if (genericAnswers.what.includes(input.toLowerCase())) { return 'Please be more specific about the problem'; } return true; } }); } // 3. WHY - Importance and impact if (!currentFaf.human_context?.why) { questions.push({ type: 'input', name: 'why', message: colors_1.chalk.yellow('3/6 šŸ’” WHY is this important? (what impact/value does it create?)'), default: getSmartDefault('why', currentFaf), transformer: (input) => colors_1.chalk.green(input), validate: (input) => { if (input.trim().length < 10) return 'Please explain why this matters'; if (genericAnswers.why.includes(input.toLowerCase())) { return 'Please be more specific about the value/impact'; } return true; } }); } // 4. WHERE - Deployment/usage context if (!currentFaf.human_context?.where) { questions.push({ type: 'input', name: 'where', message: colors_1.chalk.yellow('4/6 šŸŒ WHERE will it be used? (cloud, on-premise, mobile, browser, etc.)'), default: getSmartDefault('where', currentFaf), transformer: (input) => colors_1.chalk.green(input), validate: (input) => { if (input.trim().length < 3) return 'Please specify the deployment context'; return true; } }); } // 5. WHEN - Timeline/urgency if (!currentFaf.human_context?.when) { questions.push({ type: 'input', name: 'when', message: colors_1.chalk.yellow('5/6 ā° WHEN do you need this? (now, Q1 2025, ongoing, etc.)'), default: getSmartDefault('when', currentFaf), transformer: (input) => colors_1.chalk.green(input), validate: (input) => { if (input.trim().length < 3) return 'Please specify the timeline'; return true; } }); } // 6. HOW - Implementation approach if (!currentFaf.human_context?.how) { questions.push({ type: 'input', name: 'how', message: colors_1.chalk.yellow('6/6 šŸ”§ HOW will you build it? (agile, iterative, waterfall, etc.)'), default: getSmartDefault('how', currentFaf), transformer: (input) => colors_1.chalk.green(input), validate: (input) => { if (input.trim().length < 5) return 'Please describe your approach'; if (genericAnswers.how.includes(input.toLowerCase())) { return 'Please be more specific about your methodology'; } return true; } }); } // Priority 3: Technical stack (only if really needed and missing) const needsFrontend = !currentFaf.stack?.frontend && (currentFaf.project?.type?.includes('frontend') || currentFaf.project?.type?.includes('fullstack')); const needsBackend = !currentFaf.stack?.backend && (currentFaf.project?.type?.includes('backend') || currentFaf.project?.type?.includes('api')); const needsDatabase = !currentFaf.stack?.database && needsBackend; const needsHosting = !currentFaf.stack?.hosting; if (needsFrontend) { questions.push({ type: 'list', name: 'framework', message: 'šŸŽØ Frontend framework?', choices: ['React', 'Vue', 'Angular', 'Svelte', 'Next.js', 'Remix', 'Astro', 'None', 'Skip'] }); } if (needsBackend) { questions.push({ type: 'list', name: 'backend', message: 'āš™ļø Backend framework?', choices: ['Express', 'Fastify', 'NestJS', 'Hono', 'Django', 'FastAPI', 'Rails', 'None', 'Skip'] }); } if (needsDatabase) { questions.push({ type: 'list', name: 'database', message: 'šŸ’¾ Database?', choices: ['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite', 'Redis', 'Supabase', 'PlanetScale', 'None', 'Skip'] }); } if (needsHosting) { questions.push({ type: 'list', name: 'hosting', message: 'ā˜ļø Hosting platform?', choices: ['Vercel', 'Netlify', 'AWS', 'Google Cloud', 'Azure', 'Heroku', 'Railway', 'Fly.io', 'None', 'Skip'] }); } // Only ask if we have questions if (questions.length === 0) { return improvements; } console.log(colors_1.chalk.cyan('\nšŸŽÆ Let\'s fill the critical gaps to reach your target score:')); const answers = await inquirer_1.default.prompt(questions); // Map answers to improvements Object.entries(answers).forEach(([key, value]) => { if (value && value !== 'Skip') { improvements[key] = value; } }); // Show progress after human input const filledCount = Object.keys(improvements).length; if (filledCount > 0) { console.log(colors_1.chalk.green(`\nāœ… Added ${filledCount} improvements from your input`)); } return improvements; } // Generic answers to reject for better specificity const genericAnswers = { who: ['users', 'people', 'everyone', 'anybody', 'someone'], what: ['problems', 'issues', 'things', 'stuff', 'something'], why: ['because', 'important', 'needed', 'required', 'necessary'], how: ['normal', 'usual', 'standard', 'regular', 'typical'] }; // Smart defaults based on project type function getSmartDefault(field, currentFaf) { const projectType = currentFaf.project?.type || ''; const projectName = currentFaf.project?.name || ''; const language = currentFaf.project?.main_language || ''; const defaults = { who: { 'cli-tool': 'Developers and DevOps engineers', 'frontend': 'End users and web visitors', 'backend-api': 'Frontend applications and API consumers', 'fullstack': 'Business users and administrators', 'library': `Developers using ${language || 'this technology'}`, 'chrome-extension': 'Chrome browser users', 'default': 'Development teams' }, what: { 'cli-tool': 'Automates repetitive command-line tasks', 'frontend': 'Provides user interface for data interaction', 'backend-api': 'Manages data and business logic', 'fullstack': 'Complete solution for business operations', 'library': `Simplifies ${language || 'development'} tasks`, 'chrome-extension': 'Enhances browser functionality', 'default': 'Solves specific technical challenges' }, why: { 'cli-tool': 'Saves time and reduces errors in workflows', 'frontend': 'Improves user experience and engagement', 'backend-api': 'Centralizes data management and processing', 'fullstack': 'Streamlines business processes', 'library': 'Reduces code duplication and complexity', 'chrome-extension': 'Adds missing browser features', 'default': 'Increases productivity and quality' }, where: { 'cli-tool': 'Local development machines and CI/CD pipelines', 'frontend': 'Web browsers and CDN', 'backend-api': 'Cloud servers or containers', 'fullstack': 'Cloud platform with global availability', 'library': 'NPM/PyPI package registry', 'chrome-extension': 'Chrome Web Store', 'default': 'Cloud infrastructure' }, when: { 'default': 'Ongoing development and maintenance' }, how: { 'default': 'Agile development with continuous deployment' } }; const typeDefaults = defaults[field]; if (!typeDefaults) return ''; return typeDefaults[projectType] || typeDefaults['default'] || ''; } /** * Analyze project for REAL improvements based on actual files */ async function analyzeProjectForRealImprovements(projectPath, currentFaf, currentScore) { const improvements = {}; // Priority order: Fill critical slots first // 1. PROJECT SLOTS (name, goal, language) - Most critical for AI // 2. HUMAN CONTEXT (6 W's) - Critical for understanding // 3. STACK SLOTS - Technical details // 1. Scan for package.json to get REAL project info try { const pkgPath = path.join(projectPath, 'package.json'); const pkgContent = await fs_1.promises.readFile(pkgPath, 'utf-8'); const pkg = JSON.parse(pkgContent); // Extract REAL project data if (!currentFaf.project?.name && pkg.name) { improvements.projectName = pkg.name; } if (!currentFaf.project?.goal && pkg.description) { improvements.projectGoal = pkg.description; } if (!currentFaf.project?.version && pkg.version) { improvements.version = pkg.version; } if (!currentFaf.project?.author && pkg.author) { improvements.author = typeof pkg.author === 'string' ? pkg.author : pkg.author.name; } if (!currentFaf.project?.license && pkg.license) { improvements.license = pkg.license; } // Extract REAL dependencies for stack info const deps = { ...pkg.dependencies, ...pkg.devDependencies }; const frameworks = detectFrameworks(deps); if (frameworks.length > 0 && !currentFaf.stack?.frontend) { improvements.framework = frameworks[0]; } // Detect testing framework const testFramework = detectTestingFramework(deps); if (testFramework && !currentFaf.stack?.testing) { improvements.testing = testFramework; } // Detect database const database = detectDatabase(deps); if (database && !currentFaf.stack?.database) { improvements.database = database; } // Detect CI/CD from scripts if (pkg.scripts?.deploy && !currentFaf.stack?.cicd) { improvements.cicd = 'npm deploy'; } // Extract scripts for understanding project if (pkg.scripts) { const scripts = Object.keys(pkg.scripts); if (!currentFaf.stack?.testing && scripts.some(s => s.includes('test'))) { improvements.testing = 'jest'; // or detect from deps } if (!currentFaf.stack?.build && scripts.some(s => s.includes('build'))) { improvements.buildTool = detectBuildTool(deps); } } } catch (e) { // No package.json, try other files } // 2. Use FAB-Formats to INTELLIGENTLY discover project structure const fabEngine = new fab_formats_engine_1.FabFormatsEngine(); const fabAnalysis = await fabEngine.discoverFormats(projectPath); if (fabAnalysis.discoveredFormats && fabAnalysis.discoveredFormats.length > 0) { // Add discovered key files const keyFiles = fabAnalysis.discoveredFormats .map((f) => f.fileName) .filter((f) => isImportantFile(f)) .slice(0, 5); if (keyFiles.length > 0 && !currentFaf.instant_context?.key_files) { improvements.keyFiles = keyFiles; } // Use ALL extracted context from FAB-Formats const ctx = fabAnalysis.extractedContext; // Project information if (ctx.projectName && !currentFaf.project?.name) { improvements.projectName = ctx.projectName; } if (ctx.projectDescription && !currentFaf.project?.goal) { improvements.projectGoal = ctx.projectDescription; } if (ctx.projectType && !currentFaf.project?.type) { improvements.projectType = ctx.projectType; } // Stack information from FAB-Formats if (ctx.mainLanguage && !currentFaf.project?.main_language) { improvements.mainLanguage = ctx.mainLanguage; } if (ctx.frameworks && ctx.frameworks.length > 0) { if (!currentFaf.stack?.frontend && isFrontendFramework(ctx.frameworks[0])) { improvements.framework = ctx.frameworks[0]; } if (!currentFaf.stack?.backend && isBackendFramework(ctx.frameworks[0])) { improvements.backend = ctx.frameworks[0]; } } if (ctx.database && !currentFaf.stack?.database) { improvements.database = ctx.database; } if (ctx.backend && !currentFaf.stack?.backend) { improvements.backend = ctx.backend; } if (ctx.hosting && !currentFaf.stack?.hosting) { improvements.hosting = ctx.hosting; } // These might not exist in ctx, check if they do if (ctx.buildTool && !currentFaf.stack?.build) { improvements.buildTool = ctx.buildTool; } if (ctx.testing && !currentFaf.stack?.testing) { improvements.testing = ctx.testing; } if (ctx.cicd && !currentFaf.stack?.cicd) { improvements.cicd = ctx.cicd; } // Use FAB-Formats pattern analysis for better detection const patterns = fabAnalysis.discoveredFormats.map((f) => f.pattern); if (patterns.includes('dockerfile') && !currentFaf.stack?.hosting) { improvements.hosting = 'Docker'; } if (patterns.includes('kubernetes') && !currentFaf.stack?.hosting) { improvements.hosting = 'Kubernetes'; } if (patterns.includes('github-actions') && !currentFaf.stack?.cicd) { improvements.cicd = 'GitHub Actions'; } if (patterns.includes('gitlab-ci') && !currentFaf.stack?.cicd) { improvements.cicd = 'GitLab CI'; } } // 3. Detect project type from files const files = await fs_1.promises.readdir(projectPath); const projectType = detectProjectType(files); if (projectType && projectType !== 'unknown' && !currentFaf.project?.type) { improvements.projectType = projectType; } // 3.5 Try to get README for project goal and human context try { const readmePath = path.join(projectPath, 'README.md'); const readmeContent = await fs_1.promises.readFile(readmePath, 'utf-8'); const readmeInfo = extractFromReadme(readmeContent); if (readmeInfo.description && !currentFaf.project?.goal) { improvements.projectGoal = readmeInfo.description; } if (readmeInfo.who && !currentFaf.human_context?.who) { improvements.who = readmeInfo.who; } if (readmeInfo.what && !currentFaf.human_context?.what) { improvements.what = readmeInfo.what; } } catch (e) { // No README or can't parse } // 4. Add REAL human context from git try { // Get git remote URL for WHERE context if (!currentFaf.human_context?.where) { const gitRemote = (0, child_process_1.execSync)('git config --get remote.origin.url', { cwd: projectPath }) .toString().trim(); if (gitRemote) { if (gitRemote.includes('github.com')) { improvements.where = 'GitHub'; } else if (gitRemote.includes('gitlab')) { improvements.where = 'GitLab'; } else if (gitRemote.includes('bitbucket')) { improvements.where = 'Bitbucket'; } } } // Get last commit date for WHEN context if (!currentFaf.human_context?.when) { const lastCommit = (0, child_process_1.execSync)('git log -1 --format=%cd --date=short', { cwd: projectPath }) .toString().trim(); if (lastCommit) { improvements.when = `Active development since ${lastCommit}`; } } } catch (e) { // No git or git commands failed } // 5. Add REAL technical details if (!currentFaf.stack?.language) { const language = detectLanguage(files); if (language) { improvements.mainLanguage = language; } } // 6. Analyze file patterns for more intelligent stack detection if (!currentFaf.stack?.hosting) { if (files.includes('vercel.json')) improvements.hosting = 'Vercel'; else if (files.includes('netlify.toml')) improvements.hosting = 'Netlify'; else if (files.includes('app.yaml')) improvements.hosting = 'Google App Engine'; else if (files.includes('Procfile')) improvements.hosting = 'Heroku'; else if (files.includes('.elasticbeanstalk')) improvements.hosting = 'AWS Elastic Beanstalk'; } // 7. Intelligent project type detection from structure if (!currentFaf.project?.type) { const hasPublicDir = files.includes('public'); const hasSrcDir = files.includes('src'); const hasApiDir = files.includes('api'); const hasServerFile = files.some(f => f.includes('server')); const hasIndexHtml = files.includes('index.html'); if (hasApiDir && hasPublicDir) improvements.projectType = 'fullstack'; else if (hasServerFile && !hasIndexHtml) improvements.projectType = 'backend-api'; else if (hasPublicDir && hasIndexHtml) improvements.projectType = 'frontend'; else if (files.includes('cli.js') || files.includes('cli.ts')) improvements.projectType = 'cli-tool'; } // 8. Extract runtime from files if (!currentFaf.stack?.runtime) { if (files.includes('package.json')) improvements.runtime = 'Node.js'; else if (files.includes('requirements.txt')) improvements.runtime = 'Python'; else if (files.includes('Gemfile')) improvements.runtime = 'Ruby'; else if (files.includes('go.mod')) improvements.runtime = 'Go'; else if (files.includes('Cargo.toml')) improvements.runtime = 'Rust'; } // 9. Fill API type if we have a backend if (!currentFaf.stack?.api_type && (currentFaf.stack?.backend || improvements.backend)) { // Check package.json for API type hints try { const pkgPath = path.join(projectPath, 'package.json'); const pkgContent = await fs_1.promises.readFile(pkgPath, 'utf-8'); const pkg = JSON.parse(pkgContent); const allDeps = { ...pkg.dependencies, ...pkg.devDependencies }; if (allDeps['graphql']) improvements.api_type = 'GraphQL'; else if (allDeps['@trpc/server']) improvements.api_type = 'tRPC'; else if (allDeps['socket.io']) improvements.api_type = 'WebSocket'; else improvements.api_type = 'REST'; } catch (e) { improvements.api_type = 'REST'; // Default to REST if can't read package.json } } return improvements; } /** * Apply REAL enhancements to faf data */ function applyRealEnhancements(fafData, improvements) { // Deep clone to preserve all nested fields const enhanced = JSON.parse(JSON.stringify(fafData)); // Ensure structure exists enhanced.project = enhanced.project || {}; enhanced.stack = enhanced.stack || {}; enhanced.human_context = enhanced.human_context || {}; enhanced.instant_context = enhanced.instant_context || {}; // Apply project improvements (CRITICAL SLOTS) if (improvements.projectName) { enhanced.project.name = improvements.projectName; } if (improvements.projectGoal) { enhanced.project.goal = improvements.projectGoal; } if (improvements.mainLanguage) { enhanced.project.main_language = improvements.mainLanguage; } if (improvements.version) { enhanced.project.version = improvements.version; } if (improvements.author) { enhanced.project.author = improvements.author; } if (improvements.license) { enhanced.project.license = improvements.license; } if (improvements.projectType) { enhanced.project.type = improvements.projectType; } // Apply stack improvements (TECHNICAL SLOTS) if (improvements.framework) { enhanced.stack.frontend = improvements.framework; } if (improvements.backend) { enhanced.stack.backend = improvements.backend; } if (improvements.database) { enhanced.stack.database = improvements.database; } if (improvements.buildTool) { enhanced.stack.build = improvements.buildTool; } if (improvements.testing) { enhanced.stack.testing = improvements.testing; } if (improvements.cicd) { enhanced.stack.cicd = improvements.cicd; } if (improvements.runtime) { enhanced.stack.runtime = improvements.runtime; } if (improvements.hosting) { enhanced.stack.hosting = improvements.hosting; } if (improvements.api_type) { enhanced.stack.api_type = improvements.api_type; } if (improvements.mainLanguage) { enhanced.stack.language = improvements.mainLanguage; } // Apply human context improvements (6 W's - CRITICAL FOR AI UNDERSTANDING) if (improvements.who) { enhanced.human_context.who = improvements.who; } if (improvements.what) { enhanced.human_context.what = improvements.what; } if (improvements.why) { enhanced.human_context.why = improvements.why; } if (improvements.where) { enhanced.human_context.where = improvements.where; } if (improvements.when) { enhanced.human_context.when = improvements.when; } if (improvements.how) { enhanced.human_context.how = improvements.how; } // Apply instant context improvements if (improvements.keyFiles) { enhanced.instant_context.key_files = improvements.keyFiles; } // Add metadata enhanced.meta = enhanced.meta || {}; enhanced.meta.last_enhanced = new Date().toISOString(); enhanced.meta.enhanced_by = 'faf-real-enhance'; return enhanced; } /** * Helper functions for detection */ function detectFrameworks(deps) { const frameworks = []; // Frontend frameworks if (deps['react']) frameworks.push('React'); if (deps['vue']) frameworks.push('Vue'); if (deps['@angular/core']) frameworks.push('Angular'); if (deps['svelte']) frameworks.push('Svelte'); if (deps['solid-js']) frameworks.push('SolidJS'); if (deps['preact']) frameworks.push('Preact'); if (deps['@ember/core']) frameworks.push('Ember'); // Meta-frameworks if (deps['next']) frameworks.push('Next.js'); if (deps['nuxt']) frameworks.push('Nuxt'); if (deps['gatsby']) frameworks.push('Gatsby'); if (deps['@remix-run/react']) frameworks.push('Remix'); if (deps['astro']) frameworks.push('Astro'); if (deps['@sveltekit/adapter-auto']) frameworks.push('SvelteKit'); // Backend frameworks if (deps['express']) frameworks.push('Express'); if (deps['fastify']) frameworks.push('Fastify'); if (deps['@nestjs/core']) frameworks.push('NestJS'); if (deps['koa']) frameworks.push('Koa'); if (deps['@hapi/hapi']) frameworks.push('Hapi'); if (deps['@feathersjs/feathers']) frameworks.push('Feathers'); if (deps['@adonisjs/core']) frameworks.push('AdonisJS'); return frameworks; } function isFrontendFramework(framework) { const frontend = ['React', 'Vue', 'Angular', 'Svelte', 'SolidJS', 'Preact', 'Ember', 'Next.js', 'Nuxt', 'Gatsby', 'Remix', 'Astro', 'SvelteKit']; return frontend.includes(framework); } function isBackendFramework(framework) { const backend = ['Express', 'Fastify', 'NestJS', 'Koa', 'Hapi', 'Feathers', 'AdonisJS']; return backend.includes(framework); } function detectBuildTool(deps) { if (deps['vite']) return 'Vite'; if (deps['webpack']) return 'Webpack'; if (deps['@parcel/core'] || deps['parcel']) return 'Parcel'; if (deps['esbuild']) return 'ESBuild'; if (deps['rollup']) return 'Rollup'; if (deps['@swc/core']) return 'SWC'; if (deps['turbopack']) return 'Turbopack'; if (deps['snowpack']) return 'Snowpack'; if (deps['@rspack/core']) return 'Rspack'; return 'npm'; } function detectProjectType(files) { if (files.includes('package.json')) { if (files.includes('tsconfig.json')) return 'typescript-node'; return 'javascript-node'; } if (files.includes('requirements.txt') || files.includes('setup.py')) { return 'python'; } if (files.includes('Cargo.toml')) return 'rust'; if (files.includes('go.mod')) return 'go'; return 'unknown'; } function detectLanguage(files) { const extensions = files.map(f => path.extname(f)); if (extensions.includes('.ts') || extensions.includes('.tsx')) return 'TypeScript'; if (extensions.includes('.js') || extensions.includes('.jsx')) return 'JavaScript'; if (extensions.includes('.py')) return 'Python'; if (extensions.includes('.rs')) return 'Rust'; if (extensions.includes('.go')) return 'Go'; if (extensions.includes('.java')) return 'Java'; return 'Unknown'; } function isImportantFile(filename) { const important = [ 'index', 'main', 'app', 'server', 'cli', 'config', 'package.json', 'tsconfig.json', 'webpack.config', 'vite.config', 'README' ]; return important.some(i => filename.toLowerCase().includes(i)); } /** * Extract info from README */ function extractFromReadme(content) { const info = {}; // Try to get first paragraph as description const lines = content.split('\n').filter(l => l.trim()); const descLine = lines.find(l => !l.startsWith('#') && l.length > 20); if (descLine) { info.description = descLine.trim(); } // Look for "For" or "Built for" patterns const forMatch = content.match(/(?:built for|for|designed for|made for)\s+([^.\n]+)/i); if (forMatch) { info.who = forMatch[1].trim(); } // Look for problem statements const problemMatch = content.match(/(?:solves?|fixes?|addresses?|handles?)\s+([^.\n]+)/i); if (problemMatch) { info.what = problemMatch[1].trim(); } return info; } /** * Detect testing framework from dependencies */ function detectTestingFramework(deps) { // Unit testing if (deps['vitest']) return 'Vitest'; if (deps['jest']) return 'Jest'; if (deps['mocha']) return 'Mocha'; if (deps['jasmine']) return 'Jasmine'; if (deps['ava']) return 'AVA'; if (deps['tape']) return 'Tape'; if (deps['uvu']) return 'uvu'; // E2E testing if (deps['@playwright/test'] || deps['playwright']) return 'Playwright'; if (deps['cypress']) return 'Cypress'; if (deps['puppeteer']) return 'Puppeteer'; if (deps['webdriverio']) return 'WebdriverIO'; if (deps['nightwatch']) return 'Nightwatch'; // Testing utilities if (deps['@testing-library/react']) return 'React Testing Library'; if (deps['@testing-library/vue']) return 'Vue Testing Library'; if (deps['enzyme']) return 'Enzyme'; return null; } /** * Detect database from dependencies */ function detectDatabase(deps) { // ORMs that support multiple databases if (deps['@prisma/client']) return 'Prisma'; if (deps['typeorm']) return 'TypeORM'; if (deps['sequelize']) return 'Sequelize'; if (deps['drizzle-orm']) return 'Drizzle'; if (deps['kysely']) return 'Kysely'; // Specific databases if (deps['pg'] || deps['postgres']) return 'PostgreSQL'; if (deps['mysql'] || deps['mysql2']) return 'MySQL'; if (deps['mongodb'] || deps['mongoose']) return 'MongoDB'; if (deps['sqlite3'] || deps['better-sqlite3']) return 'SQLite'; if (deps['redis'] || deps['ioredis']) return 'Redis'; if (deps['@supabase/supabase-js']) return 'Supabase'; if (deps['firebase']) return 'Firebase'; if (deps['@planetscale/database']) return 'PlanetScale'; if (deps['@neondatabase/serverless']) return 'Neon'; if (deps['@vercel/postgres']) return 'Vercel Postgres'; return null; } function displayImprovements(improvements) { Object.entries(improvements).forEach(([key, value]) => { console.log(colors_1.chalk.gray(` • ${key}: ${value}`)); }); } //# sourceMappingURL=enhance-real.js.map