eslint-plugin-ai-guard 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../cli/utils/config-manager.ts","../../cli/index.ts","../../cli/commands/run.ts","../../cli/utils/eslint-runner.ts","../../cli/utils/logger.ts","../../cli/commands/init.ts","../../cli/utils/detector.ts","../../cli/commands/doctor.ts","../../cli/commands/preset.ts","../../cli/commands/ignore.ts","../../cli/commands/baseline.ts","../../cli/commands/init-context.ts","../../cli/commands/report.ts"],"sourcesContent":["import fs from 'fs';\r\nimport path from 'path';\r\nimport type { ConfigType } from './detector.js';\r\n\r\nexport type Preset = 'recommended' | 'strict' | 'security';\r\n\r\n// ─── File I/O primitives ──────────────────────────────────────────────────────\r\n\r\nexport function backupConfig(configPath: string): string {\r\n const backupPath = `${configPath}.bak`;\r\n fs.copyFileSync(configPath, backupPath);\r\n return backupPath;\r\n}\r\n\r\nexport function readConfig(configPath: string): string {\r\n return fs.readFileSync(configPath, 'utf-8');\r\n}\r\n\r\nexport function writeConfig(configPath: string, content: string): void {\r\n fs.writeFileSync(configPath, content, 'utf-8');\r\n}\r\n\r\n// ─── Flat Config Generator (ESLint v9) ────────────────────────────────────────\r\n//\r\n// Generates a clean eslint.config.mjs that:\r\n// 1. Uses direct spread of the preset config object (no object wrapping)\r\n// 2. Explicitly names plugin so IDEs resolve it\r\n// 3. Puts ignores first so they apply to all following configs\r\n\r\nexport function generateFlatConfig(preset: Preset): string {\r\n return `import aiGuard from 'eslint-plugin-ai-guard';\r\n\r\nexport default [\r\n // Ignore generated / dependency directories\r\n {\r\n ignores: [\r\n 'node_modules/**',\r\n '.next/**',\r\n 'dist/**',\r\n 'build/**',\r\n 'coverage/**',\r\n 'out/**',\r\n ],\r\n },\r\n\r\n // ai-guard: catch AI-generated code patterns\r\n {\r\n plugins: {\r\n 'ai-guard': aiGuard,\r\n },\r\n rules: {\r\n ...aiGuard.configs.${preset}.rules,\r\n },\r\n },\r\n];\r\n`;\r\n}\r\n\r\n// ─── Legacy Config Generator (ESLint v8) ──────────────────────────────────────\r\n\r\nexport function generateLegacyConfig(preset: Preset): string {\r\n return `module.exports = {\r\n plugins: ['ai-guard'],\r\n extends: ['plugin:ai-guard/${preset}'],\r\n ignorePatterns: [\r\n 'node_modules/',\r\n '.next/',\r\n 'dist/',\r\n 'build/',\r\n 'coverage/',\r\n 'out/',\r\n ],\r\n};\r\n`;\r\n}\r\n\r\n// ─── Flat Config Patching (ESLint v9) ─────────────────────────────────────────\r\n\r\nconst AI_GUARD_MARKER = 'eslint-plugin-ai-guard';\r\n\r\nexport function isInvalidAiGuardConfig(content: string): boolean {\r\n if (!content.includes('eslint-plugin-ai-guard') && !content.includes('ai-guard')) {\r\n return false;\r\n }\r\n\r\n // Old invalid shape: plugin assigned to aiGuard.default\r\n if (/['\"]ai-guard['\"]\\s*:\\s*aiGuard\\.default/.test(content)) return true;\r\n\r\n // Old invalid shape: rules sourced directly from aiGuard.recommended/strict/security\r\n if (/\\.\\.\\.aiGuard\\.(recommended|strict|security)\\.rules/.test(content)) return true;\r\n if (/rules\\s*:\\s*aiGuard\\.(recommended|strict|security)\\.rules/.test(content)) return true;\r\n\r\n return false;\r\n}\r\n\r\nexport function repairInvalidFlatConfig(content: string): string {\r\n let repaired = content;\r\n \r\n // 1. Fix plugin assignment: 'ai-guard': aiGuard.default -> 'ai-guard': aiGuard\r\n repaired = repaired.replace(/(['\"]ai-guard['\"]\\s*:\\s*)aiGuard\\.default/g, '$1aiGuard');\r\n \r\n // 2. Fix raw assignment: rules: aiGuard.PRESET.rules -> rules: { ...aiGuard.configs.PRESET.rules }\r\n repaired = repaired.replace(\r\n /rules\\s*:\\s*aiGuard\\.([a-zA-Z0-9_]+)\\.rules(,?)/g,\r\n 'rules: {\\n ...aiGuard.configs.$1.rules,\\n }$2',\r\n );\r\n \r\n // 3. Fix spread assignment: ...aiGuard.PRESET.rules -> ...aiGuard.configs.PRESET.rules\r\n repaired = repaired.replace(/\\.\\.\\.aiGuard\\.([a-zA-Z0-9_]+)\\.rules/g, '...aiGuard.configs.$1.rules');\r\n \r\n return repaired;\r\n}\r\n\r\nexport function patchFlatConfig(existing: string, preset: Preset): string {\r\n if (isInvalidAiGuardConfig(existing)) {\r\n return repairInvalidFlatConfig(existing);\r\n }\r\n\r\n // If already configured and valid — leave untouched\r\n if (existing.includes(AI_GUARD_MARKER)) {\r\n return existing;\r\n }\r\n\r\n const importLine = `import aiGuard from 'eslint-plugin-ai-guard';\\n`;\r\n\r\n const rulesBlock = `\r\n // ai-guard injected by ai-guard CLI\r\n {\r\n plugins: {\r\n 'ai-guard': aiGuard,\r\n },\r\n rules: {\r\n ...aiGuard.configs.${preset}.rules,\r\n },\r\n },\r\n`;\r\n\r\n // Prepend import after the last existing import, or at the very top\r\n let patched = existing;\r\n const lastImportIdx = findLastImportEnd(patched);\r\n if (lastImportIdx > -1) {\r\n patched =\r\n patched.slice(0, lastImportIdx) +\r\n importLine +\r\n patched.slice(lastImportIdx);\r\n } else {\r\n patched = importLine + patched;\r\n }\r\n\r\n // Insert rule block before the closing `];` of the export default array\r\n const lastBracket = patched.lastIndexOf('];');\r\n if (lastBracket !== -1) {\r\n patched =\r\n patched.slice(0, lastBracket) + rulesBlock + patched.slice(lastBracket);\r\n }\r\n\r\n return patched;\r\n}\r\n\r\n/** Find index just after the last `import … from '…';` line */\r\nfunction findLastImportEnd(src: string): number {\r\n const lines = src.split('\\n');\r\n let lastImportLine = -1;\r\n let charCount = 0;\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (/^\\s*import\\s+/.test(line)) lastImportLine = i;\r\n charCount += line.length + 1; // +1 for \\n\r\n }\r\n if (lastImportLine === -1) return -1;\r\n\r\n // Recalculate offset to end of that line\r\n let offset = 0;\r\n for (let i = 0; i <= lastImportLine; i++) {\r\n offset += lines[i].length + 1;\r\n }\r\n return offset;\r\n}\r\n\r\n// ─── Legacy Config Patching (ESLint v8) ───────────────────────────────────────\r\n\r\nexport function patchLegacyConfig(existing: string, preset: Preset): string {\r\n if (existing.includes('ai-guard')) {\r\n return existing; // already configured\r\n }\r\n\r\n let patched = existing;\r\n\r\n if (patched.includes('plugins:')) {\r\n patched = patched.replace(/plugins:\\s*\\[/, `plugins: ['ai-guard', `);\r\n } else {\r\n patched = patched.replace(\r\n 'module.exports = {',\r\n `module.exports = {\\n plugins: ['ai-guard'],`,\r\n );\r\n }\r\n\r\n if (patched.includes('extends:')) {\r\n patched = patched.replace(\r\n /extends:\\s*\\[/,\r\n `extends: ['plugin:ai-guard/${preset}', `,\r\n );\r\n } else {\r\n patched = patched.replace(\r\n 'module.exports = {',\r\n `module.exports = {\\n extends: ['plugin:ai-guard/${preset}'],`,\r\n );\r\n }\r\n\r\n return patched;\r\n}\r\n\r\nexport function switchFlatPreset(existing: string, preset: Preset): string {\r\n let patched = existing;\r\n\r\n patched = patched.replace(\r\n /\\.\\.\\.aiGuard\\.configs\\.(recommended|strict|security)\\.rules/g,\r\n `...aiGuard.configs.${preset}.rules`,\r\n );\r\n\r\n patched = patched.replace(\r\n /['\"]ai-guard\\/(recommended|strict|security)['\"]/g,\r\n `'ai-guard/${preset}'`,\r\n );\r\n\r\n return patched;\r\n}\r\n\r\nexport function switchLegacyPreset(existing: string, preset: Preset): string {\r\n let patched = existing;\r\n\r\n patched = patched.replace(\r\n /['\"]plugin:ai-guard\\/(recommended|strict|security)['\"]/g,\r\n `'plugin:ai-guard/${preset}'`,\r\n );\r\n\r\n patched = patched.replace(\r\n /['\"]ai-guard\\/(recommended|strict|security)['\"]/g,\r\n `'ai-guard/${preset}'`,\r\n );\r\n\r\n return patched;\r\n}\r\n\r\n// ─── Nuke-ignore removal ──────────────────────────────────────────────────────\r\n\r\n/**\r\n * Remove `ignorePatterns: [\"**\\/*\"]` from legacy configs.\r\n * Returns `{ content, changed }`.\r\n */\r\nexport function removeNukeIgnore(existing: string): {\r\n content: string;\r\n changed: boolean;\r\n} {\r\n const nukePatterns = [/\"?\\*\\*\\/\\*\"?/g];\r\n const hasNuke =\r\n existing.includes('\"**/*\"') || existing.includes(\"'**/*'\");\r\n\r\n if (!hasNuke) return { content: existing, changed: false };\r\n\r\n // Replace the entire ignorePatterns array value when it contains **/*\r\n let patched = existing\r\n .replace(\r\n /ignorePatterns:\\s*\\[.*?\\*\\*\\/\\*.*?\\]/gs,\r\n `ignorePatterns: ['node_modules/', '.next/', 'dist/', 'build/', 'coverage/']`,\r\n )\r\n .replace(\r\n /ignores:\\s*\\[.*?\\*\\*\\/\\*.*?\\]/gs,\r\n `ignores: ['node_modules/**', '.next/**', 'dist/**', 'build/**', 'coverage/**']`,\r\n );\r\n\r\n // Safety: if the regex above didn't match (complex multi-line), fall back to\r\n // a line-by-line strip of **/* entries\r\n for (const re of nukePatterns) {\r\n patched = patched.replace(re, '');\r\n }\r\n\r\n return { content: patched, changed: patched !== existing };\r\n}\r\n\r\n// ─── Ignore pattern helpers ───────────────────────────────────────────────────\r\n\r\nconst DEFAULT_FLAT_IGNORES = [\r\n 'node_modules/**',\r\n '.next/**',\r\n 'dist/**',\r\n 'build/**',\r\n 'coverage/**',\r\n 'out/**',\r\n];\r\n\r\nconst DEFAULT_LEGACY_IGNORES = [\r\n 'node_modules/',\r\n '.next/',\r\n 'dist/',\r\n 'build/',\r\n 'coverage/',\r\n 'out/',\r\n];\r\n\r\nexport function addIgnoresToFlatConfig(existing: string): string {\r\n if (existing.includes('ignores:')) return existing;\r\n\r\n const block = `\r\n // Default ignores added by ai-guard CLI\r\n {\r\n ignores: ${JSON.stringify(DEFAULT_FLAT_IGNORES)},\r\n },\r\n`;\r\n\r\n const lastBracket = existing.lastIndexOf('];');\r\n if (lastBracket !== -1) {\r\n return existing.slice(0, lastBracket) + block + existing.slice(lastBracket);\r\n }\r\n return existing;\r\n}\r\n\r\nexport function addIgnoresToLegacyConfig(existing: string): string {\r\n if (existing.includes('ignorePatterns')) return existing;\r\n return existing.replace(\r\n 'module.exports = {',\r\n `module.exports = {\\n ignorePatterns: ${JSON.stringify(DEFAULT_LEGACY_IGNORES)},`,\r\n );\r\n}\r\n\r\n// ─── Config file path resolution ──────────────────────────────────────────────\r\n\r\nexport function getConfigFilePath(\r\n configType: ConfigType,\r\n cwd = process.cwd(),\r\n): string {\r\n switch (configType) {\r\n case 'flat-js':\r\n return path.join(cwd, 'eslint.config.js');\r\n case 'flat-mjs':\r\n return path.join(cwd, 'eslint.config.mjs');\r\n case 'flat-cjs':\r\n return path.join(cwd, 'eslint.config.cjs');\r\n case 'eslintrc-js':\r\n return path.join(cwd, '.eslintrc.js');\r\n case 'eslintrc-cjs':\r\n return path.join(cwd, '.eslintrc.cjs');\r\n case 'eslintrc-json':\r\n return path.join(cwd, '.eslintrc.json');\r\n default:\r\n return path.join(cwd, '.eslintrc.js');\r\n }\r\n}\r\n\r\n// ─── Post-init config validation ──────────────────────────────────────────────\r\n\r\n/**\r\n * Lightweight structural validation of a generated/patched flat config.\r\n * Does NOT require ESLint to be loadable — just checks the text.\r\n * Returns an array of problem strings; empty = looks valid.\r\n */\r\nexport function validateFlatConfigText(content: string): string[] {\r\n const problems: string[] = [];\r\n\r\n if (!content.includes('export default')) {\r\n problems.push('Missing `export default` — file must be an ES module');\r\n }\r\n if (!content.includes('eslint-plugin-ai-guard') && !content.includes('aiGuard')) {\r\n problems.push('Plugin import not found — ai-guard plugin may not be referenced');\r\n }\r\n if (!content.trim().endsWith('];') && !content.trim().endsWith('];')) {\r\n // minor — not fatal\r\n }\r\n\r\n // Detect nuke ignore that would prevent any files from being linted\r\n if (content.includes('\"**/*\"') || content.includes(\"'**/*'\")) {\r\n problems.push(\r\n 'Config contains \"**/*\" ignore pattern — this will prevent all files from being linted',\r\n );\r\n }\r\n\r\n return problems;\r\n}\r\n\r\nexport function validateLegacyConfigText(content: string): string[] {\r\n const problems: string[] = [];\r\n\r\n if (!content.includes('module.exports')) {\r\n problems.push('Missing `module.exports` — legacy config must use CJS exports');\r\n }\r\n if (!content.includes('ai-guard')) {\r\n problems.push('Plugin not referenced — add ai-guard to plugins and extends');\r\n }\r\n if (content.includes('\"**/*\"') || content.includes(\"'**/*'\")) {\r\n problems.push(\r\n 'Config contains \"**/*\" ignore pattern — this will prevent all files from being linted',\r\n );\r\n }\r\n\r\n return problems;\r\n}\r\n","import { Command } from 'commander';\nimport fs from 'fs';\nimport path from 'path';\nimport { registerRunCommand } from './commands/run.js';\nimport { registerInitCommand } from './commands/init.js';\nimport { registerDoctorCommand } from './commands/doctor.js';\nimport { registerPresetCommand } from './commands/preset.js';\nimport { registerIgnoreCommand } from './commands/ignore.js';\nimport { registerBaselineCommand } from './commands/baseline.js';\nimport { registerInitContextCommand } from './commands/init-context.js';\nimport { registerReportCommand } from './commands/report.js';\nimport { log } from './utils/logger.js';\n\n// ─── Version resolution ───────────────────────────────────────────────────────\n\nfunction getVersion(): string {\n try {\n // In the bundled CLI output, __dirname is available (CJS bundle).\n const pkgPath = path.resolve(__dirname, '../../package.json');\n const raw = fs.readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(raw) as { version?: string };\n return typeof pkg.version === 'string' ? pkg.version : '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\n// ─── Program ──────────────────────────────────────────────────────────────────\n\nconst program = new Command();\n\nprogram\n .name('ai-guard')\n .description(\n 'Production-grade CLI for eslint-plugin-ai-guard\\n' +\n 'Catch AI-generated code issues instantly — no ESLint config required.\\n\\n' +\n 'Quick start:\\n' +\n ' npx ai-guard run Scan current project\\n' +\n ' npx ai-guard init Auto-configure ESLint\\n' +\n ' npx ai-guard init-context Generate AI agent rules\\n' +\n ' npx ai-guard report Generate shareable HTML report\\n' +\n ' npx ai-guard doctor Check your setup\\n' +\n ' npx ai-guard baseline Save baseline, track new issues only',\n )\n .version(getVersion(), '-v, --version', 'Print version number')\n .helpOption('-h, --help', 'Show help');\n\n// ─── Register commands ────────────────────────────────────────────────────────\n\nregisterRunCommand(program);\nregisterInitCommand(program);\nregisterDoctorCommand(program);\nregisterPresetCommand(program);\nregisterIgnoreCommand(program);\nregisterBaselineCommand(program);\nregisterInitContextCommand(program);\nregisterReportCommand(program);\n\n// ─── Global error handling ────────────────────────────────────────────────────\n\nprogram.configureOutput({\n writeErr(str) {\n // Strip commander's default \"error: \" prefix for cleaner output\n const cleaned = str.replace(/^error:\\s*/i, '').trim();\n log.error(cleaned);\n },\n});\n\nprocess.on('unhandledRejection', (reason: unknown) => {\n const msg =\n reason instanceof Error ? reason.message : String(reason);\n log.error(`Unexpected error: ${msg}`);\n log.info('If this looks like a bug, please report it at:');\n log.info(' https://github.com/YashJadhav21/eslint-plugin-ai-guard/issues');\n process.exit(1);\n});\n\nprocess.on('SIGINT', () => {\n log.blank();\n log.info('Cancelled.');\n process.exit(0);\n});\n\n// ─── Parse args ───────────────────────────────────────────────────────────────\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n log.error(msg);\n process.exit(1);\n});\n","import type { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { runEslint, type Preset, type EcosystemIssue } from '../utils/eslint-runner.js';\nimport { log, RULE_CATEGORY, CATEGORY_ICONS, CATEGORY_ORDER, CONFIDENCE_TIER } from '../utils/logger.js';\nimport type { RunResult } from '../utils/eslint-runner.js';\n\nexport function registerRunCommand(program: Command): void {\n program\n .command('run')\n .description('Run ai-guard rules on your project (zero ESLint config required)')\n .option('--path <dir>', 'Directory or file to scan', '.')\n .option('--strict', 'Use the strict rule preset (all rules at error)')\n .option('--security', 'Use the security-only rule preset')\n .option('--json', 'Output results as JSON (CI-friendly)')\n .option(\n '--max-warnings <n>',\n 'Fail with exit code 1 if warnings exceed this count',\n (value: string) => Number.parseInt(value, 10),\n )\n .option('--verbose', 'Show all issues — disable grouping of repeated warnings')\n .option('--debug-timing', 'Print per-phase timing diagnostics')\n .action(async (opts: {\n path: string;\n strict?: boolean;\n security?: boolean;\n json?: boolean;\n maxWarnings?: number;\n verbose?: boolean;\n debugTiming?: boolean;\n }) => {\n if (\n opts.maxWarnings !== undefined &&\n (!Number.isInteger(opts.maxWarnings) || opts.maxWarnings < 0)\n ) {\n log.blank();\n log.error('--max-warnings must be a non-negative integer.');\n log.blank();\n process.exit(1);\n return;\n }\n\n const preset: Preset = opts.strict\n ? 'strict'\n : opts.security\n ? 'security'\n : 'recommended';\n\n if (opts.strict && opts.security && !opts.json) {\n log.warn('Both --strict and --security were provided. Using --strict.');\n log.blank();\n }\n\n if (!opts.json) {\n log.banner('AI GUARD');\n log.blank();\n }\n\n const spinner = opts.json\n ? null\n : ora({ text: 'Scanning…', color: 'cyan' }).start();\n\n let result: RunResult;\n try {\n result = await runEslint({\n preset,\n targetPath: opts.path,\n debugTiming: opts.debugTiming,\n });\n spinner?.stop();\n } catch (err: unknown) {\n spinner?.stop();\n const msg = err instanceof Error ? err.message : String(err);\n\n if (msg.toLowerCase().includes('typescript') && msg.toLowerCase().includes('parser')) {\n log.blank();\n log.error('TypeScript detected but parser not found.');\n log.blank();\n log.print(` ${chalk.bold('Install the TypeScript parser:')}`);\n log.blank();\n log.print(` ${chalk.cyan('npm install --save-dev @typescript-eslint/parser')}`);\n log.blank();\n } else {\n log.blank();\n log.error(msg);\n log.blank();\n log.print(` ${chalk.bold('Fix:')} Run ${chalk.cyan('ai-guard doctor')} to diagnose your setup.`);\n log.blank();\n }\n process.exit(1);\n return;\n }\n\n // ─── JSON mode ─────────────────────────────────────────────────────────\n\n if (opts.json) {\n const jsonOutput = {\n preset,\n scannedPath: opts.path,\n filesScanned: result.filesScanned,\n totalErrors: result.totalErrors,\n totalWarnings: result.totalWarnings,\n totalIssues: result.totalIssues,\n durationMs: result.durationMs,\n timing: result.timing,\n ruleBreakdown: Object.fromEntries(result.ruleBreakdown),\n topFiles: result.topFiles,\n files: result.files,\n ecosystemIssues: result.ecosystemIssues,\n parserErrors: result.parserErrors,\n tsParserAvailable: result.tsParserAvailable,\n };\n console.log(JSON.stringify(jsonOutput, null, 2));\n process.exit(getRunExitCode(result, opts.maxWarnings));\n return;\n }\n\n // ─── Human output ────────────────────────────────────────────────────────\n\n // Scan stats header — note if TS parser missing\n log.scanStats(result.filesScanned, result.files.length, result.durationMs, preset);\n if (!result.tsParserAvailable) {\n log.print(\n chalk.dim(` ℹ TypeScript parser not found — .ts/.tsx files use espree fallback`) +\n chalk.dim(` (install @typescript-eslint/parser for full TS support)`),\n );\n }\n log.blank();\n\n // ── Success state ─────────────────────────────────────────────────────────\n\n if (result.totalIssues === 0 && result.ecosystemIssues.length === 0 && result.parserErrors.length === 0) {\n log.print(\n ` ${chalk.green('✔')} ${chalk.bold.green('No AI issues found')} ${chalk.gray(`— ${result.filesScanned} file${result.filesScanned !== 1 ? 's' : ''} scanned, all clean`)}`,\n );\n log.blank();\n process.exit(0);\n return;\n }\n\n if (result.totalIssues === 0) {\n log.print(\n ` ${chalk.green('✔')} ${chalk.bold.green('No AI issues found')} ${chalk.gray(`— ${result.filesScanned} file${result.filesScanned !== 1 ? 's' : ''} scanned, all clean`)}`,\n );\n log.blank();\n }\n\n // ── AI Guard Findings ─────────────────────────────────────────────────────\n\n if (result.totalIssues > 0) {\n\n // Category summary with icons\n log.section('Summary by Category');\n\n const categoryErrors: Record<string, number> = {};\n const categoryWarnings: Record<string, number> = {};\n\n for (const file of result.files) {\n for (const issue of file.issues) {\n const cat = RULE_CATEGORY[issue.ruleId] ?? 'Other';\n if (issue.severity === 2) {\n categoryErrors[cat] = (categoryErrors[cat] ?? 0) + 1;\n } else {\n categoryWarnings[cat] = (categoryWarnings[cat] ?? 0) + 1;\n }\n }\n }\n\n const allCategories = new Set([\n ...CATEGORY_ORDER,\n ...Object.keys(categoryErrors),\n ...Object.keys(categoryWarnings),\n ]);\n\n const sortedCategories = [...allCategories].filter(\n (cat) => (categoryErrors[cat] ?? 0) + (categoryWarnings[cat] ?? 0) > 0,\n );\n\n sortedCategories.sort((a, b) => {\n const ai = CATEGORY_ORDER.indexOf(a);\n const bi = CATEGORY_ORDER.indexOf(b);\n if (ai !== -1 && bi !== -1) return ai - bi;\n if (ai !== -1) return -1;\n if (bi !== -1) return 1;\n return a.localeCompare(b);\n });\n\n for (const cat of sortedCategories) {\n const icon = CATEGORY_ICONS[cat] ?? '⚪';\n log.category(icon, cat, categoryErrors[cat] ?? 0, categoryWarnings[cat] ?? 0);\n }\n\n log.blank();\n\n log.print(\n ` ${chalk.bold('Total:')} ${formatIssueCount(result.totalErrors, result.totalWarnings)}`,\n );\n log.blank();\n\n // By Rule — with confidence indicators\n if (result.ruleBreakdown.size > 0) {\n log.section('By Rule');\n\n const sorted = [...result.ruleBreakdown.entries()].sort(\n (a, b) => b[1] - a[1],\n );\n for (const [rule, count] of sorted) {\n const shortRule = rule.replace(/^ai-guard\\//, '');\n const tier = CONFIDENCE_TIER[rule];\n const tierLabel = tier === 'high'\n ? chalk.red.dim('[high]')\n : tier === 'medium'\n ? chalk.yellow.dim('[medium]')\n : chalk.gray.dim('[low]');\n log.print(\n ` ${chalk.gray('•')} ${chalk.yellow(shortRule)} ${tierLabel}${chalk.gray(':')} ${chalk.white(String(count))}`,\n );\n }\n log.blank();\n }\n\n // Top Files\n if (result.topFiles.length > 0) {\n log.section('Top Files');\n for (const { path: fp, count } of result.topFiles) {\n log.print(\n ` ${chalk.gray('•')} ${chalk.white(fp)} ${chalk.gray(`(${count})`)}`,\n );\n }\n log.blank();\n }\n\n // Issues by File — with grouping of repeated low-confidence warnings\n log.section('Issues by File');\n log.blank();\n\n const verbose = opts.verbose ?? false;\n renderIssuesByFile(result, verbose);\n }\n\n // ── ESLint Ecosystem Issues ───────────────────────────────────────────────\n // Shown SEPARATELY — these are NOT ai-guard findings\n\n if (result.ecosystemIssues.length > 0) {\n log.ecosystemSection('ESLint Config Issues');\n log.print(\n chalk.dim(` These issues come from your project's ESLint config, not from ai-guard.`),\n );\n log.blank();\n\n // Group by ruleId + message to de-duplicate\n const seen = new Map<string, { issue: EcosystemIssue; count: number }>();\n for (const issue of result.ecosystemIssues) {\n const key = `${issue.ruleId ?? 'null'}::${issue.message}`;\n const existing = seen.get(key);\n if (existing) {\n existing.count++;\n } else {\n seen.set(key, { issue, count: 1 });\n }\n }\n\n for (const { issue, count } of seen.values()) {\n log.ecosystemIssue(issue, count);\n }\n\n log.blank();\n }\n\n // ── Parser Errors ─────────────────────────────────────────────────────────\n\n if (result.parserErrors.length > 0) {\n log.ecosystemSection('Parser Errors');\n log.print(\n chalk.dim(` These files could not be parsed — not ai-guard findings.`),\n );\n log.blank();\n\n for (const pe of result.parserErrors) {\n log.parserError(pe);\n }\n\n if (!result.tsParserAvailable) {\n log.blank();\n log.print(\n ` ${chalk.cyan('→ Fix:')} ${chalk.yellow('npm install --save-dev @typescript-eslint/parser')}`,\n );\n log.print(\n chalk.dim(` TypeScript parser resolves most .ts/.tsx parse failures.`),\n );\n }\n log.blank();\n }\n\n log.divider();\n log.blank();\n\n // ── Next steps ────────────────────────────────────────────────────────────\n\n log.section('Next Steps');\n if (result.totalIssues > 0) {\n log.info(`Run ${chalk.cyan('ai-guard baseline')} to save these issues and track only new ones`);\n log.info(`Run ${chalk.cyan('ai-guard report')} to generate a shareable HTML report`);\n log.info(`Run ${chalk.cyan('ai-guard ignore')} to suppress dist/build noise`);\n }\n if (result.ecosystemIssues.length > 0) {\n log.info(`Run ${chalk.cyan('ai-guard doctor')} to diagnose ESLint config issues`);\n }\n if (!opts.verbose && hasGroupedWarnings(result)) {\n log.info(`Run with ${chalk.cyan('--verbose')} to expand grouped warnings`);\n }\n log.blank();\n\n process.exit(getRunExitCode(result, opts.maxWarnings));\n });\n}\n\n// ─── Issue rendering ──────────────────────────────────────────────────────────\n\nconst GROUP_THRESHOLD = 4; // Group if same rule appears >= this many times in a file\n\nfunction hasGroupedWarnings(result: RunResult): boolean {\n for (const file of result.files) {\n const ruleCounts = new Map<string, number>();\n for (const issue of file.issues) {\n ruleCounts.set(issue.ruleId, (ruleCounts.get(issue.ruleId) ?? 0) + 1);\n }\n for (const count of ruleCounts.values()) {\n if (count >= GROUP_THRESHOLD) return true;\n }\n }\n return false;\n}\n\nfunction renderIssuesByFile(result: RunResult, verbose: boolean): void {\n for (const file of result.files) {\n log.print(\n ` ${chalk.bold.white(file.filePath)} ` +\n chalk.gray(\n `(${file.errorCount} error${file.errorCount !== 1 ? 's' : ''}, ` +\n `${file.warningCount} warning${file.warningCount !== 1 ? 's' : ''})`,\n ),\n );\n\n if (!verbose) {\n // Group repeated low-confidence warnings\n const ruleCounts = new Map<string, Array<typeof file.issues[0]>>();\n for (const issue of file.issues) {\n const arr = ruleCounts.get(issue.ruleId) ?? [];\n arr.push(issue);\n ruleCounts.set(issue.ruleId, arr);\n }\n\n for (const issues of ruleCounts.values()) {\n const tier = CONFIDENCE_TIER[issues[0].ruleId] ?? 'low';\n // Group low-confidence warnings if they repeat heavily\n if (tier === 'low' && issues.length >= GROUP_THRESHOLD) {\n const sev = issues[0].severity === 2 ? chalk.red('error') : chalk.yellow(' warn');\n const shortRule = chalk.gray(issues[0].ruleId.replace(/^ai-guard\\//, ''));\n log.print(\n ` ${sev} ${chalk.white(issues[0].message)} ${shortRule}`,\n );\n log.print(\n chalk.dim(` ↳ ${issues.length} occurrences — run with --verbose to expand`),\n );\n } else {\n for (const issue of issues) {\n renderSingleIssue(issue);\n }\n }\n }\n } else {\n for (const issue of file.issues) {\n renderSingleIssue(issue);\n }\n }\n\n log.blank();\n }\n}\n\nfunction renderSingleIssue(issue: { ruleId: string; severity: 1 | 2; message: string; line: number; column: number }): void {\n const sev = issue.severity === 2\n ? chalk.red('error')\n : chalk.yellow(' warn');\n const loc = chalk.gray(`${String(issue.line)}:${String(issue.column)}`).padEnd(12);\n const ruleShort = chalk.gray(issue.ruleId.replace(/^ai-guard\\//, ''));\n const tier = CONFIDENCE_TIER[issue.ruleId];\n const tierTag = tier === 'high'\n ? ''\n : tier === 'medium'\n ? ''\n : chalk.dim(' [low]');\n log.print(\n ` ${loc} ${sev} ${chalk.white(issue.message)}${tierTag} ${ruleShort}`,\n );\n}\n\n// ─── Exit code ────────────────────────────────────────────────────────────────\n\nexport function getRunExitCode(result: RunResult, maxWarnings?: number): number {\n if (result.totalErrors > 0) return 1;\n if (maxWarnings !== undefined && result.totalWarnings > maxWarnings) return 1;\n return 0;\n}\n\nfunction formatIssueCount(errors: number, warnings: number): string {\n const parts: string[] = [];\n if (errors > 0) parts.push(chalk.red.bold(`${errors} error${errors !== 1 ? 's' : ''}`));\n if (warnings > 0) parts.push(chalk.yellow.bold(`${warnings} warning${warnings !== 1 ? 's' : ''}`));\n return parts.join(chalk.gray(' · '));\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { pathToFileURL } from 'url';\nimport { log } from './logger.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ntype RuleLevel = 'error' | 'warn' | 'off';\n\nexport type Preset = 'recommended' | 'strict' | 'security';\n\nexport interface RunOptions {\n preset: Preset;\n targetPath: string;\n maxWarnings?: number;\n jsonOutput?: boolean;\n debugTiming?: boolean;\n}\n\nexport interface IssueDetail {\n ruleId: string;\n severity: 1 | 2;\n message: string;\n line: number;\n column: number;\n}\n\nexport interface FileResult {\n filePath: string;\n issues: IssueDetail[]; // ai-guard/* findings only\n errorCount: number;\n warningCount: number;\n}\n\n/**\n * An issue from a non-ai-guard rule (e.g., react-hooks/exhaustive-deps not found,\n * foreign plugin rules, missing rule definitions). These are ESLint ecosystem issues\n * and must NEVER appear in ai-guard findings or affect the score/confidence.\n */\nexport interface EcosystemIssue {\n type: 'missing-rule' | 'foreign-rule' | 'config-error';\n ruleId: string | null;\n message: string;\n filePath: string;\n line: number;\n column: number;\n}\n\n/**\n * A fatal parse error — ESLint could not parse the file at all.\n * Not an ai-guard finding. Shown in a separate section.\n */\nexport interface ParserError {\n filePath: string;\n message: string;\n line: number;\n}\n\nexport interface TimingBreakdown {\n pluginLoadMs: number;\n parserLoadMs: number;\n lintMs: number;\n processMs: number;\n}\n\nexport interface RunResult {\n files: FileResult[];\n totalErrors: number;\n totalWarnings: number;\n totalIssues: number;\n filesScanned: number;\n ruleBreakdown: Map<string, number>;\n topFiles: Array<{ path: string; count: number }>;\n durationMs: number;\n timing?: TimingBreakdown;\n /** ESLint ecosystem issues — NOT ai-guard findings */\n ecosystemIssues: EcosystemIssue[];\n /** Fatal parser errors — NOT ai-guard findings */\n parserErrors: ParserError[];\n /** True if @typescript-eslint/parser was found and loaded */\n tsParserAvailable: boolean;\n}\n\n// ─── Plugin normalizer ────────────────────────────────────────────────────────\n\ntype AiGuardPlugin = {\n rules: Record<string, unknown>;\n configs?: Record<string, unknown>;\n meta?: Record<string, unknown>;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction normalizePlugin(raw: unknown): AiGuardPlugin {\n if (isRecord(raw) && isRecord(raw.default) && isRecord(raw.default.rules)) {\n return raw.default as AiGuardPlugin;\n }\n if (isRecord(raw) && isRecord(raw.rules)) {\n return raw as AiGuardPlugin;\n }\n throw new Error(\n 'Could not load eslint-plugin-ai-guard. Run: npm install eslint-plugin-ai-guard',\n );\n}\n\n// ─── Preset rule maps ─────────────────────────────────────────────────────────\n\nconst RECOMMENDED_RULES: Record<string, RuleLevel> = {\n // Reliability\n 'ai-guard/no-empty-catch': 'error',\n 'ai-guard/no-broad-exception': 'warn',\n // Async\n 'ai-guard/no-floating-promise': 'error',\n 'ai-guard/no-await-in-loop': 'warn',\n 'ai-guard/no-async-without-await': 'warn',\n 'ai-guard/no-async-array-callback': 'warn',\n // Security\n 'ai-guard/no-hardcoded-secret': 'error',\n 'ai-guard/no-eval-dynamic': 'error',\n 'ai-guard/no-sql-string-concat': 'warn',\n 'ai-guard/no-unsafe-deserialize': 'warn',\n 'ai-guard/require-auth-middleware': 'warn',\n 'ai-guard/require-authz-check': 'warn',\n // AI Patterns\n 'ai-guard/no-dead-branch': 'warn',\n};\n\nconst STRICT_RULES: Record<string, RuleLevel> = {\n // Reliability\n 'ai-guard/no-empty-catch': 'error',\n 'ai-guard/no-broad-exception': 'error',\n 'ai-guard/no-catch-log-rethrow': 'error',\n 'ai-guard/no-catch-without-use': 'error',\n // Async\n 'ai-guard/no-async-array-callback': 'error',\n 'ai-guard/no-floating-promise': 'error',\n 'ai-guard/no-await-in-loop': 'error',\n 'ai-guard/no-async-without-await': 'error',\n 'ai-guard/no-redundant-await': 'error',\n // Security\n 'ai-guard/no-hardcoded-secret': 'error',\n 'ai-guard/no-eval-dynamic': 'error',\n 'ai-guard/no-sql-string-concat': 'error',\n 'ai-guard/no-unsafe-deserialize': 'error',\n 'ai-guard/require-auth-middleware': 'error',\n 'ai-guard/require-authz-check': 'error',\n // AI Patterns\n 'ai-guard/no-console-in-handler': 'error',\n 'ai-guard/no-duplicate-logic-block': 'error',\n 'ai-guard/no-dead-branch': 'error',\n};\n\nconst SECURITY_RULES: Record<string, RuleLevel> = {\n 'ai-guard/no-hardcoded-secret': 'error',\n 'ai-guard/no-eval-dynamic': 'error',\n 'ai-guard/no-sql-string-concat': 'error',\n 'ai-guard/no-unsafe-deserialize': 'warn',\n 'ai-guard/require-auth-middleware': 'warn',\n 'ai-guard/require-authz-check': 'warn',\n};\n\nfunction getRules(preset: Preset): Record<string, RuleLevel> {\n if (preset === 'strict') return STRICT_RULES;\n if (preset === 'security') return SECURITY_RULES;\n return RECOMMENDED_RULES;\n}\n\n// ─── Default ignores ──────────────────────────────────────────────────────────\n\nconst DEFAULT_IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/.next/**',\n '**/dist/**',\n '**/build/**',\n '**/coverage/**',\n '**/out/**',\n '**/.git/**',\n];\n\nexport function isSkippablePatternError(error: Error): boolean {\n const msg = error.message.toLowerCase();\n return (\n msg.includes('no files') ||\n msg.includes('no files matching') ||\n msg.includes('ignored') ||\n msg.includes('all files matched by') ||\n msg.includes('are ignored') ||\n msg.includes('was ignored') ||\n msg.includes('file ignored')\n );\n}\n\n// ─── Message classifier ───────────────────────────────────────────────────────\n\ntype MessageSource = 'ai-guard' | 'parser-error' | 'ecosystem';\n\nfunction classifyMessage(msg: { ruleId: string | null; fatal?: boolean; message: string }): MessageSource {\n // Fatal parse errors (ESLint couldn't parse the file at all)\n if (msg.fatal === true) return 'parser-error';\n\n // Explicit parse errors in the message body\n if (msg.ruleId === null && (\n msg.message.startsWith('Parsing error') ||\n msg.message.includes('Unexpected token') ||\n msg.message.includes('SyntaxError')\n )) {\n return 'parser-error';\n }\n\n // Our rules — the only ones that count as ai-guard findings\n if (msg.ruleId && msg.ruleId.startsWith('ai-guard/')) {\n return 'ai-guard';\n }\n\n // Everything else: missing rule definitions, foreign plugin rules, config issues\n return 'ecosystem';\n}\n\nfunction classifyEcosystemType(\n msg: { ruleId: string | null; message: string },\n): EcosystemIssue['type'] {\n const lower = msg.message.toLowerCase();\n if (lower.includes('definition for rule') && lower.includes('was not found')) {\n return 'missing-rule';\n }\n if (lower.includes('configuration') || lower.includes('config')) {\n return 'config-error';\n }\n return 'foreign-rule';\n}\n\n// ─── Plugin loader ────────────────────────────────────────────────────────────\n\nasync function loadPluginModuleFromCwd(cwd: string): Promise<unknown> {\n const { createRequire } = await import('module');\n const requireFromCwd = createRequire(path.join(cwd, 'package.json'));\n\n try {\n const resolved = requireFromCwd.resolve('eslint-plugin-ai-guard');\n return import(pathToFileURL(resolved).href);\n } catch {\n // Fall through to local dist fallback.\n }\n\n const localDistEntry = path.join(cwd, 'dist', 'index.js');\n if (fs.existsSync(localDistEntry)) {\n return import(pathToFileURL(localDistEntry).href);\n }\n\n const localSrcEntry = path.join(cwd, 'src', 'index.ts');\n if (fs.existsSync(localSrcEntry)) {\n try {\n return import(pathToFileURL(localSrcEntry).href);\n } catch (err: unknown) {\n const reason = err instanceof Error ? err.message : String(err);\n log.debug(`Local src plugin import failed: ${reason}`);\n }\n }\n\n throw new Error(\n 'eslint-plugin-ai-guard is not installed. Run: npm install --save-dev eslint-plugin-ai-guard',\n );\n}\n\n// ─── Core runner ──────────────────────────────────────────────────────────────\n\nexport async function runEslint(options: RunOptions): Promise<RunResult> {\n const overallStart = Date.now();\n const timing: TimingBreakdown = {\n pluginLoadMs: 0,\n parserLoadMs: 0,\n lintMs: 0,\n processMs: 0,\n };\n\n const { ESLint } = await import('eslint').catch(() => {\n throw new Error(\n 'ESLint is not installed. Run: npm install --save-dev eslint',\n );\n });\n\n // ── Load plugin ────────────────────────────────────────────────────────────\n const pluginStart = Date.now();\n const rawPlugin = await loadPluginModuleFromCwd(process.cwd());\n const plugin = normalizePlugin(rawPlugin);\n timing.pluginLoadMs = Date.now() - pluginStart;\n\n const rules = getRules(options.preset);\n const resolvedTargetPath = path.resolve(options.targetPath);\n\n if (!fs.existsSync(resolvedTargetPath)) {\n throw new Error(`Path not found: ${options.targetPath}`);\n }\n\n const targetStat = fs.statSync(resolvedTargetPath);\n const isSingleFileTarget = targetStat.isFile();\n const eslintCwd = isSingleFileTarget\n ? path.dirname(resolvedTargetPath)\n : resolvedTargetPath;\n\n // ── Load TypeScript parser ─────────────────────────────────────────────────\n const parserStart = Date.now();\n let tsParser: unknown = null;\n let tsParserAvailable = false;\n try {\n // Prefer parser from user's project, fall back to ours\n try {\n tsParser = require(path.join(\n process.cwd(),\n 'node_modules',\n '@typescript-eslint',\n 'parser',\n ));\n } catch {\n tsParser = require('@typescript-eslint/parser');\n }\n tsParserAvailable = true;\n } catch {\n // TypeScript parser not available — ts/tsx files will use default espree parser\n log.debug('@typescript-eslint/parser not found — TypeScript files will use espree fallback');\n }\n timing.parserLoadMs = Date.now() - parserStart;\n\n // ── Build ESLint config ────────────────────────────────────────────────────\n\n const JS_TS_FILES = [\n '**/*.js',\n '**/*.jsx',\n '**/*.ts',\n '**/*.tsx',\n '**/*.mts',\n '**/*.cts',\n '**/*.mjs',\n '**/*.cjs',\n ];\n\n const configBlocks: Array<Record<string, unknown>> = [\n // JS/JSX files — default espree parser with JSX support\n {\n files: ['**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'],\n plugins: { 'ai-guard': plugin } as Record<string, unknown>,\n languageOptions: {\n parserOptions: {\n ecmaVersion: 'latest',\n sourceType: 'module',\n ecmaFeatures: { jsx: true },\n },\n },\n rules: rules as Record<string, unknown>,\n },\n // Ignore generated directories\n { ignores: DEFAULT_IGNORE_PATTERNS },\n ];\n\n if (tsParser) {\n // TS + TSX with TypeScript parser — JSX enabled for both\n configBlocks.splice(1, 0, {\n files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],\n plugins: { 'ai-guard': plugin } as Record<string, unknown>,\n languageOptions: {\n parser: tsParser,\n parserOptions: {\n ecmaVersion: 'latest',\n sourceType: 'module',\n ecmaFeatures: { jsx: true },\n },\n },\n rules: rules as Record<string, unknown>,\n });\n } else {\n // No TS parser — lint ts/tsx files but they may partially fail to parse\n configBlocks.splice(1, 0, {\n files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],\n plugins: { 'ai-guard': plugin } as Record<string, unknown>,\n languageOptions: {\n parserOptions: {\n ecmaVersion: 'latest',\n sourceType: 'module',\n ecmaFeatures: { jsx: true },\n },\n },\n rules: rules as Record<string, unknown>,\n });\n }\n\n const eslint = new ESLint({\n cwd: eslintCwd,\n overrideConfigFile: true as unknown as string,\n overrideConfig: configBlocks,\n });\n\n // ── Lint files ─────────────────────────────────────────────────────────────\n // Task 7: Use single lintFiles call with all patterns for maximum performance.\n // This avoids per-pattern ESLint API round-trips which cause massive overhead.\n\n const patterns = isSingleFileTarget\n ? [path.basename(resolvedTargetPath)]\n : JS_TS_FILES;\n\n const lintStart = Date.now();\n let rawResults: Array<{\n filePath: string;\n messages: Array<{\n ruleId: string | null;\n severity: number;\n message: string;\n line: number;\n column: number;\n fatal?: boolean;\n }>;\n errorCount: number;\n warningCount: number;\n }>;\n\n try {\n // Single call — much faster than Promise.all of individual patterns\n rawResults = await eslint.lintFiles(patterns) as typeof rawResults;\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n\n if (isSkippablePatternError(error)) {\n // If single-call fails with \"no files\", fall back to per-pattern\n log.debug('Single-call lintFiles failed with no-files, falling back to per-pattern');\n const perPatternResults = await Promise.all(\n patterns.map(async (pattern) => {\n try {\n return await eslint.lintFiles([pattern]) as typeof rawResults;\n } catch (patternErr: unknown) {\n const patternError = patternErr instanceof Error ? patternErr : new Error(String(patternErr));\n if (isSkippablePatternError(patternError)) {\n log.debug(`Skipping pattern '${pattern}' (no lintable files)`);\n return [] as typeof rawResults;\n }\n throw patternError;\n }\n }),\n );\n rawResults = perPatternResults.flat();\n } else {\n throw error;\n }\n }\n timing.lintMs = Date.now() - lintStart;\n\n // ── Process results ────────────────────────────────────────────────────────\n const processStart = Date.now();\n\n const files: FileResult[] = [];\n const ecosystemIssues: EcosystemIssue[] = [];\n const parserErrors: ParserError[] = [];\n const ruleBreakdown = new Map<string, number>();\n let totalErrors = 0;\n let totalWarnings = 0;\n const filesScanned = rawResults.length;\n\n for (const result of rawResults) {\n if (result.messages.length === 0) continue;\n\n const relPath = path.relative(process.cwd(), result.filePath);\n const aiGuardIssues: IssueDetail[] = [];\n let fileErrors = 0;\n let fileWarnings = 0;\n\n for (const m of result.messages) {\n const source = classifyMessage(m);\n\n if (source === 'parser-error') {\n parserErrors.push({\n filePath: relPath,\n message: m.message,\n line: m.line ?? 0,\n });\n continue;\n }\n\n if (source === 'ecosystem') {\n ecosystemIssues.push({\n type: classifyEcosystemType(m),\n ruleId: m.ruleId,\n message: m.message,\n filePath: relPath,\n line: m.line ?? 0,\n column: m.column ?? 0,\n });\n continue;\n }\n\n // source === 'ai-guard'\n const issue: IssueDetail = {\n ruleId: m.ruleId ?? 'unknown',\n severity: m.severity as 1 | 2,\n message: m.message,\n line: m.line,\n column: m.column,\n };\n\n aiGuardIssues.push(issue);\n\n if (m.severity === 2) {\n fileErrors++;\n totalErrors++;\n } else {\n fileWarnings++;\n totalWarnings++;\n }\n\n ruleBreakdown.set(\n issue.ruleId,\n (ruleBreakdown.get(issue.ruleId) ?? 0) + 1,\n );\n }\n\n if (aiGuardIssues.length > 0) {\n files.push({\n filePath: relPath,\n issues: aiGuardIssues,\n errorCount: fileErrors,\n warningCount: fileWarnings,\n });\n }\n }\n\n const topFiles = [...files]\n .sort((a, b) => b.issues.length - a.issues.length)\n .slice(0, 10)\n .map((f) => ({ path: f.filePath, count: f.issues.length }));\n\n timing.processMs = Date.now() - processStart;\n\n if (options.debugTiming) {\n log.debug(`Plugin load: ${timing.pluginLoadMs}ms`);\n log.debug(`Parser load: ${timing.parserLoadMs}ms`);\n log.debug(`Lint: ${timing.lintMs}ms`);\n log.debug(`Process: ${timing.processMs}ms`);\n log.debug(`Total: ${Date.now() - overallStart}ms`);\n }\n\n return {\n files,\n totalErrors,\n totalWarnings,\n totalIssues: totalErrors + totalWarnings,\n filesScanned,\n ruleBreakdown,\n topFiles,\n durationMs: Date.now() - overallStart,\n timing,\n ecosystemIssues,\n parserErrors,\n tsParserAvailable,\n };\n}\n","import chalk from 'chalk';\nimport type { EcosystemIssue, ParserError } from '../utils/eslint-runner.js';\n\n// ── Category icon + color map ──────────────────────────────────────────────────\n\nconst CATEGORY_ICONS: Record<string, string> = {\n Security: '🔴',\n Reliability: '🟠',\n 'Async Stability': '🟡',\n 'AI Patterns': '🔵',\n};\n\nconst CATEGORY_ORDER = ['Security', 'Reliability', 'Async Stability', 'AI Patterns'];\n\nexport { CATEGORY_ICONS, CATEGORY_ORDER };\n\n// ── Rule → category map ────────────────────────────────────────────────────────\n\nexport const RULE_CATEGORY: Record<string, string> = {\n 'ai-guard/no-empty-catch': 'Reliability',\n 'ai-guard/no-broad-exception': 'Reliability',\n 'ai-guard/no-catch-log-rethrow': 'Reliability',\n 'ai-guard/no-catch-without-use': 'Reliability',\n 'ai-guard/no-floating-promise': 'Async Stability',\n 'ai-guard/no-await-in-loop': 'Async Stability',\n 'ai-guard/no-async-array-callback': 'Async Stability',\n 'ai-guard/no-async-without-await': 'Async Stability',\n 'ai-guard/no-redundant-await': 'Async Stability',\n 'ai-guard/no-hardcoded-secret': 'Security',\n 'ai-guard/no-eval-dynamic': 'Security',\n 'ai-guard/no-sql-string-concat': 'Security',\n 'ai-guard/no-unsafe-deserialize': 'Security',\n 'ai-guard/require-auth-middleware': 'Security',\n 'ai-guard/require-authz-check': 'Security',\n 'ai-guard/no-console-in-handler': 'AI Patterns',\n 'ai-guard/no-duplicate-logic-block': 'AI Patterns',\n 'ai-guard/no-dead-branch': 'AI Patterns',\n};\n\n// ── Confidence tiers ──────────────────────────────────────────────────────────\n// high = very low FP rate, high signal, should always be investigated\n// medium = moderate confidence, context-dependent\n// low = style/suggestion level, may have intentional exceptions\n\nexport const CONFIDENCE_TIER: Record<string, 'high' | 'medium' | 'low'> = {\n // High confidence — near-zero false positive rate\n 'ai-guard/no-hardcoded-secret': 'high',\n 'ai-guard/no-eval-dynamic': 'high',\n 'ai-guard/no-floating-promise': 'high',\n 'ai-guard/no-empty-catch': 'high',\n // Medium confidence — context matters, usually valid\n 'ai-guard/no-sql-string-concat': 'medium',\n 'ai-guard/no-await-in-loop': 'medium',\n 'ai-guard/require-auth-middleware': 'medium',\n 'ai-guard/require-authz-check': 'medium',\n 'ai-guard/no-catch-log-rethrow': 'medium',\n 'ai-guard/no-catch-without-use': 'medium',\n 'ai-guard/no-unsafe-deserialize': 'medium',\n // Low confidence — suggestions, may be intentional\n 'ai-guard/no-async-without-await': 'low',\n 'ai-guard/no-async-array-callback': 'low',\n 'ai-guard/no-dead-branch': 'low',\n 'ai-guard/no-broad-exception': 'low',\n 'ai-guard/no-console-in-handler': 'low',\n 'ai-guard/no-duplicate-logic-block': 'low',\n 'ai-guard/no-redundant-await': 'low',\n};\n\n// ── Ecosystem issue fix suggestions ──────────────────────────────────────────\n\nconst ECOSYSTEM_FIX_HINTS: Record<string, string> = {\n 'react-hooks/exhaustive-deps': 'npm install --save-dev eslint-plugin-react-hooks',\n 'react-hooks/rules-of-hooks': 'npm install --save-dev eslint-plugin-react-hooks',\n '@typescript-eslint/': 'npm install --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser',\n 'import/': 'npm install --save-dev eslint-plugin-import',\n 'jsx-a11y/': 'npm install --save-dev eslint-plugin-jsx-a11y',\n 'prettier/': 'npm install --save-dev eslint-plugin-prettier',\n};\n\nfunction getEcosystemFix(ruleId: string | null): string | null {\n if (!ruleId) return null;\n for (const [prefix, fix] of Object.entries(ECOSYSTEM_FIX_HINTS)) {\n if (ruleId.startsWith(prefix)) return fix;\n }\n return null;\n}\n\n// ── Logger ────────────────────────────────────────────────────────────────────\n\nconst PREFIX = {\n success: chalk.green('✔'),\n error: chalk.red('✖'),\n warn: chalk.yellow('⚠'),\n info: chalk.cyan('ℹ'),\n section: chalk.bold.white,\n bullet: chalk.gray('•'),\n ecosystem: chalk.yellow('⚠'),\n parser: chalk.magenta('⚡'),\n};\n\nexport const log = {\n info(msg: string): void {\n console.log(` ${PREFIX.info} ${chalk.white(msg)}`);\n },\n\n success(msg: string): void {\n console.log(` ${PREFIX.success} ${chalk.green(msg)}`);\n },\n\n warn(msg: string): void {\n console.log(` ${PREFIX.warn} ${chalk.yellow(msg)}`);\n },\n\n error(msg: string): void {\n console.error(` ${PREFIX.error} ${chalk.red(msg)}`);\n },\n\n section(title: string): void {\n console.log('');\n console.log(chalk.bold.cyan(` ── ${title} ──`));\n console.log('');\n },\n\n /**\n * Ecosystem section — distinct styling to communicate it's NOT ai-guard output\n */\n ecosystemSection(title: string): void {\n console.log('');\n console.log(chalk.bold.yellow(` ── ${title} ──`) + chalk.dim(' (not ai-guard findings)'));\n console.log('');\n },\n\n rule(ruleName: string, count: number): void {\n console.log(\n ` ${PREFIX.bullet} ${chalk.yellow(ruleName)} ${chalk.gray(`(${count} issue${count !== 1 ? 's' : ''})`)}`,\n );\n },\n\n file(filePath: string, count: number): void {\n console.log(\n ` ${PREFIX.bullet} ${chalk.white(filePath)} ${chalk.gray(`→ ${count} issue${count !== 1 ? 's' : ''}`)}`,\n );\n },\n\n issue(msg: string, severity: 1 | 2, line: number, col: number): void {\n const icon = severity === 2 ? chalk.red('error') : chalk.yellow(' warn');\n console.log(\n ` ${chalk.gray(`${line}:${col}`).padEnd(12)} ${icon} ${chalk.white(msg)}`,\n );\n },\n\n /**\n * Print an ESLint ecosystem issue (missing rule definition, foreign plugin rule, etc.)\n * with a clear disclaimer that this is NOT an ai-guard finding.\n */\n ecosystemIssue(issue: EcosystemIssue, count = 1): void {\n const ruleLabel = issue.ruleId ? chalk.yellow(issue.ruleId) : chalk.gray('(no rule id)');\n const typeLabel =\n issue.type === 'missing-rule'\n ? chalk.dim('[missing rule definition]')\n : issue.type === 'config-error'\n ? chalk.dim('[config error]')\n : chalk.dim('[foreign rule]');\n\n const countLabel = count > 1 ? chalk.gray(` × ${count}`) : '';\n\n console.log(` ${PREFIX.ecosystem} ${ruleLabel} ${typeLabel}${countLabel}`);\n console.log(` ${chalk.gray('File:')} ${chalk.dim(issue.filePath)}${issue.line > 0 ? chalk.dim(`:${issue.line}`) : ''}`);\n console.log(` ${chalk.gray('Msg:')} ${chalk.dim(issue.message.slice(0, 120))}`);\n\n const fix = getEcosystemFix(issue.ruleId);\n if (fix) {\n console.log(` ${chalk.cyan('→ Fix:')} ${chalk.yellow(fix)}`);\n }\n console.log(\n chalk.dim(` Note: This comes from your ESLint config, not from ai-guard.`),\n );\n console.log('');\n },\n\n /**\n * Print a parser/syntax error — clearly NOT an ai-guard finding.\n */\n parserError(pe: ParserError): void {\n console.log(` ${PREFIX.parser} ${chalk.magenta('Parse failure')} ${chalk.dim(pe.filePath)}${pe.line > 0 ? chalk.dim(`:${pe.line}`) : ''}`);\n console.log(` ${chalk.dim(pe.message.slice(0, 120))}`);\n console.log('');\n },\n\n /**\n * Print a category summary line with icon, label, and count.\n */\n category(icon: string, label: string, errors: number, warnings: number): void {\n const parts: string[] = [];\n if (errors > 0) parts.push(chalk.red(`${errors} error${errors !== 1 ? 's' : ''}`));\n if (warnings > 0) parts.push(chalk.yellow(`${warnings} warning${warnings !== 1 ? 's' : ''}`));\n const counts = parts.length > 0 ? parts.join(chalk.gray(' · ')) : chalk.gray('0');\n const labelPadded = label.padEnd(18);\n console.log(` ${icon} ${chalk.bold.white(labelPadded)} ${counts}`);\n },\n\n /**\n * Print the scan stats line.\n */\n scanStats(filesScanned: number, filesWithIssues: number, durationMs: number, preset: string): void {\n console.log(\n ` ${chalk.gray('Files scanned:')} ${chalk.white(String(filesScanned))} ` +\n `${chalk.gray('·')} ${chalk.gray('Issues in:')} ${chalk.white(String(filesWithIssues))} file${filesWithIssues !== 1 ? 's' : ''} ` +\n `${chalk.gray('·')} ${chalk.gray('Duration:')} ${chalk.white(durationMs + 'ms')} ` +\n `${chalk.gray('·')} ${chalk.gray('Preset:')} ${chalk.cyan(preset)}`,\n );\n },\n\n divider(): void {\n console.log(chalk.gray(' ' + '─'.repeat(60)));\n },\n\n blank(): void {\n console.log('');\n },\n\n banner(title: string): void {\n console.log('');\n console.log(chalk.bold.bgCyan.black(` ${title} `));\n console.log('');\n },\n\n print(msg: string): void {\n console.log(msg);\n },\n\n debug(msg: string): void {\n if (process.env.AI_GUARD_DEBUG === '1') {\n console.log(` ${chalk.gray('·')} ${chalk.gray(msg)}`);\n }\n },\n};\n","import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport path from 'path';\nimport fs from 'fs';\nimport { detect, isFlat, isLegacy, requiresFlatConfig } from '../utils/detector.js';\nimport {\n generateFlatConfig,\n generateLegacyConfig,\n patchFlatConfig,\n patchLegacyConfig,\n backupConfig,\n readConfig,\n writeConfig,\n getConfigFilePath,\n removeNukeIgnore,\n validateFlatConfigText,\n validateLegacyConfigText,\n type Preset,\n} from '../utils/config-manager.js';\nimport { log } from '../utils/logger.js';\n\n// ─── Flags ────────────────────────────────────────────────────────────────────\n\ninterface InitOptions {\n preset: string;\n flat?: boolean;\n dryRun?: boolean;\n}\n\n// ─── Error classification ────────────────────────────────────────────────────\n\ntype VerifyError =\n | { kind: 'syntax'; message: string }\n | { kind: 'module-not-found'; pkg: string; message: string }\n | { kind: 'unknown'; message: string };\n\nfunction classifyVerifyError(err: unknown): VerifyError {\n const msg = err instanceof Error ? err.message : String(err);\n const clean = msg.replace(/\\s+at\\s+.+/gm, '').trim();\n\n // Module resolution errors\n const modNotFound = clean.match(\n /Cannot find module '([^']+)'|Cannot find package '([^']+)'/,\n );\n if (modNotFound) {\n const pkg = modNotFound[1] ?? modNotFound[2] ?? 'unknown';\n return { kind: 'module-not-found', pkg, message: clean };\n }\n\n // SyntaxError / parse errors\n if (\n clean.includes('SyntaxError') ||\n clean.includes('Unexpected token') ||\n clean.includes('Invalid or unexpected token')\n ) {\n return { kind: 'syntax', message: clean };\n }\n\n return { kind: 'unknown', message: clean };\n}\n\n// ─── Programmatic ESLint verification ────────────────────────────────────────\n\n/**\n * After writing a config, try to load it via ESLint's own API.\n * Returns null on success, a classified error on failure.\n */\nasync function verifyConfigLoads(\n configPath: string,\n cwd: string,\n): Promise<null | VerifyError> {\n try {\n type EslintCtor = new (options: {\n cwd: string;\n overrideConfigFile: string;\n }) => {\n lintText: (code: string, options: { filePath: string }) => Promise<unknown>;\n };\n\n const { ESLint } = await import('eslint') as unknown as { ESLint: EslintCtor };\n\n const eslint = new ESLint({\n cwd,\n overrideConfigFile: configPath,\n });\n\n // Lint an empty JS file — forces ESLint to parse and validate the config\n await eslint.lintText('', {\n filePath: path.join(cwd, '_ai_guard_probe_.js'),\n });\n return null; // success\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n\n // \"No files\" / probe path exclusion errors are not config errors\n if (\n msg.includes('No files matching') ||\n msg.includes('_ai_guard_probe_')\n ) {\n return null;\n }\n\n return classifyVerifyError(err);\n }\n}\n\n// ─── Command registration ─────────────────────────────────────────────────────\n\nexport function registerInitCommand(program: Command): void {\n program\n .command('init')\n .description('Configure eslint-plugin-ai-guard in this project')\n .option('--preset <name>', 'Preset to use: recommended | strict | security', 'recommended')\n .option('--flat', 'Force flat config format (eslint.config.mjs) regardless of ESLint version')\n .option('--dry-run', 'Preview what would change without writing any files')\n .action(async (opts: InitOptions) => {\n const preset = (opts.preset as Preset) ?? 'recommended';\n const cwd = process.cwd();\n const isDryRun = opts.dryRun === true;\n\n log.banner('AI GUARD INIT');\n if (isDryRun) {\n log.print(` ${chalk.yellow('⚑ DRY RUN — no files will be written')}`);\n log.blank();\n }\n log.info('Detecting your project setup…');\n log.blank();\n\n const env = detect(cwd);\n\n // ─── Step 1: Environment report ──────────────────────────────────────────\n\n log.section('Environment');\n\n if (env.eslintVersion) {\n log.success(`ESLint ${env.eslintVersion} detected (v${env.eslintMajor})`);\n } else {\n log.warn('ESLint not found in node_modules');\n }\n\n if (env.pluginInstalled) {\n log.success('eslint-plugin-ai-guard is installed');\n } else {\n log.warn('eslint-plugin-ai-guard not found');\n }\n\n if (env.configType !== 'none') {\n log.success(`ESLint config found: ${chalk.white(path.relative(cwd, env.configPath ?? env.configType))}`);\n } else {\n log.info('No ESLint config found — will generate one');\n }\n\n // Warn about conflicting configs (only if not ESLint v9, as v9 auto-resolves)\n const eslintNeedsFlat = requiresFlatConfig(env.eslintMajor);\n if (env.hasConflictingConfigs && !eslintNeedsFlat) {\n log.blank();\n log.warn('Conflicting configs detected:');\n for (const p of env.allConfigPaths) {\n log.print(` ${chalk.yellow('→')} ${chalk.white(path.relative(cwd, p))}`);\n }\n log.print(` ${chalk.gray('Multiple config formats found — this can cause unpredictable behavior.')}`);\n }\n\n log.blank();\n\n // ─── Step 2: Gate on missing deps ────────────────────────────────────────\n\n const toInstall: string[] = [];\n if (!env.eslintVersion) toInstall.push('eslint');\n if (!env.pluginInstalled) toInstall.push('eslint-plugin-ai-guard');\n\n if (toInstall.length > 0) {\n log.section('Missing Dependencies');\n log.warn('The following packages are not installed:');\n log.blank();\n for (const pkg of toInstall) {\n log.print(` ${chalk.yellow('→')} ${chalk.white(pkg)}`);\n }\n log.blank();\n log.print(` ${chalk.bold('Run this first:')}`);\n log.blank();\n log.print(` ${chalk.cyan(`npm install --save-dev ${toInstall.join(' ')}`)}`);\n log.blank();\n log.print(` Then re-run ${chalk.cyan('ai-guard init')} to complete setup.`);\n log.blank();\n process.exit(1);\n return;\n }\n\n // ─── Step 3: Runtime Safety ─────────────────────────────────────────────\n\n try {\n const { createRequire } = await import('module');\n const { pathToFileURL } = await import('url');\n const req = createRequire(path.join(cwd, '_probe.js'));\n const resolvedPath = req.resolve('eslint-plugin-ai-guard');\n const aiGuard = await import(pathToFileURL(resolvedPath).href);\n const plugin = (aiGuard.default || aiGuard) as {\n configs?: Record<string, { rules?: unknown }>;\n };\n\n const hasPresetRules =\n !!plugin.configs &&\n !!plugin.configs[preset] &&\n !!plugin.configs[preset].rules;\n\n if (!hasPresetRules) {\n // Keep this as informational only; Step 6 performs definitive runtime validation.\n log.debug('Plugin precheck could not verify configs shape; continuing to validation step.');\n }\n } catch (e) {\n // If resolution fails entirely, skip the check; validation step will catch load errors\n const reason = e instanceof Error ? e.message : String(e);\n log.debug(`Skipped plugin precheck: ${reason}`);\n }\n\n // ─── Step 4: Determine config format ────────────────────────────────────\n // Priority:\n // 1. --flat flag forces flat config\n // 2. ESLint v9+ → MUST use flat config\n // 3. ESLint v8 → use legacy; unless an existing flat config is already there\n // 4. No version info → default to flat (safer)\n\n const forceFlat = opts.flat === true;\n const existingIsFlat = isFlat(env.configType);\n const existingIsLegacy = isLegacy(env.configType);\n const useFlat = forceFlat || eslintNeedsFlat || existingIsFlat || env.configType === 'none';\n\n // Guard: ESLint v9 + existing legacy config → migrate, don't re-create legacy\n if (eslintNeedsFlat && existingIsLegacy) {\n log.section('Config Migration Required');\n log.warn(`ESLint v${env.eslintMajor} requires flat config, but a legacy config was found:`);\n log.print(` ${chalk.white(path.relative(cwd, env.configPath!))}`);\n log.blank();\n log.print(` ${chalk.bold('ai-guard will create a new flat config.')}`);\n log.blank();\n }\n\n // ─── Step 5: Apply config change ────────────────────────────────────────\n\n log.section(`Configuring ESLint${isDryRun ? ' (dry run)' : ''}`);\n\n let finalConfigPath: string;\n let configWritten = false;\n\n // Nuke-ignore removal — fix before anything else\n if (env.configPath && env.hasNukeIgnore) {\n const raw = readConfig(env.configPath);\n const { content: fixed, changed } = removeNukeIgnore(raw);\n if (changed) {\n log.warn(`Removed \"**/*\" ignore pattern from ${path.relative(cwd, env.configPath)}`);\n if (!isDryRun) {\n backupConfig(env.configPath);\n writeConfig(env.configPath, fixed);\n log.success('Ignore pattern fixed');\n } else {\n log.print(` ${chalk.gray('[dry-run] would remove nuke-ignore from existing config')}`);\n }\n }\n }\n\n if (env.configType === 'none' || (eslintNeedsFlat && existingIsLegacy)) {\n // ── Generate fresh config ──────────────────────────────────────────────\n const targetName = useFlat ? 'eslint.config.mjs' : '.eslintrc.js';\n finalConfigPath = path.join(cwd, targetName);\n\n const content = useFlat\n ? generateFlatConfig(preset)\n : generateLegacyConfig(preset);\n\n if (isDryRun) {\n log.print(` ${chalk.gray(`[dry-run] would create: ${targetName}`)}`);\n log.blank();\n log.print(chalk.gray('─── Preview ─────────────────────────────────────────────'));\n log.blank();\n for (const line of content.split('\\n')) {\n log.print(chalk.gray(` ${line}`));\n }\n log.blank();\n } else {\n writeConfig(finalConfigPath, content);\n log.success(`Created ${chalk.white(targetName)}`);\n log.info(` Preset: ${chalk.cyan(preset)}`);\n log.info(` Format: ${chalk.cyan(useFlat ? 'ESLint v9 flat config (eslint.config.mjs)' : 'ESLint v8 legacy config (.eslintrc.js)')}`);\n configWritten = true;\n }\n } else if (useFlat && existingIsFlat) {\n // ── Patch existing flat config ─────────────────────────────────────────\n const { isInvalidAiGuardConfig } = await import('../utils/config-manager.js');\n const existing = readConfig(env.configPath!);\n const isInvalid = isInvalidAiGuardConfig(existing);\n const patched = patchFlatConfig(existing, preset);\n\n if (patched === existing && !isInvalid) {\n log.warn('ai-guard is already present in your config — no changes made');\n finalConfigPath = env.configPath!;\n } else if (isDryRun) {\n finalConfigPath = env.configPath!;\n log.print(` ${chalk.gray(`[dry-run] would patch: ${path.relative(cwd, env.configPath!)}`)}`);\n } else {\n const bak = backupConfig(env.configPath!);\n log.info(`Backed up → ${chalk.gray(path.relative(cwd, bak))}`);\n writeConfig(env.configPath!, patched);\n if (isInvalid) {\n log.success(`Detected invalid ai-guard config — repairing ${chalk.white(path.relative(cwd, env.configPath!))}`);\n } else {\n log.success(`Patched ${chalk.white(path.relative(cwd, env.configPath!))}`);\n }\n finalConfigPath = env.configPath!;\n configWritten = true;\n }\n } else {\n // ── Patch existing legacy config ─────────────────────────────────────\n const existing = readConfig(env.configPath!);\n const patched = patchLegacyConfig(existing, preset);\n\n if (patched === existing) {\n log.warn('ai-guard is already present in your config — no changes made');\n finalConfigPath = env.configPath!;\n } else if (isDryRun) {\n finalConfigPath = env.configPath!;\n log.print(` ${chalk.gray(`[dry-run] would patch: ${path.relative(cwd, env.configPath!)}`)}`);\n } else {\n const bak = backupConfig(env.configPath!);\n log.info(`Backed up → ${chalk.gray(path.relative(cwd, bak))}`);\n writeConfig(env.configPath!, patched);\n log.success(`Patched ${chalk.white(path.relative(cwd, env.configPath!))}`);\n finalConfigPath = env.configPath!;\n configWritten = true;\n }\n }\n\n // ── Auto cleanup legacy config (conflict resolution) ───────────────\n if (eslintNeedsFlat) {\n // Find legacy configs that might cause conflicts\n const legacyConfigs = env.allConfigPaths.filter(p => !p.includes('eslint.config.'));\n \n let cleanedUp = false;\n for (const p of legacyConfigs) {\n if (fs.existsSync(p)) {\n if (!isDryRun) {\n try {\n fs.renameSync(p, `${p}.bak`);\n cleanedUp = true;\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n log.warn(`Could not back up ${path.relative(cwd, p)}: ${reason}`);\n }\n } else {\n cleanedUp = true;\n log.print(` ${chalk.gray(`[dry-run] would rename ${path.relative(cwd, p)} to ${path.basename(p)}.bak`)}`);\n }\n }\n }\n if (cleanedUp && !isDryRun) {\n log.success('Legacy config backed up to avoid ESLint conflict');\n }\n }\n\n if (isDryRun) {\n log.blank();\n log.print(` ${chalk.yellow('Dry run complete — no files written.')}`);\n log.print(` Re-run without ${chalk.cyan('--dry-run')} to apply.`);\n log.blank();\n process.exit(0);\n return;\n }\n\n log.blank();\n\n // ─── Step 5: Structural validation ──────────────────────────────────────\n\n log.section('Validation');\n\n if (!fs.existsSync(finalConfigPath)) {\n log.error(`Config file not found after write: ${path.relative(cwd, finalConfigPath)}`);\n log.blank();\n log.print(` ${chalk.bold('Problem:')} File write may have failed.`);\n log.print(` ${chalk.bold('Fix:')} Check disk space and file permissions, then re-run.`);\n log.blank();\n process.exit(1);\n return;\n }\n\n const content = readConfig(finalConfigPath);\n const validationErrors = useFlat\n ? validateFlatConfigText(content)\n : validateLegacyConfigText(content);\n\n if (validationErrors.length > 0) {\n log.warn('Config validation found issues:');\n for (const e of validationErrors) {\n log.print(` ${chalk.red('✖')} ${e}`);\n }\n } else {\n log.success(`Config structure valid: ${chalk.white(path.relative(cwd, finalConfigPath))}`);\n }\n\n // ─── Step 6: Programmatic ESLint load verification ───────────────────────\n\n log.info('Verifying ESLint can load the config…');\n\n const loadError = await verifyConfigLoads(finalConfigPath, cwd);\n if (loadError !== null) {\n log.blank();\n\n if (loadError.kind === 'module-not-found') {\n // Missing dep — config syntax is fine, just need to install the package\n log.warn(`Could not verify: module not found: ${chalk.yellow(loadError.pkg)}`);\n log.blank();\n log.print(` ${chalk.bold('Install the missing package:')}`);\n log.print(` ${chalk.cyan(`npm install --save-dev ${loadError.pkg}`)}`);\n log.print(` Then run ${chalk.cyan('ai-guard doctor')} to confirm.`);\n log.blank();\n // Fall through — config was written correctly; missing dep is user's next step\n } else {\n // Real error — config syntax broken or unknown failure → hard fail\n log.error('ESLint failed to load the generated config.');\n log.blank();\n log.print(` ${chalk.bold('Problem:')}`);\n log.print(` ${chalk.red(loadError.message)}`);\n if (loadError.kind === 'unknown') {\n log.blank();\n log.print(` ${chalk.yellow('Generated config may be using incorrect plugin structure.')}`);\n }\n log.blank();\n log.print(` ${chalk.bold('Fix:')}`);\n log.print(` 1. Check the syntax in ${chalk.cyan(path.relative(cwd, finalConfigPath))}`);\n log.print(` 2. Make sure ${chalk.cyan('eslint-plugin-ai-guard')} is installed`);\n log.print(` 3. Run ${chalk.cyan('ai-guard doctor')} for full diagnostics`);\n log.blank();\n process.exit(1);\n return;\n }\n } else {\n log.success('ESLint loaded config successfully');\n }\n\n\n log.blank();\n\n\n\n // ─── Step 7: Success ─────────────────────────────────────────────────────\n\n log.section('Setup Complete');\n log.blank();\n\n let cleanedUpInfo = false;\n if (eslintNeedsFlat) {\n const legacyConfigs = env.allConfigPaths.filter(p => !p.includes('eslint.config.'));\n cleanedUpInfo = legacyConfigs.some(p => fs.existsSync(`${p}.bak`) && !fs.existsSync(p));\n }\n\n const lingeringConflicts = env.hasConflictingConfigs && !eslintNeedsFlat && !cleanedUpInfo;\n if (loadError === null && !lingeringConflicts) {\n log.print(` ${chalk.green('✔')} ${chalk.bold.green('Configuration validated successfully')}`);\n }\n log.print(` ${chalk.green('✔')} ${chalk.bold('ESLint config:')} ${chalk.cyan(path.relative(cwd, finalConfigPath))}`);\n log.print(` ${chalk.green('✔')} ${chalk.bold('Mode:')} ${chalk.cyan(useFlat ? `Flat config (ESLint v${env.eslintMajor ?? 9})` : `Legacy config (ESLint v${env.eslintMajor ?? 8})`)}`);\n log.print(` ${chalk.green('✔')} ${chalk.bold('Preset:')} ${chalk.cyan(preset)}`);\n log.blank();\n log.info(`Run ${chalk.cyan('npx eslint .')} → lint with your editor integration`);\n log.info(`Run ${chalk.cyan('ai-guard run')} → zero-config scan`);\n log.info(`Run ${chalk.cyan('ai-guard doctor')} → verify the full setup`);\n log.info(`Run ${chalk.cyan('ai-guard baseline')} → save baseline, track only new issues`);\n log.blank();\n });\n}\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport { createRequire } from 'module';\r\n\r\n// ─── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport type ConfigType =\r\n | 'flat-js'\r\n | 'flat-mjs'\r\n | 'flat-cjs'\r\n | 'eslintrc-js'\r\n | 'eslintrc-cjs'\r\n | 'eslintrc-json'\r\n | 'eslintrc-yaml'\r\n | 'none';\r\n\r\nexport interface DetectionResult {\r\n /** Raw version string e.g. \"9.1.0\" — null if not installed */\r\n eslintVersion: string | null;\r\n eslintMajor: number | null;\r\n pluginInstalled: boolean;\r\n configType: ConfigType;\r\n configPath: string | null;\r\n /** All config files found — to detect conflicts */\r\n allConfigPaths: string[];\r\n /** True when a flat config AND a legacy config both exist */\r\n hasConflictingConfigs: boolean;\r\n /** True when config contains a pattern that ignores everything */\r\n hasNukeIgnore: boolean;\r\n}\r\n\r\n// ─── Config file registry ─────────────────────────────────────────────────────\r\n\r\nconst FLAT_CONFIG_FILES: Array<{ file: string; type: ConfigType }> = [\r\n { file: 'eslint.config.js', type: 'flat-js' },\r\n { file: 'eslint.config.mjs', type: 'flat-mjs' },\r\n { file: 'eslint.config.cjs', type: 'flat-cjs' },\r\n];\r\n\r\nconst LEGACY_CONFIG_FILES: Array<{ file: string; type: ConfigType }> = [\r\n { file: '.eslintrc.js', type: 'eslintrc-js' },\r\n { file: '.eslintrc.cjs', type: 'eslintrc-cjs' },\r\n { file: '.eslintrc.json', type: 'eslintrc-json' },\r\n { file: '.eslintrc.yaml', type: 'eslintrc-yaml' },\r\n { file: '.eslintrc.yml', type: 'eslintrc-yaml' },\r\n];\r\n\r\nconst ALL_CONFIG_FILES = [...FLAT_CONFIG_FILES, ...LEGACY_CONFIG_FILES];\r\n\r\n// ─── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\nexport function isPackageInstalled(pkgName: string, cwd = process.cwd()): boolean {\r\n try {\r\n const pkgPath = path.join(cwd, 'node_modules', pkgName, 'package.json');\r\n if (fs.existsSync(pkgPath)) {\r\n return true;\r\n }\r\n\r\n const req = createRequire(path.join(cwd, 'package.json'));\r\n req.resolve(`${pkgName}/package.json`);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Read a package.json version from node_modules.\r\n * Reads directly from disk — no require() involvement — so it always\r\n * reflects the *installed* version even when running inside a bundled binary.\r\n */\r\nexport function getPackageVersion(pkgName: string, cwd = process.cwd()): string | null {\r\n try {\r\n const pkgPath = path.join(cwd, 'node_modules', pkgName, 'package.json');\r\n const resolvedPath = fs.existsSync(pkgPath)\r\n ? pkgPath\r\n : createRequire(path.join(cwd, 'package.json')).resolve(`${pkgName}/package.json`);\r\n const raw = fs.readFileSync(resolvedPath, 'utf-8');\r\n const json = JSON.parse(raw) as { version?: string };\r\n return json.version ?? null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** Parse the major version number from a semver string */\r\nexport function parseMajor(version: string | null): number | null {\r\n if (!version) return null;\r\n const n = parseInt(version.split('.')[0], 10);\r\n return isNaN(n) ? null : n;\r\n}\r\n\r\n// ─── Config detection ─────────────────────────────────────────────────────────\r\n\r\nexport function detectConfigType(cwd = process.cwd()): {\r\n type: ConfigType;\r\n path: string | null;\r\n allPaths: string[];\r\n} {\r\n const found: string[] = [];\r\n let first: { type: ConfigType; path: string } | null = null;\r\n\r\n for (const { file, type } of ALL_CONFIG_FILES) {\r\n const fullPath = path.join(cwd, file);\r\n if (fs.existsSync(fullPath)) {\r\n found.push(fullPath);\r\n if (!first) first = { type, path: fullPath };\r\n }\r\n }\r\n\r\n return {\r\n type: first?.type ?? 'none',\r\n path: first?.path ?? null,\r\n allPaths: found,\r\n };\r\n}\r\n\r\nexport function isFlat(type: ConfigType): boolean {\r\n return type === 'flat-js' || type === 'flat-mjs' || type === 'flat-cjs';\r\n}\r\n\r\nexport function isLegacy(type: ConfigType): boolean {\r\n return (\r\n type === 'eslintrc-js' ||\r\n type === 'eslintrc-cjs' ||\r\n type === 'eslintrc-json' ||\r\n type === 'eslintrc-yaml'\r\n );\r\n}\r\n\r\n/**\r\n * Returns true if the given ESLint major version requires flat config.\r\n * ESLint 9+ uses flat config by default; ESLint 8 uses legacy config.\r\n */\r\nexport function requiresFlatConfig(eslintMajor: number | null): boolean {\r\n return eslintMajor !== null && eslintMajor >= 9;\r\n}\r\n\r\n/**\r\n * Check for \"nuke\" ignore patterns — patterns that silently exclude all files.\r\n * Common culprit: ignorePatterns: [\"**\\/*\"] or ignores: [\"**\\/*\"]\r\n */\r\nfunction detectNukeIgnore(configPath: string | null): boolean {\r\n if (!configPath) return false;\r\n try {\r\n const content = fs.readFileSync(configPath, 'utf-8');\r\n return content.includes('\"**/*\"') || content.includes(\"'**/*'\");\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n// ─── Main detection entry point ───────────────────────────────────────────────\r\n\r\nexport function detect(cwd = process.cwd()): DetectionResult {\r\n const eslintVersion = getPackageVersion('eslint', cwd);\r\n const eslintMajor = parseMajor(eslintVersion);\r\n const pluginInstalled = isPackageInstalled('eslint-plugin-ai-guard', cwd);\r\n\r\n const { type: configType, path: configPath, allPaths } = detectConfigType(cwd);\r\n\r\n // Conflict: both flat AND legacy config files exist\r\n const hasFlatConfig = allPaths.some((p) =>\r\n FLAT_CONFIG_FILES.some((c) => p.endsWith(c.file)),\r\n );\r\n const hasLegacyConfig = allPaths.some((p) =>\r\n LEGACY_CONFIG_FILES.some((c) => p.endsWith(c.file)),\r\n );\r\n const hasConflictingConfigs = hasFlatConfig && hasLegacyConfig;\r\n\r\n const hasNukeIgnore = detectNukeIgnore(configPath);\r\n\r\n return {\r\n eslintVersion,\r\n eslintMajor,\r\n pluginInstalled,\r\n configType,\r\n configPath,\r\n allConfigPaths: allPaths,\r\n hasConflictingConfigs,\r\n hasNukeIgnore,\r\n };\r\n}\r\n\r\n// ─── Monorepo detection ────────────────────────────────────────────────────────\r\n\r\nexport interface MonorepoResult {\r\n isMonorepo: boolean;\r\n tool: 'pnpm' | 'npm-workspaces' | 'yarn-workspaces' | 'nx' | 'turborepo' | 'lerna' | null;\r\n packages: string[];\r\n}\r\n\r\nexport function detectMonorepo(cwd = process.cwd()): MonorepoResult {\r\n if (fs.existsSync(path.join(cwd, 'pnpm-workspace.yaml'))) {\r\n return { isMonorepo: true, tool: 'pnpm', packages: discoverWorkspacePackages(cwd) };\r\n }\r\n if (fs.existsSync(path.join(cwd, 'nx.json'))) {\r\n return { isMonorepo: true, tool: 'nx', packages: discoverWorkspacePackages(cwd) };\r\n }\r\n if (fs.existsSync(path.join(cwd, 'turbo.json'))) {\r\n return { isMonorepo: true, tool: 'turborepo', packages: discoverWorkspacePackages(cwd) };\r\n }\r\n if (fs.existsSync(path.join(cwd, 'lerna.json'))) {\r\n return { isMonorepo: true, tool: 'lerna', packages: discoverWorkspacePackages(cwd) };\r\n }\r\n try {\r\n const pkgPath = path.join(cwd, 'package.json');\r\n if (fs.existsSync(pkgPath)) {\r\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as {\r\n workspaces?: string[] | { packages?: string[] };\r\n };\r\n if (pkg.workspaces) {\r\n const tool = fs.existsSync(path.join(cwd, 'yarn.lock'))\r\n ? ('yarn-workspaces' as const)\r\n : ('npm-workspaces' as const);\r\n return { isMonorepo: true, tool, packages: discoverWorkspacePackages(cwd) };\r\n }\r\n }\r\n } catch { /* not a monorepo */ }\r\n return { isMonorepo: false, tool: null, packages: [] };\r\n}\r\n\r\nfunction discoverWorkspacePackages(cwd: string): string[] {\r\n const commonDirs = ['packages', 'apps', 'libs', 'modules', 'services'];\r\n const found: string[] = [];\r\n for (const dir of commonDirs) {\r\n const dirPath = path.join(cwd, dir);\r\n if (!fs.existsSync(dirPath)) continue;\r\n try {\r\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (!entry.isDirectory()) continue;\r\n if (fs.existsSync(path.join(dirPath, entry.name, 'package.json'))) {\r\n found.push(path.join(dir, entry.name));\r\n }\r\n }\r\n } catch { /* skip */ }\r\n }\r\n return found;\r\n}\r\n","import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport path from 'path';\nimport { detect, isFlat, isLegacy, requiresFlatConfig } from '../utils/detector.js';\nimport { log } from '../utils/logger.js';\nimport { readConfig } from '../utils/config-manager.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface CheckResult {\n label: string;\n pass: boolean;\n detail: string;\n /** Exact command or action to fix — shown as cyan */\n fix?: string;\n /** Additional explanation shown below fix as gray */\n note?: string;\n}\n\n// ─── Programmatic config load probe ──────────────────────────────────────────\n\nasync function probeConfigLoad(\n configPath: string,\n cwd: string,\n): Promise<{ ok: boolean; error: string | null }> {\n try {\n const { ESLint } = await import('eslint') as { ESLint: any };\n const eslint = new ESLint({ cwd, overrideConfigFile: configPath });\n await eslint.lintText('', { filePath: path.join(cwd, '_probe_.js') });\n return { ok: true, error: null };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n // \"no files\" or \"probe\" errors are not config errors\n if (\n msg.includes('No files') ||\n msg.includes('no files') ||\n msg.includes('_probe_')\n ) {\n return { ok: true, error: null };\n }\n // Strip stack frames from message\n const clean = msg.replace(/\\s+at\\s+.+/gm, '').trim();\n return { ok: false, error: clean };\n }\n}\n\n// ─── Command ──────────────────────────────────────────────────────────────────\n\nexport function registerDoctorCommand(program: Command): void {\n program\n .command('doctor')\n .description('Diagnose your ai-guard setup and print actionable fixes')\n .action(async () => {\n const cwd = process.cwd();\n\n log.banner('AI GUARD DOCTOR');\n log.info('Checking your environment…');\n log.blank();\n\n const env = detect(cwd);\n const checks: CheckResult[] = [];\n\n // ── Check 1: ESLint installed ──────────────────────────────────────────\n\n checks.push({\n label: 'ESLint installed',\n pass: env.eslintVersion !== null,\n detail: env.eslintVersion\n ? `ESLint ${env.eslintVersion}`\n : 'Not found in node_modules',\n fix: env.eslintVersion\n ? undefined\n : 'npm install --save-dev eslint',\n });\n\n // ── Check 2: Plugin installed ──────────────────────────────────────────\n\n checks.push({\n label: 'eslint-plugin-ai-guard installed',\n pass: env.pluginInstalled,\n detail: env.pluginInstalled\n ? 'Found in node_modules'\n : 'Not found in node_modules',\n fix: env.pluginInstalled\n ? undefined\n : 'npm install --save-dev eslint-plugin-ai-guard',\n });\n\n // ── Check 3: ESLint config exists ─────────────────────────────────────\n\n const hasConfig = env.configType !== 'none';\n checks.push({\n label: 'ESLint config present',\n pass: hasConfig,\n detail: hasConfig\n ? `${path.relative(cwd, env.configPath ?? '')} (${env.configType})`\n : 'No eslint.config.* or .eslintrc.* found',\n fix: hasConfig\n ? undefined\n : 'ai-guard init',\n note: hasConfig\n ? undefined\n : 'This will generate the correct config format for your ESLint version',\n });\n\n // ── Check 4: Config type matches ESLint version ────────────────────────\n\n if (env.eslintMajor !== null && hasConfig) {\n const needsFlat = requiresFlatConfig(env.eslintMajor);\n const actuallyFlat = isFlat(env.configType);\n const actuallyLegacy = isLegacy(env.configType);\n const aligned =\n (needsFlat && actuallyFlat) || (!needsFlat && actuallyLegacy);\n\n checks.push({\n label: 'Config format matches ESLint version',\n pass: aligned,\n detail: aligned\n ? `${actuallyFlat ? 'Flat config' : 'Legacy config'} ✔ matches ESLint v${env.eslintMajor}`\n : `ESLint v${env.eslintMajor} requires ${needsFlat ? 'flat config (eslint.config.*)'\n : 'legacy config (.eslintrc.*)'} but found ${actuallyFlat ? 'flat' : 'legacy'} config`,\n fix: aligned\n ? undefined\n : needsFlat\n ? 'ai-guard init (will create eslint.config.mjs)'\n : 'npm install --save-dev eslint@8 (or upgrade to v9 and run ai-guard init)',\n note: aligned\n ? undefined\n : needsFlat\n ? 'ESLint v9 ignores .eslintrc.* files. The flat config must be used.'\n : undefined,\n });\n }\n\n // ── Check 5: Plugin wired in config ───────────────────────────────────\n\n if (hasConfig && env.configPath) {\n let pluginWired = false;\n let isInvalidConfig = false;\n let readError: string | null = null;\n try {\n const { isInvalidAiGuardConfig } = await import('../utils/config-manager.js');\n const content = readConfig(env.configPath);\n pluginWired =\n content.includes('ai-guard') ||\n content.includes('eslint-plugin-ai-guard');\n isInvalidConfig = isInvalidAiGuardConfig(content);\n } catch (err) {\n readError = err instanceof Error ? err.message : String(err);\n }\n\n checks.push({\n label: 'Plugin wired in config',\n pass: pluginWired && !isInvalidConfig,\n detail: readError\n ? `Could not read config: ${readError}`\n : isInvalidConfig\n ? 'Invalid ai-guard config detected (wrong export usage)'\n : pluginWired\n ? 'eslint-plugin-ai-guard referenced in config'\n : `Config exists but ai-guard plugin not found in ${path.relative(cwd, env.configPath)}`,\n fix: isInvalidConfig || (!pluginWired && !readError)\n ? 'ai-guard init (will patch/repair your existing config)'\n : undefined,\n });\n }\n\n // ── Check 6: No conflicting configs ───────────────────────────────────\n\n checks.push({\n label: 'No conflicting config files',\n pass: !env.hasConflictingConfigs,\n detail: env.hasConflictingConfigs\n ? `Conflicting config detected:\\n${env.allConfigPaths.map((p) => ` ${path.relative(cwd, p)}`).join('\\n')}`\n : 'Only one config format detected',\n fix: env.hasConflictingConfigs\n ? 'Remove or backup legacy config'\n : undefined,\n note: env.hasConflictingConfigs\n ? 'ESLint v9 silently ignores .eslintrc.* when a flat config exists. This can cause confusion.'\n : undefined,\n });\n\n // ── Check 7: No nuke-ignore pattern ───────────────────────────────────\n\n if (hasConfig && env.hasNukeIgnore) {\n checks.push({\n label: 'No \"ignore everything\" pattern',\n pass: false,\n detail: `Config contains \"**/*\" ignore pattern — this silently prevents all files from being linted`,\n fix: 'ai-guard init (will remove the pattern and replace with safe ignores)',\n });\n }\n\n // ── Check 8: ESLint version compatible ────────────────────────────────\n\n const versionOk = env.eslintMajor !== null && env.eslintMajor >= 8;\n checks.push({\n label: 'ESLint version compatible',\n pass: versionOk,\n detail: versionOk\n ? `v${env.eslintMajor} ✔ (requires ≥ v8)`\n : env.eslintMajor !== null\n ? `v${env.eslintMajor} is too old — requires ESLint ≥ 8`\n : 'ESLint not installed',\n fix: versionOk ? undefined : 'npm install --save-dev eslint@latest',\n });\n\n // ── Check 9: Programmatic config load ─────────────────────────────────\n // Only run this if we have a config and all prior config checks passed,\n // so we don't produce redundant errors.\n\n const configChecksPass = checks.every((c) => c.pass);\n if (hasConfig && env.configPath && env.pluginInstalled && configChecksPass) {\n log.info('Probing ESLint config load…');\n const probe = await probeConfigLoad(env.configPath, cwd);\n\n checks.push({\n label: 'ESLint config loads without errors',\n pass: probe.ok,\n detail: probe.ok\n ? 'ESLint loaded config successfully'\n : probe.error ?? 'Unknown error',\n fix: probe.ok\n ? undefined\n : `Check syntax in ${path.relative(cwd, env.configPath)}`,\n note: probe.ok\n ? undefined\n : 'Run: ai-guard init --dry-run to preview a fresh config',\n });\n }\n\n // ── Check 10: @typescript-eslint/utils resolvable at runtime ──────────\n {\n let utilsOk = false;\n let utilsVersion: string | null = null;\n try {\n const { createRequire } = await import('module');\n const req = createRequire(path.join(cwd, 'package.json'));\n const pkgPath = req.resolve('@typescript-eslint/utils/package.json');\n const pkg = JSON.parse(\n (await import('fs')).readFileSync(pkgPath, 'utf-8'),\n ) as { version?: string };\n utilsVersion = pkg.version ?? null;\n utilsOk = true;\n } catch {\n // Not found\n }\n\n if (!utilsOk) {\n // Fall back to checking our own package location\n try {\n const selfDir = path.dirname(\n new URL(import.meta.url).pathname.replace(/^\\/([A-Za-z]:)/, '$1'),\n );\n const pkgPath = path.join(selfDir, '../../node_modules/@typescript-eslint/utils/package.json');\n if ((await import('fs')).existsSync(pkgPath)) {\n utilsOk = true;\n }\n } catch { /* skip */ }\n }\n\n checks.push({\n label: '@typescript-eslint/utils available at runtime',\n pass: utilsOk,\n detail: utilsOk\n ? `Found${utilsVersion ? ` v${utilsVersion}` : ''}`\n : 'Not found — rule engine may crash on fresh installs',\n fix: utilsOk\n ? undefined\n : 'npm install @typescript-eslint/utils',\n note: utilsOk\n ? undefined\n : 'This is a runtime dependency of eslint-plugin-ai-guard rules.',\n });\n }\n\n // ── Check 11: @typescript-eslint/parser for TS projects ───────────────\n {\n let parserOk = false;\n let parserVersion: string | null = null;\n try {\n const { createRequire } = await import('module');\n const req = createRequire(path.join(cwd, 'package.json'));\n const pkgPath = req.resolve('@typescript-eslint/parser/package.json');\n const pkg = JSON.parse(\n (await import('fs')).readFileSync(pkgPath, 'utf-8'),\n ) as { version?: string };\n parserVersion = pkg.version ?? null;\n parserOk = true;\n } catch {\n // Optional — only needed for TS projects\n }\n\n const hasTsFiles = (() => {\n try {\n const { readdirSync } = require('fs');\n const files = readdirSync(cwd) as string[];\n return files.some((f: string) => f.endsWith('.ts') || f.endsWith('.tsx'));\n } catch {\n return false;\n }\n })();\n\n if (!parserOk && hasTsFiles) {\n checks.push({\n label: '@typescript-eslint/parser installed (TypeScript project)',\n pass: false,\n detail: '.ts/.tsx files detected but TypeScript parser not found',\n fix: 'npm install --save-dev @typescript-eslint/parser',\n note: 'TypeScript files will use espree fallback without this — some rules may not work correctly.',\n });\n }\n }\n\n // ─── Render results ────────────────────────────────────────────────────\n\n log.section('Diagnostics');\n\n let allPassed = true;\n for (const check of checks) {\n const icon = check.pass ? chalk.green('✔') : chalk.red('✖');\n const label = check.pass\n ? chalk.white(check.label)\n : chalk.red.bold(check.label);\n\n log.print(` ${icon} ${label}`);\n log.print(` ${chalk.gray(check.detail)}`);\n\n if (!check.pass) {\n allPassed = false;\n if (check.fix) {\n log.print(` ${chalk.cyan('→ Fix:')} ${chalk.yellow(check.fix)}`);\n }\n if (check.note) {\n log.print(` ${chalk.gray(check.note)}`);\n }\n }\n\n log.blank();\n }\n\n log.divider();\n log.blank();\n\n if (allPassed) {\n log.print(` ${chalk.green('✔')} ${chalk.bold.green('All checks passed! Your setup is correct.')}`);\n log.blank();\n log.info(`Run ${chalk.cyan('ai-guard run')} to start scanning.`);\n log.info(`Run ${chalk.cyan('npx eslint .')} to lint with ESLint directly.`);\n } else {\n log.error('Some checks failed. Follow the fixes above.');\n log.blank();\n\n // Smart suggestion — only suggest init if it won't cause an infinite loop\n const configFormatMismatch = checks.some(\n (c) => c.label === 'Config format matches ESLint version' && !c.pass,\n );\n const configMissing = checks.some(\n (c) => c.label === 'ESLint config present' && !c.pass,\n );\n const pluginMissing = checks.some(\n (c) => c.label === 'eslint-plugin-ai-guard installed' && !c.pass,\n );\n\n if (pluginMissing) {\n log.print(\n ` Install missing packages first, then re-run ${chalk.cyan('ai-guard doctor')}.`,\n );\n } else if (configMissing || configFormatMismatch) {\n log.print(\n ` Run ${chalk.cyan('ai-guard init')} to generate the correct config for your ESLint version.`,\n );\n } else {\n log.print(\n ` Run ${chalk.cyan('ai-guard init --dry-run')} to preview what would change.`,\n );\n }\n }\n\n log.blank();\n process.exit(allPassed ? 0 : 1);\n });\n}\n","import type { Command } from 'commander';\r\nimport { select } from '@inquirer/prompts';\r\nimport chalk from 'chalk';\r\nimport { detect, isFlat } from '../utils/detector.js';\r\nimport {\r\n backupConfig,\r\n readConfig,\r\n writeConfig,\r\n patchFlatConfig,\r\n patchLegacyConfig,\r\n switchFlatPreset,\r\n switchLegacyPreset,\r\n generateFlatConfig,\r\n generateLegacyConfig,\r\n type Preset,\r\n} from '../utils/config-manager.js';\r\nimport { log } from '../utils/logger.js';\r\nimport path from 'path';\r\n\r\nexport function registerPresetCommand(program: Command): void {\r\n program\r\n .command('preset')\r\n .description('Interactively select and apply an ai-guard preset to your ESLint config')\r\n .action(async () => {\r\n const cwd = process.cwd();\r\n\r\n log.banner('AI GUARD PRESET');\r\n log.blank();\r\n\r\n const preset = await select<Preset>({\r\n message: 'Choose a preset:',\r\n choices: [\r\n {\r\n name: `${chalk.green('recommended')} — balanced defaults, low noise. Best starting point.`,\r\n value: 'recommended',\r\n },\r\n {\r\n name: `${chalk.yellow('strict')} — all rules at error. For mature codebases.`,\r\n value: 'strict',\r\n },\r\n {\r\n name: `${chalk.red('security')} — security rules only. For AppSec teams.`,\r\n value: 'security',\r\n },\r\n ],\r\n });\r\n\r\n log.blank();\r\n log.info(`Applying preset: ${chalk.cyan(preset)}`);\r\n\r\n const env = detect(cwd);\r\n const useFlat =\r\n (env.eslintMajor !== null && env.eslintMajor >= 9) ||\r\n isFlat(env.configType);\r\n\r\n if (env.configType === 'none') {\r\n // Generate fresh config with chosen preset\r\n const configPath = useFlat\r\n ? path.join(cwd, 'eslint.config.mjs')\r\n : path.join(cwd, '.eslintrc.js');\r\n\r\n const content = useFlat\r\n ? generateFlatConfig(preset)\r\n : generateLegacyConfig(preset);\r\n\r\n writeConfig(configPath, content);\r\n log.success(`Created ${chalk.white(path.relative(cwd, configPath))} with ${chalk.cyan(preset)} preset`);\r\n } else {\r\n const configPath = env.configPath!;\r\n const backupPath = backupConfig(configPath);\r\n log.info(`Backed up → ${chalk.gray(path.relative(cwd, backupPath))}`);\r\n\r\n const existing = readConfig(configPath);\r\n const withPlugin = isFlat(env.configType)\r\n ? patchFlatConfig(existing, preset)\r\n : patchLegacyConfig(existing, preset);\r\n\r\n const patched = isFlat(env.configType)\r\n ? switchFlatPreset(withPlugin, preset)\r\n : switchLegacyPreset(withPlugin, preset);\r\n\r\n if (patched === existing) {\r\n log.warn('No preset changes needed. Config already matches selected preset.');\r\n } else {\r\n writeConfig(configPath, patched);\r\n log.success(`Updated ${chalk.white(path.relative(cwd, configPath))} to ${chalk.cyan(preset)} preset`);\r\n }\r\n }\r\n\r\n log.blank();\r\n log.section('Preset Details');\r\n\r\n const presetDetails: Record<Preset, Array<{ rule: string; level: string }>> = {\r\n recommended: [\r\n { rule: 'no-empty-catch', level: chalk.red('error') },\r\n { rule: 'no-floating-promise', level: chalk.red('error') },\r\n { rule: 'no-hardcoded-secret', level: chalk.red('error') },\r\n { rule: 'no-eval-dynamic', level: chalk.red('error') },\r\n { rule: 'no-broad-exception', level: chalk.yellow('warn') },\r\n { rule: 'no-async-array-callback', level: chalk.yellow('warn') },\r\n { rule: 'no-await-in-loop', level: chalk.yellow('warn') },\r\n { rule: '+ 5 more…', level: chalk.gray('warn') },\r\n ],\r\n strict: [\r\n { rule: 'All 17 rules', level: chalk.red('error') },\r\n ],\r\n security: [\r\n { rule: 'no-hardcoded-secret', level: chalk.red('error') },\r\n { rule: 'no-eval-dynamic', level: chalk.red('error') },\r\n { rule: 'no-sql-string-concat', level: chalk.red('error') },\r\n { rule: 'no-unsafe-deserialize', level: chalk.yellow('warn') },\r\n { rule: 'require-auth-middleware', level: chalk.yellow('warn') },\r\n { rule: 'require-authz-check', level: chalk.yellow('warn') },\r\n ],\r\n };\r\n\r\n for (const { rule, level } of presetDetails[preset]) {\r\n log.print(` ${chalk.gray('•')} ${chalk.white(rule).padEnd(32)}${level}`);\r\n }\r\n\r\n log.blank();\r\n log.info(`Run ${chalk.cyan('ai-guard run')} to see results with the new preset.`);\r\n log.blank();\r\n });\r\n}\r\n","import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport { detect, isFlat } from '../utils/detector.js';\nimport {\n backupConfig,\n readConfig,\n writeConfig,\n addIgnoresToFlatConfig,\n addIgnoresToLegacyConfig,\n generateFlatConfig,\n generateLegacyConfig,\n} from '../utils/config-manager.js';\nimport { log } from '../utils/logger.js';\nimport path from 'path';\n\nconst DEFAULT_IGNORES = [\n '.next/',\n 'dist/',\n 'build/',\n 'coverage/',\n 'out/',\n 'node_modules/',\n];\n\nexport function registerIgnoreCommand(program: Command): void {\n program\n .command('ignore')\n .description('Add default ignore patterns (.next, dist, build, coverage) to ESLint config')\n .action(() => {\n const cwd = process.cwd();\n\n log.banner('AI GUARD IGNORE');\n log.blank();\n log.section('Default Ignores');\n\n for (const p of DEFAULT_IGNORES) {\n log.print(` ${chalk.gray('•')} ${chalk.yellow(p)}`);\n }\n\n log.blank();\n\n const env = detect(cwd);\n\n if (env.configType === 'none') {\n // Generate a fresh minimal config with ignores\n const useFlat = env.eslintMajor !== null && env.eslintMajor >= 9;\n const configPath = useFlat\n ? path.join(cwd, 'eslint.config.mjs')\n : path.join(cwd, '.eslintrc.js');\n\n const content = useFlat\n ? generateFlatConfig('recommended')\n : generateLegacyConfig('recommended');\n\n writeConfig(configPath, content);\n log.success(`No config found — generated ${chalk.white(path.relative(cwd, configPath))} with ignores included`);\n } else {\n const configPath = env.configPath!;\n const backupPath = backupConfig(configPath);\n log.info(`Backed up → ${chalk.gray(path.relative(cwd, backupPath))}`);\n\n const existing = readConfig(configPath);\n const patched = isFlat(env.configType)\n ? addIgnoresToFlatConfig(existing)\n : addIgnoresToLegacyConfig(existing);\n\n if (patched === existing) {\n log.warn('Ignore patterns already present in config — no changes made.');\n } else {\n writeConfig(configPath, patched);\n log.success(`Patched ${chalk.white(path.relative(cwd, configPath))} with ignore patterns`);\n }\n }\n\n log.blank();\n log.info('Noisy directories will now be skipped in all future ESLint runs.');\n log.info(`Run ${chalk.cyan('ai-guard run')} to verify cleaner results.`);\n log.blank();\n });\n}\n","import type { Command } from 'commander';\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport chalk from 'chalk';\r\nimport ora from 'ora';\r\nimport { runEslint, type Preset, type RunResult } from '../utils/eslint-runner.js';\r\nimport { log } from '../utils/logger.js';\r\n\r\nconst BASELINE_FILE = '.ai-guard-baseline.json';\r\n\r\n// ─── Baseline format ──────────────────────────────────────────────────────────\r\n\r\ninterface BaselineIssue {\r\n ruleId: string;\r\n message: string;\r\n line: number;\r\n column: number;\r\n}\r\n\r\ntype BaselineMode = 'strict' | 'stable';\r\n\r\ninterface BaselineEntry {\r\n filePath: string;\r\n issues: BaselineIssue[];\r\n}\r\n\r\ninterface BaselineFile {\r\n createdAt: string;\r\n preset: Preset;\r\n mode: BaselineMode;\r\n totalIssues: number;\r\n entries: BaselineEntry[];\r\n}\r\n\r\n// ─── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\nfunction saveBaseline(\r\n result: RunResult,\r\n preset: Preset,\r\n mode: BaselineMode,\r\n cwd: string,\r\n): string {\r\n const entries: BaselineEntry[] = result.files.map((f) => ({\r\n filePath: f.filePath,\r\n issues: f.issues.map((i) => ({\r\n ruleId: i.ruleId,\r\n message: i.message,\r\n line: i.line,\r\n column: i.column,\r\n })),\r\n }));\r\n\r\n const baseline: BaselineFile = {\r\n createdAt: new Date().toISOString(),\r\n preset,\r\n mode,\r\n totalIssues: result.totalIssues,\r\n entries,\r\n };\r\n\r\n const baselinePath = path.join(cwd, BASELINE_FILE);\r\n fs.writeFileSync(baselinePath, JSON.stringify(baseline, null, 2), 'utf-8');\r\n return baselinePath;\r\n}\r\n\r\nfunction loadBaseline(cwd: string): BaselineFile | null {\r\n const baselinePath = path.join(cwd, BASELINE_FILE);\r\n if (!fs.existsSync(baselinePath)) return null;\r\n try {\r\n const raw = fs.readFileSync(baselinePath, 'utf-8');\r\n return JSON.parse(raw) as BaselineFile;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\ntype IssueKey = string;\r\n\r\nfunction issueKey(filePath: string, issue: BaselineIssue): IssueKey {\r\n return `${filePath}::${issue.ruleId}::${issue.line}::${issue.column}::${issue.message}`;\r\n}\r\n\r\nfunction stableIssueKey(filePath: string, issue: BaselineIssue): IssueKey {\r\n return `${filePath}::${issue.ruleId}::${issue.message}`;\r\n}\r\n\r\nfunction buildBaselineSet(baseline: BaselineFile, mode: BaselineMode): Set<IssueKey> {\r\n const toKey = mode === 'stable' ? stableIssueKey : issueKey;\r\n const set = new Set<IssueKey>();\r\n for (const entry of baseline.entries) {\r\n for (const issue of entry.issues) {\r\n set.add(toKey(entry.filePath, issue));\r\n }\r\n }\r\n return set;\r\n}\r\n\r\nfunction computeNewIssues(\r\n result: RunResult,\r\n baselineSet: Set<IssueKey>,\r\n mode: BaselineMode,\r\n): RunResult {\r\n const toKey = mode === 'stable' ? stableIssueKey : issueKey;\r\n const newFiles: RunResult['files'] = [];\r\n let totalErrors = 0;\r\n let totalWarnings = 0;\r\n const ruleBreakdown = new Map<string, number>();\r\n\r\n for (const file of result.files) {\r\n const newIssues = file.issues.filter(\r\n (i) => !baselineSet.has(toKey(file.filePath, i)),\r\n );\r\n if (newIssues.length === 0) continue;\r\n\r\n const errorCount = newIssues.filter((i) => i.severity === 2).length;\r\n const warningCount = newIssues.filter((i) => i.severity === 1).length;\r\n totalErrors += errorCount;\r\n totalWarnings += warningCount;\r\n\r\n for (const issue of newIssues) {\r\n ruleBreakdown.set(\r\n issue.ruleId,\r\n (ruleBreakdown.get(issue.ruleId) ?? 0) + 1,\r\n );\r\n }\r\n\r\n newFiles.push({ ...file, issues: newIssues, errorCount, warningCount });\r\n }\r\n\r\n const topFiles = [...newFiles]\r\n .sort((a, b) => b.issues.length - a.issues.length)\r\n .slice(0, 10)\r\n .map((f) => ({ path: f.filePath, count: f.issues.length }));\r\n\r\n return {\r\n files: newFiles,\r\n totalErrors,\r\n totalWarnings,\r\n totalIssues: totalErrors + totalWarnings,\r\n ruleBreakdown,\r\n topFiles,\r\n durationMs: result.durationMs,\r\n };\r\n}\r\n\r\n// ─── Command ──────────────────────────────────────────────────────────────────\r\n\r\nexport function registerBaselineCommand(program: Command): void {\r\n program\r\n .command('baseline')\r\n .description('Save current issues as baseline; future runs show only new issues')\r\n .option('--save', 'Save current state as the new baseline')\r\n .option('--check', 'Show only issues introduced since the last baseline')\r\n .option('--mode <name>', 'Baseline match mode: strict | stable', 'stable')\r\n .option('--path <dir>', 'Directory to scan', '.')\r\n .option('--preset <name>', 'Preset: recommended | strict | security', 'recommended')\r\n .action(async (opts: {\r\n save?: boolean;\r\n check?: boolean;\r\n mode?: string;\r\n path: string;\r\n preset: string;\r\n }) => {\r\n const cwd = process.cwd();\r\n const preset = (opts.preset as Preset) ?? 'recommended';\r\n const mode = (opts.mode as BaselineMode) ?? 'stable';\r\n\r\n if (mode !== 'strict' && mode !== 'stable') {\r\n log.error('Invalid --mode. Use strict or stable.');\r\n process.exit(1);\r\n }\r\n\r\n log.banner('AI GUARD BASELINE');\r\n log.blank();\r\n\r\n // If neither flag provided, default to --save if no baseline exists, else --check\r\n const existingBaseline = loadBaseline(cwd);\r\n const doSave = opts.save ?? (!existingBaseline && !opts.check);\r\n const doCheck = opts.check ?? (existingBaseline !== null && !opts.save);\r\n\r\n if (doSave) {\r\n log.info('Scanning project to save baseline…');\r\n const spinner = ora({ text: 'Running analysis…', color: 'cyan' }).start();\r\n\r\n let result: RunResult | undefined;\r\n try {\r\n result = await runEslint({ preset, targetPath: opts.path });\r\n spinner.stop();\r\n } catch (err: unknown) {\r\n spinner.stop();\r\n log.error(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n\r\n const baselinePath = saveBaseline(result!, preset, mode, cwd);\r\n log.success(\r\n `Baseline saved → ${chalk.white(path.relative(cwd, baselinePath))}`,\r\n );\r\n log.info(` ${result!.totalIssues} issues recorded (${result!.totalErrors} errors, ${result!.totalWarnings} warnings)`);\r\n log.info(` Preset: ${chalk.cyan(preset)}`);\r\n log.info(` Mode: ${chalk.cyan(mode)}`);\r\n log.blank();\r\n log.info('Future runs of ' + chalk.cyan('ai-guard baseline --check') + ' will show only NEW issues.');\r\n log.info('Add ' + chalk.white(BASELINE_FILE) + ' to your git repository to share baseline with your team.');\r\n log.blank();\r\n return;\r\n }\r\n\r\n if (doCheck) {\r\n if (!existingBaseline) {\r\n log.error(`No baseline found at ${chalk.white(BASELINE_FILE)}`);\r\n log.info(`Run ${chalk.cyan('ai-guard baseline --save')} first to create one.`);\r\n process.exit(1);\r\n }\r\n\r\n const baselineDate = new Date(existingBaseline.createdAt).toLocaleString();\r\n log.info(`Baseline from: ${chalk.gray(baselineDate)}`);\r\n log.info(`Baseline preset: ${chalk.cyan(existingBaseline.preset)}`);\r\n log.info(`Baseline mode: ${chalk.cyan(existingBaseline.mode ?? 'strict')}`);\r\n log.info(`Baseline issues: ${chalk.gray(existingBaseline.totalIssues)}`);\r\n log.blank();\r\n\r\n const spinner = ora({ text: 'Scanning for new issues…', color: 'cyan' }).start();\r\n\r\n let result: RunResult | undefined;\r\n try {\r\n result = await runEslint({ preset, targetPath: opts.path });\r\n spinner.stop();\r\n } catch (err: unknown) {\r\n spinner.stop();\r\n log.error(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n\r\n const compareMode = existingBaseline.mode ?? 'strict';\r\n const baselineSet = buildBaselineSet(existingBaseline!, compareMode);\r\n const newResult = computeNewIssues(result!, baselineSet, compareMode);\r\n\r\n if (newResult.totalIssues === 0) {\r\n log.success('No new issues since baseline! ✨');\r\n log.info(\r\n `Total in codebase: ${result!.totalIssues} (all existing, none new)`,\r\n );\r\n log.blank();\r\n process.exit(0);\r\n return;\r\n }\r\n\r\n log.print(\r\n chalk.bold.red(` ✖ ${newResult.totalIssues} new issue${newResult.totalIssues !== 1 ? 's' : ''} since baseline`),\r\n );\r\n log.blank();\r\n\r\n // By rule breakdown\r\n if (newResult.ruleBreakdown.size > 0) {\r\n log.section('New Issues by Rule');\r\n for (const [rule, count] of [...newResult.ruleBreakdown.entries()].sort(\r\n (a, b) => b[1] - a[1],\r\n )) {\r\n log.rule(rule, count);\r\n }\r\n }\r\n\r\n // Per-file breakdown\r\n if (newResult.files.length > 0) {\r\n log.section('New Issues by File');\r\n log.blank();\r\n for (const file of newResult.files) {\r\n log.print(\r\n ` ${chalk.bold.white(file.filePath)} ` +\r\n chalk.gray(`(${file.issues.length} new)`),\r\n );\r\n for (const issue of file.issues) {\r\n log.issue(issue.message, issue.severity, issue.line, issue.column);\r\n }\r\n }\r\n }\r\n\r\n log.blank();\r\n log.divider();\r\n log.blank();\r\n log.error(\r\n `${newResult.totalIssues} new issue${newResult.totalIssues !== 1 ? 's' : ''} introduced since baseline.`,\r\n );\r\n log.info(`Run ${chalk.cyan('ai-guard baseline --save')} to update the baseline after fixing them.`);\r\n log.blank();\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import type { Command } from 'commander';\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport chalk from 'chalk';\r\nimport { checkbox, confirm } from '@inquirer/prompts';\r\nimport { log } from '../utils/logger.js';\r\n\r\n// ─── Types ────────────────────────────────────────────────────────────────────\r\n\r\ntype AgentId = 'claude' | 'cursor' | 'copilot';\r\n\r\ntype RuleCategory = 'async' | 'security' | 'error-handling' | 'quality';\r\n\r\ninterface AgentTarget {\r\n id: AgentId;\r\n label: string;\r\n filePath: string;\r\n generate: (version: string, categories: RuleCategory[]) => string;\r\n}\r\n\r\n// ─── Rule Category Mapping ────────────────────────────────────────────────────\r\n\r\nconst RULE_CATEGORIES: Record<RuleCategory, string[]> = {\r\n 'error-handling': [\r\n 'no-empty-catch',\r\n 'no-broad-exception',\r\n 'no-catch-log-rethrow',\r\n 'no-catch-without-use',\r\n ],\r\n async: [\r\n 'no-async-array-callback',\r\n 'no-floating-promise',\r\n 'no-await-in-loop',\r\n 'no-async-without-await',\r\n 'no-redundant-await',\r\n ],\r\n security: [\r\n 'no-hardcoded-secret',\r\n 'no-eval-dynamic',\r\n 'no-sql-string-concat',\r\n 'no-unsafe-deserialize',\r\n 'require-auth-middleware',\r\n 'require-authz-check',\r\n ],\r\n quality: [\r\n 'no-console-in-handler',\r\n 'no-duplicate-logic-block',\r\n ],\r\n};\r\n\r\nconst ALL_CATEGORIES: RuleCategory[] = ['error-handling', 'async', 'security', 'quality'];\r\n\r\n// ─── Template Sections ────────────────────────────────────────────────────────\r\n\r\nfunction errorHandlingSection(): string {\r\n return `## Error Handling\r\n**Never** generate empty catch blocks:\r\n ❌ try { await fetchUser() } catch (e) {}\r\n ✅ try { await fetchUser() } catch (e) { logger.error(e); throw e; }\r\n\r\n**Never** catch (e: any) — use specific types or narrow with instanceof.\r\n\r\n**Never** catch, log, and immediately rethrow without adding context:\r\n ❌ catch (e) { console.error(e); throw e; }\r\n ✅ catch (e) { throw new Error('fetchUser failed', { cause: e }); }`;\r\n}\r\n\r\nfunction asyncSection(): string {\r\n return `## Async Correctness\r\n**Never** pass async callbacks to array.map(), filter(), forEach(), or reduce():\r\n ❌ const results = ids.map(async (id) => await fetchUser(id));\r\n ✅ const results = await Promise.all(ids.map((id) => fetchUser(id)));\r\n\r\n**Never** use await inside a for...of or while loop when parallel execution\r\nis possible:\r\n ❌ for (const id of ids) { const user = await fetchUser(id); }\r\n ✅ const users = await Promise.all(ids.map(fetchUser));\r\n\r\n**Never** call an async function without await or .catch():\r\n ❌ sendEmail(user);\r\n ✅ await sendEmail(user);\r\n\r\n**Never** declare a function async if it never uses await.`;\r\n}\r\n\r\nfunction securitySection(): string {\r\n return `## Security\r\n**Never** hardcode secrets, API keys, tokens, or passwords inline:\r\n ❌ const apiKey = 'sk-prod-abc123';\r\n ✅ const apiKey = process.env.API_KEY;\r\n\r\n**Never** concatenate user input into SQL strings:\r\n ❌ db.query('SELECT * FROM users WHERE id = ' + req.params.id);\r\n ✅ db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);\r\n\r\n**Never** use eval() or new Function() with dynamic/user-supplied strings.\r\n\r\n**Never** call JSON.parse() on req.body, req.query, or req.params directly\r\nwithout schema validation.\r\n\r\n**Always** add authentication middleware before route handlers:\r\n ❌ router.get('/admin/users', getUsers);\r\n ✅ router.get('/admin/users', requireAuth, getUsers);\r\n\r\n**Always** verify that the authenticated user owns or has access to the\r\nresource being accessed when using req.params.id or similar identifiers.`;\r\n}\r\n\r\nfunction qualitySection(): string {\r\n return `## Code Quality\r\n**Never** leave console.log or console.debug statements inside HTTP route\r\nhandlers or event listeners in production code.\r\n\r\n**Never** copy-paste the same logic block consecutively — extract shared\r\nlogic into a helper function or consolidate duplicated code.`;\r\n}\r\n\r\ntype SectionFn = () => string;\r\nconst SECTION_MAP: Record<RuleCategory, SectionFn> = {\r\n 'error-handling': errorHandlingSection,\r\n async: asyncSection,\r\n security: securitySection,\r\n quality: qualitySection,\r\n};\r\n\r\nfunction getSections(categories: RuleCategory[]): string {\r\n return categories.map((cat) => SECTION_MAP[cat]()).join('\\n\\n');\r\n}\r\n\r\nfunction workflowGuidanceMarkdown(): string {\r\n return `## Workflow Guardrails\r\n- Follow user and repository instructions first; apply these rules on top.\r\n- Reuse existing project patterns and libraries before introducing new abstractions.\r\n- If a rule must be bypassed intentionally, add a suppression comment with reason:\r\n \\`ai-guard-disable <rule-name> -- reason: <why>\\`.\r\n- Before finalizing changes, run tests/lint and \\`ai-guard run\\` when available.`;\r\n}\r\n\r\nfunction workflowGuidanceCursor(): string {\r\n return `## Workflow Guardrails\r\n\r\n- Follow user and repository instructions first.\r\n- Prefer existing project patterns and dependencies.\r\n- If bypassing a rule intentionally, add: ai-guard-disable <rule-name> -- reason: <why>.\r\n- Validate generated code with tests/lint and ai-guard run when available.`;\r\n}\r\n\r\nfunction workflowGuidanceCopilot(): string {\r\n return `## Required Workflow\r\n\r\n- Follow user and repository instructions first.\r\n- Prefer edits that match existing architecture and dependencies.\r\n- If intentionally violating an ai-guard rule, add an inline suppression with a reason.\r\n- Run tests/lint and \\`ai-guard run\\` before finalizing changes when possible.`;\r\n}\r\n\r\n// ─── CLAUDE.md Template ───────────────────────────────────────────────────────\r\n\r\nfunction generateClaudeFile(version: string, categories: RuleCategory[]): string {\r\n return `<!-- DO NOT EDIT MANUALLY — generated by eslint-plugin-ai-guard -->\r\n<!-- Regenerate: npx ai-guard init-context --force -->\r\n\r\n# AI Guard Rules — Claude Code Instructions\r\n\r\nYou are coding in a project that uses eslint-plugin-ai-guard.\r\nAvoid generating the following patterns. They will be flagged as lint errors.\r\n\r\n${workflowGuidanceMarkdown()}\r\n\r\n${getSections(categories)}\r\n\r\n---\r\nGenerated by eslint-plugin-ai-guard v${version}.\r\nRun \\`npx ai-guard init-context --force\\` to regenerate.\r\n`;\r\n}\r\n\r\n// ─── .cursorrules Template ────────────────────────────────────────────────────\r\n\r\nfunction cursorErrorHandling(): string {\r\n return `## Error Handling\r\n\r\nRule: no-empty-catch\r\nBad: try { await fetchUser() } catch (e) {}\r\nGood: try { await fetchUser() } catch (e) { logger.error(e); throw e; }\r\n\r\nRule: no-broad-exception\r\nBad: catch (e: any) { handle(e); }\r\nGood: catch (e) { if (e instanceof NetworkError) { retry(); } throw e; }\r\n\r\nRule: no-catch-log-rethrow\r\nBad: catch (e) { console.error(e); throw e; }\r\nGood: catch (e) { throw new Error('fetchUser failed', { cause: e }); }`;\r\n}\r\n\r\nfunction cursorAsyncSection(): string {\r\n return `## Async Correctness\r\n\r\nRule: no-async-array-callback\r\nBad: const results = ids.map(async (id) => await fetchUser(id));\r\nGood: const results = await Promise.all(ids.map((id) => fetchUser(id)));\r\n\r\nRule: no-await-in-loop\r\nBad: for (const id of ids) { const user = await fetchUser(id); }\r\nGood: const users = await Promise.all(ids.map(fetchUser));\r\n\r\nRule: no-floating-promise\r\nBad: sendEmail(user);\r\nGood: await sendEmail(user);\r\n\r\nRule: no-async-without-await\r\nBad: async function getUser() { return db.findOne(id); }\r\nGood: function getUser() { return db.findOne(id); }`;\r\n}\r\n\r\nfunction cursorSecuritySection(): string {\r\n return `## Security\r\n\r\nRule: no-hardcoded-secret\r\nBad: const apiKey = 'sk-prod-abc123';\r\nGood: const apiKey = process.env.API_KEY;\r\n\r\nRule: no-sql-string-concat\r\nBad: db.query('SELECT * FROM users WHERE id = ' + req.params.id);\r\nGood: db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);\r\n\r\nRule: no-eval-dynamic\r\nBad: eval(userInput);\r\nGood: Use a safe parser or allowlist approach instead.\r\n\r\nRule: no-unsafe-deserialize\r\nBad: const data = JSON.parse(req.body);\r\nGood: const data = schema.parse(req.body);\r\n\r\nRule: require-auth-middleware\r\nBad: router.get('/admin/users', getUsers);\r\nGood: router.get('/admin/users', requireAuth, getUsers);\r\n\r\nRule: require-authz-check\r\nBad: const user = await db.findById(req.params.id); res.json(user);\r\nGood: const user = await db.findById(req.params.id); if (user.ownerId !== req.user.id) throw new ForbiddenError(); res.json(user);`;\r\n}\r\n\r\nfunction cursorQualitySection(): string {\r\n return `## Code Quality\r\n\r\nRule: no-console-in-handler\r\nBad: router.get('/users', (req, res) => { console.log('hit'); ... });\r\nGood: router.get('/users', (req, res) => { logger.info('hit'); ... });\r\n\r\nRule: no-duplicate-logic-block\r\nBad: Two identical consecutive code blocks copy-pasted.\r\nGood: Extract the duplicated logic into a shared helper function.`;\r\n}\r\n\r\nconst CURSOR_SECTION_MAP: Record<RuleCategory, () => string> = {\r\n 'error-handling': cursorErrorHandling,\r\n async: cursorAsyncSection,\r\n security: cursorSecuritySection,\r\n quality: cursorQualitySection,\r\n};\r\n\r\nfunction generateCursorFile(version: string, categories: RuleCategory[]): string {\r\n const sections = categories.map((cat) => CURSOR_SECTION_MAP[cat]()).join('\\n\\n');\r\n\r\n return `# AI Guard Rules — Cursor Instructions\r\n# DO NOT EDIT MANUALLY — generated by eslint-plugin-ai-guard\r\n# Regenerate: npx ai-guard init-context --force\r\n\r\nThis project uses eslint-plugin-ai-guard to catch the 17 most common\r\nanti-patterns generated by AI coding tools. Follow these rules when\r\ngenerating or editing code in this project. Violations will be flagged\r\nas lint errors.\r\n\r\n${workflowGuidanceCursor()}\r\n\r\n${sections}\r\n\r\n---\r\nThese rules mirror eslint-plugin-ai-guard v${version}.\r\nRun \\`npx ai-guard init-context --force\\` to regenerate.\r\n`;\r\n}\r\n\r\n// ─── .github/copilot-instructions.md Template ─────────────────────────────────\r\n\r\nfunction copilotQuickRef(categories: RuleCategory[]): string {\r\n const lines: string[] = [];\r\n\r\n if (categories.includes('error-handling')) {\r\n lines.push(\r\n 'Never: generate empty catch blocks',\r\n 'Never: catch (e: any) without narrowing',\r\n 'Never: catch, log, and rethrow without adding context',\r\n );\r\n }\r\n if (categories.includes('async')) {\r\n lines.push(\r\n 'Never: pass async callbacks to .map(), .filter(), .forEach()',\r\n 'Never: use await inside loops when Promise.all() works',\r\n 'Never: call async functions without await or .catch()',\r\n 'Never: mark functions async if they never await',\r\n );\r\n }\r\n if (categories.includes('security')) {\r\n lines.push(\r\n 'Never: hardcode API keys, secrets, or passwords',\r\n 'Never: concatenate user input into SQL strings',\r\n 'Never: use eval() or new Function() with dynamic input',\r\n 'Never: JSON.parse() untrusted input without validation',\r\n 'Always: add auth middleware before route handlers',\r\n 'Always: verify resource ownership in handlers',\r\n );\r\n }\r\n if (categories.includes('quality')) {\r\n lines.push(\r\n 'Never: leave console.log in route handlers',\r\n 'Never: copy-paste identical consecutive code blocks',\r\n );\r\n }\r\n\r\n return lines.map((l) => `- ${l}`).join('\\n');\r\n}\r\n\r\nfunction copilotDetails(categories: RuleCategory[]): string {\r\n const details: string[] = [];\r\n\r\n if (categories.includes('async')) {\r\n details.push(`### no-floating-promise\r\n\\`\\`\\`typescript\r\n// ❌ Bad — promise rejected silently\r\nsendEmail(user);\r\n\r\n// ✅ Good\r\nawait sendEmail(user);\r\n\\`\\`\\``);\r\n\r\n details.push(`### no-async-array-callback\r\n\\`\\`\\`typescript\r\n// ❌ Bad — returns Promise[], not values\r\nids.map(async (id) => await fetchUser(id));\r\n\r\n// ✅ Good\r\nawait Promise.all(ids.map((id) => fetchUser(id)));\r\n\\`\\`\\``);\r\n }\r\n\r\n if (categories.includes('error-handling')) {\r\n details.push(`### no-empty-catch\r\n\\`\\`\\`typescript\r\n// ❌ Bad — error swallowed silently\r\ntry { await fetchUser() } catch (e) {}\r\n\r\n// ✅ Good\r\ntry { await fetchUser() } catch (e) { logger.error(e); throw e; }\r\n\\`\\`\\``);\r\n }\r\n\r\n if (categories.includes('security')) {\r\n details.push(`### no-hardcoded-secret\r\n\\`\\`\\`typescript\r\n// ❌ Bad\r\nconst apiKey = 'sk-prod-abc123';\r\n\r\n// ✅ Good\r\nconst apiKey = process.env.API_KEY;\r\n\\`\\`\\``);\r\n\r\n details.push(`### no-sql-string-concat\r\n\\`\\`\\`typescript\r\n// ❌ Bad — SQL injection\r\ndb.query('SELECT * FROM users WHERE id = ' + req.params.id);\r\n\r\n// ✅ Good\r\ndb.query('SELECT * FROM users WHERE id = $1', [req.params.id]);\r\n\\`\\`\\``);\r\n }\r\n\r\n return details.join('\\n\\n');\r\n}\r\n\r\nfunction generateCopilotFile(version: string, categories: RuleCategory[]): string {\r\n return `<!-- DO NOT EDIT MANUALLY — generated by eslint-plugin-ai-guard -->\r\n<!-- Regenerate: npx ai-guard init-context --force -->\r\n\r\n# AI Guard — GitHub Copilot Instructions\r\n\r\nThis project uses \\`eslint-plugin-ai-guard\\`. Follow these rules to avoid\r\ngenerating patterns that will be flagged as lint errors.\r\n\r\n${workflowGuidanceCopilot()}\r\n\r\n## Quick Reference\r\n\r\n${copilotQuickRef(categories)}\r\n\r\n## Details\r\n\r\n${copilotDetails(categories)}\r\n\r\n---\r\nGenerated by eslint-plugin-ai-guard v${version}.\r\nRun \\`npx ai-guard init-context --force\\` to regenerate.\r\n`;\r\n}\r\n\r\n// ─── Agent Definitions ────────────────────────────────────────────────────────\r\n\r\nconst AGENTS: AgentTarget[] = [\r\n {\r\n id: 'claude',\r\n label: 'Claude Code',\r\n filePath: 'CLAUDE.md',\r\n generate: generateClaudeFile,\r\n },\r\n {\r\n id: 'cursor',\r\n label: 'Cursor',\r\n filePath: '.cursorrules',\r\n generate: generateCursorFile,\r\n },\r\n {\r\n id: 'copilot',\r\n label: 'GitHub Copilot',\r\n filePath: path.join('.github', 'copilot-instructions.md'),\r\n generate: generateCopilotFile,\r\n },\r\n];\r\n\r\n// ─── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\nfunction getPackageVersion(cwd: string): string {\r\n try {\r\n const pkgPath = path.join(cwd, 'node_modules', 'eslint-plugin-ai-guard', 'package.json');\r\n if (fs.existsSync(pkgPath)) {\r\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { version?: string };\r\n if (pkg.version) return pkg.version;\r\n }\r\n } catch { /* fall through */ }\r\n\r\n try {\r\n const pkgPath = path.join(cwd, 'package.json');\r\n if (fs.existsSync(pkgPath)) {\r\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { version?: string };\r\n if (pkg.version) return pkg.version;\r\n }\r\n } catch { /* fall through */ }\r\n\r\n return '0.0.0';\r\n}\r\n\r\nfunction parseCategories(raw: string | undefined): RuleCategory[] {\r\n if (!raw) return ALL_CATEGORIES;\r\n const parts = raw.split(',').map((s) => s.trim().toLowerCase());\r\n const valid: RuleCategory[] = [];\r\n for (const part of parts) {\r\n if (part in RULE_CATEGORIES) {\r\n valid.push(part as RuleCategory);\r\n }\r\n }\r\n return valid.length > 0 ? valid : ALL_CATEGORIES;\r\n}\r\n\r\nfunction normalizeSelectedAgents(raw: unknown): string[] {\r\n if (Array.isArray(raw)) {\r\n return raw.filter((value): value is string => typeof value === 'string');\r\n }\r\n\r\n if (typeof raw === 'string') {\r\n return [raw];\r\n }\r\n\r\n return [];\r\n}\r\n\r\n// ─── Exported for tests ───────────────────────────────────────────────────────\r\n\r\nexport {\r\n generateClaudeFile,\r\n generateCursorFile,\r\n generateCopilotFile,\r\n parseCategories,\r\n normalizeSelectedAgents,\r\n AGENTS,\r\n ALL_CATEGORIES,\r\n};\r\nexport type { AgentTarget, RuleCategory };\r\n\r\n// ─── Command Registration ────────────────────────────────────────────────────\r\n\r\nexport function registerInitContextCommand(program: Command): void {\r\n program\r\n .command('init-context')\r\n .description(\r\n 'Generate AI agent instruction files (CLAUDE.md, .cursorrules, copilot-instructions.md)\\n' +\r\n 'so Claude Code, Cursor, and GitHub Copilot avoid the 17 most common AI anti-patterns.',\r\n )\r\n .option('-a, --all', 'Generate files for all agents (skip prompt)')\r\n .option('--force', 'Overwrite existing files without asking')\r\n .option('--dry-run', 'Print what would be generated without writing files')\r\n .option('--rules <categories>', 'Comma-separated categories: async,security,error-handling,quality')\r\n .action(async (opts: {\r\n all?: boolean;\r\n force?: boolean;\r\n dryRun?: boolean;\r\n rules?: string;\r\n }) => {\r\n const cwd = process.cwd();\r\n const version = getPackageVersion(cwd);\r\n const categories = parseCategories(opts.rules);\r\n const isDryRun = opts.dryRun === true;\r\n const isForce = opts.force === true;\r\n\r\n log.banner('AI GUARD INIT-CONTEXT');\r\n\r\n if (isDryRun) {\r\n log.print(` ${chalk.yellow('⚑ DRY RUN — no files will be written')}`);\r\n log.blank();\r\n }\r\n\r\n // ── Select agents ──────────────────────────────────────────────────────\r\n\r\n let selectedAgents: AgentTarget[];\r\n\r\n if (opts.all) {\r\n selectedAgents = [...AGENTS];\r\n } else {\r\n let selected: string[];\r\n try {\r\n selected = await checkbox({\r\n message: 'Which AI agents do you use?',\r\n choices: [\r\n { name: 'Claude Code -> writes CLAUDE.md', value: 'claude' },\r\n { name: 'Cursor -> writes .cursorrules', value: 'cursor' },\r\n { name: 'GitHub Copilot -> writes .github/copilot-instructions.md', value: 'copilot' },\r\n { name: 'All three (recommended) -> writes all files', value: 'all' },\r\n ],\r\n required: true,\r\n });\r\n } catch {\r\n log.info('Selection cancelled. Nothing to do.');\r\n return;\r\n }\r\n\r\n if (selected.length === 0) {\r\n log.info('No valid agents selected. Use --all to generate all files.');\r\n return;\r\n }\r\n\r\n if (selected.includes('all')) {\r\n selectedAgents = [...AGENTS];\r\n } else {\r\n selectedAgents = AGENTS.filter((a) => selected.includes(a.id));\r\n }\r\n }\r\n\r\n log.info(`Categories: ${chalk.cyan(categories.join(', '))}`);\r\n log.info(`Version: ${chalk.cyan(version)}`);\r\n log.blank();\r\n\r\n // ── Generate files ─────────────────────────────────────────────────────\r\n\r\n const results: { file: string; status: 'created' | 'skipped' | 'dry-run' }[] = [];\r\n\r\n for (const agent of selectedAgents) {\r\n const fullPath = path.join(cwd, agent.filePath);\r\n const exists = fs.existsSync(fullPath);\r\n\r\n if (exists && !isForce && !isDryRun) {\r\n // Ask to overwrite\r\n const overwrite = await confirm({\r\n message: `${agent.filePath} already exists. Overwrite?`,\r\n default: false,\r\n });\r\n\r\n if (!overwrite) {\r\n results.push({ file: agent.filePath, status: 'skipped' });\r\n continue;\r\n }\r\n }\r\n\r\n const content = agent.generate(version, categories);\r\n\r\n if (isDryRun) {\r\n log.section(`Preview: ${agent.filePath}`);\r\n log.print(chalk.gray('─'.repeat(60)));\r\n for (const line of content.split('\\n').slice(0, 20)) {\r\n log.print(chalk.gray(` ${line}`));\r\n }\r\n log.print(chalk.gray(' ... (truncated)'));\r\n log.print(chalk.gray('─'.repeat(60)));\r\n log.blank();\r\n results.push({ file: agent.filePath, status: 'dry-run' });\r\n continue;\r\n }\r\n\r\n // Ensure parent directory exists (for .github/copilot-instructions.md)\r\n const parentDir = path.dirname(fullPath);\r\n if (!fs.existsSync(parentDir)) {\r\n fs.mkdirSync(parentDir, { recursive: true });\r\n }\r\n\r\n fs.writeFileSync(fullPath, content, 'utf-8');\r\n results.push({ file: agent.filePath, status: 'created' });\r\n }\r\n\r\n // ── Summary ────────────────────────────────────────────────────────────\r\n\r\n log.section('Summary');\r\n\r\n for (const result of results) {\r\n switch (result.status) {\r\n case 'created':\r\n log.print(` ${chalk.green('✅')} Created ${chalk.white(result.file)}`);\r\n break;\r\n case 'skipped':\r\n log.print(` ${chalk.yellow('⏭')} Skipped ${chalk.white(result.file)} ${chalk.gray('(already exists — use --force to overwrite)')}`);\r\n break;\r\n case 'dry-run':\r\n log.print(` ${chalk.cyan('📝')} Would create ${chalk.white(result.file)}`);\r\n break;\r\n }\r\n }\r\n\r\n log.blank();\r\n\r\n if (isDryRun) {\r\n log.info('Dry run complete — no files were written.');\r\n log.info(`Re-run without ${chalk.cyan('--dry-run')} to apply.`);\r\n } else {\r\n const createdCount = results.filter((r) => r.status === 'created').length;\r\n if (createdCount > 0) {\r\n log.success(\r\n 'Done. Your AI agents will now automatically avoid the 17 most common AI-generated code anti-patterns.',\r\n );\r\n }\r\n }\r\n\r\n log.blank();\r\n });\r\n}\r\n","import type { Command } from 'commander';\nimport fs from 'fs';\nimport path from 'path';\nimport ora from 'ora';\nimport { runEslint, type RunResult } from '../utils/eslint-runner.js';\nimport { log } from '../utils/logger.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReportData {\n projectName: string;\n version: string;\n generatedAt: string;\n preset: string;\n scannedPath: string;\n durationMs: number;\n totalIssues: number;\n totalErrors: number;\n totalWarnings: number;\n score: number;\n ruleBreakdown: Record<string, number>;\n topFiles: Array<{ path: string; count: number; errors: number; warnings: number }>;\n topRules: Array<{\n rule: string;\n count: number;\n description: string;\n category: string;\n example: { file: string; line: number; column: number; message: string } | null;\n }>;\n categoryBreakdown: Record<string, number>;\n // Confidence tier breakdown\n highCount: number;\n mediumCount: number;\n lowCount: number;\n ecosystemCount: number;\n parserErrorCount: number;\n}\n\n// ─── Rule Metadata ────────────────────────────────────────────────────────────\n\nconst RULE_META: Record<string, { description: string; category: string }> = {\n 'ai-guard/no-empty-catch': { description: 'Empty catch blocks silently swallow errors', category: 'Reliability' },\n 'ai-guard/no-broad-exception': { description: 'Catching all exceptions hides bugs', category: 'Reliability' },\n 'ai-guard/no-catch-log-rethrow': { description: 'Catch-log-rethrow adds noise without context', category: 'Reliability' },\n 'ai-guard/no-catch-without-use': { description: 'Caught error is not used', category: 'Reliability' },\n 'ai-guard/no-floating-promise': { description: 'Unhandled promise can crash silently', category: 'Async Stability' },\n 'ai-guard/no-await-in-loop': { description: 'Sequential await in loops is slow; use Promise.all', category: 'Async Stability' },\n 'ai-guard/no-async-array-callback': { description: 'Async callbacks in .map()/.filter() return Promises', category: 'Async Stability' },\n 'ai-guard/no-async-without-await': { description: 'Async function never uses await', category: 'Async Stability' },\n 'ai-guard/no-redundant-await': { description: 'Redundant await in return position', category: 'Async Stability' },\n 'ai-guard/no-hardcoded-secret': { description: 'Secrets should come from environment variables', category: 'Security' },\n 'ai-guard/no-eval-dynamic': { description: 'eval() with dynamic input is a security risk', category: 'Security' },\n 'ai-guard/no-sql-string-concat': { description: 'SQL string concatenation enables injection', category: 'Security' },\n 'ai-guard/no-unsafe-deserialize': { description: 'JSON.parse on untrusted input without validation', category: 'Security' },\n 'ai-guard/require-auth-middleware': { description: 'Route handler missing authentication middleware', category: 'Security' },\n 'ai-guard/require-authz-check': { description: 'Missing authorization check for resource access', category: 'Security' },\n 'ai-guard/no-console-in-handler': { description: 'console.log in route handlers should be a logger', category: 'AI Patterns' },\n 'ai-guard/no-duplicate-logic-block': { description: 'Duplicate consecutive code blocks should be extracted', category: 'AI Patterns' },\n 'ai-guard/no-dead-branch': { description: 'Always-true/false condition creates dead or unreachable code', category: 'AI Patterns' },\n};\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction getProjectName(cwd: string): string {\n try {\n const pkgPath = path.join(cwd, 'package.json');\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { name?: string };\n if (pkg.name) return pkg.name;\n }\n } catch { /* fall through */ }\n return path.basename(cwd);\n}\n\nfunction getPluginVersion(cwd: string): string {\n try {\n const pkgPath = path.resolve(__dirname, '../../package.json');\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { version?: string };\n if (pkg.version) return pkg.version;\n }\n } catch { /* fall through */ }\n try {\n const pkgPath = path.join(cwd, 'node_modules', 'eslint-plugin-ai-guard', 'package.json');\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { version?: string };\n if (pkg.version) return pkg.version;\n }\n } catch { /* fall through */ }\n return '0.0.0';\n}\n\nfunction calculateScore(totalErrors: number, totalWarnings: number): number {\n // Errors cost 5 points each, warnings cost 2 points each, min 0\n const penalty = totalErrors * 5 + totalWarnings * 2;\n return Math.max(0, Math.min(100, 100 - penalty));\n}\n\n// ─── Report Data Builder ──────────────────────────────────────────────────────\n\nexport function buildReportData(\n result: RunResult,\n preset: string,\n scannedPath: string,\n cwd: string,\n): ReportData {\n const projectName = getProjectName(cwd);\n const version = getPluginVersion(cwd);\n const score = calculateScore(result.totalErrors, result.totalWarnings);\n\n // Top files with error/warning breakdown\n const topFiles = result.files\n .sort((a, b) => b.issues.length - a.issues.length)\n .slice(0, 10)\n .map((f) => ({\n path: f.filePath,\n count: f.issues.length,\n errors: f.errorCount,\n warnings: f.warningCount,\n }));\n\n // Category breakdown\n const categoryBreakdown: Record<string, number> = {};\n for (const [rule, count] of result.ruleBreakdown.entries()) {\n const cat = RULE_META[rule]?.category ?? 'Other';\n categoryBreakdown[cat] = (categoryBreakdown[cat] ?? 0) + count;\n }\n\n // Top 5 rules with real examples\n const sortedRules = [...result.ruleBreakdown.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5);\n\n const topRules = sortedRules.map(([rule, count]) => {\n const meta = RULE_META[rule] ?? { description: 'Rule violation', category: 'Other' };\n\n // Find a real example from the codebase\n let example: { file: string; line: number; column: number; message: string } | null = null;\n for (const file of result.files) {\n const issue = file.issues.find((i) => i.ruleId === rule);\n if (issue) {\n example = {\n file: file.filePath,\n line: issue.line,\n column: issue.column,\n message: issue.message,\n };\n break;\n }\n }\n\n return {\n rule: rule.replace(/^ai-guard\\//, ''),\n count,\n description: meta.description,\n category: meta.category,\n example,\n };\n });\n\n // Confidence tiers for display (computed from rule assignment)\n const CONFIDENCE_ASSIGNMENT: Record<string, 'high' | 'medium' | 'low'> = {\n 'ai-guard/no-hardcoded-secret': 'high',\n 'ai-guard/no-eval-dynamic': 'high',\n 'ai-guard/no-floating-promise': 'high',\n 'ai-guard/no-empty-catch': 'high',\n 'ai-guard/no-sql-string-concat': 'medium',\n 'ai-guard/no-await-in-loop': 'medium',\n 'ai-guard/require-auth-middleware': 'medium',\n 'ai-guard/require-authz-check': 'medium',\n 'ai-guard/no-catch-log-rethrow': 'medium',\n 'ai-guard/no-catch-without-use': 'medium',\n 'ai-guard/no-unsafe-deserialize': 'medium',\n 'ai-guard/no-async-without-await': 'low',\n 'ai-guard/no-async-array-callback': 'low',\n 'ai-guard/no-dead-branch': 'low',\n 'ai-guard/no-broad-exception': 'low',\n 'ai-guard/no-console-in-handler': 'low',\n 'ai-guard/no-duplicate-logic-block': 'low',\n 'ai-guard/no-redundant-await': 'low',\n };\n let highCount = 0;\n let mediumCount = 0;\n let lowCount = 0;\n for (const [rule, count] of result.ruleBreakdown.entries()) {\n const tier = CONFIDENCE_ASSIGNMENT[rule] ?? 'low';\n if (tier === 'high') highCount += count;\n else if (tier === 'medium') mediumCount += count;\n else lowCount += count;\n }\n const ecosystemCount = result.ecosystemIssues?.length ?? 0;\n const parserErrorCount = result.parserErrors?.length ?? 0;\n\n return {\n projectName,\n version,\n generatedAt: new Date().toISOString(),\n preset,\n scannedPath,\n durationMs: result.durationMs,\n totalIssues: result.totalIssues,\n totalErrors: result.totalErrors,\n totalWarnings: result.totalWarnings,\n score,\n ruleBreakdown: Object.fromEntries(result.ruleBreakdown),\n topFiles,\n topRules,\n categoryBreakdown,\n highCount,\n mediumCount,\n lowCount,\n ecosystemCount,\n parserErrorCount,\n };\n}\n\n// ─── HTML Template ────────────────────────────────────────────────────────────\n\nexport function generateHtml(data: ReportData): string {\n const scoreColor = data.score >= 80 ? '#10b981' : data.score >= 50 ? '#f59e0b' : '#ef4444';\n const scoreLabel = data.score >= 80 ? 'Great' : data.score >= 50 ? 'Needs Work' : 'Critical';\n const formattedDate = new Date(data.generatedAt).toLocaleString();\n\n const topFilesRows = data.topFiles.length === 0\n ? `<tr><td colspan=\"4\" style=\"text-align:center;color:#6b7280;padding:2rem;\">No issues found</td></tr>`\n : data.topFiles.map((f) => {\n const heatColor = f.errors > 0\n ? `rgba(239,68,68,${Math.min(0.9, 0.2 + f.errors * 0.1)})`\n : `rgba(245,158,11,${Math.min(0.9, 0.2 + f.warnings * 0.05)})`;\n return `\n <tr style=\"border-bottom:1px solid #1f2937;\">\n <td style=\"padding:0.75rem 1rem;font-family:monospace;font-size:0.8rem;color:#e5e7eb;max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\" title=\"${escHtml(f.path)}\">${escHtml(f.path)}</td>\n <td style=\"padding:0.75rem 1rem;text-align:center;\"><span style=\"background:${heatColor};border-radius:9999px;padding:0.2rem 0.7rem;font-weight:600;font-size:0.85rem;\">${f.count}</span></td>\n <td style=\"padding:0.75rem 1rem;text-align:center;color:#f87171;\">${f.errors}</td>\n <td style=\"padding:0.75rem 1rem;text-align:center;color:#fbbf24;\">${f.warnings}</td>\n </tr>`;\n }).join('');\n\n const topRulesCards = data.topRules.length === 0\n ? `<div style=\"text-align:center;color:#6b7280;padding:2rem;\">No rules fired — clean codebase!</div>`\n : data.topRules.map((r, i) => {\n const catColor: Record<string, string> = {\n 'Reliability': '#ec4899', 'Async Stability': '#8b5cf6',\n 'Security': '#ef4444', 'AI Patterns': '#14b8a6', Other: '#6b7280',\n };\n const color = catColor[r.category] ?? '#6b7280';\n const exampleHtml = r.example\n ? `<div style=\"margin-top:0.75rem;background:#0f172a;border-radius:0.5rem;padding:0.75rem;border-left:3px solid ${color};\">\n <div style=\"font-size:0.75rem;color:#94a3b8;margin-bottom:0.35rem;\">${escHtml(r.example.file)}:${r.example.line}:${r.example.column}</div>\n <code style=\"font-size:0.8rem;color:#f1f5f9;white-space:pre-wrap;word-break:break-all;\">${escHtml(r.example.message)}</code>\n </div>`\n : '';\n return `\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;display:flex;flex-direction:column;gap:0.5rem;\">\n <div style=\"display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:0.5rem;\">\n <div style=\"display:flex;align-items:center;gap:0.75rem;\">\n <span style=\"background:#1f2937;color:#9ca3af;font-size:0.75rem;padding:0.15rem 0.5rem;border-radius:9999px;\">#${i + 1}</span>\n <code style=\"font-size:0.9rem;color:#f9fafb;font-weight:600;\">${escHtml(r.rule)}</code>\n </div>\n <div style=\"display:flex;align-items:center;gap:0.5rem;\">\n <span style=\"background:${color}22;color:${color};border:1px solid ${color}44;font-size:0.72rem;border-radius:9999px;padding:0.15rem 0.6rem;\">${escHtml(r.category)}</span>\n <span style=\"background:#374151;color:#e5e7eb;font-size:0.8rem;border-radius:9999px;padding:0.2rem 0.7rem;font-weight:600;\">${r.count}×</span>\n </div>\n </div>\n <p style=\"color:#9ca3af;font-size:0.85rem;margin:0;\">${escHtml(r.description)}</p>\n ${exampleHtml}\n </div>`;\n }).join('');\n\n const categoryCards = Object.entries(data.categoryBreakdown).map(([cat, count]) => {\n const catColor: Record<string, string> = {\n 'Reliability': '#ec4899', 'Async Stability': '#8b5cf6',\n 'Security': '#ef4444', 'AI Patterns': '#14b8a6', Other: '#6b7280',\n };\n const color = catColor[cat] ?? '#6b7280';\n return `\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;display:flex;flex-direction:column;gap:0.5rem;\">\n <div style=\"font-size:0.8rem;color:#9ca3af;\">${escHtml(cat)}</div>\n <div style=\"font-size:2rem;font-weight:700;color:${color};\">${count}</div>\n <div style=\"background:#1f2937;border-radius:9999px;height:4px;overflow:hidden;\"><div style=\"background:${color};height:100%;width:${Math.min(100, (count / Math.max(data.totalIssues, 1)) * 100)}%;transition:width 0.8s ease;\"></div></div>\n </div>`;\n }).join('');\n\n const cleanBanner = data.totalIssues === 0\n ? `<div style=\"background:#064e3b;border:1px solid #10b981;border-radius:1rem;padding:2rem;text-align:center;margin-bottom:2rem;\">\n <div style=\"font-size:2.5rem;\">🎉</div>\n <div style=\"font-size:1.5rem;font-weight:700;color:#10b981;margin:0.5rem 0;\">Clean Codebase!</div>\n <div style=\"color:#6ee7b7;\">No AI guard issues detected. Your code is production-ready.</div>\n </div>`\n : '';\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>AI Guard Report — ${escHtml(data.projectName)}</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { background: #030712; color: #f9fafb; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; min-height: 100vh; }\n @keyframes pulse-score { 0%, 100% { opacity: 1; } 50% { opacity: 0.8; } }\n @keyframes slide-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }\n .card { animation: slide-in 0.4s ease both; }\n ::-webkit-scrollbar { width: 6px; height: 6px; }\n ::-webkit-scrollbar-track { background: #111827; }\n ::-webkit-scrollbar-thumb { background: #374151; border-radius: 3px; }\n </style>\n</head>\n<body>\n\n<!-- ── Header ── -->\n<header style=\"background:linear-gradient(135deg,#0f172a 0%,#1e1b4b 50%,#0f172a 100%);border-bottom:1px solid #1f2937;padding:2rem 2rem 1.5rem;\">\n <div style=\"max-width:1100px;margin:0 auto;\">\n <div style=\"display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;\">\n <div>\n <div style=\"display:flex;align-items:center;gap:0.75rem;margin-bottom:0.4rem;\">\n <span style=\"font-size:1.5rem;\">🛡️</span>\n <span style=\"font-size:0.85rem;color:#818cf8;font-weight:600;letter-spacing:0.05em;\">AI GUARD REPORT</span>\n </div>\n <h1 style=\"font-size:1.8rem;font-weight:700;color:#f9fafb;\">${escHtml(data.projectName)}</h1>\n <p style=\"color:#6b7280;font-size:0.85rem;margin-top:0.25rem;\">Scanned: <code style=\"color:#94a3b8;\">${escHtml(data.scannedPath)}</code> · Preset: <code style=\"color:#94a3b8;\">${escHtml(data.preset)}</code> · ${data.durationMs}ms</p>\n </div>\n <div style=\"text-align:center;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.75rem;letter-spacing:0.05em;\">SIGNAL CONFIDENCE</div>\n <div style=\"display:flex;flex-direction:column;gap:0.4rem;\">\n <div style=\"display:flex;align-items:center;gap:0.5rem;\">\n <span style=\"width:8px;height:8px;border-radius:50%;background:#ef4444;display:inline-block;\"></span>\n <span style=\"font-size:0.8rem;color:#f87171;font-weight:600;\">${data.highCount} high-confidence</span>\n </div>\n <div style=\"display:flex;align-items:center;gap:0.5rem;\">\n <span style=\"width:8px;height:8px;border-radius:50%;background:#f59e0b;display:inline-block;\"></span>\n <span style=\"font-size:0.8rem;color:#fbbf24;font-weight:600;\">${data.mediumCount} medium-confidence</span>\n </div>\n <div style=\"display:flex;align-items:center;gap:0.5rem;\">\n <span style=\"width:8px;height:8px;border-radius:50%;background:#6b7280;display:inline-block;\"></span>\n <span style=\"font-size:0.8rem;color:#9ca3af;font-weight:600;\">${data.lowCount} suggestions</span>\n </div>\n ${data.ecosystemCount > 0 ? `<div style=\"display:flex;align-items:center;gap:0.5rem;margin-top:0.25rem;\">\n <span style=\"font-size:0.75rem;color:#4b5563;\">⚠ ${data.ecosystemCount} config issue${data.ecosystemCount !== 1 ? 's' : ''} (not ai-guard)</span>\n </div>` : ''}\n </div>\n </div>\n </div>\n <p style=\"color:#4b5563;font-size:0.75rem;margin-top:1rem;\">Generated ${escHtml(formattedDate)}</p>\n </div>\n</header>\n\n<!-- ── Main ── -->\n<main style=\"max-width:1100px;margin:0 auto;padding:2rem;\">\n\n ${cleanBanner}\n\n <!-- Summary Cards -->\n <div class=\"card\" style=\"display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:1rem;margin-bottom:2rem;\">\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">TOTAL ISSUES</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#f9fafb;\">${data.totalIssues}</div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">ERRORS</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#f87171;\">${data.totalErrors}</div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">WARNINGS</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#fbbf24;\">${data.totalWarnings}</div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">FILES AFFECTED</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#818cf8;\">${data.topFiles.length}</div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">RULES FIRED</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#34d399;\">${Object.keys(data.ruleBreakdown).length}</div>\n </div>\n </div>\n\n <!-- Issues by Category -->\n ${Object.keys(data.categoryBreakdown).length > 0 ? `\n <section class=\"card\" style=\"margin-bottom:2rem;\">\n <h2 style=\"font-size:1rem;font-weight:600;color:#e5e7eb;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem;\">\n <span>📊</span> Issues by Category\n </h2>\n <div style=\"display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1rem;\">\n ${categoryCards}\n </div>\n </section>` : ''}\n\n <!-- Severity Heatmap by File -->\n <section class=\"card\" style=\"margin-bottom:2rem;\">\n <h2 style=\"font-size:1rem;font-weight:600;color:#e5e7eb;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem;\">\n <span>🔥</span> Severity Heatmap — Top Files\n </h2>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;overflow:hidden;\">\n <table style=\"width:100%;border-collapse:collapse;\">\n <thead>\n <tr style=\"background:#0f172a;text-align:left;\">\n <th style=\"padding:0.75rem 1rem;font-size:0.75rem;color:#6b7280;font-weight:500;letter-spacing:0.05em;\">FILE</th>\n <th style=\"padding:0.75rem 1rem;font-size:0.75rem;color:#6b7280;font-weight:500;letter-spacing:0.05em;text-align:center;\">ISSUES</th>\n <th style=\"padding:0.75rem 1rem;font-size:0.75rem;color:#6b7280;font-weight:500;letter-spacing:0.05em;text-align:center;\">ERRORS</th>\n <th style=\"padding:0.75rem 1rem;font-size:0.75rem;color:#6b7280;font-weight:500;letter-spacing:0.05em;text-align:center;\">WARNINGS</th>\n </tr>\n </thead>\n <tbody>\n ${topFilesRows}\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- Top 5 Rules -->\n <section class=\"card\" style=\"margin-bottom:2rem;\">\n <h2 style=\"font-size:1rem;font-weight:600;color:#e5e7eb;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem;\">\n <span>⚡</span> Top Rules That Fired\n </h2>\n <div style=\"display:flex;flex-direction:column;gap:1rem;\">\n ${topRulesCards}\n </div>\n </section>\n\n <!-- Next Steps -->\n <section class=\"card\" style=\"margin-bottom:2rem;\">\n <h2 style=\"font-size:1rem;font-weight:600;color:#e5e7eb;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem;\">\n <span>🚀</span> Suggested Next Steps\n </h2>\n <div style=\"display:flex;flex-direction:column;gap:0.75rem;\">\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1rem;display:flex;align-items:flex-start;gap:0.75rem;\">\n <span style=\"font-size:1.2rem;flex-shrink:0;\">🔧</span>\n <div>\n <div style=\"color:#f9fafb;font-size:0.9rem;font-weight:500;margin-bottom:0.2rem;\">Auto-fix safe issues</div>\n <code style=\"color:#818cf8;font-size:0.8rem;\">npx ai-guard run --fix</code>\n </div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1rem;display:flex;align-items:flex-start;gap:0.75rem;\">\n <span style=\"font-size:1.2rem;flex-shrink:0;\">🤖</span>\n <div>\n <div style=\"color:#f9fafb;font-size:0.9rem;font-weight:500;margin-bottom:0.2rem;\">Prevent future AI-generated issues</div>\n <code style=\"color:#818cf8;font-size:0.8rem;\">npx ai-guard init-context</code>\n </div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1rem;display:flex;align-items:flex-start;gap:0.75rem;\">\n <span style=\"font-size:1.2rem;flex-shrink:0;\">📋</span>\n <div>\n <div style=\"color:#f9fafb;font-size:0.9rem;font-weight:500;margin-bottom:0.2rem;\">Save baseline &amp; track only new issues</div>\n <code style=\"color:#818cf8;font-size:0.8rem;\">npx ai-guard baseline</code>\n </div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1rem;display:flex;align-items:flex-start;gap:0.75rem;\">\n <span style=\"font-size:1.2rem;flex-shrink:0;\">📤</span>\n <div>\n <div style=\"color:#f9fafb;font-size:0.9rem;font-weight:500;margin-bottom:0.2rem;\">Share this report with your team</div>\n <div style=\"color:#6b7280;font-size:0.8rem;\">Send the <code style=\"color:#94a3b8;\">ai-guard-report.html</code> file — it's fully self-contained.</div>\n </div>\n </div>\n </div>\n </section>\n\n</main>\n\n<!-- ── Footer ── -->\n<footer style=\"border-top:1px solid #1f2937;padding:1.5rem 2rem;text-align:center;\">\n <p style=\"color:#4b5563;font-size:0.8rem;\">\n Generated by <a href=\"https://github.com/YashJadhav21/eslint-plugin-ai-guard\" style=\"color:#818cf8;text-decoration:none;\">eslint-plugin-ai-guard</a> v${escHtml(data.version)}\n &nbsp;·&nbsp;\n <a href=\"https://github.com/YashJadhav21/eslint-plugin-ai-guard\" style=\"color:#818cf8;text-decoration:none;\">GitHub</a>\n </p>\n</footer>\n\n</body>\n</html>`;\n}\n\n// ─── Escape ───────────────────────────────────────────────────────────────────\n\nfunction escHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n// ─── Command ──────────────────────────────────────────────────────────────────\n\nexport function registerReportCommand(program: Command): void {\n program\n .command('report')\n .description(\n 'Generate a beautiful HTML report of AI Guard scan results\\n' +\n 'Perfect for sharing with your team or in Slack.',\n )\n .option('--path <dir>', 'Directory or file to scan', '.')\n .option('--preset <preset>', 'Rule preset: recommended | strict | security', 'recommended')\n .option('--html', 'Generate HTML report (default behavior)')\n .option('--json', 'Output raw JSON to stdout instead of writing HTML')\n .option('--output <filename>', 'Output file name', 'ai-guard-report.html')\n .option('--no-open', 'Do not open the report in the browser after generating')\n .action(async (opts: {\n path: string;\n preset: string;\n html?: boolean;\n json?: boolean;\n output: string;\n open: boolean;\n }) => {\n const preset = (['recommended', 'strict', 'security'].includes(opts.preset)\n ? opts.preset\n : 'recommended') as 'recommended' | 'strict' | 'security';\n\n const spinner = opts.json\n ? null\n : ora({ text: 'Scanning…', color: 'cyan' }).start();\n\n let result: RunResult;\n try {\n result = await runEslint({ preset, targetPath: opts.path });\n spinner?.stop();\n } catch (err: unknown) {\n spinner?.stop();\n const msg = err instanceof Error ? err.message : String(err);\n log.error(msg);\n process.exit(1);\n return;\n }\n\n const cwd = process.cwd();\n const reportData = buildReportData(result, preset, opts.path, cwd);\n\n // ── JSON mode ────────────────────────────────────────────────────────────\n\n if (opts.json) {\n console.log(JSON.stringify(reportData, null, 2));\n process.exit(0);\n return;\n }\n\n // ── HTML mode ────────────────────────────────────────────────────────────\n\n log.banner('AI GUARD REPORT');\n log.blank();\n\n const html = generateHtml(reportData);\n const outputPath = path.resolve(cwd, opts.output);\n\n fs.writeFileSync(outputPath, html, 'utf-8');\n\n log.success(`Report saved: ${opts.output}`);\n log.info(\n `Score: ${reportData.score}/100 · ${reportData.totalErrors} errors · ${reportData.totalWarnings} warnings`,\n );\n log.blank();\n\n // Open in browser\n if (opts.open !== false) {\n try {\n const { default: open } = await import('open').catch(() => {\n // open package may not be installed — fall back to platform commands\n return { default: null };\n });\n\n if (open) {\n await open(outputPath);\n log.info('Opened in your browser.');\n } else {\n // Fallback: use platform-native open command\n const { execSync } = await import('child_process');\n const cmd = process.platform === 'win32'\n ? `start \"\" \"${outputPath}\"`\n : process.platform === 'darwin'\n ? `open \"${outputPath}\"`\n : `xdg-open \"${outputPath}\"`;\n execSync(cmd);\n log.info('Opened in your browser.');\n }\n } catch {\n log.info(`Open manually: file://${outputPath}`);\n }\n } else {\n log.info(`Open: file://${outputPath}`);\n }\n\n log.blank();\n });\n}\n"],"mappings":"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","names":["fs","path","import_fs","import_path","import_fs","import_path","import_chalk","chalk","createRequire","path","fs","program","ora","chalk","import_chalk","import_path","import_fs","import_fs","import_path","path","fs","path","program","chalk","createRequire","pathToFileURL","content","isInvalidAiGuardConfig","fs","import_chalk","import_path","path","program","isInvalidAiGuardConfig","createRequire","chalk","import_chalk","import_path","program","chalk","path","import_chalk","import_path","program","chalk","path","import_fs","import_path","import_chalk","import_ora","path","fs","program","ora","chalk","import_fs","import_path","import_chalk","import_prompts","path","getPackageVersion","fs","program","getPackageVersion","chalk","path","fs","import_fs","import_path","import_ora","path","fs","program","ora","path","fs"]}
1
+ {"version":3,"sources":["../../cli/utils/debug.ts","../../cli/utils/config-manager.ts","../../cli/index.ts","../../cli/commands/run.ts","../../cli/utils/eslint-runner.ts","../../cli/utils/logger.ts","../../cli/utils/version.ts","../../cli/utils/sarif.ts","../../cli/utils/github-summary.ts","../../cli/utils/git-diff.ts","../../cli/commands/changed.ts","../../cli/commands/init.ts","../../cli/utils/detector.ts","../../cli/commands/doctor.ts","../../cli/commands/preset.ts","../../cli/commands/ignore.ts","../../cli/commands/baseline.ts","../../cli/commands/init-context.ts","../../cli/commands/report.ts"],"sourcesContent":["/**\n * debug.ts — Debug output helpers for --debug-git and --debug-ci flags.\n *\n * Centralized debug formatting ensures consistent output across commands.\n * All debug output goes to stderr to avoid polluting stdout (SARIF/JSON).\n */\n\nimport chalk from 'chalk';\nimport type { GitDiffDebugInfo, ChangedFilesResult } from './git-diff.js';\n\n// ─── Debug output ─────────────────────────────────────────────────────────────\n\nconst DIM = chalk.dim;\nconst LABEL = chalk.cyan.bold;\nconst OK = chalk.green('✔');\nconst WARN = chalk.yellow('⚠');\nconst ERR = chalk.red('✖');\nconst ARROW = chalk.dim('→');\n\n/** Write a debug line to stderr. Never pollutes stdout. */\nexport function debugLog(message: string): void {\n process.stderr.write(`${DIM('[debug]')} ${message}\\n`);\n}\n\n// ─── Git debug ────────────────────────────────────────────────────────────────\n\n/**\n * Print a full git resolution trace after getChangedFiles() runs.\n * Used by --debug-git flag.\n */\nexport function printGitDebug(result: ChangedFilesResult): void {\n const d = result.debugInfo;\n\n process.stderr.write('\\n');\n process.stderr.write(`${LABEL(' Git Resolution Trace')}\\n`);\n process.stderr.write(`${DIM(' ─────────────────────────────────────────────────────')}\\n`);\n\n // Mode\n process.stderr.write(` ${DIM('Mode:')} ${chalk.white(result.mode)}\\n`);\n\n // Base branch\n if (d.resolvedBase) {\n process.stderr.write(` ${DIM('Base branch:')} ${chalk.white(d.resolvedBase)}\\n`);\n } else {\n process.stderr.write(` ${DIM('Base branch:')} ${chalk.dim('(none — uncommitted mode)')}\\n`);\n }\n\n // Merge base\n if (d.mergeBase) {\n process.stderr.write(` ${DIM('Merge base:')} ${chalk.white(d.mergeBase.slice(0, 12))}…\\n`);\n }\n\n // Clone state\n if (d.isShallowClone) {\n process.stderr.write(` ${WARN} ${chalk.yellow('Shallow clone detected')} — use fetch-depth: 0 in workflow\\n`);\n }\n if (d.isDetachedHead) {\n process.stderr.write(` ${WARN} ${chalk.yellow('Detached HEAD')} — branch context unavailable\\n`);\n }\n\n // Strategies\n process.stderr.write('\\n');\n process.stderr.write(` ${DIM('Strategies attempted:')}\\n`);\n for (const strategy of d.strategiesAttempted) {\n const succeeded = strategy === d.strategySucceeded;\n const icon = succeeded ? OK : ERR;\n const label = succeeded ? chalk.green(strategy) : chalk.dim(strategy);\n process.stderr.write(` ${icon} ${label}\\n`);\n }\n\n if (d.strategySucceeded) {\n process.stderr.write(`\\n ${OK} ${chalk.green('Succeeded:')} ${d.strategySucceeded}\\n`);\n } else {\n process.stderr.write(`\\n ${ERR} ${chalk.red('All strategies failed')}\\n`);\n }\n\n // File counts\n process.stderr.write('\\n');\n process.stderr.write(` ${DIM('Files:')}\\n`);\n process.stderr.write(` ${ARROW} Detected raw: ${chalk.white(d.rawFileCount)}\\n`);\n process.stderr.write(` ${ARROW} Kept: ${chalk.green(result.files.length)}\\n`);\n if (d.droppedByExtension > 0) {\n process.stderr.write(` ${ARROW} Dropped (ext): ${chalk.dim(d.droppedByExtension)}\\n`);\n }\n if (d.droppedByIgnore > 0) {\n process.stderr.write(` ${ARROW} Dropped (ignored): ${chalk.dim(d.droppedByIgnore)}\\n`);\n }\n if (d.droppedByWorkingDir > 0) {\n process.stderr.write(` ${ARROW} Dropped (dir): ${chalk.dim(d.droppedByWorkingDir)}\\n`);\n }\n if (d.droppedMissing > 0) {\n process.stderr.write(` ${ARROW} Dropped (missing): ${chalk.dim(d.droppedMissing)}\\n`);\n }\n\n // Zero-files reason\n if (result.zeroFilesReason) {\n process.stderr.write('\\n');\n process.stderr.write(` ${WARN} ${chalk.yellow('Zero files reason:')}\\n`);\n process.stderr.write(` ${chalk.dim(result.zeroFilesReason)}\\n`);\n }\n\n // Changed files list\n if (result.files.length > 0) {\n process.stderr.write('\\n');\n process.stderr.write(` ${DIM('Changed files (first 20):')}\\n`);\n for (const f of result.files.slice(0, 20)) {\n process.stderr.write(` ${chalk.dim('·')} ${chalk.white(f)}\\n`);\n }\n if (result.files.length > 20) {\n process.stderr.write(` ${chalk.dim(`… and ${result.files.length - 20} more`)}\\n`);\n }\n }\n\n process.stderr.write('\\n');\n}\n\n// ─── CI debug ────────────────────────────────────────────────────────────────\n\nexport interface CIDebugInfo {\n isGitHubActions: boolean;\n githubBaseRef?: string;\n githubSha?: string;\n githubRef?: string;\n githubRepository?: string;\n githubWorkflow?: string;\n githubRunId?: string;\n githubEventName?: string;\n githubStepSummary?: string;\n githubOutput?: string;\n sarifOutputPath?: string;\n preset: string;\n failOn: string;\n scanMode: string;\n}\n\n/**\n * Print CI environment state for --debug-ci flag.\n */\nexport function printCIDebug(info: CIDebugInfo): void {\n process.stderr.write('\\n');\n process.stderr.write(`${LABEL(' CI Environment')}\\n`);\n process.stderr.write(`${DIM(' ─────────────────────────────────────────────────────')}\\n`);\n\n const env = (name: string, value: string | undefined): void => {\n const val = value ? chalk.white(value) : chalk.dim('(not set)');\n process.stderr.write(` ${DIM(name.padEnd(26))} ${val}\\n`);\n };\n\n env('GITHUB_ACTIONS:', info.isGitHubActions ? 'true' : 'false');\n env('GITHUB_BASE_REF:', info.githubBaseRef);\n env('GITHUB_SHA:', info.githubSha);\n env('GITHUB_REF:', info.githubRef);\n env('GITHUB_REPOSITORY:', info.githubRepository);\n env('GITHUB_WORKFLOW:', info.githubWorkflow);\n env('GITHUB_RUN_ID:', info.githubRunId);\n env('GITHUB_EVENT_NAME:', info.githubEventName);\n\n process.stderr.write('\\n');\n env('GITHUB_STEP_SUMMARY:', info.githubStepSummary);\n env('GITHUB_OUTPUT:', info.githubOutput);\n\n process.stderr.write('\\n');\n env('Scan preset:', info.preset);\n env('Fail on:', info.failOn);\n env('Scan mode:', info.scanMode);\n if (info.sarifOutputPath) {\n env('SARIF output:', info.sarifOutputPath);\n }\n\n process.stderr.write('\\n');\n}\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport type { ConfigType } from './detector.js';\r\n\r\nexport type Preset = 'recommended' | 'strict' | 'security';\r\n\r\n// ─── File I/O primitives ──────────────────────────────────────────────────────\r\n\r\nexport function backupConfig(configPath: string): string {\r\n const backupPath = `${configPath}.bak`;\r\n fs.copyFileSync(configPath, backupPath);\r\n return backupPath;\r\n}\r\n\r\nexport function readConfig(configPath: string): string {\r\n return fs.readFileSync(configPath, 'utf-8');\r\n}\r\n\r\nexport function writeConfig(configPath: string, content: string): void {\r\n fs.writeFileSync(configPath, content, 'utf-8');\r\n}\r\n\r\n// ─── Flat Config Generator (ESLint v9) ────────────────────────────────────────\r\n//\r\n// Generates a clean eslint.config.mjs that:\r\n// 1. Uses direct spread of the preset config object (no object wrapping)\r\n// 2. Explicitly names plugin so IDEs resolve it\r\n// 3. Puts ignores first so they apply to all following configs\r\n\r\nexport function generateFlatConfig(preset: Preset): string {\r\n return `import aiGuard from 'eslint-plugin-ai-guard';\r\n\r\nexport default [\r\n // Ignore generated / dependency directories\r\n {\r\n ignores: [\r\n 'node_modules/**',\r\n '.next/**',\r\n 'dist/**',\r\n 'build/**',\r\n 'coverage/**',\r\n 'out/**',\r\n ],\r\n },\r\n\r\n // ai-guard: catch AI-generated code patterns\r\n {\r\n plugins: {\r\n 'ai-guard': aiGuard,\r\n },\r\n rules: {\r\n ...aiGuard.configs.${preset}.rules,\r\n },\r\n },\r\n];\r\n`;\r\n}\r\n\r\n// ─── Legacy Config Generator (ESLint v8) ──────────────────────────────────────\r\n\r\nexport function generateLegacyConfig(preset: Preset): string {\r\n return `module.exports = {\r\n plugins: ['ai-guard'],\r\n extends: ['plugin:ai-guard/${preset}'],\r\n ignorePatterns: [\r\n 'node_modules/',\r\n '.next/',\r\n 'dist/',\r\n 'build/',\r\n 'coverage/',\r\n 'out/',\r\n ],\r\n};\r\n`;\r\n}\r\n\r\n// ─── Flat Config Patching (ESLint v9) ─────────────────────────────────────────\r\n\r\nconst AI_GUARD_MARKER = 'eslint-plugin-ai-guard';\r\n\r\nexport function isInvalidAiGuardConfig(content: string): boolean {\r\n if (!content.includes('eslint-plugin-ai-guard') && !content.includes('ai-guard')) {\r\n return false;\r\n }\r\n\r\n // Old invalid shape: plugin assigned to aiGuard.default\r\n if (/['\"]ai-guard['\"]\\s*:\\s*aiGuard\\.default/.test(content)) return true;\r\n\r\n // Old invalid shape: rules sourced directly from aiGuard.recommended/strict/security\r\n if (/\\.\\.\\.aiGuard\\.(recommended|strict|security)\\.rules/.test(content)) return true;\r\n if (/rules\\s*:\\s*aiGuard\\.(recommended|strict|security)\\.rules/.test(content)) return true;\r\n\r\n return false;\r\n}\r\n\r\nexport function repairInvalidFlatConfig(content: string): string {\r\n let repaired = content;\r\n \r\n // 1. Fix plugin assignment: 'ai-guard': aiGuard.default -> 'ai-guard': aiGuard\r\n repaired = repaired.replace(/(['\"]ai-guard['\"]\\s*:\\s*)aiGuard\\.default/g, '$1aiGuard');\r\n \r\n // 2. Fix raw assignment: rules: aiGuard.PRESET.rules -> rules: { ...aiGuard.configs.PRESET.rules }\r\n repaired = repaired.replace(\r\n /rules\\s*:\\s*aiGuard\\.([a-zA-Z0-9_]+)\\.rules(,?)/g,\r\n 'rules: {\\n ...aiGuard.configs.$1.rules,\\n }$2',\r\n );\r\n \r\n // 3. Fix spread assignment: ...aiGuard.PRESET.rules -> ...aiGuard.configs.PRESET.rules\r\n repaired = repaired.replace(/\\.\\.\\.aiGuard\\.([a-zA-Z0-9_]+)\\.rules/g, '...aiGuard.configs.$1.rules');\r\n \r\n return repaired;\r\n}\r\n\r\nexport function patchFlatConfig(existing: string, preset: Preset): string {\r\n if (isInvalidAiGuardConfig(existing)) {\r\n return repairInvalidFlatConfig(existing);\r\n }\r\n\r\n // If already configured and valid — leave untouched\r\n if (existing.includes(AI_GUARD_MARKER)) {\r\n return existing;\r\n }\r\n\r\n const importLine = `import aiGuard from 'eslint-plugin-ai-guard';\\n`;\r\n\r\n const rulesBlock = `\r\n // ai-guard injected by ai-guard CLI\r\n {\r\n plugins: {\r\n 'ai-guard': aiGuard,\r\n },\r\n rules: {\r\n ...aiGuard.configs.${preset}.rules,\r\n },\r\n },\r\n`;\r\n\r\n // Prepend import after the last existing import, or at the very top\r\n let patched = existing;\r\n const lastImportIdx = findLastImportEnd(patched);\r\n if (lastImportIdx > -1) {\r\n patched =\r\n patched.slice(0, lastImportIdx) +\r\n importLine +\r\n patched.slice(lastImportIdx);\r\n } else {\r\n patched = importLine + patched;\r\n }\r\n\r\n // Insert rule block before the closing `];` of the export default array\r\n const lastBracket = patched.lastIndexOf('];');\r\n if (lastBracket !== -1) {\r\n patched =\r\n patched.slice(0, lastBracket) + rulesBlock + patched.slice(lastBracket);\r\n }\r\n\r\n return patched;\r\n}\r\n\r\n/** Find index just after the last `import … from '…';` line */\r\nfunction findLastImportEnd(src: string): number {\r\n const lines = src.split('\\n');\r\n let lastImportLine = -1;\r\n let charCount = 0;\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (/^\\s*import\\s+/.test(line)) lastImportLine = i;\r\n charCount += line.length + 1; // +1 for \\n\r\n }\r\n if (lastImportLine === -1) return -1;\r\n\r\n // Recalculate offset to end of that line\r\n let offset = 0;\r\n for (let i = 0; i <= lastImportLine; i++) {\r\n offset += lines[i].length + 1;\r\n }\r\n return offset;\r\n}\r\n\r\n// ─── Legacy Config Patching (ESLint v8) ───────────────────────────────────────\r\n\r\nexport function patchLegacyConfig(existing: string, preset: Preset): string {\r\n if (existing.includes('ai-guard')) {\r\n return existing; // already configured\r\n }\r\n\r\n let patched = existing;\r\n\r\n if (patched.includes('plugins:')) {\r\n patched = patched.replace(/plugins:\\s*\\[/, `plugins: ['ai-guard', `);\r\n } else {\r\n patched = patched.replace(\r\n 'module.exports = {',\r\n `module.exports = {\\n plugins: ['ai-guard'],`,\r\n );\r\n }\r\n\r\n if (patched.includes('extends:')) {\r\n patched = patched.replace(\r\n /extends:\\s*\\[/,\r\n `extends: ['plugin:ai-guard/${preset}', `,\r\n );\r\n } else {\r\n patched = patched.replace(\r\n 'module.exports = {',\r\n `module.exports = {\\n extends: ['plugin:ai-guard/${preset}'],`,\r\n );\r\n }\r\n\r\n return patched;\r\n}\r\n\r\nexport function switchFlatPreset(existing: string, preset: Preset): string {\r\n let patched = existing;\r\n\r\n patched = patched.replace(\r\n /\\.\\.\\.aiGuard\\.configs\\.(recommended|strict|security)\\.rules/g,\r\n `...aiGuard.configs.${preset}.rules`,\r\n );\r\n\r\n patched = patched.replace(\r\n /['\"]ai-guard\\/(recommended|strict|security)['\"]/g,\r\n `'ai-guard/${preset}'`,\r\n );\r\n\r\n return patched;\r\n}\r\n\r\nexport function switchLegacyPreset(existing: string, preset: Preset): string {\r\n let patched = existing;\r\n\r\n patched = patched.replace(\r\n /['\"]plugin:ai-guard\\/(recommended|strict|security)['\"]/g,\r\n `'plugin:ai-guard/${preset}'`,\r\n );\r\n\r\n patched = patched.replace(\r\n /['\"]ai-guard\\/(recommended|strict|security)['\"]/g,\r\n `'ai-guard/${preset}'`,\r\n );\r\n\r\n return patched;\r\n}\r\n\r\n// ─── Nuke-ignore removal ──────────────────────────────────────────────────────\r\n\r\n/**\r\n * Remove `ignorePatterns: [\"**\\/*\"]` from legacy configs.\r\n * Returns `{ content, changed }`.\r\n */\r\nexport function removeNukeIgnore(existing: string): {\r\n content: string;\r\n changed: boolean;\r\n} {\r\n const nukePatterns = [/\"?\\*\\*\\/\\*\"?/g];\r\n const hasNuke =\r\n existing.includes('\"**/*\"') || existing.includes(\"'**/*'\");\r\n\r\n if (!hasNuke) return { content: existing, changed: false };\r\n\r\n // Replace the entire ignorePatterns array value when it contains **/*\r\n let patched = existing\r\n .replace(\r\n /ignorePatterns:\\s*\\[.*?\\*\\*\\/\\*.*?\\]/gs,\r\n `ignorePatterns: ['node_modules/', '.next/', 'dist/', 'build/', 'coverage/']`,\r\n )\r\n .replace(\r\n /ignores:\\s*\\[.*?\\*\\*\\/\\*.*?\\]/gs,\r\n `ignores: ['node_modules/**', '.next/**', 'dist/**', 'build/**', 'coverage/**']`,\r\n );\r\n\r\n // Safety: if the regex above didn't match (complex multi-line), fall back to\r\n // a line-by-line strip of **/* entries\r\n for (const re of nukePatterns) {\r\n patched = patched.replace(re, '');\r\n }\r\n\r\n return { content: patched, changed: patched !== existing };\r\n}\r\n\r\n// ─── Ignore pattern helpers ───────────────────────────────────────────────────\r\n\r\nconst DEFAULT_FLAT_IGNORES = [\r\n 'node_modules/**',\r\n '.next/**',\r\n 'dist/**',\r\n 'build/**',\r\n 'coverage/**',\r\n 'out/**',\r\n];\r\n\r\nconst DEFAULT_LEGACY_IGNORES = [\r\n 'node_modules/',\r\n '.next/',\r\n 'dist/',\r\n 'build/',\r\n 'coverage/',\r\n 'out/',\r\n];\r\n\r\nexport function addIgnoresToFlatConfig(existing: string): string {\r\n if (existing.includes('ignores:')) return existing;\r\n\r\n const block = `\r\n // Default ignores added by ai-guard CLI\r\n {\r\n ignores: ${JSON.stringify(DEFAULT_FLAT_IGNORES)},\r\n },\r\n`;\r\n\r\n const lastBracket = existing.lastIndexOf('];');\r\n if (lastBracket !== -1) {\r\n return existing.slice(0, lastBracket) + block + existing.slice(lastBracket);\r\n }\r\n return existing;\r\n}\r\n\r\nexport function addIgnoresToLegacyConfig(existing: string): string {\r\n if (existing.includes('ignorePatterns')) return existing;\r\n return existing.replace(\r\n 'module.exports = {',\r\n `module.exports = {\\n ignorePatterns: ${JSON.stringify(DEFAULT_LEGACY_IGNORES)},`,\r\n );\r\n}\r\n\r\n// ─── Config file path resolution ──────────────────────────────────────────────\r\n\r\nexport function getConfigFilePath(\r\n configType: ConfigType,\r\n cwd = process.cwd(),\r\n): string {\r\n switch (configType) {\r\n case 'flat-js':\r\n return path.join(cwd, 'eslint.config.js');\r\n case 'flat-mjs':\r\n return path.join(cwd, 'eslint.config.mjs');\r\n case 'flat-cjs':\r\n return path.join(cwd, 'eslint.config.cjs');\r\n case 'eslintrc-js':\r\n return path.join(cwd, '.eslintrc.js');\r\n case 'eslintrc-cjs':\r\n return path.join(cwd, '.eslintrc.cjs');\r\n case 'eslintrc-json':\r\n return path.join(cwd, '.eslintrc.json');\r\n default:\r\n return path.join(cwd, '.eslintrc.js');\r\n }\r\n}\r\n\r\n// ─── Post-init config validation ──────────────────────────────────────────────\r\n\r\n/**\r\n * Lightweight structural validation of a generated/patched flat config.\r\n * Does NOT require ESLint to be loadable — just checks the text.\r\n * Returns an array of problem strings; empty = looks valid.\r\n */\r\nexport function validateFlatConfigText(content: string): string[] {\r\n const problems: string[] = [];\r\n\r\n if (!content.includes('export default')) {\r\n problems.push('Missing `export default` — file must be an ES module');\r\n }\r\n if (!content.includes('eslint-plugin-ai-guard') && !content.includes('aiGuard')) {\r\n problems.push('Plugin import not found — ai-guard plugin may not be referenced');\r\n }\r\n if (!content.trim().endsWith('];') && !content.trim().endsWith('];')) {\r\n // minor — not fatal\r\n }\r\n\r\n // Detect nuke ignore that would prevent any files from being linted\r\n if (content.includes('\"**/*\"') || content.includes(\"'**/*'\")) {\r\n problems.push(\r\n 'Config contains \"**/*\" ignore pattern — this will prevent all files from being linted',\r\n );\r\n }\r\n\r\n return problems;\r\n}\r\n\r\nexport function validateLegacyConfigText(content: string): string[] {\r\n const problems: string[] = [];\r\n\r\n if (!content.includes('module.exports')) {\r\n problems.push('Missing `module.exports` — legacy config must use CJS exports');\r\n }\r\n if (!content.includes('ai-guard')) {\r\n problems.push('Plugin not referenced — add ai-guard to plugins and extends');\r\n }\r\n if (content.includes('\"**/*\"') || content.includes(\"'**/*'\")) {\r\n problems.push(\r\n 'Config contains \"**/*\" ignore pattern — this will prevent all files from being linted',\r\n );\r\n }\r\n\r\n return problems;\r\n}\r\n","import { Command } from 'commander';\nimport fs from 'fs';\nimport path from 'path';\nimport { registerRunCommand } from './commands/run.js';\nimport { registerChangedCommand } from './commands/changed.js';\nimport { registerInitCommand } from './commands/init.js';\nimport { registerDoctorCommand } from './commands/doctor.js';\nimport { registerPresetCommand } from './commands/preset.js';\nimport { registerIgnoreCommand } from './commands/ignore.js';\nimport { registerBaselineCommand } from './commands/baseline.js';\nimport { registerInitContextCommand } from './commands/init-context.js';\nimport { registerReportCommand } from './commands/report.js';\nimport { log } from './utils/logger.js';\n\n// ─── Version resolution ───────────────────────────────────────────────────────\n\nfunction getVersion(): string {\n try {\n // In the bundled CLI output, __dirname is available (CJS bundle).\n const pkgPath = path.resolve(__dirname, '../../package.json');\n const raw = fs.readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(raw) as { version?: string };\n return typeof pkg.version === 'string' ? pkg.version : '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\n// ─── Program ──────────────────────────────────────────────────────────────────\n\nconst program = new Command();\n\nprogram\n .name('ai-guard')\n .description(\n 'Production-grade CLI for eslint-plugin-ai-guard\\n' +\n 'Catch AI-generated code issues instantly — no ESLint config required.\\n\\n' +\n 'Quick start:\\n' +\n ' npx ai-guard run Scan current project\\n' +\n ' npx ai-guard changed Scan only changed files (CI mode)\\n' +\n ' npx ai-guard init Auto-configure ESLint\\n' +\n ' npx ai-guard init-context Generate AI agent rules\\n' +\n ' npx ai-guard report Generate shareable HTML report\\n' +\n ' npx ai-guard doctor Check your setup\\n' +\n ' npx ai-guard baseline Save baseline, track new issues only',\n )\n .version(getVersion(), '-v, --version', 'Print version number')\n .helpOption('-h, --help', 'Show help');\n\n// ─── Register commands ────────────────────────────────────────────────────────\n\nregisterRunCommand(program);\nregisterChangedCommand(program);\nregisterInitCommand(program);\nregisterDoctorCommand(program);\nregisterPresetCommand(program);\nregisterIgnoreCommand(program);\nregisterBaselineCommand(program);\nregisterInitContextCommand(program);\nregisterReportCommand(program);\n\n// ─── Global error handling ────────────────────────────────────────────────────\n\nprogram.configureOutput({\n writeErr(str) {\n // Strip commander's default \"error: \" prefix for cleaner output\n const cleaned = str.replace(/^error:\\s*/i, '').trim();\n log.error(cleaned);\n },\n});\n\nprocess.on('unhandledRejection', (reason: unknown) => {\n const msg =\n reason instanceof Error ? reason.message : String(reason);\n log.error(`Unexpected error: ${msg}`);\n log.info('If this looks like a bug, please report it at:');\n log.info(' https://github.com/YashJadhav21/eslint-plugin-ai-guard/issues');\n process.exit(1);\n});\n\nprocess.on('SIGINT', () => {\n log.blank();\n log.info('Cancelled.');\n process.exit(0);\n});\n\n// ─── Parse args ───────────────────────────────────────────────────────────────\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n log.error(msg);\n process.exit(1);\n});\n","import type { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { runEslint, type Preset, type EcosystemIssue } from '../utils/eslint-runner.js';\nimport { log, RULE_CATEGORY, CATEGORY_ICONS, CATEGORY_ORDER, CONFIDENCE_TIER, type ConfidenceTier, isCollapsedByDefault } from '../utils/logger.js';\nimport { buildSarifLog, sarifToJson } from '../utils/sarif.js';\nimport { emitGitHubAnnotations, writeGitHubSummary, writeGitHubOutputs } from '../utils/github-summary.js';\nimport { isGitHubActions } from '../utils/git-diff.js';\nimport type { RunResult } from '../utils/eslint-runner.js';\n\nexport function registerRunCommand(program: Command): void {\n program\n .command('run')\n .description('Run ai-guard rules on your project (zero ESLint config required)')\n .option('--path <dir>', 'Directory or file to scan', '.')\n .option('--strict', 'Use the strict rule preset (all rules at error)')\n .option('--security', 'Use the security-only rule preset')\n .option('--json', 'Output results as JSON (CI-friendly)')\n .option('--sarif', 'Output results as SARIF 2.1.0 (for GitHub Code Scanning)')\n .option('--fail-on <level>', 'Fail CI on: errors (default) | high | medium | any | none', 'errors')\n .option(\n '--max-warnings <n>',\n 'Fail with exit code 1 if warnings exceed this count',\n (value: string) => Number.parseInt(value, 10),\n )\n .option('--verbose', 'Show all issues — disable grouping of repeated warnings')\n .option('--quiet', 'Only show errors — suppress warnings and informational hints')\n .option('--debug-timing', 'Print per-phase timing diagnostics')\n .action(async (opts: {\n path: string;\n strict?: boolean;\n security?: boolean;\n json?: boolean;\n sarif?: boolean;\n failOn: string;\n maxWarnings?: number;\n verbose?: boolean;\n quiet?: boolean;\n debugTiming?: boolean;\n }) => {\n if (\n opts.maxWarnings !== undefined &&\n (!Number.isInteger(opts.maxWarnings) || opts.maxWarnings < 0)\n ) {\n log.blank();\n log.error('--max-warnings must be a non-negative integer.');\n log.blank();\n process.exit(1);\n return;\n }\n\n const preset: Preset = opts.strict\n ? 'strict'\n : opts.security\n ? 'security'\n : 'recommended';\n\n if (opts.strict && opts.security && !opts.json) {\n log.warn('Both --strict and --security were provided. Using --strict.');\n log.blank();\n }\n\n if (!opts.json) {\n log.banner('AI GUARD');\n log.blank();\n }\n\n const spinner = opts.json\n ? null\n : ora({ text: 'Scanning…', color: 'cyan' }).start();\n\n let result: RunResult;\n try {\n result = await runEslint({\n preset,\n targetPath: opts.path,\n debugTiming: opts.debugTiming,\n });\n spinner?.stop();\n } catch (err: unknown) {\n spinner?.stop();\n const msg = err instanceof Error ? err.message : String(err);\n\n if (msg.toLowerCase().includes('typescript') && msg.toLowerCase().includes('parser')) {\n log.blank();\n log.error('TypeScript detected but parser not found.');\n log.blank();\n log.print(` ${chalk.bold('Install the TypeScript parser:')}`);\n log.blank();\n log.print(` ${chalk.cyan('npm install --save-dev @typescript-eslint/parser')}`);\n log.blank();\n } else {\n log.blank();\n log.error(msg);\n log.blank();\n log.print(` ${chalk.bold('Fix:')} Run ${chalk.cyan('ai-guard doctor')} to diagnose your setup.`);\n log.blank();\n }\n process.exit(1);\n return;\n }\n\n // ─── GitHub Actions integration ────────────────────────────────────────────────\n\n // Auto-enable in GitHub Actions: annotations + step summary\n if (isGitHubActions()) {\n emitGitHubAnnotations(result);\n writeGitHubSummary(result, { preset, scanMode: 'full' });\n writeGitHubOutputs(result);\n }\n\n // ─── SARIF mode ─────────────────────────────────────────────────────────────────\n\n if (opts.sarif) {\n const sarifLog = buildSarifLog(result);\n console.log(sarifToJson(sarifLog));\n process.exit(resolveExitCode(result, opts.failOn ?? 'errors', opts.maxWarnings));\n return;\n }\n\n // ─── JSON mode ─────────────────────────────────────────────────────────────────\n\n if (opts.json) {\n const signalSummary = buildSignalSummary(result);\n const jsonOutput = {\n preset,\n scannedPath: opts.path,\n filesScanned: result.filesScanned,\n totalErrors: result.totalErrors,\n totalWarnings: result.totalWarnings,\n totalIssues: result.totalIssues,\n durationMs: result.durationMs,\n timing: result.timing,\n signalSummary,\n ruleBreakdown: Object.fromEntries(result.ruleBreakdown),\n topFiles: result.topFiles,\n files: result.files,\n ecosystemIssues: result.ecosystemIssues,\n parserErrors: result.parserErrors,\n tsParserAvailable: result.tsParserAvailable,\n };\n console.log(JSON.stringify(jsonOutput, null, 2));\n process.exit(resolveExitCode(result, opts.failOn ?? 'errors', opts.maxWarnings));\n return;\n }\n\n // ─── Human output ────────────────────────────────────────────────────────\n\n // Scan stats header — note if TS parser missing\n log.scanStats(result.filesScanned, result.files.length, result.durationMs, preset);\n if (!result.tsParserAvailable) {\n log.print(\n chalk.dim(` ℹ TypeScript parser not found — .ts/.tsx files use espree fallback`) +\n chalk.dim(` (install @typescript-eslint/parser for full TS support)`),\n );\n }\n log.blank();\n\n // ── Success state ─────────────────────────────────────────────────────────\n\n if (result.totalIssues === 0 && result.ecosystemIssues.length === 0 && result.parserErrors.length === 0) {\n log.print(\n ` ${chalk.green('✔')} ${chalk.bold.green('No AI issues found')} ${chalk.gray(`— ${result.filesScanned} file${result.filesScanned !== 1 ? 's' : ''} scanned, all clean`)}`,\n );\n log.blank();\n process.exit(0);\n return;\n }\n\n if (result.totalIssues === 0) {\n log.print(\n ` ${chalk.green('✔')} ${chalk.bold.green('No AI issues found')} ${chalk.gray(`— ${result.filesScanned} file${result.filesScanned !== 1 ? 's' : ''} scanned, all clean`)}`,\n );\n log.blank();\n }\n\n // ── AI Guard Findings ──────────────────────────────────────────────────\n\n if (result.totalIssues > 0) {\n const verbose = opts.verbose ?? false;\n const quiet = opts.quiet ?? false;\n\n // Separate informational from actionable findings\n const { actionableFiles, informationalFiles } = partitionByTier(result, quiet);\n\n // Category summary with icons\n log.section('Summary by Category');\n\n const categoryErrors: Record<string, number> = {};\n const categoryWarnings: Record<string, number> = {};\n\n // Only count actionable (non-informational) issues in category summary\n for (const file of actionableFiles) {\n for (const issue of file.issues) {\n const cat = RULE_CATEGORY[issue.ruleId] ?? 'Other';\n if (issue.severity === 2) {\n categoryErrors[cat] = (categoryErrors[cat] ?? 0) + 1;\n } else {\n categoryWarnings[cat] = (categoryWarnings[cat] ?? 0) + 1;\n }\n }\n }\n\n const allCategories = new Set([\n ...CATEGORY_ORDER,\n ...Object.keys(categoryErrors),\n ...Object.keys(categoryWarnings),\n ]);\n\n const sortedCategories = [...allCategories].filter(\n (cat) => (categoryErrors[cat] ?? 0) + (categoryWarnings[cat] ?? 0) > 0,\n );\n\n sortedCategories.sort((a, b) => {\n const ai = CATEGORY_ORDER.indexOf(a);\n const bi = CATEGORY_ORDER.indexOf(b);\n if (ai !== -1 && bi !== -1) return ai - bi;\n if (ai !== -1) return -1;\n if (bi !== -1) return 1;\n return a.localeCompare(b);\n });\n\n for (const cat of sortedCategories) {\n const icon = CATEGORY_ICONS[cat] ?? '⚪';\n log.category(icon, cat, categoryErrors[cat] ?? 0, categoryWarnings[cat] ?? 0);\n }\n\n log.blank();\n\n log.print(\n ` ${chalk.bold('Total:')} ${formatIssueCount(result.totalErrors, result.totalWarnings)}`,\n );\n log.blank();\n\n // By Rule — with confidence indicators\n if (result.ruleBreakdown.size > 0) {\n log.section('By Rule');\n\n const sorted = [...result.ruleBreakdown.entries()].sort(\n (a, b) => b[1] - a[1],\n );\n for (const [rule, count] of sorted) {\n const shortRule = rule.replace(/^ai-guard\\//, '');\n const tier = CONFIDENCE_TIER[rule] as ConfidenceTier | undefined;\n const tierLabel = tier === 'high'\n ? chalk.red.dim('[high]')\n : tier === 'medium'\n ? chalk.yellow.dim('[medium]')\n : tier === 'informational'\n ? chalk.gray.dim('[info]')\n : chalk.gray.dim('[low]');\n if (quiet && tier === 'informational') continue;\n log.print(\n ` ${chalk.gray('\\u2022')} ${chalk.yellow(shortRule)} ${tierLabel}${chalk.gray(':')} ${chalk.white(String(count))}`,\n );\n }\n log.blank();\n }\n\n // Top Files\n if (result.topFiles.length > 0) {\n log.section('Top Files');\n for (const { path: fp, count } of result.topFiles) {\n log.print(\n ` ${chalk.gray('\\u2022')} ${chalk.white(fp)} ${chalk.gray(`(${count})`)}`,\n );\n }\n log.blank();\n }\n\n // Issues by File — actionable findings\n if (actionableFiles.length > 0) {\n log.section('Issues by File');\n log.blank();\n renderIssuesByFile({ ...result, files: actionableFiles }, verbose, quiet);\n }\n\n // Informational hints — collapsed by default\n const totalInfoCount = informationalFiles.reduce((n, f) => n + f.issues.length, 0);\n if (totalInfoCount > 0 && !quiet) {\n if (verbose) {\n log.section('Informational Hints');\n log.print(chalk.dim(` Stylistic hints with higher false-positive rate — review before acting.`));\n log.blank();\n renderIssuesByFile({ ...result, files: informationalFiles }, true, false);\n } else {\n log.blank();\n log.print(\n ` ${chalk.gray('\\u25b8')} ${chalk.gray(`${totalInfoCount} informational hint${totalInfoCount !== 1 ? 's' : ''} — run with ${chalk.cyan('--verbose')} to expand`)}`,\n );\n }\n }\n }\n\n // ── ESLint Ecosystem Issues ───────────────────────────────────────────────\n // Shown SEPARATELY — these are NOT ai-guard findings\n\n if (result.ecosystemIssues.length > 0) {\n log.ecosystemSection('ESLint Config Issues');\n log.print(\n chalk.dim(` These issues come from your project's ESLint config, not from ai-guard.`),\n );\n log.blank();\n\n // Group by ruleId + message to de-duplicate\n const seen = new Map<string, { issue: EcosystemIssue; count: number }>();\n for (const issue of result.ecosystemIssues) {\n const key = `${issue.ruleId ?? 'null'}::${issue.message}`;\n const existing = seen.get(key);\n if (existing) {\n existing.count++;\n } else {\n seen.set(key, { issue, count: 1 });\n }\n }\n\n for (const { issue, count } of seen.values()) {\n log.ecosystemIssue(issue, count);\n }\n\n log.blank();\n }\n\n // ── Parser Errors ─────────────────────────────────────────────────────────\n\n if (result.parserErrors.length > 0) {\n log.ecosystemSection('Parser Errors');\n log.print(\n chalk.dim(` These files could not be parsed — not ai-guard findings.`),\n );\n log.blank();\n\n for (const pe of result.parserErrors) {\n log.parserError(pe);\n }\n\n if (!result.tsParserAvailable) {\n log.blank();\n log.print(\n ` ${chalk.cyan('→ Fix:')} ${chalk.yellow('npm install --save-dev @typescript-eslint/parser')}`,\n );\n log.print(\n chalk.dim(` TypeScript parser resolves most .ts/.tsx parse failures.`),\n );\n }\n log.blank();\n }\n\n log.divider();\n log.blank();\n\n // ── Next steps ────────────────────────────────────────────────────────────\n\n log.section('Next Steps');\n if (result.totalIssues > 0) {\n log.info(`Run ${chalk.cyan('ai-guard baseline')} to save these issues and track only new ones`);\n log.info(`Run ${chalk.cyan('ai-guard report')} to generate a shareable HTML report`);\n log.info(`Run ${chalk.cyan('ai-guard ignore')} to suppress dist/build noise`);\n }\n if (result.ecosystemIssues.length > 0) {\n log.info(`Run ${chalk.cyan('ai-guard doctor')} to diagnose ESLint config issues`);\n }\n if (!opts.verbose && hasGroupedWarnings(result)) {\n log.info(`Run with ${chalk.cyan('--verbose')} to expand grouped warnings`);\n }\n log.blank();\n\n process.exit(getRunExitCode(result, opts.maxWarnings));\n });\n}\n\n// ─── Issue rendering ──────────────────────────────────────────────────────────\n\nconst GROUP_THRESHOLD = 4; // Group if same rule appears >= this many times in a file\n\n/** Partition files into actionable and informational based on confidence tier */\nexport function partitionByTier(\n result: RunResult,\n quiet: boolean,\n): { actionableFiles: RunResult['files']; informationalFiles: RunResult['files'] } {\n const actionableFiles: RunResult['files'] = [];\n const informationalFiles: RunResult['files'] = [];\n\n for (const file of result.files) {\n const actionableIssues = file.issues.filter((i) => {\n const tier = CONFIDENCE_TIER[i.ruleId] as ConfidenceTier | undefined;\n if (quiet && (tier === 'informational' || i.severity === 1)) return false;\n return tier !== 'informational';\n });\n const infoIssues = file.issues.filter((i) => {\n const tier = CONFIDENCE_TIER[i.ruleId] as ConfidenceTier | undefined;\n return tier === 'informational';\n });\n\n if (actionableIssues.length > 0) {\n actionableFiles.push({ ...file, issues: actionableIssues });\n }\n if (infoIssues.length > 0) {\n informationalFiles.push({ ...file, issues: infoIssues });\n }\n }\n\n return { actionableFiles, informationalFiles };\n}\n\n/** Build signal summary for JSON output — replaces misleading numeric score */\nexport function buildSignalSummary(result: RunResult): {\n high: number; medium: number; low: number; informational: number;\n ecosystemIssues: number; parserErrors: number;\n} {\n let high = 0, medium = 0, low = 0, informational = 0;\n for (const file of result.files) {\n for (const issue of file.issues) {\n const tier = CONFIDENCE_TIER[issue.ruleId] as ConfidenceTier | undefined;\n if (tier === 'high') high++;\n else if (tier === 'medium') medium++;\n else if (tier === 'informational') informational++;\n else low++;\n }\n }\n return {\n high, medium, low, informational,\n ecosystemIssues: result.ecosystemIssues.length,\n parserErrors: result.parserErrors.length,\n };\n}\n\nfunction hasGroupedWarnings(result: RunResult): boolean {\n for (const file of result.files) {\n const ruleCounts = new Map<string, number>();\n for (const issue of file.issues) {\n ruleCounts.set(issue.ruleId, (ruleCounts.get(issue.ruleId) ?? 0) + 1);\n }\n for (const count of ruleCounts.values()) {\n if (count >= GROUP_THRESHOLD) return true;\n }\n }\n return false;\n}\n\nexport function renderIssuesByFile(result: RunResult, verbose: boolean, quiet = false): void {\n for (const file of result.files) {\n log.print(\n ` ${chalk.bold.white(file.filePath)} ` +\n chalk.gray(\n `(${file.errorCount} error${file.errorCount !== 1 ? 's' : ''}, ` +\n `${file.warningCount} warning${file.warningCount !== 1 ? 's' : ''})`,\n ),\n );\n\n if (!verbose) {\n // Group repeated low-confidence warnings\n const ruleCounts = new Map<string, Array<typeof file.issues[0]>>();\n for (const issue of file.issues) {\n const arr = ruleCounts.get(issue.ruleId) ?? [];\n arr.push(issue);\n ruleCounts.set(issue.ruleId, arr);\n }\n\n for (const issues of ruleCounts.values()) {\n const tier = CONFIDENCE_TIER[issues[0].ruleId] ?? 'low';\n // Group low-confidence warnings if they repeat heavily\n if (tier === 'low' && issues.length >= GROUP_THRESHOLD) {\n const sev = issues[0].severity === 2 ? chalk.red('error') : chalk.yellow(' warn');\n const shortRule = chalk.gray(issues[0].ruleId.replace(/^ai-guard\\//, ''));\n log.print(\n ` ${sev} ${chalk.white(issues[0].message)} ${shortRule}`,\n );\n log.print(\n chalk.dim(` ↳ ${issues.length} occurrences — run with --verbose to expand`),\n );\n } else {\n for (const issue of issues) {\n renderSingleIssue(issue);\n }\n }\n }\n } else {\n for (const issue of file.issues) {\n renderSingleIssue(issue);\n }\n }\n\n log.blank();\n }\n}\n\nfunction renderSingleIssue(issue: { ruleId: string; severity: 1 | 2; message: string; line: number; column: number }): void {\n const sev = issue.severity === 2\n ? chalk.red('error')\n : chalk.yellow(' warn');\n const loc = chalk.gray(`${String(issue.line)}:${String(issue.column)}`).padEnd(12);\n const ruleShort = chalk.gray(issue.ruleId.replace(/^ai-guard\\//, ''));\n const tier = CONFIDENCE_TIER[issue.ruleId] as ConfidenceTier | undefined;\n const tierTag = tier === 'informational'\n ? chalk.dim(' [info]')\n : '';\n log.print(\n ` ${loc} ${sev} ${chalk.white(issue.message)}${tierTag} ${ruleShort}`,\n );\n}\n\n// ─── Exit code ────────────────────────────────────────────────────────────────\n\nexport function getRunExitCode(result: RunResult, maxWarnings?: number): number {\n if (result.totalErrors > 0) return 1;\n if (maxWarnings !== undefined && result.totalWarnings > maxWarnings) return 1;\n return 0;\n}\n\nexport function formatIssueCount(errors: number, warnings: number): string {\n const parts: string[] = [];\n if (errors > 0) parts.push(chalk.red.bold(`${errors} error${errors !== 1 ? 's' : ''}`));\n if (warnings > 0) parts.push(chalk.yellow.bold(`${warnings} warning${warnings !== 1 ? 's' : ''}`));\n return parts.join(chalk.gray(' · '));\n}\n\n// ─── Fail-on exit code resolution ───────────────────────────────────────────────────\n\n/**\n * Determine exit code based on --fail-on level.\n *\n * - errors (default): exit 1 if any errors (severity 2) exist\n * - high: exit 1 only if high-confidence findings exist\n * - medium: exit 1 if high OR medium findings exist\n * - any: exit 1 if any findings (excluding informational)\n * - none: always exit 0 (report-only mode)\n */\nexport function resolveExitCode(\n result: RunResult,\n failOn: string,\n maxWarnings?: number,\n): number {\n if (maxWarnings !== undefined && result.totalWarnings > maxWarnings) return 1;\n\n switch (failOn) {\n case 'none': return 0;\n case 'errors': return result.totalErrors > 0 ? 1 : 0;\n case 'high': {\n const high = result.files.flatMap((f) => f.issues)\n .filter((i) => CONFIDENCE_TIER[i.ruleId] === 'high').length;\n return high > 0 ? 1 : 0;\n }\n case 'medium': {\n const highMed = result.files.flatMap((f) => f.issues)\n .filter((i) => CONFIDENCE_TIER[i.ruleId] === 'high' || CONFIDENCE_TIER[i.ruleId] === 'medium').length;\n return highMed > 0 ? 1 : 0;\n }\n case 'any': {\n const actionable = result.files.flatMap((f) => f.issues)\n .filter((i) => CONFIDENCE_TIER[i.ruleId] !== 'informational').length;\n return actionable > 0 ? 1 : 0;\n }\n default: return getRunExitCode(result, maxWarnings);\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { pathToFileURL } from 'url';\nimport chalk from 'chalk';\nimport { log } from './logger.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ntype RuleLevel = 'error' | 'warn' | 'off';\n\nexport type Preset = 'recommended' | 'strict' | 'security';\n\nexport interface RunOptions {\n preset: Preset;\n targetPath: string;\n /** Explicit list of absolute file paths — bypasses glob traversal (used for changed-file mode) */\n files?: string[];\n maxWarnings?: number;\n jsonOutput?: boolean;\n debugTiming?: boolean;\n sarif?: boolean;\n /** Working directory override (monorepo subdirectory support) */\n workingDirectory?: string;\n}\n\nexport interface IssueDetail {\n ruleId: string;\n severity: 1 | 2;\n message: string;\n line: number;\n column: number;\n endLine?: number;\n endColumn?: number;\n /** Confidence tier from CONFIDENCE_TIER — included in JSON output */\n confidence?: 'high' | 'medium' | 'low' | 'informational';\n /** High-level category (Async Stability, Security, etc.) */\n category?: string;\n /** Async risk type for async-reliability rules */\n asyncRiskType?: string;\n /** Short remediation guidance */\n remediation?: string;\n}\n\nexport interface FileResult {\n filePath: string;\n issues: IssueDetail[]; // ai-guard/* findings only\n errorCount: number;\n warningCount: number;\n}\n\n/**\n * An issue from a non-ai-guard rule (e.g., react-hooks/exhaustive-deps not found,\n * foreign plugin rules, missing rule definitions). These are ESLint ecosystem issues\n * and must NEVER appear in ai-guard findings or affect the score/confidence.\n */\nexport interface EcosystemIssue {\n type: 'missing-rule' | 'foreign-rule' | 'config-error';\n ruleId: string | null;\n message: string;\n filePath: string;\n line: number;\n column: number;\n}\n\n/**\n * A fatal parse error — ESLint could not parse the file at all.\n * Not an ai-guard finding. Shown in a separate section.\n */\nexport interface ParserError {\n filePath: string;\n message: string;\n line: number;\n}\n\nexport interface TimingBreakdown {\n pluginLoadMs: number;\n parserLoadMs: number;\n lintMs: number;\n processMs: number;\n /** True if plugin/parser came from module cache (warm start) */\n fromCache: boolean;\n}\n\nexport interface RunResult {\n files: FileResult[];\n totalErrors: number;\n totalWarnings: number;\n totalIssues: number;\n filesScanned: number;\n ruleBreakdown: Map<string, number>;\n topFiles: Array<{ path: string; count: number }>;\n durationMs: number;\n timing?: TimingBreakdown;\n /** ESLint ecosystem issues — NOT ai-guard findings */\n ecosystemIssues: EcosystemIssue[];\n /** Fatal parser errors — NOT ai-guard findings */\n parserErrors: ParserError[];\n /** True if @typescript-eslint/parser was found and loaded */\n tsParserAvailable: boolean;\n}\n\n// ─── Module-level cache ───────────────────────────────────────────────────────\n//\n// PERFORMANCE CRITICAL: ESLint initialization is expensive (~200-800ms per call\n// due to module loading, config resolution, and parser startup). By caching the\n// ESLint instance, plugin module, and TS parser at module level, we eliminate\n// this overhead from all subsequent calls within the same process.\n//\n// Cache key: `${cwd}::${preset}` — invalidated on CWD or preset change.\n// This is safe because a single CLI invocation uses one CWD and one preset.\n\n// ─── Issue metadata ───────────────────────────────────────────────────────────\n// Lookup tables for enriching IssueDetail with confidence, category,\n// asyncRiskType, and remediation. Used in JSON output and SARIF results.\n\nexport const ISSUE_CONFIDENCE: Record<string, 'high' | 'medium' | 'low' | 'informational'> = {\n // HIGH — near-certain bugs: false positive rate <2% in real-world codebases\n 'ai-guard/no-hardcoded-secret': 'high', // Literal credential string in source: almost always a mistake\n 'ai-guard/no-eval-dynamic': 'high', // Dynamic eval: no legitimate modern use case\n 'ai-guard/no-floating-promise': 'high', // Unhandled promise: async failures silently swallowed\n\n // MEDIUM — likely bugs, but legitimate patterns exist\n 'ai-guard/no-empty-catch': 'medium', // CHANGED from high: empty catch is valid for optional ops (JSON.parse, feature detection)\n 'ai-guard/no-sql-string-concat': 'medium', // SQL injection risk, but ORM template literals can FP\n 'ai-guard/no-await-in-loop': 'medium', // Sequential await is often intentional (rate limiting, ordering)\n 'ai-guard/require-auth-middleware':'medium', // Context-blind: public routes are valid\n 'ai-guard/require-authz-check': 'medium', // Context-blind: some resources are public\n 'ai-guard/no-catch-log-rethrow': 'medium', // Log-then-rethrow is a known antipattern but sometimes intentional\n 'ai-guard/no-catch-without-use': 'medium', // Unused catch param common in TS\n 'ai-guard/no-unsafe-deserialize': 'medium', // JSON.parse is sometimes safe with trusted input\n\n // LOW — possible improvement, high false-positive rate\n 'ai-guard/no-async-array-callback':'low', // Promise.all is better, but forEach async is not always a bug\n 'ai-guard/no-dead-branch': 'low', // Static analysis of conditions is inherently imprecise\n 'ai-guard/no-broad-exception': 'low', // Catching Error is common and sometimes correct\n 'ai-guard/no-console-in-handler': 'low', // Stylistic: debug logs left in vs intentional logging\n 'ai-guard/no-duplicate-logic-block':'low', // May be coincidental similarity, not true duplication\n\n // INFORMATIONAL — hints only, never fail CI\n 'ai-guard/no-async-without-await': 'informational', // Framework patterns (Next.js RSC, etc.) make this very noisy\n 'ai-guard/no-redundant-await': 'informational', // Explicit await in return is idiomatic in many codebases\n};\n\nexport const ISSUE_CATEGORY: Record<string, string> = {\n 'ai-guard/no-floating-promise': 'Async Reliability',\n 'ai-guard/no-await-in-loop': 'Async Reliability',\n 'ai-guard/no-async-without-await': 'Async Reliability',\n 'ai-guard/no-async-array-callback':'Async Reliability',\n 'ai-guard/no-redundant-await': 'Async Reliability',\n 'ai-guard/no-empty-catch': 'Reliability',\n 'ai-guard/no-broad-exception': 'Reliability',\n 'ai-guard/no-catch-log-rethrow': 'Reliability',\n 'ai-guard/no-catch-without-use': 'Reliability',\n 'ai-guard/no-hardcoded-secret': 'Security',\n 'ai-guard/no-eval-dynamic': 'Security',\n 'ai-guard/no-sql-string-concat': 'Security',\n 'ai-guard/no-unsafe-deserialize': 'Security',\n 'ai-guard/require-auth-middleware':'Security',\n 'ai-guard/require-authz-check': 'Security',\n 'ai-guard/no-console-in-handler': 'AI Patterns',\n 'ai-guard/no-duplicate-logic-block':'AI Patterns',\n 'ai-guard/no-dead-branch': 'AI Patterns',\n};\n\nexport const ISSUE_ASYNC_RISK_TYPE: Record<string, string> = {\n 'ai-guard/no-floating-promise': 'floating-promise',\n 'ai-guard/no-await-in-loop': 'sequential-await',\n 'ai-guard/no-async-without-await': 'unnecessary-async',\n 'ai-guard/no-async-array-callback':'async-array-callback',\n 'ai-guard/no-redundant-await': 'redundant-await',\n};\n\nexport const ISSUE_REMEDIATION: Record<string, string> = {\n 'ai-guard/no-floating-promise': 'Add `await` before the call, assign to a variable, or add `.catch()` to handle rejection.',\n 'ai-guard/no-await-in-loop': 'Collect promises in an array and use `await Promise.all(...)` outside the loop.',\n 'ai-guard/no-async-without-await': 'Remove `async` if no async operations are needed, or add an `await` expression.',\n 'ai-guard/no-async-array-callback':'Use `Promise.all(array.map(async item => ...))` to ensure all async callbacks are awaited.',\n 'ai-guard/no-redundant-await': 'Remove the `await` \\u2014 the value is already resolved.',\n 'ai-guard/no-empty-catch': 'Add error handling in the catch block, or at minimum log the error.',\n 'ai-guard/no-broad-exception': 'Catch specific error types or re-throw after handling.',\n 'ai-guard/no-catch-log-rethrow': 'Either log the error OR rethrow it \\u2014 doing both duplicates the error in logs.',\n 'ai-guard/no-catch-without-use': 'Use the caught error variable or rename to `_` to signal intentional suppression.',\n 'ai-guard/no-hardcoded-secret': 'Move credentials to environment variables: `process.env.SECRET_KEY`.',\n 'ai-guard/no-eval-dynamic': 'Avoid eval and Function constructors. Use safer alternatives like JSON.parse.',\n 'ai-guard/no-sql-string-concat': 'Use parameterized queries or an ORM to prevent SQL injection.',\n 'ai-guard/no-unsafe-deserialize': 'Validate input with a schema library (zod, joi, yup) before parsing.',\n 'ai-guard/require-auth-middleware':'Add an authentication middleware before the route handler.',\n 'ai-guard/require-authz-check': 'Verify the requesting user has permission to access this resource.',\n 'ai-guard/no-console-in-handler': 'Replace console.log with a structured logger (pino, winston, etc.).',\n 'ai-guard/no-duplicate-logic-block':'Extract the duplicated logic into a shared function.',\n 'ai-guard/no-dead-branch': 'Remove the unreachable branch or fix the condition.',\n};\n\ninterface CachedRunner {\n eslint: unknown; // ESLint instance — typed as unknown to avoid importing ESLint at module level\n tsParserAvailable: boolean;\n pluginLoadMs: number;\n parserLoadMs: number;\n}\n\nconst _runnerCache = new Map<string, CachedRunner>();\n\n/** Clear the module-level runner cache. Useful in tests that need a fresh state. */\nexport function clearRunnerCache(): void {\n _runnerCache.clear();\n}\n\n// ─── Plugin normalizer ────────────────────────────────────────────────────────\n\ntype AiGuardPlugin = {\n rules: Record<string, unknown>;\n configs?: Record<string, unknown>;\n meta?: Record<string, unknown>;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction normalizePlugin(raw: unknown): AiGuardPlugin {\n if (isRecord(raw) && isRecord(raw.default) && isRecord(raw.default.rules)) {\n return raw.default as AiGuardPlugin;\n }\n if (isRecord(raw) && isRecord(raw.rules)) {\n return raw as AiGuardPlugin;\n }\n throw new Error(\n 'Could not load eslint-plugin-ai-guard. Run: npm install eslint-plugin-ai-guard',\n );\n}\n\n// ─── Preset rule maps ─────────────────────────────────────────────────────────\n\nconst RECOMMENDED_RULES: Record<string, RuleLevel> = {\n // Reliability\n 'ai-guard/no-empty-catch': 'error',\n 'ai-guard/no-broad-exception': 'warn',\n // Async\n 'ai-guard/no-floating-promise': 'error',\n 'ai-guard/no-await-in-loop': 'warn',\n 'ai-guard/no-async-without-await': 'warn',\n 'ai-guard/no-async-array-callback': 'warn',\n // Security\n 'ai-guard/no-hardcoded-secret': 'error',\n 'ai-guard/no-eval-dynamic': 'error',\n 'ai-guard/no-sql-string-concat': 'warn',\n 'ai-guard/no-unsafe-deserialize': 'warn',\n 'ai-guard/require-auth-middleware': 'warn',\n 'ai-guard/require-authz-check': 'warn',\n // AI Patterns\n 'ai-guard/no-dead-branch': 'warn',\n};\n\nconst STRICT_RULES: Record<string, RuleLevel> = {\n // Reliability\n 'ai-guard/no-empty-catch': 'error',\n 'ai-guard/no-broad-exception': 'error',\n 'ai-guard/no-catch-log-rethrow': 'error',\n 'ai-guard/no-catch-without-use': 'error',\n // Async\n 'ai-guard/no-async-array-callback': 'error',\n 'ai-guard/no-floating-promise': 'error',\n 'ai-guard/no-await-in-loop': 'error',\n 'ai-guard/no-async-without-await': 'error',\n 'ai-guard/no-redundant-await': 'error',\n // Security\n 'ai-guard/no-hardcoded-secret': 'error',\n 'ai-guard/no-eval-dynamic': 'error',\n 'ai-guard/no-sql-string-concat': 'error',\n 'ai-guard/no-unsafe-deserialize': 'error',\n 'ai-guard/require-auth-middleware': 'error',\n 'ai-guard/require-authz-check': 'error',\n // AI Patterns\n 'ai-guard/no-console-in-handler': 'error',\n 'ai-guard/no-duplicate-logic-block': 'error',\n 'ai-guard/no-dead-branch': 'error',\n};\n\nconst SECURITY_RULES: Record<string, RuleLevel> = {\n 'ai-guard/no-hardcoded-secret': 'error',\n 'ai-guard/no-eval-dynamic': 'error',\n 'ai-guard/no-sql-string-concat': 'error',\n 'ai-guard/no-unsafe-deserialize': 'warn',\n 'ai-guard/require-auth-middleware': 'warn',\n 'ai-guard/require-authz-check': 'warn',\n};\n\nfunction getRules(preset: Preset): Record<string, RuleLevel> {\n if (preset === 'strict') return STRICT_RULES;\n if (preset === 'security') return SECURITY_RULES;\n return RECOMMENDED_RULES;\n}\n\n// ─── Default ignores ──────────────────────────────────────────────────────────\n//\n// PERFORMANCE: This list is critical for scan speed. Every directory listed here\n// is skipped entirely during file traversal. Broad patterns (node_modules, dist)\n// eliminate the bulk of files in typical projects. The extended list targets\n// monorepo tooling and framework-generated directories.\n\nconst DEFAULT_IGNORE_PATTERNS = [\n // Core — always skip\n '**/node_modules/**',\n '**/.next/**',\n '**/dist/**',\n '**/build/**',\n '**/coverage/**',\n '**/out/**',\n '**/.git/**',\n // Build artifacts and caches\n '**/.cache/**',\n '**/.turbo/**',\n '**/.nx/**',\n '**/.parcel-cache/**',\n '**/.webpack/**',\n '**/tmp/**',\n '**/temp/**',\n // Package manager artifacts\n '**/.yarn/**',\n '**/.pnp.*',\n // Framework generated\n '**/.expo/**',\n '**/.svelte-kit/**',\n '**/storybook-static/**',\n '**/.storybook/generated/**',\n // Generated code\n '**/generated/**',\n '**/__generated__/**',\n '**/vendor/**',\n // Test outputs\n '**/test-results/**',\n '**/playwright-report/**',\n // Misc\n '**/.docusaurus/**',\n '**/.vitepress/cache/**',\n];\n\nexport function isSkippablePatternError(error: Error): boolean {\n const msg = error.message.toLowerCase();\n return (\n msg.includes('no files') ||\n msg.includes('no files matching') ||\n msg.includes('ignored') ||\n msg.includes('all files matched by') ||\n msg.includes('are ignored') ||\n msg.includes('was ignored') ||\n msg.includes('file ignored')\n );\n}\n\n// ─── Message classifier ───────────────────────────────────────────────────────\n\ntype MessageSource = 'ai-guard' | 'parser-error' | 'ecosystem';\n\nfunction classifyMessage(msg: { ruleId: string | null; fatal?: boolean; message: string }): MessageSource {\n // Fatal parse errors (ESLint couldn't parse the file at all)\n if (msg.fatal === true) return 'parser-error';\n\n // Explicit parse errors in the message body\n if (msg.ruleId === null && (\n msg.message.startsWith('Parsing error') ||\n msg.message.includes('Unexpected token') ||\n msg.message.includes('SyntaxError')\n )) {\n return 'parser-error';\n }\n\n // Our rules — the only ones that count as ai-guard findings\n if (msg.ruleId && msg.ruleId.startsWith('ai-guard/')) {\n return 'ai-guard';\n }\n\n // Everything else: missing rule definitions, foreign plugin rules, config issues\n return 'ecosystem';\n}\n\nfunction classifyEcosystemType(\n msg: { ruleId: string | null; message: string },\n): EcosystemIssue['type'] {\n const lower = msg.message.toLowerCase();\n if (lower.includes('definition for rule') && lower.includes('was not found')) {\n return 'missing-rule';\n }\n if (lower.includes('configuration') || lower.includes('config')) {\n return 'config-error';\n }\n return 'foreign-rule';\n}\n\n// ─── Plugin loader ────────────────────────────────────────────────────────────\n\nasync function loadPluginModuleFromCwd(cwd: string): Promise<unknown> {\n const { createRequire } = await import('module');\n const requireFromCwd = createRequire(path.join(cwd, 'package.json'));\n\n try {\n const resolved = requireFromCwd.resolve('eslint-plugin-ai-guard');\n return import(pathToFileURL(resolved).href);\n } catch {\n // Fall through to local dist fallback.\n }\n\n const localDistEntry = path.join(cwd, 'dist', 'index.js');\n if (fs.existsSync(localDistEntry)) {\n return import(pathToFileURL(localDistEntry).href);\n }\n\n const localSrcEntry = path.join(cwd, 'src', 'index.ts');\n if (fs.existsSync(localSrcEntry)) {\n try {\n return import(pathToFileURL(localSrcEntry).href);\n } catch (err: unknown) {\n const reason = err instanceof Error ? err.message : String(err);\n log.debug(`Local src plugin import failed: ${reason}`);\n }\n }\n\n throw new Error(\n 'eslint-plugin-ai-guard is not installed. Run: npm install --save-dev eslint-plugin-ai-guard',\n );\n}\n\n// ─── Cached runner builder ────────────────────────────────────────────────────\n//\n// PERFORMANCE: This function builds the ESLint instance and caches it. All\n// subsequent calls with the same cwd+preset reuse the cached instance, reducing\n// startup overhead from ~500-1000ms to ~0ms on warm runs within the same process.\n\nasync function getOrBuildRunner(\n cwd: string,\n preset: Preset,\n eslintCwd: string,\n): Promise<{ runner: CachedRunner; fromCache: boolean }> {\n const cacheKey = `${eslintCwd}::${preset}`;\n const cached = _runnerCache.get(cacheKey);\n if (cached) {\n return { runner: cached, fromCache: true };\n }\n\n // ── Parallel initialization ────────────────────────────────────────────────\n // Load ESLint module, plugin, and TS parser concurrently for maximum speed.\n // These are independent operations that can safely run in parallel.\n\n const [{ ESLint }, rawPlugin, tsParserResult] = await Promise.all([\n // 1. Load ESLint\n import('eslint').catch(() => {\n throw new Error('ESLint is not installed. Run: npm install --save-dev eslint');\n }),\n\n // 2. Load plugin\n loadPluginModuleFromCwd(cwd),\n\n // 3. Load TS parser (optional — errors are caught)\n Promise.resolve().then(() => {\n const parserStart = Date.now();\n try {\n // Prefer parser from user's project (correct version), fall back to ours\n let tsParser: unknown;\n try {\n tsParser = require(path.join(\n cwd,\n 'node_modules',\n '@typescript-eslint',\n 'parser',\n ));\n } catch {\n tsParser = require('@typescript-eslint/parser');\n }\n return { tsParser, available: true, loadMs: Date.now() - parserStart };\n } catch {\n log.debug('@typescript-eslint/parser not found — TypeScript files will use espree fallback');\n return { tsParser: null, available: false, loadMs: Date.now() - parserStart };\n }\n }),\n ]);\n\n const plugin = normalizePlugin(rawPlugin);\n const rules = getRules(preset);\n const { tsParser, available: tsParserAvailable } = tsParserResult;\n\n // ── Build flat config ──────────────────────────────────────────────────────\n //\n // PERFORMANCE: Using a single config block with `files` arrays instead of\n // separate blocks reduces ESLint's config resolution overhead. The ignores\n // block is placed first so ESLint can skip excluded files early.\n\n const JS_TS_FILES = [\n '**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx',\n '**/*.mts', '**/*.cts', '**/*.mjs', '**/*.cjs',\n ];\n\n const configBlocks: Array<Record<string, unknown>> = [\n // Ignore block first — ESLint can skip excluded files without processing\n { ignores: DEFAULT_IGNORE_PATTERNS },\n // JS/JSX — espree parser with JSX support\n {\n files: ['**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'],\n plugins: { 'ai-guard': plugin } as Record<string, unknown>,\n languageOptions: {\n parserOptions: {\n ecmaVersion: 'latest',\n sourceType: 'module',\n ecmaFeatures: { jsx: true },\n },\n },\n rules: rules as Record<string, unknown>,\n },\n ];\n\n if (tsParser) {\n // TS + TSX with TypeScript parser — JSX enabled for both\n configBlocks.push({\n files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],\n plugins: { 'ai-guard': plugin } as Record<string, unknown>,\n languageOptions: {\n parser: tsParser,\n parserOptions: {\n ecmaVersion: 'latest',\n sourceType: 'module',\n ecmaFeatures: { jsx: true },\n },\n },\n rules: rules as Record<string, unknown>,\n });\n } else {\n // No TS parser — lint ts/tsx with espree (may partially fail on TS syntax)\n configBlocks.push({\n files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],\n plugins: { 'ai-guard': plugin } as Record<string, unknown>,\n languageOptions: {\n parserOptions: {\n ecmaVersion: 'latest',\n sourceType: 'module',\n ecmaFeatures: { jsx: true },\n },\n },\n rules: rules as Record<string, unknown>,\n });\n }\n\n const eslint = new ESLint({\n cwd: eslintCwd,\n overrideConfigFile: true as unknown as string,\n overrideConfig: configBlocks,\n });\n\n const runner: CachedRunner = {\n eslint,\n tsParserAvailable,\n pluginLoadMs: 0, // accounted in parallel Promise.all\n parserLoadMs: tsParserResult.loadMs,\n };\n\n _runnerCache.set(cacheKey, runner);\n return { runner, fromCache: false };\n}\n\n// ─── File patterns ────────────────────────────────────────────────────────────\n\nconst JS_TS_FILE_PATTERNS = [\n '**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx',\n '**/*.mts', '**/*.cts', '**/*.mjs', '**/*.cjs',\n];\n\n// ─── Core runner ──────────────────────────────────────────────────────────────\n\nexport async function runEslint(options: RunOptions): Promise<RunResult> {\n const overallStart = Date.now();\n\n const resolvedTargetPath = path.resolve(options.targetPath);\n\n if (!fs.existsSync(resolvedTargetPath)) {\n throw new Error(`Path not found: ${options.targetPath}`);\n }\n\n const targetStat = fs.statSync(resolvedTargetPath);\n const isSingleFileTarget = targetStat.isFile();\n const eslintCwd = isSingleFileTarget\n ? path.dirname(resolvedTargetPath)\n : resolvedTargetPath;\n\n const cwd = process.cwd();\n\n // ── Get or build cached runner ─────────────────────────────────────────────\n const initStart = Date.now();\n const { runner, fromCache } = await getOrBuildRunner(cwd, options.preset, eslintCwd);\n const initMs = Date.now() - initStart;\n\n const timing: TimingBreakdown = {\n pluginLoadMs: fromCache ? 0 : runner.pluginLoadMs,\n parserLoadMs: fromCache ? 0 : runner.parserLoadMs,\n lintMs: 0,\n processMs: 0,\n fromCache,\n };\n\n // ── Lint files ─────────────────────────────────────────────────────────────\n //\n // PERFORMANCE: Single lintFiles() call with all patterns is dramatically faster\n // than Promise.all of individual pattern calls. ESLint can batch file resolution\n // and share parser instances across files when called once.\n\n // ── Determine lint target ──────────────────────────────────────────────────\n //\n // Two modes:\n // 1. Explicit file list (changed-file mode): pass absolute paths directly\n // to lintFiles() — bypasses glob traversal entirely. This is the fastest\n // path and enables changed-file PR scanning.\n // 2. Pattern-based (full scan): use JS_TS_FILE_PATTERNS with cwd.\n\n const hasExplicitFiles = options.files && options.files.length > 0;\n const patterns = hasExplicitFiles\n ? options.files! // absolute paths — ESLint accepts them directly\n : isSingleFileTarget\n ? [path.basename(resolvedTargetPath)]\n : JS_TS_FILE_PATTERNS;\n\n const lintStart = Date.now();\n let rawResults: Array<{\n filePath: string;\n messages: Array<{\n ruleId: string | null;\n severity: number;\n message: string;\n line: number;\n column: number;\n endLine?: number;\n endColumn?: number;\n fatal?: boolean;\n }>;\n errorCount: number;\n warningCount: number;\n }>;\n\n const eslint = runner.eslint as {\n lintFiles(patterns: string[]): Promise<typeof rawResults>;\n };\n\n try {\n rawResults = await eslint.lintFiles(patterns);\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n\n if (isSkippablePatternError(error)) {\n // Single-call failed with \"no files\" — fall back to per-pattern\n log.debug('Single-call lintFiles failed, falling back to per-pattern');\n const perPatternResults = await Promise.allSettled(\n patterns.map(async (pattern) => {\n try {\n return await eslint.lintFiles([pattern]);\n } catch (patternErr: unknown) {\n const patternError = patternErr instanceof Error ? patternErr : new Error(String(patternErr));\n if (isSkippablePatternError(patternError)) {\n log.debug(`Skipping pattern '${pattern}' (no lintable files)`);\n return [] as typeof rawResults;\n }\n throw patternError;\n }\n }),\n );\n rawResults = perPatternResults\n .filter((r): r is PromiseFulfilledResult<typeof rawResults> => r.status === 'fulfilled')\n .flatMap((r) => r.value);\n } else {\n // Invalidate the cache for this key so the next call rebuilds fresh\n const cacheKey = `${eslintCwd}::${options.preset}`;\n _runnerCache.delete(cacheKey);\n throw error;\n }\n }\n timing.lintMs = Date.now() - lintStart;\n\n // ── Process results ────────────────────────────────────────────────────────\n const processStart = Date.now();\n\n const files: FileResult[] = [];\n const ecosystemIssues: EcosystemIssue[] = [];\n const parserErrors: ParserError[] = [];\n const ruleBreakdown = new Map<string, number>();\n let totalErrors = 0;\n let totalWarnings = 0;\n const filesScanned = rawResults.length;\n\n for (const result of rawResults) {\n if (result.messages.length === 0) continue;\n\n const relPath = path.relative(cwd, result.filePath);\n const aiGuardIssues: IssueDetail[] = [];\n let fileErrors = 0;\n let fileWarnings = 0;\n\n for (const m of result.messages) {\n const source = classifyMessage(m);\n\n if (source === 'parser-error') {\n parserErrors.push({\n filePath: relPath,\n message: m.message,\n line: m.line ?? 0,\n });\n continue;\n }\n\n if (source === 'ecosystem') {\n ecosystemIssues.push({\n type: classifyEcosystemType(m),\n ruleId: m.ruleId,\n message: m.message,\n filePath: relPath,\n line: m.line ?? 0,\n column: m.column ?? 0,\n });\n continue;\n }\n\n // source === 'ai-guard'\n const ruleId = m.ruleId ?? 'unknown';\n const issue: IssueDetail = {\n ruleId,\n severity: m.severity as 1 | 2,\n message: m.message,\n line: m.line,\n column: m.column,\n endLine: m.endLine,\n endColumn: m.endColumn,\n confidence: ISSUE_CONFIDENCE[ruleId],\n category: ISSUE_CATEGORY[ruleId],\n asyncRiskType: ISSUE_ASYNC_RISK_TYPE[ruleId],\n remediation: ISSUE_REMEDIATION[ruleId],\n };\n\n aiGuardIssues.push(issue);\n\n if (m.severity === 2) {\n fileErrors++;\n totalErrors++;\n } else {\n fileWarnings++;\n totalWarnings++;\n }\n\n ruleBreakdown.set(\n issue.ruleId,\n (ruleBreakdown.get(issue.ruleId) ?? 0) + 1,\n );\n }\n\n if (aiGuardIssues.length > 0) {\n files.push({\n filePath: relPath,\n issues: aiGuardIssues,\n errorCount: fileErrors,\n warningCount: fileWarnings,\n });\n }\n }\n\n const topFiles = [...files]\n .sort((a, b) => b.issues.length - a.issues.length)\n .slice(0, 10)\n .map((f) => ({ path: f.filePath, count: f.issues.length }));\n\n timing.processMs = Date.now() - processStart;\n\n if (options.debugTiming) {\n const totalMs = Date.now() - overallStart;\n const cacheLabel = fromCache ? chalk.green('warm cache') : chalk.yellow('cold start');\n log.debug(`Init: ${initMs}ms (${cacheLabel})`);\n log.debug(`Lint: ${timing.lintMs}ms`);\n log.debug(`Process: ${timing.processMs}ms`);\n log.debug(`Total: ${totalMs}ms | Files: ${filesScanned} | ${filesScanned > 0 ? Math.round(totalMs / filesScanned) : 0}ms/file`);\n }\n\n return {\n files,\n totalErrors,\n totalWarnings,\n totalIssues: totalErrors + totalWarnings,\n filesScanned,\n ruleBreakdown,\n topFiles,\n durationMs: Date.now() - overallStart,\n timing,\n ecosystemIssues,\n parserErrors,\n tsParserAvailable: runner.tsParserAvailable,\n };\n}\n","import chalk from 'chalk';\nimport type { EcosystemIssue, ParserError } from '../utils/eslint-runner.js';\n\n// ── Category icon + color map ──────────────────────────────────────────────────\n\nconst CATEGORY_ICONS: Record<string, string> = {\n Security: '🔴',\n Reliability: '🟠',\n 'Async Stability': '🟡',\n 'AI Patterns': '🔵',\n};\n\nconst CATEGORY_ORDER = ['Security', 'Reliability', 'Async Stability', 'AI Patterns'];\n\nexport { CATEGORY_ICONS, CATEGORY_ORDER };\n\n// ── Rule → category map ────────────────────────────────────────────────────────\n\nexport const RULE_CATEGORY: Record<string, string> = {\n 'ai-guard/no-empty-catch': 'Reliability',\n 'ai-guard/no-broad-exception': 'Reliability',\n 'ai-guard/no-catch-log-rethrow': 'Reliability',\n 'ai-guard/no-catch-without-use': 'Reliability',\n 'ai-guard/no-floating-promise': 'Async Stability',\n 'ai-guard/no-await-in-loop': 'Async Stability',\n 'ai-guard/no-async-array-callback': 'Async Stability',\n 'ai-guard/no-async-without-await': 'Async Stability',\n 'ai-guard/no-redundant-await': 'Async Stability',\n 'ai-guard/no-hardcoded-secret': 'Security',\n 'ai-guard/no-eval-dynamic': 'Security',\n 'ai-guard/no-sql-string-concat': 'Security',\n 'ai-guard/no-unsafe-deserialize': 'Security',\n 'ai-guard/require-auth-middleware': 'Security',\n 'ai-guard/require-authz-check': 'Security',\n 'ai-guard/no-console-in-handler': 'AI Patterns',\n 'ai-guard/no-duplicate-logic-block': 'AI Patterns',\n 'ai-guard/no-dead-branch': 'AI Patterns',\n};\n\n// ── Confidence tiers ─────────────────────────────────────────────────\n// high = near-zero FP rate, always investigate\n// medium = context matters, usually valid\n// low = may be intentional, review case-by-case\n// informational = stylistic hint, almost certainly intentional — collapsed by default\n\nexport type ConfidenceTier = 'high' | 'medium' | 'low' | 'informational';\n\nexport const CONFIDENCE_TIER: Record<string, ConfidenceTier> = {\n // High confidence — near-zero false positive rate\n 'ai-guard/no-hardcoded-secret': 'high',\n 'ai-guard/no-eval-dynamic': 'high',\n 'ai-guard/no-floating-promise': 'high',\n 'ai-guard/no-empty-catch': 'high',\n // Medium confidence — context matters, usually valid\n 'ai-guard/no-sql-string-concat': 'medium',\n 'ai-guard/no-await-in-loop': 'medium',\n 'ai-guard/require-auth-middleware': 'medium',\n 'ai-guard/require-authz-check': 'medium',\n 'ai-guard/no-catch-log-rethrow': 'medium',\n 'ai-guard/no-catch-without-use': 'medium',\n 'ai-guard/no-unsafe-deserialize': 'medium',\n // Low confidence — review case-by-case\n 'ai-guard/no-async-array-callback': 'low',\n 'ai-guard/no-dead-branch': 'low',\n 'ai-guard/no-broad-exception': 'low',\n 'ai-guard/no-console-in-handler': 'low',\n 'ai-guard/no-duplicate-logic-block': 'low',\n // Informational — mostly stylistic, high framework FP rate, collapsed by default\n 'ai-guard/no-async-without-await': 'informational',\n 'ai-guard/no-redundant-await': 'informational',\n};\n\n/** Returns true if the tier should be collapsed in default (non-verbose) output */\nexport function isCollapsedByDefault(tier: ConfidenceTier): boolean {\n return tier === 'informational';\n}\n\n// ── Ecosystem issue fix suggestions ──────────────────────────────────────────\n\nconst ECOSYSTEM_FIX_HINTS: Record<string, string> = {\n 'react-hooks/exhaustive-deps': 'npm install --save-dev eslint-plugin-react-hooks',\n 'react-hooks/rules-of-hooks': 'npm install --save-dev eslint-plugin-react-hooks',\n '@typescript-eslint/': 'npm install --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser',\n 'import/': 'npm install --save-dev eslint-plugin-import',\n 'jsx-a11y/': 'npm install --save-dev eslint-plugin-jsx-a11y',\n 'prettier/': 'npm install --save-dev eslint-plugin-prettier',\n};\n\nfunction getEcosystemFix(ruleId: string | null): string | null {\n if (!ruleId) return null;\n for (const [prefix, fix] of Object.entries(ECOSYSTEM_FIX_HINTS)) {\n if (ruleId.startsWith(prefix)) return fix;\n }\n return null;\n}\n\n// ── Logger ────────────────────────────────────────────────────────────────────\n\nconst PREFIX = {\n success: chalk.green('✔'),\n error: chalk.red('✖'),\n warn: chalk.yellow('⚠'),\n info: chalk.cyan('ℹ'),\n section: chalk.bold.white,\n bullet: chalk.gray('•'),\n ecosystem: chalk.yellow('⚠'),\n parser: chalk.magenta('⚡'),\n};\n\nexport const log = {\n info(msg: string): void {\n console.log(` ${PREFIX.info} ${chalk.white(msg)}`);\n },\n\n success(msg: string): void {\n console.log(` ${PREFIX.success} ${chalk.green(msg)}`);\n },\n\n warn(msg: string): void {\n console.log(` ${PREFIX.warn} ${chalk.yellow(msg)}`);\n },\n\n error(msg: string): void {\n console.error(` ${PREFIX.error} ${chalk.red(msg)}`);\n },\n\n section(title: string): void {\n console.log('');\n console.log(chalk.bold.cyan(` ── ${title} ──`));\n console.log('');\n },\n\n /**\n * Ecosystem section — distinct styling to communicate it's NOT ai-guard output\n */\n ecosystemSection(title: string): void {\n console.log('');\n console.log(chalk.bold.yellow(` ── ${title} ──`) + chalk.dim(' (not ai-guard findings)'));\n console.log('');\n },\n\n rule(ruleName: string, count: number): void {\n console.log(\n ` ${PREFIX.bullet} ${chalk.yellow(ruleName)} ${chalk.gray(`(${count} issue${count !== 1 ? 's' : ''})`)}`,\n );\n },\n\n file(filePath: string, count: number): void {\n console.log(\n ` ${PREFIX.bullet} ${chalk.white(filePath)} ${chalk.gray(`→ ${count} issue${count !== 1 ? 's' : ''}`)}`,\n );\n },\n\n issue(msg: string, severity: 1 | 2, line: number, col: number): void {\n const icon = severity === 2 ? chalk.red('error') : chalk.yellow(' warn');\n console.log(\n ` ${chalk.gray(`${line}:${col}`).padEnd(12)} ${icon} ${chalk.white(msg)}`,\n );\n },\n\n /**\n * Print an ESLint ecosystem issue (missing rule definition, foreign plugin rule, etc.)\n * with a clear disclaimer that this is NOT an ai-guard finding.\n */\n ecosystemIssue(issue: EcosystemIssue, count = 1): void {\n const ruleLabel = issue.ruleId ? chalk.yellow(issue.ruleId) : chalk.gray('(no rule id)');\n const typeLabel =\n issue.type === 'missing-rule'\n ? chalk.dim('[missing rule definition]')\n : issue.type === 'config-error'\n ? chalk.dim('[config error]')\n : chalk.dim('[foreign rule]');\n\n const countLabel = count > 1 ? chalk.gray(` × ${count}`) : '';\n\n console.log(` ${PREFIX.ecosystem} ${ruleLabel} ${typeLabel}${countLabel}`);\n console.log(` ${chalk.gray('File:')} ${chalk.dim(issue.filePath)}${issue.line > 0 ? chalk.dim(`:${issue.line}`) : ''}`);\n console.log(` ${chalk.gray('Msg:')} ${chalk.dim(issue.message.slice(0, 120))}`);\n\n const fix = getEcosystemFix(issue.ruleId);\n if (fix) {\n console.log(` ${chalk.cyan('→ Fix:')} ${chalk.yellow(fix)}`);\n }\n console.log(\n chalk.dim(` Note: This comes from your ESLint config, not from ai-guard.`),\n );\n console.log('');\n },\n\n /**\n * Print a parser/syntax error — clearly NOT an ai-guard finding.\n */\n parserError(pe: ParserError): void {\n console.log(` ${PREFIX.parser} ${chalk.magenta('Parse failure')} ${chalk.dim(pe.filePath)}${pe.line > 0 ? chalk.dim(`:${pe.line}`) : ''}`);\n console.log(` ${chalk.dim(pe.message.slice(0, 120))}`);\n console.log('');\n },\n\n /**\n * Print a category summary line with icon, label, and count.\n */\n category(icon: string, label: string, errors: number, warnings: number): void {\n const parts: string[] = [];\n if (errors > 0) parts.push(chalk.red(`${errors} error${errors !== 1 ? 's' : ''}`));\n if (warnings > 0) parts.push(chalk.yellow(`${warnings} warning${warnings !== 1 ? 's' : ''}`));\n const counts = parts.length > 0 ? parts.join(chalk.gray(' · ')) : chalk.gray('0');\n const labelPadded = label.padEnd(18);\n console.log(` ${icon} ${chalk.bold.white(labelPadded)} ${counts}`);\n },\n\n /**\n * Print the scan stats line.\n */\n scanStats(filesScanned: number, filesWithIssues: number, durationMs: number, preset: string): void {\n console.log(\n ` ${chalk.gray('Files scanned:')} ${chalk.white(String(filesScanned))} ` +\n `${chalk.gray('·')} ${chalk.gray('Issues in:')} ${chalk.white(String(filesWithIssues))} file${filesWithIssues !== 1 ? 's' : ''} ` +\n `${chalk.gray('·')} ${chalk.gray('Duration:')} ${chalk.white(durationMs + 'ms')} ` +\n `${chalk.gray('·')} ${chalk.gray('Preset:')} ${chalk.cyan(preset)}`,\n );\n },\n\n divider(): void {\n console.log(chalk.gray(' ' + '─'.repeat(60)));\n },\n\n blank(): void {\n console.log('');\n },\n\n banner(title: string): void {\n console.log('');\n console.log(chalk.bold.bgCyan.black(` ${title} `));\n console.log('');\n },\n\n print(msg: string): void {\n console.log(msg);\n },\n\n debug(msg: string): void {\n if (process.env.AI_GUARD_DEBUG === '1') {\n console.log(` ${chalk.gray('·')} ${chalk.gray(msg)}`);\n }\n },\n};\n","/**\n * version.ts — Single-source-of-truth version for all CLI outputs.\n *\n * Reads from package.json at module load time.\n * All CLI outputs (JSON, SARIF, summary) must use PKG_VERSION from here.\n * Never hardcode version strings in command files.\n */\n\nimport { createRequire } from 'module';\nimport { fileURLToPath } from 'url';\nimport path from 'path';\n\nlet _version: string | undefined;\n\nfunction readVersion(): string {\n try {\n // Method 1: createRequire from ESM context (Node 18+)\n const require_ = createRequire(import.meta.url);\n // Walk up from cli/utils/ to find package.json at project root\n const pkgPath = path.resolve(\n path.dirname(fileURLToPath(import.meta.url)),\n '../../package.json',\n );\n const pkg = require_(pkgPath) as { version?: string };\n if (pkg.version) return pkg.version;\n } catch {\n // Fallback: try process.env injected at build time\n }\n\n // Build-time fallback — tsup can inject this via define\n if (typeof __PKG_VERSION__ !== 'undefined') {\n return __PKG_VERSION__;\n }\n\n return '0.0.0';\n}\n\n/**\n * The current package version string (e.g. \"1.2.1\").\n * Sourced from package.json — never hardcoded.\n */\nexport const PKG_VERSION: string = _version ?? (_version = readVersion());\n\n// Suppress TS \"cannot find name\" — tsup define() injects this at build time\ndeclare const __PKG_VERSION__: string;\n","/**\n * SARIF 2.1.0 output generator for eslint-plugin-ai-guard.\n *\n * SARIF (Static Analysis Results Interchange Format) is the standard format\n * for GitHub Code Scanning, Azure DevOps, and other CI platforms. By outputting\n * SARIF, ai-guard findings appear as PR annotations in GitHub.\n *\n * Spec: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html\n */\n\nimport type { RunResult, IssueDetail, FileResult } from './eslint-runner.js';\nimport { ISSUE_CONFIDENCE, ISSUE_CATEGORY, ISSUE_ASYNC_RISK_TYPE, ISSUE_REMEDIATION } from './eslint-runner.js';\nimport { CONFIDENCE_TIER } from './logger.js';\nimport { PKG_VERSION } from './version.js';\nimport type { ConfidenceTier } from './logger.js';\n\n// ─── SARIF type definitions ────────────────────────────────────────────────────\n\ninterface SarifArtifactLocation {\n uri: string;\n uriBaseId?: string;\n}\n\ninterface SarifRegion {\n startLine: number;\n startColumn?: number;\n endLine?: number;\n endColumn?: number;\n}\n\ninterface SarifPhysicalLocation {\n artifactLocation: SarifArtifactLocation;\n region: SarifRegion;\n}\n\ninterface SarifLocation {\n physicalLocation: SarifPhysicalLocation;\n message?: { text: string };\n}\n\ninterface SarifReportingDescriptor {\n id: string;\n shortDescription: { text: string };\n fullDescription?: { text: string };\n help?: { text: string; markdown?: string };\n helpUri?: string;\n defaultConfiguration?: { level: 'error' | 'warning' | 'note' | 'none' };\n properties?: {\n tags?: string[];\n confidence?: string;\n category?: string;\n 'problem.severity'?: string;\n };\n}\n\ninterface SarifResult {\n ruleId: string;\n level: 'error' | 'warning' | 'note' | 'none';\n kind?: 'fail' | 'open' | 'informational';\n rank?: number; // 0-100 confidence rank for GitHub UI ordering\n message: { text: string };\n locations: SarifLocation[];\n properties?: {\n confidence?: string;\n asyncRiskType?: string;\n category?: string;\n };\n}\n\ninterface SarifTool {\n driver: {\n name: string;\n version: string;\n informationUri: string;\n rules: SarifReportingDescriptor[];\n };\n}\n\ninterface SarifRun {\n tool: SarifTool;\n results: SarifResult[];\n artifacts?: Array<{ location: SarifArtifactLocation }>;\n properties?: Record<string, unknown>;\n}\n\ninterface SarifLog {\n $schema: string;\n version: '2.1.0';\n runs: SarifRun[];\n}\n\n// ─── Rule metadata ────────────────────────────────────────────────────────────\n\nconst RULE_DOCS: Record<string, { shortDesc: string; tags: string[] }> = {\n 'ai-guard/no-empty-catch': { shortDesc: 'Empty catch block silently swallows errors', tags: ['reliability'] },\n 'ai-guard/no-broad-exception': { shortDesc: 'Catching broad Exception/Error masks specific failures', tags: ['reliability'] },\n 'ai-guard/no-catch-log-rethrow': { shortDesc: 'Catch block logs and rethrows — use one or the other', tags: ['reliability'] },\n 'ai-guard/no-catch-without-use': { shortDesc: 'Caught error variable is not used', tags: ['reliability'] },\n 'ai-guard/no-floating-promise': { shortDesc: 'Promise not awaited or error-handled — async failures will be silently swallowed', tags: ['async', 'async-reliability'] },\n 'ai-guard/no-await-in-loop': { shortDesc: 'Sequential await in loop — consider Promise.all for parallel execution', tags: ['async', 'async-reliability', 'performance'] },\n 'ai-guard/no-async-without-await': { shortDesc: 'Async function contains no await expressions', tags: ['async', 'async-reliability'] },\n 'ai-guard/no-async-array-callback': { shortDesc: 'Async callback in array method may not behave as expected', tags: ['async', 'async-reliability'] },\n 'ai-guard/no-redundant-await': { shortDesc: 'Redundant await on already-resolved value', tags: ['async'] },\n 'ai-guard/no-hardcoded-secret': { shortDesc: 'Hardcoded secret or credential detected', tags: ['security', 'secrets'] },\n 'ai-guard/no-eval-dynamic': { shortDesc: 'Dynamic eval or Function constructor is dangerous', tags: ['security'] },\n 'ai-guard/no-sql-string-concat': { shortDesc: 'SQL query built via string concatenation — SQL injection risk', tags: ['security', 'injection'] },\n 'ai-guard/no-unsafe-deserialize': { shortDesc: 'Unsafe deserialization of untrusted data', tags: ['security'] },\n 'ai-guard/require-auth-middleware': { shortDesc: 'Route handler appears to lack authentication middleware', tags: ['security', 'auth'] },\n 'ai-guard/require-authz-check': { shortDesc: 'Handler lacks authorization check', tags: ['security', 'auth'] },\n 'ai-guard/no-console-in-handler': { shortDesc: 'console.log in request handler — use structured logging', tags: ['ai-patterns'] },\n 'ai-guard/no-duplicate-logic-block':{ shortDesc: 'Duplicate logic block detected', tags: ['ai-patterns'] },\n 'ai-guard/no-dead-branch': { shortDesc: 'Dead code branch that can never execute', tags: ['ai-patterns'] },\n};\n\nconst BASE_DOCS_URL = 'https://github.com/YashJadhav21/eslint-plugin-ai-guard/blob/main/docs/rules';\n\n// ─── Confidence → SARIF mapping ──────────────────────────────────────────────\n\nfunction confidenceToSarifLevel(confidence: string | undefined): 'error' | 'warning' | 'note' | 'none' {\n switch (confidence) {\n case 'high': return 'error';\n case 'medium': return 'warning';\n case 'low': return 'warning';\n case 'informational': return 'note';\n default: return 'warning';\n }\n}\n\nfunction confidenceToRank(confidence: string | undefined): number {\n switch (confidence) {\n case 'high': return 90;\n case 'medium': return 60;\n case 'low': return 30;\n case 'informational': return 10;\n default: return 30;\n }\n}\n\nfunction confidenceToGitHubSeverity(confidence: string | undefined): string {\n switch (confidence) {\n case 'high': return 'high';\n case 'medium': return 'medium';\n case 'low': return 'low';\n case 'informational': return 'recommendation';\n default: return 'low';\n }\n}\n\nfunction severityToSarifLevel(severity: 1 | 2): 'error' | 'warning' {\n return severity === 2 ? 'error' : 'warning';\n}\n\nfunction filePathToUri(filePath: string): string {\n // Convert relative paths to file-relative URIs for SARIF\n // SARIF uses %SRCROOT% or similar base IDs; we use a simple relative path\n return filePath.replace(/\\\\/g, '/');\n}\n\nfunction collectUsedRuleIds(result: RunResult): string[] {\n const ids = new Set<string>();\n for (const file of result.files) {\n for (const issue of file.issues) {\n ids.add(issue.ruleId);\n }\n }\n return [...ids].sort();\n}\n\nfunction buildRuleDescriptors(ruleIds: string[]): SarifReportingDescriptor[] {\n return ruleIds.map((id) => {\n const meta = RULE_DOCS[id];\n const shortName = id.replace('ai-guard/', '');\n const confidence = ISSUE_CONFIDENCE[id];\n const category = ISSUE_CATEGORY[id] ?? 'AI Patterns';\n const remediation = ISSUE_REMEDIATION[id];\n\n const helpMarkdown = [\n `**${meta?.shortDesc ?? shortName}**`,\n '',\n remediation ? `**Fix:** ${remediation}` : '',\n '',\n `[View rule documentation](${BASE_DOCS_URL}/${shortName}.md)`,\n ].filter(Boolean).join('\\n');\n\n return {\n id,\n shortDescription: {\n text: meta?.shortDesc ?? `ai-guard rule: ${shortName}`,\n },\n fullDescription: {\n text: meta?.shortDesc ?? `ai-guard rule: ${shortName}`,\n },\n help: {\n text: remediation ?? meta?.shortDesc ?? shortName,\n markdown: helpMarkdown,\n },\n helpUri: `${BASE_DOCS_URL}/${shortName}.md`,\n defaultConfiguration: {\n level: confidenceToSarifLevel(confidence),\n },\n properties: {\n tags: [...(meta?.tags ?? ['ai-guard']), category.toLowerCase().replace(/ /g, '-')],\n confidence: confidence ?? 'low',\n category,\n 'problem.severity': confidenceToGitHubSeverity(confidence),\n },\n };\n });\n}\n\nfunction buildSarifResult(issue: IssueDetail, file: FileResult): SarifResult {\n const confidence = ISSUE_CONFIDENCE[issue.ruleId];\n const asyncRiskType = ISSUE_ASYNC_RISK_TYPE[issue.ruleId];\n const category = ISSUE_CATEGORY[issue.ruleId];\n\n return {\n ruleId: issue.ruleId,\n level: confidenceToSarifLevel(confidence),\n kind: confidence === 'informational' ? 'informational' : 'fail',\n rank: confidenceToRank(confidence),\n message: { text: issue.message },\n locations: [\n {\n physicalLocation: {\n artifactLocation: {\n uri: filePathToUri(file.filePath),\n uriBaseId: '%SRCROOT%',\n },\n region: {\n startLine: Math.max(1, issue.line),\n startColumn: issue.column > 0 ? issue.column : 1,\n ...(issue.endLine !== undefined && { endLine: issue.endLine }),\n ...(issue.endColumn !== undefined && { endColumn: issue.endColumn }),\n },\n },\n message: { text: issue.message },\n },\n ],\n properties: {\n confidence: confidence ?? 'low',\n ...(asyncRiskType && { asyncRiskType }),\n ...(category && { category }),\n },\n };\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Convert a RunResult to a SARIF 2.1.0 log object.\n *\n * Only ai-guard findings are included. Ecosystem issues and parser errors\n * are excluded — they are not ai-guard findings and should not appear in\n * Code Scanning results.\n */\nexport function buildSarifLog(result: RunResult, version = PKG_VERSION): SarifLog {\n const usedRuleIds = collectUsedRuleIds(result);\n const rules = buildRuleDescriptors(usedRuleIds);\n\n const sarifResults: SarifResult[] = [];\n for (const file of result.files) {\n for (const issue of file.issues) {\n sarifResults.push(buildSarifResult(issue, file));\n }\n }\n\n return {\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n version: '2.1.0',\n runs: [\n {\n tool: {\n driver: {\n name: 'ai-guard',\n version,\n informationUri: 'https://github.com/YashJadhav21/eslint-plugin-ai-guard',\n rules,\n },\n },\n results: sarifResults,\n properties: {\n preset: 'recommended',\n filesScanned: result.filesScanned,\n durationMs: result.durationMs,\n ecosystemIssuesCount: result.ecosystemIssues.length,\n parserErrorsCount: result.parserErrors.length,\n },\n },\n ],\n };\n}\n\n/**\n * Serialize a SARIF log to a JSON string.\n * Use this for --sarif flag output: write to stdout or a file.\n */\nexport function sarifToJson(log: SarifLog): string {\n return JSON.stringify(log, null, 2);\n}\n","/**\n * github-summary.ts — Write GitHub step summaries and PR annotations.\n *\n * When running in GitHub Actions, this module:\n * 1. Writes a formatted Markdown table to $GITHUB_STEP_SUMMARY\n * 2. Emits ::error and ::warning annotation commands to stdout\n * (these appear as inline PR code annotations)\n */\n\nimport fs from 'fs';\nimport type { RunResult, IssueDetail } from './eslint-runner.js';\nimport { CONFIDENCE_TIER, RULE_CATEGORY } from './logger.js';\nimport type { ConfidenceTier } from './logger.js';\n\n// ─── Environment availability ─────────────────────────────────────────────────\n\n/**\n * Returns true if GITHUB_STEP_SUMMARY is set and the path is writable.\n * Safe to call in any environment — never throws.\n */\nexport function isGitHubSummaryAvailable(): boolean {\n const summaryPath = process.env.GITHUB_STEP_SUMMARY;\n if (!summaryPath) return false;\n try {\n const fd = fs.openSync(summaryPath, 'a');\n fs.closeSync(fd);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Returns true if GITHUB_OUTPUT is set and writable.\n */\nexport function isGitHubOutputAvailable(): boolean {\n const outputPath = process.env.GITHUB_OUTPUT;\n if (!outputPath) return false;\n try {\n const fd = fs.openSync(outputPath, 'a');\n fs.closeSync(fd);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Soft-warn to stderr only — never stdout, never throws, never fails CI. */\nfunction warnEnvIssue(name: string, filePath: string, err: unknown): void {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `[ai-guard] Warning: Could not write to ${name}=${filePath}: ${msg}\\n`,\n );\n}\n\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface SummaryOptions {\n preset: string;\n scanMode: 'full' | 'changed' | 'staged';\n changedFilesCount?: number;\n failOn?: string;\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction escapeMarkdown(text: string): string {\n return text.replace(/[|`*_[\\]<>]/g, '\\\\$&');\n}\n\nfunction tierEmoji(tier: ConfidenceTier | undefined): string {\n switch (tier) {\n case 'high': return '🔴';\n case 'medium': return '🟡';\n case 'low': return '🔵';\n case 'informational': return '⬜';\n default: return '⬜';\n }\n}\n\nfunction tierLabel(tier: ConfidenceTier | undefined): string {\n switch (tier) {\n case 'high': return 'High';\n case 'medium': return 'Medium';\n case 'low': return 'Low';\n case 'informational': return 'Info';\n default: return 'Low';\n }\n}\n\n// ─── GitHub annotation commands ───────────────────────────────────────────────\n\n/**\n * Emit GitHub Actions annotation commands.\n * These appear as inline code review comments on PRs.\n *\n * Format: ::error file=path,line=N,endLine=N,col=N,title=RuleId::Message\n */\nexport function emitGitHubAnnotations(result: RunResult): void {\n if (process.env.GITHUB_ACTIONS !== 'true') return;\n\n for (const file of result.files) {\n for (const issue of file.issues) {\n const tier = CONFIDENCE_TIER[issue.ruleId] as ConfidenceTier | undefined;\n\n // Only emit annotations for high + medium confidence findings\n // Informational hints should never create PR noise\n if (tier === 'informational') continue;\n\n const level = issue.severity === 2 ? 'error' : 'warning';\n const filePath = file.filePath.replace(/\\\\/g, '/');\n const shortRule = issue.ruleId.replace('ai-guard/', '');\n\n const parts = [`file=${filePath}`, `line=${issue.line}`];\n if (issue.endLine) parts.push(`endLine=${issue.endLine}`);\n if (issue.column > 0) parts.push(`col=${issue.column}`);\n if (issue.endColumn) parts.push(`endColumn=${issue.endColumn}`);\n parts.push(`title=ai-guard/${shortRule}`);\n\n // Message is escaped — GitHub strips markdown in annotations\n const msg = issue.message.replace(/\\n/g, ' ');\n process.stdout.write(`::${level} ${parts.join(',')}::${msg}\\n`);\n }\n }\n}\n\n// ─── GitHub step summary ──────────────────────────────────────────────────────\n\n/**\n * Build the Markdown summary for $GITHUB_STEP_SUMMARY.\n */\nexport function buildGitHubSummaryMarkdown(\n result: RunResult,\n options: SummaryOptions,\n): string {\n const lines: string[] = [];\n\n // Header\n lines.push('## AI Guard — Async Reliability Report');\n lines.push('');\n lines.push(`> **Preset:** \\`${options.preset}\\` &nbsp;|&nbsp; **Mode:** ${options.scanMode === 'changed' ? 'Changed files only' : options.scanMode === 'staged' ? 'Staged files' : 'Full scan'}`);\n if (options.changedFilesCount !== undefined) {\n lines.push(`> **Files scanned:** ${result.filesScanned} (${options.changedFilesCount} changed)`);\n } else {\n lines.push(`> **Files scanned:** ${result.filesScanned}`);\n }\n lines.push(`> **Duration:** ${result.durationMs}ms`);\n lines.push('');\n\n // Status badge\n if (result.totalIssues === 0) {\n lines.push('### ✅ No issues found');\n lines.push('');\n lines.push('All scanned files passed AI Guard reliability checks.');\n lines.push('');\n return lines.join('\\n');\n }\n\n // Signal summary table\n const { high = 0, medium = 0, low = 0, informational = 0 } = buildSignalCounts(result);\n\n if (high > 0) {\n lines.push(`### ⚠️ ${high} high-confidence issue${high !== 1 ? 's' : ''} found`);\n } else if (medium > 0) {\n lines.push(`### 🔵 ${medium} medium-confidence issue${medium !== 1 ? 's' : ''} found`);\n } else {\n lines.push('### ℹ️ Informational hints only');\n }\n lines.push('');\n\n // Category breakdown table\n lines.push('| Category | 🔴 High | 🟡 Medium | 🔵 Low | ⬜ Info |');\n lines.push('|----------|---------|----------|-------|--------|');\n\n const categoryBreakdown = buildCategoryBreakdown(result);\n for (const [cat, counts] of Object.entries(categoryBreakdown)) {\n if ((counts.high + counts.medium + counts.low + counts.informational) === 0) continue;\n lines.push(`| ${cat} | ${counts.high} | ${counts.medium} | ${counts.low} | ${counts.informational} |`);\n }\n lines.push('');\n\n // Top findings table (max 10)\n const allIssues = result.files.flatMap((f) =>\n f.issues.map((i) => ({ ...i, filePath: f.filePath })),\n );\n const actionableIssues = allIssues\n .filter((i) => {\n const tier = CONFIDENCE_TIER[i.ruleId] as ConfidenceTier | undefined;\n return tier !== 'informational';\n })\n .sort((a, b) => {\n const tierOrder = { high: 0, medium: 1, low: 2, informational: 3 };\n const ta = CONFIDENCE_TIER[a.ruleId] as ConfidenceTier | undefined;\n const tb = CONFIDENCE_TIER[b.ruleId] as ConfidenceTier | undefined;\n return (tierOrder[ta ?? 'low'] ?? 2) - (tierOrder[tb ?? 'low'] ?? 2);\n })\n .slice(0, 10);\n\n if (actionableIssues.length > 0) {\n lines.push('### Top Findings');\n lines.push('');\n lines.push('| File | Line | Rule | Confidence |');\n lines.push('|------|------|------|------------|');\n\n for (const issue of actionableIssues) {\n const tier = CONFIDENCE_TIER[issue.ruleId] as ConfidenceTier | undefined;\n const shortFile = issue.filePath.replace(/\\\\/g, '/').split('/').slice(-2).join('/');\n const shortRule = issue.ruleId.replace('ai-guard/', '');\n lines.push(\n `| \\`${escapeMarkdown(shortFile)}\\` | ${issue.line} | \\`${shortRule}\\` | ${tierEmoji(tier)} ${tierLabel(tier)} |`,\n );\n }\n lines.push('');\n }\n\n // Informational hints summary (collapsed)\n if (informational > 0) {\n lines.push('<details>');\n lines.push(`<summary>💡 ${informational} informational hint${informational !== 1 ? 's' : ''} (click to expand)</summary>`);\n lines.push('');\n lines.push('These are stylistic hints with higher false-positive rates in frameworks like Next.js and React. Review manually before acting.');\n lines.push('');\n\n const infoIssues = allIssues\n .filter((i) => {\n const tier = CONFIDENCE_TIER[i.ruleId] as ConfidenceTier | undefined;\n return tier === 'informational';\n })\n .slice(0, 20);\n\n lines.push('| File | Line | Rule |');\n lines.push('|------|------|------|');\n for (const issue of infoIssues) {\n const shortFile = issue.filePath.replace(/\\\\/g, '/').split('/').slice(-2).join('/');\n const shortRule = issue.ruleId.replace('ai-guard/', '');\n lines.push(`| \\`${escapeMarkdown(shortFile)}\\` | ${issue.line} | \\`${shortRule}\\` |`);\n }\n\n lines.push('</details>');\n lines.push('');\n }\n\n // Ecosystem issues (separated)\n if (result.ecosystemIssues.length > 0) {\n lines.push('<details>');\n lines.push(`<summary>🔧 ${result.ecosystemIssues.length} ESLint config issue${result.ecosystemIssues.length !== 1 ? 's' : ''} (not ai-guard findings)</summary>`);\n lines.push('');\n lines.push('These are from your project\\'s ESLint configuration, not from ai-guard rules. Run `ai-guard doctor` to diagnose.');\n lines.push('</details>');\n lines.push('');\n }\n\n // Next steps\n lines.push('---');\n lines.push('');\n lines.push('**Next steps:**');\n if (high > 0 || medium > 0) {\n lines.push('- Review high/medium confidence findings in the **Files changed** tab');\n lines.push('- Run `ai-guard run --verbose` locally to see full details');\n }\n if (informational > 0) {\n lines.push('- Run `ai-guard run --verbose` to expand informational hints');\n }\n lines.push('- Run `ai-guard baseline` to suppress known issues and track only new ones');\n lines.push('');\n lines.push('*Powered by [eslint-plugin-ai-guard](https://github.com/YashJadhav21/eslint-plugin-ai-guard)*');\n\n return lines.join('\\n');\n}\n\nfunction buildSignalCounts(result: RunResult): {\n high: number; medium: number; low: number; informational: number;\n} {\n let high = 0, medium = 0, low = 0, informational = 0;\n for (const file of result.files) {\n for (const issue of file.issues) {\n const tier = CONFIDENCE_TIER[issue.ruleId] as ConfidenceTier | undefined;\n if (tier === 'high') high++;\n else if (tier === 'medium') medium++;\n else if (tier === 'informational') informational++;\n else low++;\n }\n }\n return { high, medium, low, informational };\n}\n\nfunction buildCategoryBreakdown(result: RunResult): Record<string, {\n high: number; medium: number; low: number; informational: number;\n}> {\n const breakdown: Record<string, { high: number; medium: number; low: number; informational: number }> = {};\n\n for (const file of result.files) {\n for (const issue of file.issues) {\n const cat = RULE_CATEGORY[issue.ruleId] ?? 'Other';\n const tier = CONFIDENCE_TIER[issue.ruleId] as ConfidenceTier | undefined;\n if (!breakdown[cat]) breakdown[cat] = { high: 0, medium: 0, low: 0, informational: 0 };\n if (tier === 'high') breakdown[cat].high++;\n else if (tier === 'medium') breakdown[cat].medium++;\n else if (tier === 'informational') breakdown[cat].informational++;\n else breakdown[cat].low++;\n }\n }\n\n return breakdown;\n}\n\n/**\n * Write the step summary to $GITHUB_STEP_SUMMARY file.\n *\n * Behavior:\n * - No-ops gracefully if GITHUB_STEP_SUMMARY is not set\n * - Soft-warns to stderr (never stdout) if the path is set but not writable\n * - Never throws — CI scan output is the primary feedback channel\n */\nexport function writeGitHubSummary(\n result: RunResult,\n options: SummaryOptions,\n): void {\n const summaryPath = process.env.GITHUB_STEP_SUMMARY;\n if (!summaryPath) return; // Not in GitHub Actions — silently no-op\n\n try {\n const markdown = buildGitHubSummaryMarkdown(result, options);\n fs.appendFileSync(summaryPath, markdown + '\\n', { encoding: 'utf-8' });\n } catch (err) {\n // Non-fatal — warn to stderr so it shows in CI logs but never fails the scan\n warnEnvIssue('GITHUB_STEP_SUMMARY', summaryPath, err);\n }\n}\n\n/**\n * Write output parameters to $GITHUB_OUTPUT.\n * Used by the GitHub Action to expose outputs to subsequent steps.\n *\n * Behavior:\n * - No-ops gracefully if GITHUB_OUTPUT is not set\n * - Soft-warns to stderr if the path is set but not writable\n * - Never throws\n */\nexport function writeGitHubOutputs(result: RunResult, sarifPath?: string): void {\n const outputPath = process.env.GITHUB_OUTPUT;\n if (!outputPath) return; // Not in GitHub Actions — silently no-op\n\n const { high, medium, low, informational } = buildSignalCounts(result);\n\n const outputs = [\n `issues-found=${result.totalIssues}`,\n `high-confidence-count=${high}`,\n `medium-confidence-count=${medium}`,\n `low-confidence-count=${low}`,\n `informational-count=${informational}`,\n `files-scanned=${result.filesScanned}`,\n `duration-ms=${result.durationMs}`,\n ...(sarifPath ? [`sarif-file=${sarifPath}`] : []),\n ];\n\n try {\n fs.appendFileSync(outputPath, outputs.join('\\n') + '\\n', { encoding: 'utf-8' });\n } catch (err) {\n warnEnvIssue('GITHUB_OUTPUT', outputPath, err);\n }\n}\n","/**\n * git-diff.ts — Production-grade changed-file detection for PR/staged scanning.\n *\n * Priority order for changed-file detection:\n * 1. GITHUB_BASE_REF / --base set → multi-strategy PR diff (see tryPrDiff)\n * 2. --staged → git diff --cached\n * 3. Default → uncommitted changes (staged + unstaged vs HEAD)\n * 4. Fallback → git unavailable or no changes (caller falls back to full scan)\n *\n * === BUG HISTORY ===\n * Phase 2A had two stacked bugs that caused PR diff to silently return 0 files:\n *\n * Bug 1 — Operator precedence:\n * const effectiveBase = base ?? env ? `origin/${env}` : undefined;\n * Parsed as: (base ?? env) ? `origin/${env}` : undefined\n * → When base=\"origin/main\" was passed in, effectiveBase became \"origin/\"\n *\n * Bug 2 — Double origin/ prefix:\n * changed.ts prepended `origin/` to baseRef, then git-diff.ts also added `origin/`\n * → git merge-base HEAD origin/origin/main → always fails silently\n *\n * Both are fixed in Phase 2B.\n */\n\nimport { execSync } from 'child_process';\nimport path from 'path';\nimport fs from 'fs';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ChangedFilesOptions {\n /** Scan only staged (git add'd) files */\n staged?: boolean;\n /** Base branch name to diff against — raw name like \"main\" or \"develop\".\n * Do NOT pre-prefix with \"origin/\". This function handles normalization. */\n base?: string;\n /** Working directory for git commands */\n cwd?: string;\n /** Only return files matching these extensions */\n extensions?: string[];\n /** Filter to files under this subdirectory (monorepo support) */\n workingDirectory?: string;\n /** Enable verbose git debug output */\n debug?: boolean;\n}\n\nexport interface GitDiffDebugInfo {\n /** The raw base ref used (after normalization) */\n resolvedBase?: string;\n /** The merge-base commit SHA (if resolved) */\n mergeBase?: string;\n /** Strategies attempted in order */\n strategiesAttempted: string[];\n /** Which strategy succeeded (or null if none) */\n strategySucceeded: string | null;\n /** Whether the repo is a shallow clone */\n isShallowClone: boolean;\n /** Whether HEAD is detached */\n isDetachedHead: boolean;\n /** Raw file count before filtering */\n rawFileCount: number;\n /** Files dropped by extension filter */\n droppedByExtension: number;\n /** Files dropped by ignore-prefix filter */\n droppedByIgnore: number;\n /** Files dropped because they don't exist on disk */\n droppedMissing: number;\n /** Files dropped by working-directory filter */\n droppedByWorkingDir: number;\n}\n\nexport interface ChangedFilesResult {\n files: string[];\n mode: 'pr-diff' | 'staged' | 'uncommitted' | 'fallback';\n base?: string;\n totalDetected: number;\n filteredOut: number;\n /** Diagnostic information — always present, useful for --debug-git */\n debugInfo: GitDiffDebugInfo;\n /** Human-readable reason when files.length === 0 and mode !== 'fallback' */\n zeroFilesReason?: string;\n}\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\nconst DEFAULT_EXTENSIONS = ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs', '.mts', '.cts'];\n\nconst IGNORE_PREFIXES = [\n 'node_modules/',\n 'dist/',\n 'build/',\n '.next/',\n 'out/',\n 'coverage/',\n '.cache/',\n '.turbo/',\n '.nx/',\n 'vendor/',\n 'tmp/',\n 'temp/',\n '__generated__/',\n 'generated/',\n 'storybook-static/',\n '.expo/',\n '.svelte-kit/',\n];\n\n// ─── Low-level git runner ─────────────────────────────────────────────────────\n\nfunction runGit(args: string, cwd: string): string | null {\n try {\n return execSync(`git ${args}`, {\n cwd,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 15000,\n }).trim();\n } catch {\n return null;\n }\n}\n\nfunction isGitAvailable(cwd: string): boolean {\n return runGit('rev-parse --is-inside-work-tree', cwd) === 'true';\n}\n\nfunction isShallowClone(cwd: string): boolean {\n return runGit('rev-parse --is-shallow-repository', cwd) === 'true';\n}\n\nfunction isDetachedHead(cwd: string): boolean {\n const result = runGit('symbolic-ref --quiet HEAD', cwd);\n return result === null;\n}\n\n/**\n * Detect the default upstream branch (e.g., \"main\", \"master\", \"develop\").\n * Used when no base branch is specified or detectable.\n */\nfunction detectDefaultBranch(cwd: string): string | null {\n // Try origin/HEAD (most reliable)\n const symbolic = runGit('symbolic-ref refs/remotes/origin/HEAD', cwd);\n if (symbolic) {\n const match = /refs\\/remotes\\/origin\\/(.+)$/.exec(symbolic);\n if (match) return match[1];\n }\n\n // Try common branch names\n for (const candidate of ['main', 'master', 'develop', 'development']) {\n const check = runGit(`rev-parse --verify origin/${candidate}`, cwd);\n if (check) return candidate;\n const checkLocal = runGit(`rev-parse --verify ${candidate}`, cwd);\n if (checkLocal) return candidate;\n }\n\n return null;\n}\n\n// ─── Ref normalization ────────────────────────────────────────────────────────\n\n/**\n * Normalize a base branch name to a form usable in git diff.\n * Strips leading \"origin/\" — the caller decides whether to use local or remote ref.\n * Returns the raw branch name (e.g. \"main\", \"develop\").\n */\nfunction normalizeBranchName(ref: string): string {\n return ref.replace(/^origin\\//, '').trim();\n}\n\n// ─── PR diff strategies ───────────────────────────────────────────────────────\n\ninterface DiffResult {\n output: string;\n strategy: string;\n mergeBase?: string;\n}\n\n/**\n * Try multiple strategies to get the PR diff.\n * Returns on first success. Never throws.\n *\n * Strategy order:\n * 1. merge-base with origin/branch (most accurate for GitHub Actions)\n * 2. merge-base with local branch ref (works locally)\n * 3. Direct diff with origin/branch (fallback for detached HEAD)\n * 4. Direct diff with local branch (further fallback)\n * 5. HEAD~1 (last-commit fallback — shallow clones, initial PRs)\n */\nfunction tryPrDiff(\n branch: string,\n cwd: string,\n debugInfo: GitDiffDebugInfo,\n): DiffResult | null {\n const rawBranch = normalizeBranchName(branch);\n\n // Strategy 1: merge-base with origin/branch\n {\n const strategy = `merge-base HEAD origin/${rawBranch}`;\n debugInfo.strategiesAttempted.push(strategy);\n const mergeBase = runGit(`merge-base HEAD origin/${rawBranch}`, cwd);\n if (mergeBase) {\n debugInfo.mergeBase = mergeBase;\n const out = runGit(`diff --name-only --diff-filter=ACMRT ${mergeBase}`, cwd);\n if (out !== null) {\n debugInfo.strategySucceeded = strategy;\n return { output: out, strategy, mergeBase };\n }\n }\n }\n\n // Strategy 2: merge-base with local branch\n {\n const strategy = `merge-base HEAD ${rawBranch}`;\n debugInfo.strategiesAttempted.push(strategy);\n const mergeBase = runGit(`merge-base HEAD ${rawBranch}`, cwd);\n if (mergeBase) {\n if (!debugInfo.mergeBase) debugInfo.mergeBase = mergeBase;\n const out = runGit(`diff --name-only --diff-filter=ACMRT ${mergeBase}`, cwd);\n if (out !== null) {\n debugInfo.strategySucceeded = strategy;\n return { output: out, strategy, mergeBase };\n }\n }\n }\n\n // Strategy 3: direct diff with origin/branch\n {\n const strategy = `diff origin/${rawBranch}...HEAD`;\n debugInfo.strategiesAttempted.push(strategy);\n const out = runGit(`diff --name-only --diff-filter=ACMRT origin/${rawBranch}...HEAD`, cwd);\n if (out !== null) {\n debugInfo.strategySucceeded = strategy;\n return { output: out, strategy };\n }\n }\n\n // Strategy 4: direct diff with local branch\n {\n const strategy = `diff ${rawBranch}...HEAD`;\n debugInfo.strategiesAttempted.push(strategy);\n const out = runGit(`diff --name-only --diff-filter=ACMRT ${rawBranch}...HEAD`, cwd);\n if (out !== null) {\n debugInfo.strategySucceeded = strategy;\n return { output: out, strategy };\n }\n }\n\n // Strategy 5: HEAD~1 (last commit only — shallow clone safety net)\n {\n const strategy = 'diff HEAD~1 (shallow fallback)';\n debugInfo.strategiesAttempted.push(strategy);\n const out = runGit('diff --name-only --diff-filter=ACMRT HEAD~1', cwd);\n if (out !== null) {\n debugInfo.strategySucceeded = strategy;\n return { output: out, strategy };\n }\n }\n\n debugInfo.strategySucceeded = null;\n return null;\n}\n\n// ─── File filtering ───────────────────────────────────────────────────────────\n\nfunction filterFiles(\n rawFiles: string[],\n extensions: string[],\n workingDirectory: string | undefined,\n cwd: string,\n debugInfo: GitDiffDebugInfo,\n): string[] {\n const kept: string[] = [];\n\n for (const rel of rawFiles) {\n // Normalize to POSIX separators for consistent matching\n const normalized = rel.replace(/\\\\/g, '/').trim();\n if (!normalized) continue;\n\n // Extension filter\n const ext = path.extname(normalized).toLowerCase();\n if (!extensions.includes(ext)) {\n debugInfo.droppedByExtension++;\n continue;\n }\n\n // Ignore prefix filter\n if (IGNORE_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {\n debugInfo.droppedByIgnore++;\n continue;\n }\n\n // Working directory filter (monorepo subdirectory scoping)\n if (workingDirectory) {\n const wdNorm = workingDirectory.replace(/\\\\/g, '/').replace(/\\/$/, '');\n if (!normalized.startsWith(wdNorm + '/') && normalized !== wdNorm) {\n debugInfo.droppedByWorkingDir++;\n continue;\n }\n }\n\n // Ensure file still exists on disk (may have been deleted in the PR)\n const abs = path.resolve(cwd, normalized);\n if (!fs.existsSync(abs)) {\n debugInfo.droppedMissing++;\n continue;\n }\n\n kept.push(abs);\n }\n\n return kept;\n}\n\nfunction parseFileList(output: string): string[] {\n return output\n .split('\\n')\n .map((f) => f.trim())\n .filter(Boolean);\n}\n\n// ─── Core detection ───────────────────────────────────────────────────────────\n\n/**\n * Detect changed files for targeted scanning.\n *\n * Returns absolute paths to scannable files. When files is empty:\n * - Check mode: 'fallback' means git was unavailable → caller should do full scan\n * - Check zeroFilesReason for a human-readable explanation\n * - Check debugInfo.strategiesAttempted to see what was tried\n *\n * IMPORTANT: Pass raw branch names (e.g., \"main\"), NOT pre-prefixed refs.\n * This function handles all ref normalization internally.\n */\nexport function getChangedFiles(\n options: ChangedFilesOptions = {},\n): ChangedFilesResult {\n const {\n staged = false,\n base,\n cwd = process.cwd(),\n extensions = DEFAULT_EXTENSIONS,\n workingDirectory,\n debug = false,\n } = options;\n\n const debugInfo: GitDiffDebugInfo = {\n strategiesAttempted: [],\n strategySucceeded: null,\n isShallowClone: false,\n isDetachedHead: false,\n rawFileCount: 0,\n droppedByExtension: 0,\n droppedByIgnore: 0,\n droppedMissing: 0,\n droppedByWorkingDir: 0,\n };\n\n if (!isGitAvailable(cwd)) {\n return {\n files: [],\n mode: 'fallback',\n totalDetected: 0,\n filteredOut: 0,\n debugInfo,\n zeroFilesReason: 'Git is not available in this directory. Run inside a git repository.',\n };\n }\n\n // Populate git state diagnostics\n debugInfo.isShallowClone = isShallowClone(cwd);\n debugInfo.isDetachedHead = isDetachedHead(cwd);\n\n // ── Resolve base branch ───────────────────────────────────────────────────\n // FIX: Explicitly separate env-based base from option-based base.\n // Never concatenate them — that was the source of the double-prefix bug.\n const envBase = process.env.GITHUB_BASE_REF\n ? normalizeBranchName(process.env.GITHUB_BASE_REF)\n : undefined;\n\n // Option `base` takes priority over env, then env, then auto-detect\n const resolvedBranch: string | undefined = base\n ? normalizeBranchName(base)\n : envBase;\n\n debugInfo.resolvedBase = resolvedBranch;\n\n let rawOutput: string | null = null;\n let mode: ChangedFilesResult['mode'];\n let usedBase: string | undefined;\n let zeroFilesReason: string | undefined;\n\n if (staged) {\n // ── Staged mode ─────────────────────────────────────────────────────────\n rawOutput = runGit('diff --name-only --cached --diff-filter=ACMRT', cwd);\n mode = 'staged';\n debugInfo.strategiesAttempted.push('git diff --cached');\n if (rawOutput !== null) debugInfo.strategySucceeded = 'git diff --cached';\n if (!rawOutput) {\n zeroFilesReason = 'No staged files found. Run `git add <files>` before using --staged.';\n }\n } else if (resolvedBranch) {\n // ── PR diff mode ─────────────────────────────────────────────────────────\n mode = 'pr-diff';\n usedBase = resolvedBranch;\n\n const diffResult = tryPrDiff(resolvedBranch, cwd, debugInfo);\n\n if (diffResult) {\n rawOutput = diffResult.output;\n } else {\n // All strategies failed\n const shallow = debugInfo.isShallowClone\n ? ' Shallow clone detected — try fetch-depth: 0 in your workflow.'\n : '';\n const detached = debugInfo.isDetachedHead\n ? ' HEAD is detached — ensure checkout fetches the branch.'\n : '';\n zeroFilesReason =\n `PR diff failed against \"${resolvedBranch}\". ` +\n `Tried: ${debugInfo.strategiesAttempted.join(', ')}.${shallow}${detached} ` +\n `Run with --debug-git for full diagnosis.`;\n }\n } else {\n // ── Uncommitted changes mode ─────────────────────────────────────────────\n mode = 'uncommitted';\n const staged_ = runGit('diff --name-only --cached --diff-filter=ACMRT', cwd) ?? '';\n const unstaged = runGit('diff --name-only --diff-filter=ACMRT', cwd) ?? '';\n debugInfo.strategiesAttempted.push('git diff --cached', 'git diff (unstaged)');\n const combined = new Set([...parseFileList(staged_), ...parseFileList(unstaged)]);\n rawOutput = [...combined].join('\\n');\n if (rawOutput) debugInfo.strategySucceeded = 'uncommitted changes';\n if (!rawOutput) {\n zeroFilesReason =\n 'No uncommitted changes found. ' +\n 'Use --pr to scan PR changes, or --staged for staged files.';\n }\n }\n\n if (!rawOutput) {\n return {\n files: [],\n mode,\n base: usedBase,\n totalDetected: 0,\n filteredOut: 0,\n debugInfo,\n zeroFilesReason,\n };\n }\n\n const rawFiles = parseFileList(rawOutput);\n debugInfo.rawFileCount = rawFiles.length;\n\n const kept = filterFiles(rawFiles, extensions, workingDirectory, cwd, debugInfo);\n const dropped =\n debugInfo.droppedByExtension +\n debugInfo.droppedByIgnore +\n debugInfo.droppedByWorkingDir +\n debugInfo.droppedMissing;\n\n if (kept.length === 0 && rawFiles.length > 0) {\n zeroFilesReason =\n `${rawFiles.length} changed file${rawFiles.length !== 1 ? 's' : ''} detected but all filtered out. ` +\n `Extension filter: ${debugInfo.droppedByExtension}, ` +\n `ignored paths: ${debugInfo.droppedByIgnore}, ` +\n `missing from disk: ${debugInfo.droppedMissing}.`;\n }\n\n return {\n files: kept,\n mode,\n base: usedBase,\n totalDetected: rawFiles.length,\n filteredOut: dropped,\n debugInfo,\n zeroFilesReason: kept.length === 0 ? zeroFilesReason : undefined,\n };\n}\n\n// ─── Environment helpers ──────────────────────────────────────────────────────\n\n/** Returns true if running in GitHub Actions environment. */\nexport function isGitHubActions(): boolean {\n return process.env.GITHUB_ACTIONS === 'true';\n}\n\n/** Returns the GitHub base ref for PR scanning, if available (e.g. \"main\"). */\nexport function getGitHubBaseRef(): string | undefined {\n return process.env.GITHUB_BASE_REF || undefined;\n}\n\n/** Returns the GitHub step summary file path, if available. */\nexport function getGitHubSummaryPath(): string | undefined {\n return process.env.GITHUB_STEP_SUMMARY || undefined;\n}\n\n/** Returns the GitHub output file path, if available. */\nexport function getGitHubOutputPath(): string | undefined {\n return process.env.GITHUB_OUTPUT || undefined;\n}\n","/**\n * changed.ts — ai-guard changed command.\n *\n * Scans only the files that have changed in a PR or working tree,\n * instead of the full project. This is the primary CI/CD scan mode.\n *\n * Usage:\n * ai-guard changed # Uncommitted changes + staged\n * ai-guard changed --pr # PR diff vs base branch (auto-detects GITHUB_BASE_REF)\n * ai-guard changed --staged # Staged files only\n * ai-guard changed --base main # Diff vs specific branch\n * ai-guard changed --path packages/web # Filter to subdirectory (monorepo)\n */\n\nimport type { Command } from 'commander';\nimport path from 'path';\nimport fs from 'fs';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { runEslint, type Preset, type EcosystemIssue, ISSUE_CONFIDENCE } from '../utils/eslint-runner.js';\nimport { log, CONFIDENCE_TIER, RULE_CATEGORY, CATEGORY_ICONS, CATEGORY_ORDER, type ConfidenceTier, isCollapsedByDefault } from '../utils/logger.js';\nimport { buildSarifLog, sarifToJson } from '../utils/sarif.js';\nimport {\n getChangedFiles,\n isGitHubActions,\n getGitHubBaseRef,\n} from '../utils/git-diff.js';\nimport {\n emitGitHubAnnotations,\n writeGitHubSummary,\n writeGitHubOutputs,\n buildGitHubSummaryMarkdown,\n} from '../utils/github-summary.js';\nimport { printGitDebug, printCIDebug } from '../utils/debug.js';\nimport { PKG_VERSION } from '../utils/version.js';\nimport { getRunExitCode, formatIssueCount, renderIssuesByFile, partitionByTier, buildSignalSummary, resolveExitCode } from './run.js';\nimport type { RunResult } from '../utils/eslint-runner.js';\n\n// ─── Register ─────────────────────────────────────────────────────────────────\n\nexport function registerChangedCommand(program: Command): void {\n program\n .command('changed')\n .description('Scan only changed files in the current PR or working tree (fastest CI mode)')\n .option('--pr', 'Scan files changed vs base branch (auto-detects GITHUB_BASE_REF in CI)')\n .option('--staged', 'Scan only staged (git add\\'d) files')\n .option('--base <branch>', 'Base branch to diff against (raw name: main, develop — not origin/main)')\n .option('--path <dir>', 'Root path / working directory for scanning', '.')\n .option('--strict', 'Use the strict rule preset (all rules at error)')\n .option('--security', 'Use the security-only rule preset')\n .option('--fail-on <level>', 'Fail CI on: high | medium | any | errors | none', 'high')\n .option('--json', 'Output results as JSON')\n .option('--sarif', 'Output results as SARIF 2.1.0 (for GitHub Code Scanning)')\n .option('--sarif-output <file>', 'Write SARIF to this file path')\n .option('--sarif-stdout', 'Force SARIF to stdout even in CI (overrides auto-file behavior)')\n .option('--github-summary', 'Write GitHub step summary (auto-enabled in GitHub Actions)')\n .option('--max-warnings <n>', 'Fail if warnings exceed this count',\n (v: string) => Number.parseInt(v, 10))\n .option('--verbose', 'Expand all findings (disable grouping)')\n .option('--quiet', 'Show errors only')\n .option('--debug-timing', 'Print per-phase timing diagnostics')\n .option('--debug-git', 'Print full git resolution trace (useful for diagnosing zero-file issues)')\n .option('--debug-ci', 'Print CI environment state (GITHUB_* vars, SARIF path, summary path)')\n .action(async (opts: {\n pr?: boolean;\n staged?: boolean;\n base?: string;\n path: string;\n strict?: boolean;\n security?: boolean;\n failOn: string;\n json?: boolean;\n sarif?: boolean;\n sarifOutput?: string;\n sarifStdout?: boolean;\n githubSummary?: boolean;\n maxWarnings?: number;\n verbose?: boolean;\n quiet?: boolean;\n debugTiming?: boolean;\n debugGit?: boolean;\n debugCi?: boolean;\n }) => {\n const preset: Preset = opts.strict ? 'strict' : opts.security ? 'security' : 'recommended';\n const inCI = isGitHubActions();\n // FIX: Pass raw branch name — getChangedFiles owns all ref normalization.\n // Previously, changed.ts prepended origin/ here AND git-diff.ts did it again\n // → git merge-base HEAD origin/origin/main — always fails.\n const baseRef = opts.base ?? (opts.pr || inCI ? getGitHubBaseRef() : undefined);\n\n // Resolve SARIF output path:\n // - CI: default to file output (predictable for upload-sarif)\n // - local: stdout unless --sarif-output specified\n // - --sarif-stdout: force stdout in any environment\n const sarifToFile = opts.sarif && !opts.sarifStdout && (opts.sarifOutput || inCI);\n const resolvedSarifPath = opts.sarifOutput ?? (sarifToFile ? 'ai-guard-results.sarif' : undefined);\n\n if (!opts.json && !opts.sarif) {\n log.banner('AI GUARD');\n }\n\n // ── Debug CI ────────────────────────────────────────────────────────────\n if (opts.debugCi) {\n const { printCIDebug } = await import('../utils/debug.js');\n printCIDebug({\n isGitHubActions: inCI,\n githubBaseRef: process.env.GITHUB_BASE_REF,\n githubSha: process.env.GITHUB_SHA,\n githubRef: process.env.GITHUB_REF,\n githubRepository: process.env.GITHUB_REPOSITORY,\n githubWorkflow: process.env.GITHUB_WORKFLOW,\n githubRunId: process.env.GITHUB_RUN_ID,\n githubEventName: process.env.GITHUB_EVENT_NAME,\n githubStepSummary: process.env.GITHUB_STEP_SUMMARY,\n githubOutput: process.env.GITHUB_OUTPUT,\n sarifOutputPath: resolvedSarifPath,\n preset,\n failOn: opts.failOn,\n scanMode: opts.staged ? 'staged' : baseRef ? 'pr-diff' : 'uncommitted',\n });\n }\n\n // ── Detect changed files ─────────────────────────────────────────────────\n const cwd = process.cwd();\n const resolvedPath = path.resolve(opts.path);\n const workingDirectory = opts.path !== '.' ? opts.path : undefined;\n\n const spinner = opts.json || opts.sarif\n ? null\n : ora({ text: chalk.dim('Detecting changed files…'), color: 'cyan' }).start();\n\n const changedResult = getChangedFiles({\n staged: opts.staged ?? false,\n base: baseRef,\n cwd,\n workingDirectory,\n debug: opts.debugGit,\n });\n\n // ── Debug git output ─────────────────────────────────────────────────────\n if (opts.debugGit) {\n const { printGitDebug } = await import('../utils/debug.js');\n printGitDebug(changedResult);\n }\n\n if (changedResult.files.length === 0) {\n spinner?.stop();\n\n if (changedResult.mode === 'fallback') {\n // Git not available — fall back to full scan\n if (!opts.json && !opts.sarif) {\n log.warn('Git not available. Falling back to full scan.');\n log.blank();\n }\n // Delegate to full scan\n const result = await runEslint({\n preset,\n targetPath: resolvedPath.toString(),\n debugTiming: opts.debugTiming,\n });\n handleResults(result, opts, preset, 'full', 0, inCI, resolvedSarifPath);\n return;\n }\n\n // Explicit warning when zero files — never silent\n if (!opts.json && !opts.sarif) {\n log.blank();\n log.print(` ${chalk.yellow('⚠')} No changed JS/TS files detected — nothing to scan`);\n if (changedResult.zeroFilesReason) {\n log.print(chalk.dim(` ${changedResult.zeroFilesReason}`));\n }\n if (changedResult.filteredOut > 0) {\n log.print(chalk.dim(` (${changedResult.filteredOut} file${changedResult.filteredOut !== 1 ? 's' : ''} filtered out)`));\n }\n if (!opts.debugGit) {\n log.print(chalk.dim(' Run with --debug-git for full git resolution trace.'));\n }\n log.blank();\n } else if (opts.json) {\n console.log(JSON.stringify({\n version: PKG_VERSION,\n preset,\n scanMode: changedResult.mode,\n changedFiles: 0,\n filesScanned: 0,\n totalIssues: 0,\n totalErrors: 0,\n totalWarnings: 0,\n zeroFilesReason: changedResult.zeroFilesReason,\n debugInfo: opts.debugGit ? changedResult.debugInfo : undefined,\n signalSummary: { high: 0, medium: 0, low: 0, informational: 0, ecosystemIssues: 0, parserErrors: 0 },\n }, null, 2));\n }\n process.exit(0);\n return;\n }\n\n // ── Scan changed files ─────────────────────────────────────────────────\n if (spinner) {\n spinner.text = chalk.dim(`Scanning ${changedResult.files.length} changed file${changedResult.files.length !== 1 ? 's' : ''}…`);\n }\n\n const result = await runEslint({\n preset,\n targetPath: resolvedPath.toString(),\n files: changedResult.files,\n debugTiming: opts.debugTiming,\n });\n\n spinner?.stop();\n\n const scanMode: 'full' | 'changed' | 'staged' =\n changedResult.mode === 'staged' ? 'staged' : 'changed';\n handleResults(result, opts, preset, scanMode, changedResult.files.length, inCI, resolvedSarifPath);\n });\n}\n\n// ─── Shared result handler ────────────────────────────────────────────────────\n\nfunction handleResults(\n result: RunResult,\n opts: {\n failOn: string;\n json?: boolean;\n sarif?: boolean;\n sarifOutput?: string;\n sarifStdout?: boolean;\n githubSummary?: boolean;\n maxWarnings?: number;\n verbose?: boolean;\n quiet?: boolean;\n path: string;\n preset?: string;\n debugGit?: boolean;\n },\n preset: string,\n scanMode: 'full' | 'changed' | 'staged',\n changedFilesCount: number,\n inCI: boolean,\n resolvedSarifPath?: string,\n): Promise<void> {\n // ── GitHub integrations ────────────────────────────────────────────────────\n if (inCI || opts.githubSummary) {\n writeGitHubSummary(result, { preset, scanMode, changedFilesCount });\n writeGitHubOutputs(result, opts.sarifOutput);\n emitGitHubAnnotations(result);\n }\n\n // ── SARIF mode ─────────────────────────────────────────────────────────────\n if (opts.sarif) {\n const sarifLog = buildSarifLog(result);\n const sarifJson = sarifToJson(sarifLog);\n // Write to file if a path was resolved (CI default or explicit --sarif-output)\n if (resolvedSarifPath) {\n fs.writeFileSync(resolvedSarifPath, sarifJson, 'utf-8');\n } else {\n // stdout mode: local usage or --sarif-stdout\n console.log(sarifJson);\n }\n process.exit(getFailOnExitCode(result, opts.failOn, opts.maxWarnings));\n return;\n }\n\n // ── JSON mode ──────────────────────────────────────────────────────────────\n if (opts.json) {\n const signalSummary = buildSignalSummary(result);\n const jsonOutput = {\n version: PKG_VERSION,\n preset,\n scanMode,\n scannedPath: opts.path,\n filesScanned: result.filesScanned,\n changedFilesCount,\n totalErrors: result.totalErrors,\n totalWarnings: result.totalWarnings,\n totalIssues: result.totalIssues,\n durationMs: result.durationMs,\n signalSummary,\n ruleBreakdown: Object.fromEntries(result.ruleBreakdown),\n topFiles: result.topFiles,\n files: result.files,\n ecosystemIssues: result.ecosystemIssues,\n parserErrors: result.parserErrors,\n tsParserAvailable: result.tsParserAvailable,\n };\n console.log(JSON.stringify(jsonOutput, null, 2));\n process.exit(getFailOnExitCode(result, opts.failOn, opts.maxWarnings));\n return;\n }\n\n // ── Human-readable output ──────────────────────────────────────────────────\n const scanModeLabel = scanMode === 'changed'\n ? 'Changed files'\n : scanMode === 'staged'\n ? 'Staged files'\n : 'Full scan';\n\n const modeTag = changedFilesCount > 0\n ? `${changedFilesCount} changed`\n : '';\n\n log.summary(\n result.filesScanned,\n result.totalIssues,\n result.files.filter((f) => f.issues.length > 0).length,\n result.durationMs,\n `${preset} · ${scanModeLabel}${modeTag ? ` (${modeTag})` : ''}` as string,\n );\n\n if (result.totalIssues === 0) {\n log.blank();\n log.success(`No AI issues found — ${result.filesScanned} file${result.filesScanned !== 1 ? 's' : ''} scanned, all clean`);\n log.blank();\n } else {\n const verbose = opts.verbose ?? false;\n const quiet = opts.quiet ?? false;\n const { actionableFiles, informationalFiles } = partitionByTier(result, quiet);\n\n // Category summary\n log.section('Summary by Category');\n const categoryErrors: Record<string, number> = {};\n const categoryWarnings: Record<string, number> = {};\n for (const file of actionableFiles) {\n for (const issue of file.issues) {\n const cat = RULE_CATEGORY[issue.ruleId] ?? 'Other';\n if (issue.severity === 2) categoryErrors[cat] = (categoryErrors[cat] ?? 0) + 1;\n else categoryWarnings[cat] = (categoryWarnings[cat] ?? 0) + 1;\n }\n }\n const allCategories = new Set([...CATEGORY_ORDER, ...Object.keys(categoryErrors), ...Object.keys(categoryWarnings)]);\n const sortedCats = [...allCategories].filter((c) => (categoryErrors[c] ?? 0) + (categoryWarnings[c] ?? 0) > 0)\n .sort((a, b) => {\n const ai = CATEGORY_ORDER.indexOf(a), bi = CATEGORY_ORDER.indexOf(b);\n if (ai !== -1 && bi !== -1) return ai - bi;\n if (ai !== -1) return -1;\n if (bi !== -1) return 1;\n return a.localeCompare(b);\n });\n for (const cat of sortedCats) {\n const icon = CATEGORY_ICONS[cat] ?? '⚪';\n log.category(icon, cat, categoryErrors[cat] ?? 0, categoryWarnings[cat] ?? 0);\n }\n log.blank();\n log.print(` ${chalk.bold('Total:')} ${formatIssueCount(result.totalErrors, result.totalWarnings)}`);\n log.blank();\n\n if (actionableFiles.length > 0) {\n log.section('Issues by File');\n log.blank();\n renderIssuesByFile({ ...result, files: actionableFiles }, verbose, quiet);\n }\n\n const totalInfoCount = informationalFiles.reduce((n, f) => n + f.issues.length, 0);\n if (totalInfoCount > 0 && !quiet) {\n if (verbose) {\n log.section('Informational Hints');\n log.print(chalk.dim(' Stylistic hints with higher false-positive rate — review before acting.'));\n log.blank();\n renderIssuesByFile({ ...result, files: informationalFiles }, true, false);\n } else {\n log.blank();\n log.print(` ${chalk.gray('▸')} ${chalk.gray(`${totalInfoCount} informational hint${totalInfoCount !== 1 ? 's' : ''} — run with ${chalk.cyan('--verbose')} to expand`)}`);\n }\n }\n }\n\n // Ecosystem issues\n if (result.ecosystemIssues.length > 0) {\n log.ecosystemSection('ESLint Config Issues');\n log.print(chalk.dim(' These issues come from your project\\'s ESLint config, not from ai-guard.'));\n log.blank();\n const seen = new Map<string, { issue: EcosystemIssue; count: number }>();\n for (const issue of result.ecosystemIssues) {\n const key = `${issue.ruleId ?? 'null'}::${issue.message}`;\n const existing = seen.get(key);\n if (existing) { existing.count++; } else { seen.set(key, { issue, count: 1 }); }\n }\n for (const { issue, count } of seen.values()) {\n log.ecosystemIssue(issue, count);\n }\n log.blank();\n }\n\n log.divider();\n log.blank();\n log.section('Next Steps');\n if (result.totalIssues > 0) {\n log.info(`Run ${chalk.cyan('ai-guard baseline')} to save these issues and track only new ones`);\n log.info(`Run ${chalk.cyan('ai-guard report')} to generate a shareable HTML report`);\n }\n if (result.ecosystemIssues.length > 0) {\n log.info(`Run ${chalk.cyan('ai-guard doctor')} to diagnose ESLint config issues`);\n }\n log.blank();\n\n process.exit(getFailOnExitCode(result, opts.failOn, opts.maxWarnings));\n}\n\n// ─── Fail-on exit code logic ──────────────────────────────────────────────────\n\n/**\n * Determine exit code based on --fail-on level.\n * Uses ISSUE_CONFIDENCE lookup (statically imported) for tier resolution.\n */\nexport function getFailOnExitCode(\n result: RunResult,\n failOn: string,\n maxWarnings?: number,\n): number {\n return resolveExitCode(result, failOn, maxWarnings);\n}\n","import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport path from 'path';\nimport fs from 'fs';\nimport { detect, isFlat, isLegacy, requiresFlatConfig } from '../utils/detector.js';\nimport {\n generateFlatConfig,\n generateLegacyConfig,\n patchFlatConfig,\n patchLegacyConfig,\n backupConfig,\n readConfig,\n writeConfig,\n getConfigFilePath,\n removeNukeIgnore,\n validateFlatConfigText,\n validateLegacyConfigText,\n type Preset,\n} from '../utils/config-manager.js';\nimport { log } from '../utils/logger.js';\n\n// ─── Flags ────────────────────────────────────────────────────────────────────\n\ninterface InitOptions {\n preset: string;\n flat?: boolean;\n dryRun?: boolean;\n}\n\n// ─── Error classification ────────────────────────────────────────────────────\n\ntype VerifyError =\n | { kind: 'syntax'; message: string }\n | { kind: 'module-not-found'; pkg: string; message: string }\n | { kind: 'unknown'; message: string };\n\nfunction classifyVerifyError(err: unknown): VerifyError {\n const msg = err instanceof Error ? err.message : String(err);\n const clean = msg.replace(/\\s+at\\s+.+/gm, '').trim();\n\n // Module resolution errors\n const modNotFound = clean.match(\n /Cannot find module '([^']+)'|Cannot find package '([^']+)'/,\n );\n if (modNotFound) {\n const pkg = modNotFound[1] ?? modNotFound[2] ?? 'unknown';\n return { kind: 'module-not-found', pkg, message: clean };\n }\n\n // SyntaxError / parse errors\n if (\n clean.includes('SyntaxError') ||\n clean.includes('Unexpected token') ||\n clean.includes('Invalid or unexpected token')\n ) {\n return { kind: 'syntax', message: clean };\n }\n\n return { kind: 'unknown', message: clean };\n}\n\n// ─── Programmatic ESLint verification ────────────────────────────────────────\n\n/**\n * After writing a config, try to load it via ESLint's own API.\n * Returns null on success, a classified error on failure.\n */\nasync function verifyConfigLoads(\n configPath: string,\n cwd: string,\n): Promise<null | VerifyError> {\n try {\n type EslintCtor = new (options: {\n cwd: string;\n overrideConfigFile: string;\n }) => {\n lintText: (code: string, options: { filePath: string }) => Promise<unknown>;\n };\n\n const { ESLint } = await import('eslint') as unknown as { ESLint: EslintCtor };\n\n const eslint = new ESLint({\n cwd,\n overrideConfigFile: configPath,\n });\n\n // Lint an empty JS file — forces ESLint to parse and validate the config\n await eslint.lintText('', {\n filePath: path.join(cwd, '_ai_guard_probe_.js'),\n });\n return null; // success\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n\n // \"No files\" / probe path exclusion errors are not config errors\n if (\n msg.includes('No files matching') ||\n msg.includes('_ai_guard_probe_')\n ) {\n return null;\n }\n\n return classifyVerifyError(err);\n }\n}\n\n// ─── Command registration ─────────────────────────────────────────────────────\n\nexport function registerInitCommand(program: Command): void {\n program\n .command('init')\n .description('Configure eslint-plugin-ai-guard in this project')\n .option('--preset <name>', 'Preset to use: recommended | strict | security', 'recommended')\n .option('--flat', 'Force flat config format (eslint.config.mjs) regardless of ESLint version')\n .option('--dry-run', 'Preview what would change without writing any files')\n .action(async (opts: InitOptions) => {\n const preset = (opts.preset as Preset) ?? 'recommended';\n const cwd = process.cwd();\n const isDryRun = opts.dryRun === true;\n\n log.banner('AI GUARD INIT');\n if (isDryRun) {\n log.print(` ${chalk.yellow('⚑ DRY RUN — no files will be written')}`);\n log.blank();\n }\n log.info('Detecting your project setup…');\n log.blank();\n\n const env = detect(cwd);\n\n // ─── Step 1: Environment report ──────────────────────────────────────────\n\n log.section('Environment');\n\n if (env.eslintVersion) {\n log.success(`ESLint ${env.eslintVersion} detected (v${env.eslintMajor})`);\n } else {\n log.warn('ESLint not found in node_modules');\n }\n\n if (env.pluginInstalled) {\n log.success('eslint-plugin-ai-guard is installed');\n } else {\n log.warn('eslint-plugin-ai-guard not found');\n }\n\n if (env.configType !== 'none') {\n log.success(`ESLint config found: ${chalk.white(path.relative(cwd, env.configPath ?? env.configType))}`);\n } else {\n log.info('No ESLint config found — will generate one');\n }\n\n // Warn about conflicting configs (only if not ESLint v9, as v9 auto-resolves)\n const eslintNeedsFlat = requiresFlatConfig(env.eslintMajor);\n if (env.hasConflictingConfigs && !eslintNeedsFlat) {\n log.blank();\n log.warn('Conflicting configs detected:');\n for (const p of env.allConfigPaths) {\n log.print(` ${chalk.yellow('→')} ${chalk.white(path.relative(cwd, p))}`);\n }\n log.print(` ${chalk.gray('Multiple config formats found — this can cause unpredictable behavior.')}`);\n }\n\n log.blank();\n\n // ─── Step 2: Gate on missing deps ────────────────────────────────────────\n\n const toInstall: string[] = [];\n if (!env.eslintVersion) toInstall.push('eslint');\n if (!env.pluginInstalled) toInstall.push('eslint-plugin-ai-guard');\n\n if (toInstall.length > 0) {\n log.section('Missing Dependencies');\n log.warn('The following packages are not installed:');\n log.blank();\n for (const pkg of toInstall) {\n log.print(` ${chalk.yellow('→')} ${chalk.white(pkg)}`);\n }\n log.blank();\n log.print(` ${chalk.bold('Run this first:')}`);\n log.blank();\n log.print(` ${chalk.cyan(`npm install --save-dev ${toInstall.join(' ')}`)}`);\n log.blank();\n log.print(` Then re-run ${chalk.cyan('ai-guard init')} to complete setup.`);\n log.blank();\n process.exit(1);\n return;\n }\n\n // ─── Step 3: Runtime Safety ─────────────────────────────────────────────\n\n try {\n const { createRequire } = await import('module');\n const { pathToFileURL } = await import('url');\n const req = createRequire(path.join(cwd, '_probe.js'));\n const resolvedPath = req.resolve('eslint-plugin-ai-guard');\n const aiGuard = await import(pathToFileURL(resolvedPath).href);\n const plugin = (aiGuard.default || aiGuard) as {\n configs?: Record<string, { rules?: unknown }>;\n };\n\n const hasPresetRules =\n !!plugin.configs &&\n !!plugin.configs[preset] &&\n !!plugin.configs[preset].rules;\n\n if (!hasPresetRules) {\n // Keep this as informational only; Step 6 performs definitive runtime validation.\n log.debug('Plugin precheck could not verify configs shape; continuing to validation step.');\n }\n } catch (e) {\n // If resolution fails entirely, skip the check; validation step will catch load errors\n const reason = e instanceof Error ? e.message : String(e);\n log.debug(`Skipped plugin precheck: ${reason}`);\n }\n\n // ─── Step 4: Determine config format ────────────────────────────────────\n // Priority:\n // 1. --flat flag forces flat config\n // 2. ESLint v9+ → MUST use flat config\n // 3. ESLint v8 → use legacy; unless an existing flat config is already there\n // 4. No version info → default to flat (safer)\n\n const forceFlat = opts.flat === true;\n const existingIsFlat = isFlat(env.configType);\n const existingIsLegacy = isLegacy(env.configType);\n const useFlat = forceFlat || eslintNeedsFlat || existingIsFlat || env.configType === 'none';\n\n // Guard: ESLint v9 + existing legacy config → migrate, don't re-create legacy\n if (eslintNeedsFlat && existingIsLegacy) {\n log.section('Config Migration Required');\n log.warn(`ESLint v${env.eslintMajor} requires flat config, but a legacy config was found:`);\n log.print(` ${chalk.white(path.relative(cwd, env.configPath!))}`);\n log.blank();\n log.print(` ${chalk.bold('ai-guard will create a new flat config.')}`);\n log.blank();\n }\n\n // ─── Step 5: Apply config change ────────────────────────────────────────\n\n log.section(`Configuring ESLint${isDryRun ? ' (dry run)' : ''}`);\n\n let finalConfigPath: string;\n let configWritten = false;\n\n // Nuke-ignore removal — fix before anything else\n if (env.configPath && env.hasNukeIgnore) {\n const raw = readConfig(env.configPath);\n const { content: fixed, changed } = removeNukeIgnore(raw);\n if (changed) {\n log.warn(`Removed \"**/*\" ignore pattern from ${path.relative(cwd, env.configPath)}`);\n if (!isDryRun) {\n backupConfig(env.configPath);\n writeConfig(env.configPath, fixed);\n log.success('Ignore pattern fixed');\n } else {\n log.print(` ${chalk.gray('[dry-run] would remove nuke-ignore from existing config')}`);\n }\n }\n }\n\n if (env.configType === 'none' || (eslintNeedsFlat && existingIsLegacy)) {\n // ── Generate fresh config ──────────────────────────────────────────────\n const targetName = useFlat ? 'eslint.config.mjs' : '.eslintrc.js';\n finalConfigPath = path.join(cwd, targetName);\n\n const content = useFlat\n ? generateFlatConfig(preset)\n : generateLegacyConfig(preset);\n\n if (isDryRun) {\n log.print(` ${chalk.gray(`[dry-run] would create: ${targetName}`)}`);\n log.blank();\n log.print(chalk.gray('─── Preview ─────────────────────────────────────────────'));\n log.blank();\n for (const line of content.split('\\n')) {\n log.print(chalk.gray(` ${line}`));\n }\n log.blank();\n } else {\n writeConfig(finalConfigPath, content);\n log.success(`Created ${chalk.white(targetName)}`);\n log.info(` Preset: ${chalk.cyan(preset)}`);\n log.info(` Format: ${chalk.cyan(useFlat ? 'ESLint v9 flat config (eslint.config.mjs)' : 'ESLint v8 legacy config (.eslintrc.js)')}`);\n configWritten = true;\n }\n } else if (useFlat && existingIsFlat) {\n // ── Patch existing flat config ─────────────────────────────────────────\n const { isInvalidAiGuardConfig } = await import('../utils/config-manager.js');\n const existing = readConfig(env.configPath!);\n const isInvalid = isInvalidAiGuardConfig(existing);\n const patched = patchFlatConfig(existing, preset);\n\n if (patched === existing && !isInvalid) {\n log.warn('ai-guard is already present in your config — no changes made');\n finalConfigPath = env.configPath!;\n } else if (isDryRun) {\n finalConfigPath = env.configPath!;\n log.print(` ${chalk.gray(`[dry-run] would patch: ${path.relative(cwd, env.configPath!)}`)}`);\n } else {\n const bak = backupConfig(env.configPath!);\n log.info(`Backed up → ${chalk.gray(path.relative(cwd, bak))}`);\n writeConfig(env.configPath!, patched);\n if (isInvalid) {\n log.success(`Detected invalid ai-guard config — repairing ${chalk.white(path.relative(cwd, env.configPath!))}`);\n } else {\n log.success(`Patched ${chalk.white(path.relative(cwd, env.configPath!))}`);\n }\n finalConfigPath = env.configPath!;\n configWritten = true;\n }\n } else {\n // ── Patch existing legacy config ─────────────────────────────────────\n const existing = readConfig(env.configPath!);\n const patched = patchLegacyConfig(existing, preset);\n\n if (patched === existing) {\n log.warn('ai-guard is already present in your config — no changes made');\n finalConfigPath = env.configPath!;\n } else if (isDryRun) {\n finalConfigPath = env.configPath!;\n log.print(` ${chalk.gray(`[dry-run] would patch: ${path.relative(cwd, env.configPath!)}`)}`);\n } else {\n const bak = backupConfig(env.configPath!);\n log.info(`Backed up → ${chalk.gray(path.relative(cwd, bak))}`);\n writeConfig(env.configPath!, patched);\n log.success(`Patched ${chalk.white(path.relative(cwd, env.configPath!))}`);\n finalConfigPath = env.configPath!;\n configWritten = true;\n }\n }\n\n // ── Auto cleanup legacy config (conflict resolution) ───────────────\n if (eslintNeedsFlat) {\n // Find legacy configs that might cause conflicts\n const legacyConfigs = env.allConfigPaths.filter(p => !p.includes('eslint.config.'));\n \n let cleanedUp = false;\n for (const p of legacyConfigs) {\n if (fs.existsSync(p)) {\n if (!isDryRun) {\n try {\n fs.renameSync(p, `${p}.bak`);\n cleanedUp = true;\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n log.warn(`Could not back up ${path.relative(cwd, p)}: ${reason}`);\n }\n } else {\n cleanedUp = true;\n log.print(` ${chalk.gray(`[dry-run] would rename ${path.relative(cwd, p)} to ${path.basename(p)}.bak`)}`);\n }\n }\n }\n if (cleanedUp && !isDryRun) {\n log.success('Legacy config backed up to avoid ESLint conflict');\n }\n }\n\n if (isDryRun) {\n log.blank();\n log.print(` ${chalk.yellow('Dry run complete — no files written.')}`);\n log.print(` Re-run without ${chalk.cyan('--dry-run')} to apply.`);\n log.blank();\n process.exit(0);\n return;\n }\n\n log.blank();\n\n // ─── Step 5: Structural validation ──────────────────────────────────────\n\n log.section('Validation');\n\n if (!fs.existsSync(finalConfigPath)) {\n log.error(`Config file not found after write: ${path.relative(cwd, finalConfigPath)}`);\n log.blank();\n log.print(` ${chalk.bold('Problem:')} File write may have failed.`);\n log.print(` ${chalk.bold('Fix:')} Check disk space and file permissions, then re-run.`);\n log.blank();\n process.exit(1);\n return;\n }\n\n const content = readConfig(finalConfigPath);\n const validationErrors = useFlat\n ? validateFlatConfigText(content)\n : validateLegacyConfigText(content);\n\n if (validationErrors.length > 0) {\n log.warn('Config validation found issues:');\n for (const e of validationErrors) {\n log.print(` ${chalk.red('✖')} ${e}`);\n }\n } else {\n log.success(`Config structure valid: ${chalk.white(path.relative(cwd, finalConfigPath))}`);\n }\n\n // ─── Step 6: Programmatic ESLint load verification ───────────────────────\n\n log.info('Verifying ESLint can load the config…');\n\n const loadError = await verifyConfigLoads(finalConfigPath, cwd);\n if (loadError !== null) {\n log.blank();\n\n if (loadError.kind === 'module-not-found') {\n // Missing dep — config syntax is fine, just need to install the package\n log.warn(`Could not verify: module not found: ${chalk.yellow(loadError.pkg)}`);\n log.blank();\n log.print(` ${chalk.bold('Install the missing package:')}`);\n log.print(` ${chalk.cyan(`npm install --save-dev ${loadError.pkg}`)}`);\n log.print(` Then run ${chalk.cyan('ai-guard doctor')} to confirm.`);\n log.blank();\n // Fall through — config was written correctly; missing dep is user's next step\n } else {\n // Real error — config syntax broken or unknown failure → hard fail\n log.error('ESLint failed to load the generated config.');\n log.blank();\n log.print(` ${chalk.bold('Problem:')}`);\n log.print(` ${chalk.red(loadError.message)}`);\n if (loadError.kind === 'unknown') {\n log.blank();\n log.print(` ${chalk.yellow('Generated config may be using incorrect plugin structure.')}`);\n }\n log.blank();\n log.print(` ${chalk.bold('Fix:')}`);\n log.print(` 1. Check the syntax in ${chalk.cyan(path.relative(cwd, finalConfigPath))}`);\n log.print(` 2. Make sure ${chalk.cyan('eslint-plugin-ai-guard')} is installed`);\n log.print(` 3. Run ${chalk.cyan('ai-guard doctor')} for full diagnostics`);\n log.blank();\n process.exit(1);\n return;\n }\n } else {\n log.success('ESLint loaded config successfully');\n }\n\n\n log.blank();\n\n\n\n // ─── Step 7: Success ─────────────────────────────────────────────────────\n\n log.section('Setup Complete');\n log.blank();\n\n let cleanedUpInfo = false;\n if (eslintNeedsFlat) {\n const legacyConfigs = env.allConfigPaths.filter(p => !p.includes('eslint.config.'));\n cleanedUpInfo = legacyConfigs.some(p => fs.existsSync(`${p}.bak`) && !fs.existsSync(p));\n }\n\n const lingeringConflicts = env.hasConflictingConfigs && !eslintNeedsFlat && !cleanedUpInfo;\n if (loadError === null && !lingeringConflicts) {\n log.print(` ${chalk.green('✔')} ${chalk.bold.green('Configuration validated successfully')}`);\n }\n log.print(` ${chalk.green('✔')} ${chalk.bold('ESLint config:')} ${chalk.cyan(path.relative(cwd, finalConfigPath))}`);\n log.print(` ${chalk.green('✔')} ${chalk.bold('Mode:')} ${chalk.cyan(useFlat ? `Flat config (ESLint v${env.eslintMajor ?? 9})` : `Legacy config (ESLint v${env.eslintMajor ?? 8})`)}`);\n log.print(` ${chalk.green('✔')} ${chalk.bold('Preset:')} ${chalk.cyan(preset)}`);\n log.blank();\n log.info(`Run ${chalk.cyan('npx eslint .')} → lint with your editor integration`);\n log.info(`Run ${chalk.cyan('ai-guard run')} → zero-config scan`);\n log.info(`Run ${chalk.cyan('ai-guard doctor')} → verify the full setup`);\n log.info(`Run ${chalk.cyan('ai-guard baseline')} → save baseline, track only new issues`);\n log.blank();\n });\n}\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport { createRequire } from 'module';\r\n\r\n// ─── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport type ConfigType =\r\n | 'flat-js'\r\n | 'flat-mjs'\r\n | 'flat-cjs'\r\n | 'eslintrc-js'\r\n | 'eslintrc-cjs'\r\n | 'eslintrc-json'\r\n | 'eslintrc-yaml'\r\n | 'none';\r\n\r\nexport interface DetectionResult {\r\n /** Raw version string e.g. \"9.1.0\" — null if not installed */\r\n eslintVersion: string | null;\r\n eslintMajor: number | null;\r\n pluginInstalled: boolean;\r\n configType: ConfigType;\r\n configPath: string | null;\r\n /** All config files found — to detect conflicts */\r\n allConfigPaths: string[];\r\n /** True when a flat config AND a legacy config both exist */\r\n hasConflictingConfigs: boolean;\r\n /** True when config contains a pattern that ignores everything */\r\n hasNukeIgnore: boolean;\r\n}\r\n\r\n// ─── Config file registry ─────────────────────────────────────────────────────\r\n\r\nconst FLAT_CONFIG_FILES: Array<{ file: string; type: ConfigType }> = [\r\n { file: 'eslint.config.js', type: 'flat-js' },\r\n { file: 'eslint.config.mjs', type: 'flat-mjs' },\r\n { file: 'eslint.config.cjs', type: 'flat-cjs' },\r\n];\r\n\r\nconst LEGACY_CONFIG_FILES: Array<{ file: string; type: ConfigType }> = [\r\n { file: '.eslintrc.js', type: 'eslintrc-js' },\r\n { file: '.eslintrc.cjs', type: 'eslintrc-cjs' },\r\n { file: '.eslintrc.json', type: 'eslintrc-json' },\r\n { file: '.eslintrc.yaml', type: 'eslintrc-yaml' },\r\n { file: '.eslintrc.yml', type: 'eslintrc-yaml' },\r\n];\r\n\r\nconst ALL_CONFIG_FILES = [...FLAT_CONFIG_FILES, ...LEGACY_CONFIG_FILES];\r\n\r\n// ─── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\nexport function isPackageInstalled(pkgName: string, cwd = process.cwd()): boolean {\r\n try {\r\n const pkgPath = path.join(cwd, 'node_modules', pkgName, 'package.json');\r\n if (fs.existsSync(pkgPath)) {\r\n return true;\r\n }\r\n\r\n const req = createRequire(path.join(cwd, 'package.json'));\r\n req.resolve(`${pkgName}/package.json`);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Read a package.json version from node_modules.\r\n * Reads directly from disk — no require() involvement — so it always\r\n * reflects the *installed* version even when running inside a bundled binary.\r\n */\r\nexport function getPackageVersion(pkgName: string, cwd = process.cwd()): string | null {\r\n try {\r\n const pkgPath = path.join(cwd, 'node_modules', pkgName, 'package.json');\r\n const resolvedPath = fs.existsSync(pkgPath)\r\n ? pkgPath\r\n : createRequire(path.join(cwd, 'package.json')).resolve(`${pkgName}/package.json`);\r\n const raw = fs.readFileSync(resolvedPath, 'utf-8');\r\n const json = JSON.parse(raw) as { version?: string };\r\n return json.version ?? null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** Parse the major version number from a semver string */\r\nexport function parseMajor(version: string | null): number | null {\r\n if (!version) return null;\r\n const n = parseInt(version.split('.')[0], 10);\r\n return isNaN(n) ? null : n;\r\n}\r\n\r\n// ─── Config detection ─────────────────────────────────────────────────────────\r\n\r\nexport function detectConfigType(cwd = process.cwd()): {\r\n type: ConfigType;\r\n path: string | null;\r\n allPaths: string[];\r\n} {\r\n const found: string[] = [];\r\n let first: { type: ConfigType; path: string } | null = null;\r\n\r\n for (const { file, type } of ALL_CONFIG_FILES) {\r\n const fullPath = path.join(cwd, file);\r\n if (fs.existsSync(fullPath)) {\r\n found.push(fullPath);\r\n if (!first) first = { type, path: fullPath };\r\n }\r\n }\r\n\r\n return {\r\n type: first?.type ?? 'none',\r\n path: first?.path ?? null,\r\n allPaths: found,\r\n };\r\n}\r\n\r\nexport function isFlat(type: ConfigType): boolean {\r\n return type === 'flat-js' || type === 'flat-mjs' || type === 'flat-cjs';\r\n}\r\n\r\nexport function isLegacy(type: ConfigType): boolean {\r\n return (\r\n type === 'eslintrc-js' ||\r\n type === 'eslintrc-cjs' ||\r\n type === 'eslintrc-json' ||\r\n type === 'eslintrc-yaml'\r\n );\r\n}\r\n\r\n/**\r\n * Returns true if the given ESLint major version requires flat config.\r\n * ESLint 9+ uses flat config by default; ESLint 8 uses legacy config.\r\n */\r\nexport function requiresFlatConfig(eslintMajor: number | null): boolean {\r\n return eslintMajor !== null && eslintMajor >= 9;\r\n}\r\n\r\n/**\r\n * Check for \"nuke\" ignore patterns — patterns that silently exclude all files.\r\n * Common culprit: ignorePatterns: [\"**\\/*\"] or ignores: [\"**\\/*\"]\r\n */\r\nfunction detectNukeIgnore(configPath: string | null): boolean {\r\n if (!configPath) return false;\r\n try {\r\n const content = fs.readFileSync(configPath, 'utf-8');\r\n return content.includes('\"**/*\"') || content.includes(\"'**/*'\");\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n// ─── Main detection entry point ───────────────────────────────────────────────\r\n\r\nexport function detect(cwd = process.cwd()): DetectionResult {\r\n const eslintVersion = getPackageVersion('eslint', cwd);\r\n const eslintMajor = parseMajor(eslintVersion);\r\n const pluginInstalled = isPackageInstalled('eslint-plugin-ai-guard', cwd);\r\n\r\n const { type: configType, path: configPath, allPaths } = detectConfigType(cwd);\r\n\r\n // Conflict: both flat AND legacy config files exist\r\n const hasFlatConfig = allPaths.some((p) =>\r\n FLAT_CONFIG_FILES.some((c) => p.endsWith(c.file)),\r\n );\r\n const hasLegacyConfig = allPaths.some((p) =>\r\n LEGACY_CONFIG_FILES.some((c) => p.endsWith(c.file)),\r\n );\r\n const hasConflictingConfigs = hasFlatConfig && hasLegacyConfig;\r\n\r\n const hasNukeIgnore = detectNukeIgnore(configPath);\r\n\r\n return {\r\n eslintVersion,\r\n eslintMajor,\r\n pluginInstalled,\r\n configType,\r\n configPath,\r\n allConfigPaths: allPaths,\r\n hasConflictingConfigs,\r\n hasNukeIgnore,\r\n };\r\n}\r\n\r\n// ─── Monorepo detection ────────────────────────────────────────────────────────\r\n\r\nexport interface MonorepoResult {\r\n isMonorepo: boolean;\r\n tool: 'pnpm' | 'npm-workspaces' | 'yarn-workspaces' | 'nx' | 'turborepo' | 'lerna' | null;\r\n packages: string[];\r\n}\r\n\r\nexport function detectMonorepo(cwd = process.cwd()): MonorepoResult {\r\n if (fs.existsSync(path.join(cwd, 'pnpm-workspace.yaml'))) {\r\n return { isMonorepo: true, tool: 'pnpm', packages: discoverWorkspacePackages(cwd) };\r\n }\r\n if (fs.existsSync(path.join(cwd, 'nx.json'))) {\r\n return { isMonorepo: true, tool: 'nx', packages: discoverWorkspacePackages(cwd) };\r\n }\r\n if (fs.existsSync(path.join(cwd, 'turbo.json'))) {\r\n return { isMonorepo: true, tool: 'turborepo', packages: discoverWorkspacePackages(cwd) };\r\n }\r\n if (fs.existsSync(path.join(cwd, 'lerna.json'))) {\r\n return { isMonorepo: true, tool: 'lerna', packages: discoverWorkspacePackages(cwd) };\r\n }\r\n try {\r\n const pkgPath = path.join(cwd, 'package.json');\r\n if (fs.existsSync(pkgPath)) {\r\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as {\r\n workspaces?: string[] | { packages?: string[] };\r\n };\r\n if (pkg.workspaces) {\r\n const tool = fs.existsSync(path.join(cwd, 'yarn.lock'))\r\n ? ('yarn-workspaces' as const)\r\n : ('npm-workspaces' as const);\r\n return { isMonorepo: true, tool, packages: discoverWorkspacePackages(cwd) };\r\n }\r\n }\r\n } catch { /* not a monorepo */ }\r\n return { isMonorepo: false, tool: null, packages: [] };\r\n}\r\n\r\nfunction discoverWorkspacePackages(cwd: string): string[] {\r\n const commonDirs = ['packages', 'apps', 'libs', 'modules', 'services'];\r\n const found: string[] = [];\r\n for (const dir of commonDirs) {\r\n const dirPath = path.join(cwd, dir);\r\n if (!fs.existsSync(dirPath)) continue;\r\n try {\r\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (!entry.isDirectory()) continue;\r\n if (fs.existsSync(path.join(dirPath, entry.name, 'package.json'))) {\r\n found.push(path.join(dir, entry.name));\r\n }\r\n }\r\n } catch { /* skip */ }\r\n }\r\n return found;\r\n}\r\n","import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport path from 'path';\nimport { detect, isFlat, isLegacy, requiresFlatConfig } from '../utils/detector.js';\nimport { log } from '../utils/logger.js';\nimport { readConfig } from '../utils/config-manager.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface CheckResult {\n label: string;\n pass: boolean;\n detail: string;\n /** Exact command or action to fix — shown as cyan */\n fix?: string;\n /** Additional explanation shown below fix as gray */\n note?: string;\n}\n\n// ─── Programmatic config load probe ──────────────────────────────────────────\n\nasync function probeConfigLoad(\n configPath: string,\n cwd: string,\n): Promise<{ ok: boolean; error: string | null }> {\n try {\n const { ESLint } = await import('eslint') as { ESLint: any };\n const eslint = new ESLint({ cwd, overrideConfigFile: configPath });\n await eslint.lintText('', { filePath: path.join(cwd, '_probe_.js') });\n return { ok: true, error: null };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n // \"no files\" or \"probe\" errors are not config errors\n if (\n msg.includes('No files') ||\n msg.includes('no files') ||\n msg.includes('_probe_')\n ) {\n return { ok: true, error: null };\n }\n // Strip stack frames from message\n const clean = msg.replace(/\\s+at\\s+.+/gm, '').trim();\n return { ok: false, error: clean };\n }\n}\n\n// ─── Command ──────────────────────────────────────────────────────────────────\n\nexport function registerDoctorCommand(program: Command): void {\n program\n .command('doctor')\n .description('Diagnose your ai-guard setup and print actionable fixes')\n .action(async () => {\n const cwd = process.cwd();\n\n log.banner('AI GUARD DOCTOR');\n log.info('Checking your environment…');\n log.blank();\n\n const env = detect(cwd);\n const checks: CheckResult[] = [];\n\n // ── Check 1: ESLint installed ──────────────────────────────────────────\n\n checks.push({\n label: 'ESLint installed',\n pass: env.eslintVersion !== null,\n detail: env.eslintVersion\n ? `ESLint ${env.eslintVersion}`\n : 'Not found in node_modules',\n fix: env.eslintVersion\n ? undefined\n : 'npm install --save-dev eslint',\n });\n\n // ── Check 2: Plugin installed ──────────────────────────────────────────\n\n checks.push({\n label: 'eslint-plugin-ai-guard installed',\n pass: env.pluginInstalled,\n detail: env.pluginInstalled\n ? 'Found in node_modules'\n : 'Not found in node_modules',\n fix: env.pluginInstalled\n ? undefined\n : 'npm install --save-dev eslint-plugin-ai-guard',\n });\n\n // ── Check 3: ESLint config exists ─────────────────────────────────────\n\n const hasConfig = env.configType !== 'none';\n checks.push({\n label: 'ESLint config present',\n pass: hasConfig,\n detail: hasConfig\n ? `${path.relative(cwd, env.configPath ?? '')} (${env.configType})`\n : 'No eslint.config.* or .eslintrc.* found',\n fix: hasConfig\n ? undefined\n : 'ai-guard init',\n note: hasConfig\n ? undefined\n : 'This will generate the correct config format for your ESLint version',\n });\n\n // ── Check 4: Config type matches ESLint version ────────────────────────\n\n if (env.eslintMajor !== null && hasConfig) {\n const needsFlat = requiresFlatConfig(env.eslintMajor);\n const actuallyFlat = isFlat(env.configType);\n const actuallyLegacy = isLegacy(env.configType);\n const aligned =\n (needsFlat && actuallyFlat) || (!needsFlat && actuallyLegacy);\n\n checks.push({\n label: 'Config format matches ESLint version',\n pass: aligned,\n detail: aligned\n ? `${actuallyFlat ? 'Flat config' : 'Legacy config'} ✔ matches ESLint v${env.eslintMajor}`\n : `ESLint v${env.eslintMajor} requires ${needsFlat ? 'flat config (eslint.config.*)'\n : 'legacy config (.eslintrc.*)'} but found ${actuallyFlat ? 'flat' : 'legacy'} config`,\n fix: aligned\n ? undefined\n : needsFlat\n ? 'ai-guard init (will create eslint.config.mjs)'\n : 'npm install --save-dev eslint@8 (or upgrade to v9 and run ai-guard init)',\n note: aligned\n ? undefined\n : needsFlat\n ? 'ESLint v9 ignores .eslintrc.* files. The flat config must be used.'\n : undefined,\n });\n }\n\n // ── Check 5: Plugin wired in config ───────────────────────────────────\n\n if (hasConfig && env.configPath) {\n let pluginWired = false;\n let isInvalidConfig = false;\n let readError: string | null = null;\n try {\n const { isInvalidAiGuardConfig } = await import('../utils/config-manager.js');\n const content = readConfig(env.configPath);\n pluginWired =\n content.includes('ai-guard') ||\n content.includes('eslint-plugin-ai-guard');\n isInvalidConfig = isInvalidAiGuardConfig(content);\n } catch (err) {\n readError = err instanceof Error ? err.message : String(err);\n }\n\n checks.push({\n label: 'Plugin wired in config',\n pass: pluginWired && !isInvalidConfig,\n detail: readError\n ? `Could not read config: ${readError}`\n : isInvalidConfig\n ? 'Invalid ai-guard config detected (wrong export usage)'\n : pluginWired\n ? 'eslint-plugin-ai-guard referenced in config'\n : `Config exists but ai-guard plugin not found in ${path.relative(cwd, env.configPath)}`,\n fix: isInvalidConfig || (!pluginWired && !readError)\n ? 'ai-guard init (will patch/repair your existing config)'\n : undefined,\n });\n }\n\n // ── Check 6: No conflicting configs ───────────────────────────────────\n\n checks.push({\n label: 'No conflicting config files',\n pass: !env.hasConflictingConfigs,\n detail: env.hasConflictingConfigs\n ? `Conflicting config detected:\\n${env.allConfigPaths.map((p) => ` ${path.relative(cwd, p)}`).join('\\n')}`\n : 'Only one config format detected',\n fix: env.hasConflictingConfigs\n ? 'Remove or backup legacy config'\n : undefined,\n note: env.hasConflictingConfigs\n ? 'ESLint v9 silently ignores .eslintrc.* when a flat config exists. This can cause confusion.'\n : undefined,\n });\n\n // ── Check 7: No nuke-ignore pattern ───────────────────────────────────\n\n if (hasConfig && env.hasNukeIgnore) {\n checks.push({\n label: 'No \"ignore everything\" pattern',\n pass: false,\n detail: `Config contains \"**/*\" ignore pattern — this silently prevents all files from being linted`,\n fix: 'ai-guard init (will remove the pattern and replace with safe ignores)',\n });\n }\n\n // ── Check 8: ESLint version compatible ────────────────────────────────\n\n const versionOk = env.eslintMajor !== null && env.eslintMajor >= 8;\n checks.push({\n label: 'ESLint version compatible',\n pass: versionOk,\n detail: versionOk\n ? `v${env.eslintMajor} ✔ (requires ≥ v8)`\n : env.eslintMajor !== null\n ? `v${env.eslintMajor} is too old — requires ESLint ≥ 8`\n : 'ESLint not installed',\n fix: versionOk ? undefined : 'npm install --save-dev eslint@latest',\n });\n\n // ── Check 9: Programmatic config load ─────────────────────────────────\n // Only run this if we have a config and all prior config checks passed,\n // so we don't produce redundant errors.\n\n const configChecksPass = checks.every((c) => c.pass);\n if (hasConfig && env.configPath && env.pluginInstalled && configChecksPass) {\n log.info('Probing ESLint config load…');\n const probe = await probeConfigLoad(env.configPath, cwd);\n\n checks.push({\n label: 'ESLint config loads without errors',\n pass: probe.ok,\n detail: probe.ok\n ? 'ESLint loaded config successfully'\n : probe.error ?? 'Unknown error',\n fix: probe.ok\n ? undefined\n : `Check syntax in ${path.relative(cwd, env.configPath)}`,\n note: probe.ok\n ? undefined\n : 'Run: ai-guard init --dry-run to preview a fresh config',\n });\n }\n\n // ── Check 10: @typescript-eslint/utils resolvable at runtime ──────────\n {\n let utilsOk = false;\n let utilsVersion: string | null = null;\n try {\n const { createRequire } = await import('module');\n const req = createRequire(path.join(cwd, 'package.json'));\n const pkgPath = req.resolve('@typescript-eslint/utils/package.json');\n const pkg = JSON.parse(\n (await import('fs')).readFileSync(pkgPath, 'utf-8'),\n ) as { version?: string };\n utilsVersion = pkg.version ?? null;\n utilsOk = true;\n } catch {\n // Not found\n }\n\n if (!utilsOk) {\n // Fall back to checking our own package location\n try {\n const selfDir = path.dirname(\n new URL(import.meta.url).pathname.replace(/^\\/([A-Za-z]:)/, '$1'),\n );\n const pkgPath = path.join(selfDir, '../../node_modules/@typescript-eslint/utils/package.json');\n if ((await import('fs')).existsSync(pkgPath)) {\n utilsOk = true;\n }\n } catch { /* skip */ }\n }\n\n checks.push({\n label: '@typescript-eslint/utils available at runtime',\n pass: utilsOk,\n detail: utilsOk\n ? `Found${utilsVersion ? ` v${utilsVersion}` : ''}`\n : 'Not found — rule engine may crash on fresh installs',\n fix: utilsOk\n ? undefined\n : 'npm install @typescript-eslint/utils',\n note: utilsOk\n ? undefined\n : 'This is a runtime dependency of eslint-plugin-ai-guard rules.',\n });\n }\n\n // ── Check 11: @typescript-eslint/parser for TS projects ───────────────\n {\n let parserOk = false;\n let parserVersion: string | null = null;\n try {\n const { createRequire } = await import('module');\n const req = createRequire(path.join(cwd, 'package.json'));\n const pkgPath = req.resolve('@typescript-eslint/parser/package.json');\n const pkg = JSON.parse(\n (await import('fs')).readFileSync(pkgPath, 'utf-8'),\n ) as { version?: string };\n parserVersion = pkg.version ?? null;\n parserOk = true;\n } catch {\n // Optional — only needed for TS projects\n }\n\n const hasTsFiles = (() => {\n try {\n const { readdirSync } = require('fs');\n const files = readdirSync(cwd) as string[];\n return files.some((f: string) => f.endsWith('.ts') || f.endsWith('.tsx'));\n } catch {\n return false;\n }\n })();\n\n if (!parserOk && hasTsFiles) {\n checks.push({\n label: '@typescript-eslint/parser installed (TypeScript project)',\n pass: false,\n detail: '.ts/.tsx files detected but TypeScript parser not found',\n fix: 'npm install --save-dev @typescript-eslint/parser',\n note: 'TypeScript files will use espree fallback without this — some rules may not work correctly.',\n });\n }\n }\n\n // ─── Render results ────────────────────────────────────────────────────\n\n log.section('Diagnostics');\n\n let allPassed = true;\n for (const check of checks) {\n const icon = check.pass ? chalk.green('✔') : chalk.red('✖');\n const label = check.pass\n ? chalk.white(check.label)\n : chalk.red.bold(check.label);\n\n log.print(` ${icon} ${label}`);\n log.print(` ${chalk.gray(check.detail)}`);\n\n if (!check.pass) {\n allPassed = false;\n if (check.fix) {\n log.print(` ${chalk.cyan('→ Fix:')} ${chalk.yellow(check.fix)}`);\n }\n if (check.note) {\n log.print(` ${chalk.gray(check.note)}`);\n }\n }\n\n log.blank();\n }\n\n log.divider();\n log.blank();\n\n if (allPassed) {\n log.print(` ${chalk.green('✔')} ${chalk.bold.green('All checks passed! Your setup is correct.')}`);\n log.blank();\n log.info(`Run ${chalk.cyan('ai-guard run')} to start scanning.`);\n log.info(`Run ${chalk.cyan('npx eslint .')} to lint with ESLint directly.`);\n } else {\n log.error('Some checks failed. Follow the fixes above.');\n log.blank();\n\n // Smart suggestion — only suggest init if it won't cause an infinite loop\n const configFormatMismatch = checks.some(\n (c) => c.label === 'Config format matches ESLint version' && !c.pass,\n );\n const configMissing = checks.some(\n (c) => c.label === 'ESLint config present' && !c.pass,\n );\n const pluginMissing = checks.some(\n (c) => c.label === 'eslint-plugin-ai-guard installed' && !c.pass,\n );\n\n if (pluginMissing) {\n log.print(\n ` Install missing packages first, then re-run ${chalk.cyan('ai-guard doctor')}.`,\n );\n } else if (configMissing || configFormatMismatch) {\n log.print(\n ` Run ${chalk.cyan('ai-guard init')} to generate the correct config for your ESLint version.`,\n );\n } else {\n log.print(\n ` Run ${chalk.cyan('ai-guard init --dry-run')} to preview what would change.`,\n );\n }\n }\n\n log.blank();\n process.exit(allPassed ? 0 : 1);\n });\n}\n","import type { Command } from 'commander';\r\nimport { select } from '@inquirer/prompts';\r\nimport chalk from 'chalk';\r\nimport { detect, isFlat } from '../utils/detector.js';\r\nimport {\r\n backupConfig,\r\n readConfig,\r\n writeConfig,\r\n patchFlatConfig,\r\n patchLegacyConfig,\r\n switchFlatPreset,\r\n switchLegacyPreset,\r\n generateFlatConfig,\r\n generateLegacyConfig,\r\n type Preset,\r\n} from '../utils/config-manager.js';\r\nimport { log } from '../utils/logger.js';\r\nimport path from 'path';\r\n\r\nexport function registerPresetCommand(program: Command): void {\r\n program\r\n .command('preset')\r\n .description('Interactively select and apply an ai-guard preset to your ESLint config')\r\n .action(async () => {\r\n const cwd = process.cwd();\r\n\r\n log.banner('AI GUARD PRESET');\r\n log.blank();\r\n\r\n const preset = await select<Preset>({\r\n message: 'Choose a preset:',\r\n choices: [\r\n {\r\n name: `${chalk.green('recommended')} — balanced defaults, low noise. Best starting point.`,\r\n value: 'recommended',\r\n },\r\n {\r\n name: `${chalk.yellow('strict')} — all rules at error. For mature codebases.`,\r\n value: 'strict',\r\n },\r\n {\r\n name: `${chalk.red('security')} — security rules only. For AppSec teams.`,\r\n value: 'security',\r\n },\r\n ],\r\n });\r\n\r\n log.blank();\r\n log.info(`Applying preset: ${chalk.cyan(preset)}`);\r\n\r\n const env = detect(cwd);\r\n const useFlat =\r\n (env.eslintMajor !== null && env.eslintMajor >= 9) ||\r\n isFlat(env.configType);\r\n\r\n if (env.configType === 'none') {\r\n // Generate fresh config with chosen preset\r\n const configPath = useFlat\r\n ? path.join(cwd, 'eslint.config.mjs')\r\n : path.join(cwd, '.eslintrc.js');\r\n\r\n const content = useFlat\r\n ? generateFlatConfig(preset)\r\n : generateLegacyConfig(preset);\r\n\r\n writeConfig(configPath, content);\r\n log.success(`Created ${chalk.white(path.relative(cwd, configPath))} with ${chalk.cyan(preset)} preset`);\r\n } else {\r\n const configPath = env.configPath!;\r\n const backupPath = backupConfig(configPath);\r\n log.info(`Backed up → ${chalk.gray(path.relative(cwd, backupPath))}`);\r\n\r\n const existing = readConfig(configPath);\r\n const withPlugin = isFlat(env.configType)\r\n ? patchFlatConfig(existing, preset)\r\n : patchLegacyConfig(existing, preset);\r\n\r\n const patched = isFlat(env.configType)\r\n ? switchFlatPreset(withPlugin, preset)\r\n : switchLegacyPreset(withPlugin, preset);\r\n\r\n if (patched === existing) {\r\n log.warn('No preset changes needed. Config already matches selected preset.');\r\n } else {\r\n writeConfig(configPath, patched);\r\n log.success(`Updated ${chalk.white(path.relative(cwd, configPath))} to ${chalk.cyan(preset)} preset`);\r\n }\r\n }\r\n\r\n log.blank();\r\n log.section('Preset Details');\r\n\r\n const presetDetails: Record<Preset, Array<{ rule: string; level: string }>> = {\r\n recommended: [\r\n { rule: 'no-empty-catch', level: chalk.red('error') },\r\n { rule: 'no-floating-promise', level: chalk.red('error') },\r\n { rule: 'no-hardcoded-secret', level: chalk.red('error') },\r\n { rule: 'no-eval-dynamic', level: chalk.red('error') },\r\n { rule: 'no-broad-exception', level: chalk.yellow('warn') },\r\n { rule: 'no-async-array-callback', level: chalk.yellow('warn') },\r\n { rule: 'no-await-in-loop', level: chalk.yellow('warn') },\r\n { rule: '+ 5 more…', level: chalk.gray('warn') },\r\n ],\r\n strict: [\r\n { rule: 'All 17 rules', level: chalk.red('error') },\r\n ],\r\n security: [\r\n { rule: 'no-hardcoded-secret', level: chalk.red('error') },\r\n { rule: 'no-eval-dynamic', level: chalk.red('error') },\r\n { rule: 'no-sql-string-concat', level: chalk.red('error') },\r\n { rule: 'no-unsafe-deserialize', level: chalk.yellow('warn') },\r\n { rule: 'require-auth-middleware', level: chalk.yellow('warn') },\r\n { rule: 'require-authz-check', level: chalk.yellow('warn') },\r\n ],\r\n };\r\n\r\n for (const { rule, level } of presetDetails[preset]) {\r\n log.print(` ${chalk.gray('•')} ${chalk.white(rule).padEnd(32)}${level}`);\r\n }\r\n\r\n log.blank();\r\n log.info(`Run ${chalk.cyan('ai-guard run')} to see results with the new preset.`);\r\n log.blank();\r\n });\r\n}\r\n","import type { Command } from 'commander';\nimport chalk from 'chalk';\nimport { detect, isFlat } from '../utils/detector.js';\nimport {\n backupConfig,\n readConfig,\n writeConfig,\n addIgnoresToFlatConfig,\n addIgnoresToLegacyConfig,\n generateFlatConfig,\n generateLegacyConfig,\n} from '../utils/config-manager.js';\nimport { log } from '../utils/logger.js';\nimport path from 'path';\n\nconst DEFAULT_IGNORES = [\n '.next/',\n 'dist/',\n 'build/',\n 'coverage/',\n 'out/',\n 'node_modules/',\n];\n\nexport function registerIgnoreCommand(program: Command): void {\n program\n .command('ignore')\n .description('Add default ignore patterns (.next, dist, build, coverage) to ESLint config')\n .action(() => {\n const cwd = process.cwd();\n\n log.banner('AI GUARD IGNORE');\n log.blank();\n log.section('Default Ignores');\n\n for (const p of DEFAULT_IGNORES) {\n log.print(` ${chalk.gray('•')} ${chalk.yellow(p)}`);\n }\n\n log.blank();\n\n const env = detect(cwd);\n\n if (env.configType === 'none') {\n // Generate a fresh minimal config with ignores\n const useFlat = env.eslintMajor !== null && env.eslintMajor >= 9;\n const configPath = useFlat\n ? path.join(cwd, 'eslint.config.mjs')\n : path.join(cwd, '.eslintrc.js');\n\n const content = useFlat\n ? generateFlatConfig('recommended')\n : generateLegacyConfig('recommended');\n\n writeConfig(configPath, content);\n log.success(`No config found — generated ${chalk.white(path.relative(cwd, configPath))} with ignores included`);\n } else {\n const configPath = env.configPath!;\n const backupPath = backupConfig(configPath);\n log.info(`Backed up → ${chalk.gray(path.relative(cwd, backupPath))}`);\n\n const existing = readConfig(configPath);\n const patched = isFlat(env.configType)\n ? addIgnoresToFlatConfig(existing)\n : addIgnoresToLegacyConfig(existing);\n\n if (patched === existing) {\n log.warn('Ignore patterns already present in config — no changes made.');\n } else {\n writeConfig(configPath, patched);\n log.success(`Patched ${chalk.white(path.relative(cwd, configPath))} with ignore patterns`);\n }\n }\n\n log.blank();\n log.info('Noisy directories will now be skipped in all future ESLint runs.');\n log.info(`Run ${chalk.cyan('ai-guard run')} to verify cleaner results.`);\n log.blank();\n });\n}\n","import type { Command } from 'commander';\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport chalk from 'chalk';\r\nimport ora from 'ora';\r\nimport { runEslint, type Preset, type RunResult } from '../utils/eslint-runner.js';\r\nimport { log } from '../utils/logger.js';\r\n\r\nconst BASELINE_FILE = '.ai-guard-baseline.json';\r\n\r\n// ─── Baseline format ──────────────────────────────────────────────────────────\r\n\r\ninterface BaselineIssue {\r\n ruleId: string;\r\n message: string;\r\n line: number;\r\n column: number;\r\n}\r\n\r\ntype BaselineMode = 'strict' | 'stable';\r\n\r\ninterface BaselineEntry {\r\n filePath: string;\r\n issues: BaselineIssue[];\r\n}\r\n\r\ninterface BaselineFile {\r\n createdAt: string;\r\n preset: Preset;\r\n mode: BaselineMode;\r\n totalIssues: number;\r\n entries: BaselineEntry[];\r\n}\r\n\r\n// ─── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\nfunction saveBaseline(\r\n result: RunResult,\r\n preset: Preset,\r\n mode: BaselineMode,\r\n cwd: string,\r\n): string {\r\n const entries: BaselineEntry[] = result.files.map((f) => ({\r\n filePath: f.filePath,\r\n issues: f.issues.map((i) => ({\r\n ruleId: i.ruleId,\r\n message: i.message,\r\n line: i.line,\r\n column: i.column,\r\n })),\r\n }));\r\n\r\n const baseline: BaselineFile = {\r\n createdAt: new Date().toISOString(),\r\n preset,\r\n mode,\r\n totalIssues: result.totalIssues,\r\n entries,\r\n };\r\n\r\n const baselinePath = path.join(cwd, BASELINE_FILE);\r\n fs.writeFileSync(baselinePath, JSON.stringify(baseline, null, 2), 'utf-8');\r\n return baselinePath;\r\n}\r\n\r\nfunction loadBaseline(cwd: string): BaselineFile | null {\r\n const baselinePath = path.join(cwd, BASELINE_FILE);\r\n if (!fs.existsSync(baselinePath)) return null;\r\n try {\r\n const raw = fs.readFileSync(baselinePath, 'utf-8');\r\n return JSON.parse(raw) as BaselineFile;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\ntype IssueKey = string;\r\n\r\nfunction issueKey(filePath: string, issue: BaselineIssue): IssueKey {\r\n return `${filePath}::${issue.ruleId}::${issue.line}::${issue.column}::${issue.message}`;\r\n}\r\n\r\nfunction stableIssueKey(filePath: string, issue: BaselineIssue): IssueKey {\r\n return `${filePath}::${issue.ruleId}::${issue.message}`;\r\n}\r\n\r\nfunction buildBaselineSet(baseline: BaselineFile, mode: BaselineMode): Set<IssueKey> {\r\n const toKey = mode === 'stable' ? stableIssueKey : issueKey;\r\n const set = new Set<IssueKey>();\r\n for (const entry of baseline.entries) {\r\n for (const issue of entry.issues) {\r\n set.add(toKey(entry.filePath, issue));\r\n }\r\n }\r\n return set;\r\n}\r\n\r\nfunction computeNewIssues(\r\n result: RunResult,\r\n baselineSet: Set<IssueKey>,\r\n mode: BaselineMode,\r\n): RunResult {\r\n const toKey = mode === 'stable' ? stableIssueKey : issueKey;\r\n const newFiles: RunResult['files'] = [];\r\n let totalErrors = 0;\r\n let totalWarnings = 0;\r\n const ruleBreakdown = new Map<string, number>();\r\n\r\n for (const file of result.files) {\r\n const newIssues = file.issues.filter(\r\n (i) => !baselineSet.has(toKey(file.filePath, i)),\r\n );\r\n if (newIssues.length === 0) continue;\r\n\r\n const errorCount = newIssues.filter((i) => i.severity === 2).length;\r\n const warningCount = newIssues.filter((i) => i.severity === 1).length;\r\n totalErrors += errorCount;\r\n totalWarnings += warningCount;\r\n\r\n for (const issue of newIssues) {\r\n ruleBreakdown.set(\r\n issue.ruleId,\r\n (ruleBreakdown.get(issue.ruleId) ?? 0) + 1,\r\n );\r\n }\r\n\r\n newFiles.push({ ...file, issues: newIssues, errorCount, warningCount });\r\n }\r\n\r\n const topFiles = [...newFiles]\r\n .sort((a, b) => b.issues.length - a.issues.length)\r\n .slice(0, 10)\r\n .map((f) => ({ path: f.filePath, count: f.issues.length }));\r\n\r\n return {\r\n files: newFiles,\r\n totalErrors,\r\n totalWarnings,\r\n totalIssues: totalErrors + totalWarnings,\r\n ruleBreakdown,\r\n topFiles,\r\n durationMs: result.durationMs,\r\n };\r\n}\r\n\r\n// ─── Command ──────────────────────────────────────────────────────────────────\r\n\r\nexport function registerBaselineCommand(program: Command): void {\r\n program\r\n .command('baseline')\r\n .description('Save current issues as baseline; future runs show only new issues')\r\n .option('--save', 'Save current state as the new baseline')\r\n .option('--check', 'Show only issues introduced since the last baseline')\r\n .option('--mode <name>', 'Baseline match mode: strict | stable', 'stable')\r\n .option('--path <dir>', 'Directory to scan', '.')\r\n .option('--preset <name>', 'Preset: recommended | strict | security', 'recommended')\r\n .action(async (opts: {\r\n save?: boolean;\r\n check?: boolean;\r\n mode?: string;\r\n path: string;\r\n preset: string;\r\n }) => {\r\n const cwd = process.cwd();\r\n const preset = (opts.preset as Preset) ?? 'recommended';\r\n const mode = (opts.mode as BaselineMode) ?? 'stable';\r\n\r\n if (mode !== 'strict' && mode !== 'stable') {\r\n log.error('Invalid --mode. Use strict or stable.');\r\n process.exit(1);\r\n }\r\n\r\n log.banner('AI GUARD BASELINE');\r\n log.blank();\r\n\r\n // If neither flag provided, default to --save if no baseline exists, else --check\r\n const existingBaseline = loadBaseline(cwd);\r\n const doSave = opts.save ?? (!existingBaseline && !opts.check);\r\n const doCheck = opts.check ?? (existingBaseline !== null && !opts.save);\r\n\r\n if (doSave) {\r\n log.info('Scanning project to save baseline…');\r\n const spinner = ora({ text: 'Running analysis…', color: 'cyan' }).start();\r\n\r\n let result: RunResult | undefined;\r\n try {\r\n result = await runEslint({ preset, targetPath: opts.path });\r\n spinner.stop();\r\n } catch (err: unknown) {\r\n spinner.stop();\r\n log.error(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n\r\n const baselinePath = saveBaseline(result!, preset, mode, cwd);\r\n log.success(\r\n `Baseline saved → ${chalk.white(path.relative(cwd, baselinePath))}`,\r\n );\r\n log.info(` ${result!.totalIssues} issues recorded (${result!.totalErrors} errors, ${result!.totalWarnings} warnings)`);\r\n log.info(` Preset: ${chalk.cyan(preset)}`);\r\n log.info(` Mode: ${chalk.cyan(mode)}`);\r\n log.blank();\r\n log.info('Future runs of ' + chalk.cyan('ai-guard baseline --check') + ' will show only NEW issues.');\r\n log.info('Add ' + chalk.white(BASELINE_FILE) + ' to your git repository to share baseline with your team.');\r\n log.blank();\r\n return;\r\n }\r\n\r\n if (doCheck) {\r\n if (!existingBaseline) {\r\n log.error(`No baseline found at ${chalk.white(BASELINE_FILE)}`);\r\n log.info(`Run ${chalk.cyan('ai-guard baseline --save')} first to create one.`);\r\n process.exit(1);\r\n }\r\n\r\n const baselineDate = new Date(existingBaseline.createdAt).toLocaleString();\r\n log.info(`Baseline from: ${chalk.gray(baselineDate)}`);\r\n log.info(`Baseline preset: ${chalk.cyan(existingBaseline.preset)}`);\r\n log.info(`Baseline mode: ${chalk.cyan(existingBaseline.mode ?? 'strict')}`);\r\n log.info(`Baseline issues: ${chalk.gray(existingBaseline.totalIssues)}`);\r\n log.blank();\r\n\r\n const spinner = ora({ text: 'Scanning for new issues…', color: 'cyan' }).start();\r\n\r\n let result: RunResult | undefined;\r\n try {\r\n result = await runEslint({ preset, targetPath: opts.path });\r\n spinner.stop();\r\n } catch (err: unknown) {\r\n spinner.stop();\r\n log.error(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n\r\n const compareMode = existingBaseline.mode ?? 'strict';\r\n const baselineSet = buildBaselineSet(existingBaseline!, compareMode);\r\n const newResult = computeNewIssues(result!, baselineSet, compareMode);\r\n\r\n if (newResult.totalIssues === 0) {\r\n log.success('No new issues since baseline! ✨');\r\n log.info(\r\n `Total in codebase: ${result!.totalIssues} (all existing, none new)`,\r\n );\r\n log.blank();\r\n process.exit(0);\r\n return;\r\n }\r\n\r\n log.print(\r\n chalk.bold.red(` ✖ ${newResult.totalIssues} new issue${newResult.totalIssues !== 1 ? 's' : ''} since baseline`),\r\n );\r\n log.blank();\r\n\r\n // By rule breakdown\r\n if (newResult.ruleBreakdown.size > 0) {\r\n log.section('New Issues by Rule');\r\n for (const [rule, count] of [...newResult.ruleBreakdown.entries()].sort(\r\n (a, b) => b[1] - a[1],\r\n )) {\r\n log.rule(rule, count);\r\n }\r\n }\r\n\r\n // Per-file breakdown\r\n if (newResult.files.length > 0) {\r\n log.section('New Issues by File');\r\n log.blank();\r\n for (const file of newResult.files) {\r\n log.print(\r\n ` ${chalk.bold.white(file.filePath)} ` +\r\n chalk.gray(`(${file.issues.length} new)`),\r\n );\r\n for (const issue of file.issues) {\r\n log.issue(issue.message, issue.severity, issue.line, issue.column);\r\n }\r\n }\r\n }\r\n\r\n log.blank();\r\n log.divider();\r\n log.blank();\r\n log.error(\r\n `${newResult.totalIssues} new issue${newResult.totalIssues !== 1 ? 's' : ''} introduced since baseline.`,\r\n );\r\n log.info(`Run ${chalk.cyan('ai-guard baseline --save')} to update the baseline after fixing them.`);\r\n log.blank();\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import type { Command } from 'commander';\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport chalk from 'chalk';\r\nimport { checkbox, confirm } from '@inquirer/prompts';\r\nimport { log } from '../utils/logger.js';\r\n\r\n// ─── Types ────────────────────────────────────────────────────────────────────\r\n\r\ntype AgentId = 'claude' | 'cursor' | 'copilot';\r\n\r\ntype RuleCategory = 'async' | 'security' | 'error-handling' | 'quality';\r\n\r\ninterface AgentTarget {\r\n id: AgentId;\r\n label: string;\r\n filePath: string;\r\n generate: (version: string, categories: RuleCategory[]) => string;\r\n}\r\n\r\n// ─── Rule Category Mapping ────────────────────────────────────────────────────\r\n\r\nconst RULE_CATEGORIES: Record<RuleCategory, string[]> = {\r\n 'error-handling': [\r\n 'no-empty-catch',\r\n 'no-broad-exception',\r\n 'no-catch-log-rethrow',\r\n 'no-catch-without-use',\r\n ],\r\n async: [\r\n 'no-async-array-callback',\r\n 'no-floating-promise',\r\n 'no-await-in-loop',\r\n 'no-async-without-await',\r\n 'no-redundant-await',\r\n ],\r\n security: [\r\n 'no-hardcoded-secret',\r\n 'no-eval-dynamic',\r\n 'no-sql-string-concat',\r\n 'no-unsafe-deserialize',\r\n 'require-auth-middleware',\r\n 'require-authz-check',\r\n ],\r\n quality: [\r\n 'no-console-in-handler',\r\n 'no-duplicate-logic-block',\r\n ],\r\n};\r\n\r\nconst ALL_CATEGORIES: RuleCategory[] = ['error-handling', 'async', 'security', 'quality'];\r\n\r\n// ─── Template Sections ────────────────────────────────────────────────────────\r\n\r\nfunction errorHandlingSection(): string {\r\n return `## Error Handling\r\n**Never** generate empty catch blocks:\r\n ❌ try { await fetchUser() } catch (e) {}\r\n ✅ try { await fetchUser() } catch (e) { logger.error(e); throw e; }\r\n\r\n**Never** catch (e: any) — use specific types or narrow with instanceof.\r\n\r\n**Never** catch, log, and immediately rethrow without adding context:\r\n ❌ catch (e) { console.error(e); throw e; }\r\n ✅ catch (e) { throw new Error('fetchUser failed', { cause: e }); }`;\r\n}\r\n\r\nfunction asyncSection(): string {\r\n return `## Async Correctness\r\n**Never** pass async callbacks to array.map(), filter(), forEach(), or reduce():\r\n ❌ const results = ids.map(async (id) => await fetchUser(id));\r\n ✅ const results = await Promise.all(ids.map((id) => fetchUser(id)));\r\n\r\n**Never** use await inside a for...of or while loop when parallel execution\r\nis possible:\r\n ❌ for (const id of ids) { const user = await fetchUser(id); }\r\n ✅ const users = await Promise.all(ids.map(fetchUser));\r\n\r\n**Never** call an async function without await or .catch():\r\n ❌ sendEmail(user);\r\n ✅ await sendEmail(user);\r\n\r\n**Never** declare a function async if it never uses await.`;\r\n}\r\n\r\nfunction securitySection(): string {\r\n return `## Security\r\n**Never** hardcode secrets, API keys, tokens, or passwords inline:\r\n ❌ const apiKey = 'sk-prod-abc123';\r\n ✅ const apiKey = process.env.API_KEY;\r\n\r\n**Never** concatenate user input into SQL strings:\r\n ❌ db.query('SELECT * FROM users WHERE id = ' + req.params.id);\r\n ✅ db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);\r\n\r\n**Never** use eval() or new Function() with dynamic/user-supplied strings.\r\n\r\n**Never** call JSON.parse() on req.body, req.query, or req.params directly\r\nwithout schema validation.\r\n\r\n**Always** add authentication middleware before route handlers:\r\n ❌ router.get('/admin/users', getUsers);\r\n ✅ router.get('/admin/users', requireAuth, getUsers);\r\n\r\n**Always** verify that the authenticated user owns or has access to the\r\nresource being accessed when using req.params.id or similar identifiers.`;\r\n}\r\n\r\nfunction qualitySection(): string {\r\n return `## Code Quality\r\n**Never** leave console.log or console.debug statements inside HTTP route\r\nhandlers or event listeners in production code.\r\n\r\n**Never** copy-paste the same logic block consecutively — extract shared\r\nlogic into a helper function or consolidate duplicated code.`;\r\n}\r\n\r\ntype SectionFn = () => string;\r\nconst SECTION_MAP: Record<RuleCategory, SectionFn> = {\r\n 'error-handling': errorHandlingSection,\r\n async: asyncSection,\r\n security: securitySection,\r\n quality: qualitySection,\r\n};\r\n\r\nfunction getSections(categories: RuleCategory[]): string {\r\n return categories.map((cat) => SECTION_MAP[cat]()).join('\\n\\n');\r\n}\r\n\r\nfunction workflowGuidanceMarkdown(): string {\r\n return `## Workflow Guardrails\r\n- Follow user and repository instructions first; apply these rules on top.\r\n- Reuse existing project patterns and libraries before introducing new abstractions.\r\n- If a rule must be bypassed intentionally, add a suppression comment with reason:\r\n \\`ai-guard-disable <rule-name> -- reason: <why>\\`.\r\n- Before finalizing changes, run tests/lint and \\`ai-guard run\\` when available.`;\r\n}\r\n\r\nfunction workflowGuidanceCursor(): string {\r\n return `## Workflow Guardrails\r\n\r\n- Follow user and repository instructions first.\r\n- Prefer existing project patterns and dependencies.\r\n- If bypassing a rule intentionally, add: ai-guard-disable <rule-name> -- reason: <why>.\r\n- Validate generated code with tests/lint and ai-guard run when available.`;\r\n}\r\n\r\nfunction workflowGuidanceCopilot(): string {\r\n return `## Required Workflow\r\n\r\n- Follow user and repository instructions first.\r\n- Prefer edits that match existing architecture and dependencies.\r\n- If intentionally violating an ai-guard rule, add an inline suppression with a reason.\r\n- Run tests/lint and \\`ai-guard run\\` before finalizing changes when possible.`;\r\n}\r\n\r\n// ─── CLAUDE.md Template ───────────────────────────────────────────────────────\r\n\r\nfunction generateClaudeFile(version: string, categories: RuleCategory[]): string {\r\n return `<!-- DO NOT EDIT MANUALLY — generated by eslint-plugin-ai-guard -->\r\n<!-- Regenerate: npx ai-guard init-context --force -->\r\n\r\n# AI Guard Rules — Claude Code Instructions\r\n\r\nYou are coding in a project that uses eslint-plugin-ai-guard.\r\nAvoid generating the following patterns. They will be flagged as lint errors.\r\n\r\n${workflowGuidanceMarkdown()}\r\n\r\n${getSections(categories)}\r\n\r\n---\r\nGenerated by eslint-plugin-ai-guard v${version}.\r\nRun \\`npx ai-guard init-context --force\\` to regenerate.\r\n`;\r\n}\r\n\r\n// ─── .cursorrules Template ────────────────────────────────────────────────────\r\n\r\nfunction cursorErrorHandling(): string {\r\n return `## Error Handling\r\n\r\nRule: no-empty-catch\r\nBad: try { await fetchUser() } catch (e) {}\r\nGood: try { await fetchUser() } catch (e) { logger.error(e); throw e; }\r\n\r\nRule: no-broad-exception\r\nBad: catch (e: any) { handle(e); }\r\nGood: catch (e) { if (e instanceof NetworkError) { retry(); } throw e; }\r\n\r\nRule: no-catch-log-rethrow\r\nBad: catch (e) { console.error(e); throw e; }\r\nGood: catch (e) { throw new Error('fetchUser failed', { cause: e }); }`;\r\n}\r\n\r\nfunction cursorAsyncSection(): string {\r\n return `## Async Correctness\r\n\r\nRule: no-async-array-callback\r\nBad: const results = ids.map(async (id) => await fetchUser(id));\r\nGood: const results = await Promise.all(ids.map((id) => fetchUser(id)));\r\n\r\nRule: no-await-in-loop\r\nBad: for (const id of ids) { const user = await fetchUser(id); }\r\nGood: const users = await Promise.all(ids.map(fetchUser));\r\n\r\nRule: no-floating-promise\r\nBad: sendEmail(user);\r\nGood: await sendEmail(user);\r\n\r\nRule: no-async-without-await\r\nBad: async function getUser() { return db.findOne(id); }\r\nGood: function getUser() { return db.findOne(id); }`;\r\n}\r\n\r\nfunction cursorSecuritySection(): string {\r\n return `## Security\r\n\r\nRule: no-hardcoded-secret\r\nBad: const apiKey = 'sk-prod-abc123';\r\nGood: const apiKey = process.env.API_KEY;\r\n\r\nRule: no-sql-string-concat\r\nBad: db.query('SELECT * FROM users WHERE id = ' + req.params.id);\r\nGood: db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);\r\n\r\nRule: no-eval-dynamic\r\nBad: eval(userInput);\r\nGood: Use a safe parser or allowlist approach instead.\r\n\r\nRule: no-unsafe-deserialize\r\nBad: const data = JSON.parse(req.body);\r\nGood: const data = schema.parse(req.body);\r\n\r\nRule: require-auth-middleware\r\nBad: router.get('/admin/users', getUsers);\r\nGood: router.get('/admin/users', requireAuth, getUsers);\r\n\r\nRule: require-authz-check\r\nBad: const user = await db.findById(req.params.id); res.json(user);\r\nGood: const user = await db.findById(req.params.id); if (user.ownerId !== req.user.id) throw new ForbiddenError(); res.json(user);`;\r\n}\r\n\r\nfunction cursorQualitySection(): string {\r\n return `## Code Quality\r\n\r\nRule: no-console-in-handler\r\nBad: router.get('/users', (req, res) => { console.log('hit'); ... });\r\nGood: router.get('/users', (req, res) => { logger.info('hit'); ... });\r\n\r\nRule: no-duplicate-logic-block\r\nBad: Two identical consecutive code blocks copy-pasted.\r\nGood: Extract the duplicated logic into a shared helper function.`;\r\n}\r\n\r\nconst CURSOR_SECTION_MAP: Record<RuleCategory, () => string> = {\r\n 'error-handling': cursorErrorHandling,\r\n async: cursorAsyncSection,\r\n security: cursorSecuritySection,\r\n quality: cursorQualitySection,\r\n};\r\n\r\nfunction generateCursorFile(version: string, categories: RuleCategory[]): string {\r\n const sections = categories.map((cat) => CURSOR_SECTION_MAP[cat]()).join('\\n\\n');\r\n\r\n return `# AI Guard Rules — Cursor Instructions\r\n# DO NOT EDIT MANUALLY — generated by eslint-plugin-ai-guard\r\n# Regenerate: npx ai-guard init-context --force\r\n\r\nThis project uses eslint-plugin-ai-guard to catch the 17 most common\r\nanti-patterns generated by AI coding tools. Follow these rules when\r\ngenerating or editing code in this project. Violations will be flagged\r\nas lint errors.\r\n\r\n${workflowGuidanceCursor()}\r\n\r\n${sections}\r\n\r\n---\r\nThese rules mirror eslint-plugin-ai-guard v${version}.\r\nRun \\`npx ai-guard init-context --force\\` to regenerate.\r\n`;\r\n}\r\n\r\n// ─── .github/copilot-instructions.md Template ─────────────────────────────────\r\n\r\nfunction copilotQuickRef(categories: RuleCategory[]): string {\r\n const lines: string[] = [];\r\n\r\n if (categories.includes('error-handling')) {\r\n lines.push(\r\n 'Never: generate empty catch blocks',\r\n 'Never: catch (e: any) without narrowing',\r\n 'Never: catch, log, and rethrow without adding context',\r\n );\r\n }\r\n if (categories.includes('async')) {\r\n lines.push(\r\n 'Never: pass async callbacks to .map(), .filter(), .forEach()',\r\n 'Never: use await inside loops when Promise.all() works',\r\n 'Never: call async functions without await or .catch()',\r\n 'Never: mark functions async if they never await',\r\n );\r\n }\r\n if (categories.includes('security')) {\r\n lines.push(\r\n 'Never: hardcode API keys, secrets, or passwords',\r\n 'Never: concatenate user input into SQL strings',\r\n 'Never: use eval() or new Function() with dynamic input',\r\n 'Never: JSON.parse() untrusted input without validation',\r\n 'Always: add auth middleware before route handlers',\r\n 'Always: verify resource ownership in handlers',\r\n );\r\n }\r\n if (categories.includes('quality')) {\r\n lines.push(\r\n 'Never: leave console.log in route handlers',\r\n 'Never: copy-paste identical consecutive code blocks',\r\n );\r\n }\r\n\r\n return lines.map((l) => `- ${l}`).join('\\n');\r\n}\r\n\r\nfunction copilotDetails(categories: RuleCategory[]): string {\r\n const details: string[] = [];\r\n\r\n if (categories.includes('async')) {\r\n details.push(`### no-floating-promise\r\n\\`\\`\\`typescript\r\n// ❌ Bad — promise rejected silently\r\nsendEmail(user);\r\n\r\n// ✅ Good\r\nawait sendEmail(user);\r\n\\`\\`\\``);\r\n\r\n details.push(`### no-async-array-callback\r\n\\`\\`\\`typescript\r\n// ❌ Bad — returns Promise[], not values\r\nids.map(async (id) => await fetchUser(id));\r\n\r\n// ✅ Good\r\nawait Promise.all(ids.map((id) => fetchUser(id)));\r\n\\`\\`\\``);\r\n }\r\n\r\n if (categories.includes('error-handling')) {\r\n details.push(`### no-empty-catch\r\n\\`\\`\\`typescript\r\n// ❌ Bad — error swallowed silently\r\ntry { await fetchUser() } catch (e) {}\r\n\r\n// ✅ Good\r\ntry { await fetchUser() } catch (e) { logger.error(e); throw e; }\r\n\\`\\`\\``);\r\n }\r\n\r\n if (categories.includes('security')) {\r\n details.push(`### no-hardcoded-secret\r\n\\`\\`\\`typescript\r\n// ❌ Bad\r\nconst apiKey = 'sk-prod-abc123';\r\n\r\n// ✅ Good\r\nconst apiKey = process.env.API_KEY;\r\n\\`\\`\\``);\r\n\r\n details.push(`### no-sql-string-concat\r\n\\`\\`\\`typescript\r\n// ❌ Bad — SQL injection\r\ndb.query('SELECT * FROM users WHERE id = ' + req.params.id);\r\n\r\n// ✅ Good\r\ndb.query('SELECT * FROM users WHERE id = $1', [req.params.id]);\r\n\\`\\`\\``);\r\n }\r\n\r\n return details.join('\\n\\n');\r\n}\r\n\r\nfunction generateCopilotFile(version: string, categories: RuleCategory[]): string {\r\n return `<!-- DO NOT EDIT MANUALLY — generated by eslint-plugin-ai-guard -->\r\n<!-- Regenerate: npx ai-guard init-context --force -->\r\n\r\n# AI Guard — GitHub Copilot Instructions\r\n\r\nThis project uses \\`eslint-plugin-ai-guard\\`. Follow these rules to avoid\r\ngenerating patterns that will be flagged as lint errors.\r\n\r\n${workflowGuidanceCopilot()}\r\n\r\n## Quick Reference\r\n\r\n${copilotQuickRef(categories)}\r\n\r\n## Details\r\n\r\n${copilotDetails(categories)}\r\n\r\n---\r\nGenerated by eslint-plugin-ai-guard v${version}.\r\nRun \\`npx ai-guard init-context --force\\` to regenerate.\r\n`;\r\n}\r\n\r\n// ─── Agent Definitions ────────────────────────────────────────────────────────\r\n\r\nconst AGENTS: AgentTarget[] = [\r\n {\r\n id: 'claude',\r\n label: 'Claude Code',\r\n filePath: 'CLAUDE.md',\r\n generate: generateClaudeFile,\r\n },\r\n {\r\n id: 'cursor',\r\n label: 'Cursor',\r\n filePath: '.cursorrules',\r\n generate: generateCursorFile,\r\n },\r\n {\r\n id: 'copilot',\r\n label: 'GitHub Copilot',\r\n filePath: path.join('.github', 'copilot-instructions.md'),\r\n generate: generateCopilotFile,\r\n },\r\n];\r\n\r\n// ─── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\nfunction getPackageVersion(cwd: string): string {\r\n try {\r\n const pkgPath = path.join(cwd, 'node_modules', 'eslint-plugin-ai-guard', 'package.json');\r\n if (fs.existsSync(pkgPath)) {\r\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { version?: string };\r\n if (pkg.version) return pkg.version;\r\n }\r\n } catch { /* fall through */ }\r\n\r\n try {\r\n const pkgPath = path.join(cwd, 'package.json');\r\n if (fs.existsSync(pkgPath)) {\r\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { version?: string };\r\n if (pkg.version) return pkg.version;\r\n }\r\n } catch { /* fall through */ }\r\n\r\n return '0.0.0';\r\n}\r\n\r\nfunction parseCategories(raw: string | undefined): RuleCategory[] {\r\n if (!raw) return ALL_CATEGORIES;\r\n const parts = raw.split(',').map((s) => s.trim().toLowerCase());\r\n const valid: RuleCategory[] = [];\r\n for (const part of parts) {\r\n if (part in RULE_CATEGORIES) {\r\n valid.push(part as RuleCategory);\r\n }\r\n }\r\n return valid.length > 0 ? valid : ALL_CATEGORIES;\r\n}\r\n\r\nfunction normalizeSelectedAgents(raw: unknown): string[] {\r\n if (Array.isArray(raw)) {\r\n return raw.filter((value): value is string => typeof value === 'string');\r\n }\r\n\r\n if (typeof raw === 'string') {\r\n return [raw];\r\n }\r\n\r\n return [];\r\n}\r\n\r\n// ─── Exported for tests ───────────────────────────────────────────────────────\r\n\r\nexport {\r\n generateClaudeFile,\r\n generateCursorFile,\r\n generateCopilotFile,\r\n parseCategories,\r\n normalizeSelectedAgents,\r\n AGENTS,\r\n ALL_CATEGORIES,\r\n};\r\nexport type { AgentTarget, RuleCategory };\r\n\r\n// ─── Command Registration ────────────────────────────────────────────────────\r\n\r\nexport function registerInitContextCommand(program: Command): void {\r\n program\r\n .command('init-context')\r\n .description(\r\n 'Generate AI agent instruction files (CLAUDE.md, .cursorrules, copilot-instructions.md)\\n' +\r\n 'so Claude Code, Cursor, and GitHub Copilot avoid the 17 most common AI anti-patterns.',\r\n )\r\n .option('-a, --all', 'Generate files for all agents (skip prompt)')\r\n .option('--force', 'Overwrite existing files without asking')\r\n .option('--dry-run', 'Print what would be generated without writing files')\r\n .option('--rules <categories>', 'Comma-separated categories: async,security,error-handling,quality')\r\n .action(async (opts: {\r\n all?: boolean;\r\n force?: boolean;\r\n dryRun?: boolean;\r\n rules?: string;\r\n }) => {\r\n const cwd = process.cwd();\r\n const version = getPackageVersion(cwd);\r\n const categories = parseCategories(opts.rules);\r\n const isDryRun = opts.dryRun === true;\r\n const isForce = opts.force === true;\r\n\r\n log.banner('AI GUARD INIT-CONTEXT');\r\n\r\n if (isDryRun) {\r\n log.print(` ${chalk.yellow('⚑ DRY RUN — no files will be written')}`);\r\n log.blank();\r\n }\r\n\r\n // ── Select agents ──────────────────────────────────────────────────────\r\n\r\n let selectedAgents: AgentTarget[];\r\n\r\n if (opts.all) {\r\n selectedAgents = [...AGENTS];\r\n } else {\r\n let selected: string[];\r\n try {\r\n selected = await checkbox({\r\n message: 'Which AI agents do you use?',\r\n choices: [\r\n { name: 'Claude Code -> writes CLAUDE.md', value: 'claude' },\r\n { name: 'Cursor -> writes .cursorrules', value: 'cursor' },\r\n { name: 'GitHub Copilot -> writes .github/copilot-instructions.md', value: 'copilot' },\r\n { name: 'All three (recommended) -> writes all files', value: 'all' },\r\n ],\r\n required: true,\r\n });\r\n } catch {\r\n log.info('Selection cancelled. Nothing to do.');\r\n return;\r\n }\r\n\r\n if (selected.length === 0) {\r\n log.info('No valid agents selected. Use --all to generate all files.');\r\n return;\r\n }\r\n\r\n if (selected.includes('all')) {\r\n selectedAgents = [...AGENTS];\r\n } else {\r\n selectedAgents = AGENTS.filter((a) => selected.includes(a.id));\r\n }\r\n }\r\n\r\n log.info(`Categories: ${chalk.cyan(categories.join(', '))}`);\r\n log.info(`Version: ${chalk.cyan(version)}`);\r\n log.blank();\r\n\r\n // ── Generate files ─────────────────────────────────────────────────────\r\n\r\n const results: { file: string; status: 'created' | 'skipped' | 'dry-run' }[] = [];\r\n\r\n for (const agent of selectedAgents) {\r\n const fullPath = path.join(cwd, agent.filePath);\r\n const exists = fs.existsSync(fullPath);\r\n\r\n if (exists && !isForce && !isDryRun) {\r\n // Ask to overwrite\r\n const overwrite = await confirm({\r\n message: `${agent.filePath} already exists. Overwrite?`,\r\n default: false,\r\n });\r\n\r\n if (!overwrite) {\r\n results.push({ file: agent.filePath, status: 'skipped' });\r\n continue;\r\n }\r\n }\r\n\r\n const content = agent.generate(version, categories);\r\n\r\n if (isDryRun) {\r\n log.section(`Preview: ${agent.filePath}`);\r\n log.print(chalk.gray('─'.repeat(60)));\r\n for (const line of content.split('\\n').slice(0, 20)) {\r\n log.print(chalk.gray(` ${line}`));\r\n }\r\n log.print(chalk.gray(' ... (truncated)'));\r\n log.print(chalk.gray('─'.repeat(60)));\r\n log.blank();\r\n results.push({ file: agent.filePath, status: 'dry-run' });\r\n continue;\r\n }\r\n\r\n // Ensure parent directory exists (for .github/copilot-instructions.md)\r\n const parentDir = path.dirname(fullPath);\r\n if (!fs.existsSync(parentDir)) {\r\n fs.mkdirSync(parentDir, { recursive: true });\r\n }\r\n\r\n fs.writeFileSync(fullPath, content, 'utf-8');\r\n results.push({ file: agent.filePath, status: 'created' });\r\n }\r\n\r\n // ── Summary ────────────────────────────────────────────────────────────\r\n\r\n log.section('Summary');\r\n\r\n for (const result of results) {\r\n switch (result.status) {\r\n case 'created':\r\n log.print(` ${chalk.green('✅')} Created ${chalk.white(result.file)}`);\r\n break;\r\n case 'skipped':\r\n log.print(` ${chalk.yellow('⏭')} Skipped ${chalk.white(result.file)} ${chalk.gray('(already exists — use --force to overwrite)')}`);\r\n break;\r\n case 'dry-run':\r\n log.print(` ${chalk.cyan('📝')} Would create ${chalk.white(result.file)}`);\r\n break;\r\n }\r\n }\r\n\r\n log.blank();\r\n\r\n if (isDryRun) {\r\n log.info('Dry run complete — no files were written.');\r\n log.info(`Re-run without ${chalk.cyan('--dry-run')} to apply.`);\r\n } else {\r\n const createdCount = results.filter((r) => r.status === 'created').length;\r\n if (createdCount > 0) {\r\n log.success(\r\n 'Done. Your AI agents will now automatically avoid the 17 most common AI-generated code anti-patterns.',\r\n );\r\n }\r\n }\r\n\r\n log.blank();\r\n });\r\n}\r\n","import type { Command } from 'commander';\nimport fs from 'fs';\nimport path from 'path';\nimport ora from 'ora';\nimport { runEslint, type RunResult } from '../utils/eslint-runner.js';\nimport { log } from '../utils/logger.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReportData {\n projectName: string;\n version: string;\n generatedAt: string;\n preset: string;\n scannedPath: string;\n durationMs: number;\n totalIssues: number;\n totalErrors: number;\n totalWarnings: number;\n score: number;\n ruleBreakdown: Record<string, number>;\n topFiles: Array<{ path: string; count: number; errors: number; warnings: number }>;\n topRules: Array<{\n rule: string;\n count: number;\n description: string;\n category: string;\n example: { file: string; line: number; column: number; message: string } | null;\n }>;\n categoryBreakdown: Record<string, number>;\n // Confidence tier breakdown\n highCount: number;\n mediumCount: number;\n lowCount: number;\n ecosystemCount: number;\n parserErrorCount: number;\n}\n\n// ─── Rule Metadata ────────────────────────────────────────────────────────────\n\nconst RULE_META: Record<string, { description: string; category: string }> = {\n 'ai-guard/no-empty-catch': { description: 'Empty catch blocks silently swallow errors', category: 'Reliability' },\n 'ai-guard/no-broad-exception': { description: 'Catching all exceptions hides bugs', category: 'Reliability' },\n 'ai-guard/no-catch-log-rethrow': { description: 'Catch-log-rethrow adds noise without context', category: 'Reliability' },\n 'ai-guard/no-catch-without-use': { description: 'Caught error is not used', category: 'Reliability' },\n 'ai-guard/no-floating-promise': { description: 'Unhandled promise can crash silently', category: 'Async Stability' },\n 'ai-guard/no-await-in-loop': { description: 'Sequential await in loops is slow; use Promise.all', category: 'Async Stability' },\n 'ai-guard/no-async-array-callback': { description: 'Async callbacks in .map()/.filter() return Promises', category: 'Async Stability' },\n 'ai-guard/no-async-without-await': { description: 'Async function never uses await', category: 'Async Stability' },\n 'ai-guard/no-redundant-await': { description: 'Redundant await in return position', category: 'Async Stability' },\n 'ai-guard/no-hardcoded-secret': { description: 'Secrets should come from environment variables', category: 'Security' },\n 'ai-guard/no-eval-dynamic': { description: 'eval() with dynamic input is a security risk', category: 'Security' },\n 'ai-guard/no-sql-string-concat': { description: 'SQL string concatenation enables injection', category: 'Security' },\n 'ai-guard/no-unsafe-deserialize': { description: 'JSON.parse on untrusted input without validation', category: 'Security' },\n 'ai-guard/require-auth-middleware': { description: 'Route handler missing authentication middleware', category: 'Security' },\n 'ai-guard/require-authz-check': { description: 'Missing authorization check for resource access', category: 'Security' },\n 'ai-guard/no-console-in-handler': { description: 'console.log in route handlers should be a logger', category: 'AI Patterns' },\n 'ai-guard/no-duplicate-logic-block': { description: 'Duplicate consecutive code blocks should be extracted', category: 'AI Patterns' },\n 'ai-guard/no-dead-branch': { description: 'Always-true/false condition creates dead or unreachable code', category: 'AI Patterns' },\n};\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction getProjectName(cwd: string): string {\n try {\n const pkgPath = path.join(cwd, 'package.json');\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { name?: string };\n if (pkg.name) return pkg.name;\n }\n } catch { /* fall through */ }\n return path.basename(cwd);\n}\n\nfunction getPluginVersion(cwd: string): string {\n try {\n const pkgPath = path.resolve(__dirname, '../../package.json');\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { version?: string };\n if (pkg.version) return pkg.version;\n }\n } catch { /* fall through */ }\n try {\n const pkgPath = path.join(cwd, 'node_modules', 'eslint-plugin-ai-guard', 'package.json');\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { version?: string };\n if (pkg.version) return pkg.version;\n }\n } catch { /* fall through */ }\n return '0.0.0';\n}\n\nfunction calculateScore(totalErrors: number, totalWarnings: number): number {\n // Errors cost 5 points each, warnings cost 2 points each, min 0\n const penalty = totalErrors * 5 + totalWarnings * 2;\n return Math.max(0, Math.min(100, 100 - penalty));\n}\n\n// ─── Report Data Builder ──────────────────────────────────────────────────────\n\nexport function buildReportData(\n result: RunResult,\n preset: string,\n scannedPath: string,\n cwd: string,\n): ReportData {\n const projectName = getProjectName(cwd);\n const version = getPluginVersion(cwd);\n const score = calculateScore(result.totalErrors, result.totalWarnings);\n\n // Top files with error/warning breakdown\n const topFiles = result.files\n .sort((a, b) => b.issues.length - a.issues.length)\n .slice(0, 10)\n .map((f) => ({\n path: f.filePath,\n count: f.issues.length,\n errors: f.errorCount,\n warnings: f.warningCount,\n }));\n\n // Category breakdown\n const categoryBreakdown: Record<string, number> = {};\n for (const [rule, count] of result.ruleBreakdown.entries()) {\n const cat = RULE_META[rule]?.category ?? 'Other';\n categoryBreakdown[cat] = (categoryBreakdown[cat] ?? 0) + count;\n }\n\n // Top 5 rules with real examples\n const sortedRules = [...result.ruleBreakdown.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5);\n\n const topRules = sortedRules.map(([rule, count]) => {\n const meta = RULE_META[rule] ?? { description: 'Rule violation', category: 'Other' };\n\n // Find a real example from the codebase\n let example: { file: string; line: number; column: number; message: string } | null = null;\n for (const file of result.files) {\n const issue = file.issues.find((i) => i.ruleId === rule);\n if (issue) {\n example = {\n file: file.filePath,\n line: issue.line,\n column: issue.column,\n message: issue.message,\n };\n break;\n }\n }\n\n return {\n rule: rule.replace(/^ai-guard\\//, ''),\n count,\n description: meta.description,\n category: meta.category,\n example,\n };\n });\n\n // Confidence tiers for display (computed from rule assignment)\n const CONFIDENCE_ASSIGNMENT: Record<string, 'high' | 'medium' | 'low'> = {\n 'ai-guard/no-hardcoded-secret': 'high',\n 'ai-guard/no-eval-dynamic': 'high',\n 'ai-guard/no-floating-promise': 'high',\n 'ai-guard/no-empty-catch': 'high',\n 'ai-guard/no-sql-string-concat': 'medium',\n 'ai-guard/no-await-in-loop': 'medium',\n 'ai-guard/require-auth-middleware': 'medium',\n 'ai-guard/require-authz-check': 'medium',\n 'ai-guard/no-catch-log-rethrow': 'medium',\n 'ai-guard/no-catch-without-use': 'medium',\n 'ai-guard/no-unsafe-deserialize': 'medium',\n 'ai-guard/no-async-without-await': 'low',\n 'ai-guard/no-async-array-callback': 'low',\n 'ai-guard/no-dead-branch': 'low',\n 'ai-guard/no-broad-exception': 'low',\n 'ai-guard/no-console-in-handler': 'low',\n 'ai-guard/no-duplicate-logic-block': 'low',\n 'ai-guard/no-redundant-await': 'low',\n };\n let highCount = 0;\n let mediumCount = 0;\n let lowCount = 0;\n for (const [rule, count] of result.ruleBreakdown.entries()) {\n const tier = CONFIDENCE_ASSIGNMENT[rule] ?? 'low';\n if (tier === 'high') highCount += count;\n else if (tier === 'medium') mediumCount += count;\n else lowCount += count;\n }\n const ecosystemCount = result.ecosystemIssues?.length ?? 0;\n const parserErrorCount = result.parserErrors?.length ?? 0;\n\n return {\n projectName,\n version,\n generatedAt: new Date().toISOString(),\n preset,\n scannedPath,\n durationMs: result.durationMs,\n totalIssues: result.totalIssues,\n totalErrors: result.totalErrors,\n totalWarnings: result.totalWarnings,\n score,\n ruleBreakdown: Object.fromEntries(result.ruleBreakdown),\n topFiles,\n topRules,\n categoryBreakdown,\n highCount,\n mediumCount,\n lowCount,\n ecosystemCount,\n parserErrorCount,\n };\n}\n\n// ─── HTML Template ────────────────────────────────────────────────────────────\n\nexport function generateHtml(data: ReportData): string {\n const scoreColor = data.score >= 80 ? '#10b981' : data.score >= 50 ? '#f59e0b' : '#ef4444';\n const scoreLabel = data.score >= 80 ? 'Great' : data.score >= 50 ? 'Needs Work' : 'Critical';\n const formattedDate = new Date(data.generatedAt).toLocaleString();\n\n const topFilesRows = data.topFiles.length === 0\n ? `<tr><td colspan=\"4\" style=\"text-align:center;color:#6b7280;padding:2rem;\">No issues found</td></tr>`\n : data.topFiles.map((f) => {\n const heatColor = f.errors > 0\n ? `rgba(239,68,68,${Math.min(0.9, 0.2 + f.errors * 0.1)})`\n : `rgba(245,158,11,${Math.min(0.9, 0.2 + f.warnings * 0.05)})`;\n return `\n <tr style=\"border-bottom:1px solid #1f2937;\">\n <td style=\"padding:0.75rem 1rem;font-family:monospace;font-size:0.8rem;color:#e5e7eb;max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\" title=\"${escHtml(f.path)}\">${escHtml(f.path)}</td>\n <td style=\"padding:0.75rem 1rem;text-align:center;\"><span style=\"background:${heatColor};border-radius:9999px;padding:0.2rem 0.7rem;font-weight:600;font-size:0.85rem;\">${f.count}</span></td>\n <td style=\"padding:0.75rem 1rem;text-align:center;color:#f87171;\">${f.errors}</td>\n <td style=\"padding:0.75rem 1rem;text-align:center;color:#fbbf24;\">${f.warnings}</td>\n </tr>`;\n }).join('');\n\n const topRulesCards = data.topRules.length === 0\n ? `<div style=\"text-align:center;color:#6b7280;padding:2rem;\">No rules fired — clean codebase!</div>`\n : data.topRules.map((r, i) => {\n const catColor: Record<string, string> = {\n 'Reliability': '#ec4899', 'Async Stability': '#8b5cf6',\n 'Security': '#ef4444', 'AI Patterns': '#14b8a6', Other: '#6b7280',\n };\n const color = catColor[r.category] ?? '#6b7280';\n const exampleHtml = r.example\n ? `<div style=\"margin-top:0.75rem;background:#0f172a;border-radius:0.5rem;padding:0.75rem;border-left:3px solid ${color};\">\n <div style=\"font-size:0.75rem;color:#94a3b8;margin-bottom:0.35rem;\">${escHtml(r.example.file)}:${r.example.line}:${r.example.column}</div>\n <code style=\"font-size:0.8rem;color:#f1f5f9;white-space:pre-wrap;word-break:break-all;\">${escHtml(r.example.message)}</code>\n </div>`\n : '';\n return `\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;display:flex;flex-direction:column;gap:0.5rem;\">\n <div style=\"display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:0.5rem;\">\n <div style=\"display:flex;align-items:center;gap:0.75rem;\">\n <span style=\"background:#1f2937;color:#9ca3af;font-size:0.75rem;padding:0.15rem 0.5rem;border-radius:9999px;\">#${i + 1}</span>\n <code style=\"font-size:0.9rem;color:#f9fafb;font-weight:600;\">${escHtml(r.rule)}</code>\n </div>\n <div style=\"display:flex;align-items:center;gap:0.5rem;\">\n <span style=\"background:${color}22;color:${color};border:1px solid ${color}44;font-size:0.72rem;border-radius:9999px;padding:0.15rem 0.6rem;\">${escHtml(r.category)}</span>\n <span style=\"background:#374151;color:#e5e7eb;font-size:0.8rem;border-radius:9999px;padding:0.2rem 0.7rem;font-weight:600;\">${r.count}×</span>\n </div>\n </div>\n <p style=\"color:#9ca3af;font-size:0.85rem;margin:0;\">${escHtml(r.description)}</p>\n ${exampleHtml}\n </div>`;\n }).join('');\n\n const categoryCards = Object.entries(data.categoryBreakdown).map(([cat, count]) => {\n const catColor: Record<string, string> = {\n 'Reliability': '#ec4899', 'Async Stability': '#8b5cf6',\n 'Security': '#ef4444', 'AI Patterns': '#14b8a6', Other: '#6b7280',\n };\n const color = catColor[cat] ?? '#6b7280';\n return `\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;display:flex;flex-direction:column;gap:0.5rem;\">\n <div style=\"font-size:0.8rem;color:#9ca3af;\">${escHtml(cat)}</div>\n <div style=\"font-size:2rem;font-weight:700;color:${color};\">${count}</div>\n <div style=\"background:#1f2937;border-radius:9999px;height:4px;overflow:hidden;\"><div style=\"background:${color};height:100%;width:${Math.min(100, (count / Math.max(data.totalIssues, 1)) * 100)}%;transition:width 0.8s ease;\"></div></div>\n </div>`;\n }).join('');\n\n const cleanBanner = data.totalIssues === 0\n ? `<div style=\"background:#064e3b;border:1px solid #10b981;border-radius:1rem;padding:2rem;text-align:center;margin-bottom:2rem;\">\n <div style=\"font-size:2.5rem;\">🎉</div>\n <div style=\"font-size:1.5rem;font-weight:700;color:#10b981;margin:0.5rem 0;\">Clean Codebase!</div>\n <div style=\"color:#6ee7b7;\">No AI guard issues detected. Your code is production-ready.</div>\n </div>`\n : '';\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>AI Guard Report — ${escHtml(data.projectName)}</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { background: #030712; color: #f9fafb; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; min-height: 100vh; }\n @keyframes pulse-score { 0%, 100% { opacity: 1; } 50% { opacity: 0.8; } }\n @keyframes slide-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }\n .card { animation: slide-in 0.4s ease both; }\n ::-webkit-scrollbar { width: 6px; height: 6px; }\n ::-webkit-scrollbar-track { background: #111827; }\n ::-webkit-scrollbar-thumb { background: #374151; border-radius: 3px; }\n </style>\n</head>\n<body>\n\n<!-- ── Header ── -->\n<header style=\"background:linear-gradient(135deg,#0f172a 0%,#1e1b4b 50%,#0f172a 100%);border-bottom:1px solid #1f2937;padding:2rem 2rem 1.5rem;\">\n <div style=\"max-width:1100px;margin:0 auto;\">\n <div style=\"display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;\">\n <div>\n <div style=\"display:flex;align-items:center;gap:0.75rem;margin-bottom:0.4rem;\">\n <span style=\"font-size:1.5rem;\">🛡️</span>\n <span style=\"font-size:0.85rem;color:#818cf8;font-weight:600;letter-spacing:0.05em;\">AI GUARD REPORT</span>\n </div>\n <h1 style=\"font-size:1.8rem;font-weight:700;color:#f9fafb;\">${escHtml(data.projectName)}</h1>\n <p style=\"color:#6b7280;font-size:0.85rem;margin-top:0.25rem;\">Scanned: <code style=\"color:#94a3b8;\">${escHtml(data.scannedPath)}</code> · Preset: <code style=\"color:#94a3b8;\">${escHtml(data.preset)}</code> · ${data.durationMs}ms</p>\n </div>\n <div style=\"text-align:center;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.75rem;letter-spacing:0.05em;\">SIGNAL CONFIDENCE</div>\n <div style=\"display:flex;flex-direction:column;gap:0.4rem;\">\n <div style=\"display:flex;align-items:center;gap:0.5rem;\">\n <span style=\"width:8px;height:8px;border-radius:50%;background:#ef4444;display:inline-block;\"></span>\n <span style=\"font-size:0.8rem;color:#f87171;font-weight:600;\">${data.highCount} high-confidence</span>\n </div>\n <div style=\"display:flex;align-items:center;gap:0.5rem;\">\n <span style=\"width:8px;height:8px;border-radius:50%;background:#f59e0b;display:inline-block;\"></span>\n <span style=\"font-size:0.8rem;color:#fbbf24;font-weight:600;\">${data.mediumCount} medium-confidence</span>\n </div>\n <div style=\"display:flex;align-items:center;gap:0.5rem;\">\n <span style=\"width:8px;height:8px;border-radius:50%;background:#6b7280;display:inline-block;\"></span>\n <span style=\"font-size:0.8rem;color:#9ca3af;font-weight:600;\">${data.lowCount} suggestions</span>\n </div>\n ${data.ecosystemCount > 0 ? `<div style=\"display:flex;align-items:center;gap:0.5rem;margin-top:0.25rem;\">\n <span style=\"font-size:0.75rem;color:#4b5563;\">⚠ ${data.ecosystemCount} config issue${data.ecosystemCount !== 1 ? 's' : ''} (not ai-guard)</span>\n </div>` : ''}\n </div>\n </div>\n </div>\n <p style=\"color:#4b5563;font-size:0.75rem;margin-top:1rem;\">Generated ${escHtml(formattedDate)}</p>\n </div>\n</header>\n\n<!-- ── Main ── -->\n<main style=\"max-width:1100px;margin:0 auto;padding:2rem;\">\n\n ${cleanBanner}\n\n <!-- Summary Cards -->\n <div class=\"card\" style=\"display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:1rem;margin-bottom:2rem;\">\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">TOTAL ISSUES</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#f9fafb;\">${data.totalIssues}</div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">ERRORS</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#f87171;\">${data.totalErrors}</div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">WARNINGS</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#fbbf24;\">${data.totalWarnings}</div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">FILES AFFECTED</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#818cf8;\">${data.topFiles.length}</div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1.25rem;\">\n <div style=\"font-size:0.75rem;color:#6b7280;margin-bottom:0.5rem;\">RULES FIRED</div>\n <div style=\"font-size:2.5rem;font-weight:800;color:#34d399;\">${Object.keys(data.ruleBreakdown).length}</div>\n </div>\n </div>\n\n <!-- Issues by Category -->\n ${Object.keys(data.categoryBreakdown).length > 0 ? `\n <section class=\"card\" style=\"margin-bottom:2rem;\">\n <h2 style=\"font-size:1rem;font-weight:600;color:#e5e7eb;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem;\">\n <span>📊</span> Issues by Category\n </h2>\n <div style=\"display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1rem;\">\n ${categoryCards}\n </div>\n </section>` : ''}\n\n <!-- Severity Heatmap by File -->\n <section class=\"card\" style=\"margin-bottom:2rem;\">\n <h2 style=\"font-size:1rem;font-weight:600;color:#e5e7eb;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem;\">\n <span>🔥</span> Severity Heatmap — Top Files\n </h2>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;overflow:hidden;\">\n <table style=\"width:100%;border-collapse:collapse;\">\n <thead>\n <tr style=\"background:#0f172a;text-align:left;\">\n <th style=\"padding:0.75rem 1rem;font-size:0.75rem;color:#6b7280;font-weight:500;letter-spacing:0.05em;\">FILE</th>\n <th style=\"padding:0.75rem 1rem;font-size:0.75rem;color:#6b7280;font-weight:500;letter-spacing:0.05em;text-align:center;\">ISSUES</th>\n <th style=\"padding:0.75rem 1rem;font-size:0.75rem;color:#6b7280;font-weight:500;letter-spacing:0.05em;text-align:center;\">ERRORS</th>\n <th style=\"padding:0.75rem 1rem;font-size:0.75rem;color:#6b7280;font-weight:500;letter-spacing:0.05em;text-align:center;\">WARNINGS</th>\n </tr>\n </thead>\n <tbody>\n ${topFilesRows}\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- Top 5 Rules -->\n <section class=\"card\" style=\"margin-bottom:2rem;\">\n <h2 style=\"font-size:1rem;font-weight:600;color:#e5e7eb;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem;\">\n <span>⚡</span> Top Rules That Fired\n </h2>\n <div style=\"display:flex;flex-direction:column;gap:1rem;\">\n ${topRulesCards}\n </div>\n </section>\n\n <!-- Next Steps -->\n <section class=\"card\" style=\"margin-bottom:2rem;\">\n <h2 style=\"font-size:1rem;font-weight:600;color:#e5e7eb;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem;\">\n <span>🚀</span> Suggested Next Steps\n </h2>\n <div style=\"display:flex;flex-direction:column;gap:0.75rem;\">\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1rem;display:flex;align-items:flex-start;gap:0.75rem;\">\n <span style=\"font-size:1.2rem;flex-shrink:0;\">🔧</span>\n <div>\n <div style=\"color:#f9fafb;font-size:0.9rem;font-weight:500;margin-bottom:0.2rem;\">Auto-fix safe issues</div>\n <code style=\"color:#818cf8;font-size:0.8rem;\">npx ai-guard run --fix</code>\n </div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1rem;display:flex;align-items:flex-start;gap:0.75rem;\">\n <span style=\"font-size:1.2rem;flex-shrink:0;\">🤖</span>\n <div>\n <div style=\"color:#f9fafb;font-size:0.9rem;font-weight:500;margin-bottom:0.2rem;\">Prevent future AI-generated issues</div>\n <code style=\"color:#818cf8;font-size:0.8rem;\">npx ai-guard init-context</code>\n </div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1rem;display:flex;align-items:flex-start;gap:0.75rem;\">\n <span style=\"font-size:1.2rem;flex-shrink:0;\">📋</span>\n <div>\n <div style=\"color:#f9fafb;font-size:0.9rem;font-weight:500;margin-bottom:0.2rem;\">Save baseline &amp; track only new issues</div>\n <code style=\"color:#818cf8;font-size:0.8rem;\">npx ai-guard baseline</code>\n </div>\n </div>\n <div style=\"background:#111827;border:1px solid #1f2937;border-radius:0.75rem;padding:1rem;display:flex;align-items:flex-start;gap:0.75rem;\">\n <span style=\"font-size:1.2rem;flex-shrink:0;\">📤</span>\n <div>\n <div style=\"color:#f9fafb;font-size:0.9rem;font-weight:500;margin-bottom:0.2rem;\">Share this report with your team</div>\n <div style=\"color:#6b7280;font-size:0.8rem;\">Send the <code style=\"color:#94a3b8;\">ai-guard-report.html</code> file — it's fully self-contained.</div>\n </div>\n </div>\n </div>\n </section>\n\n</main>\n\n<!-- ── Footer ── -->\n<footer style=\"border-top:1px solid #1f2937;padding:1.5rem 2rem;text-align:center;\">\n <p style=\"color:#4b5563;font-size:0.8rem;\">\n Generated by <a href=\"https://github.com/YashJadhav21/eslint-plugin-ai-guard\" style=\"color:#818cf8;text-decoration:none;\">eslint-plugin-ai-guard</a> v${escHtml(data.version)}\n &nbsp;·&nbsp;\n <a href=\"https://github.com/YashJadhav21/eslint-plugin-ai-guard\" style=\"color:#818cf8;text-decoration:none;\">GitHub</a>\n </p>\n</footer>\n\n</body>\n</html>`;\n}\n\n// ─── Escape ───────────────────────────────────────────────────────────────────\n\nfunction escHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n// ─── Command ──────────────────────────────────────────────────────────────────\n\nexport function registerReportCommand(program: Command): void {\n program\n .command('report')\n .description(\n 'Generate a beautiful HTML report of AI Guard scan results\\n' +\n 'Perfect for sharing with your team or in Slack.',\n )\n .option('--path <dir>', 'Directory or file to scan', '.')\n .option('--preset <preset>', 'Rule preset: recommended | strict | security', 'recommended')\n .option('--html', 'Generate HTML report (default behavior)')\n .option('--json', 'Output raw JSON to stdout instead of writing HTML')\n .option('--output <filename>', 'Output file name', 'ai-guard-report.html')\n .option('--no-open', 'Do not open the report in the browser after generating')\n .action(async (opts: {\n path: string;\n preset: string;\n html?: boolean;\n json?: boolean;\n output: string;\n open: boolean;\n }) => {\n const preset = (['recommended', 'strict', 'security'].includes(opts.preset)\n ? opts.preset\n : 'recommended') as 'recommended' | 'strict' | 'security';\n\n const spinner = opts.json\n ? null\n : ora({ text: 'Scanning…', color: 'cyan' }).start();\n\n let result: RunResult;\n try {\n result = await runEslint({ preset, targetPath: opts.path });\n spinner?.stop();\n } catch (err: unknown) {\n spinner?.stop();\n const msg = err instanceof Error ? err.message : String(err);\n log.error(msg);\n process.exit(1);\n return;\n }\n\n const cwd = process.cwd();\n const reportData = buildReportData(result, preset, opts.path, cwd);\n\n // ── JSON mode ────────────────────────────────────────────────────────────\n\n if (opts.json) {\n console.log(JSON.stringify(reportData, null, 2));\n process.exit(0);\n return;\n }\n\n // ── HTML mode ────────────────────────────────────────────────────────────\n\n log.banner('AI GUARD REPORT');\n log.blank();\n\n const html = generateHtml(reportData);\n const outputPath = path.resolve(cwd, opts.output);\n\n fs.writeFileSync(outputPath, html, 'utf-8');\n\n log.success(`Report saved: ${opts.output}`);\n log.info(\n `Score: ${reportData.score}/100 · ${reportData.totalErrors} errors · ${reportData.totalWarnings} warnings`,\n );\n log.blank();\n\n // Open in browser\n if (opts.open !== false) {\n try {\n const { default: open } = await import('open').catch(() => {\n // open package may not be installed — fall back to platform commands\n return { default: null };\n });\n\n if (open) {\n await open(outputPath);\n log.info('Opened in your browser.');\n } else {\n // Fallback: use platform-native open command\n const { execSync } = await import('child_process');\n const cmd = process.platform === 'win32'\n ? `start \"\" \"${outputPath}\"`\n : process.platform === 'darwin'\n ? `open \"${outputPath}\"`\n : `xdg-open \"${outputPath}\"`;\n execSync(cmd);\n log.info('Opened in your browser.');\n }\n } catch {\n log.info(`Open manually: file://${outputPath}`);\n }\n } else {\n log.info(`Open: file://${outputPath}`);\n }\n\n log.blank();\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBO,SAAS,SAAS,SAAuB;AAC9C,UAAQ,OAAO,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI,OAAO;AAAA,CAAI;AACvD;AAQO,SAAS,cAAc,QAAkC;AAC9D,QAAM,IAAI,OAAO;AAEjB,UAAQ,OAAO,MAAM,IAAI;AACzB,UAAQ,OAAO,MAAM,GAAG,MAAM,wBAAwB,CAAC;AAAA,CAAI;AAC3D,UAAQ,OAAO,MAAM,GAAG,IAAI,kUAAyD,CAAC;AAAA,CAAI;AAG1F,UAAQ,OAAO,MAAM,KAAK,IAAI,OAAO,CAAC,aAAa,cAAAA,QAAM,MAAM,OAAO,IAAI,CAAC;AAAA,CAAI;AAG/E,MAAI,EAAE,cAAc;AAClB,YAAQ,OAAO,MAAM,KAAK,IAAI,cAAc,CAAC,MAAM,cAAAA,QAAM,MAAM,EAAE,YAAY,CAAC;AAAA,CAAI;AAAA,EACpF,OAAO;AACL,YAAQ,OAAO,MAAM,KAAK,IAAI,cAAc,CAAC,MAAM,cAAAA,QAAM,IAAI,gCAA2B,CAAC;AAAA,CAAI;AAAA,EAC/F;AAGA,MAAI,EAAE,WAAW;AACf,YAAQ,OAAO,MAAM,KAAK,IAAI,aAAa,CAAC,OAAO,cAAAA,QAAM,MAAM,EAAE,UAAU,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,CAAK;AAAA,EAC/F;AAGA,MAAI,EAAE,gBAAgB;AACpB,YAAQ,OAAO,MAAM,KAAK,IAAI,IAAI,cAAAA,QAAM,OAAO,wBAAwB,CAAC;AAAA,CAAqC;AAAA,EAC/G;AACA,MAAI,EAAE,gBAAgB;AACpB,YAAQ,OAAO,MAAM,KAAK,IAAI,IAAI,cAAAA,QAAM,OAAO,eAAe,CAAC;AAAA,CAAiC;AAAA,EAClG;AAGA,UAAQ,OAAO,MAAM,IAAI;AACzB,UAAQ,OAAO,MAAM,KAAK,IAAI,uBAAuB,CAAC;AAAA,CAAI;AAC1D,aAAW,YAAY,EAAE,qBAAqB;AAC5C,UAAM,YAAY,aAAa,EAAE;AACjC,UAAM,OAAO,YAAY,KAAK;AAC9B,UAAM,QAAQ,YAAY,cAAAA,QAAM,MAAM,QAAQ,IAAI,cAAAA,QAAM,IAAI,QAAQ;AACpE,YAAQ,OAAO,MAAM,OAAO,IAAI,IAAI,KAAK;AAAA,CAAI;AAAA,EAC/C;AAEA,MAAI,EAAE,mBAAmB;AACvB,YAAQ,OAAO,MAAM;AAAA,IAAO,EAAE,IAAI,cAAAA,QAAM,MAAM,YAAY,CAAC,IAAI,EAAE,iBAAiB;AAAA,CAAI;AAAA,EACxF,OAAO;AACL,YAAQ,OAAO,MAAM;AAAA,IAAO,GAAG,IAAI,cAAAA,QAAM,IAAI,uBAAuB,CAAC;AAAA,CAAI;AAAA,EAC3E;AAGA,UAAQ,OAAO,MAAM,IAAI;AACzB,UAAQ,OAAO,MAAM,KAAK,IAAI,QAAQ,CAAC;AAAA,CAAI;AAC3C,UAAQ,OAAO,MAAM,OAAO,KAAK,wBAAwB,cAAAA,QAAM,MAAM,EAAE,YAAY,CAAC;AAAA,CAAI;AACxF,UAAQ,OAAO,MAAM,OAAO,KAAK,wBAAwB,cAAAA,QAAM,MAAM,OAAO,MAAM,MAAM,CAAC;AAAA,CAAI;AAC7F,MAAI,EAAE,qBAAqB,GAAG;AAC5B,YAAQ,OAAO,MAAM,OAAO,KAAK,wBAAwB,cAAAA,QAAM,IAAI,EAAE,kBAAkB,CAAC;AAAA,CAAI;AAAA,EAC9F;AACA,MAAI,EAAE,kBAAkB,GAAG;AACzB,YAAQ,OAAO,MAAM,OAAO,KAAK,wBAAwB,cAAAA,QAAM,IAAI,EAAE,eAAe,CAAC;AAAA,CAAI;AAAA,EAC3F;AACA,MAAI,EAAE,sBAAsB,GAAG;AAC7B,YAAQ,OAAO,MAAM,OAAO,KAAK,wBAAwB,cAAAA,QAAM,IAAI,EAAE,mBAAmB,CAAC;AAAA,CAAI;AAAA,EAC/F;AACA,MAAI,EAAE,iBAAiB,GAAG;AACxB,YAAQ,OAAO,MAAM,OAAO,KAAK,wBAAwB,cAAAA,QAAM,IAAI,EAAE,cAAc,CAAC;AAAA,CAAI;AAAA,EAC1F;AAGA,MAAI,OAAO,iBAAiB;AAC1B,YAAQ,OAAO,MAAM,IAAI;AACzB,YAAQ,OAAO,MAAM,KAAK,IAAI,IAAI,cAAAA,QAAM,OAAO,oBAAoB,CAAC;AAAA,CAAI;AACxE,YAAQ,OAAO,MAAM,OAAO,cAAAA,QAAM,IAAI,OAAO,eAAe,CAAC;AAAA,CAAI;AAAA,EACnE;AAGA,MAAI,OAAO,MAAM,SAAS,GAAG;AAC3B,YAAQ,OAAO,MAAM,IAAI;AACzB,YAAQ,OAAO,MAAM,KAAK,IAAI,2BAA2B,CAAC;AAAA,CAAI;AAC9D,eAAW,KAAK,OAAO,MAAM,MAAM,GAAG,EAAE,GAAG;AACzC,cAAQ,OAAO,MAAM,OAAO,cAAAA,QAAM,IAAI,MAAG,CAAC,IAAI,cAAAA,QAAM,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,IAClE;AACA,QAAI,OAAO,MAAM,SAAS,IAAI;AAC5B,cAAQ,OAAO,MAAM,OAAO,cAAAA,QAAM,IAAI,cAAS,OAAO,MAAM,SAAS,EAAE,OAAO,CAAC;AAAA,CAAI;AAAA,IACrF;AAAA,EACF;AAEA,UAAQ,OAAO,MAAM,IAAI;AAC3B;AAwBO,SAAS,aAAa,MAAyB;AACpD,UAAQ,OAAO,MAAM,IAAI;AACzB,UAAQ,OAAO,MAAM,GAAG,MAAM,kBAAkB,CAAC;AAAA,CAAI;AACrD,UAAQ,OAAO,MAAM,GAAG,IAAI,kUAAyD,CAAC;AAAA,CAAI;AAE1F,QAAM,MAAM,CAAC,MAAc,UAAoC;AAC7D,UAAM,MAAM,QAAQ,cAAAA,QAAM,MAAM,KAAK,IAAI,cAAAA,QAAM,IAAI,WAAW;AAC9D,YAAQ,OAAO,MAAM,KAAK,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,GAAG;AAAA,CAAI;AAAA,EAC3D;AAEA,MAAI,mBAAmB,KAAK,kBAAkB,SAAS,OAAO;AAC9D,MAAI,oBAAoB,KAAK,aAAa;AAC1C,MAAI,eAAe,KAAK,SAAS;AACjC,MAAI,eAAe,KAAK,SAAS;AACjC,MAAI,sBAAsB,KAAK,gBAAgB;AAC/C,MAAI,oBAAoB,KAAK,cAAc;AAC3C,MAAI,kBAAkB,KAAK,WAAW;AACtC,MAAI,sBAAsB,KAAK,eAAe;AAE9C,UAAQ,OAAO,MAAM,IAAI;AACzB,MAAI,wBAAwB,KAAK,iBAAiB;AAClD,MAAI,kBAAkB,KAAK,YAAY;AAEvC,UAAQ,OAAO,MAAM,IAAI;AACzB,MAAI,gBAAgB,KAAK,MAAM;AAC/B,MAAI,YAAY,KAAK,MAAM;AAC3B,MAAI,cAAc,KAAK,QAAQ;AAC/B,MAAI,KAAK,iBAAiB;AACxB,QAAI,iBAAiB,KAAK,eAAe;AAAA,EAC3C;AAEA,UAAQ,OAAO,MAAM,IAAI;AAC3B;AA1KA,IAOAC,eAKM,KACA,OACA,IACA,MACA,KACA;AAjBN;AAAA;AAAA;AAOA,IAAAA,gBAAkB;AAKlB,IAAM,MAAM,cAAAD,QAAM;AAClB,IAAM,QAAQ,cAAAA,QAAM,KAAK;AACzB,IAAM,KAAK,cAAAA,QAAM,MAAM,QAAG;AAC1B,IAAM,OAAO,cAAAA,QAAM,OAAO,QAAG;AAC7B,IAAM,MAAM,cAAAA,QAAM,IAAI,QAAG;AACzB,IAAM,QAAQ,cAAAA,QAAM,IAAI,QAAG;AAAA;AAAA;;;ACjB3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQO,SAAS,aAAa,YAA4B;AACvD,QAAM,aAAa,GAAG,UAAU;AAChC,aAAAE,QAAG,aAAa,YAAY,UAAU;AACtC,SAAO;AACT;AAEO,SAAS,WAAW,YAA4B;AACrD,SAAO,WAAAA,QAAG,aAAa,YAAY,OAAO;AAC5C;AAEO,SAAS,YAAY,YAAoB,SAAuB;AACrE,aAAAA,QAAG,cAAc,YAAY,SAAS,OAAO;AAC/C;AASO,SAAS,mBAAmB,QAAwB;AACzD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAqBkB,MAAM;AAAA;AAAA;AAAA;AAAA;AAKjC;AAIO,SAAS,qBAAqB,QAAwB;AAC3D,SAAO;AAAA;AAAA,+BAEsB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWrC;AAMO,SAAS,uBAAuB,SAA0B;AAC/D,MAAI,CAAC,QAAQ,SAAS,wBAAwB,KAAK,CAAC,QAAQ,SAAS,UAAU,GAAG;AAChF,WAAO;AAAA,EACT;AAGA,MAAI,0CAA0C,KAAK,OAAO,EAAG,QAAO;AAGpE,MAAI,sDAAsD,KAAK,OAAO,EAAG,QAAO;AAChF,MAAI,4DAA4D,KAAK,OAAO,EAAG,QAAO;AAEtF,SAAO;AACT;AAEO,SAAS,wBAAwB,SAAyB;AAC/D,MAAI,WAAW;AAGf,aAAW,SAAS,QAAQ,8CAA8C,WAAW;AAGrF,aAAW,SAAS;AAAA,IAClB;AAAA,IACA;AAAA,EACF;AAGA,aAAW,SAAS,QAAQ,0CAA0C,6BAA6B;AAEnG,SAAO;AACT;AAEO,SAAS,gBAAgB,UAAkB,QAAwB;AACxE,MAAI,uBAAuB,QAAQ,GAAG;AACpC,WAAO,wBAAwB,QAAQ;AAAA,EACzC;AAGA,MAAI,SAAS,SAAS,eAAe,GAAG;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,aAAa;AAAA;AAEnB,QAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAOM,MAAM;AAAA;AAAA;AAAA;AAM/B,MAAI,UAAU;AACd,QAAM,gBAAgB,kBAAkB,OAAO;AAC/C,MAAI,gBAAgB,IAAI;AACtB,cACE,QAAQ,MAAM,GAAG,aAAa,IAC9B,aACA,QAAQ,MAAM,aAAa;AAAA,EAC/B,OAAO;AACL,cAAU,aAAa;AAAA,EACzB;AAGA,QAAM,cAAc,QAAQ,YAAY,IAAI;AAC5C,MAAI,gBAAgB,IAAI;AACtB,cACE,QAAQ,MAAM,GAAG,WAAW,IAAI,aAAa,QAAQ,MAAM,WAAW;AAAA,EAC1E;AAEA,SAAO;AACT;AAGA,SAAS,kBAAkB,KAAqB;AAC9C,QAAM,QAAQ,IAAI,MAAM,IAAI;AAC5B,MAAI,iBAAiB;AACrB,MAAI,YAAY;AAChB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,gBAAgB,KAAK,IAAI,EAAG,kBAAiB;AACjD,iBAAa,KAAK,SAAS;AAAA,EAC7B;AACA,MAAI,mBAAmB,GAAI,QAAO;AAGlC,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,KAAK,gBAAgB,KAAK;AACxC,cAAU,MAAM,CAAC,EAAE,SAAS;AAAA,EAC9B;AACA,SAAO;AACT;AAIO,SAAS,kBAAkB,UAAkB,QAAwB;AAC1E,MAAI,SAAS,SAAS,UAAU,GAAG;AACjC,WAAO;AAAA,EACT;AAEA,MAAI,UAAU;AAEd,MAAI,QAAQ,SAAS,UAAU,GAAG;AAChC,cAAU,QAAQ,QAAQ,iBAAiB,wBAAwB;AAAA,EACrE,OAAO;AACL,cAAU,QAAQ;AAAA,MAChB;AAAA,MACA;AAAA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,UAAU,GAAG;AAChC,cAAU,QAAQ;AAAA,MAChB;AAAA,MACA,8BAA8B,MAAM;AAAA,IACtC;AAAA,EACF,OAAO;AACL,cAAU,QAAQ;AAAA,MAChB;AAAA,MACA;AAAA,+BAAoD,MAAM;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,iBAAiB,UAAkB,QAAwB;AACzE,MAAI,UAAU;AAEd,YAAU,QAAQ;AAAA,IAChB;AAAA,IACA,sBAAsB,MAAM;AAAA,EAC9B;AAEA,YAAU,QAAQ;AAAA,IAChB;AAAA,IACA,aAAa,MAAM;AAAA,EACrB;AAEA,SAAO;AACT;AAEO,SAAS,mBAAmB,UAAkB,QAAwB;AAC3E,MAAI,UAAU;AAEd,YAAU,QAAQ;AAAA,IAChB;AAAA,IACA,oBAAoB,MAAM;AAAA,EAC5B;AAEA,YAAU,QAAQ;AAAA,IAChB;AAAA,IACA,aAAa,MAAM;AAAA,EACrB;AAEA,SAAO;AACT;AAQO,SAAS,iBAAiB,UAG/B;AACA,QAAM,eAAe,CAAC,eAAe;AACrC,QAAM,UACJ,SAAS,SAAS,QAAQ,KAAK,SAAS,SAAS,QAAQ;AAE3D,MAAI,CAAC,QAAS,QAAO,EAAE,SAAS,UAAU,SAAS,MAAM;AAGzD,MAAI,UAAU,SACX;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,EACF;AAIF,aAAW,MAAM,cAAc;AAC7B,cAAU,QAAQ,QAAQ,IAAI,EAAE;AAAA,EAClC;AAEA,SAAO,EAAE,SAAS,SAAS,SAAS,YAAY,SAAS;AAC3D;AAsBO,SAAS,uBAAuB,UAA0B;AAC/D,MAAI,SAAS,SAAS,UAAU,EAAG,QAAO;AAE1C,QAAM,QAAQ;AAAA;AAAA;AAAA,eAGD,KAAK,UAAU,oBAAoB,CAAC;AAAA;AAAA;AAIjD,QAAM,cAAc,SAAS,YAAY,IAAI;AAC7C,MAAI,gBAAgB,IAAI;AACtB,WAAO,SAAS,MAAM,GAAG,WAAW,IAAI,QAAQ,SAAS,MAAM,WAAW;AAAA,EAC5E;AACA,SAAO;AACT;AAEO,SAAS,yBAAyB,UAA0B;AACjE,MAAI,SAAS,SAAS,gBAAgB,EAAG,QAAO;AAChD,SAAO,SAAS;AAAA,IACd;AAAA,IACA;AAAA,oBAAyC,KAAK,UAAU,sBAAsB,CAAC;AAAA,EACjF;AACF;AAIO,SAAS,kBACd,YACA,MAAM,QAAQ,IAAI,GACV;AACR,UAAQ,YAAY;AAAA,IAClB,KAAK;AACH,aAAO,aAAAC,QAAK,KAAK,KAAK,kBAAkB;AAAA,IAC1C,KAAK;AACH,aAAO,aAAAA,QAAK,KAAK,KAAK,mBAAmB;AAAA,IAC3C,KAAK;AACH,aAAO,aAAAA,QAAK,KAAK,KAAK,mBAAmB;AAAA,IAC3C,KAAK;AACH,aAAO,aAAAA,QAAK,KAAK,KAAK,cAAc;AAAA,IACtC,KAAK;AACH,aAAO,aAAAA,QAAK,KAAK,KAAK,eAAe;AAAA,IACvC,KAAK;AACH,aAAO,aAAAA,QAAK,KAAK,KAAK,gBAAgB;AAAA,IACxC;AACE,aAAO,aAAAA,QAAK,KAAK,KAAK,cAAc;AAAA,EACxC;AACF;AASO,SAAS,uBAAuB,SAA2B;AAChE,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,SAAS,gBAAgB,GAAG;AACvC,aAAS,KAAK,2DAAsD;AAAA,EACtE;AACA,MAAI,CAAC,QAAQ,SAAS,wBAAwB,KAAK,CAAC,QAAQ,SAAS,SAAS,GAAG;AAC/E,aAAS,KAAK,sEAAiE;AAAA,EACjF;AACA,MAAI,CAAC,QAAQ,KAAK,EAAE,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,EAAE,SAAS,IAAI,GAAG;AAAA,EAEtE;AAGA,MAAI,QAAQ,SAAS,QAAQ,KAAK,QAAQ,SAAS,QAAQ,GAAG;AAC5D,aAAS;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,yBAAyB,SAA2B;AAClE,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,SAAS,gBAAgB,GAAG;AACvC,aAAS,KAAK,oEAA+D;AAAA,EAC/E;AACA,MAAI,CAAC,QAAQ,SAAS,UAAU,GAAG;AACjC,aAAS,KAAK,kEAA6D;AAAA,EAC7E;AACA,MAAI,QAAQ,SAAS,QAAQ,KAAK,QAAQ,SAAS,QAAQ,GAAG;AAC5D,aAAS;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AA3YA,IAAAC,YACAC,cA6EM,iBA4MA,sBASA;AAnSN;AAAA;AAAA;AAAA,IAAAD,aAAe;AACf,IAAAC,eAAiB;AA6EjB,IAAM,kBAAkB;AA4MxB,IAAM,uBAAuB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,IAAM,yBAAyB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA;;;AC1SA,uBAAwB;AACxB,IAAAC,cAAe;AACf,IAAAC,gBAAiB;;;ACDjB,iBAAgB;AAChB,IAAAC,gBAAkB;;;ACFlB,gBAAe;AACf,kBAAiB;AACjB,iBAA8B;AAC9B,IAAAC,gBAAkB;;;ACHlB,mBAAkB;AAKlB,IAAM,iBAAyC;AAAA,EAC7C,UAAU;AAAA,EACV,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,eAAe;AACjB;AAEA,IAAM,iBAAiB,CAAC,YAAY,eAAe,mBAAmB,aAAa;AAM5E,IAAM,gBAAwC;AAAA,EACnD,2BAA2B;AAAA,EAC3B,+BAA+B;AAAA,EAC/B,iCAAiC;AAAA,EACjC,iCAAiC;AAAA,EACjC,gCAAgC;AAAA,EAChC,6BAA6B;AAAA,EAC7B,oCAAoC;AAAA,EACpC,mCAAmC;AAAA,EACnC,+BAA+B;AAAA,EAC/B,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,iCAAiC;AAAA,EACjC,kCAAkC;AAAA,EAClC,oCAAoC;AAAA,EACpC,gCAAgC;AAAA,EAChC,kCAAkC;AAAA,EAClC,qCAAqC;AAAA,EACrC,2BAA2B;AAC7B;AAUO,IAAM,kBAAkD;AAAA;AAAA,EAE7D,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,gCAAgC;AAAA,EAChC,2BAA2B;AAAA;AAAA,EAE3B,iCAAiC;AAAA,EACjC,6BAA6B;AAAA,EAC7B,oCAAoC;AAAA,EACpC,gCAAgC;AAAA,EAChC,iCAAiC;AAAA,EACjC,iCAAiC;AAAA,EACjC,kCAAkC;AAAA;AAAA,EAElC,oCAAoC;AAAA,EACpC,2BAA2B;AAAA,EAC3B,+BAA+B;AAAA,EAC/B,kCAAkC;AAAA,EAClC,qCAAqC;AAAA;AAAA,EAErC,mCAAmC;AAAA,EACnC,+BAA+B;AACjC;AASA,IAAM,sBAA8C;AAAA,EAClD,+BAA+B;AAAA,EAC/B,8BAA8B;AAAA,EAC9B,uBAAuB;AAAA,EACvB,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AACf;AAEA,SAAS,gBAAgB,QAAsC;AAC7D,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,CAAC,QAAQ,GAAG,KAAK,OAAO,QAAQ,mBAAmB,GAAG;AAC/D,QAAI,OAAO,WAAW,MAAM,EAAG,QAAO;AAAA,EACxC;AACA,SAAO;AACT;AAIA,IAAM,SAAS;AAAA,EACb,SAAS,aAAAC,QAAM,MAAM,QAAG;AAAA,EACxB,OAAO,aAAAA,QAAM,IAAI,QAAG;AAAA,EACpB,MAAM,aAAAA,QAAM,OAAO,QAAG;AAAA,EACtB,MAAM,aAAAA,QAAM,KAAK,QAAG;AAAA,EACpB,SAAS,aAAAA,QAAM,KAAK;AAAA,EACpB,QAAQ,aAAAA,QAAM,KAAK,QAAG;AAAA,EACtB,WAAW,aAAAA,QAAM,OAAO,QAAG;AAAA,EAC3B,QAAQ,aAAAA,QAAM,QAAQ,QAAG;AAC3B;AAEO,IAAM,MAAM;AAAA,EACjB,KAAK,KAAmB;AACtB,YAAQ,IAAI,KAAK,OAAO,IAAI,KAAK,aAAAA,QAAM,MAAM,GAAG,CAAC,EAAE;AAAA,EACrD;AAAA,EAEA,QAAQ,KAAmB;AACzB,YAAQ,IAAI,KAAK,OAAO,OAAO,KAAK,aAAAA,QAAM,MAAM,GAAG,CAAC,EAAE;AAAA,EACxD;AAAA,EAEA,KAAK,KAAmB;AACtB,YAAQ,IAAI,KAAK,OAAO,IAAI,KAAK,aAAAA,QAAM,OAAO,GAAG,CAAC,EAAE;AAAA,EACtD;AAAA,EAEA,MAAM,KAAmB;AACvB,YAAQ,MAAM,KAAK,OAAO,KAAK,KAAK,aAAAA,QAAM,IAAI,GAAG,CAAC,EAAE;AAAA,EACtD;AAAA,EAEA,QAAQ,OAAqB;AAC3B,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,aAAAA,QAAM,KAAK,KAAK,kBAAQ,KAAK,eAAK,CAAC;AAC/C,YAAQ,IAAI,EAAE;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,OAAqB;AACpC,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,aAAAA,QAAM,KAAK,OAAO,kBAAQ,KAAK,eAAK,IAAI,aAAAA,QAAM,IAAI,0BAA0B,CAAC;AACzF,YAAQ,IAAI,EAAE;AAAA,EAChB;AAAA,EAEA,KAAK,UAAkB,OAAqB;AAC1C,YAAQ;AAAA,MACN,OAAO,OAAO,MAAM,IAAI,aAAAA,QAAM,OAAO,QAAQ,CAAC,IAAI,aAAAA,QAAM,KAAK,IAAI,KAAK,SAAS,UAAU,IAAI,MAAM,EAAE,GAAG,CAAC;AAAA,IAC3G;AAAA,EACF;AAAA,EAEA,KAAK,UAAkB,OAAqB;AAC1C,YAAQ;AAAA,MACN,OAAO,OAAO,MAAM,IAAI,aAAAA,QAAM,MAAM,QAAQ,CAAC,IAAI,aAAAA,QAAM,KAAK,UAAK,KAAK,SAAS,UAAU,IAAI,MAAM,EAAE,EAAE,CAAC;AAAA,IAC1G;AAAA,EACF;AAAA,EAEA,MAAM,KAAa,UAAiB,MAAc,KAAmB;AACnE,UAAM,OAAO,aAAa,IAAI,aAAAA,QAAM,IAAI,OAAO,IAAI,aAAAA,QAAM,OAAO,OAAO;AACvE,YAAQ;AAAA,MACN,SAAS,aAAAA,QAAM,KAAK,GAAG,IAAI,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,IAAI,IAAI,KAAK,aAAAA,QAAM,MAAM,GAAG,CAAC;AAAA,IAC/E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,OAAuB,QAAQ,GAAS;AACrD,UAAM,YAAY,MAAM,SAAS,aAAAA,QAAM,OAAO,MAAM,MAAM,IAAI,aAAAA,QAAM,KAAK,cAAc;AACvF,UAAM,YACJ,MAAM,SAAS,iBACX,aAAAA,QAAM,IAAI,2BAA2B,IACrC,MAAM,SAAS,iBACf,aAAAA,QAAM,IAAI,gBAAgB,IAC1B,aAAAA,QAAM,IAAI,gBAAgB;AAEhC,UAAM,aAAa,QAAQ,IAAI,aAAAA,QAAM,KAAK,SAAM,KAAK,EAAE,IAAI;AAE3D,YAAQ,IAAI,KAAK,OAAO,SAAS,KAAK,SAAS,IAAI,SAAS,GAAG,UAAU,EAAE;AAC3E,YAAQ,IAAI,UAAU,aAAAA,QAAM,KAAK,OAAO,CAAC,IAAI,aAAAA,QAAM,IAAI,MAAM,QAAQ,CAAC,GAAG,MAAM,OAAO,IAAI,aAAAA,QAAM,IAAI,IAAI,MAAM,IAAI,EAAE,IAAI,EAAE,EAAE;AAC5H,YAAQ,IAAI,UAAU,aAAAA,QAAM,KAAK,MAAM,CAAC,KAAK,aAAAA,QAAM,IAAI,MAAM,QAAQ,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE;AAErF,UAAM,MAAM,gBAAgB,MAAM,MAAM;AACxC,QAAI,KAAK;AACP,cAAQ,IAAI,UAAU,aAAAA,QAAM,KAAK,aAAQ,CAAC,IAAI,aAAAA,QAAM,OAAO,GAAG,CAAC,EAAE;AAAA,IACnE;AACA,YAAQ;AAAA,MACN,aAAAA,QAAM,IAAI,qEAAqE;AAAA,IACjF;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,IAAuB;AACjC,YAAQ,IAAI,KAAK,OAAO,MAAM,KAAK,aAAAA,QAAM,QAAQ,eAAe,CAAC,KAAK,aAAAA,QAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,GAAG,OAAO,IAAI,aAAAA,QAAM,IAAI,IAAI,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE;AAC5I,YAAQ,IAAI,UAAU,aAAAA,QAAM,IAAI,GAAG,QAAQ,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE;AAC3D,YAAQ,IAAI,EAAE;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,MAAc,OAAe,QAAgB,UAAwB;AAC5E,UAAM,QAAkB,CAAC;AACzB,QAAI,SAAS,EAAG,OAAM,KAAK,aAAAA,QAAM,IAAI,GAAG,MAAM,SAAS,WAAW,IAAI,MAAM,EAAE,EAAE,CAAC;AACjF,QAAI,WAAW,EAAG,OAAM,KAAK,aAAAA,QAAM,OAAO,GAAG,QAAQ,WAAW,aAAa,IAAI,MAAM,EAAE,EAAE,CAAC;AAC5F,UAAM,SAAS,MAAM,SAAS,IAAI,MAAM,KAAK,aAAAA,QAAM,KAAK,QAAK,CAAC,IAAI,aAAAA,QAAM,KAAK,GAAG;AAChF,UAAM,cAAc,MAAM,OAAO,EAAE;AACnC,YAAQ,IAAI,KAAK,IAAI,KAAK,aAAAA,QAAM,KAAK,MAAM,WAAW,CAAC,IAAI,MAAM,EAAE;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,cAAsB,iBAAyB,YAAoB,QAAsB;AACjG,YAAQ;AAAA,MACN,KAAK,aAAAA,QAAM,KAAK,gBAAgB,CAAC,KAAK,aAAAA,QAAM,MAAM,OAAO,YAAY,CAAC,CAAC,KACpE,aAAAA,QAAM,KAAK,MAAG,CAAC,KAAK,aAAAA,QAAM,KAAK,YAAY,CAAC,KAAK,aAAAA,QAAM,MAAM,OAAO,eAAe,CAAC,CAAC,QAAQ,oBAAoB,IAAI,MAAM,EAAE,KAC7H,aAAAA,QAAM,KAAK,MAAG,CAAC,KAAK,aAAAA,QAAM,KAAK,WAAW,CAAC,KAAK,aAAAA,QAAM,MAAM,aAAa,IAAI,CAAC,KAC9E,aAAAA,QAAM,KAAK,MAAG,CAAC,KAAK,aAAAA,QAAM,KAAK,SAAS,CAAC,KAAK,aAAAA,QAAM,KAAK,MAAM,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,YAAQ,IAAI,aAAAA,QAAM,KAAK,OAAO,SAAI,OAAO,EAAE,CAAC,CAAC;AAAA,EAC/C;AAAA,EAEA,QAAc;AACZ,YAAQ,IAAI,EAAE;AAAA,EAChB;AAAA,EAEA,OAAO,OAAqB;AAC1B,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,aAAAA,QAAM,KAAK,OAAO,MAAM,KAAK,KAAK,IAAI,CAAC;AACnD,YAAQ,IAAI,EAAE;AAAA,EAChB;AAAA,EAEA,MAAM,KAAmB;AACvB,YAAQ,IAAI,GAAG;AAAA,EACjB;AAAA,EAEA,MAAM,KAAmB;AACvB,QAAI,QAAQ,IAAI,mBAAmB,KAAK;AACtC,cAAQ,IAAI,KAAK,aAAAA,QAAM,KAAK,MAAG,CAAC,KAAK,aAAAA,QAAM,KAAK,GAAG,CAAC,EAAE;AAAA,IACxD;AAAA,EACF;AACF;;;ADlIO,IAAM,mBAAgF;AAAA;AAAA,EAE3F,gCAAmC;AAAA;AAAA,EACnC,4BAAmC;AAAA;AAAA,EACnC,gCAAmC;AAAA;AAAA;AAAA,EAGnC,2BAAmC;AAAA;AAAA,EACnC,iCAAmC;AAAA;AAAA,EACnC,6BAAmC;AAAA;AAAA,EACnC,oCAAmC;AAAA;AAAA,EACnC,gCAAmC;AAAA;AAAA,EACnC,iCAAmC;AAAA;AAAA,EACnC,iCAAmC;AAAA;AAAA,EACnC,kCAAmC;AAAA;AAAA;AAAA,EAGnC,oCAAmC;AAAA;AAAA,EACnC,2BAAmC;AAAA;AAAA,EACnC,+BAAmC;AAAA;AAAA,EACnC,kCAAmC;AAAA;AAAA,EACnC,qCAAoC;AAAA;AAAA;AAAA,EAGpC,mCAAmC;AAAA;AAAA,EACnC,+BAAmC;AAAA;AACrC;AAEO,IAAM,iBAAyC;AAAA,EACpD,gCAAmC;AAAA,EACnC,6BAAmC;AAAA,EACnC,mCAAmC;AAAA,EACnC,oCAAmC;AAAA,EACnC,+BAAmC;AAAA,EACnC,2BAAmC;AAAA,EACnC,+BAAmC;AAAA,EACnC,iCAAmC;AAAA,EACnC,iCAAmC;AAAA,EACnC,gCAAmC;AAAA,EACnC,4BAAmC;AAAA,EACnC,iCAAmC;AAAA,EACnC,kCAAmC;AAAA,EACnC,oCAAmC;AAAA,EACnC,gCAAmC;AAAA,EACnC,kCAAmC;AAAA,EACnC,qCAAoC;AAAA,EACpC,2BAAmC;AACrC;AAEO,IAAM,wBAAgD;AAAA,EAC3D,gCAAmC;AAAA,EACnC,6BAAmC;AAAA,EACnC,mCAAmC;AAAA,EACnC,oCAAmC;AAAA,EACnC,+BAAmC;AACrC;AAEO,IAAM,oBAA4C;AAAA,EACvD,gCAAmC;AAAA,EACnC,6BAAmC;AAAA,EACnC,mCAAmC;AAAA,EACnC,oCAAmC;AAAA,EACnC,+BAAmC;AAAA,EACnC,2BAAmC;AAAA,EACnC,+BAAmC;AAAA,EACnC,iCAAmC;AAAA,EACnC,iCAAmC;AAAA,EACnC,gCAAmC;AAAA,EACnC,4BAAmC;AAAA,EACnC,iCAAmC;AAAA,EACnC,kCAAmC;AAAA,EACnC,oCAAmC;AAAA,EACnC,gCAAmC;AAAA,EACnC,kCAAmC;AAAA,EACnC,qCAAoC;AAAA,EACpC,2BAAmC;AACrC;AASA,IAAM,eAAe,oBAAI,IAA0B;AAenD,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,gBAAgB,KAA6B;AACpD,MAAI,SAAS,GAAG,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,IAAI,QAAQ,KAAK,GAAG;AACzE,WAAO,IAAI;AAAA,EACb;AACA,MAAI,SAAS,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG;AACxC,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAIA,IAAM,oBAA+C;AAAA;AAAA,EAEnD,2BAA2B;AAAA,EAC3B,+BAA+B;AAAA;AAAA,EAE/B,gCAAgC;AAAA,EAChC,6BAA6B;AAAA,EAC7B,mCAAmC;AAAA,EACnC,oCAAoC;AAAA;AAAA,EAEpC,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,iCAAiC;AAAA,EACjC,kCAAkC;AAAA,EAClC,oCAAoC;AAAA,EACpC,gCAAgC;AAAA;AAAA,EAEhC,2BAA2B;AAC7B;AAEA,IAAM,eAA0C;AAAA;AAAA,EAE9C,2BAA2B;AAAA,EAC3B,+BAA+B;AAAA,EAC/B,iCAAiC;AAAA,EACjC,iCAAiC;AAAA;AAAA,EAEjC,oCAAoC;AAAA,EACpC,gCAAgC;AAAA,EAChC,6BAA6B;AAAA,EAC7B,mCAAmC;AAAA,EACnC,+BAA+B;AAAA;AAAA,EAE/B,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,iCAAiC;AAAA,EACjC,kCAAkC;AAAA,EAClC,oCAAoC;AAAA,EACpC,gCAAgC;AAAA;AAAA,EAEhC,kCAAkC;AAAA,EAClC,qCAAqC;AAAA,EACrC,2BAA2B;AAC7B;AAEA,IAAM,iBAA4C;AAAA,EAChD,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,iCAAiC;AAAA,EACjC,kCAAkC;AAAA,EAClC,oCAAoC;AAAA,EACpC,gCAAgC;AAClC;AAEA,SAAS,SAAS,QAA2C;AAC3D,MAAI,WAAW,SAAU,QAAO;AAChC,MAAI,WAAW,WAAY,QAAO;AAClC,SAAO;AACT;AASA,IAAM,0BAA0B;AAAA;AAAA,EAE9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AACF;AAEO,SAAS,wBAAwB,OAAuB;AAC7D,QAAM,MAAM,MAAM,QAAQ,YAAY;AACtC,SACE,IAAI,SAAS,UAAU,KACvB,IAAI,SAAS,mBAAmB,KAChC,IAAI,SAAS,SAAS,KACtB,IAAI,SAAS,sBAAsB,KACnC,IAAI,SAAS,aAAa,KAC1B,IAAI,SAAS,aAAa,KAC1B,IAAI,SAAS,cAAc;AAE/B;AAMA,SAAS,gBAAgB,KAAiF;AAExG,MAAI,IAAI,UAAU,KAAM,QAAO;AAG/B,MAAI,IAAI,WAAW,SACjB,IAAI,QAAQ,WAAW,eAAe,KACtC,IAAI,QAAQ,SAAS,kBAAkB,KACvC,IAAI,QAAQ,SAAS,aAAa,IACjC;AACD,WAAO;AAAA,EACT;AAGA,MAAI,IAAI,UAAU,IAAI,OAAO,WAAW,WAAW,GAAG;AACpD,WAAO;AAAA,EACT;AAGA,SAAO;AACT;AAEA,SAAS,sBACP,KACwB;AACxB,QAAM,QAAQ,IAAI,QAAQ,YAAY;AACtC,MAAI,MAAM,SAAS,qBAAqB,KAAK,MAAM,SAAS,eAAe,GAAG;AAC5E,WAAO;AAAA,EACT;AACA,MAAI,MAAM,SAAS,eAAe,KAAK,MAAM,SAAS,QAAQ,GAAG;AAC/D,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAIA,eAAe,wBAAwB,KAA+B;AACpE,QAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,QAAQ;AAC/C,QAAM,iBAAiBA,eAAc,YAAAC,QAAK,KAAK,KAAK,cAAc,CAAC;AAEnE,MAAI;AACF,UAAM,WAAW,eAAe,QAAQ,wBAAwB;AAChE,WAAO,WAAO,0BAAc,QAAQ,EAAE;AAAA,EACxC,QAAQ;AAAA,EAER;AAEA,QAAM,iBAAiB,YAAAA,QAAK,KAAK,KAAK,QAAQ,UAAU;AACxD,MAAI,UAAAC,QAAG,WAAW,cAAc,GAAG;AACjC,WAAO,WAAO,0BAAc,cAAc,EAAE;AAAA,EAC9C;AAEA,QAAM,gBAAgB,YAAAD,QAAK,KAAK,KAAK,OAAO,UAAU;AACtD,MAAI,UAAAC,QAAG,WAAW,aAAa,GAAG;AAChC,QAAI;AACF,aAAO,WAAO,0BAAc,aAAa,EAAE;AAAA,IAC7C,SAAS,KAAc;AACrB,YAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,UAAI,MAAM,mCAAmC,MAAM,EAAE;AAAA,IACvD;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAQA,eAAe,iBACb,KACA,QACA,WACuD;AACvD,QAAM,WAAW,GAAG,SAAS,KAAK,MAAM;AACxC,QAAM,SAAS,aAAa,IAAI,QAAQ;AACxC,MAAI,QAAQ;AACV,WAAO,EAAE,QAAQ,QAAQ,WAAW,KAAK;AAAA,EAC3C;AAMA,QAAM,CAAC,EAAE,OAAO,GAAG,WAAW,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA;AAAA,IAEhE,OAAO,QAAQ,EAAE,MAAM,MAAM;AAC3B,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E,CAAC;AAAA;AAAA,IAGD,wBAAwB,GAAG;AAAA;AAAA,IAG3B,QAAQ,QAAQ,EAAE,KAAK,MAAM;AAC3B,YAAM,cAAc,KAAK,IAAI;AAC7B,UAAI;AAEF,YAAIC;AACJ,YAAI;AACF,UAAAA,YAAW,QAAQ,YAAAF,QAAK;AAAA,YACtB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH,QAAQ;AACN,UAAAE,YAAW,QAAQ,2BAA2B;AAAA,QAChD;AACA,eAAO,EAAE,UAAAA,WAAU,WAAW,MAAM,QAAQ,KAAK,IAAI,IAAI,YAAY;AAAA,MACvE,QAAQ;AACN,YAAI,MAAM,sFAAiF;AAC3F,eAAO,EAAE,UAAU,MAAM,WAAW,OAAO,QAAQ,KAAK,IAAI,IAAI,YAAY;AAAA,MAC9E;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,QAAM,SAAS,gBAAgB,SAAS;AACxC,QAAM,QAAQ,SAAS,MAAM;AAC7B,QAAM,EAAE,UAAU,WAAW,kBAAkB,IAAI;AAQnD,QAAM,cAAc;AAAA,IAClB;AAAA,IAAW;AAAA,IAAY;AAAA,IAAW;AAAA,IAClC;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,EACtC;AAEA,QAAM,eAA+C;AAAA;AAAA,IAEnD,EAAE,SAAS,wBAAwB;AAAA;AAAA,IAEnC;AAAA,MACE,OAAO,CAAC,WAAW,YAAY,YAAY,UAAU;AAAA,MACrD,SAAS,EAAE,YAAY,OAAO;AAAA,MAC9B,iBAAiB;AAAA,QACf,eAAe;AAAA,UACb,aAAa;AAAA,UACb,YAAY;AAAA,UACZ,cAAc,EAAE,KAAK,KAAK;AAAA,QAC5B;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU;AAEZ,iBAAa,KAAK;AAAA,MAChB,OAAO,CAAC,WAAW,YAAY,YAAY,UAAU;AAAA,MACrD,SAAS,EAAE,YAAY,OAAO;AAAA,MAC9B,iBAAiB;AAAA,QACf,QAAQ;AAAA,QACR,eAAe;AAAA,UACb,aAAa;AAAA,UACb,YAAY;AAAA,UACZ,cAAc,EAAE,KAAK,KAAK;AAAA,QAC5B;AAAA,MACF;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,OAAO;AAEL,iBAAa,KAAK;AAAA,MAChB,OAAO,CAAC,WAAW,YAAY,YAAY,UAAU;AAAA,MACrD,SAAS,EAAE,YAAY,OAAO;AAAA,MAC9B,iBAAiB;AAAA,QACf,eAAe;AAAA,UACb,aAAa;AAAA,UACb,YAAY;AAAA,UACZ,cAAc,EAAE,KAAK,KAAK;AAAA,QAC5B;AAAA,MACF;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,IAAI,OAAO;AAAA,IACxB,KAAK;AAAA,IACL,oBAAoB;AAAA,IACpB,gBAAgB;AAAA,EAClB,CAAC;AAED,QAAM,SAAuB;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,cAAc;AAAA;AAAA,IACd,cAAc,eAAe;AAAA,EAC/B;AAEA,eAAa,IAAI,UAAU,MAAM;AACjC,SAAO,EAAE,QAAQ,WAAW,MAAM;AACpC;AAIA,IAAM,sBAAsB;AAAA,EAC1B;AAAA,EAAW;AAAA,EAAY;AAAA,EAAW;AAAA,EAClC;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AACtC;AAIA,eAAsB,UAAU,SAAyC;AACvE,QAAM,eAAe,KAAK,IAAI;AAE9B,QAAM,qBAAqB,YAAAF,QAAK,QAAQ,QAAQ,UAAU;AAE1D,MAAI,CAAC,UAAAC,QAAG,WAAW,kBAAkB,GAAG;AACtC,UAAM,IAAI,MAAM,mBAAmB,QAAQ,UAAU,EAAE;AAAA,EACzD;AAEA,QAAM,aAAa,UAAAA,QAAG,SAAS,kBAAkB;AACjD,QAAM,qBAAqB,WAAW,OAAO;AAC7C,QAAM,YAAY,qBACd,YAAAD,QAAK,QAAQ,kBAAkB,IAC/B;AAEJ,QAAM,MAAM,QAAQ,IAAI;AAGxB,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,EAAE,QAAQ,UAAU,IAAI,MAAM,iBAAiB,KAAK,QAAQ,QAAQ,SAAS;AACnF,QAAM,SAAS,KAAK,IAAI,IAAI;AAE5B,QAAM,SAA0B;AAAA,IAC9B,cAAc,YAAY,IAAI,OAAO;AAAA,IACrC,cAAc,YAAY,IAAI,OAAO;AAAA,IACrC,QAAQ;AAAA,IACR,WAAW;AAAA,IACX;AAAA,EACF;AAgBA,QAAM,mBAAmB,QAAQ,SAAS,QAAQ,MAAM,SAAS;AACjE,QAAM,WAAW,mBACb,QAAQ,QACR,qBACA,CAAC,YAAAA,QAAK,SAAS,kBAAkB,CAAC,IAClC;AAEJ,QAAM,YAAY,KAAK,IAAI;AAC3B,MAAI;AAgBJ,QAAM,SAAS,OAAO;AAItB,MAAI;AACF,iBAAa,MAAM,OAAO,UAAU,QAAQ;AAAA,EAC9C,SAAS,KAAc;AACrB,UAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAEhE,QAAI,wBAAwB,KAAK,GAAG;AAElC,UAAI,MAAM,2DAA2D;AACrE,YAAM,oBAAoB,MAAM,QAAQ;AAAA,QACtC,SAAS,IAAI,OAAO,YAAY;AAC9B,cAAI;AACF,mBAAO,MAAM,OAAO,UAAU,CAAC,OAAO,CAAC;AAAA,UACzC,SAAS,YAAqB;AAC5B,kBAAM,eAAe,sBAAsB,QAAQ,aAAa,IAAI,MAAM,OAAO,UAAU,CAAC;AAC5F,gBAAI,wBAAwB,YAAY,GAAG;AACzC,kBAAI,MAAM,qBAAqB,OAAO,uBAAuB;AAC7D,qBAAO,CAAC;AAAA,YACV;AACA,kBAAM;AAAA,UACR;AAAA,QACF,CAAC;AAAA,MACH;AACA,mBAAa,kBACV,OAAO,CAAC,MAAsD,EAAE,WAAW,WAAW,EACtF,QAAQ,CAAC,MAAM,EAAE,KAAK;AAAA,IAC3B,OAAO;AAEL,YAAM,WAAW,GAAG,SAAS,KAAK,QAAQ,MAAM;AAChD,mBAAa,OAAO,QAAQ;AAC5B,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO,SAAS,KAAK,IAAI,IAAI;AAG7B,QAAM,eAAe,KAAK,IAAI;AAE9B,QAAM,QAAsB,CAAC;AAC7B,QAAM,kBAAoC,CAAC;AAC3C,QAAM,eAA8B,CAAC;AACrC,QAAM,gBAAgB,oBAAI,IAAoB;AAC9C,MAAI,cAAc;AAClB,MAAI,gBAAgB;AACpB,QAAM,eAAe,WAAW;AAEhC,aAAW,UAAU,YAAY;AAC/B,QAAI,OAAO,SAAS,WAAW,EAAG;AAElC,UAAM,UAAU,YAAAA,QAAK,SAAS,KAAK,OAAO,QAAQ;AAClD,UAAM,gBAA+B,CAAC;AACtC,QAAI,aAAa;AACjB,QAAI,eAAe;AAEnB,eAAW,KAAK,OAAO,UAAU;AAC/B,YAAM,SAAS,gBAAgB,CAAC;AAEhC,UAAI,WAAW,gBAAgB;AAC7B,qBAAa,KAAK;AAAA,UAChB,UAAU;AAAA,UACV,SAAS,EAAE;AAAA,UACX,MAAM,EAAE,QAAQ;AAAA,QAClB,CAAC;AACD;AAAA,MACF;AAEA,UAAI,WAAW,aAAa;AAC1B,wBAAgB,KAAK;AAAA,UACnB,MAAM,sBAAsB,CAAC;AAAA,UAC7B,QAAQ,EAAE;AAAA,UACV,SAAS,EAAE;AAAA,UACX,UAAU;AAAA,UACV,MAAM,EAAE,QAAQ;AAAA,UAChB,QAAQ,EAAE,UAAU;AAAA,QACtB,CAAC;AACD;AAAA,MACF;AAGA,YAAM,SAAS,EAAE,UAAU;AAC3B,YAAM,QAAqB;AAAA,QACzB;AAAA,QACA,UAAU,EAAE;AAAA,QACZ,SAAS,EAAE;AAAA,QACX,MAAM,EAAE;AAAA,QACR,QAAQ,EAAE;AAAA,QACV,SAAS,EAAE;AAAA,QACX,WAAW,EAAE;AAAA,QACb,YAAY,iBAAiB,MAAM;AAAA,QACnC,UAAU,eAAe,MAAM;AAAA,QAC/B,eAAe,sBAAsB,MAAM;AAAA,QAC3C,aAAa,kBAAkB,MAAM;AAAA,MACvC;AAEA,oBAAc,KAAK,KAAK;AAExB,UAAI,EAAE,aAAa,GAAG;AACpB;AACA;AAAA,MACF,OAAO;AACL;AACA;AAAA,MACF;AAEA,oBAAc;AAAA,QACZ,MAAM;AAAA,SACL,cAAc,IAAI,MAAM,MAAM,KAAK,KAAK;AAAA,MAC3C;AAAA,IACF;AAEA,QAAI,cAAc,SAAS,GAAG;AAC5B,YAAM,KAAK;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,GAAG,KAAK,EACvB,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,SAAS,EAAE,OAAO,MAAM,EAChD,MAAM,GAAG,EAAE,EACX,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,OAAO,EAAE,OAAO,OAAO,EAAE;AAE5D,SAAO,YAAY,KAAK,IAAI,IAAI;AAEhC,MAAI,QAAQ,aAAa;AACvB,UAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,UAAM,aAAa,YAAY,cAAAG,QAAM,MAAM,YAAY,IAAI,cAAAA,QAAM,OAAO,YAAY;AACpF,QAAI,MAAM,YAAY,MAAM,OAAO,UAAU,GAAG;AAChD,QAAI,MAAM,YAAY,OAAO,MAAM,IAAI;AACvC,QAAI,MAAM,YAAY,OAAO,SAAS,IAAI;AAC1C,QAAI,MAAM,YAAY,OAAO,eAAe,YAAY,MAAM,eAAe,IAAI,KAAK,MAAM,UAAU,YAAY,IAAI,CAAC,SAAS;AAAA,EAClI;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,cAAc;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,KAAK,IAAI,IAAI;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB,OAAO;AAAA,EAC5B;AACF;;;AE3wBA,oBAA8B;AAC9B,IAAAC,cAA8B;AAC9B,IAAAC,eAAiB;AAVjB;AAYA,IAAI;AAEJ,SAAS,cAAsB;AAC7B,MAAI;AAEF,UAAM,eAAW,6BAAc,YAAY,GAAG;AAE9C,UAAM,UAAU,aAAAC,QAAK;AAAA,MACnB,aAAAA,QAAK,YAAQ,2BAAc,YAAY,GAAG,CAAC;AAAA,MAC3C;AAAA,IACF;AACA,UAAM,MAAM,SAAS,OAAO;AAC5B,QAAI,IAAI,QAAS,QAAO,IAAI;AAAA,EAC9B,QAAQ;AAAA,EAER;AAGA,MAAI,OAAO,oBAAoB,aAAa;AAC1C,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAMO,IAAM,cAAsB,aAAa,WAAW,YAAY;;;ACoDvE,IAAM,YAAmE;AAAA,EACvE,2BAAoC,EAAE,WAAW,8CAA8C,MAAM,CAAC,aAAa,EAAE;AAAA,EACrH,+BAAoC,EAAE,WAAW,0DAA0D,MAAM,CAAC,aAAa,EAAE;AAAA,EACjI,iCAAoC,EAAE,WAAW,6DAAwD,MAAM,CAAC,aAAa,EAAE;AAAA,EAC/H,iCAAoC,EAAE,WAAW,qCAAqC,MAAM,CAAC,aAAa,EAAE;AAAA,EAC5G,gCAAoC,EAAE,WAAW,yFAAoF,MAAM,CAAC,SAAS,mBAAmB,EAAE;AAAA,EAC1K,6BAAoC,EAAE,WAAW,+EAA0E,MAAM,CAAC,SAAS,qBAAqB,aAAa,EAAE;AAAA,EAC/K,mCAAoC,EAAE,WAAW,gDAAgD,MAAM,CAAC,SAAS,mBAAmB,EAAE;AAAA,EACtI,oCAAoC,EAAE,WAAW,6DAA6D,MAAM,CAAC,SAAS,mBAAmB,EAAE;AAAA,EACnJ,+BAAoC,EAAE,WAAW,6CAA6C,MAAM,CAAC,OAAO,EAAE;AAAA,EAC9G,gCAAoC,EAAE,WAAW,2CAA2C,MAAM,CAAC,YAAY,SAAS,EAAE;AAAA,EAC1H,4BAAoC,EAAE,WAAW,qDAAqD,MAAM,CAAC,UAAU,EAAE;AAAA,EACzH,iCAAoC,EAAE,WAAW,sEAAiE,MAAM,CAAC,YAAY,WAAW,EAAE;AAAA,EAClJ,kCAAoC,EAAE,WAAW,4CAA4C,MAAM,CAAC,UAAU,EAAE;AAAA,EAChH,oCAAoC,EAAE,WAAW,2DAA2D,MAAM,CAAC,YAAY,MAAM,EAAE;AAAA,EACvI,gCAAoC,EAAE,WAAW,qCAAqC,MAAM,CAAC,YAAY,MAAM,EAAE;AAAA,EACjH,kCAAoC,EAAE,WAAW,gEAA2D,MAAM,CAAC,aAAa,EAAE;AAAA,EAClI,qCAAoC,EAAE,WAAW,kCAAkC,MAAM,CAAC,aAAa,EAAE;AAAA,EACzG,2BAAoC,EAAE,WAAW,2CAA2C,MAAM,CAAC,aAAa,EAAE;AACpH;AAEA,IAAM,gBAAgB;AAItB,SAAS,uBAAuB,YAAuE;AACrG,UAAQ,YAAY;AAAA,IAClB,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B;AAAsB,aAAO;AAAA,EAC/B;AACF;AAEA,SAAS,iBAAiB,YAAwC;AAChE,UAAQ,YAAY;AAAA,IAClB,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B;AAAsB,aAAO;AAAA,EAC/B;AACF;AAEA,SAAS,2BAA2B,YAAwC;AAC1E,UAAQ,YAAY;AAAA,IAClB,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B;AAAsB,aAAO;AAAA,EAC/B;AACF;AAMA,SAAS,cAAc,UAA0B;AAG/C,SAAO,SAAS,QAAQ,OAAO,GAAG;AACpC;AAEA,SAAS,mBAAmB,QAA6B;AACvD,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,QAAQ,OAAO,OAAO;AAC/B,eAAW,SAAS,KAAK,QAAQ;AAC/B,UAAI,IAAI,MAAM,MAAM;AAAA,IACtB;AAAA,EACF;AACA,SAAO,CAAC,GAAG,GAAG,EAAE,KAAK;AACvB;AAEA,SAAS,qBAAqB,SAA+C;AAC3E,SAAO,QAAQ,IAAI,CAAC,OAAO;AACzB,UAAM,OAAO,UAAU,EAAE;AACzB,UAAM,YAAY,GAAG,QAAQ,aAAa,EAAE;AAC5C,UAAM,aAAa,iBAAiB,EAAE;AACtC,UAAM,WAAW,eAAe,EAAE,KAAK;AACvC,UAAM,cAAc,kBAAkB,EAAE;AAExC,UAAM,eAAe;AAAA,MACnB,KAAK,MAAM,aAAa,SAAS;AAAA,MACjC;AAAA,MACA,cAAc,YAAY,WAAW,KAAK;AAAA,MAC1C;AAAA,MACA,6BAA6B,aAAa,IAAI,SAAS;AAAA,IACzD,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAE3B,WAAO;AAAA,MACL;AAAA,MACA,kBAAkB;AAAA,QAChB,MAAM,MAAM,aAAa,kBAAkB,SAAS;AAAA,MACtD;AAAA,MACA,iBAAiB;AAAA,QACf,MAAM,MAAM,aAAa,kBAAkB,SAAS;AAAA,MACtD;AAAA,MACA,MAAM;AAAA,QACJ,MAAM,eAAe,MAAM,aAAa;AAAA,QACxC,UAAU;AAAA,MACZ;AAAA,MACA,SAAS,GAAG,aAAa,IAAI,SAAS;AAAA,MACtC,sBAAsB;AAAA,QACpB,OAAO,uBAAuB,UAAU;AAAA,MAC1C;AAAA,MACA,YAAY;AAAA,QACV,MAAM,CAAC,GAAI,MAAM,QAAQ,CAAC,UAAU,GAAI,SAAS,YAAY,EAAE,QAAQ,MAAM,GAAG,CAAC;AAAA,QACjF,YAAY,cAAc;AAAA,QAC1B;AAAA,QACA,oBAAoB,2BAA2B,UAAU;AAAA,MAC3D;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,SAAS,iBAAiB,OAAoB,MAA+B;AAC3E,QAAM,aAAa,iBAAiB,MAAM,MAAM;AAChD,QAAM,gBAAgB,sBAAsB,MAAM,MAAM;AACxD,QAAM,WAAW,eAAe,MAAM,MAAM;AAE5C,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,IACd,OAAO,uBAAuB,UAAU;AAAA,IACxC,MAAM,eAAe,kBAAkB,kBAAkB;AAAA,IACzD,MAAM,iBAAiB,UAAU;AAAA,IACjC,SAAS,EAAE,MAAM,MAAM,QAAQ;AAAA,IAC/B,WAAW;AAAA,MACT;AAAA,QACE,kBAAkB;AAAA,UAChB,kBAAkB;AAAA,YAChB,KAAK,cAAc,KAAK,QAAQ;AAAA,YAChC,WAAW;AAAA,UACb;AAAA,UACA,QAAQ;AAAA,YACN,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI;AAAA,YACjC,aAAa,MAAM,SAAS,IAAI,MAAM,SAAS;AAAA,YAC/C,GAAI,MAAM,YAAY,UAAa,EAAE,SAAS,MAAM,QAAQ;AAAA,YAC5D,GAAI,MAAM,cAAc,UAAa,EAAE,WAAW,MAAM,UAAU;AAAA,UACpE;AAAA,QACF;AAAA,QACA,SAAS,EAAE,MAAM,MAAM,QAAQ;AAAA,MACjC;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV,YAAY,cAAc;AAAA,MAC1B,GAAI,iBAAiB,EAAE,cAAc;AAAA,MACrC,GAAI,YAAY,EAAE,SAAS;AAAA,IAC7B;AAAA,EACF;AACF;AAWO,SAAS,cAAc,QAAmB,UAAU,aAAuB;AAChF,QAAM,cAAc,mBAAmB,MAAM;AAC7C,QAAM,QAAQ,qBAAqB,WAAW;AAE9C,QAAM,eAA8B,CAAC;AACrC,aAAW,QAAQ,OAAO,OAAO;AAC/B,eAAW,SAAS,KAAK,QAAQ;AAC/B,mBAAa,KAAK,iBAAiB,OAAO,IAAI,CAAC;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,MACJ;AAAA,QACE,MAAM;AAAA,UACJ,QAAQ;AAAA,YACN,MAAM;AAAA,YACN;AAAA,YACA,gBAAgB;AAAA,YAChB;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,QACT,YAAY;AAAA,UACV,QAAQ;AAAA,UACR,cAAc,OAAO;AAAA,UACrB,YAAY,OAAO;AAAA,UACnB,sBAAsB,OAAO,gBAAgB;AAAA,UAC7C,mBAAmB,OAAO,aAAa;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAMO,SAAS,YAAYC,MAAuB;AACjD,SAAO,KAAK,UAAUA,MAAK,MAAM,CAAC;AACpC;;;ACjSA,IAAAC,aAAe;AAuCf,SAAS,aAAa,MAAc,UAAkB,KAAoB;AACxE,QAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAQ,OAAO;AAAA,IACb,0CAA0C,IAAI,IAAI,QAAQ,KAAK,GAAG;AAAA;AAAA,EACpE;AACF;AAcA,SAAS,eAAe,MAAsB;AAC5C,SAAO,KAAK,QAAQ,gBAAgB,MAAM;AAC5C;AAEA,SAAS,UAAU,MAA0C;AAC3D,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B;AAAsB,aAAO;AAAA,EAC/B;AACF;AAEA,SAAS,UAAU,MAA0C;AAC3D,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B,KAAK;AAAiB,aAAO;AAAA,IAC7B;AAAsB,aAAO;AAAA,EAC/B;AACF;AAUO,SAAS,sBAAsB,QAAyB;AAC7D,MAAI,QAAQ,IAAI,mBAAmB,OAAQ;AAE3C,aAAW,QAAQ,OAAO,OAAO;AAC/B,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,OAAO,gBAAgB,MAAM,MAAM;AAIzC,UAAI,SAAS,gBAAiB;AAE9B,YAAM,QAAQ,MAAM,aAAa,IAAI,UAAU;AAC/C,YAAM,WAAW,KAAK,SAAS,QAAQ,OAAO,GAAG;AACjD,YAAM,YAAY,MAAM,OAAO,QAAQ,aAAa,EAAE;AAEtD,YAAM,QAAQ,CAAC,QAAQ,QAAQ,IAAI,QAAQ,MAAM,IAAI,EAAE;AACvD,UAAI,MAAM,QAAS,OAAM,KAAK,WAAW,MAAM,OAAO,EAAE;AACxD,UAAI,MAAM,SAAS,EAAG,OAAM,KAAK,OAAO,MAAM,MAAM,EAAE;AACtD,UAAI,MAAM,UAAW,OAAM,KAAK,aAAa,MAAM,SAAS,EAAE;AAC9D,YAAM,KAAK,kBAAkB,SAAS,EAAE;AAGxC,YAAM,MAAM,MAAM,QAAQ,QAAQ,OAAO,GAAG;AAC5C,cAAQ,OAAO,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,GAAG,CAAC,KAAK,GAAG;AAAA,CAAI;AAAA,IAChE;AAAA,EACF;AACF;AAOO,SAAS,2BACd,QACA,SACQ;AACR,QAAM,QAAkB,CAAC;AAGzB,QAAM,KAAK,6CAAwC;AACnD,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,mBAAmB,QAAQ,MAAM,8BAA8B,QAAQ,aAAa,YAAY,uBAAuB,QAAQ,aAAa,WAAW,iBAAiB,WAAW,EAAE;AAChM,MAAI,QAAQ,sBAAsB,QAAW;AAC3C,UAAM,KAAK,wBAAwB,OAAO,YAAY,KAAK,QAAQ,iBAAiB,WAAW;AAAA,EACjG,OAAO;AACL,UAAM,KAAK,wBAAwB,OAAO,YAAY,EAAE;AAAA,EAC1D;AACA,QAAM,KAAK,mBAAmB,OAAO,UAAU,IAAI;AACnD,QAAM,KAAK,EAAE;AAGb,MAAI,OAAO,gBAAgB,GAAG;AAC5B,UAAM,KAAK,4BAAuB;AAClC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,uDAAuD;AAClE,UAAM,KAAK,EAAE;AACb,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAGA,QAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,gBAAgB,EAAE,IAAI,kBAAkB,MAAM;AAErF,MAAI,OAAO,GAAG;AACZ,UAAM,KAAK,oBAAU,IAAI,yBAAyB,SAAS,IAAI,MAAM,EAAE,QAAQ;AAAA,EACjF,WAAW,SAAS,GAAG;AACrB,UAAM,KAAK,iBAAU,MAAM,2BAA2B,WAAW,IAAI,MAAM,EAAE,QAAQ;AAAA,EACvF,OAAO;AACL,UAAM,KAAK,2CAAiC;AAAA,EAC9C;AACA,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,gFAAsD;AACjE,QAAM,KAAK,oDAAoD;AAE/D,QAAM,oBAAoB,uBAAuB,MAAM;AACvD,aAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,iBAAiB,GAAG;AAC7D,QAAK,OAAO,OAAO,OAAO,SAAS,OAAO,MAAM,OAAO,kBAAmB,EAAG;AAC7E,UAAM,KAAK,KAAK,GAAG,MAAM,OAAO,IAAI,MAAM,OAAO,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,aAAa,IAAI;AAAA,EACvG;AACA,QAAM,KAAK,EAAE;AAGb,QAAM,YAAY,OAAO,MAAM;AAAA,IAAQ,CAAC,MACtC,EAAE,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,UAAU,EAAE,SAAS,EAAE;AAAA,EACtD;AACA,QAAM,mBAAmB,UACtB,OAAO,CAAC,MAAM;AACb,UAAM,OAAO,gBAAgB,EAAE,MAAM;AACrC,WAAO,SAAS;AAAA,EAClB,CAAC,EACA,KAAK,CAAC,GAAG,MAAM;AACd,UAAM,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,eAAe,EAAE;AACjE,UAAM,KAAK,gBAAgB,EAAE,MAAM;AACnC,UAAM,KAAK,gBAAgB,EAAE,MAAM;AACnC,YAAQ,UAAU,MAAM,KAAK,KAAK,MAAM,UAAU,MAAM,KAAK,KAAK;AAAA,EACpE,CAAC,EACA,MAAM,GAAG,EAAE;AAEd,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,KAAK,kBAAkB;AAC7B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,qCAAqC;AAChD,UAAM,KAAK,qCAAqC;AAEhD,eAAW,SAAS,kBAAkB;AACpC,YAAM,OAAO,gBAAgB,MAAM,MAAM;AACzC,YAAM,YAAY,MAAM,SAAS,QAAQ,OAAO,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG;AAClF,YAAM,YAAY,MAAM,OAAO,QAAQ,aAAa,EAAE;AACtD,YAAM;AAAA,QACJ,OAAO,eAAe,SAAS,CAAC,QAAQ,MAAM,IAAI,QAAQ,SAAS,QAAQ,UAAU,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC;AAAA,MAC/G;AAAA,IACF;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,MAAI,gBAAgB,GAAG;AACrB,UAAM,KAAK,WAAW;AACtB,UAAM,KAAK,sBAAe,aAAa,sBAAsB,kBAAkB,IAAI,MAAM,EAAE,8BAA8B;AACzH,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,iIAAiI;AAC5I,UAAM,KAAK,EAAE;AAEb,UAAM,aAAa,UAChB,OAAO,CAAC,MAAM;AACb,YAAM,OAAO,gBAAgB,EAAE,MAAM;AACrC,aAAO,SAAS;AAAA,IAClB,CAAC,EACA,MAAM,GAAG,EAAE;AAEd,UAAM,KAAK,wBAAwB;AACnC,UAAM,KAAK,wBAAwB;AACnC,eAAW,SAAS,YAAY;AAC9B,YAAM,YAAY,MAAM,SAAS,QAAQ,OAAO,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG;AAClF,YAAM,YAAY,MAAM,OAAO,QAAQ,aAAa,EAAE;AACtD,YAAM,KAAK,OAAO,eAAe,SAAS,CAAC,QAAQ,MAAM,IAAI,QAAQ,SAAS,MAAM;AAAA,IACtF;AAEA,UAAM,KAAK,YAAY;AACvB,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,MAAI,OAAO,gBAAgB,SAAS,GAAG;AACrC,UAAM,KAAK,WAAW;AACtB,UAAM,KAAK,sBAAe,OAAO,gBAAgB,MAAM,uBAAuB,OAAO,gBAAgB,WAAW,IAAI,MAAM,EAAE,oCAAoC;AAChK,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,iHAAkH;AAC7H,UAAM,KAAK,YAAY;AACvB,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,iBAAiB;AAC5B,MAAI,OAAO,KAAK,SAAS,GAAG;AAC1B,UAAM,KAAK,uEAAuE;AAClF,UAAM,KAAK,4DAA4D;AAAA,EACzE;AACA,MAAI,gBAAgB,GAAG;AACrB,UAAM,KAAK,8DAA8D;AAAA,EAC3E;AACA,QAAM,KAAK,4EAA4E;AACvF,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,+FAA+F;AAE1G,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,kBAAkB,QAEzB;AACA,MAAI,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,gBAAgB;AACnD,aAAW,QAAQ,OAAO,OAAO;AAC/B,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,OAAO,gBAAgB,MAAM,MAAM;AACzC,UAAI,SAAS,OAAQ;AAAA,eACZ,SAAS,SAAU;AAAA,eACnB,SAAS,gBAAiB;AAAA,UAC9B;AAAA,IACP;AAAA,EACF;AACA,SAAO,EAAE,MAAM,QAAQ,KAAK,cAAc;AAC5C;AAEA,SAAS,uBAAuB,QAE7B;AACD,QAAM,YAAkG,CAAC;AAEzG,aAAW,QAAQ,OAAO,OAAO;AAC/B,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,MAAM,cAAc,MAAM,MAAM,KAAK;AAC3C,YAAM,OAAO,gBAAgB,MAAM,MAAM;AACzC,UAAI,CAAC,UAAU,GAAG,EAAG,WAAU,GAAG,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,eAAe,EAAE;AACrF,UAAI,SAAS,OAAQ,WAAU,GAAG,EAAE;AAAA,eAC3B,SAAS,SAAU,WAAU,GAAG,EAAE;AAAA,eAClC,SAAS,gBAAiB,WAAU,GAAG,EAAE;AAAA,UAC7C,WAAU,GAAG,EAAE;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AACT;AAUO,SAAS,mBACd,QACA,SACM;AACN,QAAM,cAAc,QAAQ,IAAI;AAChC,MAAI,CAAC,YAAa;AAElB,MAAI;AACF,UAAM,WAAW,2BAA2B,QAAQ,OAAO;AAC3D,eAAAC,QAAG,eAAe,aAAa,WAAW,MAAM,EAAE,UAAU,QAAQ,CAAC;AAAA,EACvE,SAAS,KAAK;AAEZ,iBAAa,uBAAuB,aAAa,GAAG;AAAA,EACtD;AACF;AAWO,SAAS,mBAAmB,QAAmB,WAA0B;AAC9E,QAAM,aAAa,QAAQ,IAAI;AAC/B,MAAI,CAAC,WAAY;AAEjB,QAAM,EAAE,MAAM,QAAQ,KAAK,cAAc,IAAI,kBAAkB,MAAM;AAErE,QAAM,UAAU;AAAA,IACd,gBAAgB,OAAO,WAAW;AAAA,IAClC,yBAAyB,IAAI;AAAA,IAC7B,2BAA2B,MAAM;AAAA,IACjC,wBAAwB,GAAG;AAAA,IAC3B,uBAAuB,aAAa;AAAA,IACpC,iBAAiB,OAAO,YAAY;AAAA,IACpC,eAAe,OAAO,UAAU;AAAA,IAChC,GAAI,YAAY,CAAC,cAAc,SAAS,EAAE,IAAI,CAAC;AAAA,EACjD;AAEA,MAAI;AACF,eAAAA,QAAG,eAAe,YAAY,QAAQ,KAAK,IAAI,IAAI,MAAM,EAAE,UAAU,QAAQ,CAAC;AAAA,EAChF,SAAS,KAAK;AACZ,iBAAa,iBAAiB,YAAY,GAAG;AAAA,EAC/C;AACF;;;AClVA,2BAAyB;AACzB,IAAAC,eAAiB;AACjB,IAAAC,aAAe;AA2Df,IAAM,qBAAqB,CAAC,OAAO,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAExF,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIA,SAAS,OAAO,MAAc,KAA4B;AACxD,MAAI;AACF,eAAO,+BAAS,OAAO,IAAI,IAAI;AAAA,MAC7B;AAAA,MACA,UAAU;AAAA,MACV,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,MAC9B,SAAS;AAAA,IACX,CAAC,EAAE,KAAK;AAAA,EACV,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,eAAe,KAAsB;AAC5C,SAAO,OAAO,mCAAmC,GAAG,MAAM;AAC5D;AAEA,SAAS,eAAe,KAAsB;AAC5C,SAAO,OAAO,qCAAqC,GAAG,MAAM;AAC9D;AAEA,SAAS,eAAe,KAAsB;AAC5C,QAAM,SAAS,OAAO,6BAA6B,GAAG;AACtD,SAAO,WAAW;AACpB;AAgCA,SAAS,oBAAoB,KAAqB;AAChD,SAAO,IAAI,QAAQ,aAAa,EAAE,EAAE,KAAK;AAC3C;AAqBA,SAAS,UACP,QACA,KACA,WACmB;AACnB,QAAM,YAAY,oBAAoB,MAAM;AAG5C;AACE,UAAM,WAAW,0BAA0B,SAAS;AACpD,cAAU,oBAAoB,KAAK,QAAQ;AAC3C,UAAM,YAAY,OAAO,0BAA0B,SAAS,IAAI,GAAG;AACnE,QAAI,WAAW;AACb,gBAAU,YAAY;AACtB,YAAM,MAAM,OAAO,wCAAwC,SAAS,IAAI,GAAG;AAC3E,UAAI,QAAQ,MAAM;AAChB,kBAAU,oBAAoB;AAC9B,eAAO,EAAE,QAAQ,KAAK,UAAU,UAAU;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAM,WAAW,mBAAmB,SAAS;AAC7C,cAAU,oBAAoB,KAAK,QAAQ;AAC3C,UAAM,YAAY,OAAO,mBAAmB,SAAS,IAAI,GAAG;AAC5D,QAAI,WAAW;AACb,UAAI,CAAC,UAAU,UAAW,WAAU,YAAY;AAChD,YAAM,MAAM,OAAO,wCAAwC,SAAS,IAAI,GAAG;AAC3E,UAAI,QAAQ,MAAM;AAChB,kBAAU,oBAAoB;AAC9B,eAAO,EAAE,QAAQ,KAAK,UAAU,UAAU;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAM,WAAW,eAAe,SAAS;AACzC,cAAU,oBAAoB,KAAK,QAAQ;AAC3C,UAAM,MAAM,OAAO,+CAA+C,SAAS,WAAW,GAAG;AACzF,QAAI,QAAQ,MAAM;AAChB,gBAAU,oBAAoB;AAC9B,aAAO,EAAE,QAAQ,KAAK,SAAS;AAAA,IACjC;AAAA,EACF;AAGA;AACE,UAAM,WAAW,QAAQ,SAAS;AAClC,cAAU,oBAAoB,KAAK,QAAQ;AAC3C,UAAM,MAAM,OAAO,wCAAwC,SAAS,WAAW,GAAG;AAClF,QAAI,QAAQ,MAAM;AAChB,gBAAU,oBAAoB;AAC9B,aAAO,EAAE,QAAQ,KAAK,SAAS;AAAA,IACjC;AAAA,EACF;AAGA;AACE,UAAM,WAAW;AACjB,cAAU,oBAAoB,KAAK,QAAQ;AAC3C,UAAM,MAAM,OAAO,+CAA+C,GAAG;AACrE,QAAI,QAAQ,MAAM;AAChB,gBAAU,oBAAoB;AAC9B,aAAO,EAAE,QAAQ,KAAK,SAAS;AAAA,IACjC;AAAA,EACF;AAEA,YAAU,oBAAoB;AAC9B,SAAO;AACT;AAIA,SAAS,YACP,UACA,YACA,kBACA,KACA,WACU;AACV,QAAM,OAAiB,CAAC;AAExB,aAAW,OAAO,UAAU;AAE1B,UAAM,aAAa,IAAI,QAAQ,OAAO,GAAG,EAAE,KAAK;AAChD,QAAI,CAAC,WAAY;AAGjB,UAAM,MAAM,aAAAC,QAAK,QAAQ,UAAU,EAAE,YAAY;AACjD,QAAI,CAAC,WAAW,SAAS,GAAG,GAAG;AAC7B,gBAAU;AACV;AAAA,IACF;AAGA,QAAI,gBAAgB,KAAK,CAAC,WAAW,WAAW,WAAW,MAAM,CAAC,GAAG;AACnE,gBAAU;AACV;AAAA,IACF;AAGA,QAAI,kBAAkB;AACpB,YAAM,SAAS,iBAAiB,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AACrE,UAAI,CAAC,WAAW,WAAW,SAAS,GAAG,KAAK,eAAe,QAAQ;AACjE,kBAAU;AACV;AAAA,MACF;AAAA,IACF;AAGA,UAAM,MAAM,aAAAA,QAAK,QAAQ,KAAK,UAAU;AACxC,QAAI,CAAC,WAAAC,QAAG,WAAW,GAAG,GAAG;AACvB,gBAAU;AACV;AAAA,IACF;AAEA,SAAK,KAAK,GAAG;AAAA,EACf;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,QAA0B;AAC/C,SAAO,OACJ,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AACnB;AAeO,SAAS,gBACd,UAA+B,CAAC,GACZ;AACpB,QAAM;AAAA,IACJ,SAAS;AAAA,IACT;AAAA,IACA,MAAM,QAAQ,IAAI;AAAA,IAClB,aAAa;AAAA,IACb;AAAA,IACA,QAAQ;AAAA,EACV,IAAI;AAEJ,QAAM,YAA8B;AAAA,IAClC,qBAAqB,CAAC;AAAA,IACtB,mBAAmB;AAAA,IACnB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,qBAAqB;AAAA,EACvB;AAEA,MAAI,CAAC,eAAe,GAAG,GAAG;AACxB,WAAO;AAAA,MACL,OAAO,CAAC;AAAA,MACR,MAAM;AAAA,MACN,eAAe;AAAA,MACf,aAAa;AAAA,MACb;AAAA,MACA,iBAAiB;AAAA,IACnB;AAAA,EACF;AAGA,YAAU,iBAAiB,eAAe,GAAG;AAC7C,YAAU,iBAAiB,eAAe,GAAG;AAK7C,QAAM,UAAU,QAAQ,IAAI,kBACxB,oBAAoB,QAAQ,IAAI,eAAe,IAC/C;AAGJ,QAAM,iBAAqC,OACvC,oBAAoB,IAAI,IACxB;AAEJ,YAAU,eAAe;AAEzB,MAAI,YAA2B;AAC/B,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,QAAQ;AAEV,gBAAY,OAAO,iDAAiD,GAAG;AACvE,WAAO;AACP,cAAU,oBAAoB,KAAK,mBAAmB;AACtD,QAAI,cAAc,KAAM,WAAU,oBAAoB;AACtD,QAAI,CAAC,WAAW;AACd,wBAAkB;AAAA,IACpB;AAAA,EACF,WAAW,gBAAgB;AAEzB,WAAO;AACP,eAAW;AAEX,UAAM,aAAa,UAAU,gBAAgB,KAAK,SAAS;AAE3D,QAAI,YAAY;AACd,kBAAY,WAAW;AAAA,IACzB,OAAO;AAEL,YAAM,UAAU,UAAU,iBACtB,wEACA;AACJ,YAAM,WAAW,UAAU,iBACvB,iEACA;AACJ,wBACE,2BAA2B,cAAc,aAC/B,UAAU,oBAAoB,KAAK,IAAI,CAAC,IAAI,OAAO,GAAG,QAAQ;AAAA,IAE5E;AAAA,EACF,OAAO;AAEL,WAAO;AACP,UAAM,UAAU,OAAO,iDAAiD,GAAG,KAAK;AAChF,UAAM,WAAW,OAAO,wCAAwC,GAAG,KAAK;AACxE,cAAU,oBAAoB,KAAK,qBAAqB,qBAAqB;AAC7E,UAAM,WAAW,oBAAI,IAAI,CAAC,GAAG,cAAc,OAAO,GAAG,GAAG,cAAc,QAAQ,CAAC,CAAC;AAChF,gBAAY,CAAC,GAAG,QAAQ,EAAE,KAAK,IAAI;AACnC,QAAI,UAAW,WAAU,oBAAoB;AAC7C,QAAI,CAAC,WAAW;AACd,wBACE;AAAA,IAEJ;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL,OAAO,CAAC;AAAA,MACR;AAAA,MACA,MAAM;AAAA,MACN,eAAe;AAAA,MACf,aAAa;AAAA,MACb;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,cAAc,SAAS;AACxC,YAAU,eAAe,SAAS;AAElC,QAAM,OAAO,YAAY,UAAU,YAAY,kBAAkB,KAAK,SAAS;AAC/E,QAAM,UACJ,UAAU,qBACV,UAAU,kBACV,UAAU,sBACV,UAAU;AAEZ,MAAI,KAAK,WAAW,KAAK,SAAS,SAAS,GAAG;AAC5C,sBACE,GAAG,SAAS,MAAM,gBAAgB,SAAS,WAAW,IAAI,MAAM,EAAE,qDAC7C,UAAU,kBAAkB,oBAC/B,UAAU,eAAe,wBACrB,UAAU,cAAc;AAAA,EAClD;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP;AAAA,IACA,MAAM;AAAA,IACN,eAAe,SAAS;AAAA,IACxB,aAAa;AAAA,IACb;AAAA,IACA,iBAAiB,KAAK,WAAW,IAAI,kBAAkB;AAAA,EACzD;AACF;AAKO,SAAS,kBAA2B;AACzC,SAAO,QAAQ,IAAI,mBAAmB;AACxC;AAGO,SAAS,mBAAuC;AACrD,SAAO,QAAQ,IAAI,mBAAmB;AACxC;;;AN/dO,SAAS,mBAAmBC,UAAwB;AACzD,EAAAA,SACG,QAAQ,KAAK,EACb,YAAY,kEAAkE,EAC9E,OAAO,gBAAgB,6BAA6B,GAAG,EACvD,OAAO,YAAY,iDAAiD,EACpE,OAAO,cAAc,mCAAmC,EACxD,OAAO,UAAU,sCAAsC,EACvD,OAAO,WAAW,0DAA0D,EAC5E,OAAO,qBAAqB,6DAA6D,QAAQ,EACjG;AAAA,IACC;AAAA,IACA;AAAA,IACA,CAAC,UAAkB,OAAO,SAAS,OAAO,EAAE;AAAA,EAC9C,EACC,OAAO,aAAa,8DAAyD,EAC7E,OAAO,WAAW,mEAA8D,EAChF,OAAO,kBAAkB,oCAAoC,EAC7D,OAAO,OAAO,SAWT;AACJ,QACE,KAAK,gBAAgB,WACpB,CAAC,OAAO,UAAU,KAAK,WAAW,KAAK,KAAK,cAAc,IAC3D;AACA,UAAI,MAAM;AACV,UAAI,MAAM,gDAAgD;AAC1D,UAAI,MAAM;AACV,cAAQ,KAAK,CAAC;AACd;AAAA,IACF;AAEA,UAAM,SAAiB,KAAK,SACxB,WACA,KAAK,WACL,aACA;AAEJ,QAAI,KAAK,UAAU,KAAK,YAAY,CAAC,KAAK,MAAM;AAC9C,UAAI,KAAK,6DAA6D;AACtE,UAAI,MAAM;AAAA,IACZ;AAEA,QAAI,CAAC,KAAK,MAAM;AACd,UAAI,OAAO,UAAU;AACrB,UAAI,MAAM;AAAA,IACZ;AAEA,UAAM,UAAU,KAAK,OACjB,WACA,WAAAC,SAAI,EAAE,MAAM,kBAAa,OAAO,OAAO,CAAC,EAAE,MAAM;AAEpD,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,UAAU;AAAA,QACvB;AAAA,QACA,YAAY,KAAK;AAAA,QACjB,aAAa,KAAK;AAAA,MACpB,CAAC;AACD,eAAS,KAAK;AAAA,IAChB,SAAS,KAAc;AACrB,eAAS,KAAK;AACd,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAE3D,UAAI,IAAI,YAAY,EAAE,SAAS,YAAY,KAAK,IAAI,YAAY,EAAE,SAAS,QAAQ,GAAG;AACpF,YAAI,MAAM;AACV,YAAI,MAAM,2CAA2C;AACrD,YAAI,MAAM;AACV,YAAI,MAAM,KAAK,cAAAC,QAAM,KAAK,gCAAgC,CAAC,EAAE;AAC7D,YAAI,MAAM;AACV,YAAI,MAAM,OAAO,cAAAA,QAAM,KAAK,kDAAkD,CAAC,EAAE;AACjF,YAAI,MAAM;AAAA,MACZ,OAAO;AACL,YAAI,MAAM;AACV,YAAI,MAAM,GAAG;AACb,YAAI,MAAM;AACV,YAAI,MAAM,KAAK,cAAAA,QAAM,KAAK,MAAM,CAAC,QAAQ,cAAAA,QAAM,KAAK,iBAAiB,CAAC,0BAA0B;AAChG,YAAI,MAAM;AAAA,MACZ;AACA,cAAQ,KAAK,CAAC;AACd;AAAA,IACF;AAKA,QAAI,gBAAgB,GAAG;AACrB,4BAAsB,MAAM;AAC5B,yBAAmB,QAAQ,EAAE,QAAQ,UAAU,OAAO,CAAC;AACvD,yBAAmB,MAAM;AAAA,IAC3B;AAIA,QAAI,KAAK,OAAO;AACd,YAAM,WAAW,cAAc,MAAM;AACrC,cAAQ,IAAI,YAAY,QAAQ,CAAC;AACjC,cAAQ,KAAK,gBAAgB,QAAQ,KAAK,UAAU,UAAU,KAAK,WAAW,CAAC;AAC/E;AAAA,IACF;AAIA,QAAI,KAAK,MAAM;AACb,YAAM,gBAAgB,mBAAmB,MAAM;AAC/C,YAAM,aAAa;AAAA,QACjB;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,cAAc,OAAO;AAAA,QACrB,aAAa,OAAO;AAAA,QACpB,eAAe,OAAO;AAAA,QACtB,aAAa,OAAO;AAAA,QACpB,YAAY,OAAO;AAAA,QACnB,QAAQ,OAAO;AAAA,QACf;AAAA,QACA,eAAe,OAAO,YAAY,OAAO,aAAa;AAAA,QACtD,UAAU,OAAO;AAAA,QACjB,OAAO,OAAO;AAAA,QACd,iBAAiB,OAAO;AAAA,QACxB,cAAc,OAAO;AAAA,QACrB,mBAAmB,OAAO;AAAA,MAC5B;AACA,cAAQ,IAAI,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAC/C,cAAQ,KAAK,gBAAgB,QAAQ,KAAK,UAAU,UAAU,KAAK,WAAW,CAAC;AAC/E;AAAA,IACF;AAKA,QAAI,UAAU,OAAO,cAAc,OAAO,MAAM,QAAQ,OAAO,YAAY,MAAM;AACjF,QAAI,CAAC,OAAO,mBAAmB;AAC7B,UAAI;AAAA,QACF,cAAAA,QAAM,IAAI,iFAAuE,IACjF,cAAAA,QAAM,IAAI,2DAA2D;AAAA,MACvE;AAAA,IACF;AACA,QAAI,MAAM;AAIV,QAAI,OAAO,gBAAgB,KAAK,OAAO,gBAAgB,WAAW,KAAK,OAAO,aAAa,WAAW,GAAG;AACvG,UAAI;AAAA,QACF,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,KAAK,cAAAA,QAAM,KAAK,MAAM,oBAAoB,CAAC,KAAK,cAAAA,QAAM,KAAK,UAAK,OAAO,YAAY,QAAQ,OAAO,iBAAiB,IAAI,MAAM,EAAE,qBAAqB,CAAC;AAAA,MAC5K;AACA,UAAI,MAAM;AACV,cAAQ,KAAK,CAAC;AACd;AAAA,IACF;AAEA,QAAI,OAAO,gBAAgB,GAAG;AAC5B,UAAI;AAAA,QACF,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,KAAK,cAAAA,QAAM,KAAK,MAAM,oBAAoB,CAAC,KAAK,cAAAA,QAAM,KAAK,UAAK,OAAO,YAAY,QAAQ,OAAO,iBAAiB,IAAI,MAAM,EAAE,qBAAqB,CAAC;AAAA,MAC5K;AACA,UAAI,MAAM;AAAA,IACZ;AAIA,QAAI,OAAO,cAAc,GAAG;AAC1B,YAAM,UAAU,KAAK,WAAW;AAChC,YAAM,QAAQ,KAAK,SAAS;AAG5B,YAAM,EAAE,iBAAiB,mBAAmB,IAAI,gBAAgB,QAAQ,KAAK;AAG7E,UAAI,QAAQ,qBAAqB;AAEjC,YAAM,iBAAyC,CAAC;AAChD,YAAM,mBAA2C,CAAC;AAGlD,iBAAW,QAAQ,iBAAiB;AAClC,mBAAW,SAAS,KAAK,QAAQ;AAC/B,gBAAM,MAAM,cAAc,MAAM,MAAM,KAAK;AAC3C,cAAI,MAAM,aAAa,GAAG;AACxB,2BAAe,GAAG,KAAK,eAAe,GAAG,KAAK,KAAK;AAAA,UACrD,OAAO;AACL,6BAAiB,GAAG,KAAK,iBAAiB,GAAG,KAAK,KAAK;AAAA,UACzD;AAAA,QACF;AAAA,MACF;AAEA,YAAM,gBAAgB,oBAAI,IAAI;AAAA,QAC5B,GAAG;AAAA,QACH,GAAG,OAAO,KAAK,cAAc;AAAA,QAC7B,GAAG,OAAO,KAAK,gBAAgB;AAAA,MACjC,CAAC;AAED,YAAM,mBAAmB,CAAC,GAAG,aAAa,EAAE;AAAA,QAC1C,CAAC,SAAS,eAAe,GAAG,KAAK,MAAM,iBAAiB,GAAG,KAAK,KAAK;AAAA,MACvE;AAEA,uBAAiB,KAAK,CAAC,GAAG,MAAM;AAC9B,cAAM,KAAK,eAAe,QAAQ,CAAC;AACnC,cAAM,KAAK,eAAe,QAAQ,CAAC;AACnC,YAAI,OAAO,MAAM,OAAO,GAAI,QAAO,KAAK;AACxC,YAAI,OAAO,GAAI,QAAO;AACtB,YAAI,OAAO,GAAI,QAAO;AACtB,eAAO,EAAE,cAAc,CAAC;AAAA,MAC1B,CAAC;AAED,iBAAW,OAAO,kBAAkB;AAClC,cAAM,OAAO,eAAe,GAAG,KAAK;AACpC,YAAI,SAAS,MAAM,KAAK,eAAe,GAAG,KAAK,GAAG,iBAAiB,GAAG,KAAK,CAAC;AAAA,MAC9E;AAEA,UAAI,MAAM;AAEV,UAAI;AAAA,QACF,KAAK,cAAAA,QAAM,KAAK,QAAQ,CAAC,IAAI,iBAAiB,OAAO,aAAa,OAAO,aAAa,CAAC;AAAA,MACzF;AACA,UAAI,MAAM;AAGV,UAAI,OAAO,cAAc,OAAO,GAAG;AACjC,YAAI,QAAQ,SAAS;AAErB,cAAM,SAAS,CAAC,GAAG,OAAO,cAAc,QAAQ,CAAC,EAAE;AAAA,UACjD,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,QACtB;AACA,mBAAW,CAAC,MAAM,KAAK,KAAK,QAAQ;AAClC,gBAAM,YAAY,KAAK,QAAQ,eAAe,EAAE;AAChD,gBAAM,OAAO,gBAAgB,IAAI;AACjC,gBAAMC,aAAY,SAAS,SACvB,cAAAD,QAAM,IAAI,IAAI,QAAQ,IACtB,SAAS,WACT,cAAAA,QAAM,OAAO,IAAI,UAAU,IAC3B,SAAS,kBACT,cAAAA,QAAM,KAAK,IAAI,QAAQ,IACvB,cAAAA,QAAM,KAAK,IAAI,OAAO;AAC1B,cAAI,SAAS,SAAS,gBAAiB;AACvC,cAAI;AAAA,YACF,OAAO,cAAAA,QAAM,KAAK,QAAQ,CAAC,IAAI,cAAAA,QAAM,OAAO,SAAS,CAAC,IAAIC,UAAS,GAAG,cAAAD,QAAM,KAAK,GAAG,CAAC,IAAI,cAAAA,QAAM,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,UACrH;AAAA,QACF;AACA,YAAI,MAAM;AAAA,MACZ;AAGA,UAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,YAAI,QAAQ,WAAW;AACvB,mBAAW,EAAE,MAAM,IAAI,MAAM,KAAK,OAAO,UAAU;AACjD,cAAI;AAAA,YACF,OAAO,cAAAA,QAAM,KAAK,QAAQ,CAAC,IAAI,cAAAA,QAAM,MAAM,EAAE,CAAC,IAAI,cAAAA,QAAM,KAAK,IAAI,KAAK,GAAG,CAAC;AAAA,UAC5E;AAAA,QACF;AACA,YAAI,MAAM;AAAA,MACZ;AAGA,UAAI,gBAAgB,SAAS,GAAG;AAC9B,YAAI,QAAQ,gBAAgB;AAC5B,YAAI,MAAM;AACV,2BAAmB,EAAE,GAAG,QAAQ,OAAO,gBAAgB,GAAG,SAAS,KAAK;AAAA,MAC1E;AAGA,YAAM,iBAAiB,mBAAmB,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,QAAQ,CAAC;AACjF,UAAI,iBAAiB,KAAK,CAAC,OAAO;AAChC,YAAI,SAAS;AACX,cAAI,QAAQ,qBAAqB;AACjC,cAAI,MAAM,cAAAA,QAAM,IAAI,gFAA2E,CAAC;AAChG,cAAI,MAAM;AACV,6BAAmB,EAAE,GAAG,QAAQ,OAAO,mBAAmB,GAAG,MAAM,KAAK;AAAA,QAC1E,OAAO;AACL,cAAI,MAAM;AACV,cAAI;AAAA,YACF,KAAK,cAAAA,QAAM,KAAK,QAAQ,CAAC,KAAK,cAAAA,QAAM,KAAK,GAAG,cAAc,sBAAsB,mBAAmB,IAAI,MAAM,EAAE,oBAAe,cAAAA,QAAM,KAAK,WAAW,CAAC,YAAY,CAAC;AAAA,UACpK;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAKA,QAAI,OAAO,gBAAgB,SAAS,GAAG;AACrC,UAAI,iBAAiB,sBAAsB;AAC3C,UAAI;AAAA,QACF,cAAAA,QAAM,IAAI,2EAA2E;AAAA,MACvF;AACA,UAAI,MAAM;AAGV,YAAM,OAAO,oBAAI,IAAsD;AACvE,iBAAW,SAAS,OAAO,iBAAiB;AAC1C,cAAM,MAAM,GAAG,MAAM,UAAU,MAAM,KAAK,MAAM,OAAO;AACvD,cAAM,WAAW,KAAK,IAAI,GAAG;AAC7B,YAAI,UAAU;AACZ,mBAAS;AAAA,QACX,OAAO;AACL,eAAK,IAAI,KAAK,EAAE,OAAO,OAAO,EAAE,CAAC;AAAA,QACnC;AAAA,MACF;AAEA,iBAAW,EAAE,OAAO,MAAM,KAAK,KAAK,OAAO,GAAG;AAC5C,YAAI,eAAe,OAAO,KAAK;AAAA,MACjC;AAEA,UAAI,MAAM;AAAA,IACZ;AAIA,QAAI,OAAO,aAAa,SAAS,GAAG;AAClC,UAAI,iBAAiB,eAAe;AACpC,UAAI;AAAA,QACF,cAAAA,QAAM,IAAI,iEAA4D;AAAA,MACxE;AACA,UAAI,MAAM;AAEV,iBAAW,MAAM,OAAO,cAAc;AACpC,YAAI,YAAY,EAAE;AAAA,MACpB;AAEA,UAAI,CAAC,OAAO,mBAAmB;AAC7B,YAAI,MAAM;AACV,YAAI;AAAA,UACF,KAAK,cAAAA,QAAM,KAAK,aAAQ,CAAC,IAAI,cAAAA,QAAM,OAAO,kDAAkD,CAAC;AAAA,QAC/F;AACA,YAAI;AAAA,UACF,cAAAA,QAAM,IAAI,4DAA4D;AAAA,QACxE;AAAA,MACF;AACA,UAAI,MAAM;AAAA,IACZ;AAEA,QAAI,QAAQ;AACZ,QAAI,MAAM;AAIV,QAAI,QAAQ,YAAY;AACxB,QAAI,OAAO,cAAc,GAAG;AAC1B,UAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,mBAAmB,CAAC,+CAA+C;AAC9F,UAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,iBAAiB,CAAC,wCAAwC;AACrF,UAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,iBAAiB,CAAC,iCAAiC;AAAA,IAChF;AACA,QAAI,OAAO,gBAAgB,SAAS,GAAG;AACrC,UAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,iBAAiB,CAAC,qCAAqC;AAAA,IACpF;AACA,QAAI,CAAC,KAAK,WAAW,mBAAmB,MAAM,GAAG;AAC/C,UAAI,KAAK,YAAY,cAAAA,QAAM,KAAK,WAAW,CAAC,6BAA6B;AAAA,IAC3E;AACA,QAAI,MAAM;AAEV,YAAQ,KAAK,eAAe,QAAQ,KAAK,WAAW,CAAC;AAAA,EACvD,CAAC;AACL;AAIA,IAAM,kBAAkB;AAGjB,SAAS,gBACd,QACA,OACiF;AACjF,QAAM,kBAAsC,CAAC;AAC7C,QAAM,qBAAyC,CAAC;AAEhD,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,mBAAmB,KAAK,OAAO,OAAO,CAAC,MAAM;AACjD,YAAM,OAAO,gBAAgB,EAAE,MAAM;AACrC,UAAI,UAAU,SAAS,mBAAmB,EAAE,aAAa,GAAI,QAAO;AACpE,aAAO,SAAS;AAAA,IAClB,CAAC;AACD,UAAM,aAAa,KAAK,OAAO,OAAO,CAAC,MAAM;AAC3C,YAAM,OAAO,gBAAgB,EAAE,MAAM;AACrC,aAAO,SAAS;AAAA,IAClB,CAAC;AAED,QAAI,iBAAiB,SAAS,GAAG;AAC/B,sBAAgB,KAAK,EAAE,GAAG,MAAM,QAAQ,iBAAiB,CAAC;AAAA,IAC5D;AACA,QAAI,WAAW,SAAS,GAAG;AACzB,yBAAmB,KAAK,EAAE,GAAG,MAAM,QAAQ,WAAW,CAAC;AAAA,IACzD;AAAA,EACF;AAEA,SAAO,EAAE,iBAAiB,mBAAmB;AAC/C;AAGO,SAAS,mBAAmB,QAGjC;AACA,MAAI,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,gBAAgB;AACnD,aAAW,QAAQ,OAAO,OAAO;AAC/B,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,OAAO,gBAAgB,MAAM,MAAM;AACzC,UAAI,SAAS,OAAQ;AAAA,eACZ,SAAS,SAAU;AAAA,eACnB,SAAS,gBAAiB;AAAA,UAC9B;AAAA,IACP;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IAAM;AAAA,IAAQ;AAAA,IAAK;AAAA,IACnB,iBAAiB,OAAO,gBAAgB;AAAA,IACxC,cAAc,OAAO,aAAa;AAAA,EACpC;AACF;AAEA,SAAS,mBAAmB,QAA4B;AACtD,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,aAAa,oBAAI,IAAoB;AAC3C,eAAW,SAAS,KAAK,QAAQ;AAC/B,iBAAW,IAAI,MAAM,SAAS,WAAW,IAAI,MAAM,MAAM,KAAK,KAAK,CAAC;AAAA,IACtE;AACA,eAAW,SAAS,WAAW,OAAO,GAAG;AACvC,UAAI,SAAS,gBAAiB,QAAO;AAAA,IACvC;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,mBAAmB,QAAmB,SAAkB,QAAQ,OAAa;AAC3F,aAAW,QAAQ,OAAO,OAAO;AAC/B,QAAI;AAAA,MACF,KAAK,cAAAA,QAAM,KAAK,MAAM,KAAK,QAAQ,CAAC,MAClC,cAAAA,QAAM;AAAA,QACJ,IAAI,KAAK,UAAU,SAAS,KAAK,eAAe,IAAI,MAAM,EAAE,KACzD,KAAK,YAAY,WAAW,KAAK,iBAAiB,IAAI,MAAM,EAAE;AAAA,MACnE;AAAA,IACJ;AAEA,QAAI,CAAC,SAAS;AAEZ,YAAM,aAAa,oBAAI,IAA0C;AACjE,iBAAW,SAAS,KAAK,QAAQ;AAC/B,cAAM,MAAM,WAAW,IAAI,MAAM,MAAM,KAAK,CAAC;AAC7C,YAAI,KAAK,KAAK;AACd,mBAAW,IAAI,MAAM,QAAQ,GAAG;AAAA,MAClC;AAEA,iBAAW,UAAU,WAAW,OAAO,GAAG;AACxC,cAAM,OAAO,gBAAgB,OAAO,CAAC,EAAE,MAAM,KAAK;AAElD,YAAI,SAAS,SAAS,OAAO,UAAU,iBAAiB;AACtD,gBAAM,MAAM,OAAO,CAAC,EAAE,aAAa,IAAI,cAAAA,QAAM,IAAI,OAAO,IAAI,cAAAA,QAAM,OAAO,OAAO;AAChF,gBAAM,YAAY,cAAAA,QAAM,KAAK,OAAO,CAAC,EAAE,OAAO,QAAQ,eAAe,EAAE,CAAC;AACxE,cAAI;AAAA,YACF,OAAO,GAAG,KAAK,cAAAA,QAAM,MAAM,OAAO,CAAC,EAAE,OAAO,CAAC,KAAK,SAAS;AAAA,UAC7D;AACA,cAAI;AAAA,YACF,cAAAA,QAAM,IAAI,qBAAgB,OAAO,MAAM,kDAA6C;AAAA,UACtF;AAAA,QACF,OAAO;AACL,qBAAW,SAAS,QAAQ;AAC1B,8BAAkB,KAAK;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,iBAAW,SAAS,KAAK,QAAQ;AAC/B,0BAAkB,KAAK;AAAA,MACzB;AAAA,IACF;AAEA,QAAI,MAAM;AAAA,EACZ;AACF;AAEA,SAAS,kBAAkB,OAAiG;AAC1H,QAAM,MAAM,MAAM,aAAa,IAC3B,cAAAA,QAAM,IAAI,OAAO,IACjB,cAAAA,QAAM,OAAO,OAAO;AACxB,QAAM,MAAM,cAAAA,QAAM,KAAK,GAAG,OAAO,MAAM,IAAI,CAAC,IAAI,OAAO,MAAM,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE;AACjF,QAAM,YAAY,cAAAA,QAAM,KAAK,MAAM,OAAO,QAAQ,eAAe,EAAE,CAAC;AACpE,QAAM,OAAO,gBAAgB,MAAM,MAAM;AACzC,QAAM,UAAU,SAAS,kBACrB,cAAAA,QAAM,IAAI,SAAS,IACnB;AACJ,MAAI;AAAA,IACF,OAAO,GAAG,IAAI,GAAG,KAAK,cAAAA,QAAM,MAAM,MAAM,OAAO,CAAC,GAAG,OAAO,KAAK,SAAS;AAAA,EAC1E;AACF;AAIO,SAAS,eAAe,QAAmB,aAA8B;AAC9E,MAAI,OAAO,cAAc,EAAG,QAAO;AACnC,MAAI,gBAAgB,UAAa,OAAO,gBAAgB,YAAa,QAAO;AAC5E,SAAO;AACT;AAEO,SAAS,iBAAiB,QAAgB,UAA0B;AACzE,QAAM,QAAkB,CAAC;AACzB,MAAI,SAAS,EAAG,OAAM,KAAK,cAAAA,QAAM,IAAI,KAAK,GAAG,MAAM,SAAS,WAAW,IAAI,MAAM,EAAE,EAAE,CAAC;AACtF,MAAI,WAAW,EAAG,OAAM,KAAK,cAAAA,QAAM,OAAO,KAAK,GAAG,QAAQ,WAAW,aAAa,IAAI,MAAM,EAAE,EAAE,CAAC;AACjG,SAAO,MAAM,KAAK,cAAAA,QAAM,KAAK,QAAK,CAAC;AACrC;AAaO,SAAS,gBACd,QACA,QACA,aACQ;AACR,MAAI,gBAAgB,UAAa,OAAO,gBAAgB,YAAa,QAAO;AAE5E,UAAQ,QAAQ;AAAA,IACd,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAU,aAAO,OAAO,cAAc,IAAI,IAAI;AAAA,IACnD,KAAK,QAAQ;AACX,YAAM,OAAO,OAAO,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,EAC9C,OAAO,CAAC,MAAM,gBAAgB,EAAE,MAAM,MAAM,MAAM,EAAE;AACvD,aAAO,OAAO,IAAI,IAAI;AAAA,IACxB;AAAA,IACA,KAAK,UAAU;AACb,YAAM,UAAU,OAAO,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,EACjD,OAAO,CAAC,MAAM,gBAAgB,EAAE,MAAM,MAAM,UAAU,gBAAgB,EAAE,MAAM,MAAM,QAAQ,EAAE;AACjG,aAAO,UAAU,IAAI,IAAI;AAAA,IAC3B;AAAA,IACA,KAAK,OAAO;AACV,YAAM,aAAa,OAAO,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,EACpD,OAAO,CAAC,MAAM,gBAAgB,EAAE,MAAM,MAAM,eAAe,EAAE;AAChE,aAAO,aAAa,IAAI,IAAI;AAAA,IAC9B;AAAA,IACA;AAAS,aAAO,eAAe,QAAQ,WAAW;AAAA,EACpD;AACF;;;AO5hBA,IAAAE,eAAiB;AACjB,IAAAC,aAAe;AACf,IAAAC,cAAgB;AAChB,IAAAC,gBAAkB;AAsBX,SAAS,uBAAuBC,UAAwB;AAC7D,EAAAA,SACG,QAAQ,SAAS,EACjB,YAAY,6EAA6E,EACzF,OAAO,QAAQ,wEAAwE,EACvF,OAAO,YAAY,oCAAqC,EACxD,OAAO,mBAAmB,8EAAyE,EACnG,OAAO,gBAAgB,8CAA8C,GAAG,EACxE,OAAO,YAAY,iDAAiD,EACpE,OAAO,cAAc,mCAAmC,EACxD,OAAO,qBAAqB,mDAAmD,MAAM,EACrF,OAAO,UAAU,wBAAwB,EACzC,OAAO,WAAW,0DAA0D,EAC5E,OAAO,yBAAyB,+BAA+B,EAC/D,OAAO,kBAAkB,iEAAiE,EAC1F,OAAO,oBAAoB,4DAA4D,EACvF;AAAA,IAAO;AAAA,IAAsB;AAAA,IAC5B,CAAC,MAAc,OAAO,SAAS,GAAG,EAAE;AAAA,EAAC,EACtC,OAAO,aAAa,wCAAwC,EAC5D,OAAO,WAAW,kBAAkB,EACpC,OAAO,kBAAkB,oCAAoC,EAC7D,OAAO,eAAe,0EAA0E,EAChG,OAAO,cAAc,sEAAsE,EAC3F,OAAO,OAAO,SAmBT;AACJ,UAAM,SAAiB,KAAK,SAAS,WAAW,KAAK,WAAW,aAAa;AAC7E,UAAM,OAAO,gBAAgB;AAI7B,UAAM,UAAU,KAAK,SAAS,KAAK,MAAM,OAAO,iBAAiB,IAAI;AAMrE,UAAM,cAAc,KAAK,SAAS,CAAC,KAAK,gBAAgB,KAAK,eAAe;AAC5E,UAAM,oBAAoB,KAAK,gBAAgB,cAAc,2BAA2B;AAExF,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,OAAO;AAC7B,UAAI,OAAO,UAAU;AAAA,IACvB;AAGA,QAAI,KAAK,SAAS;AAChB,YAAM,EAAE,cAAAC,cAAa,IAAI,MAAM;AAC/B,MAAAA,cAAa;AAAA,QACX,iBAAiB;AAAA,QACjB,eAAe,QAAQ,IAAI;AAAA,QAC3B,WAAW,QAAQ,IAAI;AAAA,QACvB,WAAW,QAAQ,IAAI;AAAA,QACvB,kBAAkB,QAAQ,IAAI;AAAA,QAC9B,gBAAgB,QAAQ,IAAI;AAAA,QAC5B,aAAa,QAAQ,IAAI;AAAA,QACzB,iBAAiB,QAAQ,IAAI;AAAA,QAC7B,mBAAmB,QAAQ,IAAI;AAAA,QAC/B,cAAc,QAAQ,IAAI;AAAA,QAC1B,iBAAiB;AAAA,QACjB;AAAA,QACA,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK,SAAS,WAAW,UAAU,YAAY;AAAA,MAC3D,CAAC;AAAA,IACH;AAGA,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,eAAe,aAAAC,QAAK,QAAQ,KAAK,IAAI;AAC3C,UAAM,mBAAmB,KAAK,SAAS,MAAM,KAAK,OAAO;AAEzD,UAAM,UAAU,KAAK,QAAQ,KAAK,QAC9B,WACA,YAAAC,SAAI,EAAE,MAAM,cAAAC,QAAM,IAAI,+BAA0B,GAAG,OAAO,OAAO,CAAC,EAAE,MAAM;AAE9E,UAAM,gBAAgB,gBAAgB;AAAA,MACpC,QAAQ,KAAK,UAAU;AAAA,MACvB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,OAAO,KAAK;AAAA,IACd,CAAC;AAGD,QAAI,KAAK,UAAU;AACjB,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM;AAChC,MAAAA,eAAc,aAAa;AAAA,IAC7B;AAEA,QAAI,cAAc,MAAM,WAAW,GAAG;AACpC,eAAS,KAAK;AAEd,UAAI,cAAc,SAAS,YAAY;AAErC,YAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,OAAO;AAC7B,cAAI,KAAK,+CAA+C;AACxD,cAAI,MAAM;AAAA,QACZ;AAEA,cAAMC,UAAS,MAAM,UAAU;AAAA,UAC7B;AAAA,UACA,YAAY,aAAa,SAAS;AAAA,UAClC,aAAa,KAAK;AAAA,QACpB,CAAC;AACD,sBAAcA,SAAQ,MAAM,QAAQ,QAAQ,GAAG,MAAM,iBAAiB;AACtE;AAAA,MACF;AAGA,UAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,OAAO;AAC7B,YAAI,MAAM;AACV,YAAI,MAAM,KAAK,cAAAF,QAAM,OAAO,QAAG,CAAC,0DAAqD;AACrF,YAAI,cAAc,iBAAiB;AACjC,cAAI,MAAM,cAAAA,QAAM,IAAI,QAAQ,cAAc,eAAe,EAAE,CAAC;AAAA,QAC9D;AACA,YAAI,cAAc,cAAc,GAAG;AACjC,cAAI,MAAM,cAAAA,QAAM,IAAI,SAAS,cAAc,WAAW,QAAQ,cAAc,gBAAgB,IAAI,MAAM,EAAE,gBAAgB,CAAC;AAAA,QAC3H;AACA,YAAI,CAAC,KAAK,UAAU;AAClB,cAAI,MAAM,cAAAA,QAAM,IAAI,0DAA0D,CAAC;AAAA,QACjF;AACA,YAAI,MAAM;AAAA,MACZ,WAAW,KAAK,MAAM;AACpB,gBAAQ,IAAI,KAAK,UAAU;AAAA,UACzB,SAAS;AAAA,UACT;AAAA,UACA,UAAU,cAAc;AAAA,UACxB,cAAc;AAAA,UACd,cAAc;AAAA,UACd,aAAa;AAAA,UACb,aAAa;AAAA,UACb,eAAe;AAAA,UACf,iBAAiB,cAAc;AAAA,UAC/B,WAAW,KAAK,WAAW,cAAc,YAAY;AAAA,UACrD,eAAe,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,eAAe,GAAG,iBAAiB,GAAG,cAAc,EAAE;AAAA,QACrG,GAAG,MAAM,CAAC,CAAC;AAAA,MACb;AACA,cAAQ,KAAK,CAAC;AACd;AAAA,IACF;AAGA,QAAI,SAAS;AACX,cAAQ,OAAO,cAAAA,QAAM,IAAI,YAAY,cAAc,MAAM,MAAM,gBAAgB,cAAc,MAAM,WAAW,IAAI,MAAM,EAAE,QAAG;AAAA,IAC/H;AAEA,UAAM,SAAS,MAAM,UAAU;AAAA,MAC7B;AAAA,MACA,YAAY,aAAa,SAAS;AAAA,MAClC,OAAO,cAAc;AAAA,MACrB,aAAa,KAAK;AAAA,IACpB,CAAC;AAED,aAAS,KAAK;AAEd,UAAM,WACJ,cAAc,SAAS,WAAW,WAAW;AAC/C,kBAAc,QAAQ,MAAM,QAAQ,UAAU,cAAc,MAAM,QAAQ,MAAM,iBAAiB;AAAA,EACnG,CAAC;AACL;AAIA,SAAS,cACP,QACA,MAcA,QACA,UACA,mBACA,MACA,mBACe;AAEf,MAAI,QAAQ,KAAK,eAAe;AAC9B,uBAAmB,QAAQ,EAAE,QAAQ,UAAU,kBAAkB,CAAC;AAClE,uBAAmB,QAAQ,KAAK,WAAW;AAC3C,0BAAsB,MAAM;AAAA,EAC9B;AAGA,MAAI,KAAK,OAAO;AACd,UAAM,WAAW,cAAc,MAAM;AACrC,UAAM,YAAY,YAAY,QAAQ;AAEtC,QAAI,mBAAmB;AACrB,iBAAAG,QAAG,cAAc,mBAAmB,WAAW,OAAO;AAAA,IACxD,OAAO;AAEL,cAAQ,IAAI,SAAS;AAAA,IACvB;AACA,YAAQ,KAAK,kBAAkB,QAAQ,KAAK,QAAQ,KAAK,WAAW,CAAC;AACrE;AAAA,EACF;AAGA,MAAI,KAAK,MAAM;AACb,UAAM,gBAAgB,mBAAmB,MAAM;AAC/C,UAAM,aAAa;AAAA,MACjB,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,cAAc,OAAO;AAAA,MACrB;AAAA,MACA,aAAa,OAAO;AAAA,MACpB,eAAe,OAAO;AAAA,MACtB,aAAa,OAAO;AAAA,MACpB,YAAY,OAAO;AAAA,MACnB;AAAA,MACA,eAAe,OAAO,YAAY,OAAO,aAAa;AAAA,MACtD,UAAU,OAAO;AAAA,MACjB,OAAO,OAAO;AAAA,MACd,iBAAiB,OAAO;AAAA,MACxB,cAAc,OAAO;AAAA,MACrB,mBAAmB,OAAO;AAAA,IAC5B;AACA,YAAQ,IAAI,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAC/C,YAAQ,KAAK,kBAAkB,QAAQ,KAAK,QAAQ,KAAK,WAAW,CAAC;AACrE;AAAA,EACF;AAGA,QAAM,gBAAgB,aAAa,YAC/B,kBACA,aAAa,WACb,iBACA;AAEJ,QAAM,UAAU,oBAAoB,IAChC,GAAG,iBAAiB,aACpB;AAEJ,MAAI;AAAA,IACF,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS,CAAC,EAAE;AAAA,IAChD,OAAO;AAAA,IACP,GAAG,MAAM,SAAM,aAAa,GAAG,UAAU,KAAK,OAAO,MAAM,EAAE;AAAA,EAC/D;AAEA,MAAI,OAAO,gBAAgB,GAAG;AAC5B,QAAI,MAAM;AACV,QAAI,QAAQ,6BAAwB,OAAO,YAAY,QAAQ,OAAO,iBAAiB,IAAI,MAAM,EAAE,qBAAqB;AACxH,QAAI,MAAM;AAAA,EACZ,OAAO;AACL,UAAM,UAAU,KAAK,WAAW;AAChC,UAAM,QAAQ,KAAK,SAAS;AAC5B,UAAM,EAAE,iBAAiB,mBAAmB,IAAI,gBAAgB,QAAQ,KAAK;AAG7E,QAAI,QAAQ,qBAAqB;AACjC,UAAM,iBAAyC,CAAC;AAChD,UAAM,mBAA2C,CAAC;AAClD,eAAW,QAAQ,iBAAiB;AAClC,iBAAW,SAAS,KAAK,QAAQ;AAC/B,cAAM,MAAM,cAAc,MAAM,MAAM,KAAK;AAC3C,YAAI,MAAM,aAAa,EAAG,gBAAe,GAAG,KAAK,eAAe,GAAG,KAAK,KAAK;AAAA,YACxE,kBAAiB,GAAG,KAAK,iBAAiB,GAAG,KAAK,KAAK;AAAA,MAC9D;AAAA,IACF;AACA,UAAM,gBAAgB,oBAAI,IAAI,CAAC,GAAG,gBAAgB,GAAG,OAAO,KAAK,cAAc,GAAG,GAAG,OAAO,KAAK,gBAAgB,CAAC,CAAC;AACnH,UAAM,aAAa,CAAC,GAAG,aAAa,EAAE,OAAO,CAAC,OAAO,eAAe,CAAC,KAAK,MAAM,iBAAiB,CAAC,KAAK,KAAK,CAAC,EAC1G,KAAK,CAAC,GAAG,MAAM;AACd,YAAM,KAAK,eAAe,QAAQ,CAAC,GAAG,KAAK,eAAe,QAAQ,CAAC;AACnE,UAAI,OAAO,MAAM,OAAO,GAAI,QAAO,KAAK;AACxC,UAAI,OAAO,GAAI,QAAO;AACtB,UAAI,OAAO,GAAI,QAAO;AACtB,aAAO,EAAE,cAAc,CAAC;AAAA,IAC1B,CAAC;AACH,eAAW,OAAO,YAAY;AAC5B,YAAM,OAAO,eAAe,GAAG,KAAK;AACpC,UAAI,SAAS,MAAM,KAAK,eAAe,GAAG,KAAK,GAAG,iBAAiB,GAAG,KAAK,CAAC;AAAA,IAC9E;AACA,QAAI,MAAM;AACV,QAAI,MAAM,KAAK,cAAAH,QAAM,KAAK,QAAQ,CAAC,IAAI,iBAAiB,OAAO,aAAa,OAAO,aAAa,CAAC,EAAE;AACnG,QAAI,MAAM;AAEV,QAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAI,QAAQ,gBAAgB;AAC5B,UAAI,MAAM;AACV,yBAAmB,EAAE,GAAG,QAAQ,OAAO,gBAAgB,GAAG,SAAS,KAAK;AAAA,IAC1E;AAEA,UAAM,iBAAiB,mBAAmB,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,QAAQ,CAAC;AACjF,QAAI,iBAAiB,KAAK,CAAC,OAAO;AAChC,UAAI,SAAS;AACX,YAAI,QAAQ,qBAAqB;AACjC,YAAI,MAAM,cAAAA,QAAM,IAAI,gFAA2E,CAAC;AAChG,YAAI,MAAM;AACV,2BAAmB,EAAE,GAAG,QAAQ,OAAO,mBAAmB,GAAG,MAAM,KAAK;AAAA,MAC1E,OAAO;AACL,YAAI,MAAM;AACV,YAAI,MAAM,KAAK,cAAAA,QAAM,KAAK,QAAG,CAAC,KAAK,cAAAA,QAAM,KAAK,GAAG,cAAc,sBAAsB,mBAAmB,IAAI,MAAM,EAAE,oBAAe,cAAAA,QAAM,KAAK,WAAW,CAAC,YAAY,CAAC,EAAE;AAAA,MAC3K;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,gBAAgB,SAAS,GAAG;AACrC,QAAI,iBAAiB,sBAAsB;AAC3C,QAAI,MAAM,cAAAA,QAAM,IAAI,2EAA4E,CAAC;AACjG,QAAI,MAAM;AACV,UAAM,OAAO,oBAAI,IAAsD;AACvE,eAAW,SAAS,OAAO,iBAAiB;AAC1C,YAAM,MAAM,GAAG,MAAM,UAAU,MAAM,KAAK,MAAM,OAAO;AACvD,YAAM,WAAW,KAAK,IAAI,GAAG;AAC7B,UAAI,UAAU;AAAE,iBAAS;AAAA,MAAS,OAAO;AAAE,aAAK,IAAI,KAAK,EAAE,OAAO,OAAO,EAAE,CAAC;AAAA,MAAG;AAAA,IACjF;AACA,eAAW,EAAE,OAAO,MAAM,KAAK,KAAK,OAAO,GAAG;AAC5C,UAAI,eAAe,OAAO,KAAK;AAAA,IACjC;AACA,QAAI,MAAM;AAAA,EACZ;AAEA,MAAI,QAAQ;AACZ,MAAI,MAAM;AACV,MAAI,QAAQ,YAAY;AACxB,MAAI,OAAO,cAAc,GAAG;AAC1B,QAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,mBAAmB,CAAC,+CAA+C;AAC9F,QAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,iBAAiB,CAAC,wCAAwC;AAAA,EACvF;AACA,MAAI,OAAO,gBAAgB,SAAS,GAAG;AACrC,QAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,iBAAiB,CAAC,qCAAqC;AAAA,EACpF;AACA,MAAI,MAAM;AAEV,UAAQ,KAAK,kBAAkB,QAAQ,KAAK,QAAQ,KAAK,WAAW,CAAC;AACvE;AAQO,SAAS,kBACd,QACA,QACA,aACQ;AACR,SAAO,gBAAgB,QAAQ,QAAQ,WAAW;AACpD;;;ACzZA,IAAAI,gBAAkB;AAClB,IAAAC,eAAiB;AACjB,IAAAC,aAAe;;;ACHf,IAAAC,aAAe;AACf,IAAAC,eAAiB;AACjB,IAAAC,iBAA8B;AA+B9B,IAAM,oBAA+D;AAAA,EACnE,EAAE,MAAM,oBAAoB,MAAM,UAAU;AAAA,EAC5C,EAAE,MAAM,qBAAqB,MAAM,WAAW;AAAA,EAC9C,EAAE,MAAM,qBAAqB,MAAM,WAAW;AAChD;AAEA,IAAM,sBAAiE;AAAA,EACrE,EAAE,MAAM,gBAAgB,MAAM,cAAc;AAAA,EAC5C,EAAE,MAAM,iBAAiB,MAAM,eAAe;AAAA,EAC9C,EAAE,MAAM,kBAAkB,MAAM,gBAAgB;AAAA,EAChD,EAAE,MAAM,kBAAkB,MAAM,gBAAgB;AAAA,EAChD,EAAE,MAAM,iBAAiB,MAAM,gBAAgB;AACjD;AAEA,IAAM,mBAAmB,CAAC,GAAG,mBAAmB,GAAG,mBAAmB;AAI/D,SAAS,mBAAmB,SAAiB,MAAM,QAAQ,IAAI,GAAY;AAChF,MAAI;AACF,UAAM,UAAU,aAAAC,QAAK,KAAK,KAAK,gBAAgB,SAAS,cAAc;AACtE,QAAI,WAAAC,QAAG,WAAW,OAAO,GAAG;AAC1B,aAAO;AAAA,IACT;AAEA,UAAM,UAAM,8BAAc,aAAAD,QAAK,KAAK,KAAK,cAAc,CAAC;AACxD,QAAI,QAAQ,GAAG,OAAO,eAAe;AACrC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOO,SAAS,kBAAkB,SAAiB,MAAM,QAAQ,IAAI,GAAkB;AACrF,MAAI;AACF,UAAM,UAAU,aAAAA,QAAK,KAAK,KAAK,gBAAgB,SAAS,cAAc;AACtE,UAAM,eAAe,WAAAC,QAAG,WAAW,OAAO,IACtC,cACA,8BAAc,aAAAD,QAAK,KAAK,KAAK,cAAc,CAAC,EAAE,QAAQ,GAAG,OAAO,eAAe;AACnF,UAAM,MAAM,WAAAC,QAAG,aAAa,cAAc,OAAO;AACjD,UAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,WAAO,KAAK,WAAW;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,WAAW,SAAuC;AAChE,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,IAAI,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE;AAC5C,SAAO,MAAM,CAAC,IAAI,OAAO;AAC3B;AAIO,SAAS,iBAAiB,MAAM,QAAQ,IAAI,GAIjD;AACA,QAAM,QAAkB,CAAC;AACzB,MAAI,QAAmD;AAEvD,aAAW,EAAE,MAAM,KAAK,KAAK,kBAAkB;AAC7C,UAAM,WAAW,aAAAD,QAAK,KAAK,KAAK,IAAI;AACpC,QAAI,WAAAC,QAAG,WAAW,QAAQ,GAAG;AAC3B,YAAM,KAAK,QAAQ;AACnB,UAAI,CAAC,MAAO,SAAQ,EAAE,MAAM,MAAM,SAAS;AAAA,IAC7C;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,OAAO,QAAQ;AAAA,IACrB,MAAM,OAAO,QAAQ;AAAA,IACrB,UAAU;AAAA,EACZ;AACF;AAEO,SAAS,OAAO,MAA2B;AAChD,SAAO,SAAS,aAAa,SAAS,cAAc,SAAS;AAC/D;AAEO,SAAS,SAAS,MAA2B;AAClD,SACE,SAAS,iBACT,SAAS,kBACT,SAAS,mBACT,SAAS;AAEb;AAMO,SAAS,mBAAmB,aAAqC;AACtE,SAAO,gBAAgB,QAAQ,eAAe;AAChD;AAMA,SAAS,iBAAiB,YAAoC;AAC5D,MAAI,CAAC,WAAY,QAAO;AACxB,MAAI;AACF,UAAM,UAAU,WAAAA,QAAG,aAAa,YAAY,OAAO;AACnD,WAAO,QAAQ,SAAS,QAAQ,KAAK,QAAQ,SAAS,QAAQ;AAAA,EAChE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIO,SAAS,OAAO,MAAM,QAAQ,IAAI,GAAoB;AAC3D,QAAM,gBAAgB,kBAAkB,UAAU,GAAG;AACrD,QAAM,cAAc,WAAW,aAAa;AAC5C,QAAM,kBAAkB,mBAAmB,0BAA0B,GAAG;AAExE,QAAM,EAAE,MAAM,YAAY,MAAM,YAAY,SAAS,IAAI,iBAAiB,GAAG;AAG7E,QAAM,gBAAgB,SAAS;AAAA,IAAK,CAAC,MACnC,kBAAkB,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC;AAAA,EAClD;AACA,QAAM,kBAAkB,SAAS;AAAA,IAAK,CAAC,MACrC,oBAAoB,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC;AAAA,EACpD;AACA,QAAM,wBAAwB,iBAAiB;AAE/C,QAAM,gBAAgB,iBAAiB,UAAU;AAEjD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,EACF;AACF;;;ADjLA;AA+BA,SAAS,oBAAoB,KAA2B;AACtD,QAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,QAAM,QAAQ,IAAI,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AAGnD,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,EACF;AACA,MAAI,aAAa;AACf,UAAM,MAAM,YAAY,CAAC,KAAK,YAAY,CAAC,KAAK;AAChD,WAAO,EAAE,MAAM,oBAAoB,KAAK,SAAS,MAAM;AAAA,EACzD;AAGA,MACE,MAAM,SAAS,aAAa,KAC5B,MAAM,SAAS,kBAAkB,KACjC,MAAM,SAAS,6BAA6B,GAC5C;AACA,WAAO,EAAE,MAAM,UAAU,SAAS,MAAM;AAAA,EAC1C;AAEA,SAAO,EAAE,MAAM,WAAW,SAAS,MAAM;AAC3C;AAQA,eAAe,kBACb,YACA,KAC6B;AAC7B,MAAI;AAQF,UAAM,EAAE,OAAO,IAAI,MAAM,OAAO,QAAQ;AAExC,UAAM,SAAS,IAAI,OAAO;AAAA,MACxB;AAAA,MACA,oBAAoB;AAAA,IACtB,CAAC;AAGD,UAAM,OAAO,SAAS,IAAI;AAAA,MACxB,UAAU,aAAAC,QAAK,KAAK,KAAK,qBAAqB;AAAA,IAChD,CAAC;AACD,WAAO;AAAA,EACT,SAAS,KAAc;AACrB,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAG3D,QACE,IAAI,SAAS,mBAAmB,KAChC,IAAI,SAAS,kBAAkB,GAC/B;AACA,aAAO;AAAA,IACT;AAEA,WAAO,oBAAoB,GAAG;AAAA,EAChC;AACF;AAIO,SAAS,oBAAoBC,UAAwB;AAC1D,EAAAA,SACG,QAAQ,MAAM,EACd,YAAY,kDAAkD,EAC9D,OAAO,mBAAmB,kDAAkD,aAAa,EACzF,OAAO,UAAU,2EAA2E,EAC5F,OAAO,aAAa,qDAAqD,EACzE,OAAO,OAAO,SAAsB;AACnC,UAAM,SAAU,KAAK,UAAqB;AAC1C,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,WAAW,KAAK,WAAW;AAEjC,QAAI,OAAO,eAAe;AAC1B,QAAI,UAAU;AACZ,UAAI,MAAM,KAAK,cAAAC,QAAM,OAAO,iDAAuC,CAAC,EAAE;AACtE,UAAI,MAAM;AAAA,IACZ;AACA,QAAI,KAAK,oCAA+B;AACxC,QAAI,MAAM;AAEV,UAAM,MAAM,OAAO,GAAG;AAItB,QAAI,QAAQ,aAAa;AAEzB,QAAI,IAAI,eAAe;AACrB,UAAI,QAAQ,UAAU,IAAI,aAAa,eAAe,IAAI,WAAW,GAAG;AAAA,IAC1E,OAAO;AACL,UAAI,KAAK,kCAAkC;AAAA,IAC7C;AAEA,QAAI,IAAI,iBAAiB;AACvB,UAAI,QAAQ,qCAAqC;AAAA,IACnD,OAAO;AACL,UAAI,KAAK,kCAAkC;AAAA,IAC7C;AAEA,QAAI,IAAI,eAAe,QAAQ;AAC7B,UAAI,QAAQ,wBAAwB,cAAAA,QAAM,MAAM,aAAAF,QAAK,SAAS,KAAK,IAAI,cAAc,IAAI,UAAU,CAAC,CAAC,EAAE;AAAA,IACzG,OAAO;AACL,UAAI,KAAK,iDAA4C;AAAA,IACvD;AAGA,UAAM,kBAAkB,mBAAmB,IAAI,WAAW;AAC1D,QAAI,IAAI,yBAAyB,CAAC,iBAAiB;AACjD,UAAI,MAAM;AACV,UAAI,KAAK,+BAA+B;AACxC,iBAAW,KAAK,IAAI,gBAAgB;AAClC,YAAI,MAAM,OAAO,cAAAE,QAAM,OAAO,QAAG,CAAC,IAAI,cAAAA,QAAM,MAAM,aAAAF,QAAK,SAAS,KAAK,CAAC,CAAC,CAAC,EAAE;AAAA,MAC5E;AACA,UAAI,MAAM,KAAK,cAAAE,QAAM,KAAK,6EAAwE,CAAC,EAAE;AAAA,IACvG;AAEA,QAAI,MAAM;AAIV,UAAM,YAAsB,CAAC;AAC7B,QAAI,CAAC,IAAI,cAAe,WAAU,KAAK,QAAQ;AAC/C,QAAI,CAAC,IAAI,gBAAiB,WAAU,KAAK,wBAAwB;AAEjE,QAAI,UAAU,SAAS,GAAG;AACxB,UAAI,QAAQ,sBAAsB;AAClC,UAAI,KAAK,2CAA2C;AACpD,UAAI,MAAM;AACV,iBAAW,OAAO,WAAW;AAC3B,YAAI,MAAM,OAAO,cAAAA,QAAM,OAAO,QAAG,CAAC,IAAI,cAAAA,QAAM,MAAM,GAAG,CAAC,EAAE;AAAA,MAC1D;AACA,UAAI,MAAM;AACV,UAAI,MAAM,KAAK,cAAAA,QAAM,KAAK,iBAAiB,CAAC,EAAE;AAC9C,UAAI,MAAM;AACV,UAAI,MAAM,OAAO,cAAAA,QAAM,KAAK,0BAA0B,UAAU,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE;AAC9E,UAAI,MAAM;AACV,UAAI,MAAM,iBAAiB,cAAAA,QAAM,KAAK,eAAe,CAAC,qBAAqB;AAC3E,UAAI,MAAM;AACV,cAAQ,KAAK,CAAC;AACd;AAAA,IACF;AAIA,QAAI;AACF,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,QAAQ;AAC/C,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,KAAK;AAC5C,YAAM,MAAMD,eAAc,aAAAH,QAAK,KAAK,KAAK,WAAW,CAAC;AACrD,YAAM,eAAe,IAAI,QAAQ,wBAAwB;AACzD,YAAM,UAAU,MAAM,OAAOI,eAAc,YAAY,EAAE;AACzD,YAAM,SAAU,QAAQ,WAAW;AAInC,YAAM,iBACJ,CAAC,CAAC,OAAO,WACT,CAAC,CAAC,OAAO,QAAQ,MAAM,KACvB,CAAC,CAAC,OAAO,QAAQ,MAAM,EAAE;AAE3B,UAAI,CAAC,gBAAgB;AAEnB,YAAI,MAAM,gFAAgF;AAAA,MAC5F;AAAA,IACF,SAAS,GAAG;AAEV,YAAM,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AACxD,UAAI,MAAM,4BAA4B,MAAM,EAAE;AAAA,IAChD;AASA,UAAM,YAAY,KAAK,SAAS;AAChC,UAAM,iBAAiB,OAAO,IAAI,UAAU;AAC5C,UAAM,mBAAmB,SAAS,IAAI,UAAU;AAChD,UAAM,UAAU,aAAa,mBAAmB,kBAAkB,IAAI,eAAe;AAGnF,QAAI,mBAAmB,kBAAkB;AACvC,UAAI,QAAQ,2BAA2B;AACvC,UAAI,KAAK,WAAW,IAAI,WAAW,uDAAuD;AAC1F,UAAI,MAAM,OAAO,cAAAF,QAAM,MAAM,aAAAF,QAAK,SAAS,KAAK,IAAI,UAAW,CAAC,CAAC,EAAE;AACnE,UAAI,MAAM;AACV,UAAI,MAAM,KAAK,cAAAE,QAAM,KAAK,yCAAyC,CAAC,EAAE;AACtE,UAAI,MAAM;AAAA,IACZ;AAIF,QAAI,QAAQ,qBAAqB,WAAW,eAAe,EAAE,EAAE;AAE/D,QAAI;AACJ,QAAI,gBAAgB;AAGpB,QAAI,IAAI,cAAc,IAAI,eAAe;AACvC,YAAM,MAAM,WAAW,IAAI,UAAU;AACrC,YAAM,EAAE,SAAS,OAAO,QAAQ,IAAI,iBAAiB,GAAG;AACxD,UAAI,SAAS;AACX,YAAI,KAAK,sCAAsC,aAAAF,QAAK,SAAS,KAAK,IAAI,UAAU,CAAC,EAAE;AACnF,YAAI,CAAC,UAAU;AACb,uBAAa,IAAI,UAAU;AAC3B,sBAAY,IAAI,YAAY,KAAK;AACjC,cAAI,QAAQ,sBAAsB;AAAA,QACpC,OAAO;AACL,cAAI,MAAM,KAAK,cAAAE,QAAM,KAAK,yDAAyD,CAAC,EAAE;AAAA,QACxF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,IAAI,eAAe,UAAW,mBAAmB,kBAAmB;AAEtE,YAAM,aAAa,UAAU,sBAAsB;AACnD,wBAAkB,aAAAF,QAAK,KAAK,KAAK,UAAU;AAE3C,YAAMK,WAAU,UACZ,mBAAmB,MAAM,IACzB,qBAAqB,MAAM;AAE/B,UAAI,UAAU;AACZ,YAAI,MAAM,KAAK,cAAAH,QAAM,KAAK,2BAA2B,UAAU,EAAE,CAAC,EAAE;AACpE,YAAI,MAAM;AACV,YAAI,MAAM,cAAAA,QAAM,KAAK,2SAA2D,CAAC;AACjF,YAAI,MAAM;AACV,mBAAW,QAAQG,SAAQ,MAAM,IAAI,GAAG;AACtC,cAAI,MAAM,cAAAH,QAAM,KAAK,KAAK,IAAI,EAAE,CAAC;AAAA,QACnC;AACA,YAAI,MAAM;AAAA,MACZ,OAAO;AACL,oBAAY,iBAAiBG,QAAO;AACpC,YAAI,QAAQ,WAAW,cAAAH,QAAM,MAAM,UAAU,CAAC,EAAE;AAChD,YAAI,KAAK,aAAa,cAAAA,QAAM,KAAK,MAAM,CAAC,EAAE;AAC1C,YAAI,KAAK,aAAa,cAAAA,QAAM,KAAK,UAAU,8CAA8C,wCAAwC,CAAC,EAAE;AACpI,wBAAgB;AAAA,MAClB;AAAA,IACF,WAAW,WAAW,gBAAgB;AAEpC,YAAM,EAAE,wBAAAI,wBAAuB,IAAI,MAAM;AACzC,YAAM,WAAW,WAAW,IAAI,UAAW;AAC3C,YAAM,YAAYA,wBAAuB,QAAQ;AACjD,YAAM,UAAU,gBAAgB,UAAU,MAAM;AAEhD,UAAI,YAAY,YAAY,CAAC,WAAW;AACtC,YAAI,KAAK,mEAA8D;AACvE,0BAAkB,IAAI;AAAA,MACxB,WAAW,UAAU;AACnB,0BAAkB,IAAI;AACtB,YAAI,MAAM,KAAK,cAAAJ,QAAM,KAAK,0BAA0B,aAAAF,QAAK,SAAS,KAAK,IAAI,UAAW,CAAC,EAAE,CAAC,EAAE;AAAA,MAC9F,OAAO;AACL,cAAM,MAAM,aAAa,IAAI,UAAW;AACxC,YAAI,KAAK,oBAAe,cAAAE,QAAM,KAAK,aAAAF,QAAK,SAAS,KAAK,GAAG,CAAC,CAAC,EAAE;AAC7D,oBAAY,IAAI,YAAa,OAAO;AACpC,YAAI,WAAW;AACb,cAAI,QAAQ,qDAAgD,cAAAE,QAAM,MAAM,aAAAF,QAAK,SAAS,KAAK,IAAI,UAAW,CAAC,CAAC,EAAE;AAAA,QAChH,OAAO;AACL,cAAI,QAAQ,WAAW,cAAAE,QAAM,MAAM,aAAAF,QAAK,SAAS,KAAK,IAAI,UAAW,CAAC,CAAC,EAAE;AAAA,QAC3E;AACA,0BAAkB,IAAI;AACtB,wBAAgB;AAAA,MAClB;AAAA,IACF,OAAO;AAEL,YAAM,WAAW,WAAW,IAAI,UAAW;AAC3C,YAAM,UAAU,kBAAkB,UAAU,MAAM;AAElD,UAAI,YAAY,UAAU;AACxB,YAAI,KAAK,mEAA8D;AACvE,0BAAkB,IAAI;AAAA,MACxB,WAAW,UAAU;AACnB,0BAAkB,IAAI;AACtB,YAAI,MAAM,KAAK,cAAAE,QAAM,KAAK,0BAA0B,aAAAF,QAAK,SAAS,KAAK,IAAI,UAAW,CAAC,EAAE,CAAC,EAAE;AAAA,MAC9F,OAAO;AACL,cAAM,MAAM,aAAa,IAAI,UAAW;AACxC,YAAI,KAAK,oBAAe,cAAAE,QAAM,KAAK,aAAAF,QAAK,SAAS,KAAK,GAAG,CAAC,CAAC,EAAE;AAC7D,oBAAY,IAAI,YAAa,OAAO;AACpC,YAAI,QAAQ,WAAW,cAAAE,QAAM,MAAM,aAAAF,QAAK,SAAS,KAAK,IAAI,UAAW,CAAC,CAAC,EAAE;AACzE,0BAAkB,IAAI;AACtB,wBAAgB;AAAA,MAClB;AAAA,IACF;AAGA,QAAI,iBAAiB;AAEnB,YAAM,gBAAgB,IAAI,eAAe,OAAO,OAAK,CAAC,EAAE,SAAS,gBAAgB,CAAC;AAElF,UAAI,YAAY;AAChB,iBAAW,KAAK,eAAe;AAC7B,YAAI,WAAAO,QAAG,WAAW,CAAC,GAAG;AACpB,cAAI,CAAC,UAAU;AACZ,gBAAI;AACF,yBAAAA,QAAG,WAAW,GAAG,GAAG,CAAC,MAAM;AAC3B,0BAAY;AAAA,YACd,SAAS,KAAK;AACZ,oBAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,kBAAI,KAAK,qBAAqB,aAAAP,QAAK,SAAS,KAAK,CAAC,CAAC,KAAK,MAAM,EAAE;AAAA,YAClE;AAAA,UACH,OAAO;AACJ,wBAAY;AACZ,gBAAI,MAAM,KAAK,cAAAE,QAAM,KAAK,0BAA0B,aAAAF,QAAK,SAAS,KAAK,CAAC,CAAC,OAAO,aAAAA,QAAK,SAAS,CAAC,CAAC,MAAM,CAAC,EAAE;AAAA,UAC5G;AAAA,QACF;AAAA,MACF;AACA,UAAI,aAAa,CAAC,UAAU;AAC1B,YAAI,QAAQ,kDAAkD;AAAA,MAChE;AAAA,IACF;AAEA,QAAI,UAAU;AACZ,UAAI,MAAM;AACV,UAAI,MAAM,KAAK,cAAAE,QAAM,OAAO,2CAAsC,CAAC,EAAE;AACrE,UAAI,MAAM,oBAAoB,cAAAA,QAAM,KAAK,WAAW,CAAC,YAAY;AACjE,UAAI,MAAM;AACV,cAAQ,KAAK,CAAC;AACd;AAAA,IACF;AAEA,QAAI,MAAM;AAIV,QAAI,QAAQ,YAAY;AAExB,QAAI,CAAC,WAAAK,QAAG,WAAW,eAAe,GAAG;AACnC,UAAI,MAAM,sCAAsC,aAAAP,QAAK,SAAS,KAAK,eAAe,CAAC,EAAE;AACrF,UAAI,MAAM;AACV,UAAI,MAAM,KAAK,cAAAE,QAAM,KAAK,UAAU,CAAC,8BAA8B;AACnE,UAAI,MAAM,KAAK,cAAAA,QAAM,KAAK,MAAM,CAAC,sDAAsD;AACvF,UAAI,MAAM;AACV,cAAQ,KAAK,CAAC;AACd;AAAA,IACF;AAEA,UAAM,UAAU,WAAW,eAAe;AAC1C,UAAM,mBAAmB,UACrB,uBAAuB,OAAO,IAC9B,yBAAyB,OAAO;AAEpC,QAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAI,KAAK,iCAAiC;AAC1C,iBAAW,KAAK,kBAAkB;AAChC,YAAI,MAAM,OAAO,cAAAA,QAAM,IAAI,QAAG,CAAC,IAAI,CAAC,EAAE;AAAA,MACxC;AAAA,IACF,OAAO;AACL,UAAI,QAAQ,2BAA2B,cAAAA,QAAM,MAAM,aAAAF,QAAK,SAAS,KAAK,eAAe,CAAC,CAAC,EAAE;AAAA,IAC3F;AAIA,QAAI,KAAK,4CAAuC;AAEhD,UAAM,YAAY,MAAM,kBAAkB,iBAAiB,GAAG;AAC9D,QAAI,cAAc,MAAM;AACtB,UAAI,MAAM;AAEV,UAAI,UAAU,SAAS,oBAAoB;AAEzC,YAAI,KAAK,uCAAuC,cAAAE,QAAM,OAAO,UAAU,GAAG,CAAC,EAAE;AAC7E,YAAI,MAAM;AACV,YAAI,MAAM,KAAK,cAAAA,QAAM,KAAK,8BAA8B,CAAC,EAAE;AAC3D,YAAI,MAAM,OAAO,cAAAA,QAAM,KAAK,0BAA0B,UAAU,GAAG,EAAE,CAAC,EAAE;AACxE,YAAI,MAAM,cAAc,cAAAA,QAAM,KAAK,iBAAiB,CAAC,cAAc;AACnE,YAAI,MAAM;AAAA,MAEZ,OAAO;AAEL,YAAI,MAAM,6CAA6C;AACvD,YAAI,MAAM;AACV,YAAI,MAAM,KAAK,cAAAA,QAAM,KAAK,UAAU,CAAC,EAAE;AACvC,YAAI,MAAM,OAAO,cAAAA,QAAM,IAAI,UAAU,OAAO,CAAC,EAAE;AAC/C,YAAI,UAAU,SAAS,WAAW;AAChC,cAAI,MAAM;AACV,cAAI,MAAM,OAAO,cAAAA,QAAM,OAAO,2DAA2D,CAAC,EAAE;AAAA,QAC9F;AACA,YAAI,MAAM;AACV,YAAI,MAAM,KAAK,cAAAA,QAAM,KAAK,MAAM,CAAC,EAAE;AACnC,YAAI,MAAM,8BAA8B,cAAAA,QAAM,KAAK,aAAAF,QAAK,SAAS,KAAK,eAAe,CAAC,CAAC,EAAE;AACzF,YAAI,MAAM,oBAAoB,cAAAE,QAAM,KAAK,wBAAwB,CAAC,eAAe;AACjF,YAAI,MAAM,cAAc,cAAAA,QAAM,KAAK,iBAAiB,CAAC,uBAAuB;AAC5E,YAAI,MAAM;AACV,gBAAQ,KAAK,CAAC;AACd;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,QAAQ,mCAAmC;AAAA,IACjD;AAGA,QAAI,MAAM;AAMV,QAAI,QAAQ,gBAAgB;AAC5B,QAAI,MAAM;AAEV,QAAI,gBAAgB;AACpB,QAAI,iBAAiB;AAClB,YAAM,gBAAgB,IAAI,eAAe,OAAO,OAAK,CAAC,EAAE,SAAS,gBAAgB,CAAC;AAClF,sBAAgB,cAAc,KAAK,OAAK,WAAAK,QAAG,WAAW,GAAG,CAAC,MAAM,KAAK,CAAC,WAAAA,QAAG,WAAW,CAAC,CAAC;AAAA,IACzF;AAEA,UAAM,qBAAqB,IAAI,yBAAyB,CAAC,mBAAmB,CAAC;AAC7E,QAAI,cAAc,QAAQ,CAAC,oBAAoB;AAC7C,UAAI,MAAM,KAAK,cAAAL,QAAM,MAAM,QAAG,CAAC,KAAK,cAAAA,QAAM,KAAK,MAAM,sCAAsC,CAAC,EAAE;AAAA,IAChG;AACA,QAAI,MAAM,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,KAAK,cAAAA,QAAM,KAAK,gBAAgB,CAAC,IAAI,cAAAA,QAAM,KAAK,aAAAF,QAAK,SAAS,KAAK,eAAe,CAAC,CAAC,EAAE;AACrH,QAAI,MAAM,KAAK,cAAAE,QAAM,MAAM,QAAG,CAAC,KAAK,cAAAA,QAAM,KAAK,OAAO,CAAC,IAAI,cAAAA,QAAM,KAAK,UAAU,wBAAwB,IAAI,eAAe,CAAC,MAAM,0BAA0B,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE;AACtL,QAAI,MAAM,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,KAAK,cAAAA,QAAM,KAAK,SAAS,CAAC,IAAI,cAAAA,QAAM,KAAK,MAAM,CAAC,EAAE;AACjF,QAAI,MAAM;AACV,QAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,cAAc,CAAC,mDAA8C;AACxF,QAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,cAAc,CAAC,mCAA8B;AACxE,QAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,iBAAiB,CAAC,qCAAgC;AAC7E,QAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,mBAAmB,CAAC,kDAA6C;AAC5F,QAAI,MAAM;AAAA,EACZ,CAAC;AACL;;;AEndA,IAAAM,gBAAkB;AAClB,IAAAC,eAAiB;AAGjB;AALA,IAAAC,eAAA;AAqBA,eAAe,gBACb,YACA,KACgD;AAChD,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,OAAO,QAAQ;AACxC,UAAM,SAAS,IAAI,OAAO,EAAE,KAAK,oBAAoB,WAAW,CAAC;AACjE,UAAM,OAAO,SAAS,IAAI,EAAE,UAAU,aAAAC,QAAK,KAAK,KAAK,YAAY,EAAE,CAAC;AACpE,WAAO,EAAE,IAAI,MAAM,OAAO,KAAK;AAAA,EACjC,SAAS,KAAc;AACrB,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAE3D,QACE,IAAI,SAAS,UAAU,KACvB,IAAI,SAAS,UAAU,KACvB,IAAI,SAAS,SAAS,GACtB;AACA,aAAO,EAAE,IAAI,MAAM,OAAO,KAAK;AAAA,IACjC;AAEA,UAAM,QAAQ,IAAI,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AACnD,WAAO,EAAE,IAAI,OAAO,OAAO,MAAM;AAAA,EACnC;AACF;AAIO,SAAS,sBAAsBC,UAAwB;AAC5D,EAAAA,SACG,QAAQ,QAAQ,EAChB,YAAY,yDAAyD,EACrE,OAAO,YAAY;AAClB,UAAM,MAAM,QAAQ,IAAI;AAExB,QAAI,OAAO,iBAAiB;AAC5B,QAAI,KAAK,iCAA4B;AACrC,QAAI,MAAM;AAEV,UAAM,MAAM,OAAO,GAAG;AACtB,UAAM,SAAwB,CAAC;AAI/B,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,MAAM,IAAI,kBAAkB;AAAA,MAC5B,QAAQ,IAAI,gBACR,UAAU,IAAI,aAAa,KAC3B;AAAA,MACJ,KAAK,IAAI,gBACL,SACA;AAAA,IACN,CAAC;AAID,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,MAAM,IAAI;AAAA,MACV,QAAQ,IAAI,kBACR,0BACA;AAAA,MACJ,KAAK,IAAI,kBACL,SACA;AAAA,IACN,CAAC;AAID,UAAM,YAAY,IAAI,eAAe;AACrC,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,MAAM;AAAA,MACN,QAAQ,YACJ,GAAG,aAAAD,QAAK,SAAS,KAAK,IAAI,cAAc,EAAE,CAAC,KAAK,IAAI,UAAU,MAC9D;AAAA,MACJ,KAAK,YACD,SACA;AAAA,MACJ,MAAM,YACF,SACA;AAAA,IACN,CAAC;AAID,QAAI,IAAI,gBAAgB,QAAQ,WAAW;AACzC,YAAM,YAAY,mBAAmB,IAAI,WAAW;AACpD,YAAM,eAAe,OAAO,IAAI,UAAU;AAC1C,YAAM,iBAAiB,SAAS,IAAI,UAAU;AAC9C,YAAM,UACH,aAAa,gBAAkB,CAAC,aAAa;AAEhD,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ,UACJ,GAAG,eAAe,gBAAgB,eAAe,2BAAsB,IAAI,WAAW,KACtF,WAAW,IAAI,WAAW,aAAa,YAAY,kCAC/C,6BAA6B,cAAc,eAAe,SAAS,QAAQ;AAAA,QACnF,KAAK,UACD,SACA,YACA,mDACA;AAAA,QACJ,MAAM,UACF,SACA,YACA,uEACA;AAAA,MACN,CAAC;AAAA,IACH;AAIA,QAAI,aAAa,IAAI,YAAY;AAC/B,UAAI,cAAc;AAClB,UAAI,kBAAkB;AACtB,UAAI,YAA2B;AAC/B,UAAI;AACF,cAAM,EAAE,wBAAAE,wBAAuB,IAAI,MAAM;AACzC,cAAM,UAAU,WAAW,IAAI,UAAU;AACzC,sBACE,QAAQ,SAAS,UAAU,KAC3B,QAAQ,SAAS,wBAAwB;AAC3C,0BAAkBA,wBAAuB,OAAO;AAAA,MAClD,SAAS,KAAK;AACZ,oBAAY,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MAC7D;AAEA,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,QACP,MAAM,eAAe,CAAC;AAAA,QACtB,QAAQ,YACJ,0BAA0B,SAAS,KACnC,kBACA,0DACA,cACA,gDACA,kDAAkD,aAAAF,QAAK,SAAS,KAAK,IAAI,UAAU,CAAC;AAAA,QACxF,KAAK,mBAAoB,CAAC,eAAe,CAAC,YACtC,4DACA;AAAA,MACN,CAAC;AAAA,IACH;AAIA,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,MAAM,CAAC,IAAI;AAAA,MACX,QAAQ,IAAI,wBACR;AAAA,EAAiC,IAAI,eAAe,IAAI,CAAC,MAAM,UAAU,aAAAA,QAAK,SAAS,KAAK,CAAC,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KAC5G;AAAA,MACJ,KAAK,IAAI,wBACL,mCACA;AAAA,MACJ,MAAM,IAAI,wBACN,gGACA;AAAA,IACN,CAAC;AAID,QAAI,aAAa,IAAI,eAAe;AAClC,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AAIA,UAAM,YAAY,IAAI,gBAAgB,QAAQ,IAAI,eAAe;AACjE,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,MAAM;AAAA,MACN,QAAQ,YACJ,IAAI,IAAI,WAAW,iCACnB,IAAI,gBAAgB,OACpB,IAAI,IAAI,WAAW,gDACnB;AAAA,MACJ,KAAK,YAAY,SAAY;AAAA,IAC/B,CAAC;AAMD,UAAM,mBAAmB,OAAO,MAAM,CAAC,MAAM,EAAE,IAAI;AACnD,QAAI,aAAa,IAAI,cAAc,IAAI,mBAAmB,kBAAkB;AAC1E,UAAI,KAAK,kCAA6B;AACtC,YAAM,QAAQ,MAAM,gBAAgB,IAAI,YAAY,GAAG;AAEvD,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,QACP,MAAM,MAAM;AAAA,QACZ,QAAQ,MAAM,KACV,sCACA,MAAM,SAAS;AAAA,QACnB,KAAK,MAAM,KACP,SACA,mBAAmB,aAAAA,QAAK,SAAS,KAAK,IAAI,UAAU,CAAC;AAAA,QACzD,MAAM,MAAM,KACR,SACA;AAAA,MACN,CAAC;AAAA,IACH;AAGA;AACE,UAAI,UAAU;AACd,UAAI,eAA8B;AAClC,UAAI;AACF,cAAM,EAAE,eAAAG,eAAc,IAAI,MAAM,OAAO,QAAQ;AAC/C,cAAM,MAAMA,eAAc,aAAAH,QAAK,KAAK,KAAK,cAAc,CAAC;AACxD,cAAM,UAAU,IAAI,QAAQ,uCAAuC;AACnE,cAAM,MAAM,KAAK;AAAA,WACd,MAAM,OAAO,IAAI,GAAG,aAAa,SAAS,OAAO;AAAA,QACpD;AACA,uBAAe,IAAI,WAAW;AAC9B,kBAAU;AAAA,MACZ,QAAQ;AAAA,MAER;AAEA,UAAI,CAAC,SAAS;AAEZ,YAAI;AACF,gBAAM,UAAU,aAAAA,QAAK;AAAA,YACnB,IAAI,IAAID,aAAY,GAAG,EAAE,SAAS,QAAQ,kBAAkB,IAAI;AAAA,UAClE;AACA,gBAAM,UAAU,aAAAC,QAAK,KAAK,SAAS,0DAA0D;AAC7F,eAAK,MAAM,OAAO,IAAI,GAAG,WAAW,OAAO,GAAG;AAC5C,sBAAU;AAAA,UACZ;AAAA,QACF,QAAQ;AAAA,QAAa;AAAA,MACvB;AAEA,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ,UACJ,QAAQ,eAAe,KAAK,YAAY,KAAK,EAAE,KAC/C;AAAA,QACJ,KAAK,UACD,SACA;AAAA,QACJ,MAAM,UACF,SACA;AAAA,MACN,CAAC;AAAA,IACH;AAGA;AACE,UAAI,WAAW;AACf,UAAI,gBAA+B;AACnC,UAAI;AACF,cAAM,EAAE,eAAAG,eAAc,IAAI,MAAM,OAAO,QAAQ;AAC/C,cAAM,MAAMA,eAAc,aAAAH,QAAK,KAAK,KAAK,cAAc,CAAC;AACxD,cAAM,UAAU,IAAI,QAAQ,wCAAwC;AACpE,cAAM,MAAM,KAAK;AAAA,WACd,MAAM,OAAO,IAAI,GAAG,aAAa,SAAS,OAAO;AAAA,QACpD;AACA,wBAAgB,IAAI,WAAW;AAC/B,mBAAW;AAAA,MACb,QAAQ;AAAA,MAER;AAEA,YAAM,cAAc,MAAM;AACxB,YAAI;AACF,gBAAM,EAAE,YAAY,IAAI,QAAQ,IAAI;AACpC,gBAAM,QAAQ,YAAY,GAAG;AAC7B,iBAAO,MAAM,KAAK,CAAC,MAAc,EAAE,SAAS,KAAK,KAAK,EAAE,SAAS,MAAM,CAAC;AAAA,QAC1E,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF,GAAG;AAEH,UAAI,CAAC,YAAY,YAAY;AAC3B,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,KAAK;AAAA,UACL,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,IACF;AAIA,QAAI,QAAQ,aAAa;AAEzB,QAAI,YAAY;AAChB,eAAW,SAAS,QAAQ;AAC1B,YAAM,OAAO,MAAM,OAAO,cAAAI,QAAM,MAAM,QAAG,IAAI,cAAAA,QAAM,IAAI,QAAG;AAC1D,YAAM,QAAQ,MAAM,OAChB,cAAAA,QAAM,MAAM,MAAM,KAAK,IACvB,cAAAA,QAAM,IAAI,KAAK,MAAM,KAAK;AAE9B,UAAI,MAAM,KAAK,IAAI,KAAK,KAAK,EAAE;AAC/B,UAAI,MAAM,UAAU,cAAAA,QAAM,KAAK,MAAM,MAAM,CAAC,EAAE;AAE9C,UAAI,CAAC,MAAM,MAAM;AACf,oBAAY;AACZ,YAAI,MAAM,KAAK;AACb,cAAI,MAAM,UAAU,cAAAA,QAAM,KAAK,aAAQ,CAAC,IAAI,cAAAA,QAAM,OAAO,MAAM,GAAG,CAAC,EAAE;AAAA,QACvE;AACA,YAAI,MAAM,MAAM;AACd,cAAI,MAAM,UAAU,cAAAA,QAAM,KAAK,MAAM,IAAI,CAAC,EAAE;AAAA,QAC9C;AAAA,MACF;AAEA,UAAI,MAAM;AAAA,IACZ;AAEA,QAAI,QAAQ;AACZ,QAAI,MAAM;AAEV,QAAI,WAAW;AACb,UAAI,MAAM,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,KAAK,cAAAA,QAAM,KAAK,MAAM,2CAA2C,CAAC,EAAE;AACnG,UAAI,MAAM;AACV,UAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,cAAc,CAAC,qBAAqB;AAC/D,UAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,cAAc,CAAC,gCAAgC;AAAA,IAC5E,OAAO;AACL,UAAI,MAAM,6CAA6C;AACvD,UAAI,MAAM;AAGV,YAAM,uBAAuB,OAAO;AAAA,QAClC,CAAC,MAAM,EAAE,UAAU,0CAA0C,CAAC,EAAE;AAAA,MAClE;AACA,YAAM,gBAAgB,OAAO;AAAA,QAC3B,CAAC,MAAM,EAAE,UAAU,2BAA2B,CAAC,EAAE;AAAA,MACnD;AACA,YAAM,gBAAgB,OAAO;AAAA,QAC3B,CAAC,MAAM,EAAE,UAAU,sCAAsC,CAAC,EAAE;AAAA,MAC9D;AAEA,UAAI,eAAe;AACjB,YAAI;AAAA,UACF,iDAAiD,cAAAA,QAAM,KAAK,iBAAiB,CAAC;AAAA,QAChF;AAAA,MACF,WAAW,iBAAiB,sBAAsB;AAChD,YAAI;AAAA,UACF,SAAS,cAAAA,QAAM,KAAK,eAAe,CAAC;AAAA,QACtC;AAAA,MACF,OAAO;AACL,YAAI;AAAA,UACF,SAAS,cAAAA,QAAM,KAAK,yBAAyB,CAAC;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM;AACV,YAAQ,KAAK,YAAY,IAAI,CAAC;AAAA,EAChC,CAAC;AACL;;;AC9XA,qBAAuB;AACvB,IAAAC,gBAAkB;AAElB;AAaA,IAAAC,eAAiB;AAEV,SAAS,sBAAsBC,UAAwB;AAC5D,EAAAA,SACG,QAAQ,QAAQ,EAChB,YAAY,yEAAyE,EACrF,OAAO,YAAY;AAClB,UAAM,MAAM,QAAQ,IAAI;AAExB,QAAI,OAAO,iBAAiB;AAC5B,QAAI,MAAM;AAEV,UAAM,SAAS,UAAM,uBAAe;AAAA,MAClC,SAAS;AAAA,MACT,SAAS;AAAA,QACP;AAAA,UACE,MAAM,GAAG,cAAAC,QAAM,MAAM,aAAa,CAAC;AAAA,UACnC,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,MAAM,GAAG,cAAAA,QAAM,OAAO,QAAQ,CAAC;AAAA,UAC/B,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,MAAM,GAAG,cAAAA,QAAM,IAAI,UAAU,CAAC;AAAA,UAC9B,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,MAAM;AACV,QAAI,KAAK,oBAAoB,cAAAA,QAAM,KAAK,MAAM,CAAC,EAAE;AAEjD,UAAM,MAAM,OAAO,GAAG;AACtB,UAAM,UACH,IAAI,gBAAgB,QAAQ,IAAI,eAAe,KAChD,OAAO,IAAI,UAAU;AAEvB,QAAI,IAAI,eAAe,QAAQ;AAE7B,YAAM,aAAa,UACf,aAAAC,QAAK,KAAK,KAAK,mBAAmB,IAClC,aAAAA,QAAK,KAAK,KAAK,cAAc;AAEjC,YAAM,UAAU,UACZ,mBAAmB,MAAM,IACzB,qBAAqB,MAAM;AAE/B,kBAAY,YAAY,OAAO;AAC/B,UAAI,QAAQ,WAAW,cAAAD,QAAM,MAAM,aAAAC,QAAK,SAAS,KAAK,UAAU,CAAC,CAAC,SAAS,cAAAD,QAAM,KAAK,MAAM,CAAC,SAAS;AAAA,IACxG,OAAO;AACL,YAAM,aAAa,IAAI;AACvB,YAAM,aAAa,aAAa,UAAU;AAC1C,UAAI,KAAK,oBAAe,cAAAA,QAAM,KAAK,aAAAC,QAAK,SAAS,KAAK,UAAU,CAAC,CAAC,EAAE;AAEpE,YAAM,WAAW,WAAW,UAAU;AACtC,YAAM,aAAa,OAAO,IAAI,UAAU,IACpC,gBAAgB,UAAU,MAAM,IAChC,kBAAkB,UAAU,MAAM;AAEtC,YAAM,UAAU,OAAO,IAAI,UAAU,IACjC,iBAAiB,YAAY,MAAM,IACnC,mBAAmB,YAAY,MAAM;AAEzC,UAAI,YAAY,UAAU;AACxB,YAAI,KAAK,mEAAmE;AAAA,MAC9E,OAAO;AACL,oBAAY,YAAY,OAAO;AAC/B,YAAI,QAAQ,WAAW,cAAAD,QAAM,MAAM,aAAAC,QAAK,SAAS,KAAK,UAAU,CAAC,CAAC,OAAO,cAAAD,QAAM,KAAK,MAAM,CAAC,SAAS;AAAA,MACtG;AAAA,IACF;AAEA,QAAI,MAAM;AACV,QAAI,QAAQ,gBAAgB;AAE5B,UAAM,gBAAwE;AAAA,MAC5E,aAAa;AAAA,QACX,EAAE,MAAM,kBAAkB,OAAO,cAAAA,QAAM,IAAI,OAAO,EAAE;AAAA,QACpD,EAAE,MAAM,uBAAuB,OAAO,cAAAA,QAAM,IAAI,OAAO,EAAE;AAAA,QACzD,EAAE,MAAM,uBAAuB,OAAO,cAAAA,QAAM,IAAI,OAAO,EAAE;AAAA,QACzD,EAAE,MAAM,mBAAmB,OAAO,cAAAA,QAAM,IAAI,OAAO,EAAE;AAAA,QACrD,EAAE,MAAM,sBAAsB,OAAO,cAAAA,QAAM,OAAO,MAAM,EAAE;AAAA,QAC1D,EAAE,MAAM,2BAA2B,OAAO,cAAAA,QAAM,OAAO,MAAM,EAAE;AAAA,QAC/D,EAAE,MAAM,oBAAoB,OAAO,cAAAA,QAAM,OAAO,MAAM,EAAE;AAAA,QACxD,EAAE,MAAM,kBAAa,OAAO,cAAAA,QAAM,KAAK,MAAM,EAAE;AAAA,MACjD;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,MAAM,gBAAgB,OAAO,cAAAA,QAAM,IAAI,OAAO,EAAE;AAAA,MACpD;AAAA,MACA,UAAU;AAAA,QACR,EAAE,MAAM,uBAAuB,OAAO,cAAAA,QAAM,IAAI,OAAO,EAAE;AAAA,QACzD,EAAE,MAAM,mBAAmB,OAAO,cAAAA,QAAM,IAAI,OAAO,EAAE;AAAA,QACrD,EAAE,MAAM,wBAAwB,OAAO,cAAAA,QAAM,IAAI,OAAO,EAAE;AAAA,QAC1D,EAAE,MAAM,yBAAyB,OAAO,cAAAA,QAAM,OAAO,MAAM,EAAE;AAAA,QAC7D,EAAE,MAAM,2BAA2B,OAAO,cAAAA,QAAM,OAAO,MAAM,EAAE;AAAA,QAC/D,EAAE,MAAM,uBAAuB,OAAO,cAAAA,QAAM,OAAO,MAAM,EAAE;AAAA,MAC7D;AAAA,IACF;AAEA,eAAW,EAAE,MAAM,MAAM,KAAK,cAAc,MAAM,GAAG;AACnD,UAAI,MAAM,OAAO,cAAAA,QAAM,KAAK,QAAG,CAAC,IAAI,cAAAA,QAAM,MAAM,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,KAAK,EAAE;AAAA,IAC5E;AAEA,QAAI,MAAM;AACV,QAAI,KAAK,OAAO,cAAAA,QAAM,KAAK,cAAc,CAAC,sCAAsC;AAChF,QAAI,MAAM;AAAA,EACZ,CAAC;AACL;;;AC3HA,IAAAE,gBAAkB;AAElB;AAUA,IAAAC,gBAAiB;AAEjB,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,sBAAsBC,UAAwB;AAC5D,EAAAA,SACG,QAAQ,QAAQ,EAChB,YAAY,6EAA6E,EACzF,OAAO,MAAM;AACZ,UAAM,MAAM,QAAQ,IAAI;AAExB,QAAI,OAAO,iBAAiB;AAC5B,QAAI,MAAM;AACV,QAAI,QAAQ,iBAAiB;AAE7B,eAAW,KAAK,iBAAiB;AAC/B,UAAI,MAAM,OAAO,cAAAC,QAAM,KAAK,QAAG,CAAC,IAAI,cAAAA,QAAM,OAAO,CAAC,CAAC,EAAE;AAAA,IACvD;AAEA,QAAI,MAAM;AAEV,UAAM,MAAM,OAAO,GAAG;AAEtB,QAAI,IAAI,eAAe,QAAQ;AAE7B,YAAM,UAAU,IAAI,gBAAgB,QAAQ,IAAI,eAAe;AAC/D,YAAM,aAAa,UACf,cAAAC,QAAK,KAAK,KAAK,mBAAmB,IAClC,cAAAA,QAAK,KAAK,KAAK,cAAc;AAEjC,YAAM,UAAU,UACZ,mBAAmB,aAAa,IAChC,qBAAqB,aAAa;AAEtC,kBAAY,YAAY,OAAO;AAC/B,UAAI,QAAQ,oCAA+B,cAAAD,QAAM,MAAM,cAAAC,QAAK,SAAS,KAAK,UAAU,CAAC,CAAC,wBAAwB;AAAA,IAChH,OAAO;AACL,YAAM,aAAa,IAAI;AACvB,YAAM,aAAa,aAAa,UAAU;AAC1C,UAAI,KAAK,oBAAe,cAAAD,QAAM,KAAK,cAAAC,QAAK,SAAS,KAAK,UAAU,CAAC,CAAC,EAAE;AAEpE,YAAM,WAAW,WAAW,UAAU;AACtC,YAAM,UAAU,OAAO,IAAI,UAAU,IACjC,uBAAuB,QAAQ,IAC/B,yBAAyB,QAAQ;AAErC,UAAI,YAAY,UAAU;AACxB,YAAI,KAAK,mEAA8D;AAAA,MACzE,OAAO;AACL,oBAAY,YAAY,OAAO;AAC/B,YAAI,QAAQ,WAAW,cAAAD,QAAM,MAAM,cAAAC,QAAK,SAAS,KAAK,UAAU,CAAC,CAAC,uBAAuB;AAAA,MAC3F;AAAA,IACF;AAEA,QAAI,MAAM;AACV,QAAI,KAAK,kEAAkE;AAC3E,QAAI,KAAK,OAAO,cAAAD,QAAM,KAAK,cAAc,CAAC,6BAA6B;AACvE,QAAI,MAAM;AAAA,EACZ,CAAC;AACL;;;AC9EA,IAAAE,aAAe;AACf,IAAAC,gBAAiB;AACjB,IAAAC,iBAAkB;AAClB,IAAAC,cAAgB;AAIhB,IAAM,gBAAgB;AA4BtB,SAAS,aACP,QACA,QACA,MACA,KACQ;AACR,QAAM,UAA2B,OAAO,MAAM,IAAI,CAAC,OAAO;AAAA,IACxD,UAAU,EAAE;AAAA,IACZ,QAAQ,EAAE,OAAO,IAAI,CAAC,OAAO;AAAA,MAC3B,QAAQ,EAAE;AAAA,MACV,SAAS,EAAE;AAAA,MACX,MAAM,EAAE;AAAA,MACR,QAAQ,EAAE;AAAA,IACZ,EAAE;AAAA,EACJ,EAAE;AAEF,QAAM,WAAyB;AAAA,IAC7B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,IACA,aAAa,OAAO;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,eAAe,cAAAC,QAAK,KAAK,KAAK,aAAa;AACjD,aAAAC,QAAG,cAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;AACzE,SAAO;AACT;AAEA,SAAS,aAAa,KAAkC;AACtD,QAAM,eAAe,cAAAD,QAAK,KAAK,KAAK,aAAa;AACjD,MAAI,CAAC,WAAAC,QAAG,WAAW,YAAY,EAAG,QAAO;AACzC,MAAI;AACF,UAAM,MAAM,WAAAA,QAAG,aAAa,cAAc,OAAO;AACjD,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIA,SAAS,SAAS,UAAkB,OAAgC;AAClE,SAAO,GAAG,QAAQ,KAAK,MAAM,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,MAAM,KAAK,MAAM,OAAO;AACvF;AAEA,SAAS,eAAe,UAAkB,OAAgC;AACxE,SAAO,GAAG,QAAQ,KAAK,MAAM,MAAM,KAAK,MAAM,OAAO;AACvD;AAEA,SAAS,iBAAiB,UAAwB,MAAmC;AACnF,QAAM,QAAQ,SAAS,WAAW,iBAAiB;AACnD,QAAM,MAAM,oBAAI,IAAc;AAC9B,aAAW,SAAS,SAAS,SAAS;AACpC,eAAW,SAAS,MAAM,QAAQ;AAChC,UAAI,IAAI,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,IACtC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,iBACP,QACA,aACA,MACW;AACX,QAAM,QAAQ,SAAS,WAAW,iBAAiB;AACnD,QAAM,WAA+B,CAAC;AACtC,MAAI,cAAc;AAClB,MAAI,gBAAgB;AACpB,QAAM,gBAAgB,oBAAI,IAAoB;AAE9C,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,YAAY,KAAK,OAAO;AAAA,MAC5B,CAAC,MAAM,CAAC,YAAY,IAAI,MAAM,KAAK,UAAU,CAAC,CAAC;AAAA,IACjD;AACA,QAAI,UAAU,WAAW,EAAG;AAE5B,UAAM,aAAa,UAAU,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE;AAC7D,UAAM,eAAe,UAAU,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE;AAC/D,mBAAe;AACf,qBAAiB;AAEjB,eAAW,SAAS,WAAW;AAC7B,oBAAc;AAAA,QACZ,MAAM;AAAA,SACL,cAAc,IAAI,MAAM,MAAM,KAAK,KAAK;AAAA,MAC3C;AAAA,IACF;AAEA,aAAS,KAAK,EAAE,GAAG,MAAM,QAAQ,WAAW,YAAY,aAAa,CAAC;AAAA,EACxE;AAEA,QAAM,WAAW,CAAC,GAAG,QAAQ,EAC1B,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,SAAS,EAAE,OAAO,MAAM,EAChD,MAAM,GAAG,EAAE,EACX,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,OAAO,EAAE,OAAO,OAAO,EAAE;AAE5D,SAAO;AAAA,IACL,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,aAAa,cAAc;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,YAAY,OAAO;AAAA,EACrB;AACF;AAIO,SAAS,wBAAwBC,UAAwB;AAC9D,EAAAA,SACG,QAAQ,UAAU,EAClB,YAAY,mEAAmE,EAC/E,OAAO,UAAU,wCAAwC,EACzD,OAAO,WAAW,qDAAqD,EACvE,OAAO,iBAAiB,wCAAwC,QAAQ,EACxE,OAAO,gBAAgB,qBAAqB,GAAG,EAC/C,OAAO,mBAAmB,2CAA2C,aAAa,EAClF,OAAO,OAAO,SAMT;AACJ,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,SAAU,KAAK,UAAqB;AAC1C,UAAM,OAAQ,KAAK,QAAyB;AAE5C,QAAI,SAAS,YAAY,SAAS,UAAU;AAC1C,UAAI,MAAM,uCAAuC;AACjD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI,OAAO,mBAAmB;AAC9B,QAAI,MAAM;AAGV,UAAM,mBAAmB,aAAa,GAAG;AACzC,UAAM,SAAS,KAAK,SAAS,CAAC,oBAAoB,CAAC,KAAK;AACxD,UAAM,UAAU,KAAK,UAAU,qBAAqB,QAAQ,CAAC,KAAK;AAElE,QAAI,QAAQ;AACV,UAAI,KAAK,yCAAoC;AAC7C,YAAM,cAAU,YAAAC,SAAI,EAAE,MAAM,0BAAqB,OAAO,OAAO,CAAC,EAAE,MAAM;AAExE,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,UAAU,EAAE,QAAQ,YAAY,KAAK,KAAK,CAAC;AAC1D,gBAAQ,KAAK;AAAA,MACf,SAAS,KAAc;AACrB,gBAAQ,KAAK;AACb,YAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC1D,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,eAAe,aAAa,QAAS,QAAQ,MAAM,GAAG;AAC5D,UAAI;AAAA,QACF,yBAAoB,eAAAC,QAAM,MAAM,cAAAJ,QAAK,SAAS,KAAK,YAAY,CAAC,CAAC;AAAA,MACnE;AACA,UAAI,KAAK,KAAK,OAAQ,WAAW,qBAAqB,OAAQ,WAAW,YAAY,OAAQ,aAAa,YAAY;AACtH,UAAI,KAAK,aAAa,eAAAI,QAAM,KAAK,MAAM,CAAC,EAAE;AAC1C,UAAI,KAAK,WAAW,eAAAA,QAAM,KAAK,IAAI,CAAC,EAAE;AACtC,UAAI,MAAM;AACV,UAAI,KAAK,oBAAoB,eAAAA,QAAM,KAAK,2BAA2B,IAAI,6BAA6B;AACpG,UAAI,KAAK,SAAS,eAAAA,QAAM,MAAM,aAAa,IAAI,2DAA2D;AAC1G,UAAI,MAAM;AACV;AAAA,IACF;AAEA,QAAI,SAAS;AACX,UAAI,CAAC,kBAAkB;AACrB,YAAI,MAAM,wBAAwB,eAAAA,QAAM,MAAM,aAAa,CAAC,EAAE;AAC9D,YAAI,KAAK,OAAO,eAAAA,QAAM,KAAK,0BAA0B,CAAC,uBAAuB;AAC7E,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,eAAe,IAAI,KAAK,iBAAiB,SAAS,EAAE,eAAe;AACzE,UAAI,KAAK,kBAAkB,eAAAA,QAAM,KAAK,YAAY,CAAC,EAAE;AACrD,UAAI,KAAK,oBAAoB,eAAAA,QAAM,KAAK,iBAAiB,MAAM,CAAC,EAAE;AAClE,UAAI,KAAK,kBAAkB,eAAAA,QAAM,KAAK,iBAAiB,QAAQ,QAAQ,CAAC,EAAE;AAC1E,UAAI,KAAK,oBAAoB,eAAAA,QAAM,KAAK,iBAAiB,WAAW,CAAC,EAAE;AACvE,UAAI,MAAM;AAEV,YAAM,cAAU,YAAAD,SAAI,EAAE,MAAM,iCAA4B,OAAO,OAAO,CAAC,EAAE,MAAM;AAE/E,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,UAAU,EAAE,QAAQ,YAAY,KAAK,KAAK,CAAC;AAC1D,gBAAQ,KAAK;AAAA,MACf,SAAS,KAAc;AACrB,gBAAQ,KAAK;AACb,YAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC1D,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,cAAc,iBAAiB,QAAQ;AAC7C,YAAM,cAAc,iBAAiB,kBAAmB,WAAW;AACnE,YAAM,YAAY,iBAAiB,QAAS,aAAa,WAAW;AAEpE,UAAI,UAAU,gBAAgB,GAAG;AAC/B,YAAI,QAAQ,sCAAiC;AAC7C,YAAI;AAAA,UACF,sBAAsB,OAAQ,WAAW;AAAA,QAC3C;AACA,YAAI,MAAM;AACV,gBAAQ,KAAK,CAAC;AACd;AAAA,MACF;AAEA,UAAI;AAAA,QACF,eAAAC,QAAM,KAAK,IAAI,aAAQ,UAAU,WAAW,aAAa,UAAU,gBAAgB,IAAI,MAAM,EAAE,iBAAiB;AAAA,MAClH;AACA,UAAI,MAAM;AAGV,UAAI,UAAU,cAAc,OAAO,GAAG;AACpC,YAAI,QAAQ,oBAAoB;AAChC,mBAAW,CAAC,MAAM,KAAK,KAAK,CAAC,GAAG,UAAU,cAAc,QAAQ,CAAC,EAAE;AAAA,UACjE,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,QACtB,GAAG;AACD,cAAI,KAAK,MAAM,KAAK;AAAA,QACtB;AAAA,MACF;AAGA,UAAI,UAAU,MAAM,SAAS,GAAG;AAC9B,YAAI,QAAQ,oBAAoB;AAChC,YAAI,MAAM;AACV,mBAAW,QAAQ,UAAU,OAAO;AAClC,cAAI;AAAA,YACF,KAAK,eAAAA,QAAM,KAAK,MAAM,KAAK,QAAQ,CAAC,MAClC,eAAAA,QAAM,KAAK,IAAI,KAAK,OAAO,MAAM,OAAO;AAAA,UAC5C;AACA,qBAAW,SAAS,KAAK,QAAQ;AAC/B,gBAAI,MAAM,MAAM,SAAS,MAAM,UAAU,MAAM,MAAM,MAAM,MAAM;AAAA,UACnE;AAAA,QACF;AAAA,MACF;AAEA,UAAI,MAAM;AACV,UAAI,QAAQ;AACZ,UAAI,MAAM;AACV,UAAI;AAAA,QACF,GAAG,UAAU,WAAW,aAAa,UAAU,gBAAgB,IAAI,MAAM,EAAE;AAAA,MAC7E;AACA,UAAI,KAAK,OAAO,eAAAA,QAAM,KAAK,0BAA0B,CAAC,4CAA4C;AAClG,UAAI,MAAM;AACV,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;;;AChSA,IAAAC,aAAe;AACf,IAAAC,gBAAiB;AACjB,IAAAC,iBAAkB;AAClB,IAAAC,kBAAkC;AAkBlC,IAAM,kBAAkD;AAAA,EACtD,kBAAkB;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,iBAAiC,CAAC,kBAAkB,SAAS,YAAY,SAAS;AAIxF,SAAS,uBAA+B;AACtC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUT;AAEA,SAAS,eAAuB;AAC9B,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeT;AAEA,SAAS,kBAA0B;AACjC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBT;AAEA,SAAS,iBAAyB;AAChC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAMT;AAGA,IAAM,cAA+C;AAAA,EACnD,kBAAkB;AAAA,EAClB,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AACX;AAEA,SAAS,YAAY,YAAoC;AACvD,SAAO,WAAW,IAAI,CAAC,QAAQ,YAAY,GAAG,EAAE,CAAC,EAAE,KAAK,MAAM;AAChE;AAEA,SAAS,2BAAmC;AAC1C,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAMT;AAEA,SAAS,yBAAiC;AACxC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAMT;AAEA,SAAS,0BAAkC;AACzC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAMT;AAIA,SAAS,mBAAmB,SAAiB,YAAoC;AAC/E,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQP,yBAAyB,CAAC;AAAA;AAAA,EAE1B,YAAY,UAAU,CAAC;AAAA;AAAA;AAAA,uCAGc,OAAO;AAAA;AAAA;AAG9C;AAIA,SAAS,sBAA8B;AACrC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaT;AAEA,SAAS,qBAA6B;AACpC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBT;AAEA,SAAS,wBAAgC;AACvC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBT;AAEA,SAAS,uBAA+B;AACtC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAST;AAEA,IAAM,qBAAyD;AAAA,EAC7D,kBAAkB;AAAA,EAClB,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AACX;AAEA,SAAS,mBAAmB,SAAiB,YAAoC;AAC/E,QAAM,WAAW,WAAW,IAAI,CAAC,QAAQ,mBAAmB,GAAG,EAAE,CAAC,EAAE,KAAK,MAAM;AAE/E,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASP,uBAAuB,CAAC;AAAA;AAAA,EAExB,QAAQ;AAAA;AAAA;AAAA,6CAGmC,OAAO;AAAA;AAAA;AAGpD;AAIA,SAAS,gBAAgB,YAAoC;AAC3D,QAAM,QAAkB,CAAC;AAEzB,MAAI,WAAW,SAAS,gBAAgB,GAAG;AACzC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW,SAAS,OAAO,GAAG;AAChC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW,SAAS,UAAU,GAAG;AACnC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW,SAAS,SAAS,GAAG;AAClC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,MAAM,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI;AAC7C;AAEA,SAAS,eAAe,YAAoC;AAC1D,QAAM,UAAoB,CAAC;AAE3B,MAAI,WAAW,SAAS,OAAO,GAAG;AAChC,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAOV;AAEH,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAOV;AAAA,EACL;AAEA,MAAI,WAAW,SAAS,gBAAgB,GAAG;AACzC,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAOV;AAAA,EACL;AAEA,MAAI,WAAW,SAAS,UAAU,GAAG;AACnC,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAOV;AAEH,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAOV;AAAA,EACL;AAEA,SAAO,QAAQ,KAAK,MAAM;AAC5B;AAEA,SAAS,oBAAoB,SAAiB,YAAoC;AAChF,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQP,wBAAwB,CAAC;AAAA;AAAA;AAAA;AAAA,EAIzB,gBAAgB,UAAU,CAAC;AAAA;AAAA;AAAA;AAAA,EAI3B,eAAe,UAAU,CAAC;AAAA;AAAA;AAAA,uCAGW,OAAO;AAAA;AAAA;AAG9C;AAIA,IAAM,SAAwB;AAAA,EAC5B;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,UAAU,cAAAC,QAAK,KAAK,WAAW,yBAAyB;AAAA,IACxD,UAAU;AAAA,EACZ;AACF;AAIA,SAASC,mBAAkB,KAAqB;AAC9C,MAAI;AACF,UAAM,UAAU,cAAAD,QAAK,KAAK,KAAK,gBAAgB,0BAA0B,cAAc;AACvF,QAAI,WAAAE,QAAG,WAAW,OAAO,GAAG;AAC1B,YAAM,MAAM,KAAK,MAAM,WAAAA,QAAG,aAAa,SAAS,OAAO,CAAC;AACxD,UAAI,IAAI,QAAS,QAAO,IAAI;AAAA,IAC9B;AAAA,EACF,QAAQ;AAAA,EAAqB;AAE7B,MAAI;AACF,UAAM,UAAU,cAAAF,QAAK,KAAK,KAAK,cAAc;AAC7C,QAAI,WAAAE,QAAG,WAAW,OAAO,GAAG;AAC1B,YAAM,MAAM,KAAK,MAAM,WAAAA,QAAG,aAAa,SAAS,OAAO,CAAC;AACxD,UAAI,IAAI,QAAS,QAAO,IAAI;AAAA,IAC9B;AAAA,EACF,QAAQ;AAAA,EAAqB;AAE7B,SAAO;AACT;AAEA,SAAS,gBAAgB,KAAyC;AAChE,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAQ,IAAI,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC;AAC9D,QAAM,QAAwB,CAAC;AAC/B,aAAW,QAAQ,OAAO;AACxB,QAAI,QAAQ,iBAAiB;AAC3B,YAAM,KAAK,IAAoB;AAAA,IACjC;AAAA,EACF;AACA,SAAO,MAAM,SAAS,IAAI,QAAQ;AACpC;AA6BO,SAAS,2BAA2BC,UAAwB;AACjE,EAAAA,SACG,QAAQ,cAAc,EACtB;AAAA,IACC;AAAA,EAEF,EACC,OAAO,aAAa,6CAA6C,EACjE,OAAO,WAAW,yCAAyC,EAC3D,OAAO,aAAa,qDAAqD,EACzE,OAAO,wBAAwB,mEAAmE,EAClG,OAAO,OAAO,SAKT;AACJ,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,UAAUC,mBAAkB,GAAG;AACrC,UAAM,aAAa,gBAAgB,KAAK,KAAK;AAC7C,UAAM,WAAW,KAAK,WAAW;AACjC,UAAM,UAAU,KAAK,UAAU;AAE/B,QAAI,OAAO,uBAAuB;AAElC,QAAI,UAAU;AACZ,UAAI,MAAM,KAAK,eAAAC,QAAM,OAAO,iDAAuC,CAAC,EAAE;AACtE,UAAI,MAAM;AAAA,IACZ;AAIA,QAAI;AAEJ,QAAI,KAAK,KAAK;AACZ,uBAAiB,CAAC,GAAG,MAAM;AAAA,IAC7B,OAAO;AACL,UAAI;AACJ,UAAI;AACF,mBAAW,UAAM,0BAAS;AAAA,UACxB,SAAS;AAAA,UACT,SAAS;AAAA,YACP,EAAE,MAAM,mCAAmC,OAAO,SAAS;AAAA,YAC3D,EAAE,MAAM,iCAAiC,OAAO,SAAS;AAAA,YACzD,EAAE,MAAM,4DAA4D,OAAO,UAAU;AAAA,YACrF,EAAE,MAAM,+CAA+C,OAAO,MAAM;AAAA,UACtE;AAAA,UACA,UAAU;AAAA,QACZ,CAAC;AAAA,MACH,QAAQ;AACN,YAAI,KAAK,qCAAqC;AAC9C;AAAA,MACF;AAEA,UAAI,SAAS,WAAW,GAAG;AACzB,YAAI,KAAK,4DAA4D;AACrE;AAAA,MACF;AAEA,UAAI,SAAS,SAAS,KAAK,GAAG;AAC5B,yBAAiB,CAAC,GAAG,MAAM;AAAA,MAC7B,OAAO;AACL,yBAAiB,OAAO,OAAO,CAAC,MAAM,SAAS,SAAS,EAAE,EAAE,CAAC;AAAA,MAC/D;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,eAAAA,QAAM,KAAK,WAAW,KAAK,IAAI,CAAC,CAAC,EAAE;AAC3D,QAAI,KAAK,YAAY,eAAAA,QAAM,KAAK,OAAO,CAAC,EAAE;AAC1C,QAAI,MAAM;AAIV,UAAM,UAAyE,CAAC;AAEhF,eAAW,SAAS,gBAAgB;AAClC,YAAM,WAAW,cAAAC,QAAK,KAAK,KAAK,MAAM,QAAQ;AAC9C,YAAM,SAAS,WAAAC,QAAG,WAAW,QAAQ;AAErC,UAAI,UAAU,CAAC,WAAW,CAAC,UAAU;AAEnC,cAAM,YAAY,UAAM,yBAAQ;AAAA,UAC9B,SAAS,GAAG,MAAM,QAAQ;AAAA,UAC1B,SAAS;AAAA,QACX,CAAC;AAED,YAAI,CAAC,WAAW;AACd,kBAAQ,KAAK,EAAE,MAAM,MAAM,UAAU,QAAQ,UAAU,CAAC;AACxD;AAAA,QACF;AAAA,MACF;AAEA,YAAM,UAAU,MAAM,SAAS,SAAS,UAAU;AAElD,UAAI,UAAU;AACZ,YAAI,QAAQ,YAAY,MAAM,QAAQ,EAAE;AACxC,YAAI,MAAM,eAAAF,QAAM,KAAK,SAAI,OAAO,EAAE,CAAC,CAAC;AACpC,mBAAW,QAAQ,QAAQ,MAAM,IAAI,EAAE,MAAM,GAAG,EAAE,GAAG;AACnD,cAAI,MAAM,eAAAA,QAAM,KAAK,KAAK,IAAI,EAAE,CAAC;AAAA,QACnC;AACA,YAAI,MAAM,eAAAA,QAAM,KAAK,mBAAmB,CAAC;AACzC,YAAI,MAAM,eAAAA,QAAM,KAAK,SAAI,OAAO,EAAE,CAAC,CAAC;AACpC,YAAI,MAAM;AACV,gBAAQ,KAAK,EAAE,MAAM,MAAM,UAAU,QAAQ,UAAU,CAAC;AACxD;AAAA,MACF;AAGA,YAAM,YAAY,cAAAC,QAAK,QAAQ,QAAQ;AACvC,UAAI,CAAC,WAAAC,QAAG,WAAW,SAAS,GAAG;AAC7B,mBAAAA,QAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,MAC7C;AAEA,iBAAAA,QAAG,cAAc,UAAU,SAAS,OAAO;AAC3C,cAAQ,KAAK,EAAE,MAAM,MAAM,UAAU,QAAQ,UAAU,CAAC;AAAA,IAC1D;AAIA,QAAI,QAAQ,SAAS;AAErB,eAAW,UAAU,SAAS;AAC5B,cAAQ,OAAO,QAAQ;AAAA,QACrB,KAAK;AACH,cAAI,MAAM,KAAK,eAAAF,QAAM,MAAM,QAAG,CAAC,YAAY,eAAAA,QAAM,MAAM,OAAO,IAAI,CAAC,EAAE;AACrE;AAAA,QACF,KAAK;AACH,cAAI,MAAM,KAAK,eAAAA,QAAM,OAAO,QAAG,CAAC,aAAa,eAAAA,QAAM,MAAM,OAAO,IAAI,CAAC,IAAI,eAAAA,QAAM,KAAK,kDAA6C,CAAC,EAAE;AACpI;AAAA,QACF,KAAK;AACH,cAAI,MAAM,KAAK,eAAAA,QAAM,KAAK,WAAI,CAAC,iBAAiB,eAAAA,QAAM,MAAM,OAAO,IAAI,CAAC,EAAE;AAC1E;AAAA,MACJ;AAAA,IACF;AAEA,QAAI,MAAM;AAEV,QAAI,UAAU;AACZ,UAAI,KAAK,gDAA2C;AACpD,UAAI,KAAK,kBAAkB,eAAAA,QAAM,KAAK,WAAW,CAAC,YAAY;AAAA,IAChE,OAAO;AACL,YAAM,eAAe,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE;AACnE,UAAI,eAAe,GAAG;AACpB,YAAI;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM;AAAA,EACZ,CAAC;AACL;;;AC/nBA,IAAAG,cAAe;AACf,IAAAC,gBAAiB;AACjB,IAAAC,cAAgB;AAqChB,IAAM,YAAuE;AAAA,EAC3E,2BAA2B,EAAE,aAAa,8CAA8C,UAAU,cAAc;AAAA,EAChH,+BAA+B,EAAE,aAAa,sCAAsC,UAAU,cAAc;AAAA,EAC5G,iCAAiC,EAAE,aAAa,gDAAgD,UAAU,cAAc;AAAA,EACxH,iCAAiC,EAAE,aAAa,4BAA4B,UAAU,cAAc;AAAA,EACpG,gCAAgC,EAAE,aAAa,wCAAwC,UAAU,kBAAkB;AAAA,EACnH,6BAA6B,EAAE,aAAa,sDAAsD,UAAU,kBAAkB;AAAA,EAC9H,oCAAoC,EAAE,aAAa,uDAAuD,UAAU,kBAAkB;AAAA,EACtI,mCAAmC,EAAE,aAAa,mCAAmC,UAAU,kBAAkB;AAAA,EACjH,+BAA+B,EAAE,aAAa,sCAAsC,UAAU,kBAAkB;AAAA,EAChH,gCAAgC,EAAE,aAAa,kDAAkD,UAAU,WAAW;AAAA,EACtH,4BAA4B,EAAE,aAAa,gDAAgD,UAAU,WAAW;AAAA,EAChH,iCAAiC,EAAE,aAAa,8CAA8C,UAAU,WAAW;AAAA,EACnH,kCAAkC,EAAE,aAAa,oDAAoD,UAAU,WAAW;AAAA,EAC1H,oCAAoC,EAAE,aAAa,mDAAmD,UAAU,WAAW;AAAA,EAC3H,gCAAgC,EAAE,aAAa,mDAAmD,UAAU,WAAW;AAAA,EACvH,kCAAkC,EAAE,aAAa,oDAAoD,UAAU,cAAc;AAAA,EAC7H,qCAAqC,EAAE,aAAa,yDAAyD,UAAU,cAAc;AAAA,EACrI,2BAA2B,EAAE,aAAa,gEAAgE,UAAU,cAAc;AACpI;AAIA,SAAS,eAAe,KAAqB;AAC3C,MAAI;AACF,UAAM,UAAU,cAAAC,QAAK,KAAK,KAAK,cAAc;AAC7C,QAAI,YAAAC,QAAG,WAAW,OAAO,GAAG;AAC1B,YAAM,MAAM,KAAK,MAAM,YAAAA,QAAG,aAAa,SAAS,OAAO,CAAC;AACxD,UAAI,IAAI,KAAM,QAAO,IAAI;AAAA,IAC3B;AAAA,EACF,QAAQ;AAAA,EAAqB;AAC7B,SAAO,cAAAD,QAAK,SAAS,GAAG;AAC1B;AAEA,SAAS,iBAAiB,KAAqB;AAC7C,MAAI;AACF,UAAM,UAAU,cAAAA,QAAK,QAAQ,WAAW,oBAAoB;AAC5D,QAAI,YAAAC,QAAG,WAAW,OAAO,GAAG;AAC1B,YAAM,MAAM,KAAK,MAAM,YAAAA,QAAG,aAAa,SAAS,OAAO,CAAC;AACxD,UAAI,IAAI,QAAS,QAAO,IAAI;AAAA,IAC9B;AAAA,EACF,QAAQ;AAAA,EAAqB;AAC7B,MAAI;AACF,UAAM,UAAU,cAAAD,QAAK,KAAK,KAAK,gBAAgB,0BAA0B,cAAc;AACvF,QAAI,YAAAC,QAAG,WAAW,OAAO,GAAG;AAC1B,YAAM,MAAM,KAAK,MAAM,YAAAA,QAAG,aAAa,SAAS,OAAO,CAAC;AACxD,UAAI,IAAI,QAAS,QAAO,IAAI;AAAA,IAC9B;AAAA,EACF,QAAQ;AAAA,EAAqB;AAC7B,SAAO;AACT;AAEA,SAAS,eAAe,aAAqB,eAA+B;AAE1E,QAAM,UAAU,cAAc,IAAI,gBAAgB;AAClD,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAM,OAAO,CAAC;AACjD;AAIO,SAAS,gBACd,QACA,QACA,aACA,KACY;AACZ,QAAM,cAAc,eAAe,GAAG;AACtC,QAAM,UAAU,iBAAiB,GAAG;AACpC,QAAM,QAAQ,eAAe,OAAO,aAAa,OAAO,aAAa;AAGrE,QAAM,WAAW,OAAO,MACrB,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,SAAS,EAAE,OAAO,MAAM,EAChD,MAAM,GAAG,EAAE,EACX,IAAI,CAAC,OAAO;AAAA,IACX,MAAM,EAAE;AAAA,IACR,OAAO,EAAE,OAAO;AAAA,IAChB,QAAQ,EAAE;AAAA,IACV,UAAU,EAAE;AAAA,EACd,EAAE;AAGJ,QAAM,oBAA4C,CAAC;AACnD,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,cAAc,QAAQ,GAAG;AAC1D,UAAM,MAAM,UAAU,IAAI,GAAG,YAAY;AACzC,sBAAkB,GAAG,KAAK,kBAAkB,GAAG,KAAK,KAAK;AAAA,EAC3D;AAGA,QAAM,cAAc,CAAC,GAAG,OAAO,cAAc,QAAQ,CAAC,EACnD,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,MAAM,GAAG,CAAC;AAEb,QAAM,WAAW,YAAY,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AAClD,UAAM,OAAO,UAAU,IAAI,KAAK,EAAE,aAAa,kBAAkB,UAAU,QAAQ;AAGnF,QAAI,UAAkF;AACtF,eAAW,QAAQ,OAAO,OAAO;AAC/B,YAAM,QAAQ,KAAK,OAAO,KAAK,CAAC,MAAM,EAAE,WAAW,IAAI;AACvD,UAAI,OAAO;AACT,kBAAU;AAAA,UACR,MAAM,KAAK;AAAA,UACX,MAAM,MAAM;AAAA,UACZ,QAAQ,MAAM;AAAA,UACd,SAAS,MAAM;AAAA,QACjB;AACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM,KAAK,QAAQ,eAAe,EAAE;AAAA,MACpC;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,UAAU,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF,CAAC;AAGD,QAAM,wBAAmE;AAAA,IACvE,gCAAgC;AAAA,IAChC,4BAA4B;AAAA,IAC5B,gCAAgC;AAAA,IAChC,2BAA2B;AAAA,IAC3B,iCAAiC;AAAA,IACjC,6BAA6B;AAAA,IAC7B,oCAAoC;AAAA,IACpC,gCAAgC;AAAA,IAChC,iCAAiC;AAAA,IACjC,iCAAiC;AAAA,IACjC,kCAAkC;AAAA,IAClC,mCAAmC;AAAA,IACnC,oCAAoC;AAAA,IACpC,2BAA2B;AAAA,IAC3B,+BAA+B;AAAA,IAC/B,kCAAkC;AAAA,IAClC,qCAAqC;AAAA,IACrC,+BAA+B;AAAA,EACjC;AACA,MAAI,YAAY;AAChB,MAAI,cAAc;AAClB,MAAI,WAAW;AACf,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,cAAc,QAAQ,GAAG;AAC1D,UAAM,OAAO,sBAAsB,IAAI,KAAK;AAC5C,QAAI,SAAS,OAAQ,cAAa;AAAA,aACzB,SAAS,SAAU,gBAAe;AAAA,QACtC,aAAY;AAAA,EACnB;AACA,QAAM,iBAAiB,OAAO,iBAAiB,UAAU;AACzD,QAAM,mBAAmB,OAAO,cAAc,UAAU;AAExD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAAA,IACA;AAAA,IACA,YAAY,OAAO;AAAA,IACnB,aAAa,OAAO;AAAA,IACpB,aAAa,OAAO;AAAA,IACpB,eAAe,OAAO;AAAA,IACtB;AAAA,IACA,eAAe,OAAO,YAAY,OAAO,aAAa;AAAA,IACtD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAIO,SAAS,aAAa,MAA0B;AACrD,QAAM,aAAa,KAAK,SAAS,KAAK,YAAY,KAAK,SAAS,KAAK,YAAY;AACjF,QAAM,aAAa,KAAK,SAAS,KAAK,UAAU,KAAK,SAAS,KAAK,eAAe;AAClF,QAAM,gBAAgB,IAAI,KAAK,KAAK,WAAW,EAAE,eAAe;AAEhE,QAAM,eAAe,KAAK,SAAS,WAAW,IAC1C,wGACA,KAAK,SAAS,IAAI,CAAC,MAAM;AACvB,UAAM,YAAY,EAAE,SAAS,IACzB,kBAAkB,KAAK,IAAI,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC,MACrD,mBAAmB,KAAK,IAAI,KAAK,MAAM,EAAE,WAAW,IAAI,CAAC;AAC7D,WAAO;AAAA;AAAA,sLAEuK,QAAQ,EAAE,IAAI,CAAC,KAAK,QAAQ,EAAE,IAAI,CAAC;AAAA,0FAC/H,SAAS,mFAAmF,EAAE,KAAK;AAAA,gFAC7G,EAAE,MAAM;AAAA,gFACR,EAAE,QAAQ;AAAA;AAAA,EAEpF,CAAC,EAAE,KAAK,EAAE;AAEd,QAAM,gBAAgB,KAAK,SAAS,WAAW,IAC3C,2GACA,KAAK,SAAS,IAAI,CAAC,GAAG,MAAM;AAC1B,UAAM,WAAmC;AAAA,MACvC,eAAe;AAAA,MAAW,mBAAmB;AAAA,MAC7C,YAAY;AAAA,MAAW,eAAe;AAAA,MAAW,OAAO;AAAA,IAC1D;AACA,UAAM,QAAQ,SAAS,EAAE,QAAQ,KAAK;AACtC,UAAM,cAAc,EAAE,UAClB,gHAAgH,KAAK;AAAA,oFAC7C,QAAQ,EAAE,QAAQ,IAAI,CAAC,IAAI,EAAE,QAAQ,IAAI,IAAI,EAAE,QAAQ,MAAM;AAAA,wGACzC,QAAQ,EAAE,QAAQ,OAAO,CAAC;AAAA,sBAEtH;AACJ,WAAO;AAAA;AAAA;AAAA;AAAA,iIAIkH,IAAI,CAAC;AAAA,gFACtD,QAAQ,EAAE,IAAI,CAAC;AAAA;AAAA;AAAA,0CAGrD,KAAK,YAAY,KAAK,qBAAqB,KAAK,sEAAsE,QAAQ,EAAE,QAAQ,CAAC;AAAA,8IACrC,EAAE,KAAK;AAAA;AAAA;AAAA,mEAGlF,QAAQ,EAAE,WAAW,CAAC;AAAA,cAC3E,WAAW;AAAA;AAAA,EAEnB,CAAC,EAAE,KAAK,EAAE;AAEd,QAAM,gBAAgB,OAAO,QAAQ,KAAK,iBAAiB,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AACjF,UAAM,WAAmC;AAAA,MACvC,eAAe;AAAA,MAAW,mBAAmB;AAAA,MAC7C,YAAY;AAAA,MAAW,eAAe;AAAA,MAAW,OAAO;AAAA,IAC1D;AACA,UAAM,QAAQ,SAAS,GAAG,KAAK;AAC/B,WAAO;AAAA;AAAA,uDAE4C,QAAQ,GAAG,CAAC;AAAA,2DACR,KAAK,MAAM,KAAK;AAAA,kHACuC,KAAK,sBAAsB,KAAK,IAAI,KAAM,QAAQ,KAAK,IAAI,KAAK,aAAa,CAAC,IAAK,GAAG,CAAC;AAAA;AAAA,EAEvM,CAAC,EAAE,KAAK,EAAE;AAEV,QAAM,cAAc,KAAK,gBAAgB,IACrC;AAAA;AAAA;AAAA;AAAA,gBAKA;AAEJ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,kCAKoB,QAAQ,KAAK,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sEAwBgB,QAAQ,KAAK,WAAW,CAAC;AAAA,+GACgB,QAAQ,KAAK,WAAW,CAAC,qDAAkD,QAAQ,KAAK,MAAM,CAAC,gBAAa,KAAK,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4EAO9J,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA,4EAId,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA,4EAIhB,KAAK,QAAQ;AAAA;AAAA,YAE7E,KAAK,iBAAiB,IAAI;AAAA,oEACyB,KAAK,cAAc,gBAAgB,KAAK,mBAAmB,IAAI,MAAM,EAAE;AAAA,oBAClH,EAAE;AAAA;AAAA;AAAA;AAAA,4EAIsD,QAAQ,aAAa,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAO9F,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qEAMsD,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA,qEAIhB,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA,qEAIhB,KAAK,aAAa;AAAA;AAAA;AAAA;AAAA,qEAIlB,KAAK,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA,qEAIpB,OAAO,KAAK,KAAK,aAAa,EAAE,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,IAKvG,OAAO,KAAK,KAAK,iBAAiB,EAAE,SAAS,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAM7C,aAAa;AAAA;AAAA,gBAEL,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAkBN,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYhB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4JA8CuI,QAAQ,KAAK,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQjL;AAIA,SAAS,QAAQ,KAAqB;AACpC,SAAO,IACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,OAAO;AAC1B;AAIO,SAAS,sBAAsBC,UAAwB;AAC5D,EAAAA,SACG,QAAQ,QAAQ,EAChB;AAAA,IACC;AAAA,EAEF,EACC,OAAO,gBAAgB,6BAA6B,GAAG,EACvD,OAAO,qBAAqB,gDAAgD,aAAa,EACzF,OAAO,UAAU,yCAAyC,EAC1D,OAAO,UAAU,mDAAmD,EACpE,OAAO,uBAAuB,oBAAoB,sBAAsB,EACxE,OAAO,aAAa,wDAAwD,EAC5E,OAAO,OAAO,SAOT;AACJ,UAAM,SAAU,CAAC,eAAe,UAAU,UAAU,EAAE,SAAS,KAAK,MAAM,IACtE,KAAK,SACL;AAEJ,UAAM,UAAU,KAAK,OACjB,WACA,YAAAC,SAAI,EAAE,MAAM,kBAAa,OAAO,OAAO,CAAC,EAAE,MAAM;AAEpD,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,UAAU,EAAE,QAAQ,YAAY,KAAK,KAAK,CAAC;AAC1D,eAAS,KAAK;AAAA,IAChB,SAAS,KAAc;AACrB,eAAS,KAAK;AACd,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAI,MAAM,GAAG;AACb,cAAQ,KAAK,CAAC;AACd;AAAA,IACF;AAEA,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,aAAa,gBAAgB,QAAQ,QAAQ,KAAK,MAAM,GAAG;AAIjE,QAAI,KAAK,MAAM;AACb,cAAQ,IAAI,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAC/C,cAAQ,KAAK,CAAC;AACd;AAAA,IACF;AAIA,QAAI,OAAO,iBAAiB;AAC5B,QAAI,MAAM;AAEV,UAAM,OAAO,aAAa,UAAU;AACpC,UAAM,aAAa,cAAAH,QAAK,QAAQ,KAAK,KAAK,MAAM;AAEhD,gBAAAC,QAAG,cAAc,YAAY,MAAM,OAAO;AAE1C,QAAI,QAAQ,iBAAiB,KAAK,MAAM,EAAE;AAC1C,QAAI;AAAA,MACF,UAAU,WAAW,KAAK,aAAU,WAAW,WAAW,gBAAa,WAAW,aAAa;AAAA,IACjG;AACA,QAAI,MAAM;AAGV,QAAI,KAAK,SAAS,OAAO;AACvB,UAAI;AACF,cAAM,EAAE,SAAS,KAAK,IAAI,MAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAEzD,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB,CAAC;AAED,YAAI,MAAM;AACR,gBAAM,KAAK,UAAU;AACrB,cAAI,KAAK,yBAAyB;AAAA,QACpC,OAAO;AAEL,gBAAM,EAAE,UAAAG,UAAS,IAAI,MAAM,OAAO,eAAe;AACjD,gBAAM,MAAM,QAAQ,aAAa,UAC7B,aAAa,UAAU,MACvB,QAAQ,aAAa,WACrB,SAAS,UAAU,MACnB,aAAa,UAAU;AAC3B,UAAAA,UAAS,GAAG;AACZ,cAAI,KAAK,yBAAyB;AAAA,QACpC;AAAA,MACF,QAAQ;AACN,YAAI,KAAK,yBAAyB,UAAU,EAAE;AAAA,MAChD;AAAA,IACF,OAAO;AACL,UAAI,KAAK,gBAAgB,UAAU,EAAE;AAAA,IACvC;AAEA,QAAI,MAAM;AAAA,EACZ,CAAC;AACL;;;AhBxjBA,SAAS,aAAqB;AAC5B,MAAI;AAEF,UAAM,UAAU,cAAAC,QAAK,QAAQ,WAAW,oBAAoB;AAC5D,UAAM,MAAM,YAAAC,QAAG,aAAa,SAAS,OAAO;AAC5C,UAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,WAAO,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAAA,EACzD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIA,IAAM,UAAU,IAAI,yBAAQ;AAE5B,QACG,KAAK,UAAU,EACf;AAAA,EACC;AAUF,EACC,QAAQ,WAAW,GAAG,iBAAiB,sBAAsB,EAC7D,WAAW,cAAc,WAAW;AAIvC,mBAAmB,OAAO;AAC1B,uBAAuB,OAAO;AAC9B,oBAAoB,OAAO;AAC3B,sBAAsB,OAAO;AAC7B,sBAAsB,OAAO;AAC7B,sBAAsB,OAAO;AAC7B,wBAAwB,OAAO;AAC/B,2BAA2B,OAAO;AAClC,sBAAsB,OAAO;AAI7B,QAAQ,gBAAgB;AAAA,EACtB,SAAS,KAAK;AAEZ,UAAM,UAAU,IAAI,QAAQ,eAAe,EAAE,EAAE,KAAK;AACpD,QAAI,MAAM,OAAO;AAAA,EACnB;AACF,CAAC;AAED,QAAQ,GAAG,sBAAsB,CAAC,WAAoB;AACpD,QAAM,MACJ,kBAAkB,QAAQ,OAAO,UAAU,OAAO,MAAM;AAC1D,MAAI,MAAM,qBAAqB,GAAG,EAAE;AACpC,MAAI,KAAK,gDAAgD;AACzD,MAAI,KAAK,iEAAiE;AAC1E,UAAQ,KAAK,CAAC;AAChB,CAAC;AAED,QAAQ,GAAG,UAAU,MAAM;AACzB,MAAI,MAAM;AACV,MAAI,KAAK,YAAY;AACrB,UAAQ,KAAK,CAAC;AAChB,CAAC;AAID,QAAQ,WAAW,QAAQ,IAAI,EAAE,MAAM,CAAC,QAAiB;AACvD,QAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,MAAI,MAAM,GAAG;AACb,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["chalk","import_chalk","fs","path","import_fs","import_path","import_fs","import_path","import_chalk","import_chalk","chalk","createRequire","path","fs","tsParser","chalk","import_url","import_path","path","log","import_fs","fs","import_path","import_fs","path","fs","program","ora","chalk","tierLabel","import_path","import_fs","import_ora","import_chalk","program","printCIDebug","path","ora","chalk","printGitDebug","result","fs","import_chalk","import_path","import_fs","import_fs","import_path","import_module","path","fs","path","program","chalk","createRequire","pathToFileURL","content","isInvalidAiGuardConfig","fs","import_chalk","import_path","import_meta","path","program","isInvalidAiGuardConfig","createRequire","chalk","import_chalk","import_path","program","chalk","path","import_chalk","import_path","program","chalk","path","import_fs","import_path","import_chalk","import_ora","path","fs","program","ora","chalk","import_fs","import_path","import_chalk","import_prompts","path","getPackageVersion","fs","program","getPackageVersion","chalk","path","fs","import_fs","import_path","import_ora","path","fs","program","ora","execSync","path","fs"]}