@puberty-labs/refuctor
Version:
AI-powered, snark-fueled technical debt cleansing suite with automatic snarky language detection that turns code cleanup into a darkly humorous financial metaphor.
1,063 lines (911 loc) โข 112 kB
JavaScript
#!/usr/bin/env node
const { Command } = require('commander');
const { debtDetector } = require('../src/debt-detector');
const { techDebtManager } = require('../src/techdebt-manager');
const { markdownFixerGoon } = require('../src/goons/markdown-fixer');
const { DebtDetector } = require('../src/debt-detector.js');
const { DebtIgnoreParser } = require('../src/debt-ignore-parser');
const { DebtModeManager } = require('../src/debt-mode-manager');
const SetupWizard = require('../src/setup-wizard');
const packageJson = require('../package.json');
const fs = require('fs-extra');
const path = require('path');
const { execSync } = require('child_process');
const glob = require('glob');
const SnarkySpellHandler = require('../src/snarky-spell-handler');
// Simple color functions (avoiding chalk v5 ES module issues)
const colors = {
red: (text) => `\x1b[31m${text}\x1b[0m`,
green: (text) => `\x1b[32m${text}\x1b[0m`,
yellow: (text) => `\x1b[33m${text}\x1b[0m`,
blue: (text) => `\x1b[34m${text}\x1b[0m`,
magenta: (text) => `\x1b[35m${text}\x1b[0m`,
cyan: (text) => `\x1b[36m${text}\x1b[0m`,
gray: (text) => `\x1b[90m${text}\x1b[0m`,
white: (text) => `\x1b[37m${text}\x1b[0m`,
bold: (text) => `\x1b[1m${text}\x1b[0m`
};
// Extract color functions for easier use
const { red, green, yellow, magenta, cyan, gray } = colors;
const program = new Command();
// Refuctor branding and personality
const TAGLINES = [
"Refactor or Be Repossessed",
"No Bloat. No Debt. No Bullshit.",
"Because your code deserves better than being held hostage by technical debt",
"Debt Never Sleeps. Neither Should You."
];
const getRandomTagline = () => TAGLINES[Math.floor(Math.random() * TAGLINES.length)];
// CLI setup with Refuctor personality
program
.name('refuctor')
.description(colors.red('๐ฆ The Debt Cleansing Syndicate') + '\n' + colors.gray(getRandomTagline()))
.version(packageJson.version)
.configureOutput({
writeOut: (str) => process.stdout.write(colors.cyan(str)),
writeErr: (str) => process.stderr.write(colors.red(str))
})
.addHelpText('after', `
${colors.bold(colors.cyan('๐ฏ DEBT DETECTION TYPES:'))}
๐ Markdown linting ${colors.gray('(markdownlint rules)')}
๐ Spelling errors ${colors.gray('(cspell with snarky intelligence)')}
๐ป ESLint/TypeScript ${colors.gray('(requires config files)')}
๐จ Code formatting ${colors.gray('(Prettier integration)')}
๐ Security audit ${colors.gray('(npm audit)')}
๐ฆ Dependencies ${colors.gray('(package.json analysis)')}
${colors.bold(colors.magenta('โก DEBT PRIORITY LEVELS:'))}
P4 Low: Minor style issues
P3 Medium: Moderate cleanup needed
P2 High: Significant problems
P1 Critical: Urgent fixes required
๐ค Guido Level: EXTREME debt - Thumb Crusher deployed
๐ด๏ธ Mafia Level: Debt sold to loan sharks
${colors.bold(colors.yellow('๐ก QUICK START:'))}
refuctor info Show capabilities and project analysis
refuctor scan Full debt analysis
refuctor cook Export VS Code problems to markdown (when scan misses issues)
refuctor fix --dry-run See what can be auto-fixed
refuctor init Set up debt tracking
`);
// Scan command - core debt detection
program
.command('scan')
.description(colors.yellow('๐๏ธ Detect technical debt in your project (markdown, spelling, security)'))
.option('-v, --verbose', 'Show detailed debt breakdown')
.option('-o, --output <file>', 'Save debt report to file')
.action(async (options) => {
console.log(colors.bold(colors.red('\n๐ฆ REFUCTOR DEBT COLLECTION AGENCY')));
console.log(colors.gray('Initiating debt scan... Your code is about to be audited.\n'));
// Show what's being scanned for transparency
const projectPath = process.cwd();
console.log(colors.bold(colors.blue('๐ SCANNING FOR:')));
// Quick file count analysis with .debtignore respect
const { DebtIgnoreParser } = require('../src/debt-ignore-parser');
const debtIgnore = new DebtIgnoreParser();
await debtIgnore.loadIgnorePatterns(projectPath);
// Get all files and filter by .debtignore
const allMdFiles = glob.sync('**/*.{md,mdc}', { cwd: projectPath, ignore: ['node_modules/**', '.git/**'] });
const allCodeFiles = glob.sync('**/*.{js,ts,jsx,tsx}', { cwd: projectPath, ignore: ['node_modules/**', '.git/**'] });
const mdFiles = allMdFiles.filter(file => !debtIgnore.shouldIgnore(file));
const codeFiles = allCodeFiles.filter(file => !debtIgnore.shouldIgnore(file));
const hasPackageJson = fs.existsSync(path.join(projectPath, 'package.json'));
console.log(colors.cyan(` ๐ Markdown issues (${mdFiles.length} files)`));
console.log(colors.cyan(` ๐ Spelling errors with snarky intelligence`));
if (hasPackageJson) {
console.log(colors.cyan(` ๐ Security vulnerabilities (package.json found)`));
console.log(colors.cyan(` ๐ฆ Dependency issues`));
}
if (codeFiles.length > 0) {
console.log(colors.cyan(` ๐ป Code quality issues (${codeFiles.length} files)`));
console.log(colors.cyan(` ๐จ ESLint/TypeScript/Formatting problems`));
}
try {
const debtReport = await debtDetector.scanProject(process.cwd(), options.verbose);
// Show snarky processing results if it occurred
if (debtReport.summary.snarkyProcessed && debtReport.summary.snarkyAdded > 0) {
console.log(colors.bold(colors.cyan('\n๐ฏ SNARKY INTELLIGENCE RESULTS:')));
console.log(colors.cyan(`๐ Auto-whitelisted ${debtReport.summary.snarkyAdded} snarky terms in project dictionary`));
console.log(colors.gray('Intelligently distinguished between typos and intentional snarky language\n'));
}
if (debtReport.totalDebt === 0) {
console.log(colors.bold(colors.green('๐ DEBT-FREE STATUS ACHIEVED!')));
console.log(colors.green('You magnificent debt-slayer! Your code is cleaner than a banker\'s conscience.'));
// Show what was actually checked for transparency
console.log(colors.bold(colors.blue('\n๐ SCAN SUMMARY:')));
console.log(colors.blue(` โ
Checked ${mdFiles.length} markdown files`));
console.log(colors.blue(` โ
Checked ${codeFiles.length} code files`));
if (hasPackageJson) {
console.log(colors.blue(` โ
Security audit passed`));
console.log(colors.blue(` โ
Dependencies validated`));
}
if (debtReport.summary.snarkyProcessed) {
console.log(colors.cyan(` ๐ฏ Snarky language detection kept your creative vocabulary intact!`));
}
console.log(colors.bold(colors.gray('\n๐ก DEBT WOULD TRIGGER AT:')));
console.log(colors.gray(' P4 Low: 1+ markdown issues, 1+ ESLint warnings'));
console.log(colors.gray(' P3 Medium: 2+ markdown issues, 5+ ESLint warnings'));
console.log(colors.gray(' P2 High: 5+ markdown issues, 10+ ESLint errors'));
console.log(colors.gray(' P1 Critical: 20+ markdown issues, 25+ ESLint errors'));
console.log(colors.red(' ๐ค Guido: 100+ markdown issues, 150+ ESLint errors'));
console.log(colors.magenta(' ๐ด๏ธ Mafia: 50+ markdown issues, 75+ ESLint errors'));
} else {
console.log(colors.bold(colors.red(`๐ธ DEBT DETECTED: ${debtReport.totalDebt} issues found`)));
console.log(colors.yellow('Time to refinance this technical disaster...\n'));
// Check for Guido the Thumb Crusher appearance FIRST
if (debtReport.guidoAppearance && debtReport.guidoAppearance.triggered) {
console.log(colors.bold(colors.red('\n' + '='.repeat(80))));
console.log(colors.bold(colors.red('๐ค GUIDO THE THUMB CRUSHER HAS ARRIVED ๐ค')));
console.log(colors.bold(colors.red('='.repeat(80))));
console.log(colors.red(debtReport.guidoAppearance.message));
if (debtReport.guidoAppearance.daysOverdue > 0) {
console.log(colors.bold(colors.red(`โฐ VIGorish overdue: ${debtReport.guidoAppearance.daysOverdue} days`)));
}
console.log(colors.bold(colors.yellow('\n' + debtReport.guidoAppearance.recommendation)));
console.log(colors.red('='.repeat(80) + '\n'));
}
// Check for Mafia Takeover
if (debtReport.mafiaStatus && debtReport.mafiaStatus.triggered) {
console.log(colors.bold(colors.magenta('\n' + '='.repeat(60))));
console.log(colors.bold(colors.magenta('๐ด๏ธ MAFIA TAKEOVER - DEBT SOLD TO THE FAMILY ๐ด๏ธ')));
console.log(colors.bold(colors.magenta('='.repeat(60))));
console.log(colors.magenta(debtReport.mafiaStatus.message));
console.log(colors.bold(colors.yellow(`๐ฐ VIGorish Rate: ${debtReport.mafiaStatus.vigorishRate}% daily`)));
console.log(colors.bold(colors.yellow(`๐ธ Daily Penalty: ${debtReport.mafiaStatus.dailyPenalty} debt units`)));
console.log(colors.bold(colors.cyan('\n' + debtReport.mafiaStatus.recommendation)));
console.log(colors.magenta('='.repeat(60) + '\n'));
}
// Display Guido Level debt
if (debtReport.guido.length > 0) {
console.log(colors.bold(colors.red('๐ค GUIDO LEVEL - THUMB CRUSHER COLLECTION:')));
debtReport.guido.forEach(debt => console.log(colors.red(` ๐ ${debt}`)));
}
// Display Mafia Level debt
if (debtReport.mafia.length > 0) {
console.log(colors.bold(colors.magenta('๐ด๏ธ MAFIA LEVEL - FAMILY BUSINESS:')));
debtReport.mafia.forEach(debt => console.log(colors.magenta(` ๐ฐ ${debt}`)));
}
// Display debt by priority
if (debtReport.p1.length > 0) {
console.log(colors.bold(colors.red('๐จ P1 CRITICAL - FORECLOSURE IMMINENT:')));
debtReport.p1.forEach(debt => console.log(colors.red(` โ ${debt}`)));
}
if (debtReport.p2.length > 0) {
console.log(colors.bold(colors.yellow('\nโ ๏ธ P2 HIGH - REPOSSESSION NOTICE:')));
debtReport.p2.forEach(debt => console.log(colors.yellow(` โก ${debt}`)));
}
if (debtReport.p3.length > 0) {
console.log(colors.bold(colors.blue('\n๐ P3 MEDIUM - LIENS FILED:')));
debtReport.p3.forEach(debt => console.log(colors.blue(` ๐ ${debt}`)));
}
if (debtReport.p4.length > 0) {
console.log(colors.bold(colors.gray('\n๐ฐ P4 LOW - INTEREST ACCRUING:')));
debtReport.p4.forEach(debt => console.log(colors.gray(` ๐ณ ${debt}`)));
}
}
// Save output if requested
if (options.output) {
await techDebtManager.saveDebtReport(debtReport, options.output);
console.log(colors.green(`\n๐พ Debt report saved to ${options.output}`));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ DEBT COLLECTION FAILED:')));
console.error(colors.red(`Your code is so broken even the debt collector quit: ${error.message}`));
process.exit(1);
}
});
// Fix command - attempt to auto-fix common issues
program
.command('fix')
.description(colors.green('๐ง Auto-fix common debt issues (formatting, console.logs, simple errors)'))
.option('-d, --dry-run', 'Show what would be fixed without making changes')
.option('-t, --type <type>', 'Fix specific type: formatting, console-logs, todos, spelling')
.action(async (options) => {
console.log(colors.bold(colors.green('\n๐ง REFUCTOR AUTO-FIXER')));
console.log(colors.gray('Attempting to resolve your debt issues automatically...\n'));
try {
const projectPath = process.cwd();
const fixReport = { fixed: 0, attempted: 0, errors: [] };
// Run targeted fixes based on type
if (!options.type || options.type === 'formatting') {
console.log(colors.blue('๐จ Attempting to fix formatting issues...'));
const formattingResult = await attemptFormattingFix(projectPath, options.dryRun);
fixReport.fixed += formattingResult.fixed;
fixReport.attempted += formattingResult.attempted;
if (formattingResult.error) fixReport.errors.push(formattingResult.error);
}
if (!options.type || options.type === 'console-logs') {
console.log(colors.yellow('๐๏ธ Attempting to remove console.log statements...'));
const consoleResult = await attemptConsoleLogCleanup(projectPath, options.dryRun);
fixReport.fixed += consoleResult.fixed;
fixReport.attempted += consoleResult.attempted;
if (consoleResult.error) fixReport.errors.push(consoleResult.error);
}
if (!options.type || options.type === 'spelling') {
console.log(colors.magenta('๐ Attempting to fix spelling issues...'));
const spellResult = await attemptSpellingFix(projectPath, options.dryRun);
fixReport.fixed += spellResult.fixed;
fixReport.attempted += spellResult.attempted;
if (spellResult.error) fixReport.errors.push(spellResult.error);
}
// Report results
if (fixReport.fixed > 0) {
console.log(colors.bold(colors.green(`\nโ
DEBT REDUCTION SUCCESSFUL!`)));
console.log(colors.green(`Fixed ${fixReport.fixed} out of ${fixReport.attempted} issues`));
console.log(colors.cyan('Your debt collectors are pleased with this progress.'));
} else if (fixReport.attempted > 0) {
console.log(colors.bold(colors.yellow(`\nโ ๏ธ AUTO-FIX PARTIALLY SUCCESSFUL`)));
console.log(colors.yellow(`Attempted ${fixReport.attempted} fixes, but manual intervention required`));
console.log(colors.gray('Some debt requires human intelligence. Shocking, we know.'));
} else {
console.log(colors.bold(colors.blue(`\n๐ฏ NO FIXABLE ISSUES DETECTED`)));
console.log(colors.blue('Either you\'re debt-free, or your issues are too complex for automation.'));
}
if (fixReport.errors.length > 0) {
console.log(colors.bold(colors.red('\n๐ฅ SOME FIXES FAILED:')));
fixReport.errors.forEach(error => console.log(colors.red(` โ ${error}`)));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ AUTO-FIX SYSTEM FAILURE:')));
console.error(colors.red(`The debt is so bad, even our automatic fixer quit: ${error.message}`));
process.exit(1);
}
});
// Info command - show capabilities and configuration detection
program
.command('info')
.description(colors.blue('โน๏ธ Show Refuctor capabilities and detected configurations'))
.action(async () => {
console.log(colors.bold(colors.cyan('\n๐ REFUCTOR DEBT DETECTION CAPABILITIES')));
console.log(colors.gray(`Version: ${packageJson.version}`));
console.log(colors.gray('Checking your project configuration...\n'));
const projectPath = process.cwd();
const capabilities = {
core: [],
enhanced: [],
configs: [],
files: []
};
// Core detection (always available)
capabilities.core = [
'โ
Markdown linting (markdownlint)',
'โ
Spell checking (cspell with snarky intelligence)',
'โ
Security audit (npm audit)',
'โ
Dependency analysis'
];
// Enhanced detection (check if methods exist)
const detector = new DebtDetector();
if (detector.detectESLintDebt) {
const eslintConfigs = ['.eslintrc.js', '.eslintrc.json', '.eslintrc.yml', 'eslint.config.js'];
const hasESLint = eslintConfigs.some(file => fs.existsSync(path.join(projectPath, file)));
capabilities.enhanced.push(hasESLint ? 'โ
ESLint detection (config found)' : 'โ ๏ธ ESLint detection (no config found)');
capabilities.configs.push(...eslintConfigs.filter(file => fs.existsSync(path.join(projectPath, file))));
}
if (detector.detectTypeScriptDebt) {
const hasTSConfig = fs.existsSync(path.join(projectPath, 'tsconfig.json'));
capabilities.enhanced.push(hasTSConfig ? 'โ
TypeScript compilation (tsconfig.json found)' : 'โ ๏ธ TypeScript compilation (no tsconfig.json)');
if (hasTSConfig) capabilities.configs.push('tsconfig.json');
}
if (detector.detectCodeQualityDebt) {
capabilities.enhanced.push('โ
Code quality analysis (console.logs, TODOs, dead code)');
}
if (detector.detectFormattingDebt) {
const prettierConfigs = ['.prettierrc', '.prettierrc.json', '.prettierrc.js', 'prettier.config.js'];
const hasPrettier = prettierConfigs.some(file => fs.existsSync(path.join(projectPath, file)));
capabilities.enhanced.push(hasPrettier ? 'โ
Prettier formatting (config found)' : 'โ ๏ธ Prettier formatting (no config found)');
capabilities.configs.push(...prettierConfigs.filter(file => fs.existsSync(path.join(projectPath, file))));
}
// File analysis
const codeFiles = glob.sync('**/*.{js,ts,jsx,tsx}', { cwd: projectPath, ignore: ['node_modules/**', '.git/**'] });
const mdFiles = glob.sync('**/*.{md,mdc}', { cwd: projectPath, ignore: ['node_modules/**', '.git/**'] });
const hasPackageJson = fs.existsSync(path.join(projectPath, 'package.json'));
capabilities.files = [
`๐ ${mdFiles.length} markdown files`,
`๐ป ${codeFiles.length} code files`,
hasPackageJson ? '๐ฆ package.json found' : 'โ No package.json'
];
// Display results
console.log(colors.bold(colors.green('๐ CORE DETECTION (Always Available):')));
capabilities.core.forEach(item => console.log(` ${item}`));
if (capabilities.enhanced.length > 0) {
console.log(colors.bold(colors.cyan('\nโก ENHANCED DETECTION:')));
capabilities.enhanced.forEach(item => console.log(` ${item}`));
}
console.log(colors.bold(colors.blue('\n๐ PROJECT ANALYSIS:')));
capabilities.files.forEach(item => console.log(` ${item}`));
if (capabilities.configs.length > 0) {
console.log(colors.bold(colors.yellow('\nโ๏ธ DETECTED CONFIG FILES:')));
capabilities.configs.forEach(config => console.log(` ๐ ${config}`));
}
console.log(colors.bold(colors.magenta('\n๐ฏ DEBT THRESHOLDS:')));
console.log(' ๐ค Guido Level: 150+ ESLint errors, 50+ TS errors (EXTREME!)');
console.log(' ๐ด๏ธ Mafia Level: 75+ ESLint errors, 30+ TS errors (LOAN SHARK!)');
console.log(colors.bold(colors.gray('\n๐ก USAGE TIPS:')));
console.log(' refuctor cook # Export VS Code problems (when scan misses issues)');
console.log(' refuctor init # Set up debt tracking (TECHDEBT.md)');
});
// Cook the Books command - export VS Code problems to markdown
program
.command('cook-the-books')
.alias('cook')
.description(colors.yellow('๐ณ Export VS Code problems to debt report (when Refuctor scan misses issues)'))
.option('-o, --output <file>', 'Output file for cooked books', 'vscode-debt-report.md')
.option('-f, --format <type>', 'Output format: md, json, csv', 'md')
.action(async (options) => {
console.log(colors.bold(colors.yellow('\n๐ณ COOKING THE BOOKS...')));
console.log(colors.gray('Extracting VS Code problems that slipped through the cracks...\n'));
try {
const projectPath = process.cwd();
const cookingReport = await cookTheBooks(projectPath, options);
if (cookingReport.totalIssues === 0) {
console.log(colors.green('๐ No hidden problems found - VS Code is clean!'));
console.log(colors.gray('Either VS Code has no problems, or they\'re already detected by Refuctor.'));
} else {
console.log(colors.bold(colors.red(`๐ COOKED BOOKS REVEAL: ${cookingReport.totalIssues} hidden issues!`)));
console.log(colors.yellow(`๐ Exported to: ${options.output}`));
console.log(colors.gray(`This explains why VS Code status bar shows problems Refuctor missed.\n`));
// Show summary by file
console.log(colors.bold(colors.cyan('๐ฏ TOP PROBLEM FILES:')));
Object.entries(cookingReport.fileBreakdown)
.sort(([,a], [,b]) => b - a)
.slice(0, 5)
.forEach(([file, count]) => {
console.log(colors.cyan(` ๐ ${file}: ${count} issues`));
});
console.log(colors.bold(colors.magenta('\n๐ก RECOMMENDED ACTIONS:')));
console.log(colors.magenta('1. Review the exported report for specific fixes'));
console.log(colors.magenta('2. Run VS Code "Problems" panel fixes manually'));
console.log(colors.magenta('3. Consider adding missing linter configs for Refuctor'));
console.log(colors.magenta('4. Re-run refuctor scan after manual cleanup'));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ COOKING FAILED:')));
console.error(colors.red(`Book cooking error: ${error.message}`));
console.log(colors.gray('\nTip: Make sure VS Code diagnostics are available or run from VS Code terminal'));
process.exit(1);
}
});
// Status command - show current debt overview
program
.command('status')
.description(colors.blue('๐ Show current debt status and trends'))
.action(async () => {
console.log(colors.bold(colors.cyan('\n๐ REFUCTOR DEBT STATUS REPORT')));
console.log(colors.gray('Checking your financial... err, technical standing...\n'));
try {
const status = await techDebtManager.getDebtStatus(process.cwd());
if (status.hasDebtFile) {
console.log(colors.green('โ
TECHDEBT.md tracking active'));
console.log(colors.blue(`๐ Sessions tracked: ${status.sessionsTracked}`));
console.log(colors.yellow(`โ๏ธ Current debt level: ${status.currentDebtLevel}`));
if (status.debtTrend === 'improving') {
console.log(colors.green('๐ Debt trend: IMPROVING (you\'re doing great!)'));
} else if (status.debtTrend === 'worsening') {
console.log(colors.red('๐ Debt trend: WORSENING (time to panic?)'));
} else {
console.log(colors.gray('๐ Debt trend: STABLE (maintain course)'));
}
} else {
console.log(colors.yellow('โ ๏ธ No TECHDEBT.md found'));
console.log(colors.gray('Run `refuctor init` to start tracking your technical debt'));
}
} catch (error) {
console.error(colors.red(`Status check failed: ${error.message}`));
process.exit(1);
}
});
// Init command - automated setup wizard
program
.command('init')
.description(colors.green('๐๏ธ Run automated setup wizard to initialize complete debt management infrastructure'))
.option('-f, --force', 'Overwrite existing configuration files')
.option('--basic', 'Run basic setup (TECHDEBT.md only)')
.action(async (options) => {
console.log(colors.bold(colors.green('\n๐๏ธ REFUCTOR AUTOMATED SETUP WIZARD')));
console.log(colors.gray('Establishing comprehensive debt management infrastructure...\n'));
try {
if (options.basic) {
// Basic setup - just TECHDEBT.md (original functionality)
console.log(colors.yellow('Running basic setup (TECHDEBT.md only)...\n'));
const result = await techDebtManager.initializeProject(process.cwd(), options.force);
if (result.created) {
console.log(colors.bold(colors.green('โ
BASIC DEBT TRACKING ACTIVATED!')));
console.log(colors.green('TECHDEBT.md created - your debt has nowhere to hide now'));
console.log(colors.blue('Run `refuctor scan` to start detecting issues'));
console.log(colors.gray('\n๐ก For full setup wizard, run `refuctor init` without --basic flag'));
} else if (result.exists && !options.force) {
console.log(colors.yellow('โ ๏ธ TECHDEBT.md already exists'));
console.log(colors.gray('Use --force to overwrite, or you\'re already in debt management'));
}
} else {
// Full automated setup wizard
console.log(colors.cyan('Running comprehensive automated setup wizard...\n'));
const wizard = new SetupWizard();
const setupResults = await wizard.runSetupWizard(process.cwd(), options);
// Display setup summary
console.log(colors.bold(colors.green('\n๐ SETUP WIZARD COMPLETE!')));
console.log(colors.bold(colors.cyan('๐ SETUP SUMMARY:')));
if (setupResults.techDebtCreated) {
console.log(colors.green(' โ
TECHDEBT.md created with project-specific context'));
}
if (setupResults.spellCheckSetup) {
console.log(colors.green(' โ
Spell checking configured with project dictionary'));
}
if (setupResults.debtIgnoreCreated) {
console.log(colors.green(' โ
Debt ignore patterns configured'));
}
if (setupResults.workspaceConfigured) {
console.log(colors.green(' โ
IDE integration configured'));
}
if (setupResults.configsGenerated.length > 0) {
console.log(colors.blue(` ๐ Generated configs: ${setupResults.configsGenerated.join(', ')}`));
}
console.log(colors.bold(colors.green('\n๐ READY FOR DEBT MANAGEMENT!')));
console.log(colors.blue('Next steps:'));
console.log(colors.blue(' 1. Run `refuctor scan` to analyze current debt'));
console.log(colors.blue(' 2. Review and customize generated configuration files'));
console.log(colors.blue(' 3. Start your debt-free development journey!'));
// Show project-specific recommendations
if (wizard.projectAnalysis) {
console.log(colors.gray(`\n๐ก Optimized for ${wizard.projectAnalysis.projectType} development`));
}
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ SETUP WIZARD FAILED:')));
console.error(colors.red(`Setup error: ${error.message}`));
console.error(colors.gray('Try running with --basic flag for minimal setup'));
process.exit(1);
}
});
// Shame command - humorous debt report
program
.command('shame')
.description(colors.magenta('๐ฑ Generate a humorous debt shaming report'))
.action(async () => {
console.log(colors.bold(colors.magenta('\n๐ฑ REFUCTOR HALL OF SHAME')));
console.log(colors.gray('Preparing your public humiliation...\n'));
try {
const shameReport = await debtDetector.generateShameReport(process.cwd());
if (shameReport.totalShame === 0) {
console.log(colors.bold(colors.green('๐ CONGRATULATIONS!')));
console.log(colors.green('Your code is so clean it squeaks. No shame here, you absolute legend.'));
} else {
console.log(colors.bold(colors.red(`๐ฅ SHAME LEVEL: ${shameReport.shameLevel.toUpperCase()}`)));
console.log(colors.yellow(`๐ธ Total debt: ${shameReport.totalShame} issues`));
console.log(colors.gray(`๐ Time wasted: ~${shameReport.timeWasted} hours`));
console.log(colors.magenta(`๐ฐ Estimated cleanup cost: $${shameReport.cleanupCost}`));
console.log(colors.red('\n๐ญ SHAME BREAKDOWN:'));
shameReport.shameItems.forEach(item => {
console.log(colors.red(` ${item.emoji} ${item.description}`));
});
console.log(colors.yellow('\n๐ก REDEMPTION PATH:'));
console.log(colors.green(' 1. Run `refuctor scan` to see all issues'));
console.log(colors.green(' 2. Fix P1 critical issues immediately'));
console.log(colors.green(' 3. Schedule time for P2-P4 cleanup'));
console.log(colors.green(' 4. Run `refuctor shame` again to measure improvement'));
}
} catch (error) {
console.error(colors.red(`Shame generation failed: ${error.message}`));
process.exit(1);
}
});
// Fix command - general auto-repair
program
.command('fix')
.description(colors.cyan('๐ง Auto-repair common debt issues (safe fixes only)'))
.option('--dry-run', 'Preview fixes without applying them')
.option('--all', 'Fix all file types (markdown, spelling, etc.)')
.action(async (options) => {
console.log(colors.bold(colors.cyan('\n๐ง REFUCTOR AUTO-REPAIR SERVICE')));
console.log(colors.gray('Applying safe automated fixes to eliminate debt...\n'));
try {
let totalFixes = 0;
// Always fix markdown (safe and proven)
console.log(colors.magenta('๐ Applying markdown fixes...'));
const glob = require('glob');
const mdFiles = glob.sync('**/*.{md,mdc}', {
ignore: ['node_modules/**', '.git/**', 'dist/**', 'build/**', 'REFUCTOR_MYTHOS.md']
});
for (const file of mdFiles) {
const report = await markdownFixerGoon.eliminateDebt(file, options.dryRun);
if (report.fixesApplied > 0) {
console.log(colors.green(` โ
${file}: ${report.fixesApplied} fixes applied`));
totalFixes += report.fixesApplied;
}
}
// Future: Add other safe auto-fixes here
if (options.all) {
console.log(colors.gray(' ๐ฆ Additional fix types coming in future updates...'));
}
console.log(colors.bold(colors.green(`\n๐ AUTO-REPAIR COMPLETE!`)));
console.log(colors.green(`Total fixes applied: ${totalFixes}`));
if (options.dryRun) {
console.log(colors.yellow('โ ๏ธ DRY RUN: No actual changes made'));
console.log(colors.gray('Remove --dry-run flag to apply fixes'));
} else if (totalFixes > 0) {
console.log(colors.green('Your debt has been refinanced. Much better!'));
} else {
console.log(colors.blue('No debt found to fix. You magnificent debt-slayer!'));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ AUTO-REPAIR FAILED:')));
console.error(colors.red(`Even our automated systems couldn't handle this: ${error.message}`));
process.exit(1);
}
});
// Wrap command - session wrap protocol
program
.command('wrap')
.description(colors.blue('๐ Execute comprehensive session wrap protocol'))
.option('--skip-debt-scan', 'Skip automated debt detection')
.option('--brief', 'Generate brief wrap summary')
.action(async (options) => {
console.log(colors.bold(colors.blue('\n๐ REFUCTOR SESSION WRAP PROTOCOL')));
console.log(colors.gray('Executing comprehensive session cleanup and debt assessment...\n'));
try {
// Step 1: Debt scan (unless skipped)
if (!options.skipDebtScan) {
console.log(colors.cyan('๐ STEP 1: Technical Debt Assessment'));
const debtReport = await debtDetector.scanProject(process.cwd(), true);
if (debtReport.totalDebt === 0) {
console.log(colors.bold(colors.green(' โ
DEBT-FREE STATUS MAINTAINED!')));
} else {
console.log(colors.yellow(` โ ๏ธ ${debtReport.totalDebt} debt items detected`));
console.log(colors.gray(' Run `refuctor fix` or `refuctor scan` for details'));
}
}
// Step 2: Session Summary
console.log(colors.cyan('\n๐ STEP 2: Session Summary Generation'));
// Future: Add more comprehensive session analysis
console.log(colors.green(' โ
Session data collected'));
// Step 3: Recommendations
console.log(colors.cyan('\n๐ก STEP 3: Next Session Recommendations'));
console.log(colors.blue(' ๐ฏ Continue with Phase 1 completion'));
console.log(colors.blue(' ๐ Consider NPM package publishing'));
console.log(colors.blue(' ๐ Add more specialized goons'));
if (options.brief) {
console.log(colors.bold(colors.green('\n๐ BRIEF WRAP COMPLETE')));
} else {
console.log(colors.bold(colors.green('\n๐ COMPREHENSIVE WRAP COMPLETE')));
console.log(colors.gray('Session state documented for next development cycle'));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ SESSION WRAP FAILED:')));
console.error(colors.red(`Wrap protocol error: ${error.message}`));
process.exit(1);
}
});
// Easter egg commands
program
.command('bailmeout')
.description(colors.gray('๐ Emergency motivation for desperate developers'))
.action(() => {
const motivationalQuotes = [
"Your code called. It wants a debt consolidation loan.",
"Bankruptcy is not an option. Fix it or live with the shame.",
"Even your comments have trust issues with your code.",
"This isn't technical debt, it's technical bankruptcy.",
"Your future self is writing a strongly worded letter about this code.",
"Code like this is why senior developers drink coffee by the pot.",
"Git blame was invented for code like yours.",
"Your IDE is filing a restraining order."
];
const quote = motivationalQuotes[Math.floor(Math.random() * motivationalQuotes.length)];
console.log(colors.bold(colors.yellow('\n๐ EMERGENCY MOTIVATION:')));
console.log(colors.white(`"${quote}"`));
console.log(colors.gray('\n- The Refuctor Debt Collection Agency\n'));
});
// Mafia/Guido test command - demonstrate loan shark escalation hierarchy
program
.command('guido')
.description(colors.red('๐ค [EASTER EGG] Demonstrate the Mafia โ Guido escalation hierarchy'))
.option('--mafia-only', 'Show only mafia takeover (before Guido)')
.action((options) => {
const detector = new DebtDetector();
if (options.mafiaOnly) {
// Show mafia takeover
console.log(colors.bold(colors.magenta('\n' + '='.repeat(60))));
console.log(colors.bold(colors.magenta('๐ด๏ธ MAFIA TAKEOVER - DEBT SOLD TO THE FAMILY ๐ด๏ธ')));
console.log(colors.bold(colors.magenta('='.repeat(60))));
const mafiaMessage = detector.mafiaMessages[Math.floor(Math.random() * detector.mafiaMessages.length)];
console.log(colors.magenta(mafiaMessage));
console.log(colors.bold(colors.yellow('๐ฐ VIGorish Rate: 15% daily')));
console.log(colors.bold(colors.yellow('๐ธ Daily Penalty: 11 debt units')));
console.log(colors.bold(colors.cyan('\n๐ฐ DEBT SOLD TO FAMILY: Your technical debt has been purchased by private investors. VIGorish is now being charged daily.')));
console.log(colors.magenta('='.repeat(60)));
console.log(colors.gray('\n๐ก Mafia takeover happens when:'));
console.log(colors.gray(' โข 100+ markdown errors'));
console.log(colors.gray(' โข 50+ spelling errors'));
console.log(colors.gray(' โข 3+ critical security vulnerabilities'));
console.log(colors.gray(' โข 75+ total debt items'));
console.log(colors.gray(' โข 5+ P1 critical issues'));
console.log(colors.gray('\nโฐ If VIGorish goes unpaid for 2+ days... Guido gets deployed.'));
} else {
// Show full Guido escalation
console.log(colors.bold(colors.red('\n' + '='.repeat(80))));
console.log(colors.bold(colors.red('๐ค GUIDO THE THUMB CRUSHER HAS ARRIVED ๐ค')));
console.log(colors.bold(colors.red('='.repeat(80))));
const randomMessage = detector.getGuidoMessage();
console.log(colors.red(randomMessage));
console.log(colors.bold(colors.red('โฐ VIGorish overdue: 3 days')));
console.log(colors.bold(colors.yellow('\n๐ค GUIDO DEPLOYED: VIGorish payment overdue. The Thumb Crusher is here for collection. Fix debt NOW or face "coding accidents".')));
console.log(colors.red('='.repeat(80)));
console.log(colors.gray('\n๐ก Debt Escalation Hierarchy:'));
console.log(colors.gray(' 1. P4 โ P3 โ P2 โ P1 (Normal Collection Agency)'));
console.log(colors.gray(' 2. ๐ด๏ธ MAFIA TAKEOVER (debt sold to family, VIGorish starts)'));
console.log(colors.gray(' 3. ๐ค GUIDO DEPLOYED (VIGorish overdue 2+ days)'));
console.log(colors.gray('\n๐ญ This is a demonstration. Use --mafia-only to see mafia stage.'));
}
});
// Un-cook command - Process ignored files in manageable chunks
program
.command('uncook')
.description('๐ณ Un-cook the books: Process ignored files in manageable chunks')
.option('--chunks <size>', 'Chunk size for batch processing (default: 10)', '10')
.option('--max-chunks <count>', 'Maximum chunks to process', '20')
.option('--max-files <count>', 'Maximum files for smart mode (default: 25)', '25')
.action(async (options) => {
try {
const { Accountant } = require('../src/goons/accountant');
const accountant = new Accountant();
const uncookOptions = {
chunkSize: parseInt(options.chunks),
maxChunks: parseInt(options.maxChunks),
maxFiles: parseInt(options.maxFiles)
};
await accountant.uncookTheBooks('.', uncookOptions);
} catch (error) {
console.error('๐ฅ Un-cooking failed:', error.message);
process.exit(1);
}
});
// Goon command - specialized debt elimination tools
const goonCommand = program
.command('goon')
.description(colors.magenta('๐ Deploy specialized debt elimination goons'))
.configureOutput({
writeOut: (str) => process.stdout.write(str),
writeErr: (str) => process.stderr.write(str)
});
// Goon: Markdown Fixer
goonCommand
.command('fix-markdown <file>')
.description(colors.magenta('๐ Aggressive markdown debt elimination'))
.option('-p, --preview', 'Preview fixes without applying them')
.action(async (file, options) => {
console.log(colors.bold(colors.magenta('\n๐ MARKDOWN FIXER GOON DEPLOYED')));
console.log(colors.gray(`Target acquired: ${file}`));
console.log(colors.gray('Initiating aggressive document restructuring...\n'));
try {
const report = options.preview
? await markdownFixerGoon.previewFixes(file)
: await markdownFixerGoon.eliminateDebt(file);
// Handle debt-ignored files
if (report.ignored) {
console.log(colors.bold(colors.gray('๐ซ FILE DEBT-IGNORED')));
console.log(colors.gray(`๐ File: ${report.filePath}`));
console.log(colors.yellow(`๐ฌ Status: ${report.message}`));
console.log(colors.gray('\nFile excluded from debt tracking per .debtignore patterns.'));
return;
}
console.log(colors.bold(colors.green('๐ DEBT ELIMINATION REPORT:')));
console.log(colors.blue(`๐ File: ${report.filePath}`));
console.log(colors.blue(`๐ Lines: ${report.originalLines} โ ${report.fixedLines}`));
console.log(colors.green(`๐ง Fixes Applied: ${report.fixesApplied}`));
console.log(colors.magenta(`๐ฌ Status: ${report.message}`));
if (options.preview) {
console.log(colors.yellow('\nโ ๏ธ PREVIEW MODE: No changes were made'));
console.log(colors.gray('Remove --preview flag to apply fixes'));
} else {
console.log(colors.bold(colors.green('\nโ
DEBT ELIMINATED!')));
console.log(colors.green('Your markdown is now cleaner than a loan shark\'s books.'));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ GOON DEPLOYMENT FAILED:')));
console.error(colors.red(`Even our best goon couldn't handle this mess: ${error.message}`));
process.exit(1);
}
});
// Goon: Fix-Lint
goonCommand
.command('fix-lint')
.description(colors.magenta('๐ง Aggressive code quality debt elimination'))
.option('-d, --dry-run', 'Preview fixes without applying them', true)
.option('-f, --files <pattern>', 'Target specific file pattern')
.option('-t, --types <types>', 'Linter types (javascript,typescript,json)', 'javascript,typescript,json')
.action(async (options) => {
console.log(colors.bold(colors.magenta('\n๐ง FIX-LINT GOON DEPLOYED')));
console.log(colors.gray('Aggressive code quality enforcement specialist'));
console.log(colors.gray('Initiating linting debt elimination...\n'));
try {
const FixLintGoon = require('../src/goons/fix-lint');
const fixLintGoon = new FixLintGoon();
const types = options.types.split(',').map(t => t.trim());
const goonOptions = {
dryRun: options.dryRun,
filePattern: options.files,
types: types
};
const report = await fixLintGoon.eliminateDebt('.', goonOptions);
console.log(colors.bold(colors.green('\n๐ FIX-LINT GOON DEPLOYMENT COMPLETE')));
console.log(colors.blue(`โฑ๏ธ Duration: ${Math.round(report.duration / 1000)}s`));
console.log(colors.blue(`๐ Files Processed: ${report.totalFilesProcessed}`));
console.log(colors.yellow(`๐๏ธ Files on Debt Holiday: ${report.totalFilesIgnored}`));
console.log(colors.green(`๐ง Total Fixes: ${report.totalFixesApplied}`));
if (report.totalFixesApplied === 0 && report.totalFilesProcessed > 0) {
console.log(colors.bold(colors.green('\n๐ DEBT-FREE ACHIEVEMENT UNLOCKED!')));
console.log(colors.green('Your code is cleaner than a mobster\'s money after laundering!'));
} else if (report.totalFixesApplied > 0) {
console.log(colors.bold(colors.green(`\n๐ฐ DEBT REFINANCED: ${report.totalFixesApplied} issues eliminated!`)));
console.log(colors.green('Your code just got a credit score boost!'));
}
if (options.dryRun) {
console.log(colors.yellow('\nโ ๏ธ DRY RUN MODE: No changes were made'));
console.log(colors.gray('Remove --dry-run flag to apply fixes'));
}
if (report.errors.length > 0) {
console.log(colors.yellow(`\nโ ๏ธ Encountered ${report.errors.length} errors during processing`));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ FIX-LINT GOON DEPLOYMENT FAILED:')));
console.error(colors.red(`Even our most aggressive goon couldn't handle this mess: ${error.message}`));
process.exit(1);
}
});
// Goon: Clean-Imports
goonCommand
.command('clean-imports')
.description(colors.magenta('๐งน Aggressive import optimization and cleanup'))
.option('-d, --dry-run', 'Preview cleanup without applying changes', true)
.option('-a, --aggressive', 'Enable aggressive cleanup mode')
.option('-u, --unused', 'Remove unused imports', true)
.action(async (options) => {
console.log(colors.bold(colors.magenta('\n๐งน IMPORT CLEANER GOON DEPLOYED')));
console.log(colors.gray('Aggressive import optimization specialist'));
console.log(colors.gray('Initiating import debt elimination...\n'));
try {
const { ImportCleaner } = require('../src/goons/import-cleaner');
const importCleaner = new ImportCleaner();
const goonOptions = {
dryRun: options.dryRun,
aggressive: options.aggressive,
removeUnused: options.unused
};
const report = await importCleaner.eliminateDebt('.', goonOptions);
console.log(colors.bold(colors.green('\n๐ IMPORT CLEANER GOON DEPLOYMENT COMPLETE')));
console.log(colors.blue(`โฑ๏ธ Duration: ${Math.round(report.duration / 1000)}s`));
console.log(colors.blue(`๐ Files Analyzed: ${report.totalFilesAnalyzed}`));
console.log(colors.yellow(`๐๏ธ Unused Imports Found: ${report.unusedImportsFound}`));
console.log(colors.yellow(`๐ Circular Dependencies: ${report.circularDependencies}`));
if (report.totalIssuesFound === 0) {
console.log(colors.bold(colors.green('\n๐ IMPORT PERFECTION ACHIEVED!')));
console.log(colors.green('Your imports are cleaner than a mobster\'s money after laundering!'));
} else if (report.importsRemoved > 0) {
console.log(colors.bold(colors.green(`\n๐ฐ IMPORT DEBT REFINANCED: ${report.importsRemoved} unused imports eliminated!`)));
if (report.bytesFreed > 0) {
console.log(colors.green(`๐พ Bytes freed: ${report.bytesFreed} (bundle optimization)`));
}
}
if (options.dryRun) {
console.log(colors.yellow('\nโ ๏ธ DRY RUN MODE: No changes were made'));
console.log(colors.gray('Remove --dry-run flag to apply cleanup'));
}
if (report.errors.length > 0) {
console.log(colors.yellow(`\nโ ๏ธ Encountered ${report.errors.length} errors during processing`));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ IMPORT CLEANER GOON DEPLOYMENT FAILED:')));
console.error(colors.red(`Import optimization failed: ${error.message}`));
process.exit(1);
}
});
// Goon: Comment Killer
goonCommand
.command('kill-comments')
.option('--dry-run', 'Preview comment elimination without making changes')
.option('--aggressive', 'Enable aggressive comment removal mode')
.option('--preserve-license', 'Keep license headers intact')
.description('๐ Eliminate TODO comments, dead code comments, and debug cruft')
.action(async (options) => {
try {
console.log(colors.bold(colors.magenta('\n๐ COMMENT KILLER GOON DEPLOYED')));
console.log(colors.gray('Targeting TODO comments, debug statements, and commented-out code...'));
const { CommentKiller } = require('../src/goons/comment-killer');
const commentKiller = new CommentKiller();
const goonOptions = {
dryRun: options.dryRun || false,
aggressive: options.aggressive || false,
preserveLicense: options.preserveLicense !== false,
showProgress: true
};
const report = await commentKiller.eliminateCommentDebt('.', goonOptions);
console.log(colors.bold(colors.green('\n๐ COMMENT KILLER GOON DEPLOYMENT COMPLETE')));
if (report.summary) {
console.log(colors.cyan('\n๐ ELIMINATION SUMMARY:'));
if (report.summary.todoComments > 0) {
console.log(colors.yellow(` โข TODO Comments: ${report.summary.todoComments} eliminated`));
}
if (report.summary.debugComments > 0) {
console.log(colors.yellow(` โข Debug Comments: ${report.summary.debugComments} eliminated`));
}
if (report.summary.commentedCode > 0) {
console.log(colors.yellow(` โข Commented Code: ${report.summary.commentedCode} blocks removed`));
}
if (report.summary.emptyComments > 0) {
console.log(colors.yellow(` โข Empty Comments: ${report.summary.emptyComments} cleaned up`));
}
const totalEliminated = Object.values(report.summary).reduce((sum, count) => sum + count, 0);
if (totalEliminated === 0) {
console.log(colors.green(' โจ No comment debt found! Your comments are pristine.'));
} else {
console.log(colors.green(` ๐ช Total comment debt eliminated: ${totalEliminated} issues`));
}
}
if (options.dryRun) {
console.log(colors.blue('\n๐ DRY RUN MODE: No files were modified'));
console.log(colors.blue(' Run without --dry-run to apply changes'));
} else {
console.log(colors.green('\nโ
Comment elimination complete! Repository is cleaner.'));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ COMMENT KILLER GOON DEPLOYMENT FAILED:')));
console.error(colors.red(`Comment elimination failed: ${error.message}`));
process.exit(1);
}
});
// Goon: The Fixer
goonCommand
.command('fix-syntax')
.option('--dry-run', 'Preview syntax fixes without making changes')
.option('--emergency', 'Emergency pre-build mode - fix only critical blocking issues')
.option('--max-attempts <number>', 'Maximum fix attempts per file', '5')
.description('๐ง Emergency pre-build syntax cleanup and formatting fixes')
.action(async (options) => {
try {
console.log(colors.bold(colors.magenta('\n๐ง THE FIXER GOON DEPLOYED')));
console.log(colors.gray('Emergency pre-build cleanup in progress...'));
const { Fixer } = require('../src/goons/fixer');
const fixer = new Fixer();
const goonOptions = {
dryRun: options.dryRun || false,
emergency: options.emergency || false,
maxFixAttempts: parseInt(options.maxAttempts) || 5,
showProgress: true
};
const report = await fixer.emergencyFix('.', goonOptions);
console.log(colors.bold(colors.green('\n๐ THE FIXER GOON DEPLOYMENT COMPLETE')));
if (report.summary) {
console.log(colors.cyan('\n๐ง REPAIR SUMMARY:'));
if (report.summary.syntaxFixed > 0) {
console.log(colors.yellow(` โข Syntax Errors: ${report.summary.syntaxFixed} fixed`));
}
if (report.summary.formattingFixed > 0) {
console.log(colors.yellow(` โข Formatting Issues: ${report.summary.formattingFixed} corrected`));
}
if (report.summary.importsFixed > 0) {
console.log(colors.yellow(` โข Import Issues: ${report.summary.importsFixed} resolved`));
}
if (report.summary.consoleStatementsRemoved > 0) {
console.log(colors.yellow(` โข Console Statements: ${report.summary.consoleStatementsRemoved} removed`));
}
const totalFixed = Object.values(report.summary).reduce((sum, count) => sum + count, 0);
if (totalFixed === 0) {
console.log(colors.green(' โจ No syntax issues found! Code is ready for build.'));
} else {
console.log(colors.green(` ๐ช Total issues fixed: ${totalFixed} problems resolved`));
}
}
if (options.dryRun) {
console.log(colors.blue('\n๐ DRY RUN MODE: No files were modified'));
console.log(colors.blue(' Run without --dry-run to apply fixes'));
} else {
console.log(colors.green('\nโ
Emergency fixes complete! Build should proceed.'));
}
} catch (error) {
console.error(colors.bold(colors.red('\n๐ฅ THE FIXER GOON DEPLOYMENT FAILED:')));
console.error(colors.red(`Emergency fixes failed: ${error.message}`));
process.exit(1);
}
});
// Goon: Dead Code Hunter
goonCommand
.command('hunt-dead-c