viberails 0.3.0 → 0.3.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.
- package/dist/index.cjs +771 -378
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +771 -378
- package/dist/index.js.map +1 -1
- package/package.json +9 -7
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/boundaries.ts","../src/utils/find-project-root.ts","../src/utils/prompt.ts","../src/utils/resolve-workspace-packages.ts","../src/commands/check.ts","../src/commands/check-config.ts","../src/commands/check-files.ts","../src/commands/check-tests.ts","../src/commands/fix.ts","../src/commands/fix-helpers.ts","../src/commands/fix-imports.ts","../src/commands/fix-naming.ts","../src/commands/convert-name.ts","../src/commands/fix-tests.ts","../src/commands/init.ts","../src/utils/write-generated-files.ts","../src/commands/init-hooks.ts","../src/commands/init-wizard.ts","../src/display.ts","../src/display-helpers.ts","../src/display-monorepo.ts","../src/commands/sync.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { Command } from 'commander';\nimport { boundariesCommand } from './commands/boundaries.js';\nimport { checkCommand } from './commands/check.js';\nimport { fixCommand } from './commands/fix.js';\nimport { initCommand } from './commands/init.js';\nimport { syncCommand } from './commands/sync.js';\n\ndeclare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n\nconst program = new Command();\n\nprogram.name('viberails').description('Guardrails for vibe coding').version(VERSION);\n\nprogram\n .command('init', { isDefault: true })\n .description('Scan your project and set up enforcement guardrails')\n .option('-y, --yes', 'Non-interactive mode (use defaults, high-confidence only)')\n .action(async (options: { yes?: boolean }) => {\n try {\n await initCommand(options);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command('sync')\n .description('Re-scan and update generated files')\n .action(async () => {\n try {\n await syncCommand();\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command('check')\n .description('Check files against enforced rules')\n .option('--staged', 'Check only staged files (for pre-commit hooks)')\n .option('--files <files...>', 'Check specific files')\n .option('--no-boundaries', 'Skip boundary checking')\n .option('--quiet', 'Show only summary counts, not individual violations')\n .option('--limit <n>', 'Maximum number of violations to display', Number.parseInt)\n .action(\n async (options: {\n staged?: boolean;\n files?: string[];\n boundaries?: boolean;\n quiet?: boolean;\n limit?: number;\n }) => {\n try {\n const exitCode = await checkCommand({\n ...options,\n noBoundaries: options.boundaries === false,\n });\n process.exit(exitCode);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('fix')\n .description('Auto-fix file naming violations and generate missing test stubs')\n .option('--dry-run', 'Show planned fixes without applying them')\n .option('--rule <rules...>', 'Fix only specific rules (file-naming, missing-test)')\n .option('-y, --yes', 'Skip confirmation prompt')\n .action(async (options: { dryRun?: boolean; rule?: string[]; yes?: boolean }) => {\n try {\n const exitCode = await fixCommand(options);\n process.exit(exitCode);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command('boundaries')\n .description('Display, infer, or inspect import boundary rules')\n .option('--infer', 'Infer boundary rules from current import patterns')\n .option('--graph', 'Display import graph summary')\n .action(async (options: { infer?: boolean; graph?: boolean }) => {\n try {\n await boundariesCommand(options);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { loadConfig } from '@viberails/config';\nimport type { ViberailsConfig } from '@viberails/types';\nimport chalk from 'chalk';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport { confirm } from '../utils/prompt.js';\nimport { resolveWorkspacePackages } from '../utils/resolve-workspace-packages.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\nexport interface BoundariesOptions {\n infer?: boolean;\n graph?: boolean;\n}\n\n/**\n * Display, infer, or inspect import boundary rules.\n *\n * @param options - CLI options\n * @param cwd - Working directory override (for testing)\n */\nexport async function boundariesCommand(options: BoundariesOptions, cwd?: string): Promise<void> {\n const startDir = cwd ?? process.cwd();\n const projectRoot = findProjectRoot(startDir);\n if (!projectRoot) {\n throw new Error('No package.json found. Are you in a JS/TS project?');\n }\n\n const configPath = path.join(projectRoot, CONFIG_FILE);\n if (!fs.existsSync(configPath)) {\n throw new Error('No viberails.config.json found. Run `viberails init` first.');\n }\n\n const config = await loadConfig(configPath);\n\n if (options.graph) {\n await showGraph(projectRoot, config);\n return;\n }\n\n if (options.infer) {\n await inferAndDisplay(projectRoot, config, configPath);\n return;\n }\n\n displayRules(config);\n}\n\n/** Count total rules across either format. */\nfunction countBoundaries(boundaries: ViberailsConfig['boundaries']): number {\n if (!boundaries) return 0;\n if (Array.isArray(boundaries)) return boundaries.length;\n return Object.values(boundaries).reduce((sum, denied) => sum + denied.length, 0);\n}\n\n/** Display configured boundary rules. */\nfunction displayRules(config: ViberailsConfig): void {\n const total = countBoundaries(config.boundaries);\n if (total === 0) {\n console.log(chalk.yellow('No boundary rules configured.'));\n console.log(`Run ${chalk.cyan('viberails boundaries --infer')} to generate rules.`);\n return;\n }\n\n console.log(`\\n${chalk.bold(`Boundary rules (${total} rules):`)}\\n`);\n\n if (Array.isArray(config.boundaries)) {\n const allowRules = config.boundaries.filter((r) => r.allow);\n const denyRules = config.boundaries.filter((r) => !r.allow);\n\n for (const r of allowRules) {\n console.log(` ${chalk.green('✓')} ${r.from} → ${r.to}`);\n }\n for (const r of denyRules) {\n const reason = r.reason ? chalk.dim(` (${r.reason})`) : '';\n console.log(` ${chalk.red('✗')} ${r.from} → ${r.to}${reason}`);\n }\n } else if (config.boundaries) {\n for (const [from, denied] of Object.entries(config.boundaries)) {\n for (const to of denied) {\n console.log(` ${chalk.red('✗')} ${from} → ${to}`);\n }\n }\n }\n\n console.log(\n `\\nEnforcement: ${config.rules.enforceBoundaries ? chalk.green('on') : chalk.yellow('off')}`,\n );\n}\n\n/** Infer boundary rules from import patterns and optionally save. */\nasync function inferAndDisplay(\n projectRoot: string,\n config: ViberailsConfig,\n configPath: string,\n): Promise<void> {\n console.log(chalk.dim('Analyzing imports...'));\n const { buildImportGraph, inferBoundaries } = await import('@viberails/graph');\n\n const packages = config.workspace\n ? resolveWorkspacePackages(projectRoot, config.workspace)\n : undefined;\n\n const graph = await buildImportGraph(projectRoot, {\n packages,\n ignore: config.ignore,\n });\n\n console.log(chalk.dim(`${graph.nodes.length} files, ${graph.edges.length} edges`));\n\n const inferred = inferBoundaries(graph);\n const entries = Object.entries(inferred);\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No boundary rules could be inferred.'));\n return;\n }\n\n const totalRules = entries.reduce((sum, [, denied]) => sum + denied.length, 0);\n\n console.log(`\\n${chalk.bold('Inferred boundary rules:')}\\n`);\n\n for (const [from, denied] of entries) {\n for (const to of denied) {\n console.log(` ${chalk.red('✗')} ${from} → ${to}`);\n }\n }\n\n console.log(`\\n ${totalRules} deny rules`);\n\n const shouldSave = await confirm('\\nSave to viberails.config.json?');\n if (shouldSave) {\n config.boundaries = inferred;\n config.rules.enforceBoundaries = true;\n fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`);\n console.log(`${chalk.green('✓')} Saved ${totalRules} rules`);\n }\n}\n\n/** Display import graph summary. */\nasync function showGraph(projectRoot: string, config: ViberailsConfig): Promise<void> {\n console.log(chalk.dim('Building import graph...'));\n const { buildImportGraph } = await import('@viberails/graph');\n\n const packages = config.workspace\n ? resolveWorkspacePackages(projectRoot, config.workspace)\n : undefined;\n\n const graph = await buildImportGraph(projectRoot, {\n packages,\n ignore: config.ignore,\n });\n\n console.log(`\\n${chalk.bold('Import dependency graph:')}\\n`);\n console.log(` ${graph.nodes.length} files, ${graph.edges.length} imports\\n`);\n\n if (graph.packages.length > 0) {\n for (const pkg of graph.packages) {\n const deps =\n pkg.internalDeps.length > 0\n ? `\\n${pkg.internalDeps.map((d) => ` → ${d}`).join('\\n')}`\n : chalk.dim(' (no internal deps)');\n console.log(` ${pkg.name}${deps}`);\n }\n }\n\n if (graph.cycles.length > 0) {\n console.log(`\\n${chalk.yellow('Cycles detected:')}`);\n for (const cycle of graph.cycles) {\n const paths = cycle.map((f) => path.relative(projectRoot, f));\n console.log(` ${paths.join(' → ')}`);\n }\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * Walk up from startDir looking for a directory containing package.json.\n *\n * @param startDir - The directory to start searching from\n * @returns The project root path, or null if no package.json is found\n */\nexport function findProjectRoot(startDir: string): string | null {\n let dir = path.resolve(startDir);\n\n while (true) {\n if (fs.existsSync(path.join(dir, 'package.json'))) {\n return dir;\n }\n\n const parent = path.dirname(dir);\n if (parent === dir) {\n return null;\n }\n dir = parent;\n }\n}\n","import * as readline from 'node:readline';\n\n/**\n * Prompt the user for a yes/no confirmation.\n *\n * @param message - The question to display (without the Y/n suffix)\n * @returns true if the user confirms, false otherwise\n */\nexport async function confirm(message: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise<boolean>((resolve) => {\n rl.question(`${message} (Y/n) `, (answer) => {\n rl.close();\n const trimmed = answer.trim().toLowerCase();\n resolve(trimmed === '' || trimmed === 'y' || trimmed === 'yes');\n });\n });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { WorkspaceConfig, WorkspacePackage } from '@viberails/types';\n\n/**\n * Resolve WorkspacePackage[] from config workspace relative paths.\n *\n * Reads each package's package.json to get the name and dependencies,\n * then filters internalDeps to only include workspace-internal packages.\n *\n * @param projectRoot - Absolute path to the project root\n * @param workspace - The workspace config from viberails.config.json\n * @returns Array of resolved WorkspacePackage objects\n */\nexport function resolveWorkspacePackages(\n projectRoot: string,\n workspace: WorkspaceConfig,\n): WorkspacePackage[] {\n const packages: WorkspacePackage[] = [];\n\n for (const relativePath of workspace.packages) {\n const absPath = path.join(projectRoot, relativePath);\n const pkgJsonPath = path.join(absPath, 'package.json');\n\n if (!fs.existsSync(pkgJsonPath)) continue;\n\n let pkg: Record<string, unknown>;\n try {\n pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));\n } catch {\n continue;\n }\n\n const name = pkg.name as string;\n if (!name) continue;\n\n const allDeps = [\n ...Object.keys((pkg.dependencies as Record<string, unknown>) ?? {}),\n ...Object.keys((pkg.devDependencies as Record<string, unknown>) ?? {}),\n ];\n\n packages.push({ name, path: absPath, relativePath, internalDeps: allDeps });\n }\n\n // Filter internalDeps to only workspace-internal package names\n const packageNames = new Set(packages.map((p) => p.name));\n for (const pkg of packages) {\n pkg.internalDeps = pkg.internalDeps.filter((dep) => packageNames.has(dep));\n }\n\n return packages;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { loadConfig } from '@viberails/config';\nimport type { CheckViolation } from '@viberails/types';\nimport chalk from 'chalk';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport { resolveWorkspacePackages } from '../utils/resolve-workspace-packages.js';\nimport { resolveConfigForFile, resolveIgnoreForFile } from './check-config.js';\nimport {\n checkNaming,\n countFileLines,\n getAllSourceFiles,\n getStagedFiles,\n isIgnored,\n} from './check-files.js';\nimport { checkMissingTests } from './check-tests.js';\n\nexport { resolveConfigForFile } from './check-config.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\nexport interface CheckOptions {\n files?: string[];\n staged?: boolean;\n noBoundaries?: boolean;\n quiet?: boolean;\n limit?: number;\n}\n\n/** Check if a file path looks like a test file. */\nfunction isTestFile(relPath: string): boolean {\n const filename = path.basename(relPath);\n return (\n filename.includes('.test.') ||\n filename.includes('.spec.') ||\n filename.startsWith('test.') ||\n filename.startsWith('spec.') ||\n relPath.includes('__tests__/') ||\n relPath.includes('__test__/')\n );\n}\n\n/**\n * Print violations grouped by rule type with counts.\n */\nfunction printGroupedViolations(violations: CheckViolation[], limit?: number): void {\n const groups = new Map<string, CheckViolation[]>();\n for (const v of violations) {\n const existing = groups.get(v.rule) ?? [];\n existing.push(v);\n groups.set(v.rule, existing);\n }\n\n const ruleOrder = ['file-size', 'file-naming', 'missing-test', 'boundary-violation'];\n const sortedKeys = [...groups.keys()].sort(\n (a, b) =>\n (ruleOrder.indexOf(a) === -1 ? 99 : ruleOrder.indexOf(a)) -\n (ruleOrder.indexOf(b) === -1 ? 99 : ruleOrder.indexOf(b)),\n );\n\n let totalShown = 0;\n const totalLimit = limit ?? Number.POSITIVE_INFINITY;\n\n for (const rule of sortedKeys) {\n const group = groups.get(rule);\n if (!group) continue;\n const remaining = totalLimit - totalShown;\n if (remaining <= 0) break;\n\n const toShow = group.slice(0, remaining);\n const hidden = group.length - toShow.length;\n\n for (const v of toShow) {\n const icon = v.severity === 'error' ? chalk.red('✗') : chalk.yellow('!');\n console.log(`${icon} ${chalk.dim(v.rule)} ${v.file}: ${v.message}`);\n }\n totalShown += toShow.length;\n\n if (hidden > 0) {\n console.log(chalk.dim(` ... and ${hidden} more ${rule} violations`));\n }\n }\n}\n\n/**\n * Print a summary of violations by rule type.\n */\nfunction printSummary(violations: CheckViolation[]): void {\n const counts = new Map<string, number>();\n for (const v of violations) {\n counts.set(v.rule, (counts.get(v.rule) ?? 0) + 1);\n }\n\n const word = violations.length === 1 ? 'violation' : 'violations';\n const parts = [...counts.entries()].map(([rule, count]) => `${count} ${rule}`);\n console.log(`\\n${violations.length} ${word} found (${parts.join(', ')}).`);\n}\n\n/**\n * Run the viberails check command.\n * Returns exit code: 0 = pass or warn-mode, 1 = violations in enforce mode.\n */\nexport async function checkCommand(options: CheckOptions, cwd?: string): Promise<number> {\n const startDir = cwd ?? process.cwd();\n\n const projectRoot = findProjectRoot(startDir);\n if (!projectRoot) {\n console.error(`${chalk.red('Error:')} No package.json found. Are you in a JS/TS project?`);\n return 1;\n }\n\n const configPath = path.join(projectRoot, CONFIG_FILE);\n if (!fs.existsSync(configPath)) {\n console.error(\n `${chalk.red('Error:')} No viberails.config.json found. Run \\`viberails init\\` first.`,\n );\n return 1;\n }\n\n const config = await loadConfig(configPath);\n\n // Determine which files to check\n let filesToCheck: string[];\n if (options.staged) {\n filesToCheck = getStagedFiles(projectRoot);\n } else if (options.files && options.files.length > 0) {\n filesToCheck = options.files;\n } else {\n filesToCheck = getAllSourceFiles(projectRoot, config);\n }\n\n if (filesToCheck.length === 0) {\n console.log(`${chalk.green('✓')} No files to check.`);\n return 0;\n }\n\n const violations: CheckViolation[] = [];\n const severity = config.enforcement === 'enforce' ? 'error' : 'warn';\n\n for (const file of filesToCheck) {\n const absPath = path.isAbsolute(file) ? file : path.join(projectRoot, file);\n const relPath = path.relative(projectRoot, absPath);\n\n const effectiveIgnore = resolveIgnoreForFile(relPath, config);\n if (isIgnored(relPath, effectiveIgnore)) continue;\n if (!fs.existsSync(absPath)) continue;\n\n const resolved = resolveConfigForFile(relPath, config);\n\n // Check 1: File size (with separate threshold for test files)\n const testFile = isTestFile(relPath);\n const maxLines = testFile ? resolved.rules.maxTestFileLines : resolved.rules.maxFileLines;\n if (maxLines > 0) {\n const lines = countFileLines(absPath);\n if (lines !== null && lines > maxLines) {\n violations.push({\n file: relPath,\n rule: 'file-size',\n message: `${lines} lines (max ${maxLines}). Split into focused modules.`,\n severity,\n });\n }\n }\n\n // Check 2: File naming convention\n if (resolved.rules.enforceNaming && resolved.conventions.fileNaming) {\n const namingViolation = checkNaming(relPath, resolved.conventions);\n if (namingViolation) {\n violations.push({\n file: relPath,\n rule: 'file-naming',\n message: namingViolation,\n severity,\n });\n }\n }\n }\n\n // Check 3: Missing tests (only on full project check, not staged/specific files)\n if (config.rules.requireTests && !options.staged && !options.files) {\n const testViolations = checkMissingTests(projectRoot, config, severity);\n violations.push(...testViolations);\n }\n\n // Check 4: Boundary violations\n const hasBoundaries = config.boundaries\n ? Array.isArray(config.boundaries)\n ? config.boundaries.length > 0\n : Object.keys(config.boundaries).length > 0\n : false;\n if (config.rules.enforceBoundaries && hasBoundaries && !options.noBoundaries) {\n const startTime = Date.now();\n const { buildImportGraph, checkBoundaries } = await import('@viberails/graph');\n\n const packages = config.workspace\n ? resolveWorkspacePackages(projectRoot, config.workspace)\n : undefined;\n\n const graph = await buildImportGraph(projectRoot, {\n packages,\n ignore: config.ignore,\n });\n\n const boundaryViolations = checkBoundaries(graph, config.boundaries);\n\n // In staged/files mode, only report violations in those files\n const filterSet =\n options.staged || options.files\n ? new Set(filesToCheck.map((f) => path.resolve(projectRoot, f)))\n : null;\n\n for (const bv of boundaryViolations) {\n if (filterSet && !filterSet.has(bv.file)) continue;\n\n const relFile = path.relative(projectRoot, bv.file);\n violations.push({\n file: relFile,\n rule: 'boundary-violation',\n message: `Imports \"${bv.specifier}\" violating boundary: ${bv.rule.from} → ${bv.rule.to}${bv.rule.reason ? ` (${bv.rule.reason})` : ''}`,\n severity,\n });\n }\n\n const elapsed = Date.now() - startTime;\n console.log(chalk.dim(` Boundary check: ${graph.nodes.length} files in ${elapsed}ms`));\n }\n\n // Output results\n if (violations.length === 0) {\n console.log(`${chalk.green('✓')} ${filesToCheck.length} files checked — no violations`);\n return 0;\n }\n\n if (!options.quiet) {\n printGroupedViolations(violations, options.limit);\n }\n\n printSummary(violations);\n\n if (config.enforcement === 'enforce') {\n console.log(chalk.red('Fix violations before committing.'));\n return 1;\n }\n\n return 0;\n}\n","import type { ConfigConventions, ConfigRules, ViberailsConfig } from '@viberails/types';\n\nexport interface ResolvedConfig {\n rules: ConfigRules;\n conventions: ConfigConventions;\n}\n\n/**\n * Resolve the effective config for a file by finding its package override.\n * Returns the global config merged with any matching package overrides.\n */\nexport function resolveConfigForFile(relPath: string, config: ViberailsConfig): ResolvedConfig {\n if (!config.packages || config.packages.length === 0) {\n return { rules: config.rules, conventions: config.conventions };\n }\n\n // Sort by path length descending to match the most specific package first\n const sortedPackages = [...config.packages].sort((a, b) => b.path.length - a.path.length);\n\n for (const pkg of sortedPackages) {\n if (relPath.startsWith(`${pkg.path}/`) || relPath === pkg.path) {\n return {\n rules: { ...config.rules, ...pkg.rules },\n conventions: { ...config.conventions, ...pkg.conventions },\n };\n }\n }\n\n return { rules: config.rules, conventions: config.conventions };\n}\n\n/**\n * Resolve ignore patterns for a file, appending any package-specific patterns.\n */\nexport function resolveIgnoreForFile(relPath: string, config: ViberailsConfig): string[] {\n const globalIgnore = config.ignore;\n if (!config.packages) return globalIgnore;\n\n for (const pkg of config.packages) {\n if (pkg.ignore && relPath.startsWith(`${pkg.path}/`)) {\n return [...globalIgnore, ...pkg.ignore];\n }\n }\n return globalIgnore;\n}\n","import { execSync } from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ConfigConventions, ConventionValue, ViberailsConfig } from '@viberails/types';\n\nconst ALWAYS_SKIP_DIRS = new Set([\n 'node_modules',\n '.git',\n 'dist',\n 'build',\n '.next',\n '.expo',\n '.output',\n '.svelte-kit',\n '.turbo',\n 'coverage',\n 'public',\n 'vendor',\n '__generated__',\n 'generated',\n '.viberails',\n]);\n\nexport const SOURCE_EXTS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.vue',\n '.svelte',\n '.astro',\n]);\n\nexport const NAMING_PATTERNS: Record<string, RegExp> = {\n 'kebab-case': /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/,\n camelCase: /^[a-z][a-zA-Z0-9]*$/,\n PascalCase: /^[A-Z][a-zA-Z0-9]*$/,\n snake_case: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,\n};\n\n/** Check if a path matches any ignore pattern. */\nexport function isIgnored(relPath: string, ignorePatterns: string[]): boolean {\n for (const pattern of ignorePatterns) {\n const startsGlob = pattern.startsWith('**/');\n const endsGlob = pattern.endsWith('/**');\n\n if (startsGlob && endsGlob) {\n // Pattern like **/public/** — match directory name anywhere in path\n const middle = pattern.slice(3, -3);\n if (\n relPath.startsWith(`${middle}/`) ||\n relPath.includes(`/${middle}/`) ||\n relPath === middle\n ) {\n return true;\n }\n } else if (endsGlob) {\n const prefix = pattern.slice(0, -3);\n if (relPath.startsWith(`${prefix}/`) || relPath === prefix) return true;\n } else if (startsGlob) {\n const suffix = pattern.slice(3);\n if (relPath.endsWith(suffix) || relPath === suffix) return true;\n } else if (relPath === pattern || relPath.startsWith(`${pattern}/`)) {\n return true;\n }\n }\n return false;\n}\n\n/** Count lines in a file. Returns null if the file can't be read. */\nexport function countFileLines(filePath: string): number | null {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n if (content.length === 0) return 0;\n let count = 1;\n for (let i = 0; i < content.length; i++) {\n if (content.charCodeAt(i) === 10) count++;\n }\n return count;\n } catch {\n return null;\n }\n}\n\n/** Check whether a file's name violates the configured naming convention. */\nexport function checkNaming(relPath: string, conventions: ConfigConventions): string | undefined {\n const filename = path.basename(relPath);\n\n // Skip non-source files\n const ext = path.extname(filename);\n if (!SOURCE_EXTS.has(ext)) return undefined;\n\n // Skip special files\n if (\n filename.startsWith('index.') ||\n filename.includes('.config.') ||\n filename.includes('.test.') ||\n filename.includes('.spec.') ||\n filename.startsWith('.') ||\n filename.startsWith('_') ||\n filename.startsWith('+') ||\n filename.startsWith('$') ||\n filename.startsWith('[')\n ) {\n return undefined;\n }\n\n const bare = filename.slice(0, filename.indexOf('.'));\n const convention =\n typeof conventions.fileNaming === 'string'\n ? conventions.fileNaming\n : (conventions.fileNaming as Exclude<ConventionValue, string> | undefined)?.value;\n\n if (!convention) return undefined;\n\n const pattern = NAMING_PATTERNS[convention];\n if (!pattern || pattern.test(bare)) return undefined;\n\n return `File name \"${filename}\" does not follow ${convention} convention.`;\n}\n\n/** Get staged files from git. */\nexport function getStagedFiles(projectRoot: string): string[] {\n try {\n const output = execSync('git diff --cached --name-only --diff-filter=ACM', {\n cwd: projectRoot,\n encoding: 'utf-8',\n });\n return output.trim().split('\\n').filter(Boolean);\n } catch {\n return [];\n }\n}\n\n/** Get all source files in the project. */\nexport function getAllSourceFiles(projectRoot: string, config: ViberailsConfig): string[] {\n const files: string[] = [];\n const walk = (dir: string) => {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const rel = path.relative(projectRoot, path.join(dir, entry.name));\n if (entry.isDirectory()) {\n if (ALWAYS_SKIP_DIRS.has(entry.name)) {\n continue;\n }\n if (isIgnored(rel, config.ignore)) continue;\n walk(path.join(dir, entry.name));\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name);\n if (SOURCE_EXTS.has(ext) && !isIgnored(rel, config.ignore)) {\n files.push(rel);\n }\n }\n }\n };\n walk(projectRoot);\n return files;\n}\n\n/** Collect source files from a directory recursively. */\nexport function collectSourceFiles(dir: string, projectRoot: string): string[] {\n const files: string[] = [];\n const walk = (d: string) => {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(d, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules') continue;\n walk(path.join(d, entry.name));\n } else if (entry.isFile()) {\n files.push(path.relative(projectRoot, path.join(d, entry.name)));\n }\n }\n };\n walk(dir);\n return files;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { CheckViolation, ViberailsConfig } from '@viberails/types';\nimport { collectSourceFiles } from './check-files.js';\n\nconst SOURCE_EXTS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.vue',\n '.svelte',\n '.astro',\n]);\n\n/** Check for source files without corresponding test files. */\nexport function checkMissingTests(\n projectRoot: string,\n config: ViberailsConfig,\n severity: 'error' | 'warn',\n): CheckViolation[] {\n const violations: CheckViolation[] = [];\n const { testPattern } = config.structure;\n if (!testPattern) return violations;\n\n const srcDir = config.structure.srcDir;\n if (!srcDir) return violations;\n\n const srcPath = path.join(projectRoot, srcDir);\n if (!fs.existsSync(srcPath)) return violations;\n\n const testSuffix = testPattern.replace('*', '');\n const sourceFiles = collectSourceFiles(srcPath, projectRoot);\n\n for (const relFile of sourceFiles) {\n const basename = path.basename(relFile);\n\n // Skip test files, index files, type definition files\n if (\n basename.includes('.test.') ||\n basename.includes('.spec.') ||\n basename.startsWith('index.') ||\n basename.endsWith('.d.ts')\n ) {\n continue;\n }\n\n const ext = path.extname(basename);\n if (!SOURCE_EXTS.has(ext)) continue;\n\n const stem = basename.slice(0, basename.indexOf('.'));\n const expectedTestFile = `${stem}${testSuffix}`;\n\n // Look for the test file next to the source or in the tests directory\n const dir = path.dirname(path.join(projectRoot, relFile));\n const colocatedTest = path.join(dir, expectedTestFile);\n const testsDir = config.structure.tests;\n const dedicatedTest = testsDir ? path.join(projectRoot, testsDir, expectedTestFile) : null;\n\n const hasTest =\n fs.existsSync(colocatedTest) || (dedicatedTest !== null && fs.existsSync(dedicatedTest));\n\n if (!hasTest) {\n violations.push({\n file: relFile,\n rule: 'missing-test',\n message: `No test file found. Expected \\`${expectedTestFile}\\`.`,\n severity,\n });\n }\n }\n\n return violations;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { loadConfig } from '@viberails/config';\nimport chalk from 'chalk';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport { resolveConfigForFile } from './check-config.js';\nimport { checkNaming, getAllSourceFiles } from './check-files.js';\nimport { checkMissingTests } from './check-tests.js';\nimport { checkGitDirty, getConventionValue, printPlan, promptConfirm } from './fix-helpers.js';\nimport { updateImportsAfterRenames } from './fix-imports.js';\nimport {\n computeRename,\n deduplicateRenames,\n executeRename,\n type RenameRecord,\n} from './fix-naming.js';\nimport { generateTestStub, type TestStubRecord, writeTestStub } from './fix-tests.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\nexport interface FixOptions {\n dryRun?: boolean;\n rule?: string[];\n yes?: boolean;\n}\n\n/**\n * Run the viberails fix command.\n * Detects violations, computes fixes, optionally confirms, then applies.\n */\nexport async function fixCommand(options: FixOptions, cwd?: string): Promise<number> {\n const startDir = cwd ?? process.cwd();\n const projectRoot = findProjectRoot(startDir);\n\n if (!projectRoot) {\n console.error(`${chalk.red('Error:')} No package.json found. Are you in a JS/TS project?`);\n return 1;\n }\n\n const configPath = path.join(projectRoot, CONFIG_FILE);\n if (!fs.existsSync(configPath)) {\n console.error(\n `${chalk.red('Error:')} No viberails.config.json found. Run \\`viberails init\\` first.`,\n );\n return 1;\n }\n\n const config = await loadConfig(configPath);\n\n // Git dirty check — warn but don't block\n if (!options.dryRun) {\n const isDirty = checkGitDirty(projectRoot);\n if (isDirty) {\n console.log(\n chalk.yellow('Warning: You have uncommitted changes. Consider committing first.'),\n );\n }\n }\n\n const shouldFixNaming = !options.rule || options.rule.includes('file-naming');\n const shouldFixTests = !options.rule || options.rule.includes('missing-test');\n\n // Collect source files\n const allFiles = getAllSourceFiles(projectRoot, config);\n\n // Compute naming renames\n const renames: RenameRecord[] = [];\n if (shouldFixNaming) {\n for (const file of allFiles) {\n const resolved = resolveConfigForFile(file, config);\n if (!resolved.rules.enforceNaming || !resolved.conventions.fileNaming) continue;\n\n const violation = checkNaming(file, resolved.conventions);\n if (!violation) continue;\n\n const convention = getConventionValue(resolved.conventions.fileNaming);\n if (!convention) continue;\n\n const rename = computeRename(file, convention, projectRoot);\n if (rename) renames.push(rename);\n }\n }\n\n const dedupedRenames = deduplicateRenames(renames);\n\n // Compute test stubs\n const testStubs: TestStubRecord[] = [];\n if (shouldFixTests && config.rules.requireTests) {\n const testViolations = checkMissingTests(projectRoot, config, 'warn');\n for (const v of testViolations) {\n const stub = generateTestStub(v.file, config, projectRoot);\n if (stub) testStubs.push(stub);\n }\n }\n\n // Nothing to fix\n if (dedupedRenames.length === 0 && testStubs.length === 0) {\n console.log(`${chalk.green('✓')} No fixable violations found.`);\n return 0;\n }\n\n // Display plan\n printPlan(dedupedRenames, testStubs);\n\n if (options.dryRun) {\n console.log(chalk.dim('\\nDry run — no changes applied.'));\n return 0;\n }\n\n // Confirm\n if (!options.yes) {\n const confirmed = await promptConfirm('Apply these fixes?');\n if (!confirmed) {\n console.log('Aborted.');\n return 0;\n }\n }\n\n // Apply: 1. Renames\n let renameCount = 0;\n for (const rename of dedupedRenames) {\n if (executeRename(rename)) {\n renameCount++;\n }\n }\n\n // Apply: 2. Import updates\n let importUpdateCount = 0;\n if (renameCount > 0) {\n const appliedRenames = dedupedRenames.filter((r) => fs.existsSync(r.newAbsPath));\n const updates = await updateImportsAfterRenames(appliedRenames, projectRoot);\n importUpdateCount = updates.length;\n }\n\n // Apply: 3. Test stubs\n let stubCount = 0;\n for (const stub of testStubs) {\n if (!fs.existsSync(stub.absPath)) {\n writeTestStub(stub, config);\n stubCount++;\n }\n }\n\n // Summary\n console.log('');\n if (renameCount > 0) {\n console.log(`${chalk.green('✓')} Renamed ${renameCount} file${renameCount > 1 ? 's' : ''}`);\n }\n if (importUpdateCount > 0) {\n console.log(\n `${chalk.green('✓')} Updated ${importUpdateCount} import${importUpdateCount > 1 ? 's' : ''}`,\n );\n }\n if (stubCount > 0) {\n console.log(`${chalk.green('✓')} Generated ${stubCount} test stub${stubCount > 1 ? 's' : ''}`);\n }\n\n return 0;\n}\n","import { execSync } from 'node:child_process';\nimport { createInterface } from 'node:readline';\nimport chalk from 'chalk';\nimport type { RenameRecord } from './fix-naming.js';\nimport type { TestStubRecord } from './fix-tests.js';\n\n/**\n * Display the planned renames and test stubs.\n */\nexport function printPlan(renames: RenameRecord[], stubs: TestStubRecord[]): void {\n if (renames.length > 0) {\n console.log(chalk.bold('\\nFile renames:'));\n for (const r of renames) {\n console.log(` ${chalk.red(r.oldPath)} → ${chalk.green(r.newPath)}`);\n }\n }\n\n if (stubs.length > 0) {\n console.log(chalk.bold('\\nTest stubs to create:'));\n for (const s of stubs) {\n console.log(` ${chalk.green('+')} ${s.path}`);\n }\n }\n}\n\n/**\n * Check if the git working tree has uncommitted changes.\n */\nexport function checkGitDirty(projectRoot: string): boolean {\n try {\n const output = execSync('git status --porcelain', {\n cwd: projectRoot,\n encoding: 'utf-8',\n });\n return output.trim().length > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Extract the string value from a convention (which may be a string or an object with a value property).\n */\nexport function getConventionValue(convention: unknown): string | undefined {\n if (typeof convention === 'string') return convention;\n if (convention && typeof convention === 'object' && 'value' in convention) {\n return (convention as { value: string }).value;\n }\n return undefined;\n}\n\n/**\n * Prompt the user to confirm an action.\n */\nexport function promptConfirm(question: string): Promise<boolean> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(`${question} (y/N) `, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');\n });\n });\n}\n","import * as path from 'node:path';\nimport type { RenameRecord } from './fix-naming.js';\n\nexport interface ImportUpdateRecord {\n file: string;\n oldSpecifier: string;\n newSpecifier: string;\n line: number;\n}\n\n/**\n * Strip known JS/TS extensions from a file path for specifier comparison.\n * E.g. \"/foo/bar.ts\" → \"/foo/bar\", \"/foo/bar.js\" → \"/foo/bar\"\n */\nfunction stripExtension(filePath: string): string {\n return filePath.replace(/\\.(tsx?|jsx?|mjs|cjs)$/, '');\n}\n\n/**\n * Compute the new import specifier given the old specifier and the rename.\n * Preserves `.js` suffix if present.\n */\nfunction computeNewSpecifier(oldSpecifier: string, newBare: string): string {\n const hasJsExt = oldSpecifier.endsWith('.js');\n const base = hasJsExt ? oldSpecifier.slice(0, -3) : oldSpecifier;\n\n // Replace the last path segment\n const dir = base.lastIndexOf('/');\n const prefix = dir >= 0 ? base.slice(0, dir + 1) : '';\n const newSpec = prefix + newBare;\n\n return hasJsExt ? `${newSpec}.js` : newSpec;\n}\n\n/**\n * Update import specifiers in all source files after renames.\n * Uses ts-morph for AST-accurate rewriting.\n *\n * @param renames - The renames that were applied\n * @param projectRoot - Absolute path to project root\n * @returns Records of all import updates made\n */\nexport async function updateImportsAfterRenames(\n renames: RenameRecord[],\n projectRoot: string,\n): Promise<ImportUpdateRecord[]> {\n if (renames.length === 0) return [];\n\n // Lazy import ts-morph to avoid startup cost\n const { Project, SyntaxKind } = await import('ts-morph');\n\n // Build rename map: stripped old abs path → { newBare }\n const renameMap = new Map<string, { newBare: string }>();\n for (const r of renames) {\n const oldStripped = stripExtension(r.oldAbsPath);\n const newFilename = path.basename(r.newPath);\n const newName = newFilename.slice(0, newFilename.indexOf('.'));\n renameMap.set(oldStripped, { newBare: newName });\n }\n\n const project = new Project({\n tsConfigFilePath: undefined,\n skipAddingFilesFromTsConfig: true,\n });\n\n // Add all TS/JS source files\n project.addSourceFilesAtPaths(path.join(projectRoot, '**/*.{ts,tsx,js,jsx,mjs,cjs}'));\n\n const updates: ImportUpdateRecord[] = [];\n const extensions = ['', '.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.tsx', '/index.js'];\n\n for (const sourceFile of project.getSourceFiles()) {\n const filePath = sourceFile.getFilePath();\n // Skip node_modules and dist\n if (filePath.includes('/node_modules/') || filePath.includes('/dist/')) continue;\n\n const fileDir = path.dirname(filePath);\n\n // Process static imports\n for (const decl of sourceFile.getImportDeclarations()) {\n const specifier = decl.getModuleSpecifierValue();\n if (!specifier.startsWith('.')) continue;\n\n const match = resolveToRenamedFile(specifier, fileDir, renameMap, extensions);\n if (!match) continue;\n\n const newSpec = computeNewSpecifier(specifier, match.newBare);\n updates.push({\n file: filePath,\n oldSpecifier: specifier,\n newSpecifier: newSpec,\n line: decl.getStartLineNumber(),\n });\n decl.setModuleSpecifier(newSpec);\n }\n\n // Process re-exports\n for (const decl of sourceFile.getExportDeclarations()) {\n const specifier = decl.getModuleSpecifierValue();\n if (!specifier || !specifier.startsWith('.')) continue;\n\n const match = resolveToRenamedFile(specifier, fileDir, renameMap, extensions);\n if (!match) continue;\n\n const newSpec = computeNewSpecifier(specifier, match.newBare);\n updates.push({\n file: filePath,\n oldSpecifier: specifier,\n newSpecifier: newSpec,\n line: decl.getStartLineNumber(),\n });\n decl.setModuleSpecifier(newSpec);\n }\n\n // Process dynamic imports\n for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n if (call.getExpression().getKind() !== SyntaxKind.ImportKeyword) continue;\n\n const args = call.getArguments();\n if (args.length === 0) continue;\n\n const arg = args[0];\n if (arg.getKind() !== SyntaxKind.StringLiteral) continue;\n\n const specifier = arg.getText().slice(1, -1);\n if (!specifier.startsWith('.')) continue;\n\n const match = resolveToRenamedFile(specifier, fileDir, renameMap, extensions);\n if (!match) continue;\n\n const newSpec = computeNewSpecifier(specifier, match.newBare);\n updates.push({\n file: filePath,\n oldSpecifier: specifier,\n newSpecifier: newSpec,\n line: call.getStartLineNumber(),\n });\n // Replace the string literal content\n const quote = arg.getText()[0];\n arg.replaceWithText(`${quote}${newSpec}${quote}`);\n }\n }\n\n if (updates.length > 0) {\n await project.save();\n }\n\n return updates;\n}\n\n/**\n * Try to resolve a relative specifier to a renamed file.\n * Returns the rename info if matched, undefined otherwise.\n */\nfunction resolveToRenamedFile(\n specifier: string,\n fromDir: string,\n renameMap: Map<string, { newBare: string }>,\n extensions: string[],\n): { newBare: string } | undefined {\n // Strip .js extension for resolution (TypeScript convention)\n const cleanSpec = specifier.endsWith('.js') ? specifier.slice(0, -3) : specifier;\n const resolved = path.resolve(fromDir, cleanSpec);\n\n for (const ext of extensions) {\n const candidate = resolved + ext;\n const stripped = stripExtension(candidate);\n const match = renameMap.get(stripped);\n if (match) return match;\n }\n\n return undefined;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { convertName } from './convert-name.js';\n\nexport interface RenameRecord {\n oldPath: string;\n newPath: string;\n oldAbsPath: string;\n newAbsPath: string;\n}\n\n/**\n * Compute the rename for a file that violates the naming convention.\n * Returns null if no rename is needed or the target already exists.\n */\nexport function computeRename(\n relPath: string,\n targetConvention: string,\n projectRoot: string,\n): RenameRecord | null {\n const filename = path.basename(relPath);\n const dir = path.dirname(relPath);\n\n // Extract bare name (before first dot) — matches checkNaming logic\n const dotIndex = filename.indexOf('.');\n if (dotIndex === -1) return null;\n\n const bare = filename.slice(0, dotIndex);\n const suffix = filename.slice(dotIndex); // e.g. \".tsx\" or \".test.ts\"\n\n const newBare = convertName(bare, targetConvention);\n if (newBare === bare) return null;\n\n const newFilename = newBare + suffix;\n const newRelPath = path.join(dir, newFilename);\n const oldAbsPath = path.join(projectRoot, relPath);\n const newAbsPath = path.join(projectRoot, newRelPath);\n\n // Skip if target already exists\n if (fs.existsSync(newAbsPath)) return null;\n\n return { oldPath: relPath, newPath: newRelPath, oldAbsPath, newAbsPath };\n}\n\n/**\n * Execute a single rename on disk.\n * Returns true if successful, false if skipped (target exists).\n */\nexport function executeRename(rename: RenameRecord): boolean {\n if (fs.existsSync(rename.newAbsPath)) return false;\n fs.renameSync(rename.oldAbsPath, rename.newAbsPath);\n return true;\n}\n\n/**\n * Detect and deduplicate rename collisions.\n * If two planned renames target the same path, the second is removed.\n */\nexport function deduplicateRenames(renames: RenameRecord[]): RenameRecord[] {\n const seen = new Set<string>();\n const result: RenameRecord[] = [];\n for (const r of renames) {\n if (seen.has(r.newAbsPath)) continue;\n seen.add(r.newAbsPath);\n result.push(r);\n }\n return result;\n}\n","/**\n * Split a bare filename into its constituent words.\n *\n * Handles kebab-case, camelCase, PascalCase, and snake_case inputs.\n * Consecutive uppercase letters (acronyms like \"URL\") are kept together.\n */\nexport function splitIntoWords(name: string): string[] {\n // First, split on explicit separators (hyphens and underscores)\n const parts = name.split(/[-_]/);\n\n const words: string[] = [];\n for (const part of parts) {\n if (part === '') continue;\n\n // Split camelCase and PascalCase boundaries\n // \"UserProfile\" → [\"User\", \"Profile\"]\n // \"parseJSON\" → [\"parse\", \"JSON\"]\n // \"XMLParser\" → [\"XML\", \"Parser\"]\n let current = '';\n for (let i = 0; i < part.length; i++) {\n const ch = part[i];\n const isUpper = ch >= 'A' && ch <= 'Z';\n\n if (isUpper && current.length > 0) {\n const prevIsUpper =\n current[current.length - 1] >= 'A' && current[current.length - 1] <= 'Z';\n const nextIsLower = i + 1 < part.length && part[i + 1] >= 'a' && part[i + 1] <= 'z';\n\n if (!prevIsUpper || nextIsLower) {\n words.push(current.toLowerCase());\n current = '';\n }\n }\n current += ch;\n }\n if (current) words.push(current.toLowerCase());\n }\n\n return words;\n}\n\n/**\n * Convert a bare filename to the specified naming convention.\n *\n * @param bare - The bare filename without extension (e.g. \"UserProfile\")\n * @param target - The target convention (kebab-case, camelCase, PascalCase, snake_case)\n * @returns The converted name\n */\nexport function convertName(bare: string, target: string): string {\n const words = splitIntoWords(bare);\n if (words.length === 0) return bare;\n\n switch (target) {\n case 'kebab-case':\n return words.join('-');\n case 'camelCase':\n return words[0] + words.slice(1).map(capitalize).join('');\n case 'PascalCase':\n return words.map(capitalize).join('');\n case 'snake_case':\n return words.join('_');\n default:\n return bare;\n }\n}\n\nfunction capitalize(word: string): string {\n if (word.length === 0) return word;\n return word[0].toUpperCase() + word.slice(1);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ViberailsConfig } from '@viberails/types';\n\nexport interface TestStubRecord {\n path: string;\n absPath: string;\n moduleName: string;\n}\n\n/**\n * Generate a test stub record for a source file that is missing tests.\n * Returns null if the test file already exists.\n */\nexport function generateTestStub(\n sourceRelPath: string,\n config: ViberailsConfig,\n projectRoot: string,\n): TestStubRecord | null {\n const { testPattern } = config.structure;\n if (!testPattern) return null;\n\n const basename = path.basename(sourceRelPath);\n const stem = basename.slice(0, basename.indexOf('.'));\n const testSuffix = testPattern.replace('*', '');\n const testFilename = `${stem}${testSuffix}`;\n\n const dir = path.dirname(path.join(projectRoot, sourceRelPath));\n const testAbsPath = path.join(dir, testFilename);\n\n if (fs.existsSync(testAbsPath)) return null;\n\n return {\n path: path.relative(projectRoot, testAbsPath),\n absPath: testAbsPath,\n moduleName: stem,\n };\n}\n\n/**\n * Write a test stub file to disk.\n */\nexport function writeTestStub(stub: TestStubRecord, config: ViberailsConfig): void {\n const runner = config.stack.testRunner === 'jest' ? 'jest' : 'vitest';\n const importLine =\n runner === 'jest'\n ? '' // jest globals are available without import\n : \"import { describe, it, expect } from 'vitest';\\n\\n\";\n\n const content = `${importLine}describe('${stub.moduleName}', () => {\\n it.todo('add tests');\\n});\\n`;\n\n fs.mkdirSync(path.dirname(stub.absPath), { recursive: true });\n fs.writeFileSync(stub.absPath, content);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as p from '@clack/prompts';\nimport { generateConfig } from '@viberails/config';\nimport { scan } from '@viberails/scanner';\nimport type { ConfigConventions, ConventionValue } from '@viberails/types';\nimport chalk from 'chalk';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport { resolveWorkspacePackages } from '../utils/resolve-workspace-packages.js';\nimport { writeGeneratedFiles } from '../utils/write-generated-files.js';\nimport { setupClaudeCodeHook, setupPreCommitHook } from './init-hooks.js';\nimport type { WizardResult } from './init-wizard.js';\nimport { DEFAULT_WIZARD_RESULT, runWizard } from './init-wizard.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\n/**\n * Filter a ConfigConventions object to only include high-confidence entries.\n */\nfunction filterHighConfidence(conventions: ConfigConventions): ConfigConventions {\n const filtered: ConfigConventions = {};\n for (const [key, value] of Object.entries(conventions)) {\n if (value === undefined) continue;\n if (typeof value === 'string') {\n filtered[key as keyof ConfigConventions] = value;\n } else if (value._confidence === 'high') {\n filtered[key as keyof ConfigConventions] = value as ConventionValue;\n }\n }\n return filtered;\n}\n\n/**\n * Apply wizard choices to the generated config.\n */\nfunction applyWizardResult(config: ReturnType<typeof generateConfig>, wizard: WizardResult): void {\n config.enforcement = wizard.enforcement;\n if (!wizard.checks.fileSize) config.rules.maxFileLines = 0;\n config.rules.enforceNaming = wizard.checks.naming;\n config.rules.requireTests = wizard.checks.tests;\n config.rules.enforceBoundaries = wizard.checks.boundaries;\n}\n\n/**\n * Run the viberails init flow.\n *\n * @param options - CLI options\n * @param cwd - Working directory override (for testing)\n */\nexport async function initCommand(options: { yes?: boolean }, cwd?: string): Promise<void> {\n const startDir = cwd ?? process.cwd();\n\n // 1. Find project root\n const projectRoot = findProjectRoot(startDir);\n if (!projectRoot) {\n throw new Error(\n 'No package.json found in this directory or any parent.\\n\\n' +\n 'Make sure you are inside a JavaScript or TypeScript project, then run:\\n' +\n ' npx viberails',\n );\n }\n\n // 2. Check for existing config\n const configPath = path.join(projectRoot, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n console.log(\n chalk.yellow('!') +\n ' viberails is already initialized in this project.\\n' +\n ' Run ' +\n chalk.cyan('viberails sync') +\n ' to update the generated files.',\n );\n return;\n }\n\n // 3. Scan project\n p.intro('viberails');\n const s = p.spinner();\n s.start('Scanning project...');\n const scanResult = await scan(projectRoot);\n s.stop('Scan complete');\n\n // 4. Sparse project notice\n if (scanResult.statistics.totalFiles === 0) {\n p.log.warn(\n 'No source files detected. viberails will generate context with minimal content.\\n' +\n `Run ${chalk.cyan('viberails sync')} after adding source files.`,\n );\n }\n\n // 5. Interactive wizard or --yes defaults\n let wizard: WizardResult;\n if (options.yes) {\n wizard = { ...DEFAULT_WIZARD_RESULT };\n } else {\n const result = await runWizard(scanResult);\n if (!result) return;\n wizard = result;\n }\n\n // 6. Generate config\n const config = generateConfig(scanResult);\n if (options.yes) {\n config.conventions = filterHighConfidence(config.conventions);\n }\n\n // Apply wizard choices\n applyWizardResult(config, wizard);\n\n // 7. Infer boundary rules for workspace projects if boundaries enabled\n if (wizard.checks.boundaries && config.workspace && config.workspace.packages.length > 0) {\n s.start('Inferring boundary rules...');\n const { buildImportGraph, inferBoundaries } = await import('@viberails/graph');\n const packages = resolveWorkspacePackages(projectRoot, config.workspace);\n const graph = await buildImportGraph(projectRoot, { packages, ignore: config.ignore });\n const inferred = inferBoundaries(graph);\n const ruleCount = Object.values(inferred).reduce((sum, denied) => sum + denied.length, 0);\n if (ruleCount > 0) {\n config.boundaries = inferred;\n s.stop(`Inferred ${ruleCount} boundary rules`);\n } else {\n s.stop('No boundary rules could be inferred');\n config.rules.enforceBoundaries = false;\n }\n }\n\n // 8. Write config file\n fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`);\n\n // 9. Generate context and scan-result.json\n writeGeneratedFiles(projectRoot, config, scanResult);\n\n // 10. Update .gitignore\n updateGitignore(projectRoot);\n\n // 11. Set up hooks based on wizard choice\n if (wizard.integration.includes('pre-commit')) {\n setupPreCommitHook(projectRoot);\n }\n if (wizard.integration.includes('claude-hook')) {\n setupClaudeCodeHook(projectRoot);\n }\n\n // 12. Print summary\n p.log.success(`${chalk.bold('Created:')}`);\n console.log(` ${chalk.green('✓')} ${CONFIG_FILE}`);\n console.log(` ${chalk.green('✓')} .viberails/context.md`);\n console.log(` ${chalk.green('✓')} .viberails/scan-result.json`);\n\n p.outro(\n `${chalk.bold('Next steps:')}\\n` +\n ` 1. Review ${chalk.cyan('viberails.config.json')} and adjust rules\\n` +\n ` 2. Commit ${chalk.cyan('viberails.config.json')} and ${chalk.cyan('.viberails/context.md')}\\n` +\n ` 3. Run ${chalk.cyan('viberails check')} to verify your project passes`,\n );\n}\n\n/**\n * Append viberails entries to .gitignore if not already present.\n * Only scan-result.json is ignored — context.md should be committed\n * so AI agents can read the enforced rules.\n */\nfunction updateGitignore(projectRoot: string): void {\n const gitignorePath = path.join(projectRoot, '.gitignore');\n let content = '';\n\n if (fs.existsSync(gitignorePath)) {\n content = fs.readFileSync(gitignorePath, 'utf-8');\n }\n\n if (!content.includes('.viberails/scan-result.json')) {\n const block = '\\n# viberails\\n.viberails/scan-result.json\\n';\n fs.writeFileSync(gitignorePath, `${content.trimEnd()}\\n${block}`);\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { generateContext } from '@viberails/context';\nimport type { ScanResult, ViberailsConfig } from '@viberails/types';\n\nconst CONTEXT_DIR = '.viberails';\nconst CONTEXT_FILE = 'context.md';\nconst SCAN_RESULT_FILE = 'scan-result.json';\n\n/**\n * Write all generated files: context.md and scan-result.json.\n *\n * @param projectRoot - Absolute path to the project root\n * @param config - The viberails configuration\n * @param scanResult - The raw scan result\n */\nexport function writeGeneratedFiles(\n projectRoot: string,\n config: ViberailsConfig,\n scanResult: ScanResult,\n): void {\n const contextDir = path.join(projectRoot, CONTEXT_DIR);\n\n try {\n if (!fs.existsSync(contextDir)) {\n fs.mkdirSync(contextDir, { recursive: true });\n }\n\n const context = generateContext(config);\n fs.writeFileSync(path.join(contextDir, CONTEXT_FILE), context);\n\n fs.writeFileSync(\n path.join(contextDir, SCAN_RESULT_FILE),\n `${JSON.stringify(scanResult, null, 2)}\\n`,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to write generated files to ${contextDir}: ${message}`);\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport chalk from 'chalk';\n\n/**\n * Set up a Claude Code hook that runs viberails check after every file edit.\n * Writes to `.claude/settings.json` (project-level, committable).\n */\nexport function setupClaudeCodeHook(projectRoot: string): void {\n const claudeDir = path.join(projectRoot, '.claude');\n if (!fs.existsSync(claudeDir)) {\n fs.mkdirSync(claudeDir, { recursive: true });\n }\n\n const settingsPath = path.join(claudeDir, 'settings.json');\n let settings: Record<string, unknown> = {};\n\n if (fs.existsSync(settingsPath)) {\n try {\n settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8')) as Record<string, unknown>;\n } catch {\n // If invalid JSON, start fresh\n }\n }\n\n // Check if hook already exists\n const hooks = (settings.hooks ?? {}) as Record<string, unknown>;\n const postToolUse = hooks.PostToolUse;\n if (Array.isArray(postToolUse)) {\n const hasViberails = postToolUse.some(\n (entry: unknown) =>\n typeof entry === 'object' &&\n entry !== null &&\n Array.isArray((entry as Record<string, unknown>).hooks) &&\n ((entry as Record<string, unknown>).hooks as unknown[]).some(\n (h: unknown) =>\n typeof h === 'object' &&\n h !== null &&\n typeof (h as Record<string, unknown>).command === 'string' &&\n ((h as Record<string, unknown>).command as string).includes('viberails'),\n ),\n );\n if (hasViberails) return;\n }\n\n const viberailsHook = {\n matcher: 'Edit|Write',\n hooks: [\n {\n type: 'command',\n command: \"jq -r '.tool_input.file_path' | xargs npx viberails check --files\",\n },\n ],\n };\n\n if (!hooks.PostToolUse) {\n hooks.PostToolUse = [viberailsHook];\n } else if (Array.isArray(hooks.PostToolUse)) {\n (hooks.PostToolUse as unknown[]).push(viberailsHook);\n }\n\n settings.hooks = hooks;\n fs.writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\\n`);\n console.log(` ${chalk.green('✓')} .claude/settings.json — added viberails PostToolUse hook`);\n}\n\n/**\n * Set up a pre-commit hook that runs viberails check on staged files.\n * Detects Lefthook, Husky, or falls back to a raw git hook.\n */\nexport function setupPreCommitHook(projectRoot: string): void {\n // Check for Lefthook\n const lefthookPath = path.join(projectRoot, 'lefthook.yml');\n if (fs.existsSync(lefthookPath)) {\n addLefthookPreCommit(lefthookPath);\n console.log(` ${chalk.green('✓')} lefthook.yml — added viberails pre-commit`);\n return;\n }\n\n // Check for Husky\n const huskyDir = path.join(projectRoot, '.husky');\n if (fs.existsSync(huskyDir)) {\n writeHuskyPreCommit(huskyDir);\n console.log(` ${chalk.green('✓')} .husky/pre-commit — added viberails check`);\n return;\n }\n\n // Fall back to raw git hook\n const gitDir = path.join(projectRoot, '.git');\n if (fs.existsSync(gitDir)) {\n const hooksDir = path.join(gitDir, 'hooks');\n if (!fs.existsSync(hooksDir)) {\n fs.mkdirSync(hooksDir, { recursive: true });\n }\n writeGitHookPreCommit(hooksDir);\n console.log(` ${chalk.green('✓')} .git/hooks/pre-commit`);\n }\n}\n\nfunction writeGitHookPreCommit(hooksDir: string): void {\n const hookPath = path.join(hooksDir, 'pre-commit');\n if (fs.existsSync(hookPath)) {\n const existing = fs.readFileSync(hookPath, 'utf-8');\n if (existing.includes('viberails')) return;\n fs.writeFileSync(\n hookPath,\n `${existing.trimEnd()}\\n\\n# viberails check\\nnpx viberails check --staged\\n`,\n );\n return;\n }\n const script = [\n '#!/bin/sh',\n '# Generated by viberails — https://viberails.sh',\n '',\n 'npx viberails check --staged',\n '',\n ].join('\\n');\n fs.writeFileSync(hookPath, script, { mode: 0o755 });\n}\n\nfunction addLefthookPreCommit(lefthookPath: string): void {\n const content = fs.readFileSync(lefthookPath, 'utf-8');\n if (content.includes('viberails')) return;\n const addition = ['', ' viberails:', ' run: npx viberails check --staged'].join('\\n');\n fs.writeFileSync(lefthookPath, `${content.trimEnd()}\\n${addition}\\n`);\n}\n\nfunction writeHuskyPreCommit(huskyDir: string): void {\n const hookPath = path.join(huskyDir, 'pre-commit');\n if (fs.existsSync(hookPath)) {\n const existing = fs.readFileSync(hookPath, 'utf-8');\n if (!existing.includes('viberails')) {\n fs.writeFileSync(hookPath, `${existing.trimEnd()}\\nnpx viberails check --staged\\n`);\n }\n return;\n }\n fs.writeFileSync(hookPath, '#!/bin/sh\\nnpx viberails check --staged\\n', { mode: 0o755 });\n}\n","import * as p from '@clack/prompts';\nimport type { ScanResult } from '@viberails/types';\nimport { FRAMEWORK_NAMES, LIBRARY_NAMES, STYLING_NAMES } from '@viberails/types';\nimport chalk from 'chalk';\nimport { formatItem } from '../display.js';\nimport { formatRoleGroup, formatSummary, groupByRole } from '../display-helpers.js';\n\nexport type IntegrationChoice = 'pre-commit' | 'claude-hook' | 'context-only';\n\nexport interface WizardResult {\n enforcement: 'warn' | 'enforce';\n checks: {\n fileSize: boolean;\n naming: boolean;\n tests: boolean;\n boundaries: boolean;\n };\n integration: IntegrationChoice[];\n}\n\n/** Default wizard result used in --yes mode. */\nexport const DEFAULT_WIZARD_RESULT: WizardResult = {\n enforcement: 'warn',\n checks: {\n fileSize: true,\n naming: true,\n tests: true,\n boundaries: false,\n },\n integration: ['pre-commit'],\n};\n\n/**\n * Display scan results in @clack's visual style and run the interactive wizard.\n *\n * @param scanResult - The output of scanning the project\n * @returns The user's wizard choices, or null if cancelled\n */\nexport async function runWizard(scanResult: ScanResult): Promise<WizardResult | null> {\n const isMonorepo = scanResult.packages.length > 1;\n\n // Display scan results\n displayScanSummary(scanResult);\n\n // Step 1: Enforcement mode\n const enforcement = await p.select({\n message: 'How strict should viberails be?',\n initialValue: 'warn' as const,\n options: [\n { value: 'warn' as const, label: 'Warn', hint: 'show issues, never block commits' },\n { value: 'enforce' as const, label: 'Enforce', hint: 'block commits with violations' },\n ],\n });\n\n if (p.isCancel(enforcement)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n // Step 2: Check toggles\n const checkOptions = [\n { value: 'fileSize' as const, label: 'File size limit (300 lines)' },\n { value: 'naming' as const, label: 'File naming conventions' },\n { value: 'tests' as const, label: 'Missing test files' },\n ];\n\n if (isMonorepo) {\n checkOptions.push({ value: 'boundaries' as const, label: 'Import boundaries' });\n }\n\n const enabledChecks = await p.multiselect({\n message: 'Which checks should viberails run?',\n options: checkOptions,\n initialValues: ['fileSize', 'naming', 'tests'] as const,\n required: false,\n });\n\n if (p.isCancel(enabledChecks)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n const checks = {\n fileSize: enabledChecks.includes('fileSize'),\n naming: enabledChecks.includes('naming'),\n tests: enabledChecks.includes('tests'),\n boundaries: enabledChecks.includes('boundaries'),\n };\n\n // Step 3: Integration\n const integrationOptions = [\n { value: 'pre-commit' as const, label: 'Git pre-commit hook', hint: 'runs on every commit' },\n {\n value: 'claude-hook' as const,\n label: 'Claude Code hook',\n hint: 'checks files as Claude edits them',\n },\n { value: 'context-only' as const, label: 'Context files only', hint: 'no hooks' },\n ];\n\n const integration = await p.multiselect({\n message: 'Where should checks run?',\n options: integrationOptions,\n initialValues: ['pre-commit'] as IntegrationChoice[],\n required: true,\n });\n\n if (p.isCancel(integration)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n // If context-only is selected alongside hooks, just use context-only\n const finalIntegration = integration.includes('context-only')\n ? (['context-only'] as IntegrationChoice[])\n : integration;\n\n return {\n enforcement,\n checks,\n integration: finalIntegration,\n };\n}\n\n/** Display a compact scan summary using console.log (works well with @clack). */\nfunction displayScanSummary(scanResult: ScanResult): void {\n const { stack } = scanResult;\n const parts: string[] = [];\n\n if (stack.framework) parts.push(formatItem(stack.framework, FRAMEWORK_NAMES));\n parts.push(formatItem(stack.language));\n if (stack.styling) parts.push(formatItem(stack.styling, STYLING_NAMES));\n if (stack.backend) parts.push(formatItem(stack.backend, FRAMEWORK_NAMES));\n\n p.log.info(`${chalk.bold('Stack:')} ${parts.join(', ')}`);\n\n if (stack.linter || stack.formatter || stack.testRunner || stack.packageManager) {\n const tools: string[] = [];\n if (stack.linter) tools.push(formatItem(stack.linter));\n if (stack.formatter && stack.formatter !== stack.linter)\n tools.push(formatItem(stack.formatter));\n if (stack.testRunner) tools.push(formatItem(stack.testRunner));\n if (stack.packageManager) tools.push(formatItem(stack.packageManager));\n p.log.info(`${chalk.bold('Tools:')} ${tools.join(', ')}`);\n }\n\n if (stack.libraries.length > 0) {\n const libs = stack.libraries.map((lib) => formatItem(lib, LIBRARY_NAMES)).join(', ');\n p.log.info(`${chalk.bold('Libraries:')} ${libs}`);\n }\n\n // Structure\n const groups = groupByRole(scanResult.structure.directories);\n if (groups.length > 0) {\n const structParts = groups.map((g) => formatRoleGroup(g));\n p.log.info(`${chalk.bold('Structure:')} ${structParts.join(', ')}`);\n }\n\n // Conventions (inline)\n const conventionEntries = Object.entries(scanResult.conventions).filter(\n ([, c]) => c.confidence !== 'low',\n );\n if (conventionEntries.length > 0) {\n const convParts = conventionEntries.map(([, c]) => {\n const pct = Math.round(c.consistency);\n return `${c.value} (${pct}%)`;\n });\n p.log.info(`${chalk.bold('Conventions:')} ${convParts.join(', ')}`);\n }\n\n // Summary stats\n const pkgCount = scanResult.packages.length > 1 ? scanResult.packages.length : undefined;\n p.log.info(`${chalk.bold('Summary:')} ${formatSummary(scanResult.statistics, pkgCount)}`);\n}\n","import type { DetectedConvention, ScanResult, StackItem } from '@viberails/types';\nimport { FRAMEWORK_NAMES, LIBRARY_NAMES, STYLING_NAMES } from '@viberails/types';\nimport chalk from 'chalk';\nimport {\n formatExtensions,\n formatRoleGroup,\n formatSummary,\n groupByRole,\n} from './display-helpers.js';\nimport { displayMonorepoResults } from './display-monorepo.js';\n\n/** Labels for convention keys. */\nconst CONVENTION_LABELS: Record<string, string> = {\n fileNaming: 'File naming',\n componentNaming: 'Component naming',\n hookNaming: 'Hook naming',\n importAlias: 'Import alias',\n};\n\n/**\n * Format a StackItem for display: \"DisplayName Version\".\n */\nexport function formatItem(item: StackItem, nameMap?: Record<string, string>): string {\n const name = nameMap?.[item.name] ?? item.name;\n return item.version ? `${name} ${item.version}` : name;\n}\n\n/**\n * Format a confidence label for display.\n */\nexport function confidenceLabel(convention: DetectedConvention): string {\n const pct = Math.round(convention.consistency);\n if (convention.confidence === 'high') {\n return `${pct}% — high confidence, will enforce`;\n }\n return `${pct}% — medium confidence, suggested only`;\n}\n\n/**\n * Display conventions section, shared between single-package and monorepo.\n */\nexport function displayConventions(scanResult: ScanResult): void {\n const conventionEntries = Object.entries(scanResult.conventions);\n if (conventionEntries.length === 0) return;\n\n console.log(`\\n${chalk.bold('Conventions:')}`);\n for (const [key, convention] of conventionEntries) {\n if (convention.confidence === 'low') continue;\n const label = CONVENTION_LABELS[key] ?? key;\n\n if (scanResult.packages.length > 1) {\n const pkgValues = scanResult.packages\n .filter((pkg) => pkg.conventions[key] && pkg.conventions[key].confidence !== 'low')\n .map((pkg) => ({ relativePath: pkg.relativePath, convention: pkg.conventions[key] }));\n\n const allSame = pkgValues.every((pv) => pv.convention.value === convention.value);\n\n if (allSame || pkgValues.length <= 1) {\n const ind = convention.confidence === 'high' ? chalk.green('✓') : chalk.yellow('~');\n const detail = chalk.dim(`(${confidenceLabel(convention)})`);\n console.log(` ${ind} ${label}: ${convention.value} ${detail}`);\n } else {\n console.log(` ${chalk.yellow('~')} ${label}: varies by package`);\n for (const pv of pkgValues) {\n const pct = Math.round(pv.convention.consistency);\n console.log(` ${pv.relativePath}: ${pv.convention.value} (${pct}%)`);\n }\n }\n } else {\n const ind = convention.confidence === 'high' ? chalk.green('✓') : chalk.yellow('~');\n const detail = chalk.dim(`(${confidenceLabel(convention)})`);\n console.log(` ${ind} ${label}: ${convention.value} ${detail}`);\n }\n }\n}\n\n/**\n * Display summary section with statistics.\n */\nexport function displaySummarySection(scanResult: ScanResult): void {\n const pkgCount = scanResult.packages.length > 1 ? scanResult.packages.length : undefined;\n console.log(`\\n${chalk.bold('Summary:')}`);\n console.log(` ${formatSummary(scanResult.statistics, pkgCount)}`);\n const ext = formatExtensions(scanResult.statistics.filesByExtension);\n if (ext) {\n console.log(` ${ext}`);\n }\n}\n\n/**\n * Display scan results to the console with confidence indicators.\n *\n * @param scanResult - The scan result to display\n */\nexport function displayScanResults(scanResult: ScanResult): void {\n if (scanResult.packages.length > 1) {\n displayMonorepoResults(scanResult);\n return;\n }\n\n const { stack } = scanResult;\n\n console.log(`\\n${chalk.bold('Detected:')}`);\n\n if (stack.framework) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.framework, FRAMEWORK_NAMES)}`);\n }\n console.log(` ${chalk.green('✓')} ${formatItem(stack.language)}`);\n if (stack.styling) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.styling, STYLING_NAMES)}`);\n }\n if (stack.backend) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.backend, FRAMEWORK_NAMES)}`);\n }\n if (stack.linter) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.linter)}`);\n }\n if (stack.formatter) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.formatter)}`);\n }\n if (stack.testRunner) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.testRunner)}`);\n }\n if (stack.packageManager) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.packageManager)}`);\n }\n if (stack.libraries.length > 0) {\n for (const lib of stack.libraries) {\n console.log(` ${chalk.green('✓')} ${formatItem(lib, LIBRARY_NAMES)}`);\n }\n }\n\n // Structure grouped by role\n const groups = groupByRole(scanResult.structure.directories);\n if (groups.length > 0) {\n console.log(`\\n${chalk.bold('Structure:')}`);\n for (const group of groups) {\n console.log(` ${chalk.green('✓')} ${formatRoleGroup(group)}`);\n }\n }\n\n displayConventions(scanResult);\n displaySummarySection(scanResult);\n console.log('');\n}\n","import type { CodebaseStatistics, DirectoryInfo, DirectoryRole } from '@viberails/types';\nimport { ROLE_DESCRIPTIONS } from '@viberails/types';\n\n/**\n * A group of directories sharing the same role within a package.\n */\nexport interface RoleGroup {\n role: DirectoryRole;\n label: string;\n dirCount: number;\n totalFiles: number;\n singlePath?: string;\n}\n\n/**\n * Groups a package's directories by role, merging file counts.\n * Filters out `unknown` role. For single-directory roles, sets `singlePath`.\n *\n * @param directories - The directories to group.\n * @returns Array of RoleGroup entries sorted by role label.\n */\nexport function groupByRole(directories: DirectoryInfo[]): RoleGroup[] {\n const map = new Map<DirectoryRole, { dirs: DirectoryInfo[] }>();\n\n for (const dir of directories) {\n if (dir.role === 'unknown') continue;\n const existing = map.get(dir.role);\n if (existing) {\n existing.dirs.push(dir);\n } else {\n map.set(dir.role, { dirs: [dir] });\n }\n }\n\n const groups: RoleGroup[] = [];\n for (const [role, { dirs }] of map) {\n const label = ROLE_DESCRIPTIONS[role] ?? role;\n const totalFiles = dirs.reduce((sum, d) => sum + d.fileCount, 0);\n groups.push({\n role,\n label,\n dirCount: dirs.length,\n totalFiles,\n singlePath: dirs.length === 1 ? dirs[0].path : undefined,\n });\n }\n\n return groups;\n}\n\n/**\n * Format a summary line from CodebaseStatistics.\n *\n * @param stats - The codebase statistics.\n * @param packageCount - Number of packages (shown for monorepos with > 1).\n * @returns Formatted summary string, e.g. \"3 packages · 743 source files · 48,200 lines · avg 65 lines/file\"\n */\nexport function formatSummary(stats: CodebaseStatistics, packageCount?: number): string {\n const parts: string[] = [];\n if (packageCount && packageCount > 1) {\n parts.push(`${packageCount} packages`);\n }\n parts.push(`${stats.totalFiles.toLocaleString()} source files`);\n parts.push(`${stats.totalLines.toLocaleString()} lines`);\n parts.push(`avg ${Math.round(stats.averageFileLines)} lines/file`);\n return parts.join(' \\u00b7 ');\n}\n\n/**\n * Format top extensions by count, e.g. \".tsx 312 · .ts 289 · .js 142\".\n *\n * @param filesByExtension - Extension counts from CodebaseStatistics.\n * @param maxEntries - Maximum number of extensions to show (default 4).\n * @returns Formatted extension string.\n */\nexport function formatExtensions(\n filesByExtension: Record<string, number>,\n maxEntries: number = 4,\n): string {\n return Object.entries(filesByExtension)\n .sort(([, a], [, b]) => b - a)\n .slice(0, maxEntries)\n .map(([ext, count]) => `${ext} ${count}`)\n .join(' \\u00b7 ');\n}\n\n/**\n * Format a RoleGroup for display.\n *\n * @param group - The role group.\n * @returns Formatted string, e.g. \"Hooks — 4 dirs (55 files)\" or \"Pages / Routes — app (12 files)\"\n */\nexport function formatRoleGroup(group: RoleGroup): string {\n const files = group.totalFiles === 1 ? '1 file' : `${group.totalFiles} files`;\n if (group.singlePath) {\n return `${group.label} — ${group.singlePath} (${files})`;\n }\n const dirs = group.dirCount === 1 ? '1 dir' : `${group.dirCount} dirs`;\n return `${group.label} — ${dirs} (${files})`;\n}\n","import type { PackageScanResult, ScanResult } from '@viberails/types';\nimport { FRAMEWORK_NAMES, STYLING_NAMES } from '@viberails/types';\nimport chalk from 'chalk';\nimport { displayConventions, displaySummarySection, formatItem } from './display.js';\nimport { formatRoleGroup, groupByRole } from './display-helpers.js';\n\n/**\n * Format a package summary line for monorepo display.\n */\nexport function formatPackageSummary(pkg: PackageScanResult): string {\n const parts: string[] = [];\n if (pkg.stack.framework) {\n parts.push(formatItem(pkg.stack.framework, FRAMEWORK_NAMES));\n }\n if (pkg.stack.styling) {\n parts.push(formatItem(pkg.stack.styling, STYLING_NAMES));\n }\n const files = `${pkg.statistics.totalFiles} files`;\n const detail = parts.length > 0 ? `${parts.join(', ')} (${files})` : `(${files})`;\n return ` ${pkg.relativePath} — ${detail}`;\n}\n\n/**\n * Display scan results for a monorepo with per-package summaries.\n */\nexport function displayMonorepoResults(scanResult: ScanResult): void {\n const { stack, packages } = scanResult;\n\n console.log(`\\n${chalk.bold(`Detected: (monorepo, ${packages.length} packages)`)}`);\n\n // Shared stack items at the top\n console.log(` ${chalk.green('✓')} ${formatItem(stack.language)}`);\n if (stack.packageManager) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.packageManager)}`);\n }\n if (stack.linter) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.linter)}`);\n }\n if (stack.formatter) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.formatter)}`);\n }\n if (stack.testRunner) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.testRunner)}`);\n }\n\n // Per-package summaries\n console.log('');\n for (const pkg of packages) {\n console.log(formatPackageSummary(pkg));\n }\n\n // Structure grouped by role per package\n const packagesWithDirs = packages.filter((pkg) =>\n pkg.structure.directories.some((d) => d.role !== 'unknown'),\n );\n if (packagesWithDirs.length > 0) {\n console.log(`\\n${chalk.bold('Structure:')}`);\n for (const pkg of packagesWithDirs) {\n const groups = groupByRole(pkg.structure.directories);\n if (groups.length === 0) continue;\n console.log(` ${pkg.relativePath}:`);\n for (const group of groups) {\n console.log(` ${chalk.green('✓')} ${formatRoleGroup(group)}`);\n }\n }\n }\n\n displayConventions(scanResult);\n displaySummarySection(scanResult);\n console.log('');\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { loadConfig, mergeConfig } from '@viberails/config';\nimport { scan } from '@viberails/scanner';\nimport chalk from 'chalk';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport { writeGeneratedFiles } from '../utils/write-generated-files.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\n/**\n * Run the viberails sync flow: re-scan, merge config, regenerate context.\n *\n * @param cwd - Working directory override (for testing)\n */\nexport async function syncCommand(cwd?: string): Promise<void> {\n const startDir = cwd ?? process.cwd();\n\n // 1. Find project root\n const projectRoot = findProjectRoot(startDir);\n if (!projectRoot) {\n throw new Error(\n 'No package.json found in this directory or any parent.\\n\\n' +\n 'Make sure you are inside a JavaScript or TypeScript project, then run:\\n' +\n ' npx viberails',\n );\n }\n\n // 2. Load existing config\n const configPath = path.join(projectRoot, CONFIG_FILE);\n const existing = await loadConfig(configPath);\n\n // 3. Re-scan\n console.log(chalk.dim('Scanning project...'));\n const scanResult = await scan(projectRoot);\n\n // 4. Merge config\n const merged = mergeConfig(existing, scanResult);\n fs.writeFileSync(configPath, `${JSON.stringify(merged, null, 2)}\\n`);\n\n // 5. Regenerate context and scan-result.json\n writeGeneratedFiles(projectRoot, merged, scanResult);\n\n console.log(`\\n${chalk.bold('Synced:')}`);\n console.log(` ${chalk.green('✓')} ${CONFIG_FILE} — updated`);\n console.log(` ${chalk.green('✓')} .viberails/context.md — regenerated`);\n console.log(` ${chalk.green('✓')} .viberails/scan-result.json — updated`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,iBAAkB;AAClB,uBAAwB;;;ACDxB,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;AACtB,oBAA2B;AAE3B,mBAAkB;;;ACJlB,SAAoB;AACpB,WAAsB;AAQf,SAAS,gBAAgB,UAAiC;AAC/D,MAAI,MAAW,aAAQ,QAAQ;AAE/B,SAAO,MAAM;AACX,QAAO,cAAgB,UAAK,KAAK,cAAc,CAAC,GAAG;AACjD,aAAO;AAAA,IACT;AAEA,UAAM,SAAc,aAAQ,GAAG;AAC/B,QAAI,WAAW,KAAK;AAClB,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;;;ACvBA,eAA0B;AAQ1B,eAAsB,QAAQ,SAAmC;AAC/D,QAAM,KAAc,yBAAgB;AAAA,IAClC,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ;AAAA,EAClB,CAAC;AAED,SAAO,IAAI,QAAiB,CAACC,aAAY;AACvC,OAAG,SAAS,GAAG,OAAO,WAAW,CAAC,WAAW;AAC3C,SAAG,MAAM;AACT,YAAM,UAAU,OAAO,KAAK,EAAE,YAAY;AAC1C,MAAAA,SAAQ,YAAY,MAAM,YAAY,OAAO,YAAY,KAAK;AAAA,IAChE,CAAC;AAAA,EACH,CAAC;AACH;;;ACrBA,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;AAaf,SAAS,yBACd,aACA,WACoB;AACpB,QAAM,WAA+B,CAAC;AAEtC,aAAW,gBAAgB,UAAU,UAAU;AAC7C,UAAM,UAAe,WAAK,aAAa,YAAY;AACnD,UAAM,cAAmB,WAAK,SAAS,cAAc;AAErD,QAAI,CAAI,eAAW,WAAW,EAAG;AAEjC,QAAI;AACJ,QAAI;AACF,YAAM,KAAK,MAAS,iBAAa,aAAa,OAAO,CAAC;AAAA,IACxD,QAAQ;AACN;AAAA,IACF;AAEA,UAAM,OAAO,IAAI;AACjB,QAAI,CAAC,KAAM;AAEX,UAAM,UAAU;AAAA,MACd,GAAG,OAAO,KAAM,IAAI,gBAA4C,CAAC,CAAC;AAAA,MAClE,GAAG,OAAO,KAAM,IAAI,mBAA+C,CAAC,CAAC;AAAA,IACvE;AAEA,aAAS,KAAK,EAAE,MAAM,MAAM,SAAS,cAAc,cAAc,QAAQ,CAAC;AAAA,EAC5E;AAGA,QAAM,eAAe,IAAI,IAAI,SAAS,IAAI,CAACC,OAAMA,GAAE,IAAI,CAAC;AACxD,aAAW,OAAO,UAAU;AAC1B,QAAI,eAAe,IAAI,aAAa,OAAO,CAAC,QAAQ,aAAa,IAAI,GAAG,CAAC;AAAA,EAC3E;AAEA,SAAO;AACT;;;AH1CA,IAAM,cAAc;AAapB,eAAsB,kBAAkB,SAA4B,KAA6B;AAC/F,QAAM,WAAW,OAAO,QAAQ,IAAI;AACpC,QAAM,cAAc,gBAAgB,QAAQ;AAC5C,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AAEA,QAAM,aAAkB,WAAK,aAAa,WAAW;AACrD,MAAI,CAAI,eAAW,UAAU,GAAG;AAC9B,UAAM,IAAI,MAAM,6DAA6D;AAAA,EAC/E;AAEA,QAAM,SAAS,UAAM,0BAAW,UAAU;AAE1C,MAAI,QAAQ,OAAO;AACjB,UAAM,UAAU,aAAa,MAAM;AACnC;AAAA,EACF;AAEA,MAAI,QAAQ,OAAO;AACjB,UAAM,gBAAgB,aAAa,QAAQ,UAAU;AACrD;AAAA,EACF;AAEA,eAAa,MAAM;AACrB;AAGA,SAAS,gBAAgB,YAAmD;AAC1E,MAAI,CAAC,WAAY,QAAO;AACxB,MAAI,MAAM,QAAQ,UAAU,EAAG,QAAO,WAAW;AACjD,SAAO,OAAO,OAAO,UAAU,EAAE,OAAO,CAAC,KAAK,WAAW,MAAM,OAAO,QAAQ,CAAC;AACjF;AAGA,SAAS,aAAa,QAA+B;AACnD,QAAM,QAAQ,gBAAgB,OAAO,UAAU;AAC/C,MAAI,UAAU,GAAG;AACf,YAAQ,IAAI,aAAAC,QAAM,OAAO,+BAA+B,CAAC;AACzD,YAAQ,IAAI,OAAO,aAAAA,QAAM,KAAK,8BAA8B,CAAC,qBAAqB;AAClF;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,EAAK,aAAAA,QAAM,KAAK,mBAAmB,KAAK,UAAU,CAAC;AAAA,CAAI;AAEnE,MAAI,MAAM,QAAQ,OAAO,UAAU,GAAG;AACpC,UAAM,aAAa,OAAO,WAAW,OAAO,CAAC,MAAM,EAAE,KAAK;AAC1D,UAAM,YAAY,OAAO,WAAW,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK;AAE1D,eAAW,KAAK,YAAY;AAC1B,cAAQ,IAAI,KAAK,aAAAA,QAAM,MAAM,QAAG,CAAC,IAAI,EAAE,IAAI,WAAM,EAAE,EAAE,EAAE;AAAA,IACzD;AACA,eAAW,KAAK,WAAW;AACzB,YAAM,SAAS,EAAE,SAAS,aAAAA,QAAM,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI;AACxD,cAAQ,IAAI,KAAK,aAAAA,QAAM,IAAI,QAAG,CAAC,IAAI,EAAE,IAAI,WAAM,EAAE,EAAE,GAAG,MAAM,EAAE;AAAA,IAChE;AAAA,EACF,WAAW,OAAO,YAAY;AAC5B,eAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AAC9D,iBAAW,MAAM,QAAQ;AACvB,gBAAQ,IAAI,KAAK,aAAAA,QAAM,IAAI,QAAG,CAAC,IAAI,IAAI,WAAM,EAAE,EAAE;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAEA,UAAQ;AAAA,IACN;AAAA,eAAkB,OAAO,MAAM,oBAAoB,aAAAA,QAAM,MAAM,IAAI,IAAI,aAAAA,QAAM,OAAO,KAAK,CAAC;AAAA,EAC5F;AACF;AAGA,eAAe,gBACb,aACA,QACA,YACe;AACf,UAAQ,IAAI,aAAAA,QAAM,IAAI,sBAAsB,CAAC;AAC7C,QAAM,EAAE,kBAAkB,gBAAgB,IAAI,MAAM,OAAO,kBAAkB;AAE7E,QAAM,WAAW,OAAO,YACpB,yBAAyB,aAAa,OAAO,SAAS,IACtD;AAEJ,QAAM,QAAQ,MAAM,iBAAiB,aAAa;AAAA,IAChD;AAAA,IACA,QAAQ,OAAO;AAAA,EACjB,CAAC;AAED,UAAQ,IAAI,aAAAA,QAAM,IAAI,GAAG,MAAM,MAAM,MAAM,WAAW,MAAM,MAAM,MAAM,QAAQ,CAAC;AAEjF,QAAM,WAAW,gBAAgB,KAAK;AACtC,QAAM,UAAU,OAAO,QAAQ,QAAQ;AAEvC,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,aAAAA,QAAM,OAAO,sCAAsC,CAAC;AAChE;AAAA,EACF;AAEA,QAAM,aAAa,QAAQ,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,CAAC;AAE7E,UAAQ,IAAI;AAAA,EAAK,aAAAA,QAAM,KAAK,0BAA0B,CAAC;AAAA,CAAI;AAE3D,aAAW,CAAC,MAAM,MAAM,KAAK,SAAS;AACpC,eAAW,MAAM,QAAQ;AACvB,cAAQ,IAAI,KAAK,aAAAA,QAAM,IAAI,QAAG,CAAC,IAAI,IAAI,WAAM,EAAE,EAAE;AAAA,IACnD;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,IAAO,UAAU,aAAa;AAE1C,QAAM,aAAa,MAAM,QAAQ,kCAAkC;AACnE,MAAI,YAAY;AACd,WAAO,aAAa;AACpB,WAAO,MAAM,oBAAoB;AACjC,IAAG,kBAAc,YAAY,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AACnE,YAAQ,IAAI,GAAG,aAAAA,QAAM,MAAM,QAAG,CAAC,UAAU,UAAU,QAAQ;AAAA,EAC7D;AACF;AAGA,eAAe,UAAU,aAAqB,QAAwC;AACpF,UAAQ,IAAI,aAAAA,QAAM,IAAI,0BAA0B,CAAC;AACjD,QAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,kBAAkB;AAE5D,QAAM,WAAW,OAAO,YACpB,yBAAyB,aAAa,OAAO,SAAS,IACtD;AAEJ,QAAM,QAAQ,MAAM,iBAAiB,aAAa;AAAA,IAChD;AAAA,IACA,QAAQ,OAAO;AAAA,EACjB,CAAC;AAED,UAAQ,IAAI;AAAA,EAAK,aAAAA,QAAM,KAAK,0BAA0B,CAAC;AAAA,CAAI;AAC3D,UAAQ,IAAI,KAAK,MAAM,MAAM,MAAM,WAAW,MAAM,MAAM,MAAM;AAAA,CAAY;AAE5E,MAAI,MAAM,SAAS,SAAS,GAAG;AAC7B,eAAW,OAAO,MAAM,UAAU;AAChC,YAAM,OACJ,IAAI,aAAa,SAAS,IACtB;AAAA,EAAK,IAAI,aAAa,IAAI,CAAC,MAAM,cAAS,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KACzD,aAAAA,QAAM,IAAI,qBAAqB;AACrC,cAAQ,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE;AAAA,IACpC;AAAA,EACF;AAEA,MAAI,MAAM,OAAO,SAAS,GAAG;AAC3B,YAAQ,IAAI;AAAA,EAAK,aAAAA,QAAM,OAAO,kBAAkB,CAAC,EAAE;AACnD,eAAW,SAAS,MAAM,QAAQ;AAChC,YAAM,QAAQ,MAAM,IAAI,CAAC,MAAW,eAAS,aAAa,CAAC,CAAC;AAC5D,cAAQ,IAAI,KAAK,MAAM,KAAK,UAAK,CAAC,EAAE;AAAA,IACtC;AAAA,EACF;AACF;;;AI9KA,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;AACtB,IAAAC,iBAA2B;AAE3B,IAAAC,gBAAkB;;;ACOX,SAAS,qBAAqB,SAAiB,QAAyC;AAC7F,MAAI,CAAC,OAAO,YAAY,OAAO,SAAS,WAAW,GAAG;AACpD,WAAO,EAAE,OAAO,OAAO,OAAO,aAAa,OAAO,YAAY;AAAA,EAChE;AAGA,QAAM,iBAAiB,CAAC,GAAG,OAAO,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,EAAE,KAAK,MAAM;AAExF,aAAW,OAAO,gBAAgB;AAChC,QAAI,QAAQ,WAAW,GAAG,IAAI,IAAI,GAAG,KAAK,YAAY,IAAI,MAAM;AAC9D,aAAO;AAAA,QACL,OAAO,EAAE,GAAG,OAAO,OAAO,GAAG,IAAI,MAAM;AAAA,QACvC,aAAa,EAAE,GAAG,OAAO,aAAa,GAAG,IAAI,YAAY;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,OAAO,OAAO,aAAa,OAAO,YAAY;AAChE;AAKO,SAAS,qBAAqB,SAAiB,QAAmC;AACvF,QAAM,eAAe,OAAO;AAC5B,MAAI,CAAC,OAAO,SAAU,QAAO;AAE7B,aAAW,OAAO,OAAO,UAAU;AACjC,QAAI,IAAI,UAAU,QAAQ,WAAW,GAAG,IAAI,IAAI,GAAG,GAAG;AACpD,aAAO,CAAC,GAAG,cAAc,GAAG,IAAI,MAAM;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;;;AC5CA,gCAAyB;AACzB,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;AAGtB,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;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,CAAC;AAEM,IAAM,cAAc,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,kBAA0C;AAAA,EACrD,cAAc;AAAA,EACd,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AACd;AAGO,SAAS,UAAU,SAAiB,gBAAmC;AAC5E,aAAW,WAAW,gBAAgB;AACpC,UAAM,aAAa,QAAQ,WAAW,KAAK;AAC3C,UAAM,WAAW,QAAQ,SAAS,KAAK;AAEvC,QAAI,cAAc,UAAU;AAE1B,YAAM,SAAS,QAAQ,MAAM,GAAG,EAAE;AAClC,UACE,QAAQ,WAAW,GAAG,MAAM,GAAG,KAC/B,QAAQ,SAAS,IAAI,MAAM,GAAG,KAC9B,YAAY,QACZ;AACA,eAAO;AAAA,MACT;AAAA,IACF,WAAW,UAAU;AACnB,YAAM,SAAS,QAAQ,MAAM,GAAG,EAAE;AAClC,UAAI,QAAQ,WAAW,GAAG,MAAM,GAAG,KAAK,YAAY,OAAQ,QAAO;AAAA,IACrE,WAAW,YAAY;AACrB,YAAM,SAAS,QAAQ,MAAM,CAAC;AAC9B,UAAI,QAAQ,SAAS,MAAM,KAAK,YAAY,OAAQ,QAAO;AAAA,IAC7D,WAAW,YAAY,WAAW,QAAQ,WAAW,GAAG,OAAO,GAAG,GAAG;AACnE,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,eAAe,UAAiC;AAC9D,MAAI;AACF,UAAM,UAAa,iBAAa,UAAU,OAAO;AACjD,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAI,QAAQ;AACZ,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAI,QAAQ,WAAW,CAAC,MAAM,GAAI;AAAA,IACpC;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,YAAY,SAAiB,aAAoD;AAC/F,QAAM,WAAgB,eAAS,OAAO;AAGtC,QAAM,MAAW,cAAQ,QAAQ;AACjC,MAAI,CAAC,YAAY,IAAI,GAAG,EAAG,QAAO;AAGlC,MACE,SAAS,WAAW,QAAQ,KAC5B,SAAS,SAAS,UAAU,KAC5B,SAAS,SAAS,QAAQ,KAC1B,SAAS,SAAS,QAAQ,KAC1B,SAAS,WAAW,GAAG,KACvB,SAAS,WAAW,GAAG,KACvB,SAAS,WAAW,GAAG,KACvB,SAAS,WAAW,GAAG,KACvB,SAAS,WAAW,GAAG,GACvB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,SAAS,MAAM,GAAG,SAAS,QAAQ,GAAG,CAAC;AACpD,QAAM,aACJ,OAAO,YAAY,eAAe,WAC9B,YAAY,aACX,YAAY,YAA6D;AAEhF,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,UAAU,gBAAgB,UAAU;AAC1C,MAAI,CAAC,WAAW,QAAQ,KAAK,IAAI,EAAG,QAAO;AAE3C,SAAO,cAAc,QAAQ,qBAAqB,UAAU;AAC9D;AAGO,SAAS,eAAe,aAA+B;AAC5D,MAAI;AACF,UAAM,aAAS,oCAAS,mDAAmD;AAAA,MACzE,KAAK;AAAA,MACL,UAAU;AAAA,IACZ,CAAC;AACD,WAAO,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,OAAO;AAAA,EACjD,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAGO,SAAS,kBAAkB,aAAqB,QAAmC;AACxF,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,CAAC,QAAgB;AAC5B,QAAI;AACJ,QAAI;AACF,gBAAa,gBAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,IACvD,QAAQ;AACN;AAAA,IACF;AACA,eAAW,SAAS,SAAS;AAC3B,YAAM,MAAW,eAAS,aAAkB,WAAK,KAAK,MAAM,IAAI,CAAC;AACjE,UAAI,MAAM,YAAY,GAAG;AACvB,YAAI,iBAAiB,IAAI,MAAM,IAAI,GAAG;AACpC;AAAA,QACF;AACA,YAAI,UAAU,KAAK,OAAO,MAAM,EAAG;AACnC,aAAU,WAAK,KAAK,MAAM,IAAI,CAAC;AAAA,MACjC,WAAW,MAAM,OAAO,GAAG;AACzB,cAAM,MAAW,cAAQ,MAAM,IAAI;AACnC,YAAI,YAAY,IAAI,GAAG,KAAK,CAAC,UAAU,KAAK,OAAO,MAAM,GAAG;AAC1D,gBAAM,KAAK,GAAG;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,OAAK,WAAW;AAChB,SAAO;AACT;AAGO,SAAS,mBAAmB,KAAa,aAA+B;AAC7E,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,CAAC,MAAc;AAC1B,QAAI;AACJ,QAAI;AACF,gBAAa,gBAAY,GAAG,EAAE,eAAe,KAAK,CAAC;AAAA,IACrD,QAAQ;AACN;AAAA,IACF;AACA,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,YAAY,GAAG;AACvB,YAAI,MAAM,SAAS,eAAgB;AACnC,aAAU,WAAK,GAAG,MAAM,IAAI,CAAC;AAAA,MAC/B,WAAW,MAAM,OAAO,GAAG;AACzB,cAAM,KAAU,eAAS,aAAkB,WAAK,GAAG,MAAM,IAAI,CAAC,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AACA,OAAK,GAAG;AACR,SAAO;AACT;;;AC3LA,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;AAItB,IAAMC,eAAc,oBAAI,IAAI;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,kBACd,aACA,QACA,UACkB;AAClB,QAAM,aAA+B,CAAC;AACtC,QAAM,EAAE,YAAY,IAAI,OAAO;AAC/B,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,SAAS,OAAO,UAAU;AAChC,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,UAAe,WAAK,aAAa,MAAM;AAC7C,MAAI,CAAI,eAAW,OAAO,EAAG,QAAO;AAEpC,QAAM,aAAa,YAAY,QAAQ,KAAK,EAAE;AAC9C,QAAM,cAAc,mBAAmB,SAAS,WAAW;AAE3D,aAAW,WAAW,aAAa;AACjC,UAAMC,YAAgB,eAAS,OAAO;AAGtC,QACEA,UAAS,SAAS,QAAQ,KAC1BA,UAAS,SAAS,QAAQ,KAC1BA,UAAS,WAAW,QAAQ,KAC5BA,UAAS,SAAS,OAAO,GACzB;AACA;AAAA,IACF;AAEA,UAAM,MAAW,cAAQA,SAAQ;AACjC,QAAI,CAACD,aAAY,IAAI,GAAG,EAAG;AAE3B,UAAM,OAAOC,UAAS,MAAM,GAAGA,UAAS,QAAQ,GAAG,CAAC;AACpD,UAAM,mBAAmB,GAAG,IAAI,GAAG,UAAU;AAG7C,UAAM,MAAW,cAAa,WAAK,aAAa,OAAO,CAAC;AACxD,UAAM,gBAAqB,WAAK,KAAK,gBAAgB;AACrD,UAAM,WAAW,OAAO,UAAU;AAClC,UAAM,gBAAgB,WAAgB,WAAK,aAAa,UAAU,gBAAgB,IAAI;AAEtF,UAAM,UACD,eAAW,aAAa,KAAM,kBAAkB,QAAW,eAAW,aAAa;AAExF,QAAI,CAAC,SAAS;AACZ,iBAAW,KAAK;AAAA,QACd,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,kCAAkC,gBAAgB;AAAA,QAC3D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;;;AHxDA,IAAMC,eAAc;AAWpB,SAAS,WAAW,SAA0B;AAC5C,QAAM,WAAgB,eAAS,OAAO;AACtC,SACE,SAAS,SAAS,QAAQ,KAC1B,SAAS,SAAS,QAAQ,KAC1B,SAAS,WAAW,OAAO,KAC3B,SAAS,WAAW,OAAO,KAC3B,QAAQ,SAAS,YAAY,KAC7B,QAAQ,SAAS,WAAW;AAEhC;AAKA,SAAS,uBAAuB,YAA8B,OAAsB;AAClF,QAAM,SAAS,oBAAI,IAA8B;AACjD,aAAW,KAAK,YAAY;AAC1B,UAAM,WAAW,OAAO,IAAI,EAAE,IAAI,KAAK,CAAC;AACxC,aAAS,KAAK,CAAC;AACf,WAAO,IAAI,EAAE,MAAM,QAAQ;AAAA,EAC7B;AAEA,QAAM,YAAY,CAAC,aAAa,eAAe,gBAAgB,oBAAoB;AACnF,QAAM,aAAa,CAAC,GAAG,OAAO,KAAK,CAAC,EAAE;AAAA,IACpC,CAAC,GAAG,OACD,UAAU,QAAQ,CAAC,MAAM,KAAK,KAAK,UAAU,QAAQ,CAAC,MACtD,UAAU,QAAQ,CAAC,MAAM,KAAK,KAAK,UAAU,QAAQ,CAAC;AAAA,EAC3D;AAEA,MAAI,aAAa;AACjB,QAAM,aAAa,SAAS,OAAO;AAEnC,aAAW,QAAQ,YAAY;AAC7B,UAAM,QAAQ,OAAO,IAAI,IAAI;AAC7B,QAAI,CAAC,MAAO;AACZ,UAAM,YAAY,aAAa;AAC/B,QAAI,aAAa,EAAG;AAEpB,UAAM,SAAS,MAAM,MAAM,GAAG,SAAS;AACvC,UAAM,SAAS,MAAM,SAAS,OAAO;AAErC,eAAW,KAAK,QAAQ;AACtB,YAAM,OAAO,EAAE,aAAa,UAAU,cAAAC,QAAM,IAAI,QAAG,IAAI,cAAAA,QAAM,OAAO,GAAG;AACvE,cAAQ,IAAI,GAAG,IAAI,IAAI,cAAAA,QAAM,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AAAA,IACpE;AACA,kBAAc,OAAO;AAErB,QAAI,SAAS,GAAG;AACd,cAAQ,IAAI,cAAAA,QAAM,IAAI,aAAa,MAAM,SAAS,IAAI,aAAa,CAAC;AAAA,IACtE;AAAA,EACF;AACF;AAKA,SAAS,aAAa,YAAoC;AACxD,QAAM,SAAS,oBAAI,IAAoB;AACvC,aAAW,KAAK,YAAY;AAC1B,WAAO,IAAI,EAAE,OAAO,OAAO,IAAI,EAAE,IAAI,KAAK,KAAK,CAAC;AAAA,EAClD;AAEA,QAAM,OAAO,WAAW,WAAW,IAAI,cAAc;AACrD,QAAM,QAAQ,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,GAAG,KAAK,IAAI,IAAI,EAAE;AAC7E,UAAQ,IAAI;AAAA,EAAK,WAAW,MAAM,IAAI,IAAI,WAAW,MAAM,KAAK,IAAI,CAAC,IAAI;AAC3E;AAMA,eAAsB,aAAa,SAAuB,KAA+B;AACvF,QAAM,WAAW,OAAO,QAAQ,IAAI;AAEpC,QAAM,cAAc,gBAAgB,QAAQ;AAC5C,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,GAAG,cAAAA,QAAM,IAAI,QAAQ,CAAC,qDAAqD;AACzF,WAAO;AAAA,EACT;AAEA,QAAM,aAAkB,WAAK,aAAaD,YAAW;AACrD,MAAI,CAAI,eAAW,UAAU,GAAG;AAC9B,YAAQ;AAAA,MACN,GAAG,cAAAC,QAAM,IAAI,QAAQ,CAAC;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,UAAM,2BAAW,UAAU;AAG1C,MAAI;AACJ,MAAI,QAAQ,QAAQ;AAClB,mBAAe,eAAe,WAAW;AAAA,EAC3C,WAAW,QAAQ,SAAS,QAAQ,MAAM,SAAS,GAAG;AACpD,mBAAe,QAAQ;AAAA,EACzB,OAAO;AACL,mBAAe,kBAAkB,aAAa,MAAM;AAAA,EACtD;AAEA,MAAI,aAAa,WAAW,GAAG;AAC7B,YAAQ,IAAI,GAAG,cAAAA,QAAM,MAAM,QAAG,CAAC,qBAAqB;AACpD,WAAO;AAAA,EACT;AAEA,QAAM,aAA+B,CAAC;AACtC,QAAM,WAAW,OAAO,gBAAgB,YAAY,UAAU;AAE9D,aAAW,QAAQ,cAAc;AAC/B,UAAM,UAAe,iBAAW,IAAI,IAAI,OAAY,WAAK,aAAa,IAAI;AAC1E,UAAM,UAAe,eAAS,aAAa,OAAO;AAElD,UAAM,kBAAkB,qBAAqB,SAAS,MAAM;AAC5D,QAAI,UAAU,SAAS,eAAe,EAAG;AACzC,QAAI,CAAI,eAAW,OAAO,EAAG;AAE7B,UAAM,WAAW,qBAAqB,SAAS,MAAM;AAGrD,UAAM,WAAW,WAAW,OAAO;AACnC,UAAM,WAAW,WAAW,SAAS,MAAM,mBAAmB,SAAS,MAAM;AAC7E,QAAI,WAAW,GAAG;AAChB,YAAM,QAAQ,eAAe,OAAO;AACpC,UAAI,UAAU,QAAQ,QAAQ,UAAU;AACtC,mBAAW,KAAK;AAAA,UACd,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,GAAG,KAAK,eAAe,QAAQ;AAAA,UACxC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,SAAS,MAAM,iBAAiB,SAAS,YAAY,YAAY;AACnE,YAAM,kBAAkB,YAAY,SAAS,SAAS,WAAW;AACjE,UAAI,iBAAiB;AACnB,mBAAW,KAAK;AAAA,UACd,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,MAAM,gBAAgB,CAAC,QAAQ,UAAU,CAAC,QAAQ,OAAO;AAClE,UAAM,iBAAiB,kBAAkB,aAAa,QAAQ,QAAQ;AACtE,eAAW,KAAK,GAAG,cAAc;AAAA,EACnC;AAGA,QAAM,gBAAgB,OAAO,aACzB,MAAM,QAAQ,OAAO,UAAU,IAC7B,OAAO,WAAW,SAAS,IAC3B,OAAO,KAAK,OAAO,UAAU,EAAE,SAAS,IAC1C;AACJ,MAAI,OAAO,MAAM,qBAAqB,iBAAiB,CAAC,QAAQ,cAAc;AAC5E,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,EAAE,kBAAkB,gBAAgB,IAAI,MAAM,OAAO,kBAAkB;AAE7E,UAAM,WAAW,OAAO,YACpB,yBAAyB,aAAa,OAAO,SAAS,IACtD;AAEJ,UAAM,QAAQ,MAAM,iBAAiB,aAAa;AAAA,MAChD;AAAA,MACA,QAAQ,OAAO;AAAA,IACjB,CAAC;AAED,UAAM,qBAAqB,gBAAgB,OAAO,OAAO,UAAU;AAGnE,UAAM,YACJ,QAAQ,UAAU,QAAQ,QACtB,IAAI,IAAI,aAAa,IAAI,CAAC,MAAW,cAAQ,aAAa,CAAC,CAAC,CAAC,IAC7D;AAEN,eAAW,MAAM,oBAAoB;AACnC,UAAI,aAAa,CAAC,UAAU,IAAI,GAAG,IAAI,EAAG;AAE1C,YAAM,UAAe,eAAS,aAAa,GAAG,IAAI;AAClD,iBAAW,KAAK;AAAA,QACd,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,YAAY,GAAG,SAAS,yBAAyB,GAAG,KAAK,IAAI,WAAM,GAAG,KAAK,EAAE,GAAG,GAAG,KAAK,SAAS,KAAK,GAAG,KAAK,MAAM,MAAM,EAAE;AAAA,QACrI;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,YAAQ,IAAI,cAAAA,QAAM,IAAI,qBAAqB,MAAM,MAAM,MAAM,aAAa,OAAO,IAAI,CAAC;AAAA,EACxF;AAGA,MAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,IAAI,GAAG,cAAAA,QAAM,MAAM,QAAG,CAAC,IAAI,aAAa,MAAM,qCAAgC;AACtF,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ,OAAO;AAClB,2BAAuB,YAAY,QAAQ,KAAK;AAAA,EAClD;AAEA,eAAa,UAAU;AAEvB,MAAI,OAAO,gBAAgB,WAAW;AACpC,YAAQ,IAAI,cAAAA,QAAM,IAAI,mCAAmC,CAAC;AAC1D,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;AIrPA,IAAAC,MAAoB;AACpB,IAAAC,SAAsB;AACtB,IAAAC,iBAA2B;AAC3B,IAAAC,gBAAkB;;;ACHlB,IAAAC,6BAAyB;AACzB,2BAAgC;AAChC,IAAAC,gBAAkB;AAOX,SAAS,UAAU,SAAyB,OAA+B;AAChF,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,cAAAC,QAAM,KAAK,iBAAiB,CAAC;AACzC,eAAW,KAAK,SAAS;AACvB,cAAQ,IAAI,KAAK,cAAAA,QAAM,IAAI,EAAE,OAAO,CAAC,WAAM,cAAAA,QAAM,MAAM,EAAE,OAAO,CAAC,EAAE;AAAA,IACrE;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,YAAQ,IAAI,cAAAA,QAAM,KAAK,yBAAyB,CAAC;AACjD,eAAW,KAAK,OAAO;AACrB,cAAQ,IAAI,KAAK,cAAAA,QAAM,MAAM,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE;AAAA,IAC/C;AAAA,EACF;AACF;AAKO,SAAS,cAAc,aAA8B;AAC1D,MAAI;AACF,UAAM,aAAS,qCAAS,0BAA0B;AAAA,MAChD,KAAK;AAAA,MACL,UAAU;AAAA,IACZ,CAAC;AACD,WAAO,OAAO,KAAK,EAAE,SAAS;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,mBAAmB,YAAyC;AAC1E,MAAI,OAAO,eAAe,SAAU,QAAO;AAC3C,MAAI,cAAc,OAAO,eAAe,YAAY,WAAW,YAAY;AACzE,WAAQ,WAAiC;AAAA,EAC3C;AACA,SAAO;AACT;AAKO,SAAS,cAAc,UAAoC;AAChE,QAAM,SAAK,sCAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,SAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,OAAG,SAAS,GAAG,QAAQ,WAAW,CAAC,WAAW;AAC5C,SAAG,MAAM;AACT,MAAAA,SAAQ,OAAO,YAAY,MAAM,OAAO,OAAO,YAAY,MAAM,KAAK;AAAA,IACxE,CAAC;AAAA,EACH,CAAC;AACH;;;AC9DA,IAAAC,QAAsB;AActB,SAAS,eAAe,UAA0B;AAChD,SAAO,SAAS,QAAQ,0BAA0B,EAAE;AACtD;AAMA,SAAS,oBAAoB,cAAsB,SAAyB;AAC1E,QAAM,WAAW,aAAa,SAAS,KAAK;AAC5C,QAAM,OAAO,WAAW,aAAa,MAAM,GAAG,EAAE,IAAI;AAGpD,QAAM,MAAM,KAAK,YAAY,GAAG;AAChC,QAAM,SAAS,OAAO,IAAI,KAAK,MAAM,GAAG,MAAM,CAAC,IAAI;AACnD,QAAM,UAAU,SAAS;AAEzB,SAAO,WAAW,GAAG,OAAO,QAAQ;AACtC;AAUA,eAAsB,0BACpB,SACA,aAC+B;AAC/B,MAAI,QAAQ,WAAW,EAAG,QAAO,CAAC;AAGlC,QAAM,EAAE,SAAS,WAAW,IAAI,MAAM,OAAO,UAAU;AAGvD,QAAM,YAAY,oBAAI,IAAiC;AACvD,aAAW,KAAK,SAAS;AACvB,UAAM,cAAc,eAAe,EAAE,UAAU;AAC/C,UAAM,cAAmB,eAAS,EAAE,OAAO;AAC3C,UAAM,UAAU,YAAY,MAAM,GAAG,YAAY,QAAQ,GAAG,CAAC;AAC7D,cAAU,IAAI,aAAa,EAAE,SAAS,QAAQ,CAAC;AAAA,EACjD;AAEA,QAAM,UAAU,IAAI,QAAQ;AAAA,IAC1B,kBAAkB;AAAA,IAClB,6BAA6B;AAAA,EAC/B,CAAC;AAGD,UAAQ,sBAA2B,WAAK,aAAa,8BAA8B,CAAC;AAEpF,QAAM,UAAgC,CAAC;AACvC,QAAM,aAAa,CAAC,IAAI,OAAO,QAAQ,OAAO,QAAQ,aAAa,cAAc,WAAW;AAE5F,aAAW,cAAc,QAAQ,eAAe,GAAG;AACjD,UAAM,WAAW,WAAW,YAAY;AAExC,QAAI,SAAS,SAAS,gBAAgB,KAAK,SAAS,SAAS,QAAQ,EAAG;AAExE,UAAM,UAAe,cAAQ,QAAQ;AAGrC,eAAW,QAAQ,WAAW,sBAAsB,GAAG;AACrD,YAAM,YAAY,KAAK,wBAAwB;AAC/C,UAAI,CAAC,UAAU,WAAW,GAAG,EAAG;AAEhC,YAAM,QAAQ,qBAAqB,WAAW,SAAS,WAAW,UAAU;AAC5E,UAAI,CAAC,MAAO;AAEZ,YAAM,UAAU,oBAAoB,WAAW,MAAM,OAAO;AAC5D,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,cAAc;AAAA,QACd,cAAc;AAAA,QACd,MAAM,KAAK,mBAAmB;AAAA,MAChC,CAAC;AACD,WAAK,mBAAmB,OAAO;AAAA,IACjC;AAGA,eAAW,QAAQ,WAAW,sBAAsB,GAAG;AACrD,YAAM,YAAY,KAAK,wBAAwB;AAC/C,UAAI,CAAC,aAAa,CAAC,UAAU,WAAW,GAAG,EAAG;AAE9C,YAAM,QAAQ,qBAAqB,WAAW,SAAS,WAAW,UAAU;AAC5E,UAAI,CAAC,MAAO;AAEZ,YAAM,UAAU,oBAAoB,WAAW,MAAM,OAAO;AAC5D,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,cAAc;AAAA,QACd,cAAc;AAAA,QACd,MAAM,KAAK,mBAAmB;AAAA,MAChC,CAAC;AACD,WAAK,mBAAmB,OAAO;AAAA,IACjC;AAGA,eAAW,QAAQ,WAAW,qBAAqB,WAAW,cAAc,GAAG;AAC7E,UAAI,KAAK,cAAc,EAAE,QAAQ,MAAM,WAAW,cAAe;AAEjE,YAAM,OAAO,KAAK,aAAa;AAC/B,UAAI,KAAK,WAAW,EAAG;AAEvB,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,IAAI,QAAQ,MAAM,WAAW,cAAe;AAEhD,YAAM,YAAY,IAAI,QAAQ,EAAE,MAAM,GAAG,EAAE;AAC3C,UAAI,CAAC,UAAU,WAAW,GAAG,EAAG;AAEhC,YAAM,QAAQ,qBAAqB,WAAW,SAAS,WAAW,UAAU;AAC5E,UAAI,CAAC,MAAO;AAEZ,YAAM,UAAU,oBAAoB,WAAW,MAAM,OAAO;AAC5D,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,cAAc;AAAA,QACd,cAAc;AAAA,QACd,MAAM,KAAK,mBAAmB;AAAA,MAChC,CAAC;AAED,YAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;AAC7B,UAAI,gBAAgB,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,EAAE;AAAA,IAClD;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,QAAQ,KAAK;AAAA,EACrB;AAEA,SAAO;AACT;AAMA,SAAS,qBACP,WACA,SACA,WACA,YACiC;AAEjC,QAAM,YAAY,UAAU,SAAS,KAAK,IAAI,UAAU,MAAM,GAAG,EAAE,IAAI;AACvE,QAAM,WAAgB,cAAQ,SAAS,SAAS;AAEhD,aAAW,OAAO,YAAY;AAC5B,UAAM,YAAY,WAAW;AAC7B,UAAM,WAAW,eAAe,SAAS;AACzC,UAAM,QAAQ,UAAU,IAAI,QAAQ;AACpC,QAAI,MAAO,QAAO;AAAA,EACpB;AAEA,SAAO;AACT;;;AC5KA,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;;;ACKf,SAAS,eAAe,MAAwB;AAErD,QAAM,QAAQ,KAAK,MAAM,MAAM;AAE/B,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,GAAI;AAMjB,QAAI,UAAU;AACd,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,KAAK,KAAK,CAAC;AACjB,YAAM,UAAU,MAAM,OAAO,MAAM;AAEnC,UAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,cAAM,cACJ,QAAQ,QAAQ,SAAS,CAAC,KAAK,OAAO,QAAQ,QAAQ,SAAS,CAAC,KAAK;AACvE,cAAM,cAAc,IAAI,IAAI,KAAK,UAAU,KAAK,IAAI,CAAC,KAAK,OAAO,KAAK,IAAI,CAAC,KAAK;AAEhF,YAAI,CAAC,eAAe,aAAa;AAC/B,gBAAM,KAAK,QAAQ,YAAY,CAAC;AAChC,oBAAU;AAAA,QACZ;AAAA,MACF;AACA,iBAAW;AAAA,IACb;AACA,QAAI,QAAS,OAAM,KAAK,QAAQ,YAAY,CAAC;AAAA,EAC/C;AAEA,SAAO;AACT;AASO,SAAS,YAAY,MAAc,QAAwB;AAChE,QAAM,QAAQ,eAAe,IAAI;AACjC,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,MAAM,KAAK,GAAG;AAAA,IACvB,KAAK;AACH,aAAO,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,EAAE,IAAI,UAAU,EAAE,KAAK,EAAE;AAAA,IAC1D,KAAK;AACH,aAAO,MAAM,IAAI,UAAU,EAAE,KAAK,EAAE;AAAA,IACtC,KAAK;AACH,aAAO,MAAM,KAAK,GAAG;AAAA,IACvB;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,WAAW,MAAsB;AACxC,MAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,SAAO,KAAK,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AAC7C;;;ADtDO,SAAS,cACd,SACA,kBACA,aACqB;AACrB,QAAM,WAAgB,eAAS,OAAO;AACtC,QAAM,MAAW,cAAQ,OAAO;AAGhC,QAAM,WAAW,SAAS,QAAQ,GAAG;AACrC,MAAI,aAAa,GAAI,QAAO;AAE5B,QAAM,OAAO,SAAS,MAAM,GAAG,QAAQ;AACvC,QAAM,SAAS,SAAS,MAAM,QAAQ;AAEtC,QAAM,UAAU,YAAY,MAAM,gBAAgB;AAClD,MAAI,YAAY,KAAM,QAAO;AAE7B,QAAM,cAAc,UAAU;AAC9B,QAAM,aAAkB,WAAK,KAAK,WAAW;AAC7C,QAAM,aAAkB,WAAK,aAAa,OAAO;AACjD,QAAM,aAAkB,WAAK,aAAa,UAAU;AAGpD,MAAO,eAAW,UAAU,EAAG,QAAO;AAEtC,SAAO,EAAE,SAAS,SAAS,SAAS,YAAY,YAAY,WAAW;AACzE;AAMO,SAAS,cAAc,QAA+B;AAC3D,MAAO,eAAW,OAAO,UAAU,EAAG,QAAO;AAC7C,EAAG,eAAW,OAAO,YAAY,OAAO,UAAU;AAClD,SAAO;AACT;AAMO,SAAS,mBAAmB,SAAyC;AAC1E,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAAyB,CAAC;AAChC,aAAW,KAAK,SAAS;AACvB,QAAI,KAAK,IAAI,EAAE,UAAU,EAAG;AAC5B,SAAK,IAAI,EAAE,UAAU;AACrB,WAAO,KAAK,CAAC;AAAA,EACf;AACA,SAAO;AACT;;;AEnEA,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;AAaf,SAAS,iBACd,eACA,QACA,aACuB;AACvB,QAAM,EAAE,YAAY,IAAI,OAAO;AAC/B,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAMC,YAAgB,eAAS,aAAa;AAC5C,QAAM,OAAOA,UAAS,MAAM,GAAGA,UAAS,QAAQ,GAAG,CAAC;AACpD,QAAM,aAAa,YAAY,QAAQ,KAAK,EAAE;AAC9C,QAAM,eAAe,GAAG,IAAI,GAAG,UAAU;AAEzC,QAAM,MAAW,cAAa,WAAK,aAAa,aAAa,CAAC;AAC9D,QAAM,cAAmB,WAAK,KAAK,YAAY;AAE/C,MAAO,eAAW,WAAW,EAAG,QAAO;AAEvC,SAAO;AAAA,IACL,MAAW,eAAS,aAAa,WAAW;AAAA,IAC5C,SAAS;AAAA,IACT,YAAY;AAAA,EACd;AACF;AAKO,SAAS,cAAc,MAAsB,QAA+B;AACjF,QAAM,SAAS,OAAO,MAAM,eAAe,SAAS,SAAS;AAC7D,QAAM,aACJ,WAAW,SACP,KACA;AAEN,QAAM,UAAU,GAAG,UAAU,aAAa,KAAK,UAAU;AAAA;AAAA;AAAA;AAEzD,EAAG,cAAe,cAAQ,KAAK,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,EAAG,kBAAc,KAAK,SAAS,OAAO;AACxC;;;ALnCA,IAAMC,eAAc;AAYpB,eAAsB,WAAW,SAAqB,KAA+B;AACnF,QAAM,WAAW,OAAO,QAAQ,IAAI;AACpC,QAAM,cAAc,gBAAgB,QAAQ;AAE5C,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,GAAG,cAAAC,QAAM,IAAI,QAAQ,CAAC,qDAAqD;AACzF,WAAO;AAAA,EACT;AAEA,QAAM,aAAkB,YAAK,aAAaD,YAAW;AACrD,MAAI,CAAI,eAAW,UAAU,GAAG;AAC9B,YAAQ;AAAA,MACN,GAAG,cAAAC,QAAM,IAAI,QAAQ,CAAC;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,UAAM,2BAAW,UAAU;AAG1C,MAAI,CAAC,QAAQ,QAAQ;AACnB,UAAM,UAAU,cAAc,WAAW;AACzC,QAAI,SAAS;AACX,cAAQ;AAAA,QACN,cAAAA,QAAM,OAAO,mEAAmE;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,kBAAkB,CAAC,QAAQ,QAAQ,QAAQ,KAAK,SAAS,aAAa;AAC5E,QAAM,iBAAiB,CAAC,QAAQ,QAAQ,QAAQ,KAAK,SAAS,cAAc;AAG5E,QAAM,WAAW,kBAAkB,aAAa,MAAM;AAGtD,QAAM,UAA0B,CAAC;AACjC,MAAI,iBAAiB;AACnB,eAAW,QAAQ,UAAU;AAC3B,YAAM,WAAW,qBAAqB,MAAM,MAAM;AAClD,UAAI,CAAC,SAAS,MAAM,iBAAiB,CAAC,SAAS,YAAY,WAAY;AAEvE,YAAM,YAAY,YAAY,MAAM,SAAS,WAAW;AACxD,UAAI,CAAC,UAAW;AAEhB,YAAM,aAAa,mBAAmB,SAAS,YAAY,UAAU;AACrE,UAAI,CAAC,WAAY;AAEjB,YAAM,SAAS,cAAc,MAAM,YAAY,WAAW;AAC1D,UAAI,OAAQ,SAAQ,KAAK,MAAM;AAAA,IACjC;AAAA,EACF;AAEA,QAAM,iBAAiB,mBAAmB,OAAO;AAGjD,QAAM,YAA8B,CAAC;AACrC,MAAI,kBAAkB,OAAO,MAAM,cAAc;AAC/C,UAAM,iBAAiB,kBAAkB,aAAa,QAAQ,MAAM;AACpE,eAAW,KAAK,gBAAgB;AAC9B,YAAM,OAAO,iBAAiB,EAAE,MAAM,QAAQ,WAAW;AACzD,UAAI,KAAM,WAAU,KAAK,IAAI;AAAA,IAC/B;AAAA,EACF;AAGA,MAAI,eAAe,WAAW,KAAK,UAAU,WAAW,GAAG;AACzD,YAAQ,IAAI,GAAG,cAAAA,QAAM,MAAM,QAAG,CAAC,+BAA+B;AAC9D,WAAO;AAAA,EACT;AAGA,YAAU,gBAAgB,SAAS;AAEnC,MAAI,QAAQ,QAAQ;AAClB,YAAQ,IAAI,cAAAA,QAAM,IAAI,sCAAiC,CAAC;AACxD,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,QAAQ,KAAK;AAChB,UAAM,YAAY,MAAM,cAAc,oBAAoB;AAC1D,QAAI,CAAC,WAAW;AACd,cAAQ,IAAI,UAAU;AACtB,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,cAAc;AAClB,aAAW,UAAU,gBAAgB;AACnC,QAAI,cAAc,MAAM,GAAG;AACzB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,oBAAoB;AACxB,MAAI,cAAc,GAAG;AACnB,UAAM,iBAAiB,eAAe,OAAO,CAAC,MAAS,eAAW,EAAE,UAAU,CAAC;AAC/E,UAAM,UAAU,MAAM,0BAA0B,gBAAgB,WAAW;AAC3E,wBAAoB,QAAQ;AAAA,EAC9B;AAGA,MAAI,YAAY;AAChB,aAAW,QAAQ,WAAW;AAC5B,QAAI,CAAI,eAAW,KAAK,OAAO,GAAG;AAChC,oBAAc,MAAM,MAAM;AAC1B;AAAA,IACF;AAAA,EACF;AAGA,UAAQ,IAAI,EAAE;AACd,MAAI,cAAc,GAAG;AACnB,YAAQ,IAAI,GAAG,cAAAA,QAAM,MAAM,QAAG,CAAC,YAAY,WAAW,QAAQ,cAAc,IAAI,MAAM,EAAE,EAAE;AAAA,EAC5F;AACA,MAAI,oBAAoB,GAAG;AACzB,YAAQ;AAAA,MACN,GAAG,cAAAA,QAAM,MAAM,QAAG,CAAC,YAAY,iBAAiB,UAAU,oBAAoB,IAAI,MAAM,EAAE;AAAA,IAC5F;AAAA,EACF;AACA,MAAI,YAAY,GAAG;AACjB,YAAQ,IAAI,GAAG,cAAAA,QAAM,MAAM,QAAG,CAAC,cAAc,SAAS,aAAa,YAAY,IAAI,MAAM,EAAE,EAAE;AAAA,EAC/F;AAEA,SAAO;AACT;;;AM9JA,IAAAC,OAAoB;AACpB,IAAAC,SAAsB;AACtB,IAAAC,KAAmB;AACnB,IAAAC,iBAA+B;AAC/B,qBAAqB;AAErB,IAAAC,gBAAkB;;;ACNlB,IAAAC,OAAoB;AACpB,IAAAC,SAAsB;AACtB,qBAAgC;AAGhC,IAAM,cAAc;AACpB,IAAM,eAAe;AACrB,IAAM,mBAAmB;AASlB,SAAS,oBACd,aACA,QACA,YACM;AACN,QAAM,aAAkB,YAAK,aAAa,WAAW;AAErD,MAAI;AACF,QAAI,CAAI,gBAAW,UAAU,GAAG;AAC9B,MAAG,eAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,IAC9C;AAEA,UAAM,cAAU,gCAAgB,MAAM;AACtC,IAAG,mBAAmB,YAAK,YAAY,YAAY,GAAG,OAAO;AAE7D,IAAG;AAAA,MACI,YAAK,YAAY,gBAAgB;AAAA,MACtC,GAAG,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAAA;AAAA,IACxC;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,IAAI,MAAM,sCAAsC,UAAU,KAAK,OAAO,EAAE;AAAA,EAChF;AACF;;;ACvCA,IAAAC,OAAoB;AACpB,IAAAC,SAAsB;AACtB,IAAAC,gBAAkB;AAMX,SAAS,oBAAoB,aAA2B;AAC7D,QAAM,YAAiB,YAAK,aAAa,SAAS;AAClD,MAAI,CAAI,gBAAW,SAAS,GAAG;AAC7B,IAAG,eAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC7C;AAEA,QAAM,eAAoB,YAAK,WAAW,eAAe;AACzD,MAAI,WAAoC,CAAC;AAEzC,MAAO,gBAAW,YAAY,GAAG;AAC/B,QAAI;AACF,iBAAW,KAAK,MAAS,kBAAa,cAAc,OAAO,CAAC;AAAA,IAC9D,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,QAAM,QAAS,SAAS,SAAS,CAAC;AAClC,QAAM,cAAc,MAAM;AAC1B,MAAI,MAAM,QAAQ,WAAW,GAAG;AAC9B,UAAM,eAAe,YAAY;AAAA,MAC/B,CAAC,UACC,OAAO,UAAU,YACjB,UAAU,QACV,MAAM,QAAS,MAAkC,KAAK,KACpD,MAAkC,MAAoB;AAAA,QACtD,CAAC,MACC,OAAO,MAAM,YACb,MAAM,QACN,OAAQ,EAA8B,YAAY,YAChD,EAA8B,QAAmB,SAAS,WAAW;AAAA,MAC3E;AAAA,IACJ;AACA,QAAI,aAAc;AAAA,EACpB;AAEA,QAAM,gBAAgB;AAAA,IACpB,SAAS;AAAA,IACT,OAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,MAAM,aAAa;AACtB,UAAM,cAAc,CAAC,aAAa;AAAA,EACpC,WAAW,MAAM,QAAQ,MAAM,WAAW,GAAG;AAC3C,IAAC,MAAM,YAA0B,KAAK,aAAa;AAAA,EACrD;AAEA,WAAS,QAAQ;AACjB,EAAG,mBAAc,cAAc,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,CAAI;AACvE,UAAQ,IAAI,KAAK,cAAAC,QAAM,MAAM,QAAG,CAAC,gEAA2D;AAC9F;AAMO,SAAS,mBAAmB,aAA2B;AAE5D,QAAM,eAAoB,YAAK,aAAa,cAAc;AAC1D,MAAO,gBAAW,YAAY,GAAG;AAC/B,yBAAqB,YAAY;AACjC,YAAQ,IAAI,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,iDAA4C;AAC7E;AAAA,EACF;AAGA,QAAM,WAAgB,YAAK,aAAa,QAAQ;AAChD,MAAO,gBAAW,QAAQ,GAAG;AAC3B,wBAAoB,QAAQ;AAC5B,YAAQ,IAAI,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,iDAA4C;AAC7E;AAAA,EACF;AAGA,QAAM,SAAc,YAAK,aAAa,MAAM;AAC5C,MAAO,gBAAW,MAAM,GAAG;AACzB,UAAM,WAAgB,YAAK,QAAQ,OAAO;AAC1C,QAAI,CAAI,gBAAW,QAAQ,GAAG;AAC5B,MAAG,eAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,IAC5C;AACA,0BAAsB,QAAQ;AAC9B,YAAQ,IAAI,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,wBAAwB;AAAA,EAC3D;AACF;AAEA,SAAS,sBAAsB,UAAwB;AACrD,QAAM,WAAgB,YAAK,UAAU,YAAY;AACjD,MAAO,gBAAW,QAAQ,GAAG;AAC3B,UAAM,WAAc,kBAAa,UAAU,OAAO;AAClD,QAAI,SAAS,SAAS,WAAW,EAAG;AACpC,IAAG;AAAA,MACD;AAAA,MACA,GAAG,SAAS,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,IACvB;AACA;AAAA,EACF;AACA,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACX,EAAG,mBAAc,UAAU,QAAQ,EAAE,MAAM,IAAM,CAAC;AACpD;AAEA,SAAS,qBAAqB,cAA4B;AACxD,QAAM,UAAa,kBAAa,cAAc,OAAO;AACrD,MAAI,QAAQ,SAAS,WAAW,EAAG;AACnC,QAAM,WAAW,CAAC,IAAI,gBAAgB,uCAAuC,EAAE,KAAK,IAAI;AACxF,EAAG,mBAAc,cAAc,GAAG,QAAQ,QAAQ,CAAC;AAAA,EAAK,QAAQ;AAAA,CAAI;AACtE;AAEA,SAAS,oBAAoB,UAAwB;AACnD,QAAM,WAAgB,YAAK,UAAU,YAAY;AACjD,MAAO,gBAAW,QAAQ,GAAG;AAC3B,UAAM,WAAc,kBAAa,UAAU,OAAO;AAClD,QAAI,CAAC,SAAS,SAAS,WAAW,GAAG;AACnC,MAAG,mBAAc,UAAU,GAAG,SAAS,QAAQ,CAAC;AAAA;AAAA,CAAkC;AAAA,IACpF;AACA;AAAA,EACF;AACA,EAAG,mBAAc,UAAU,6CAA6C,EAAE,MAAM,IAAM,CAAC;AACzF;;;ACzIA,QAAmB;AAEnB,IAAAC,gBAA8D;AAC9D,IAAAC,gBAAkB;;;ACFlB,IAAAC,gBAA8D;AAC9D,IAAAC,gBAAkB;;;ACDlB,mBAAkC;AAoB3B,SAAS,YAAY,aAA2C;AACrE,QAAM,MAAM,oBAAI,IAA8C;AAE9D,aAAW,OAAO,aAAa;AAC7B,QAAI,IAAI,SAAS,UAAW;AAC5B,UAAM,WAAW,IAAI,IAAI,IAAI,IAAI;AACjC,QAAI,UAAU;AACZ,eAAS,KAAK,KAAK,GAAG;AAAA,IACxB,OAAO;AACL,UAAI,IAAI,IAAI,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;AAAA,IACnC;AAAA,EACF;AAEA,QAAM,SAAsB,CAAC;AAC7B,aAAW,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK;AAClC,UAAM,QAAQ,+BAAkB,IAAI,KAAK;AACzC,UAAM,aAAa,KAAK,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,WAAW,CAAC;AAC/D,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA,UAAU,KAAK;AAAA,MACf;AAAA,MACA,YAAY,KAAK,WAAW,IAAI,KAAK,CAAC,EAAE,OAAO;AAAA,IACjD,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AASO,SAAS,cAAc,OAA2B,cAA+B;AACtF,QAAM,QAAkB,CAAC;AACzB,MAAI,gBAAgB,eAAe,GAAG;AACpC,UAAM,KAAK,GAAG,YAAY,WAAW;AAAA,EACvC;AACA,QAAM,KAAK,GAAG,MAAM,WAAW,eAAe,CAAC,eAAe;AAC9D,QAAM,KAAK,GAAG,MAAM,WAAW,eAAe,CAAC,QAAQ;AACvD,QAAM,KAAK,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC,aAAa;AACjE,SAAO,MAAM,KAAK,QAAU;AAC9B;AA0BO,SAAS,gBAAgB,OAA0B;AACxD,QAAM,QAAQ,MAAM,eAAe,IAAI,WAAW,GAAG,MAAM,UAAU;AACrE,MAAI,MAAM,YAAY;AACpB,WAAO,GAAG,MAAM,KAAK,WAAM,MAAM,UAAU,KAAK,KAAK;AAAA,EACvD;AACA,QAAM,OAAO,MAAM,aAAa,IAAI,UAAU,GAAG,MAAM,QAAQ;AAC/D,SAAO,GAAG,MAAM,KAAK,WAAM,IAAI,KAAK,KAAK;AAC3C;;;AClGA,IAAAC,gBAA+C;AAC/C,IAAAC,gBAAkB;;;AFoBX,SAAS,WAAW,MAAiB,SAA0C;AACpF,QAAM,OAAO,UAAU,KAAK,IAAI,KAAK,KAAK;AAC1C,SAAO,KAAK,UAAU,GAAG,IAAI,IAAI,KAAK,OAAO,KAAK;AACpD;;;ADJO,IAAM,wBAAsC;AAAA,EACjD,aAAa;AAAA,EACb,QAAQ;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,YAAY;AAAA,EACd;AAAA,EACA,aAAa,CAAC,YAAY;AAC5B;AAQA,eAAsB,UAAU,YAAsD;AACpF,QAAM,aAAa,WAAW,SAAS,SAAS;AAGhD,qBAAmB,UAAU;AAG7B,QAAM,cAAc,MAAQ,SAAO;AAAA,IACjC,SAAS;AAAA,IACT,cAAc;AAAA,IACd,SAAS;AAAA,MACP,EAAE,OAAO,QAAiB,OAAO,QAAQ,MAAM,mCAAmC;AAAA,MAClF,EAAE,OAAO,WAAoB,OAAO,WAAW,MAAM,gCAAgC;AAAA,IACvF;AAAA,EACF,CAAC;AAED,MAAM,WAAS,WAAW,GAAG;AAC3B,IAAE,SAAO,kBAAkB;AAC3B,WAAO;AAAA,EACT;AAGA,QAAM,eAAe;AAAA,IACnB,EAAE,OAAO,YAAqB,OAAO,8BAA8B;AAAA,IACnE,EAAE,OAAO,UAAmB,OAAO,0BAA0B;AAAA,IAC7D,EAAE,OAAO,SAAkB,OAAO,qBAAqB;AAAA,EACzD;AAEA,MAAI,YAAY;AACd,iBAAa,KAAK,EAAE,OAAO,cAAuB,OAAO,oBAAoB,CAAC;AAAA,EAChF;AAEA,QAAM,gBAAgB,MAAQ,cAAY;AAAA,IACxC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,eAAe,CAAC,YAAY,UAAU,OAAO;AAAA,IAC7C,UAAU;AAAA,EACZ,CAAC;AAED,MAAM,WAAS,aAAa,GAAG;AAC7B,IAAE,SAAO,kBAAkB;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS;AAAA,IACb,UAAU,cAAc,SAAS,UAAU;AAAA,IAC3C,QAAQ,cAAc,SAAS,QAAQ;AAAA,IACvC,OAAO,cAAc,SAAS,OAAO;AAAA,IACrC,YAAY,cAAc,SAAS,YAAY;AAAA,EACjD;AAGA,QAAM,qBAAqB;AAAA,IACzB,EAAE,OAAO,cAAuB,OAAO,uBAAuB,MAAM,uBAAuB;AAAA,IAC3F;AAAA,MACE,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,IACR;AAAA,IACA,EAAE,OAAO,gBAAyB,OAAO,sBAAsB,MAAM,WAAW;AAAA,EAClF;AAEA,QAAM,cAAc,MAAQ,cAAY;AAAA,IACtC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,eAAe,CAAC,YAAY;AAAA,IAC5B,UAAU;AAAA,EACZ,CAAC;AAED,MAAM,WAAS,WAAW,GAAG;AAC3B,IAAE,SAAO,kBAAkB;AAC3B,WAAO;AAAA,EACT;AAGA,QAAM,mBAAmB,YAAY,SAAS,cAAc,IACvD,CAAC,cAAc,IAChB;AAEJ,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa;AAAA,EACf;AACF;AAGA,SAAS,mBAAmB,YAA8B;AACxD,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,QAAkB,CAAC;AAEzB,MAAI,MAAM,UAAW,OAAM,KAAK,WAAW,MAAM,WAAW,6BAAe,CAAC;AAC5E,QAAM,KAAK,WAAW,MAAM,QAAQ,CAAC;AACrC,MAAI,MAAM,QAAS,OAAM,KAAK,WAAW,MAAM,SAAS,2BAAa,CAAC;AACtE,MAAI,MAAM,QAAS,OAAM,KAAK,WAAW,MAAM,SAAS,6BAAe,CAAC;AAExE,EAAE,MAAI,KAAK,GAAG,cAAAC,QAAM,KAAK,QAAQ,CAAC,IAAI,MAAM,KAAK,IAAI,CAAC,EAAE;AAExD,MAAI,MAAM,UAAU,MAAM,aAAa,MAAM,cAAc,MAAM,gBAAgB;AAC/E,UAAM,QAAkB,CAAC;AACzB,QAAI,MAAM,OAAQ,OAAM,KAAK,WAAW,MAAM,MAAM,CAAC;AACrD,QAAI,MAAM,aAAa,MAAM,cAAc,MAAM;AAC/C,YAAM,KAAK,WAAW,MAAM,SAAS,CAAC;AACxC,QAAI,MAAM,WAAY,OAAM,KAAK,WAAW,MAAM,UAAU,CAAC;AAC7D,QAAI,MAAM,eAAgB,OAAM,KAAK,WAAW,MAAM,cAAc,CAAC;AACrE,IAAE,MAAI,KAAK,GAAG,cAAAA,QAAM,KAAK,QAAQ,CAAC,IAAI,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,EAC1D;AAEA,MAAI,MAAM,UAAU,SAAS,GAAG;AAC9B,UAAM,OAAO,MAAM,UAAU,IAAI,CAAC,QAAQ,WAAW,KAAK,2BAAa,CAAC,EAAE,KAAK,IAAI;AACnF,IAAE,MAAI,KAAK,GAAG,cAAAA,QAAM,KAAK,YAAY,CAAC,IAAI,IAAI,EAAE;AAAA,EAClD;AAGA,QAAM,SAAS,YAAY,WAAW,UAAU,WAAW;AAC3D,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,cAAc,OAAO,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC;AACxD,IAAE,MAAI,KAAK,GAAG,cAAAA,QAAM,KAAK,YAAY,CAAC,IAAI,YAAY,KAAK,IAAI,CAAC,EAAE;AAAA,EACpE;AAGA,QAAM,oBAAoB,OAAO,QAAQ,WAAW,WAAW,EAAE;AAAA,IAC/D,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe;AAAA,EAC9B;AACA,MAAI,kBAAkB,SAAS,GAAG;AAChC,UAAM,YAAY,kBAAkB,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM;AACjD,YAAM,MAAM,KAAK,MAAM,EAAE,WAAW;AACpC,aAAO,GAAG,EAAE,KAAK,KAAK,GAAG;AAAA,IAC3B,CAAC;AACD,IAAE,MAAI,KAAK,GAAG,cAAAA,QAAM,KAAK,cAAc,CAAC,IAAI,UAAU,KAAK,IAAI,CAAC,EAAE;AAAA,EACpE;AAGA,QAAM,WAAW,WAAW,SAAS,SAAS,IAAI,WAAW,SAAS,SAAS;AAC/E,EAAE,MAAI,KAAK,GAAG,cAAAA,QAAM,KAAK,UAAU,CAAC,IAAI,cAAc,WAAW,YAAY,QAAQ,CAAC,EAAE;AAC1F;;;AH/JA,IAAMC,eAAc;AAKpB,SAAS,qBAAqB,aAAmD;AAC/E,QAAM,WAA8B,CAAC;AACrC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,WAAW,GAAG;AACtD,QAAI,UAAU,OAAW;AACzB,QAAI,OAAO,UAAU,UAAU;AAC7B,eAAS,GAA8B,IAAI;AAAA,IAC7C,WAAW,MAAM,gBAAgB,QAAQ;AACvC,eAAS,GAA8B,IAAI;AAAA,IAC7C;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,kBAAkB,QAA2C,QAA4B;AAChG,SAAO,cAAc,OAAO;AAC5B,MAAI,CAAC,OAAO,OAAO,SAAU,QAAO,MAAM,eAAe;AACzD,SAAO,MAAM,gBAAgB,OAAO,OAAO;AAC3C,SAAO,MAAM,eAAe,OAAO,OAAO;AAC1C,SAAO,MAAM,oBAAoB,OAAO,OAAO;AACjD;AAQA,eAAsB,YAAY,SAA4B,KAA6B;AACzF,QAAM,WAAW,OAAO,QAAQ,IAAI;AAGpC,QAAM,cAAc,gBAAgB,QAAQ;AAC5C,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AAGA,QAAM,aAAkB,YAAK,aAAaA,YAAW;AACrD,MAAO,gBAAW,UAAU,GAAG;AAC7B,YAAQ;AAAA,MACN,cAAAC,QAAM,OAAO,GAAG,IACd,+DAEA,cAAAA,QAAM,KAAK,gBAAgB,IAC3B;AAAA,IACJ;AACA;AAAA,EACF;AAGA,EAAE,SAAM,WAAW;AACnB,QAAM,IAAM,WAAQ;AACpB,IAAE,MAAM,qBAAqB;AAC7B,QAAM,aAAa,UAAM,qBAAK,WAAW;AACzC,IAAE,KAAK,eAAe;AAGtB,MAAI,WAAW,WAAW,eAAe,GAAG;AAC1C,IAAE,OAAI;AAAA,MACJ;AAAA,MACS,cAAAA,QAAM,KAAK,gBAAgB,CAAC;AAAA,IACvC;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,QAAQ,KAAK;AACf,aAAS,EAAE,GAAG,sBAAsB;AAAA,EACtC,OAAO;AACL,UAAM,SAAS,MAAM,UAAU,UAAU;AACzC,QAAI,CAAC,OAAQ;AACb,aAAS;AAAA,EACX;AAGA,QAAM,aAAS,+BAAe,UAAU;AACxC,MAAI,QAAQ,KAAK;AACf,WAAO,cAAc,qBAAqB,OAAO,WAAW;AAAA,EAC9D;AAGA,oBAAkB,QAAQ,MAAM;AAGhC,MAAI,OAAO,OAAO,cAAc,OAAO,aAAa,OAAO,UAAU,SAAS,SAAS,GAAG;AACxF,MAAE,MAAM,6BAA6B;AACrC,UAAM,EAAE,kBAAkB,gBAAgB,IAAI,MAAM,OAAO,kBAAkB;AAC7E,UAAM,WAAW,yBAAyB,aAAa,OAAO,SAAS;AACvE,UAAM,QAAQ,MAAM,iBAAiB,aAAa,EAAE,UAAU,QAAQ,OAAO,OAAO,CAAC;AACrF,UAAM,WAAW,gBAAgB,KAAK;AACtC,UAAM,YAAY,OAAO,OAAO,QAAQ,EAAE,OAAO,CAAC,KAAK,WAAW,MAAM,OAAO,QAAQ,CAAC;AACxF,QAAI,YAAY,GAAG;AACjB,aAAO,aAAa;AACpB,QAAE,KAAK,YAAY,SAAS,iBAAiB;AAAA,IAC/C,OAAO;AACL,QAAE,KAAK,qCAAqC;AAC5C,aAAO,MAAM,oBAAoB;AAAA,IACnC;AAAA,EACF;AAGA,EAAG,mBAAc,YAAY,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAGnE,sBAAoB,aAAa,QAAQ,UAAU;AAGnD,kBAAgB,WAAW;AAG3B,MAAI,OAAO,YAAY,SAAS,YAAY,GAAG;AAC7C,uBAAmB,WAAW;AAAA,EAChC;AACA,MAAI,OAAO,YAAY,SAAS,aAAa,GAAG;AAC9C,wBAAoB,WAAW;AAAA,EACjC;AAGA,EAAE,OAAI,QAAQ,GAAG,cAAAA,QAAM,KAAK,UAAU,CAAC,EAAE;AACzC,UAAQ,IAAI,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,IAAID,YAAW,EAAE;AAClD,UAAQ,IAAI,KAAK,cAAAC,QAAM,MAAM,QAAG,CAAC,wBAAwB;AACzD,UAAQ,IAAI,KAAK,cAAAA,QAAM,MAAM,QAAG,CAAC,8BAA8B;AAE/D,EAAE;AAAA,IACA,GAAG,cAAAA,QAAM,KAAK,aAAa,CAAC;AAAA,cACX,cAAAA,QAAM,KAAK,uBAAuB,CAAC;AAAA,cACnC,cAAAA,QAAM,KAAK,uBAAuB,CAAC,QAAQ,cAAAA,QAAM,KAAK,uBAAuB,CAAC;AAAA,WACjF,cAAAA,QAAM,KAAK,iBAAiB,CAAC;AAAA,EAC7C;AACF;AAOA,SAAS,gBAAgB,aAA2B;AAClD,QAAM,gBAAqB,YAAK,aAAa,YAAY;AACzD,MAAI,UAAU;AAEd,MAAO,gBAAW,aAAa,GAAG;AAChC,cAAa,kBAAa,eAAe,OAAO;AAAA,EAClD;AAEA,MAAI,CAAC,QAAQ,SAAS,6BAA6B,GAAG;AACpD,UAAM,QAAQ;AACd,IAAG,mBAAc,eAAe,GAAG,QAAQ,QAAQ,CAAC;AAAA,EAAK,KAAK,EAAE;AAAA,EAClE;AACF;;;AO9KA,IAAAC,OAAoB;AACpB,IAAAC,SAAsB;AACtB,IAAAC,iBAAwC;AACxC,IAAAC,kBAAqB;AACrB,IAAAC,iBAAkB;AAIlB,IAAMC,eAAc;AAOpB,eAAsB,YAAY,KAA6B;AAC7D,QAAM,WAAW,OAAO,QAAQ,IAAI;AAGpC,QAAM,cAAc,gBAAgB,QAAQ;AAC5C,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AAGA,QAAM,aAAkB,YAAK,aAAaA,YAAW;AACrD,QAAM,WAAW,UAAM,2BAAW,UAAU;AAG5C,UAAQ,IAAI,eAAAC,QAAM,IAAI,qBAAqB,CAAC;AAC5C,QAAM,aAAa,UAAM,sBAAK,WAAW;AAGzC,QAAM,aAAS,4BAAY,UAAU,UAAU;AAC/C,EAAG,mBAAc,YAAY,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAGnE,sBAAoB,aAAa,QAAQ,UAAU;AAEnD,UAAQ,IAAI;AAAA,EAAK,eAAAA,QAAM,KAAK,SAAS,CAAC,EAAE;AACxC,UAAQ,IAAI,KAAK,eAAAA,QAAM,MAAM,QAAG,CAAC,IAAID,YAAW,iBAAY;AAC5D,UAAQ,IAAI,KAAK,eAAAC,QAAM,MAAM,QAAG,CAAC,2CAAsC;AACvE,UAAQ,IAAI,KAAK,eAAAA,QAAM,MAAM,QAAG,CAAC,6CAAwC;AAC3E;;;AtBtCO,IAAM,UAAkB;AAE/B,IAAM,UAAU,IAAI,yBAAQ;AAE5B,QAAQ,KAAK,WAAW,EAAE,YAAY,4BAA4B,EAAE,QAAQ,OAAO;AAEnF,QACG,QAAQ,QAAQ,EAAE,WAAW,KAAK,CAAC,EACnC,YAAY,qDAAqD,EACjE,OAAO,aAAa,2DAA2D,EAC/E,OAAO,OAAO,YAA+B;AAC5C,MAAI;AACF,UAAM,YAAY,OAAO;AAAA,EAC3B,SAAS,KAAc;AACrB,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAQ,MAAM,GAAG,eAAAC,QAAM,IAAI,QAAQ,CAAC,IAAI,OAAO,EAAE;AACjD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,oCAAoC,EAChD,OAAO,YAAY;AAClB,MAAI;AACF,UAAM,YAAY;AAAA,EACpB,SAAS,KAAc;AACrB,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAQ,MAAM,GAAG,eAAAA,QAAM,IAAI,QAAQ,CAAC,IAAI,OAAO,EAAE;AACjD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QACG,QAAQ,OAAO,EACf,YAAY,oCAAoC,EAChD,OAAO,YAAY,gDAAgD,EACnE,OAAO,sBAAsB,sBAAsB,EACnD,OAAO,mBAAmB,wBAAwB,EAClD,OAAO,WAAW,qDAAqD,EACvE,OAAO,eAAe,2CAA2C,OAAO,QAAQ,EAChF;AAAA,EACC,OAAO,YAMD;AACJ,QAAI;AACF,YAAM,WAAW,MAAM,aAAa;AAAA,QAClC,GAAG;AAAA,QACH,cAAc,QAAQ,eAAe;AAAA,MACvC,CAAC;AACD,cAAQ,KAAK,QAAQ;AAAA,IACvB,SAAS,KAAc;AACrB,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,cAAQ,MAAM,GAAG,eAAAA,QAAM,IAAI,QAAQ,CAAC,IAAI,OAAO,EAAE;AACjD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF;AAEF,QACG,QAAQ,KAAK,EACb,YAAY,iEAAiE,EAC7E,OAAO,aAAa,0CAA0C,EAC9D,OAAO,qBAAqB,qDAAqD,EACjF,OAAO,aAAa,0BAA0B,EAC9C,OAAO,OAAO,YAAkE;AAC/E,MAAI;AACF,UAAM,WAAW,MAAM,WAAW,OAAO;AACzC,YAAQ,KAAK,QAAQ;AAAA,EACvB,SAAS,KAAc;AACrB,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAQ,MAAM,GAAG,eAAAA,QAAM,IAAI,QAAQ,CAAC,IAAI,OAAO,EAAE;AACjD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QACG,QAAQ,YAAY,EACpB,YAAY,kDAAkD,EAC9D,OAAO,WAAW,mDAAmD,EACrE,OAAO,WAAW,8BAA8B,EAChD,OAAO,OAAO,YAAkD;AAC/D,MAAI;AACF,UAAM,kBAAkB,OAAO;AAAA,EACjC,SAAS,KAAc;AACrB,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAQ,MAAM,GAAG,eAAAA,QAAM,IAAI,QAAQ,CAAC,IAAI,OAAO,EAAE;AACjD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QAAQ,MAAM;","names":["import_chalk","fs","path","resolve","fs","path","p","chalk","fs","path","import_config","import_chalk","fs","path","fs","path","SOURCE_EXTS","basename","CONFIG_FILE","chalk","fs","path","import_config","import_chalk","import_node_child_process","import_chalk","chalk","resolve","path","fs","path","fs","path","basename","CONFIG_FILE","chalk","fs","path","p","import_config","import_chalk","fs","path","fs","path","import_chalk","chalk","import_types","import_chalk","import_types","import_chalk","import_types","import_chalk","chalk","CONFIG_FILE","chalk","fs","path","import_config","import_scanner","import_chalk","CONFIG_FILE","chalk","chalk"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/boundaries.ts","../src/utils/find-project-root.ts","../src/utils/prompt.ts","../src/utils/resolve-workspace-packages.ts","../src/commands/check.ts","../src/commands/check-config.ts","../src/commands/check-files.ts","../src/commands/check-tests.ts","../src/commands/fix.ts","../src/commands/fix-helpers.ts","../src/commands/fix-imports.ts","../src/commands/fix-naming.ts","../src/commands/convert-name.ts","../src/commands/fix-tests.ts","../src/commands/init.ts","../src/display.ts","../src/display-helpers.ts","../src/display-monorepo.ts","../src/utils/write-generated-files.ts","../src/commands/init-hooks.ts","../src/commands/sync.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { Command } from 'commander';\nimport { boundariesCommand } from './commands/boundaries.js';\nimport { checkCommand } from './commands/check.js';\nimport { fixCommand } from './commands/fix.js';\nimport { initCommand } from './commands/init.js';\nimport { syncCommand } from './commands/sync.js';\n\ndeclare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n\nconst program = new Command();\n\nprogram.name('viberails').description('Guardrails for vibe coding').version(VERSION);\n\nprogram\n .command('init', { isDefault: true })\n .description('Scan your project and set up enforcement guardrails')\n .option('-y, --yes', 'Non-interactive mode (use defaults, high-confidence only)')\n .action(async (options: { yes?: boolean }) => {\n try {\n await initCommand(options);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command('sync')\n .description('Re-scan and update generated files')\n .action(async () => {\n try {\n await syncCommand();\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command('check')\n .description('Check files against enforced rules')\n .option('--staged', 'Check only staged files (for pre-commit hooks)')\n .option('--files <files...>', 'Check specific files')\n .option('--no-boundaries', 'Skip boundary checking')\n .option('--quiet', 'Show only summary counts, not individual violations')\n .option('--limit <n>', 'Maximum number of violations to display', Number.parseInt)\n .option('--format <format>', 'Output format: text (default) or json')\n .action(\n async (options: {\n staged?: boolean;\n files?: string[];\n boundaries?: boolean;\n quiet?: boolean;\n limit?: number;\n format?: string;\n }) => {\n try {\n const exitCode = await checkCommand({\n ...options,\n noBoundaries: options.boundaries === false,\n format: options.format === 'json' ? 'json' : 'text',\n });\n process.exit(exitCode);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('fix')\n .description('Auto-fix file naming violations and generate missing test stubs')\n .option('--dry-run', 'Show planned fixes without applying them')\n .option('--rule <rules...>', 'Fix only specific rules (file-naming, missing-test)')\n .option('-y, --yes', 'Skip confirmation prompt')\n .action(async (options: { dryRun?: boolean; rule?: string[]; yes?: boolean }) => {\n try {\n const exitCode = await fixCommand(options);\n process.exit(exitCode);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command('boundaries')\n .description('Display, infer, or inspect import boundary rules')\n .option('--infer', 'Infer boundary rules from current import patterns')\n .option('--graph', 'Display import graph summary')\n .action(async (options: { infer?: boolean; graph?: boolean }) => {\n try {\n await boundariesCommand(options);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(`${chalk.red('Error:')} ${message}`);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { loadConfig } from '@viberails/config';\nimport type { ViberailsConfig } from '@viberails/types';\nimport chalk from 'chalk';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport { confirm } from '../utils/prompt.js';\nimport { resolveWorkspacePackages } from '../utils/resolve-workspace-packages.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\nexport interface BoundariesOptions {\n infer?: boolean;\n graph?: boolean;\n}\n\n/**\n * Display, infer, or inspect import boundary rules.\n *\n * @param options - CLI options\n * @param cwd - Working directory override (for testing)\n */\nexport async function boundariesCommand(options: BoundariesOptions, cwd?: string): Promise<void> {\n const startDir = cwd ?? process.cwd();\n const projectRoot = findProjectRoot(startDir);\n if (!projectRoot) {\n throw new Error('No package.json found. Are you in a JS/TS project?');\n }\n\n const configPath = path.join(projectRoot, CONFIG_FILE);\n if (!fs.existsSync(configPath)) {\n throw new Error('No viberails.config.json found. Run `viberails init` first.');\n }\n\n const config = await loadConfig(configPath);\n\n if (options.graph) {\n await showGraph(projectRoot, config);\n return;\n }\n\n if (options.infer) {\n await inferAndDisplay(projectRoot, config, configPath);\n return;\n }\n\n displayRules(config);\n}\n\n/** Display configured boundary rules. */\nfunction displayRules(config: ViberailsConfig): void {\n if (!config.boundaries || config.boundaries.length === 0) {\n console.log(chalk.yellow('No boundary rules configured.'));\n console.log(`Run ${chalk.cyan('viberails boundaries --infer')} to generate rules.`);\n return;\n }\n\n const allowRules = config.boundaries.filter((r) => r.allow);\n const denyRules = config.boundaries.filter((r) => !r.allow);\n\n console.log(`\\n${chalk.bold(`Boundary rules (${config.boundaries.length} rules):`)}\\n`);\n\n for (const r of allowRules) {\n console.log(` ${chalk.green('✓')} ${r.from} → ${r.to}`);\n }\n\n for (const r of denyRules) {\n const reason = r.reason ? chalk.dim(` (${r.reason})`) : '';\n console.log(` ${chalk.red('✗')} ${r.from} → ${r.to}${reason}`);\n }\n\n console.log(\n `\\nEnforcement: ${config.rules.enforceBoundaries ? chalk.green('on') : chalk.yellow('off')}`,\n );\n}\n\n/** Infer boundary rules from import patterns and optionally save. */\nasync function inferAndDisplay(\n projectRoot: string,\n config: ViberailsConfig,\n configPath: string,\n): Promise<void> {\n console.log(chalk.dim('Analyzing imports...'));\n const { buildImportGraph, inferBoundaries } = await import('@viberails/graph');\n\n const packages = config.workspace\n ? resolveWorkspacePackages(projectRoot, config.workspace)\n : undefined;\n\n const graph = await buildImportGraph(projectRoot, {\n packages,\n ignore: config.ignore,\n });\n\n console.log(chalk.dim(`${graph.nodes.length} files, ${graph.edges.length} edges`));\n\n const inferred = inferBoundaries(graph);\n\n if (inferred.length === 0) {\n console.log(chalk.yellow('No boundary rules could be inferred.'));\n return;\n }\n\n const allow = inferred.filter((r) => r.allow);\n const deny = inferred.filter((r) => !r.allow);\n\n console.log(`\\n${chalk.bold('Inferred boundary rules:')}\\n`);\n\n for (const r of allow) {\n console.log(` ${chalk.green('✓')} ${r.from} → ${r.to}`);\n }\n\n for (const r of deny) {\n const reason = r.reason ? chalk.dim(` (${r.reason})`) : '';\n console.log(` ${chalk.red('✗')} ${r.from} → ${r.to}${reason}`);\n }\n\n console.log(`\\n ${allow.length} allowed, ${deny.length} denied`);\n\n console.log('');\n const shouldSave = await confirm('Save to viberails.config.json?');\n if (shouldSave) {\n config.boundaries = inferred;\n config.rules.enforceBoundaries = true;\n fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`);\n console.log(`${chalk.green('✓')} Saved ${inferred.length} rules`);\n }\n}\n\n/** Display import graph summary. */\nasync function showGraph(projectRoot: string, config: ViberailsConfig): Promise<void> {\n console.log(chalk.dim('Building import graph...'));\n const { buildImportGraph } = await import('@viberails/graph');\n\n const packages = config.workspace\n ? resolveWorkspacePackages(projectRoot, config.workspace)\n : undefined;\n\n const graph = await buildImportGraph(projectRoot, {\n packages,\n ignore: config.ignore,\n });\n\n console.log(`\\n${chalk.bold('Import dependency graph:')}\\n`);\n console.log(` ${graph.nodes.length} files, ${graph.edges.length} imports\\n`);\n\n if (graph.packages.length > 0) {\n for (const pkg of graph.packages) {\n const deps =\n pkg.internalDeps.length > 0\n ? `\\n${pkg.internalDeps.map((d) => ` → ${d}`).join('\\n')}`\n : chalk.dim(' (no internal deps)');\n console.log(` ${pkg.name}${deps}`);\n }\n }\n\n if (graph.cycles.length > 0) {\n console.log(`\\n${chalk.yellow('Cycles detected:')}`);\n for (const cycle of graph.cycles) {\n const paths = cycle.map((f) => path.relative(projectRoot, f));\n console.log(` ${paths.join(' → ')}`);\n }\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * Walk up from startDir looking for a directory containing package.json.\n *\n * @param startDir - The directory to start searching from\n * @returns The project root path, or null if no package.json is found\n */\nexport function findProjectRoot(startDir: string): string | null {\n let dir = path.resolve(startDir);\n\n while (true) {\n if (fs.existsSync(path.join(dir, 'package.json'))) {\n return dir;\n }\n\n const parent = path.dirname(dir);\n if (parent === dir) {\n return null;\n }\n dir = parent;\n }\n}\n","import * as clack from '@clack/prompts';\n\n/**\n * Assert that a clack prompt result was not cancelled (Ctrl+C).\n * If cancelled, prints a message and exits the process.\n */\nfunction assertNotCancelled<T>(value: T | symbol): asserts value is T {\n if (clack.isCancel(value)) {\n clack.cancel('Setup cancelled.');\n process.exit(0);\n }\n}\n\n/**\n * Prompt the user for a yes/no confirmation.\n *\n * @param message - The question to display\n * @returns true if the user confirms, false otherwise\n */\nexport async function confirm(message: string): Promise<boolean> {\n const result = await clack.confirm({ message, initialValue: true });\n assertNotCancelled(result);\n return result;\n}\n\n/**\n * Prompt the user for a yes/no confirmation that defaults to NO.\n * Use for destructive or risky actions.\n *\n * @param message - The question to display\n * @returns true if the user confirms, false otherwise\n */\nexport async function confirmDangerous(message: string): Promise<boolean> {\n const result = await clack.confirm({ message, initialValue: false });\n assertNotCancelled(result);\n return result;\n}\n\nexport interface IntegrationChoice {\n preCommitHook: boolean;\n claudeCodeHook: boolean;\n}\n\n/**\n * Prompt the user to choose between accepting defaults or customizing.\n *\n * @returns 'accept' or 'customize'\n */\nexport async function promptInitDecision(): Promise<'accept' | 'customize'> {\n const result = await clack.select({\n message: 'Accept these settings?',\n options: [\n { value: 'accept' as const, label: 'Yes, looks good', hint: 'recommended' },\n { value: 'customize' as const, label: 'Let me customize' },\n ],\n });\n assertNotCancelled(result);\n return result;\n}\n\nexport interface RuleOverrides {\n maxFileLines: number;\n requireTests: boolean;\n enforceNaming: boolean;\n enforcement: 'warn' | 'enforce';\n}\n\n/**\n * Prompt the user to customize rule settings.\n *\n * @param defaults - Current detected/default values to pre-fill\n * @returns The user's chosen rule settings\n */\nexport async function promptRuleCustomization(defaults: {\n maxFileLines: number;\n requireTests: boolean;\n enforceNaming: boolean;\n enforcement: 'warn' | 'enforce';\n fileNamingValue?: string;\n}): Promise<RuleOverrides> {\n const maxFileLinesResult = await clack.text({\n message: 'Maximum lines per source file?',\n placeholder: String(defaults.maxFileLines),\n initialValue: String(defaults.maxFileLines),\n validate: (v) => {\n const n = Number.parseInt(v, 10);\n if (Number.isNaN(n) || n < 1) return 'Enter a positive number';\n },\n });\n assertNotCancelled(maxFileLinesResult);\n\n const requireTestsResult = await clack.confirm({\n message: 'Require matching test files for source files?',\n initialValue: defaults.requireTests,\n });\n assertNotCancelled(requireTestsResult);\n\n const namingLabel = defaults.fileNamingValue\n ? `Enforce file naming? (detected: ${defaults.fileNamingValue})`\n : 'Enforce file naming?';\n const enforceNamingResult = await clack.confirm({\n message: namingLabel,\n initialValue: defaults.enforceNaming,\n });\n assertNotCancelled(enforceNamingResult);\n\n const enforcementResult = await clack.select({\n message: 'Enforcement mode',\n options: [\n {\n value: 'warn' as const,\n label: 'warn',\n hint: \"show violations but don't block commits (recommended)\",\n },\n {\n value: 'enforce' as const,\n label: 'enforce',\n hint: 'block commits with violations',\n },\n ],\n initialValue: defaults.enforcement,\n });\n assertNotCancelled(enforcementResult);\n\n return {\n maxFileLines: Number.parseInt(maxFileLinesResult, 10),\n requireTests: requireTestsResult,\n enforceNaming: enforceNamingResult,\n enforcement: enforcementResult,\n };\n}\n\n/**\n * Prompt the user to select which integrations to set up.\n *\n * @param hookManager - Detected hook manager name (e.g. \"Husky\", \"Lefthook\") or undefined\n * @returns Object with selected integrations\n */\nexport async function promptIntegrations(\n hookManager: string | undefined,\n): Promise<IntegrationChoice> {\n const hookLabel = hookManager ? `Pre-commit hook (${hookManager})` : 'Pre-commit hook (git hook)';\n\n const result = await clack.multiselect({\n message: 'Set up integrations?',\n options: [\n {\n value: 'preCommit' as const,\n label: hookLabel,\n hint: 'runs checks when you commit',\n },\n {\n value: 'claude' as const,\n label: 'Claude Code hook',\n hint: 'checks files when Claude edits them',\n },\n ],\n initialValues: ['preCommit', 'claude'],\n required: false,\n });\n assertNotCancelled(result);\n\n return {\n preCommitHook: result.includes('preCommit'),\n claudeCodeHook: result.includes('claude'),\n };\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { WorkspaceConfig, WorkspacePackage } from '@viberails/types';\n\n/**\n * Resolve WorkspacePackage[] from config workspace relative paths.\n *\n * Reads each package's package.json to get the name and dependencies,\n * then filters internalDeps to only include workspace-internal packages.\n *\n * @param projectRoot - Absolute path to the project root\n * @param workspace - The workspace config from viberails.config.json\n * @returns Array of resolved WorkspacePackage objects\n */\nexport function resolveWorkspacePackages(\n projectRoot: string,\n workspace: WorkspaceConfig,\n): WorkspacePackage[] {\n const packages: WorkspacePackage[] = [];\n\n for (const relativePath of workspace.packages) {\n const absPath = path.join(projectRoot, relativePath);\n const pkgJsonPath = path.join(absPath, 'package.json');\n\n if (!fs.existsSync(pkgJsonPath)) continue;\n\n let pkg: Record<string, unknown>;\n try {\n pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));\n } catch {\n continue;\n }\n\n const name = pkg.name as string;\n if (!name) continue;\n\n const allDeps = [\n ...Object.keys((pkg.dependencies as Record<string, unknown>) ?? {}),\n ...Object.keys((pkg.devDependencies as Record<string, unknown>) ?? {}),\n ];\n\n packages.push({ name, path: absPath, relativePath, internalDeps: allDeps });\n }\n\n // Filter internalDeps to only workspace-internal package names\n const packageNames = new Set(packages.map((p) => p.name));\n for (const pkg of packages) {\n pkg.internalDeps = pkg.internalDeps.filter((dep) => packageNames.has(dep));\n }\n\n return packages;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { loadConfig } from '@viberails/config';\nimport type { CheckViolation } from '@viberails/types';\nimport chalk from 'chalk';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport { resolveWorkspacePackages } from '../utils/resolve-workspace-packages.js';\nimport { resolveConfigForFile, resolveIgnoreForFile } from './check-config.js';\nimport {\n checkNaming,\n countFileLines,\n getAllSourceFiles,\n getStagedFiles,\n isIgnored,\n} from './check-files.js';\nimport { checkMissingTests } from './check-tests.js';\n\nexport { resolveConfigForFile } from './check-config.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\nexport interface CheckOptions {\n files?: string[];\n staged?: boolean;\n noBoundaries?: boolean;\n quiet?: boolean;\n limit?: number;\n format?: 'text' | 'json';\n}\n\n/** Check if a file path looks like a test file. */\nfunction isTestFile(relPath: string): boolean {\n const filename = path.basename(relPath);\n return (\n filename.includes('.test.') ||\n filename.includes('.spec.') ||\n filename.startsWith('test.') ||\n filename.startsWith('spec.') ||\n relPath.includes('__tests__/') ||\n relPath.includes('__test__/')\n );\n}\n\n/**\n * Print violations grouped by rule type with counts.\n */\nfunction printGroupedViolations(violations: CheckViolation[], limit?: number): void {\n const groups = new Map<string, CheckViolation[]>();\n for (const v of violations) {\n const existing = groups.get(v.rule) ?? [];\n existing.push(v);\n groups.set(v.rule, existing);\n }\n\n const ruleOrder = ['file-size', 'file-naming', 'missing-test', 'boundary-violation'];\n const sortedKeys = [...groups.keys()].sort(\n (a, b) =>\n (ruleOrder.indexOf(a) === -1 ? 99 : ruleOrder.indexOf(a)) -\n (ruleOrder.indexOf(b) === -1 ? 99 : ruleOrder.indexOf(b)),\n );\n\n let totalShown = 0;\n const totalLimit = limit ?? Number.POSITIVE_INFINITY;\n\n for (const rule of sortedKeys) {\n const group = groups.get(rule);\n if (!group) continue;\n const remaining = totalLimit - totalShown;\n if (remaining <= 0) break;\n\n const toShow = group.slice(0, remaining);\n const hidden = group.length - toShow.length;\n\n for (const v of toShow) {\n const icon = v.severity === 'error' ? chalk.red('✗') : chalk.yellow('!');\n console.log(`${icon} ${chalk.dim(v.rule)} ${v.file}: ${v.message}`);\n }\n totalShown += toShow.length;\n\n if (hidden > 0) {\n console.log(chalk.dim(` ... and ${hidden} more ${rule} violations`));\n }\n }\n}\n\n/**\n * Print a summary of violations by rule type.\n */\nfunction printSummary(violations: CheckViolation[]): void {\n const counts = new Map<string, number>();\n for (const v of violations) {\n counts.set(v.rule, (counts.get(v.rule) ?? 0) + 1);\n }\n\n const word = violations.length === 1 ? 'violation' : 'violations';\n const parts = [...counts.entries()].map(([rule, count]) => `${count} ${rule}`);\n console.log(`\\n${violations.length} ${word} found (${parts.join(', ')}).`);\n}\n\n/**\n * Run the viberails check command.\n * Returns exit code: 0 = pass or warn-mode, 1 = violations in enforce mode.\n */\nexport async function checkCommand(options: CheckOptions, cwd?: string): Promise<number> {\n const startDir = cwd ?? process.cwd();\n\n const projectRoot = findProjectRoot(startDir);\n if (!projectRoot) {\n console.error(`${chalk.red('Error:')} No package.json found. Are you in a JS/TS project?`);\n return 1;\n }\n\n const configPath = path.join(projectRoot, CONFIG_FILE);\n if (!fs.existsSync(configPath)) {\n console.error(\n `${chalk.red('Error:')} No viberails.config.json found. Run \\`viberails init\\` first.`,\n );\n return 1;\n }\n\n const config = await loadConfig(configPath);\n\n // Determine which files to check\n let filesToCheck: string[];\n if (options.staged) {\n filesToCheck = getStagedFiles(projectRoot);\n } else if (options.files && options.files.length > 0) {\n filesToCheck = options.files;\n } else {\n filesToCheck = getAllSourceFiles(projectRoot, config);\n }\n\n if (filesToCheck.length === 0) {\n console.log(`${chalk.green('✓')} No files to check.`);\n return 0;\n }\n\n const violations: CheckViolation[] = [];\n const severity = config.enforcement === 'enforce' ? 'error' : 'warn';\n\n for (const file of filesToCheck) {\n const absPath = path.isAbsolute(file) ? file : path.join(projectRoot, file);\n const relPath = path.relative(projectRoot, absPath);\n\n const effectiveIgnore = resolveIgnoreForFile(relPath, config);\n if (isIgnored(relPath, effectiveIgnore)) continue;\n if (!fs.existsSync(absPath)) continue;\n\n const resolved = resolveConfigForFile(relPath, config);\n\n // Check 1: File size (with separate threshold for test files)\n const testFile = isTestFile(relPath);\n const maxLines = testFile ? resolved.rules.maxTestFileLines : resolved.rules.maxFileLines;\n if (maxLines > 0) {\n const lines = countFileLines(absPath);\n if (lines !== null && lines > maxLines) {\n violations.push({\n file: relPath,\n rule: 'file-size',\n message: `${lines} lines (max ${maxLines}). Split into focused modules.`,\n severity,\n });\n }\n }\n\n // Check 2: File naming convention\n if (resolved.rules.enforceNaming && resolved.conventions.fileNaming) {\n const namingViolation = checkNaming(relPath, resolved.conventions);\n if (namingViolation) {\n violations.push({\n file: relPath,\n rule: 'file-naming',\n message: namingViolation,\n severity,\n });\n }\n }\n }\n\n // Check 3: Missing tests (only on full project check, not staged/specific files)\n if (config.rules.requireTests && !options.staged && !options.files) {\n const testViolations = checkMissingTests(projectRoot, config, severity);\n violations.push(...testViolations);\n }\n\n // Check 4: Boundary violations\n if (\n config.rules.enforceBoundaries &&\n config.boundaries &&\n config.boundaries.length > 0 &&\n !options.noBoundaries\n ) {\n const startTime = Date.now();\n const { buildImportGraph, checkBoundaries } = await import('@viberails/graph');\n\n const packages = config.workspace\n ? resolveWorkspacePackages(projectRoot, config.workspace)\n : undefined;\n\n const graph = await buildImportGraph(projectRoot, {\n packages,\n ignore: config.ignore,\n });\n\n const boundaryViolations = checkBoundaries(graph, config.boundaries);\n\n // In staged/files mode, only report violations in those files\n const filterSet =\n options.staged || options.files\n ? new Set(filesToCheck.map((f) => path.resolve(projectRoot, f)))\n : null;\n\n for (const bv of boundaryViolations) {\n if (filterSet && !filterSet.has(bv.file)) continue;\n\n const relFile = path.relative(projectRoot, bv.file);\n violations.push({\n file: relFile,\n rule: 'boundary-violation',\n message: `Imports \"${bv.specifier}\" violating boundary: ${bv.rule.from} → ${bv.rule.to}${bv.rule.reason ? ` (${bv.rule.reason})` : ''}`,\n severity,\n });\n }\n\n const elapsed = Date.now() - startTime;\n console.log(chalk.dim(` Boundary check: ${graph.nodes.length} files in ${elapsed}ms`));\n }\n\n // Output results\n if (options.format === 'json') {\n console.log(\n JSON.stringify({\n violations,\n checkedFiles: filesToCheck.length,\n enforcement: config.enforcement,\n }),\n );\n return config.enforcement === 'enforce' && violations.length > 0 ? 1 : 0;\n }\n\n if (violations.length === 0) {\n console.log(`${chalk.green('✓')} ${filesToCheck.length} files checked — no violations`);\n return 0;\n }\n\n if (!options.quiet) {\n printGroupedViolations(violations, options.limit);\n }\n\n printSummary(violations);\n\n if (config.enforcement === 'enforce') {\n console.log(chalk.red('Fix violations before committing.'));\n return 1;\n }\n\n return 0;\n}\n","import type { ConfigConventions, ConfigRules, ViberailsConfig } from '@viberails/types';\n\nexport interface ResolvedConfig {\n rules: ConfigRules;\n conventions: ConfigConventions;\n}\n\n/**\n * Resolve the effective config for a file by finding its package override.\n * Returns the global config merged with any matching package overrides.\n */\nexport function resolveConfigForFile(relPath: string, config: ViberailsConfig): ResolvedConfig {\n if (!config.packages || config.packages.length === 0) {\n return { rules: config.rules, conventions: config.conventions };\n }\n\n // Sort by path length descending to match the most specific package first\n const sortedPackages = [...config.packages].sort((a, b) => b.path.length - a.path.length);\n\n for (const pkg of sortedPackages) {\n if (relPath.startsWith(`${pkg.path}/`) || relPath === pkg.path) {\n return {\n rules: { ...config.rules, ...pkg.rules },\n conventions: { ...config.conventions, ...pkg.conventions },\n };\n }\n }\n\n return { rules: config.rules, conventions: config.conventions };\n}\n\n/**\n * Resolve ignore patterns for a file, appending any package-specific patterns.\n */\nexport function resolveIgnoreForFile(relPath: string, config: ViberailsConfig): string[] {\n const globalIgnore = config.ignore;\n if (!config.packages) return globalIgnore;\n\n for (const pkg of config.packages) {\n if (pkg.ignore && relPath.startsWith(`${pkg.path}/`)) {\n return [...globalIgnore, ...pkg.ignore];\n }\n }\n return globalIgnore;\n}\n","import { execSync } from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ConfigConventions, ConventionValue, ViberailsConfig } from '@viberails/types';\nimport picomatch from 'picomatch';\n\nconst ALWAYS_SKIP_DIRS = new Set([\n 'node_modules',\n '.git',\n 'dist',\n 'build',\n '.next',\n '.expo',\n '.output',\n '.svelte-kit',\n '.turbo',\n 'coverage',\n 'public',\n 'vendor',\n '__generated__',\n 'generated',\n '.viberails',\n]);\n\nexport const SOURCE_EXTS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.vue',\n '.svelte',\n '.astro',\n]);\n\nexport const NAMING_PATTERNS: Record<string, RegExp> = {\n 'kebab-case': /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/,\n camelCase: /^[a-z][a-zA-Z0-9]*$/,\n PascalCase: /^[A-Z][a-zA-Z0-9]*$/,\n snake_case: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,\n};\n\n/** Check if a path matches any ignore pattern. */\nexport function isIgnored(relPath: string, ignorePatterns: string[]): boolean {\n if (ignorePatterns.length === 0) return false;\n const isMatch = picomatch(ignorePatterns, { dot: true });\n return isMatch(relPath);\n}\n\n/** Count lines in a file. Returns null if the file can't be read. */\nexport function countFileLines(filePath: string): number | null {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n if (content.length === 0) return 0;\n let count = 1;\n for (let i = 0; i < content.length; i++) {\n if (content.charCodeAt(i) === 10) count++;\n }\n return count;\n } catch {\n return null;\n }\n}\n\n/** Check whether a file's name violates the configured naming convention. */\nexport function checkNaming(relPath: string, conventions: ConfigConventions): string | undefined {\n const filename = path.basename(relPath);\n\n // Skip non-source files\n const ext = path.extname(filename);\n if (!SOURCE_EXTS.has(ext)) return undefined;\n\n // Skip special files\n if (\n filename.startsWith('index.') ||\n filename.includes('.config.') ||\n filename.includes('.test.') ||\n filename.includes('.spec.') ||\n filename.startsWith('.') ||\n filename.startsWith('_') ||\n filename.startsWith('+') ||\n filename.startsWith('$') ||\n filename.startsWith('[')\n ) {\n return undefined;\n }\n\n const bare = filename.slice(0, filename.indexOf('.'));\n const convention =\n typeof conventions.fileNaming === 'string'\n ? conventions.fileNaming\n : (conventions.fileNaming as Exclude<ConventionValue, string> | undefined)?.value;\n\n if (!convention) return undefined;\n\n const pattern = NAMING_PATTERNS[convention];\n if (!pattern || pattern.test(bare)) return undefined;\n\n return `File name \"${filename}\" does not follow ${convention} convention.`;\n}\n\n/** Get staged files from git. */\nexport function getStagedFiles(projectRoot: string): string[] {\n try {\n const output = execSync('git diff --cached --name-only --diff-filter=ACM', {\n cwd: projectRoot,\n encoding: 'utf-8',\n });\n return output.trim().split('\\n').filter(Boolean);\n } catch {\n return [];\n }\n}\n\n/** Get all source files in the project. */\nexport function getAllSourceFiles(projectRoot: string, config: ViberailsConfig): string[] {\n const files: string[] = [];\n const walk = (dir: string) => {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const rel = path.relative(projectRoot, path.join(dir, entry.name));\n if (entry.isDirectory()) {\n if (ALWAYS_SKIP_DIRS.has(entry.name)) {\n continue;\n }\n if (isIgnored(rel, config.ignore)) continue;\n walk(path.join(dir, entry.name));\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name);\n if (SOURCE_EXTS.has(ext) && !isIgnored(rel, config.ignore)) {\n files.push(rel);\n }\n }\n }\n };\n walk(projectRoot);\n return files;\n}\n\n/** Collect source files from a directory recursively. */\nexport function collectSourceFiles(dir: string, projectRoot: string): string[] {\n const files: string[] = [];\n const walk = (d: string) => {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(d, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules') continue;\n walk(path.join(d, entry.name));\n } else if (entry.isFile()) {\n files.push(path.relative(projectRoot, path.join(d, entry.name)));\n }\n }\n };\n walk(dir);\n return files;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { CheckViolation, ViberailsConfig } from '@viberails/types';\nimport { collectSourceFiles } from './check-files.js';\n\nconst SOURCE_EXTS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.vue',\n '.svelte',\n '.astro',\n]);\n\n/** Check for source files without corresponding test files. */\nexport function checkMissingTests(\n projectRoot: string,\n config: ViberailsConfig,\n severity: 'error' | 'warn',\n): CheckViolation[] {\n const violations: CheckViolation[] = [];\n const { testPattern } = config.structure;\n if (!testPattern) return violations;\n\n const srcDir = config.structure.srcDir;\n if (!srcDir) return violations;\n\n const srcPath = path.join(projectRoot, srcDir);\n if (!fs.existsSync(srcPath)) return violations;\n\n const testSuffix = testPattern.replace('*', '');\n const sourceFiles = collectSourceFiles(srcPath, projectRoot);\n\n for (const relFile of sourceFiles) {\n const basename = path.basename(relFile);\n\n // Skip test files, index files, type definition files\n if (\n basename.includes('.test.') ||\n basename.includes('.spec.') ||\n basename.startsWith('index.') ||\n basename.endsWith('.d.ts')\n ) {\n continue;\n }\n\n const ext = path.extname(basename);\n if (!SOURCE_EXTS.has(ext)) continue;\n\n const stem = basename.slice(0, basename.indexOf('.'));\n const expectedTestFile = `${stem}${testSuffix}`;\n\n // Look for the test file next to the source or in the tests directory\n const dir = path.dirname(path.join(projectRoot, relFile));\n const colocatedTest = path.join(dir, expectedTestFile);\n const testsDir = config.structure.tests;\n const dedicatedTest = testsDir ? path.join(projectRoot, testsDir, expectedTestFile) : null;\n\n const hasTest =\n fs.existsSync(colocatedTest) || (dedicatedTest !== null && fs.existsSync(dedicatedTest));\n\n if (!hasTest) {\n violations.push({\n file: relFile,\n rule: 'missing-test',\n message: `No test file found. Expected \\`${expectedTestFile}\\`.`,\n severity,\n });\n }\n }\n\n return violations;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { loadConfig } from '@viberails/config';\nimport chalk from 'chalk';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport { resolveConfigForFile } from './check-config.js';\nimport { checkNaming, getAllSourceFiles } from './check-files.js';\nimport { checkMissingTests } from './check-tests.js';\nimport { checkGitDirty, getConventionValue, printPlan } from './fix-helpers.js';\nimport { confirmDangerous } from '../utils/prompt.js';\nimport { updateImportsAfterRenames } from './fix-imports.js';\nimport {\n computeRename,\n deduplicateRenames,\n executeRename,\n type RenameRecord,\n} from './fix-naming.js';\nimport { generateTestStub, type TestStubRecord, writeTestStub } from './fix-tests.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\nexport interface FixOptions {\n dryRun?: boolean;\n rule?: string[];\n yes?: boolean;\n}\n\n/**\n * Run the viberails fix command.\n * Detects violations, computes fixes, optionally confirms, then applies.\n */\nexport async function fixCommand(options: FixOptions, cwd?: string): Promise<number> {\n const startDir = cwd ?? process.cwd();\n const projectRoot = findProjectRoot(startDir);\n\n if (!projectRoot) {\n console.error(`${chalk.red('Error:')} No package.json found. Are you in a JS/TS project?`);\n return 1;\n }\n\n const configPath = path.join(projectRoot, CONFIG_FILE);\n if (!fs.existsSync(configPath)) {\n console.error(\n `${chalk.red('Error:')} No viberails.config.json found. Run \\`viberails init\\` first.`,\n );\n return 1;\n }\n\n const config = await loadConfig(configPath);\n\n // Git dirty check — warn but don't block\n if (!options.dryRun) {\n const isDirty = checkGitDirty(projectRoot);\n if (isDirty) {\n console.log(\n chalk.yellow('Warning: You have uncommitted changes. Consider committing first.'),\n );\n }\n }\n\n const shouldFixNaming = !options.rule || options.rule.includes('file-naming');\n const shouldFixTests = !options.rule || options.rule.includes('missing-test');\n\n // Collect source files\n const allFiles = getAllSourceFiles(projectRoot, config);\n\n // Compute naming renames\n const renames: RenameRecord[] = [];\n if (shouldFixNaming) {\n for (const file of allFiles) {\n const resolved = resolveConfigForFile(file, config);\n if (!resolved.rules.enforceNaming || !resolved.conventions.fileNaming) continue;\n\n const violation = checkNaming(file, resolved.conventions);\n if (!violation) continue;\n\n const convention = getConventionValue(resolved.conventions.fileNaming);\n if (!convention) continue;\n\n const rename = computeRename(file, convention, projectRoot);\n if (rename) renames.push(rename);\n }\n }\n\n const dedupedRenames = deduplicateRenames(renames);\n\n // Compute test stubs\n const testStubs: TestStubRecord[] = [];\n if (shouldFixTests && config.rules.requireTests) {\n const testViolations = checkMissingTests(projectRoot, config, 'warn');\n for (const v of testViolations) {\n const stub = generateTestStub(v.file, config, projectRoot);\n if (stub) testStubs.push(stub);\n }\n }\n\n // Nothing to fix\n if (dedupedRenames.length === 0 && testStubs.length === 0) {\n console.log(`${chalk.green('✓')} No fixable violations found.`);\n return 0;\n }\n\n // Display plan\n printPlan(dedupedRenames, testStubs);\n\n if (options.dryRun) {\n console.log(chalk.dim('\\nDry run — no changes applied.'));\n return 0;\n }\n\n // Confirm\n if (!options.yes) {\n const confirmed = await confirmDangerous('Apply these fixes?');\n if (!confirmed) {\n console.log('Aborted.');\n return 0;\n }\n }\n\n // Apply: 1. Renames\n let renameCount = 0;\n for (const rename of dedupedRenames) {\n if (executeRename(rename)) {\n renameCount++;\n }\n }\n\n // Apply: 2. Import updates\n let importUpdateCount = 0;\n if (renameCount > 0) {\n const appliedRenames = dedupedRenames.filter((r) => fs.existsSync(r.newAbsPath));\n const updates = await updateImportsAfterRenames(appliedRenames, projectRoot);\n importUpdateCount = updates.length;\n }\n\n // Apply: 3. Test stubs\n let stubCount = 0;\n for (const stub of testStubs) {\n if (!fs.existsSync(stub.absPath)) {\n writeTestStub(stub, config);\n stubCount++;\n }\n }\n\n // Summary\n console.log('');\n if (renameCount > 0) {\n console.log(`${chalk.green('✓')} Renamed ${renameCount} file${renameCount > 1 ? 's' : ''}`);\n }\n if (importUpdateCount > 0) {\n console.log(\n `${chalk.green('✓')} Updated ${importUpdateCount} import${importUpdateCount > 1 ? 's' : ''}`,\n );\n }\n if (stubCount > 0) {\n console.log(`${chalk.green('✓')} Generated ${stubCount} test stub${stubCount > 1 ? 's' : ''}`);\n }\n\n return 0;\n}\n","import { execSync } from 'node:child_process';\nimport chalk from 'chalk';\nimport type { RenameRecord } from './fix-naming.js';\nimport type { TestStubRecord } from './fix-tests.js';\n\n/**\n * Display the planned renames and test stubs.\n */\nexport function printPlan(renames: RenameRecord[], stubs: TestStubRecord[]): void {\n if (renames.length > 0) {\n console.log(chalk.bold('\\nFile renames:'));\n for (const r of renames) {\n console.log(` ${chalk.red(r.oldPath)} → ${chalk.green(r.newPath)}`);\n }\n }\n\n if (stubs.length > 0) {\n console.log(chalk.bold('\\nTest stubs to create:'));\n for (const s of stubs) {\n console.log(` ${chalk.green('+')} ${s.path}`);\n }\n }\n}\n\n/**\n * Check if the git working tree has uncommitted changes.\n */\nexport function checkGitDirty(projectRoot: string): boolean {\n try {\n const output = execSync('git status --porcelain', {\n cwd: projectRoot,\n encoding: 'utf-8',\n });\n return output.trim().length > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Extract the string value from a convention (which may be a string or an object with a value property).\n */\nexport function getConventionValue(convention: unknown): string | undefined {\n if (typeof convention === 'string') return convention;\n if (convention && typeof convention === 'object' && 'value' in convention) {\n return (convention as { value: string }).value;\n }\n return undefined;\n}\n","import * as path from 'node:path';\nimport type { RenameRecord } from './fix-naming.js';\n\nexport interface ImportUpdateRecord {\n file: string;\n oldSpecifier: string;\n newSpecifier: string;\n line: number;\n}\n\n/**\n * Strip known JS/TS extensions from a file path for specifier comparison.\n * E.g. \"/foo/bar.ts\" → \"/foo/bar\", \"/foo/bar.js\" → \"/foo/bar\"\n */\nfunction stripExtension(filePath: string): string {\n return filePath.replace(/\\.(tsx?|jsx?|mjs|cjs)$/, '');\n}\n\n/**\n * Compute the new import specifier given the old specifier and the rename.\n * Preserves `.js` suffix if present.\n */\nfunction computeNewSpecifier(oldSpecifier: string, newBare: string): string {\n const hasJsExt = oldSpecifier.endsWith('.js');\n const base = hasJsExt ? oldSpecifier.slice(0, -3) : oldSpecifier;\n\n // Replace the last path segment\n const dir = base.lastIndexOf('/');\n const prefix = dir >= 0 ? base.slice(0, dir + 1) : '';\n const newSpec = prefix + newBare;\n\n return hasJsExt ? `${newSpec}.js` : newSpec;\n}\n\n/**\n * Update import specifiers in all source files after renames.\n * Uses ts-morph for AST-accurate rewriting.\n *\n * @param renames - The renames that were applied\n * @param projectRoot - Absolute path to project root\n * @returns Records of all import updates made\n */\nexport async function updateImportsAfterRenames(\n renames: RenameRecord[],\n projectRoot: string,\n): Promise<ImportUpdateRecord[]> {\n if (renames.length === 0) return [];\n\n // Lazy import ts-morph to avoid startup cost\n const { Project, SyntaxKind } = await import('ts-morph');\n\n // Build rename map: stripped old abs path → { newBare }\n const renameMap = new Map<string, { newBare: string }>();\n for (const r of renames) {\n const oldStripped = stripExtension(r.oldAbsPath);\n const newFilename = path.basename(r.newPath);\n const newName = newFilename.slice(0, newFilename.indexOf('.'));\n renameMap.set(oldStripped, { newBare: newName });\n }\n\n const project = new Project({\n tsConfigFilePath: undefined,\n skipAddingFilesFromTsConfig: true,\n });\n\n // Add all TS/JS source files\n project.addSourceFilesAtPaths(path.join(projectRoot, '**/*.{ts,tsx,js,jsx,mjs,cjs}'));\n\n const updates: ImportUpdateRecord[] = [];\n const extensions = ['', '.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.tsx', '/index.js'];\n\n for (const sourceFile of project.getSourceFiles()) {\n const filePath = sourceFile.getFilePath();\n // Skip node_modules and dist (check path segments to avoid false matches)\n const segments = filePath.split(path.sep);\n if (segments.includes('node_modules') || segments.includes('dist')) continue;\n\n const fileDir = path.dirname(filePath);\n\n // Process static imports\n for (const decl of sourceFile.getImportDeclarations()) {\n const specifier = decl.getModuleSpecifierValue();\n if (!specifier.startsWith('.')) continue;\n\n const match = resolveToRenamedFile(specifier, fileDir, renameMap, extensions);\n if (!match) continue;\n\n const newSpec = computeNewSpecifier(specifier, match.newBare);\n updates.push({\n file: filePath,\n oldSpecifier: specifier,\n newSpecifier: newSpec,\n line: decl.getStartLineNumber(),\n });\n decl.setModuleSpecifier(newSpec);\n }\n\n // Process re-exports\n for (const decl of sourceFile.getExportDeclarations()) {\n const specifier = decl.getModuleSpecifierValue();\n if (!specifier || !specifier.startsWith('.')) continue;\n\n const match = resolveToRenamedFile(specifier, fileDir, renameMap, extensions);\n if (!match) continue;\n\n const newSpec = computeNewSpecifier(specifier, match.newBare);\n updates.push({\n file: filePath,\n oldSpecifier: specifier,\n newSpecifier: newSpec,\n line: decl.getStartLineNumber(),\n });\n decl.setModuleSpecifier(newSpec);\n }\n\n // Process dynamic imports\n for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n if (call.getExpression().getKind() !== SyntaxKind.ImportKeyword) continue;\n\n const args = call.getArguments();\n if (args.length === 0) continue;\n\n const arg = args[0];\n if (arg.getKind() !== SyntaxKind.StringLiteral) continue;\n\n const specifier = arg.getText().slice(1, -1);\n if (!specifier.startsWith('.')) continue;\n\n const match = resolveToRenamedFile(specifier, fileDir, renameMap, extensions);\n if (!match) continue;\n\n const newSpec = computeNewSpecifier(specifier, match.newBare);\n updates.push({\n file: filePath,\n oldSpecifier: specifier,\n newSpecifier: newSpec,\n line: call.getStartLineNumber(),\n });\n // Replace the string literal content\n const quote = arg.getText()[0];\n arg.replaceWithText(`${quote}${newSpec}${quote}`);\n }\n }\n\n if (updates.length > 0) {\n await project.save();\n }\n\n return updates;\n}\n\n/**\n * Try to resolve a relative specifier to a renamed file.\n * Returns the rename info if matched, undefined otherwise.\n */\nfunction resolveToRenamedFile(\n specifier: string,\n fromDir: string,\n renameMap: Map<string, { newBare: string }>,\n extensions: string[],\n): { newBare: string } | undefined {\n // Strip .js extension for resolution (TypeScript convention)\n const cleanSpec = specifier.endsWith('.js') ? specifier.slice(0, -3) : specifier;\n const resolved = path.resolve(fromDir, cleanSpec);\n\n for (const ext of extensions) {\n const candidate = resolved + ext;\n const stripped = stripExtension(candidate);\n const match = renameMap.get(stripped);\n if (match) return match;\n }\n\n return undefined;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { convertName } from './convert-name.js';\n\nexport interface RenameRecord {\n oldPath: string;\n newPath: string;\n oldAbsPath: string;\n newAbsPath: string;\n}\n\n/**\n * Compute the rename for a file that violates the naming convention.\n * Returns null if no rename is needed or the target already exists.\n */\nexport function computeRename(\n relPath: string,\n targetConvention: string,\n projectRoot: string,\n): RenameRecord | null {\n const filename = path.basename(relPath);\n const dir = path.dirname(relPath);\n\n // Extract bare name (before first dot) — matches checkNaming logic\n const dotIndex = filename.indexOf('.');\n if (dotIndex === -1) return null;\n\n const bare = filename.slice(0, dotIndex);\n const suffix = filename.slice(dotIndex); // e.g. \".tsx\" or \".test.ts\"\n\n const newBare = convertName(bare, targetConvention);\n if (newBare === bare) return null;\n\n const newFilename = newBare + suffix;\n const newRelPath = path.join(dir, newFilename);\n const oldAbsPath = path.join(projectRoot, relPath);\n const newAbsPath = path.join(projectRoot, newRelPath);\n\n // Skip if target already exists\n if (fs.existsSync(newAbsPath)) return null;\n\n return { oldPath: relPath, newPath: newRelPath, oldAbsPath, newAbsPath };\n}\n\n/**\n * Execute a single rename on disk.\n * Returns true if successful, false if skipped (target exists).\n */\nexport function executeRename(rename: RenameRecord): boolean {\n if (fs.existsSync(rename.newAbsPath)) return false;\n fs.renameSync(rename.oldAbsPath, rename.newAbsPath);\n return true;\n}\n\n/**\n * Detect and deduplicate rename collisions.\n * If two planned renames target the same path, the second is removed.\n */\nexport function deduplicateRenames(renames: RenameRecord[]): RenameRecord[] {\n const seen = new Set<string>();\n const result: RenameRecord[] = [];\n for (const r of renames) {\n if (seen.has(r.newAbsPath)) continue;\n seen.add(r.newAbsPath);\n result.push(r);\n }\n return result;\n}\n","/**\n * Split a bare filename into its constituent words.\n *\n * Handles kebab-case, camelCase, PascalCase, and snake_case inputs.\n * Consecutive uppercase letters (acronyms like \"URL\") are kept together.\n */\nexport function splitIntoWords(name: string): string[] {\n // First, split on explicit separators (hyphens and underscores)\n const parts = name.split(/[-_]/);\n\n const words: string[] = [];\n for (const part of parts) {\n if (part === '') continue;\n\n // Split camelCase and PascalCase boundaries\n // \"UserProfile\" → [\"User\", \"Profile\"]\n // \"parseJSON\" → [\"parse\", \"JSON\"]\n // \"XMLParser\" → [\"XML\", \"Parser\"]\n let current = '';\n for (let i = 0; i < part.length; i++) {\n const ch = part[i];\n const isUpper = ch >= 'A' && ch <= 'Z';\n\n if (isUpper && current.length > 0) {\n const prevIsUpper =\n current[current.length - 1] >= 'A' && current[current.length - 1] <= 'Z';\n const nextIsLower = i + 1 < part.length && part[i + 1] >= 'a' && part[i + 1] <= 'z';\n\n if (!prevIsUpper || nextIsLower) {\n words.push(current.toLowerCase());\n current = '';\n }\n }\n current += ch;\n }\n if (current) words.push(current.toLowerCase());\n }\n\n return words;\n}\n\n/**\n * Convert a bare filename to the specified naming convention.\n *\n * @param bare - The bare filename without extension (e.g. \"UserProfile\")\n * @param target - The target convention (kebab-case, camelCase, PascalCase, snake_case)\n * @returns The converted name\n */\nexport function convertName(bare: string, target: string): string {\n const words = splitIntoWords(bare);\n if (words.length === 0) return bare;\n\n switch (target) {\n case 'kebab-case':\n return words.join('-');\n case 'camelCase':\n return words[0] + words.slice(1).map(capitalize).join('');\n case 'PascalCase':\n return words.map(capitalize).join('');\n case 'snake_case':\n return words.join('_');\n default:\n return bare;\n }\n}\n\nfunction capitalize(word: string): string {\n if (word.length === 0) return word;\n return word[0].toUpperCase() + word.slice(1);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ViberailsConfig } from '@viberails/types';\n\nexport interface TestStubRecord {\n path: string;\n absPath: string;\n moduleName: string;\n}\n\n/**\n * Generate a test stub record for a source file that is missing tests.\n * Returns null if the test file already exists.\n */\nexport function generateTestStub(\n sourceRelPath: string,\n config: ViberailsConfig,\n projectRoot: string,\n): TestStubRecord | null {\n const { testPattern } = config.structure;\n if (!testPattern) return null;\n\n const basename = path.basename(sourceRelPath);\n const stem = basename.slice(0, basename.indexOf('.'));\n const testSuffix = testPattern.replace('*', '');\n const testFilename = `${stem}${testSuffix}`;\n\n const dir = path.dirname(path.join(projectRoot, sourceRelPath));\n const testAbsPath = path.join(dir, testFilename);\n\n if (fs.existsSync(testAbsPath)) return null;\n\n return {\n path: path.relative(projectRoot, testAbsPath),\n absPath: testAbsPath,\n moduleName: stem,\n };\n}\n\n/**\n * Write a test stub file to disk.\n */\nexport function writeTestStub(stub: TestStubRecord, config: ViberailsConfig): void {\n const runner = config.stack.testRunner === 'jest' ? 'jest' : 'vitest';\n const importLine =\n runner === 'jest'\n ? '' // jest globals are available without import\n : \"import { describe, it, expect } from 'vitest';\\n\\n\";\n\n const content = `${importLine}describe('${stub.moduleName}', () => {\\n it.todo('add tests');\\n});\\n`;\n\n fs.mkdirSync(path.dirname(stub.absPath), { recursive: true });\n fs.writeFileSync(stub.absPath, content);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as clack from '@clack/prompts';\nimport { generateConfig } from '@viberails/config';\nimport { scan } from '@viberails/scanner';\nimport type { ConfigConventions, ConventionValue, ViberailsConfig } from '@viberails/types';\nimport chalk from 'chalk';\nimport { displayRulesPreview, displayScanResults, formatScanResultsText } from '../display.js';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport {\n confirm,\n promptInitDecision,\n promptIntegrations,\n promptRuleCustomization,\n} from '../utils/prompt.js';\nimport { resolveWorkspacePackages } from '../utils/resolve-workspace-packages.js';\nimport { writeGeneratedFiles } from '../utils/write-generated-files.js';\nimport { detectHookManager, setupClaudeCodeHook, setupPreCommitHook } from './init-hooks.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\n/**\n * Filter a ConfigConventions object to only include high-confidence entries.\n */\nfunction filterHighConfidence(conventions: ConfigConventions): ConfigConventions {\n const filtered: ConfigConventions = {};\n for (const [key, value] of Object.entries(conventions)) {\n if (value === undefined) continue;\n if (typeof value === 'string') {\n filtered[key as keyof ConfigConventions] = value;\n } else if (value._confidence === 'high') {\n filtered[key as keyof ConfigConventions] = value as ConventionValue;\n }\n }\n return filtered;\n}\n\n/**\n * Extract the string value from a ConventionValue.\n */\nfunction getConventionStr(\n cv: string | { value: string; _confidence: string; _consistency: number } | undefined,\n): string | undefined {\n if (!cv) return undefined;\n return typeof cv === 'string' ? cv : cv.value;\n}\n\n/**\n * Check if a monorepo config has per-package convention overrides.\n */\nfunction hasConventionOverrides(config: ViberailsConfig): boolean {\n if (!config.packages || config.packages.length === 0) return false;\n return config.packages.some((pkg) => pkg.conventions && Object.keys(pkg.conventions).length > 0);\n}\n\n/**\n * Run the viberails init flow.\n *\n * @param options - CLI options\n * @param cwd - Working directory override (for testing)\n */\nexport async function initCommand(options: { yes?: boolean }, cwd?: string): Promise<void> {\n const startDir = cwd ?? process.cwd();\n\n // 1. Find project root\n const projectRoot = findProjectRoot(startDir);\n if (!projectRoot) {\n throw new Error(\n 'No package.json found in this directory or any parent.\\n\\n' +\n 'Make sure you are inside a JavaScript or TypeScript project, then run:\\n' +\n ' npx viberails',\n );\n }\n\n // 2. Check for existing config (early exit — no clack)\n const configPath = path.join(projectRoot, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n console.log(\n `${chalk.yellow('!')} viberails is already initialized.\\n` +\n ` Run ${chalk.cyan('viberails sync')} to update, or delete viberails.config.json to start fresh.`,\n );\n return;\n }\n\n // === Non-interactive path: console.log only, no clack, no hooks ===\n if (options.yes) {\n console.log(chalk.dim('Scanning project...'));\n const scanResult = await scan(projectRoot);\n const config = generateConfig(scanResult);\n config.conventions = filterHighConfidence(config.conventions);\n\n displayScanResults(scanResult);\n displayRulesPreview(config);\n\n // Auto-infer boundaries for monorepos\n if (config.workspace?.packages && config.workspace.packages.length > 0) {\n console.log(chalk.dim('Building import graph...'));\n const { buildImportGraph, inferBoundaries } = await import('@viberails/graph');\n const packages = resolveWorkspacePackages(projectRoot, config.workspace);\n const graph = await buildImportGraph(projectRoot, {\n packages,\n ignore: config.ignore,\n });\n const inferred = inferBoundaries(graph);\n if (inferred.length > 0) {\n config.boundaries = inferred;\n config.rules.enforceBoundaries = true;\n console.log(` Inferred ${inferred.length} boundary rules`);\n }\n }\n\n // Write files\n fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`);\n writeGeneratedFiles(projectRoot, config, scanResult);\n updateGitignore(projectRoot);\n\n // No hooks installed in --yes mode\n console.log(`\\nCreated:`);\n console.log(` ${chalk.green('\\u2713')} ${CONFIG_FILE}`);\n console.log(` ${chalk.green('\\u2713')} .viberails/context.md`);\n console.log(` ${chalk.green('\\u2713')} .viberails/scan-result.json`);\n return;\n }\n\n // === Interactive path: all clack ===\n clack.intro('viberails');\n\n // 3. Scan with spinner\n const s = clack.spinner();\n s.start('Scanning project...');\n const scanResult = await scan(projectRoot);\n const config = generateConfig(scanResult);\n s.stop('Scan complete');\n\n // 4. Sparse project warning\n if (scanResult.statistics.totalFiles === 0) {\n clack.log.warn(\n 'No source files detected. viberails will generate context\\n' +\n 'with minimal content. Run viberails sync after adding files.',\n );\n }\n\n // 5. Show scan results + rules as a note box\n const resultsText = formatScanResultsText(scanResult, config);\n clack.note(resultsText, 'Scan results');\n\n // 6. Accept or Customize\n const decision = await promptInitDecision();\n\n if (decision === 'customize') {\n clack.note(\n 'Rules control what viberails checks for.\\nYou can change these later in viberails.config.json.',\n 'Rules',\n );\n\n const overrides = await promptRuleCustomization({\n maxFileLines: config.rules.maxFileLines,\n requireTests: config.rules.requireTests,\n enforceNaming: config.rules.enforceNaming,\n enforcement: config.enforcement,\n fileNamingValue: getConventionStr(config.conventions.fileNaming),\n });\n\n config.rules.maxFileLines = overrides.maxFileLines;\n config.rules.requireTests = overrides.requireTests;\n config.rules.enforceNaming = overrides.enforceNaming;\n config.enforcement = overrides.enforcement;\n\n if (config.workspace?.packages && config.workspace.packages.length > 0) {\n clack.note(\n 'These rules apply globally. To customize per package,\\n' +\n 'edit the \"packages\" section in viberails.config.json.',\n 'Per-package overrides',\n );\n }\n }\n\n // 7. Boundary inference (monorepo only)\n if (config.workspace?.packages && config.workspace.packages.length > 0) {\n clack.note(\n 'Boundary rules prevent packages from importing where they\\n' +\n \"shouldn't. viberails scans your existing imports and creates\\n\" +\n \"rules based on what's already working.\",\n 'Boundaries',\n );\n const shouldInfer = await confirm('Infer boundary rules from import patterns?');\n\n if (shouldInfer) {\n const bs = clack.spinner();\n bs.start('Building import graph...');\n const { buildImportGraph, inferBoundaries } = await import('@viberails/graph');\n const packages = resolveWorkspacePackages(projectRoot, config.workspace);\n const graph = await buildImportGraph(projectRoot, {\n packages,\n ignore: config.ignore,\n });\n const inferred = inferBoundaries(graph);\n if (inferred.length > 0) {\n config.boundaries = inferred;\n config.rules.enforceBoundaries = true;\n bs.stop(`Inferred ${inferred.length} boundary rules`);\n } else {\n bs.stop('No boundary rules inferred');\n }\n }\n }\n\n // 8. Integration selection\n const hookManager = detectHookManager(projectRoot);\n const integrations = await promptIntegrations(hookManager);\n\n // 9. Per-package convention differences note\n if (hasConventionOverrides(config)) {\n clack.note(\n 'Some packages use different conventions. Per-package\\n' +\n 'overrides have been saved in viberails.config.json —\\n' +\n 'review and adjust as needed.',\n 'Per-package conventions',\n );\n }\n\n // 10. Write config\n fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`);\n\n // 11. Generate context and scan-result.json\n writeGeneratedFiles(projectRoot, config, scanResult);\n\n // 12. Update .gitignore\n updateGitignore(projectRoot);\n\n // 13. Set up hooks based on selection\n const createdFiles: string[] = [\n CONFIG_FILE,\n '.viberails/context.md',\n '.viberails/scan-result.json',\n ];\n\n if (integrations.preCommitHook) {\n setupPreCommitHook(projectRoot);\n const hookMgr = detectHookManager(projectRoot);\n if (hookMgr) {\n createdFiles.push(`lefthook.yml \\u2014 added viberails pre-commit`);\n }\n }\n if (integrations.claudeCodeHook) {\n setupClaudeCodeHook(projectRoot);\n createdFiles.push('.claude/settings.json \\u2014 added viberails hook');\n }\n\n // 14. Summary\n clack.log.success(`Created:\\n${createdFiles.map((f) => ` ${f}`).join('\\n')}`);\n\n clack.outro('Done! Next: review viberails.config.json, then run viberails check');\n}\n\n/**\n * Append viberails entries to .gitignore if not already present.\n * Only scan-result.json is ignored — context.md should be committed\n * so AI agents can read the enforced rules.\n */\nfunction updateGitignore(projectRoot: string): void {\n const gitignorePath = path.join(projectRoot, '.gitignore');\n let content = '';\n\n if (fs.existsSync(gitignorePath)) {\n content = fs.readFileSync(gitignorePath, 'utf-8');\n }\n\n if (!content.includes('.viberails/scan-result.json')) {\n const block = '\\n# viberails\\n.viberails/scan-result.json\\n';\n const prefix = content.length === 0 ? '' : `${content.trimEnd()}\\n`;\n fs.writeFileSync(gitignorePath, `${prefix}${block}`);\n }\n}\n","import type { DetectedConvention, ScanResult, StackItem, ViberailsConfig } from '@viberails/types';\nimport { FRAMEWORK_NAMES, LIBRARY_NAMES, ORM_NAMES, STYLING_NAMES } from '@viberails/types';\nimport chalk from 'chalk';\nimport {\n formatExtensions,\n formatRoleGroup,\n formatSummary,\n groupByRole,\n} from './display-helpers.js';\nimport { displayMonorepoResults, formatMonorepoResultsText } from './display-monorepo.js';\n\n/** Labels for convention keys. */\nconst CONVENTION_LABELS: Record<string, string> = {\n fileNaming: 'File naming',\n componentNaming: 'Component naming',\n hookNaming: 'Hook naming',\n importAlias: 'Import alias',\n};\n\n/**\n * Format a StackItem for display: \"DisplayName Version\".\n */\nexport function formatItem(item: StackItem, nameMap?: Record<string, string>): string {\n const name = nameMap?.[item.name] ?? item.name;\n return item.version ? `${name} ${item.version}` : name;\n}\n\n/**\n * Format a confidence label for display.\n */\nexport function confidenceLabel(convention: DetectedConvention): string {\n const pct = Math.round(convention.consistency);\n if (convention.confidence === 'high') {\n return `${pct}% — high confidence, will enforce`;\n }\n return `${pct}% — medium confidence, suggested only`;\n}\n\n/**\n * Display conventions section, shared between single-package and monorepo.\n */\nexport function displayConventions(scanResult: ScanResult): void {\n const conventionEntries = Object.entries(scanResult.conventions);\n if (conventionEntries.length === 0) return;\n\n console.log(`\\n${chalk.bold('Conventions:')}`);\n for (const [key, convention] of conventionEntries) {\n if (convention.confidence === 'low') continue;\n const label = CONVENTION_LABELS[key] ?? key;\n\n if (scanResult.packages.length > 1) {\n const pkgValues = scanResult.packages\n .filter((pkg) => pkg.conventions[key] && pkg.conventions[key].confidence !== 'low')\n .map((pkg) => ({ relativePath: pkg.relativePath, convention: pkg.conventions[key] }));\n\n const allSame = pkgValues.every((pv) => pv.convention.value === convention.value);\n\n if (allSame || pkgValues.length <= 1) {\n const ind = convention.confidence === 'high' ? chalk.green('✓') : chalk.yellow('~');\n const detail = chalk.dim(`(${confidenceLabel(convention)})`);\n console.log(` ${ind} ${label}: ${convention.value} ${detail}`);\n } else {\n console.log(` ${chalk.yellow('~')} ${label}: varies by package`);\n for (const pv of pkgValues) {\n const pct = Math.round(pv.convention.consistency);\n console.log(` ${pv.relativePath}: ${pv.convention.value} (${pct}%)`);\n }\n }\n } else {\n const ind = convention.confidence === 'high' ? chalk.green('✓') : chalk.yellow('~');\n const detail = chalk.dim(`(${confidenceLabel(convention)})`);\n console.log(` ${ind} ${label}: ${convention.value} ${detail}`);\n }\n }\n}\n\n/**\n * Display summary section with statistics.\n */\nexport function displaySummarySection(scanResult: ScanResult): void {\n const pkgCount = scanResult.packages.length > 1 ? scanResult.packages.length : undefined;\n console.log(`\\n${chalk.bold('Summary:')}`);\n console.log(` ${formatSummary(scanResult.statistics, pkgCount)}`);\n const ext = formatExtensions(scanResult.statistics.filesByExtension);\n if (ext) {\n console.log(` ${ext}`);\n }\n}\n\n/**\n * Display scan results to the console with confidence indicators.\n *\n * @param scanResult - The scan result to display\n */\nexport function displayScanResults(scanResult: ScanResult): void {\n if (scanResult.packages.length > 1) {\n displayMonorepoResults(scanResult);\n return;\n }\n\n const { stack } = scanResult;\n\n console.log(`\\n${chalk.bold('Detected:')}`);\n\n if (stack.framework) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.framework, FRAMEWORK_NAMES)}`);\n }\n console.log(` ${chalk.green('✓')} ${formatItem(stack.language)}`);\n if (stack.styling) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.styling, STYLING_NAMES)}`);\n }\n if (stack.backend) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.backend, FRAMEWORK_NAMES)}`);\n }\n if (stack.orm) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.orm, ORM_NAMES)}`);\n }\n if (stack.linter) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.linter)}`);\n }\n if (stack.formatter) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.formatter)}`);\n }\n if (stack.testRunner) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.testRunner)}`);\n }\n if (stack.packageManager) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.packageManager)}`);\n }\n if (stack.libraries.length > 0) {\n for (const lib of stack.libraries) {\n console.log(` ${chalk.green('✓')} ${formatItem(lib, LIBRARY_NAMES)}`);\n }\n }\n\n // Structure grouped by role\n const groups = groupByRole(scanResult.structure.directories);\n if (groups.length > 0) {\n console.log(`\\n${chalk.bold('Structure:')}`);\n for (const group of groups) {\n console.log(` ${chalk.green('✓')} ${formatRoleGroup(group)}`);\n }\n }\n\n displayConventions(scanResult);\n displaySummarySection(scanResult);\n console.log('');\n}\n\n/**\n * Extract the convention value string from a ConventionValue.\n */\nfunction getConventionStr(\n cv: string | { value: string; _confidence: string; _consistency: number },\n): string {\n return typeof cv === 'string' ? cv : cv.value;\n}\n\n/**\n * Display a preview of the rules that will be enforced.\n */\nexport function displayRulesPreview(config: ViberailsConfig): void {\n console.log(`${chalk.bold('Rules:')}`);\n console.log(` ${chalk.dim('\\u2022')} Max file size: ${config.rules.maxFileLines} lines`);\n\n if (config.rules.requireTests && config.structure.testPattern) {\n console.log(\n ` ${chalk.dim('\\u2022')} Require test files: yes (${config.structure.testPattern})`,\n );\n } else if (config.rules.requireTests) {\n console.log(` ${chalk.dim('\\u2022')} Require test files: yes`);\n } else {\n console.log(` ${chalk.dim('\\u2022')} Require test files: no`);\n }\n\n if (config.rules.enforceNaming && config.conventions.fileNaming) {\n console.log(\n ` ${chalk.dim('\\u2022')} Enforce file naming: ${getConventionStr(config.conventions.fileNaming)}`,\n );\n } else {\n console.log(` ${chalk.dim('\\u2022')} Enforce file naming: no`);\n }\n\n console.log(\n ` ${chalk.dim('\\u2022')} Enforce boundaries: ${config.rules.enforceBoundaries ? 'yes' : 'no'}`,\n );\n\n console.log('');\n\n if (config.enforcement === 'enforce') {\n console.log(`${chalk.bold('Enforcement mode:')} enforce (violations will block commits)`);\n } else {\n console.log(\n `${chalk.bold('Enforcement mode:')} warn (violations shown but won't block commits)`,\n );\n }\n console.log('');\n}\n\n/**\n * Format a plain-text confidence label (no chalk).\n */\nfunction plainConfidenceLabel(convention: DetectedConvention): string {\n const pct = Math.round(convention.consistency);\n if (convention.confidence === 'high') {\n return `${pct}%`;\n }\n return `${pct}%, suggested only`;\n}\n\n/**\n * Build conventions section as plain text lines.\n */\nexport function formatConventionsText(scanResult: ScanResult): string[] {\n const lines: string[] = [];\n const conventionEntries = Object.entries(scanResult.conventions);\n if (conventionEntries.length === 0) return lines;\n\n lines.push('');\n lines.push('Conventions:');\n for (const [key, convention] of conventionEntries) {\n if (convention.confidence === 'low') continue;\n const label = CONVENTION_LABELS[key] ?? key;\n\n if (scanResult.packages.length > 1) {\n const pkgValues = scanResult.packages\n .filter((pkg) => pkg.conventions[key] && pkg.conventions[key].confidence !== 'low')\n .map((pkg) => ({ relativePath: pkg.relativePath, convention: pkg.conventions[key] }));\n\n const allSame = pkgValues.every((pv) => pv.convention.value === convention.value);\n\n if (allSame || pkgValues.length <= 1) {\n const ind = convention.confidence === 'high' ? '\\u2713' : '~';\n lines.push(` ${ind} ${label}: ${convention.value} (${plainConfidenceLabel(convention)})`);\n } else {\n lines.push(` ~ ${label}: varies by package`);\n for (const pv of pkgValues) {\n const pct = Math.round(pv.convention.consistency);\n lines.push(` ${pv.relativePath}: ${pv.convention.value} (${pct}%)`);\n }\n }\n } else {\n const ind = convention.confidence === 'high' ? '\\u2713' : '~';\n lines.push(` ${ind} ${label}: ${convention.value} (${plainConfidenceLabel(convention)})`);\n }\n }\n return lines;\n}\n\n/**\n * Build rules preview as plain text lines.\n */\nexport function formatRulesText(config: ViberailsConfig): string[] {\n const lines: string[] = [];\n lines.push('');\n lines.push('Rules:');\n lines.push(` \\u2022 Max file size: ${config.rules.maxFileLines} lines`);\n\n if (config.rules.requireTests && config.structure.testPattern) {\n lines.push(` \\u2022 Require test files: yes (${config.structure.testPattern})`);\n } else if (config.rules.requireTests) {\n lines.push(' \\u2022 Require test files: yes');\n } else {\n lines.push(' \\u2022 Require test files: no');\n }\n\n if (config.rules.enforceNaming && config.conventions.fileNaming) {\n lines.push(` \\u2022 Enforce file naming: ${getConventionStr(config.conventions.fileNaming)}`);\n } else {\n lines.push(' \\u2022 Enforce file naming: no');\n }\n\n lines.push(` \\u2022 Enforcement mode: ${config.enforcement}`);\n\n return lines;\n}\n\n/**\n * Build scan results as a multi-line string for clack.note().\n * Returns plain text without chalk colors.\n *\n * @param scanResult - The scan result to format\n * @param config - The generated config (for rules preview)\n * @returns Formatted multi-line string\n */\nexport function formatScanResultsText(scanResult: ScanResult, config: ViberailsConfig): string {\n if (scanResult.packages.length > 1) {\n return formatMonorepoResultsText(scanResult, config);\n }\n\n const lines: string[] = [];\n const { stack } = scanResult;\n\n lines.push('Detected:');\n if (stack.framework) {\n lines.push(` \\u2713 ${formatItem(stack.framework, FRAMEWORK_NAMES)}`);\n }\n lines.push(` \\u2713 ${formatItem(stack.language)}`);\n if (stack.styling) {\n lines.push(` \\u2713 ${formatItem(stack.styling, STYLING_NAMES)}`);\n }\n if (stack.backend) {\n lines.push(` \\u2713 ${formatItem(stack.backend, FRAMEWORK_NAMES)}`);\n }\n if (stack.orm) {\n lines.push(` \\u2713 ${formatItem(stack.orm, ORM_NAMES)}`);\n }\n\n // Compact secondary tools line\n const secondaryParts: string[] = [];\n if (stack.packageManager) secondaryParts.push(formatItem(stack.packageManager));\n if (stack.linter) secondaryParts.push(formatItem(stack.linter));\n if (stack.formatter) secondaryParts.push(formatItem(stack.formatter));\n if (stack.testRunner) secondaryParts.push(formatItem(stack.testRunner));\n if (secondaryParts.length > 0) {\n lines.push(` \\u2713 ${secondaryParts.join(' \\u00b7 ')}`);\n }\n\n if (stack.libraries.length > 0) {\n for (const lib of stack.libraries) {\n lines.push(` \\u2713 ${formatItem(lib, LIBRARY_NAMES)}`);\n }\n }\n\n // Structure\n const groups = groupByRole(scanResult.structure.directories);\n if (groups.length > 0) {\n lines.push('');\n lines.push('Structure:');\n for (const group of groups) {\n lines.push(` \\u2713 ${formatRoleGroup(group)}`);\n }\n }\n\n // Conventions\n lines.push(...formatConventionsText(scanResult));\n\n // Summary stats\n const pkgCount = scanResult.packages.length > 1 ? scanResult.packages.length : undefined;\n lines.push('');\n lines.push(formatSummary(scanResult.statistics, pkgCount));\n const ext = formatExtensions(scanResult.statistics.filesByExtension);\n if (ext) {\n lines.push(ext);\n }\n\n // Rules\n lines.push(...formatRulesText(config));\n\n return lines.join('\\n');\n}\n","import type { CodebaseStatistics, DirectoryInfo, DirectoryRole } from '@viberails/types';\nimport { ROLE_DESCRIPTIONS } from '@viberails/types';\n\n/**\n * A group of directories sharing the same role within a package.\n */\nexport interface RoleGroup {\n role: DirectoryRole;\n label: string;\n dirCount: number;\n totalFiles: number;\n singlePath?: string;\n}\n\n/**\n * Groups a package's directories by role, merging file counts.\n * Filters out `unknown` role. For single-directory roles, sets `singlePath`.\n *\n * @param directories - The directories to group.\n * @returns Array of RoleGroup entries sorted by role label.\n */\nexport function groupByRole(directories: DirectoryInfo[]): RoleGroup[] {\n const map = new Map<DirectoryRole, { dirs: DirectoryInfo[] }>();\n\n for (const dir of directories) {\n if (dir.role === 'unknown') continue;\n const existing = map.get(dir.role);\n if (existing) {\n existing.dirs.push(dir);\n } else {\n map.set(dir.role, { dirs: [dir] });\n }\n }\n\n const groups: RoleGroup[] = [];\n for (const [role, { dirs }] of map) {\n const label = ROLE_DESCRIPTIONS[role] ?? role;\n const totalFiles = dirs.reduce((sum, d) => sum + d.fileCount, 0);\n groups.push({\n role,\n label,\n dirCount: dirs.length,\n totalFiles,\n singlePath: dirs.length === 1 ? dirs[0].path : undefined,\n });\n }\n\n return groups;\n}\n\n/**\n * Format a summary line from CodebaseStatistics.\n *\n * @param stats - The codebase statistics.\n * @param packageCount - Number of packages (shown for monorepos with > 1).\n * @returns Formatted summary string, e.g. \"3 packages · 743 source files · 48,200 lines · avg 65 lines/file\"\n */\nexport function formatSummary(stats: CodebaseStatistics, packageCount?: number): string {\n const parts: string[] = [];\n if (packageCount && packageCount > 1) {\n parts.push(`${packageCount} packages`);\n }\n parts.push(`${stats.totalFiles.toLocaleString()} source files`);\n parts.push(`${stats.totalLines.toLocaleString()} lines`);\n parts.push(`avg ${Math.round(stats.averageFileLines)} lines/file`);\n return parts.join(' \\u00b7 ');\n}\n\n/**\n * Format top extensions by count, e.g. \".tsx 312 · .ts 289 · .js 142\".\n *\n * @param filesByExtension - Extension counts from CodebaseStatistics.\n * @param maxEntries - Maximum number of extensions to show (default 4).\n * @returns Formatted extension string.\n */\nexport function formatExtensions(\n filesByExtension: Record<string, number>,\n maxEntries: number = 4,\n): string {\n return Object.entries(filesByExtension)\n .sort(([, a], [, b]) => b - a)\n .slice(0, maxEntries)\n .map(([ext, count]) => `${ext} ${count}`)\n .join(' \\u00b7 ');\n}\n\n/**\n * Format a RoleGroup for display.\n *\n * @param group - The role group.\n * @returns Formatted string, e.g. \"Hooks — 4 dirs (55 files)\" or \"Pages / Routes — app (12 files)\"\n */\nexport function formatRoleGroup(group: RoleGroup): string {\n const files = group.totalFiles === 1 ? '1 file' : `${group.totalFiles} files`;\n if (group.singlePath) {\n return `${group.label} — ${group.singlePath} (${files})`;\n }\n const dirs = group.dirCount === 1 ? '1 dir' : `${group.dirCount} dirs`;\n return `${group.label} — ${dirs} (${files})`;\n}\n","import type { PackageScanResult, ScanResult, ViberailsConfig } from '@viberails/types';\nimport { FRAMEWORK_NAMES, STYLING_NAMES } from '@viberails/types';\nimport chalk from 'chalk';\nimport {\n displayConventions,\n displaySummarySection,\n formatConventionsText,\n formatItem,\n formatRulesText,\n} from './display.js';\nimport {\n formatExtensions,\n formatRoleGroup,\n formatSummary,\n groupByRole,\n} from './display-helpers.js';\n\n/**\n * Format a package summary line for monorepo display.\n */\nexport function formatPackageSummary(pkg: PackageScanResult): string {\n const parts: string[] = [];\n if (pkg.stack.framework) {\n parts.push(formatItem(pkg.stack.framework, FRAMEWORK_NAMES));\n }\n if (pkg.stack.styling) {\n parts.push(formatItem(pkg.stack.styling, STYLING_NAMES));\n }\n const files = `${pkg.statistics.totalFiles} files`;\n const detail = parts.length > 0 ? `${parts.join(', ')} (${files})` : `(${files})`;\n return ` ${pkg.relativePath} — ${detail}`;\n}\n\n/**\n * Display scan results for a monorepo with per-package summaries.\n */\nexport function displayMonorepoResults(scanResult: ScanResult): void {\n const { stack, packages } = scanResult;\n\n console.log(`\\n${chalk.bold(`Detected: (monorepo, ${packages.length} packages)`)}`);\n\n // Shared stack items at the top\n console.log(` ${chalk.green('✓')} ${formatItem(stack.language)}`);\n if (stack.packageManager) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.packageManager)}`);\n }\n if (stack.linter) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.linter)}`);\n }\n if (stack.formatter) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.formatter)}`);\n }\n if (stack.testRunner) {\n console.log(` ${chalk.green('✓')} ${formatItem(stack.testRunner)}`);\n }\n\n // Per-package summaries\n console.log('');\n for (const pkg of packages) {\n console.log(formatPackageSummary(pkg));\n }\n\n // Structure grouped by role per package\n const packagesWithDirs = packages.filter((pkg) =>\n pkg.structure.directories.some((d) => d.role !== 'unknown'),\n );\n if (packagesWithDirs.length > 0) {\n console.log(`\\n${chalk.bold('Structure:')}`);\n for (const pkg of packagesWithDirs) {\n const groups = groupByRole(pkg.structure.directories);\n if (groups.length === 0) continue;\n console.log(` ${pkg.relativePath}:`);\n for (const group of groups) {\n console.log(` ${chalk.green('✓')} ${formatRoleGroup(group)}`);\n }\n }\n }\n\n displayConventions(scanResult);\n displaySummarySection(scanResult);\n console.log('');\n}\n\n/**\n * Format a plain-text package summary line (no chalk).\n */\nfunction formatPackageSummaryPlain(pkg: PackageScanResult): string {\n const parts: string[] = [];\n if (pkg.stack.framework) {\n parts.push(formatItem(pkg.stack.framework, FRAMEWORK_NAMES));\n }\n if (pkg.stack.styling) {\n parts.push(formatItem(pkg.stack.styling, STYLING_NAMES));\n }\n const files = `${pkg.statistics.totalFiles} files`;\n const detail = parts.length > 0 ? `${parts.join(', ')} (${files})` : `(${files})`;\n return ` ${pkg.relativePath} — ${detail}`;\n}\n\n/**\n * Build monorepo scan results as a multi-line string for clack.note().\n * Returns plain text without chalk colors.\n */\nexport function formatMonorepoResultsText(scanResult: ScanResult, config: ViberailsConfig): string {\n const lines: string[] = [];\n const { stack, packages } = scanResult;\n\n lines.push(`Detected: (monorepo, ${packages.length} packages)`);\n\n // Shared stack items as compact line\n const sharedParts: string[] = [formatItem(stack.language)];\n if (stack.packageManager) sharedParts.push(formatItem(stack.packageManager));\n if (stack.linter) sharedParts.push(formatItem(stack.linter));\n if (stack.formatter) sharedParts.push(formatItem(stack.formatter));\n if (stack.testRunner) sharedParts.push(formatItem(stack.testRunner));\n lines.push(` \\u2713 ${sharedParts.join(' \\u00b7 ')}`);\n\n // Per-package summaries\n lines.push('');\n for (const pkg of packages) {\n lines.push(formatPackageSummaryPlain(pkg));\n }\n\n // Structure grouped by role per package\n const packagesWithDirs = packages.filter((pkg) =>\n pkg.structure.directories.some((d) => d.role !== 'unknown'),\n );\n if (packagesWithDirs.length > 0) {\n lines.push('');\n lines.push('Structure:');\n for (const pkg of packagesWithDirs) {\n const groups = groupByRole(pkg.structure.directories);\n if (groups.length === 0) continue;\n lines.push(` ${pkg.relativePath}:`);\n for (const group of groups) {\n lines.push(` \\u2713 ${formatRoleGroup(group)}`);\n }\n }\n }\n\n // Conventions\n lines.push(...formatConventionsText(scanResult));\n\n // Summary stats\n const pkgCount = packages.length > 1 ? packages.length : undefined;\n lines.push('');\n lines.push(formatSummary(scanResult.statistics, pkgCount));\n const ext = formatExtensions(scanResult.statistics.filesByExtension);\n if (ext) {\n lines.push(ext);\n }\n\n // Rules\n lines.push(...formatRulesText(config));\n\n return lines.join('\\n');\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { generateContext } from '@viberails/context';\nimport type { ScanResult, ViberailsConfig } from '@viberails/types';\n\nconst CONTEXT_DIR = '.viberails';\nconst CONTEXT_FILE = 'context.md';\nconst SCAN_RESULT_FILE = 'scan-result.json';\n\n/**\n * Write all generated files: context.md and scan-result.json.\n *\n * @param projectRoot - Absolute path to the project root\n * @param config - The viberails configuration\n * @param scanResult - The raw scan result\n */\nexport function writeGeneratedFiles(\n projectRoot: string,\n config: ViberailsConfig,\n scanResult: ScanResult,\n): void {\n const contextDir = path.join(projectRoot, CONTEXT_DIR);\n\n try {\n if (!fs.existsSync(contextDir)) {\n fs.mkdirSync(contextDir, { recursive: true });\n }\n\n const context = generateContext(config);\n fs.writeFileSync(path.join(contextDir, CONTEXT_FILE), context);\n\n fs.writeFileSync(\n path.join(contextDir, SCAN_RESULT_FILE),\n `${JSON.stringify(scanResult, null, 2)}\\n`,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to write generated files to ${contextDir}: ${message}`);\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport chalk from 'chalk';\n\n/**\n * Set up a pre-commit hook that runs viberails check on staged files.\n * Detects Lefthook, Husky, or falls back to a raw git hook.\n */\nexport function setupPreCommitHook(projectRoot: string): void {\n // Check for Lefthook\n const lefthookPath = path.join(projectRoot, 'lefthook.yml');\n if (fs.existsSync(lefthookPath)) {\n addLefthookPreCommit(lefthookPath);\n console.log(` ${chalk.green('✓')} lefthook.yml — added viberails pre-commit`);\n return;\n }\n\n // Check for Husky\n const huskyDir = path.join(projectRoot, '.husky');\n if (fs.existsSync(huskyDir)) {\n writeHuskyPreCommit(huskyDir);\n console.log(` ${chalk.green('✓')} .husky/pre-commit — added viberails check`);\n return;\n }\n\n // Fall back to raw git hook\n const gitDir = path.join(projectRoot, '.git');\n if (fs.existsSync(gitDir)) {\n const hooksDir = path.join(gitDir, 'hooks');\n if (!fs.existsSync(hooksDir)) {\n fs.mkdirSync(hooksDir, { recursive: true });\n }\n writeGitHookPreCommit(hooksDir);\n console.log(` ${chalk.green('✓')} .git/hooks/pre-commit`);\n }\n}\n\nfunction writeGitHookPreCommit(hooksDir: string): void {\n const hookPath = path.join(hooksDir, 'pre-commit');\n if (fs.existsSync(hookPath)) {\n const existing = fs.readFileSync(hookPath, 'utf-8');\n if (existing.includes('viberails')) return;\n fs.writeFileSync(\n hookPath,\n `${existing.trimEnd()}\\n\\n# viberails check\\nnpx viberails check --staged\\n`,\n );\n return;\n }\n const script = [\n '#!/bin/sh',\n '# Generated by viberails — https://viberails.sh',\n '',\n 'npx viberails check --staged',\n '',\n ].join('\\n');\n fs.writeFileSync(hookPath, script, { mode: 0o755 });\n}\n\nfunction addLefthookPreCommit(lefthookPath: string): void {\n const content = fs.readFileSync(lefthookPath, 'utf-8');\n if (content.includes('viberails')) return;\n\n const hasPreCommit = /^pre-commit:/m.test(content);\n if (hasPreCommit) {\n // Append under existing pre-commit section. This appends at the end of the file,\n // which works when pre-commit is the last section. A full YAML parser would handle\n // arbitrary section ordering, but we avoid that dependency to stay lightweight.\n const commandBlock = ['', ' viberails:', ' run: npx viberails check --staged'].join(\n '\\n',\n );\n const updated = `${content.trimEnd()}\\n${commandBlock}\\n`;\n fs.writeFileSync(lefthookPath, updated);\n } else {\n // Add new pre-commit section\n const section = [\n '',\n 'pre-commit:',\n ' commands:',\n ' viberails:',\n ' run: npx viberails check --staged',\n ].join('\\n');\n fs.writeFileSync(lefthookPath, `${content.trimEnd()}\\n${section}\\n`);\n }\n}\n\n/**\n * Detect which pre-commit hook manager is present.\n * Returns a label like \"Lefthook\", \"Husky\", \"git hook\", or undefined if no .git.\n */\nexport function detectHookManager(projectRoot: string): string | undefined {\n if (fs.existsSync(path.join(projectRoot, 'lefthook.yml'))) return 'Lefthook';\n if (fs.existsSync(path.join(projectRoot, '.husky'))) return 'Husky';\n if (fs.existsSync(path.join(projectRoot, '.git'))) return 'git hook';\n return undefined;\n}\n\n/**\n * Set up a Claude Code PostToolUse hook that checks files after edit/write.\n * Writes to .claude/settings.json (project-level, team-shared).\n */\nexport function setupClaudeCodeHook(projectRoot: string): void {\n const claudeDir = path.join(projectRoot, '.claude');\n if (!fs.existsSync(claudeDir)) {\n fs.mkdirSync(claudeDir, { recursive: true });\n }\n\n const settingsPath = path.join(claudeDir, 'settings.json');\n let settings: Record<string, unknown> = {};\n\n if (fs.existsSync(settingsPath)) {\n try {\n settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));\n } catch {\n console.warn(\n ` ${chalk.yellow('!')} .claude/settings.json contains invalid JSON — resetting to add hook`,\n );\n settings = {};\n }\n }\n\n const hooks = (settings.hooks ?? {}) as Record<string, unknown[]>;\n\n // Check if viberails hook already exists\n const existing = hooks.PostToolUse ?? [];\n if (existing.some((h) => JSON.stringify(h).includes('viberails'))) return;\n\n // The hook command reads the tool input from stdin, extracts file_path, and checks it.\n // Uses Node.js to parse JSON (no external dependency like jq required).\n // readFileSync(0) reads stdin synchronously via file descriptor 0.\n // `; exit 0` ensures warn-mode (always exit 0) while still showing check output.\n const extractFile =\n \"node -e \\\"try{process.stdout.write(JSON.parse(require('fs').readFileSync(0,'utf8')).tool_input?.file_path??'')}catch{}\\\"\";\n const hookCommand = `FILE=$(${extractFile}) && [ -n \"$FILE\" ] && npx viberails check --files \"$FILE\" --format json; exit 0`;\n\n hooks.PostToolUse = [\n ...existing,\n {\n matcher: 'Edit|Write',\n hooks: [\n {\n type: 'command',\n command: hookCommand,\n },\n ],\n },\n ];\n\n settings.hooks = hooks;\n fs.writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\\n`);\n console.log(` ${chalk.green('✓')} .claude/settings.json — added viberails PostToolUse hook`);\n}\n\nfunction writeHuskyPreCommit(huskyDir: string): void {\n const hookPath = path.join(huskyDir, 'pre-commit');\n if (fs.existsSync(hookPath)) {\n const existing = fs.readFileSync(hookPath, 'utf-8');\n if (!existing.includes('viberails')) {\n fs.writeFileSync(hookPath, `${existing.trimEnd()}\\nnpx viberails check --staged\\n`);\n }\n return;\n }\n fs.writeFileSync(hookPath, '#!/bin/sh\\nnpx viberails check --staged\\n', { mode: 0o755 });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { loadConfig, mergeConfig } from '@viberails/config';\nimport { scan } from '@viberails/scanner';\nimport chalk from 'chalk';\nimport { findProjectRoot } from '../utils/find-project-root.js';\nimport { writeGeneratedFiles } from '../utils/write-generated-files.js';\n\nconst CONFIG_FILE = 'viberails.config.json';\n\n/**\n * Run the viberails sync flow: re-scan, merge config, regenerate context.\n *\n * @param cwd - Working directory override (for testing)\n */\nexport async function syncCommand(cwd?: string): Promise<void> {\n const startDir = cwd ?? process.cwd();\n\n // 1. Find project root\n const projectRoot = findProjectRoot(startDir);\n if (!projectRoot) {\n throw new Error(\n 'No package.json found in this directory or any parent.\\n\\n' +\n 'Make sure you are inside a JavaScript or TypeScript project, then run:\\n' +\n ' npx viberails',\n );\n }\n\n // 2. Load existing config\n const configPath = path.join(projectRoot, CONFIG_FILE);\n const existing = await loadConfig(configPath);\n\n // 3. Re-scan\n console.log(chalk.dim('Scanning project...'));\n const scanResult = await scan(projectRoot);\n\n // 4. Merge config and detect changes\n const merged = mergeConfig(existing, scanResult);\n const existingJson = JSON.stringify(existing, null, 2);\n const mergedJson = JSON.stringify(merged, null, 2);\n const configChanged = existingJson !== mergedJson;\n\n if (configChanged) {\n console.log(\n ` ${chalk.yellow('!')} Config updated — review ${chalk.cyan(CONFIG_FILE)} for changes`,\n );\n }\n\n fs.writeFileSync(configPath, `${mergedJson}\\n`);\n\n // 5. Regenerate context and scan-result.json\n writeGeneratedFiles(projectRoot, merged, scanResult);\n\n console.log(`\\n${chalk.bold('Synced:')}`);\n if (configChanged) {\n console.log(` ${chalk.yellow('!')} ${CONFIG_FILE} — updated (review changes)`);\n } else {\n console.log(` ${chalk.green('✓')} ${CONFIG_FILE} — unchanged`);\n }\n console.log(` ${chalk.green('✓')} .viberails/context.md — regenerated`);\n console.log(` ${chalk.green('✓')} .viberails/scan-result.json — updated`);\n}\n"],"mappings":"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","names":["import_chalk","fs","path","confirm","fs","path","chalk","confirm","fs","path","import_config","import_chalk","fs","path","picomatch","fs","path","SOURCE_EXTS","basename","CONFIG_FILE","chalk","fs","path","import_config","import_chalk","import_node_child_process","import_chalk","chalk","path","fs","path","fs","path","basename","CONFIG_FILE","chalk","fs","path","clack","import_config","import_chalk","import_types","import_chalk","import_types","import_chalk","chalk","chalk","fs","path","fs","path","import_chalk","chalk","CONFIG_FILE","getConventionStr","chalk","scanResult","config","confirm","fs","path","import_config","import_scanner","import_chalk","CONFIG_FILE","chalk","chalk"]}
|