uilint 0.2.147 → 0.2.149

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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/scan.ts","../src/utils/input.ts","../src/utils/path-specifiers.ts","../src/utils/llm-client.ts","../src/utils/timing.ts","../src/utils/output.ts","../src/commands/analyze.ts","../src/commands/consistency.ts","../src/commands/update.ts","../src/commands/serve.ts","../src/commands/serve/dashboard/logger.ts","../src/utils/eslint-utils.ts","../src/scope-extractor.ts","../src/commands/vision.ts","../src/commands/config.ts","../src/commands/duplicates/index.ts","../src/commands/duplicates/index-cmd.ts","../src/commands/duplicates/find.ts","../src/commands/duplicates/search.ts","../src/commands/duplicates/similar.ts","../src/commands/manifest/index.ts","../src/commands/manifest/generator.ts","../src/commands/socket/index.ts","../src/commands/socket/client.ts"],"sourcesContent":["/**\n * UILint CLI - AI-powered UI consistency checking\n */\n\nimport { Command } from \"commander\";\nimport { scan } from \"./commands/scan.js\";\nimport { analyze } from \"./commands/analyze.js\";\nimport { consistency } from \"./commands/consistency.js\";\nimport { update } from \"./commands/update.js\";\nimport { serve } from \"./commands/serve.js\";\nimport { vision } from \"./commands/vision.js\";\nimport { config } from \"./commands/config.js\";\nimport { createDuplicatesCommand } from \"./commands/duplicates/index.js\";\nimport { readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nfunction assertNodeVersion(minMajor: number, minMinor: number): void {\n const ver = process.versions.node || \"\";\n const parts = ver.split(\".\");\n const major = Number.parseInt(parts[0] || \"\", 10);\n const minor = Number.parseInt(parts[1] || \"\", 10);\n\n const meetsRequirement =\n Number.isFinite(major) &&\n Number.isFinite(minor) &&\n (major > minMajor || (major === minMajor && minor >= minMinor));\n\n if (!meetsRequirement) {\n // Keep this dependency-free and stdout/stderr friendly.\n \n console.error(\n `uilint requires Node.js >= ${minMajor}.${minMinor}.0. You are running Node.js ${ver}.`\n );\n process.exit(1);\n }\n}\n\n// Required by dependencies: chokidar, jsdom, readdirp, etc.\nassertNodeVersion(20, 19);\n\nconst program = new Command();\n\nfunction getCLIVersion(): string {\n try {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as {\n version?: string;\n };\n return pkg.version || \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nprogram\n .name(\"uilint\")\n .description(\"AI-powered UI consistency checker\")\n .version(getCLIVersion());\n\n// Analyze command\nprogram\n .command(\"analyze\")\n .description(\n \"Analyze a source file/snippet for style issues (data-loc aware)\"\n )\n .option(\"-f, --input-file <path>\", \"Path to a source file to analyze\")\n .option(\"--source-code <code>\", \"Source code to analyze (string)\")\n .option(\"--file-path <path>\", \"File path label shown in the prompt\")\n .option(\"--style-guide <text>\", \"Inline styleguide content to use\")\n .option(\"--styleguide-path <path>\", \"Path to a style guide file\")\n .option(\"--component-name <name>\", \"Component name for focused analysis\")\n .option(\"--component-line <n>\", \"Component line number (integer)\", (v) =>\n parseInt(v, 10)\n )\n .option(\"--include-children\", \"Scope: selected element + children\")\n .option(\n \"--data-loc <value>\",\n \"data-loc value (repeatable) in format path:line:column\",\n (v, prev: string[] | undefined) => (prev ? [...prev, v] : [v]),\n []\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--stream\", \"Stream progress while analyzing (text mode UI only)\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/source/styleguide (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full LLM payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await analyze({\n inputFile: options.inputFile,\n sourceCode: options.sourceCode,\n filePath: options.filePath,\n styleGuide: options.styleGuide,\n styleguidePath: options.styleguidePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n output: options.output,\n stream: options.stream,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Scan command\nprogram\n .command(\"scan\")\n .description(\"Scan HTML for UI consistency issues\")\n .option(\"-f, --input-file <path>\", \"Path to HTML file to scan\")\n .option(\"-j, --input-json <json>\", \"JSON input with html and styles\")\n .option(\"-s, --styleguide <path>\", \"Path to style guide file\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/style summary/styleguide (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full LLM payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await scan({\n inputFile: options.inputFile,\n inputJson: options.inputJson,\n styleguide: options.styleguide,\n output: options.output,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Consistency command\nprogram\n .command(\"consistency\")\n .description(\"Analyze grouped DOM elements for visual inconsistencies\")\n .option(\"-j, --input-json <json>\", \"JSON input with GroupedSnapshot\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n await consistency({\n inputJson: options.inputJson,\n output: options.output,\n });\n });\n\n// Update command\nprogram\n .command(\"update\")\n .description(\"Update existing style guide with new styles\")\n .option(\"-f, --input-file <path>\", \"Path to HTML file to analyze\")\n .option(\"-j, --input-json <json>\", \"JSON input with html and styles\")\n .option(\"-s, --styleguide <path>\", \"Path to style guide file\")\n .option(\"--llm\", \"Use LLM to suggest updates\")\n .action(async (options) => {\n await update({\n inputFile: options.inputFile,\n inputJson: options.inputJson,\n styleguide: options.styleguide,\n llm: options.llm,\n });\n });\n\n// Init command — plugin flags are added dynamically below in main()\nconst initCommand = program\n .command(\"init\")\n .description(\"Initialize UILint integration\")\n .option(\"--force\", \"Overwrite existing configuration files\")\n .option(\"--react\", \"Install React DevTool (non-interactive)\")\n .option(\"--eslint\", \"Install ESLint rules (non-interactive)\")\n .option(\"--genstyleguide\", \"Generate styleguide (non-interactive)\")\n .option(\"--skill\", \"Install Claude skill (non-interactive)\");\n\n// Remove command\nprogram\n .command(\"remove\")\n .description(\"Remove UILint components from your project\")\n .option(\"--dry-run\", \"Preview changes without removing anything\")\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\n .action(async (options) => {\n const { removeUI } = await import(\"./commands/remove-ui.js\");\n await removeUI({ dryRun: options.dryRun, yes: options.yes });\n });\n\n// Serve command - WebSocket server for UI overlay\nprogram\n .command(\"serve\")\n .description(\"Start WebSocket server for real-time UI linting\")\n .option(\"-p, --port <number>\", \"Port to listen on\", \"9234\")\n .option(\"--no-dashboard\", \"Disable dashboard UI (use simple logging)\")\n .action(async (options) => {\n await serve({\n port: parseInt(options.port, 10),\n noDashboard: !options.dashboard,\n });\n });\n\n// Vision command\nprogram\n .command(\"vision\")\n .description(\"Analyze a screenshot with Ollama vision models (requires a manifest)\")\n .option(\"--list\", \"List available .uilint/screenshots sidecars and exit\")\n .option(\n \"--screenshots-dir <path>\",\n \"Screenshots directory for --list (default: nearest .uilint/screenshots)\"\n )\n .option(\"--image <path>\", \"Path to a screenshot image (png/jpg)\")\n .option(\n \"--sidecar <path>\",\n \"Path to a .uilint/screenshots/*.json sidecar (contains manifest + metadata)\"\n )\n .option(\"--manifest-file <path>\", \"Path to a manifest JSON file (array)\")\n .option(\"--manifest-json <json>\", \"Inline manifest JSON (array)\")\n .option(\"--route <route>\", \"Optional route label (e.g., /todos)\")\n .option(\n \"-s, --styleguide <path>\",\n \"Path to style guide file OR project directory (falls back to upward search)\"\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--model <name>\", \"Ollama vision model override\", undefined)\n .option(\"--base-url <url>\", \"Ollama base URL (default: http://localhost:11434)\")\n .option(\"--stream\", \"Stream model output/progress to stderr (text mode only)\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/styleguide and include base64 in dumps (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full analysis payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await vision({\n list: options.list,\n screenshotsDir: options.screenshotsDir,\n image: options.image,\n sidecar: options.sidecar,\n manifestFile: options.manifestFile,\n manifestJson: options.manifestJson,\n route: options.route,\n styleguide: options.styleguide,\n output: options.output,\n model: options.model,\n baseUrl: options.baseUrl,\n stream: options.stream,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Config command\nprogram\n .command(\"config\")\n .description(\"Get or set UILint configuration options\")\n .argument(\"<action>\", \"Action: set or get\")\n .argument(\"<key>\", \"Config key (e.g., position, rule)\")\n .argument(\"[value]\", \"Value to set (for set action)\")\n .argument(\"[extraArg]\", \"Extra argument (e.g., options JSON for rule config)\")\n .option(\"-p, --port <number>\", \"WebSocket server port\", \"9234\")\n .action(async (action, key, value, extraArg, options) => {\n await config(action, key, value, extraArg, {\n port: parseInt(options.port, 10),\n });\n });\n\n// Duplicates command group - semantic code duplicate detection\nprogram.addCommand(createDuplicatesCommand());\n\n// Build manifest command - generate static lint manifest for production\nimport { createManifestCommand } from \"./commands/manifest/index.js\";\nprogram.addCommand(createManifestCommand());\n\n// Socket command - CLI for interacting with socket server\nimport { createSocketCommand } from \"./commands/socket/index.js\";\nprogram.addCommand(createSocketCommand());\n\n// Upgrade command - update installed rules\nprogram\n .command(\"upgrade\")\n .description(\"Update installed ESLint rules to latest versions\")\n .option(\"--check\", \"Show available updates without applying\")\n .option(\"-y, --yes\", \"Auto-confirm all updates\")\n .option(\"--dry-run\", \"Show what would change without modifying files\")\n .option(\"--rule <id>\", \"Upgrade only a specific rule\")\n .action(async (options) => {\n const { upgrade } = await import(\"./commands/upgrade.js\");\n await upgrade({\n check: options.check,\n yes: options.yes,\n dryRun: options.dryRun,\n rule: options.rule,\n });\n });\n\n// Discover plugin manifests and wire up the init command dynamically\nasync function main() {\n const { discoverPlugins } = await import(\"./utils/plugin-loader.js\");\n const pluginManifests = await discoverPlugins();\n\n // Add a --<flag> option for each discovered plugin\n for (const manifest of pluginManifests) {\n initCommand.option(`--${manifest.cliFlag}`, manifest.cliDescription);\n }\n\n // Wire up the init action handler (after plugin options are registered)\n initCommand.action(async (options) => {\n // Collect plugin flags into a string array\n const plugins = pluginManifests\n .filter((m) => options[m.cliFlag])\n .map((m) => m.cliFlag);\n\n const { initUI } = await import(\"./commands/init-ui.js\");\n await initUI({\n force: options.force,\n react: options.react,\n eslint: options.eslint,\n genstyleguide: options.genstyleguide,\n skill: options.skill,\n plugins: plugins.length > 0 ? plugins : undefined,\n });\n });\n\n await program.parseAsync();\n}\n\nmain();\n","/**\n * Scan command - scans HTML for UI consistency issues\n */\n\nimport { dirname, resolve } from \"path\";\nimport { existsSync, mkdirSync, statSync, writeFileSync } from \"fs\";\nimport {\n createStyleSummary,\n buildAnalysisPrompt,\n buildSourceAnalysisPrompt,\n formatViolationsText,\n sanitizeIssues,\n ensureOllamaReady,\n readStyleGuide,\n findStyleGuidePath,\n findUILintStyleGuideUpwards,\n STYLEGUIDE_PATHS,\n readTailwindThemeTokens,\n} from \"uilint-core/node\";\nimport {\n getScanInput,\n type InputOptions,\n type ScanInput,\n} from \"../utils/input.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n createSpinner,\n note,\n logInfo,\n logWarning,\n logError,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface ScanOptions extends InputOptions {\n styleguide?: string;\n output?: \"text\" | \"json\";\n /**\n * Enable debug logging (stderr only; never pollutes JSON stdout).\n * Can also be enabled via UILINT_DEBUG=1\n */\n debug?: boolean;\n /**\n * Print full prompt/styleSummary/styleGuide to stderr (can be very large).\n * Can also be enabled via UILINT_DEBUG_FULL=1\n */\n debugFull?: boolean;\n /**\n * Dump full LLM payload (prompt + inputs) to a JSON file.\n * Can also be set via UILINT_DEBUG_DUMP=/path/to/file-or-dir\n */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: ScanOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: ScanOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: ScanOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nexport async function scan(options: ScanOptions): Promise<void> {\n // For JSON output, skip the fancy UI\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) {\n intro(\"Scan for UI Issues\");\n }\n\n try {\n // Get input\n let snapshot: ScanInput;\n try {\n const normalizedOptions: ScanOptions = {\n ...options,\n inputFile: options.inputFile\n ? resolvePathSpecifier(options.inputFile, process.cwd())\n : options.inputFile,\n };\n if (isJsonOutput) {\n snapshot = await getScanInput(normalizedOptions);\n } else {\n snapshot = await withSpinner(\"Parsing input\", async () => {\n return await getScanInput(normalizedOptions);\n });\n }\n } catch {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", issues: [] });\n } else {\n logError(\"No input provided. Use --input-file or pipe HTML to stdin.\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n debugLog(dbg, \"Input options\", {\n inputFile: options.inputFile,\n inputJson: options.inputJson ? \"(provided)\" : undefined,\n styleguide: options.styleguide,\n output: options.output,\n });\n\n if (snapshot.kind === \"dom\") {\n const dom = snapshot.snapshot;\n debugLog(dbg, \"Parsed snapshot (high-level)\", {\n elementCount: dom.elementCount,\n timestamp: dom.timestamp,\n htmlLength: dom.html.length,\n styles: {\n colors: dom.styles.colors.size,\n fontSizes: dom.styles.fontSizes.size,\n fontFamilies: dom.styles.fontFamilies.size,\n fontWeights: dom.styles.fontWeights.size,\n spacing: dom.styles.spacing.size,\n borderRadius: dom.styles.borderRadius.size,\n },\n });\n if (dbgFull) {\n debugLog(dbg, \"Snapshot HTML (full)\", dom.html);\n } else if (dbg) {\n debugLog(dbg, \"Snapshot HTML (preview)\", preview(dom.html, 800));\n }\n\n if (!isJsonOutput) {\n logInfo(`Scanning ${pc.cyan(String(dom.elementCount))} elements`);\n }\n } else {\n debugLog(dbg, \"Parsed source input (high-level)\", {\n inputPath: snapshot.inputPath,\n extension: snapshot.extension,\n length: snapshot.source.length,\n lines: snapshot.source.split(\"\\n\").length,\n });\n if (dbgFull) {\n debugLog(dbg, \"Source (full)\", snapshot.source);\n } else if (dbg) {\n debugLog(dbg, \"Source (preview)\", preview(snapshot.source, 1200));\n }\n\n if (!isJsonOutput) {\n logInfo(\n `Scanning ${pc.cyan(snapshot.extension || \"source\")} (${pc.cyan(\n String(snapshot.source.split(\"\\n\").length)\n )} lines)`\n );\n }\n }\n\n // Get style guide\n // --styleguide can be either:\n // 1. Direct path to a styleguide file (e.g., /path/to/.uilint/styleguide.md)\n // 2. Path to a project directory to search in\n // 3. Not provided - search from cwd\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n const projectPath = process.cwd();\n\n if (options.styleguide) {\n const styleguideArg = resolvePathSpecifier(\n options.styleguide,\n projectPath\n );\n if (existsSync(styleguideArg)) {\n const stat = statSync(styleguideArg);\n if (stat.isFile()) {\n // Direct path to styleguide file\n styleguideLocation = styleguideArg;\n styleGuide = await readStyleGuide(styleguideArg);\n } else if (stat.isDirectory()) {\n // Path to project directory - search within it\n styleguideLocation = findStyleGuidePath(styleguideArg);\n if (styleguideLocation) {\n styleGuide = await readStyleGuide(styleguideLocation);\n }\n }\n } else {\n if (!isJsonOutput) {\n logWarning(`Styleguide not found: ${styleguideArg}`);\n }\n }\n } else {\n // No --styleguide provided:\n // Prefer searching upward from the input file directory for `.uilint/styleguide.md`\n // (helps when running from repo root but scanning a nested app/package).\n const startPath =\n snapshot.kind === \"source\"\n ? snapshot.inputPath\n : snapshot.kind === \"dom\"\n ? snapshot.inputPath\n : undefined;\n if (startPath) {\n styleguideLocation = findUILintStyleGuideUpwards(dirname(startPath));\n }\n\n // Fallback: search from cwd\n styleguideLocation =\n styleguideLocation ?? findStyleGuidePath(projectPath);\n if (styleguideLocation) {\n styleGuide = await readStyleGuide(styleguideLocation);\n }\n }\n\n if (styleguideLocation && styleGuide) {\n if (!isJsonOutput) {\n logSuccess(`Using styleguide: ${pc.dim(styleguideLocation)}`);\n }\n } else if (!styleGuide) {\n if (!isJsonOutput) {\n logWarning(\"No styleguide found\");\n note(\n [\n `Searched in: ${options.styleguide || projectPath}`,\n \"\",\n \"Looked for:\",\n ...STYLEGUIDE_PATHS.map((p) => ` • ${p}`),\n \"\",\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n ].join(\"\\n\"),\n \"Missing Styleguide\"\n );\n }\n }\n\n debugLog(dbg, \"Styleguide resolved\", {\n styleguideArg: options.styleguide,\n styleguideLocation: styleguideLocation ?? null,\n styleGuideLength: styleGuide ? styleGuide.length : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Styleguide contents (full)\", styleGuide ?? \"\");\n } else if (dbg && styleGuide) {\n debugLog(dbg, \"Styleguide contents (preview)\", preview(styleGuide, 800));\n }\n\n // Create style summary\n const tailwindSearchDir =\n (snapshot.kind === \"source\" || snapshot.kind === \"dom\") &&\n snapshot.inputPath\n ? dirname(snapshot.inputPath)\n : projectPath;\n const tailwindTheme = readTailwindThemeTokens(tailwindSearchDir);\n const styleSummary =\n snapshot.kind === \"dom\"\n ? createStyleSummary(snapshot.snapshot.styles, {\n html: snapshot.snapshot.html,\n tailwindTheme,\n })\n : null;\n\n debugLog(dbg, \"Tailwind context\", {\n tailwindSearchDir,\n tailwindTheme: tailwindTheme\n ? {\n configPath: tailwindTheme.configPath,\n colors: tailwindTheme.colors.length,\n spacingKeys: tailwindTheme.spacingKeys.length,\n borderRadiusKeys: tailwindTheme.borderRadiusKeys.length,\n fontFamilyKeys: tailwindTheme.fontFamilyKeys.length,\n fontSizeKeys: tailwindTheme.fontSizeKeys.length,\n }\n : null,\n });\n\n debugLog(dbg, \"Style summary (stats)\", {\n length: styleSummary ? styleSummary.length : 0,\n lines: styleSummary ? styleSummary.split(\"\\n\").length : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Style summary (full)\", styleSummary ?? \"\");\n } else if (dbg && styleSummary) {\n debugLog(dbg, \"Style summary (preview)\", preview(styleSummary, 800));\n }\n\n // Prepare Ollama\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n const prepEndNs = nsNow();\n\n // Call Ollama for analysis\n const client = await createLLMClient({});\n let result;\n\n // Build the exact prompt (this is what analyzeStyles() uses internally)\n const prompt =\n snapshot.kind === \"dom\"\n ? buildAnalysisPrompt(styleSummary ?? \"\", styleGuide)\n : buildSourceAnalysisPrompt(snapshot.source, styleGuide, {\n filePath: snapshot.inputPath,\n languageHint: snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n });\n debugLog(dbg, \"LLM request (high-level)\", {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: !isJsonOutput,\n promptLength: prompt.length,\n promptLines: prompt.split(\"\\n\").length,\n });\n\n if (dbgFull) {\n debugLog(dbg, \"LLM prompt (full)\", prompt);\n } else if (dbg) {\n debugLog(dbg, \"LLM prompt (preview)\", preview(prompt, 1200));\n }\n\n if (dbgDump) {\n try {\n const now = new Date();\n const safeStamp = now.toISOString().replace(/[:.]/g, \"-\");\n const resolved = resolve(process.cwd(), dbgDump);\n const dumpFile =\n resolved.endsWith(\".json\") || resolved.endsWith(\".jsonl\")\n ? resolved\n : resolve(resolved, `scan-debug-${safeStamp}.json`);\n\n // If path looks like a directory (or a non-json file), ensure dir exists.\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: now.toISOString(),\n options: {\n inputFile: options.inputFile,\n inputJson: options.inputJson ? \"(provided)\" : undefined,\n styleguide: options.styleguide,\n styleguideLocation,\n output: options.output,\n model: client.getModel(),\n },\n snapshot: {\n kind: snapshot.kind,\n ...(snapshot.kind === \"dom\"\n ? {\n elementCount: snapshot.snapshot.elementCount,\n timestamp: snapshot.snapshot.timestamp,\n html: snapshot.snapshot.html,\n styles: {\n colors: [...snapshot.snapshot.styles.colors.entries()],\n fontSizes: [\n ...snapshot.snapshot.styles.fontSizes.entries(),\n ],\n fontFamilies: [\n ...snapshot.snapshot.styles.fontFamilies.entries(),\n ],\n fontWeights: [\n ...snapshot.snapshot.styles.fontWeights.entries(),\n ],\n spacing: [\n ...snapshot.snapshot.styles.spacing.entries(),\n ],\n borderRadius: [\n ...snapshot.snapshot.styles.borderRadius.entries(),\n ],\n },\n }\n : {\n inputPath: snapshot.inputPath,\n extension: snapshot.extension,\n source: snapshot.source,\n }),\n },\n styleGuide,\n styleSummary,\n prompt,\n tailwindTheme,\n llmRequest: {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: !isJsonOutput,\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n debugLog(dbg, `Wrote debug dump to ${dumpFile}`);\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write debug dump\",\n e instanceof Error ? e.message : e\n );\n }\n }\n\n if (isJsonOutput) {\n result =\n snapshot.kind === \"dom\"\n ? await client.analyzeStyles(styleSummary ?? \"\", styleGuide)\n : await client.analyzeSource(snapshot.source, styleGuide, undefined, {\n filePath: snapshot.inputPath,\n languageHint: snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n });\n } else {\n // Use streaming to show progress\n const s = createSpinner();\n s.start(\"Analyzing with LLM\");\n let thinkingStarted = false;\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n\n const onProgress = (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ): void => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!thinkingStarted) {\n thinkingStarted = true;\n s.stop(pc.dim(\"[scan] streaming thinking:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n // Truncate line if too long for terminal\n const maxLen = 60;\n const displayLine =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(displayLine || \"...\")}`);\n };\n\n try {\n result =\n snapshot.kind === \"dom\"\n ? await client.analyzeStyles(\n styleSummary ?? \"\",\n styleGuide,\n onProgress\n )\n : await client.analyzeSource(\n snapshot.source,\n styleGuide,\n onProgress,\n {\n filePath: snapshot.inputPath,\n languageHint:\n snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n }\n );\n s.stop(pc.green(\"✓ \") + \"Analyzing with LLM\");\n\n if (process.stdout.isTTY) {\n const analysisEndNs = nsNow();\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n result?.analysisTime\n ? pc.dim(`(core analysisTime: ${formatMs(result.analysisTime)})`)\n : pc.dim(\"(core analysisTime: n/a)\"),\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n } catch (error) {\n s.stop(pc.red(\"✗ \") + \"Analyzing with LLM\");\n throw error;\n }\n }\n\n // Sanitize (enforce violations-only output)\n const issues = sanitizeIssues(result.issues);\n\n // Output results\n if (isJsonOutput) {\n printJSON({\n issues,\n analysisTime: result.analysisTime,\n elementCount:\n snapshot.kind === \"dom\" ? snapshot.snapshot.elementCount : 0,\n });\n } else {\n // Minimal output: list violations only, plus footer to consult the style guide.\n process.stdout.write(\n formatViolationsText(issues, { includeFooter: issues.length > 0 }) +\n \"\\n\"\n );\n }\n\n // Exit with error code if issues found\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (options.output === \"json\") {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Scan failed\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * Input handling utilities for CLI\n */\n\nimport { readFile } from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport { extname } from \"path\";\nimport {\n parseCLIInput,\n hasStdin,\n readStdin,\n type DOMSnapshot,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"./path-specifiers.js\";\n\nexport interface InputOptions {\n inputFile?: string;\n inputJson?: string;\n}\n\nexport type ScanInput =\n | {\n kind: \"dom\";\n snapshot: DOMSnapshot;\n source: \"json\" | \"file\" | \"stdin\";\n inputPath?: string;\n }\n | {\n kind: \"source\";\n source: string;\n inputPath: string;\n extension: string;\n };\n\nfunction isHtmlLikeExtension(ext: string): boolean {\n return ext === \".html\" || ext === \".htm\";\n}\n\nfunction isJsonLikeExtension(ext: string): boolean {\n return ext === \".json\";\n}\n\n/**\n * Gets input from various sources: stdin, file, or JSON string\n */\nexport async function getInput(options: InputOptions): Promise<DOMSnapshot> {\n // Priority: explicit JSON > explicit file > stdin\n if (options.inputJson) {\n return parseCLIInput(options.inputJson);\n }\n\n if (options.inputFile) {\n const filePath = resolvePathSpecifier(options.inputFile, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.inputFile}`);\n }\n const content = await readFile(filePath, \"utf-8\");\n return parseCLIInput(content);\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No input provided via stdin\");\n }\n return parseCLIInput(content);\n }\n\n throw new Error(\n \"No input provided. Use --input-file, --input-json, or pipe content to stdin.\"\n );\n}\n\n/**\n * Gets scan input:\n * - If input is a file and it's not HTML/JSON, treat it as raw source (TSX/JSX/etc).\n * - Otherwise, treat it as HTML/DOM input (including JSON-wrapped snapshots).\n */\nexport async function getScanInput(options: InputOptions): Promise<ScanInput> {\n // Priority: explicit JSON > explicit file > stdin\n if (options.inputJson) {\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(options.inputJson),\n source: \"json\",\n };\n }\n\n if (options.inputFile) {\n const filePath = resolvePathSpecifier(options.inputFile, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.inputFile}`);\n }\n const content = await readFile(filePath, \"utf-8\");\n const ext = extname(filePath).toLowerCase();\n\n if (isHtmlLikeExtension(ext) || isJsonLikeExtension(ext)) {\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(content),\n source: \"file\",\n inputPath: filePath,\n };\n }\n\n return {\n kind: \"source\",\n source: content,\n inputPath: filePath,\n extension: ext,\n };\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No input provided via stdin\");\n }\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(content),\n source: \"stdin\",\n };\n }\n\n throw new Error(\n \"No input provided. Use --input-file, --input-json, or pipe content to stdin.\"\n );\n}\n\n/**\n * Gets code input from various sources\n */\nexport async function getCodeInput(options: {\n code?: string;\n file?: string;\n}): Promise<string> {\n if (options.code) {\n return options.code;\n }\n\n if (options.file) {\n const filePath = resolvePathSpecifier(options.file, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.file}`);\n }\n return readFile(filePath, \"utf-8\");\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No code provided via stdin\");\n }\n return content;\n }\n\n throw new Error(\n \"No code provided. Use --code, provide a file, or pipe to stdin.\"\n );\n}\n\n/**\n * Validates that a path exists\n */\nexport function validatePath(path: string, description: string): void {\n if (!existsSync(path)) {\n throw new Error(`${description} not found: ${path}`);\n }\n}\n","/**\n * Path specifier utilities for CLI.\n *\n * We support \"workspace-relative\" specifiers using a leading \"@\", e.g.:\n * - @apps/test-app/app/page.tsx\n * - @apps/test-app/.uilint/styleguide.md\n *\n * This mirrors how some tools (and humans) refer to \"repo-relative\" paths.\n */\n\nimport { isAbsolute, resolve } from \"path\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\n\n/**\n * Resolve a user-provided path specifier into an absolute filesystem path.\n *\n * Rules:\n * - Absolute paths are left absolute (normalized with resolve()).\n * - \"@<path>\" is resolved relative to the workspace root (pnpm-workspace/.git).\n * - Everything else is resolved relative to cwd.\n */\nexport function resolvePathSpecifier(\n spec: string,\n cwd: string = process.cwd()\n): string {\n const raw = (spec ?? \"\").trim();\n if (!raw) return resolve(cwd, spec);\n\n if (raw.startsWith(\"@\")) {\n const workspaceRoot = findWorkspaceRoot(cwd);\n let rest = raw.slice(1);\n if (rest.startsWith(\"/\")) rest = rest.slice(1);\n // Note: resolve(workspaceRoot, rest) is safe even if rest contains \"..\";\n // callers that need a security boundary should validate separately.\n return resolve(workspaceRoot, rest);\n }\n\n if (isAbsolute(raw)) return resolve(raw);\n return resolve(cwd, raw);\n}\n","/**\n * LLM Client Factory with Optional Langfuse Instrumentation\n *\n * This module provides a centralized way to create OllamaClient instances\n * with optional Langfuse tracing enabled. Langfuse is only loaded if:\n * 1. LANGFUSE_ENABLED=1 (or true/yes)\n * 2. LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY are set\n */\n\nimport { config } from \"dotenv\";\nimport { join } from \"path\";\nimport {\n OllamaClient,\n type LLMInstrumentationCallbacks,\n type InstrumentationSpan,\n findWorkspaceRoot,\n} from \"uilint-core/node\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { LangfuseSpanProcessor } from \"@langfuse/otel\";\nimport {\n startActiveObservation,\n startObservation,\n type LangfuseObservation,\n type LangfuseGeneration,\n} from \"@langfuse/tracing\";\n\n// Load .env.local from workspace root\nlet envLoaded = false;\nfunction loadEnvLocal(): void {\n if (envLoaded) return;\n envLoaded = true;\n\n const workspaceRoot = findWorkspaceRoot(process.cwd());\n const envLocalPath = join(workspaceRoot, \".env.local\");\n\n // Load .env.local if it exists (dotenv will silently skip if file doesn't exist)\n config({ path: envLocalPath });\n}\n\n// Load environment variables immediately on module load\nloadEnvLocal();\n\n// Lazy-loaded instrumentation\nlet langfuseInitialized = false;\nlet langfuseInstrumentation: LLMInstrumentationCallbacks | undefined;\nlet sdkInstance: NodeSDK | undefined;\nlet spanProcessor: LangfuseSpanProcessor | undefined;\n\n/**\n * Checks if Langfuse is enabled via environment variable\n */\nfunction isLangfuseEnabled(): boolean {\n const enabled = process.env.LANGFUSE_ENABLED;\n if (!enabled) return false;\n return (\n enabled === \"1\" ||\n enabled.toLowerCase() === \"true\" ||\n enabled.toLowerCase() === \"yes\"\n );\n}\n\n/**\n * Initialize Langfuse if enabled. This is called automatically on first client creation,\n * but can also be called explicitly at app startup.\n */\nexport async function initializeLangfuseIfEnabled(): Promise<void> {\n if (langfuseInitialized) return;\n langfuseInitialized = true;\n\n if (!isLangfuseEnabled()) {\n return;\n }\n\n const publicKey = process.env.LANGFUSE_PUBLIC_KEY;\n const secretKey = process.env.LANGFUSE_SECRET_KEY;\n\n if (!publicKey || !secretKey) {\n console.error(\n \"[uilint] LANGFUSE_ENABLED=1 but missing LANGFUSE_PUBLIC_KEY or LANGFUSE_SECRET_KEY\"\n );\n return;\n }\n\n try {\n const baseUrl = process.env.LANGFUSE_BASE_URL || \"http://localhost:3333\";\n\n // Create the span processor with immediate export mode for CLI usage\n spanProcessor = new LangfuseSpanProcessor({\n publicKey,\n secretKey,\n baseUrl,\n // Use immediate mode to ensure spans are exported right away in CLI context\n exportMode: \"immediate\",\n });\n\n // Initialize OpenTelemetry with LangfuseSpanProcessor\n const sdk = new NodeSDK({\n spanProcessors: [spanProcessor],\n });\n\n sdk.start();\n sdkInstance = sdk;\n\n // Create instrumentation callbacks using @langfuse/tracing\n // Use startActiveObservation at top level to create the trace context\n langfuseInstrumentation = {\n onGenerationStart: ({\n name,\n model,\n prompt,\n metadata,\n }: {\n name: string;\n model: string;\n prompt: string;\n metadata?: Record<string, unknown>;\n }): InstrumentationSpan => {\n // We need to bridge the callback-based startActiveObservation with our\n // synchronous start / async end pattern. Use a promise to control when the trace ends.\n let resolveTrace: () => void;\n let generationRef: LangfuseGeneration | undefined;\n let _traceRef: LangfuseObservation | undefined;\n let endData:\n | {\n output: string;\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n error?: string;\n };\n }\n | undefined;\n\n // Start the active observation (trace) - this runs the callback immediately\n // but doesn't resolve until we call resolveTrace()\n const tracePromise = startActiveObservation(\n `uilint-${name}`,\n async (span) => {\n _traceRef = span;\n span.update({\n input: { operation: name },\n metadata: {\n ...metadata,\n source: \"uilint\",\n },\n });\n\n // Create the generation as a child - startObservation within startActiveObservation\n // automatically nests under the active trace\n generationRef = startObservation(\n name,\n {\n model,\n input: prompt,\n metadata: {\n ...metadata,\n source: \"uilint\",\n },\n },\n { asType: \"generation\" }\n );\n\n // Wait for end() to be called before completing the trace\n await new Promise<void>((resolve) => {\n resolveTrace = resolve;\n });\n\n // Now process the end data\n if (endData && generationRef) {\n const usageDetails: Record<string, number> | undefined =\n endData.usage\n ? Object.fromEntries(\n Object.entries({\n input: endData.usage.promptTokens,\n output: endData.usage.completionTokens,\n total: endData.usage.totalTokens,\n }).filter(([, v]) => v !== undefined) as [\n string,\n number\n ][]\n )\n : undefined;\n\n // End the generation\n generationRef.update({\n output: endData.output,\n usageDetails:\n usageDetails && Object.keys(usageDetails).length > 0\n ? usageDetails\n : undefined,\n metadata: endData.usage?.error\n ? { ...metadata, error: endData.usage.error }\n : metadata,\n });\n generationRef.end();\n\n // Update the trace output\n span.update({\n output: endData.usage?.error\n ? `Error: ${endData.usage.error}`\n : \"completed\",\n });\n }\n // The trace automatically ends when the callback completes\n }\n );\n\n // Handle any errors from the trace promise\n tracePromise.catch((error) => {\n console.error(\"[uilint] Langfuse trace error:\", error);\n });\n\n return {\n end: (\n output: string,\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n error?: string;\n }\n ) => {\n // Store the end data and resolve the trace promise\n endData = { output, usage };\n if (resolveTrace) {\n resolveTrace();\n }\n },\n };\n },\n };\n\n console.error(`[uilint] Langfuse tracing enabled (${baseUrl})`);\n } catch (error) {\n console.error(\n \"[uilint] Failed to initialize Langfuse:\",\n error instanceof Error ? error.message : error\n );\n }\n}\n\n/**\n * Creates an OllamaClient with optional Langfuse instrumentation.\n * Automatically initializes Langfuse on first call if enabled.\n */\nexport async function createLLMClient(options: {\n model?: string;\n baseUrl?: string;\n timeout?: number;\n}): Promise<OllamaClient> {\n // Initialize Langfuse on first client creation\n await initializeLangfuseIfEnabled();\n\n return new OllamaClient({\n ...options,\n instrumentation: langfuseInstrumentation,\n });\n}\n\n/**\n * Flushes Langfuse traces. Call this before process exit to ensure all traces are sent.\n */\nexport async function flushLangfuse(): Promise<void> {\n // Force flush the span processor first to ensure all pending spans are sent\n if (spanProcessor) {\n try {\n await spanProcessor.forceFlush();\n } catch (error) {\n console.error(\n \"[uilint] Failed to flush Langfuse spans:\",\n error instanceof Error ? error.message : error\n );\n }\n }\n\n // Then shutdown the SDK\n if (sdkInstance) {\n try {\n await sdkInstance.shutdown();\n } catch (error) {\n console.error(\n \"[uilint] Failed to shutdown OpenTelemetry SDK:\",\n error instanceof Error ? error.message : error\n );\n }\n }\n}\n\n/**\n * Returns true if Langfuse is currently initialized and active.\n */\nexport function isLangfuseActive(): boolean {\n return spanProcessor !== undefined;\n}\n\n// Register shutdown handler\nlet shutdownRegistered = false;\nfunction registerShutdownHandler(): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n\n const cleanup = async () => {\n await flushLangfuse();\n };\n\n process.on(\"beforeExit\", cleanup);\n process.on(\"SIGINT\", async () => {\n await cleanup();\n process.exit(130);\n });\n process.on(\"SIGTERM\", async () => {\n await cleanup();\n process.exit(143);\n });\n}\n\n// Auto-register on module load\nregisterShutdownHandler();\n","/**\n * High-precision timing helpers for CLI UX\n */\n\nexport function nsNow(): bigint {\n return process.hrtime.bigint();\n}\n\nexport function nsToMs(ns: bigint): number {\n return Number(ns) / 1_000_000;\n}\n\nexport function formatMs(ms: number): string {\n if (!Number.isFinite(ms)) return \"n/a\";\n if (ms < 1000) return `${ms.toFixed(ms < 10 ? 2 : ms < 100 ? 1 : 0)}ms`;\n const s = ms / 1000;\n if (s < 60) return `${s.toFixed(s < 10 ? 2 : 1)}s`;\n const m = Math.floor(s / 60);\n const rem = s - m * 60;\n return `${m}m ${rem.toFixed(rem < 10 ? 1 : 0)}s`;\n}\n\nexport function maybeMs(ms: number | null | undefined): string {\n return ms == null ? \"n/a\" : formatMs(ms);\n}\n","/**\n * Output formatting utilities for CLI\n */\n\nimport chalk from \"chalk\";\nimport {\n formatViolationsText,\n sanitizeIssues,\n type UILintIssue,\n} from \"uilint-core\";\n\n/**\n * Formats UILint issues for console output\n */\nexport function formatIssues(issues: UILintIssue[]): string {\n const sanitized = sanitizeIssues(issues);\n const text = formatViolationsText(sanitized, {\n includeFooter: sanitized.length > 0,\n });\n // Preserve existing callers expecting a string; apply minimal coloring only.\n return sanitized.length === 0 ? chalk.green(text) : text;\n}\n\n/**\n * Prints JSON output\n */\nexport function printJSON(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\n/**\n * Prints an error message\n */\nexport function printError(message: string): void {\n console.error(chalk.red(`Error: ${message}`));\n}\n\n/**\n * Prints a success message\n */\nexport function printSuccess(message: string): void {\n console.log(chalk.green(`✓ ${message}`));\n}\n\n/**\n * Prints a warning message\n */\nexport function printWarning(message: string): void {\n console.log(chalk.yellow(`⚠️ ${message}`));\n}\n\n/**\n * Prints an info message\n */\nexport function printInfo(message: string): void {\n console.log(chalk.blue(`ℹ ${message}`));\n}\n\n/**\n * Prints a debug/path message (dimmed)\n */\nexport function printPath(label: string, path: string): void {\n console.log(chalk.gray(` ${label}: ${chalk.dim(path)}`));\n}\n\n/**\n * Prints a styled box for important messages\n */\nexport function printBox(\n title: string,\n lines: string[],\n style: \"warning\" | \"error\" | \"info\" = \"info\"\n): void {\n const colors = {\n warning: { border: chalk.yellow, title: chalk.yellow.bold, icon: \"⚠\" },\n error: { border: chalk.red, title: chalk.red.bold, icon: \"✖\" },\n info: { border: chalk.blue, title: chalk.blue.bold, icon: \"ℹ\" },\n };\n const { border, title: titleColor, icon } = colors[style];\n\n const maxLen = Math.max(title.length, ...lines.map((l) => l.length)) + 4;\n const horizontal = \"─\".repeat(maxLen);\n\n console.log();\n console.log(border(`╭${horizontal}╮`));\n console.log(border(`│ ${icon} ${titleColor(title.padEnd(maxLen - 3))}│`));\n console.log(border(`├${horizontal}┤`));\n lines.forEach((line) => {\n console.log(border(`│ ${chalk.gray(line.padEnd(maxLen - 1))}│`));\n });\n console.log(border(`╰${horizontal}╯`));\n console.log();\n}\n\n/**\n * Prints styleguide status information\n */\nexport function printStyleguideNotFound(\n searchedPaths: string[],\n projectPath: string\n): void {\n printBox(\n \"No styleguide found\",\n [\n `Searched in: ${projectPath}`,\n \"\",\n \"Looked for:\",\n ...searchedPaths.map((p) => ` • ${p}`),\n \"\",\n \"To create one, run:\",\n ` ${chalk.cyan(\"/genstyleguide\")} ${chalk.gray(\"(Cursor)\")}`,\n ],\n \"warning\"\n );\n}\n\n/**\n * Prints styleguide found confirmation\n */\nexport function printStyleguideFound(path: string): void {\n console.log(chalk.green(`📋 Using styleguide: ${chalk.dim(path)}`));\n}\n","/**\n * Analyze command - analyzes a source file/snippet for style issues (data-loc aware)\n */\n\nimport { dirname, resolve } from \"path\";\nimport { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport {\n buildSourceScanPrompt,\n ensureOllamaReady,\n readStyleGuide,\n findStyleGuidePath,\n findWorkspaceRoot,\n findUILintStyleGuideUpwards,\n} from \"uilint-core/node\";\nimport { getCodeInput } from \"../utils/input.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n createSpinner,\n note,\n logError,\n logWarning,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\ntype UILintScanIssue = {\n line?: number;\n message: string;\n dataLoc?: string;\n};\n\nexport interface AnalyzeOptions {\n // Input\n inputFile?: string;\n sourceCode?: string;\n\n // Styleguide\n styleGuide?: string;\n styleguidePath?: string;\n\n // Prompt context\n filePath?: string;\n componentName?: string;\n componentLine?: number;\n includeChildren?: boolean;\n dataLoc?: string[]; // repeatable\n\n // LLM\n stream?: boolean;\n\n // Output\n output?: \"text\" | \"json\";\n\n /**\n * Enable debug logging (stderr only; never pollutes JSON stdout).\n * Can also be enabled via UILINT_DEBUG=1\n */\n debug?: boolean;\n /**\n * Print full prompt/styleguide to stderr (can be very large).\n * Can also be enabled via UILINT_DEBUG_FULL=1\n */\n debugFull?: boolean;\n /**\n * Dump full LLM payload (prompt + inputs) to a JSON file.\n * Can also be set via UILINT_DEBUG_DUMP=/path/to/file-or-dir\n */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: AnalyzeOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: AnalyzeOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: AnalyzeOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nasync function resolveStyleGuideForAnalyze(options: {\n styleGuide?: string;\n styleguidePath?: string;\n inputFile?: string;\n}): Promise<{ content: string | null; path: string | null }> {\n // 1) Inline (highest priority)\n if (options.styleGuide && typeof options.styleGuide === \"string\") {\n return { content: options.styleGuide, path: null };\n }\n\n // 2) Explicit path\n if (options.styleguidePath && typeof options.styleguidePath === \"string\") {\n const p = resolvePathSpecifier(options.styleguidePath, process.cwd());\n if (existsSync(p)) {\n return { content: await readStyleGuide(p), path: p };\n }\n return { content: null, path: null };\n }\n\n // 3) Env var pin\n const env = process.env.UILINT_STYLEGUIDE_PATH;\n if (env && env.trim()) {\n const p = resolvePathSpecifier(env.trim(), process.cwd());\n if (existsSync(p)) {\n return { content: await readStyleGuide(p), path: p };\n }\n }\n\n // 4) Smarter default: walk upward from the input file dir looking for `.uilint/styleguide.md`\n if (options.inputFile) {\n const absInput = resolvePathSpecifier(options.inputFile, process.cwd());\n const found = findUILintStyleGuideUpwards(dirname(absInput));\n if (found) return { content: await readStyleGuide(found), path: found };\n }\n\n // 5) Fallbacks: cwd, then workspace root (monorepo)\n const cwdPath = findStyleGuidePath(process.cwd());\n if (cwdPath) return { content: await readStyleGuide(cwdPath), path: cwdPath };\n\n const wsRoot = findWorkspaceRoot(process.cwd());\n const wsPath = findStyleGuidePath(wsRoot);\n if (wsPath) return { content: await readStyleGuide(wsPath), path: wsPath };\n\n return { content: null, path: null };\n}\n\nfunction formatScanIssuesText(issues: UILintScanIssue[]): string {\n if (issues.length === 0) return pc.green(\"No issues found.\");\n const lines = issues.map((i) => {\n const line = typeof i.line === \"number\" ? `Line ${i.line}: ` : \"\";\n const loc = i.dataLoc ? ` ${pc.dim(`(${i.dataLoc})`)}` : \"\";\n return `- ${line}${i.message}${loc}`;\n });\n return lines.join(\"\\n\");\n}\n\nexport async function analyze(options: AnalyzeOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) {\n intro(\"Analyze Source Code\");\n }\n\n try {\n debugLog(dbg, \"Input options\", {\n inputFile: options.inputFile,\n sourceCode: options.sourceCode ? \"(provided)\" : undefined,\n styleGuide: options.styleGuide ? \"(inline)\" : undefined,\n styleguidePath: options.styleguidePath,\n filePath: options.filePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n stream: options.stream,\n output: options.output,\n });\n\n // Input\n const sourceCode = await getCodeInput({\n code: options.sourceCode,\n file: options.inputFile\n ? resolvePathSpecifier(options.inputFile)\n : undefined,\n });\n\n debugLog(dbg, \"Source code (high-level)\", {\n length: sourceCode.length,\n lines: sourceCode.split(\"\\n\").length,\n });\n if (dbgFull) {\n debugLog(dbg, \"Source code (full)\", sourceCode);\n } else if (dbg) {\n debugLog(dbg, \"Source code (preview)\", preview(sourceCode, 800));\n }\n\n const resolvedStyle = await resolveStyleGuideForAnalyze({\n styleGuide: options.styleGuide,\n styleguidePath: options.styleguidePath,\n inputFile: options.inputFile,\n });\n\n debugLog(dbg, \"Styleguide resolved\", {\n styleGuideArg:\n options.styleguidePath ?? options.styleGuide ? \"(inline)\" : null,\n styleguideLocation: resolvedStyle.path,\n styleGuideLength: resolvedStyle.content\n ? resolvedStyle.content.length\n : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Styleguide contents (full)\", resolvedStyle.content ?? \"\");\n } else if (dbg && resolvedStyle.content) {\n debugLog(\n dbg,\n \"Styleguide contents (preview)\",\n preview(resolvedStyle.content, 800)\n );\n }\n\n if (!resolvedStyle.content && !isJsonOutput) {\n logWarning(\"No styleguide found (analyzing without it)\");\n } else if (resolvedStyle.path && !isJsonOutput) {\n logSuccess(`Using styleguide: ${pc.dim(resolvedStyle.path)}`);\n }\n\n // Prepare Ollama\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n const prepEndNs = nsNow();\n\n const client = await createLLMClient({});\n\n const promptContext = {\n filePath:\n options.filePath ||\n (options.inputFile ? options.inputFile : undefined) ||\n \"component.tsx\",\n componentName: options.componentName,\n componentLine:\n typeof options.componentLine === \"number\"\n ? options.componentLine\n : undefined,\n includeChildren: options.includeChildren === true,\n dataLocs: Array.isArray(options.dataLoc) ? options.dataLoc : undefined,\n };\n\n const prompt = buildSourceScanPrompt(\n sourceCode,\n resolvedStyle.content,\n promptContext\n );\n\n debugLog(dbg, \"LLM request (high-level)\", {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: options.stream ?? false,\n promptLength: prompt.length,\n promptLines: prompt.split(\"\\n\").length,\n });\n\n if (dbgFull) {\n debugLog(dbg, \"LLM prompt (full)\", prompt);\n } else if (dbg) {\n debugLog(dbg, \"LLM prompt (preview)\", preview(prompt, 1200));\n }\n\n // Debug dump\n if (dbgDump) {\n try {\n const now = new Date();\n const safeStamp = now.toISOString().replace(/[:.]/g, \"-\");\n const resolved = resolve(process.cwd(), dbgDump);\n const dumpFile =\n resolved.endsWith(\".json\") || resolved.endsWith(\".jsonl\")\n ? resolved\n : resolve(resolved, `analyze-debug-${safeStamp}.json`);\n\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: now.toISOString(),\n command: \"analyze\",\n options: {\n inputFile: options.inputFile,\n sourceCode: options.sourceCode ? \"(provided)\" : undefined,\n styleGuide: options.styleGuide ? \"(inline)\" : undefined,\n styleguidePath: options.styleguidePath,\n styleguideLocation: resolvedStyle.path,\n filePath: options.filePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n model: client.getModel(),\n stream: options.stream,\n output: options.output,\n },\n input: {\n sourceCode,\n sourceLines: sourceCode.split(\"\\n\").length,\n },\n styleGuide: resolvedStyle.content,\n promptContext,\n prompt,\n llmRequest: {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: options.stream ?? false,\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n debugLog(dbg, `Wrote debug dump to ${dumpFile}`);\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write debug dump\",\n e instanceof Error ? e.message : e\n );\n }\n }\n\n let responseText = \"\";\n if (options.stream) {\n if (!isJsonOutput) {\n const s = createSpinner();\n s.start(\"Analyzing with LLM\");\n let thinkingStarted = false;\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n try {\n responseText = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!thinkingStarted) {\n thinkingStarted = true;\n s.stop(pc.dim(\"[analyze] streaming thinking:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n const maxLen = 60;\n const line =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(line || \"...\")}`);\n },\n });\n s.stop(pc.green(\"✓ \") + \"Analyzing with LLM\");\n\n if (process.stdout.isTTY) {\n const analysisEndNs = nsNow();\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n } catch (e) {\n s.stop(pc.red(\"✗ \") + \"Analyzing with LLM\");\n throw e;\n }\n } else {\n responseText = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: () => {\n // JSON mode: never write progress to stdout\n },\n });\n }\n } else {\n responseText = await client.complete(prompt, { json: true });\n }\n\n const parsed = JSON.parse(responseText) as { issues?: UILintScanIssue[] };\n const issues = Array.isArray(parsed.issues) ? parsed.issues : [];\n\n if (isJsonOutput) {\n printJSON({ issues });\n } else {\n process.stdout.write(formatScanIssuesText(issues) + \"\\n\");\n }\n\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (isJsonOutput) {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Analyze failed\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * Consistency command - analyzes grouped DOM elements for visual inconsistencies\n */\n\nimport { createInterface } from \"readline\";\nimport {\n parseGroupedSnapshot,\n analyzeConsistency,\n formatConsistencyViolations,\n countElements,\n hasAnalyzableGroups,\n type ConsistencyResult,\n} from \"uilint-core\";\nimport { ensureOllamaReady } from \"uilint-core/node\";\nimport {\n intro,\n withSpinner,\n logInfo,\n logError,\n logSuccess,\n logWarning,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface ConsistencyOptions {\n inputJson?: string;\n output?: \"text\" | \"json\";\n}\n\n/**\n * Reads JSON input from stdin\n */\nasync function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = \"\";\n const rl = createInterface({ input: process.stdin });\n rl.on(\"line\", (line) => {\n data += line;\n });\n rl.on(\"close\", () => {\n resolve(data);\n });\n });\n}\n\n/**\n * Main consistency analysis command\n */\nexport async function consistency(options: ConsistencyOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n\n if (!isJsonOutput) {\n intro(\"UI Consistency Analysis\");\n }\n\n try {\n // Get input\n let inputJson = options.inputJson;\n if (!inputJson) {\n // Check if stdin has data\n if (!process.stdin.isTTY) {\n inputJson = await readStdin();\n }\n }\n\n if (!inputJson) {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", violations: [] });\n } else {\n logError(\"No input provided. Use --input-json or pipe JSON to stdin.\");\n }\n process.exit(1);\n }\n\n // Parse snapshot\n const snapshot = parseGroupedSnapshot(inputJson);\n if (!snapshot) {\n if (isJsonOutput) {\n printJSON({ error: \"Invalid JSON input\", violations: [] });\n } else {\n logError(\"Failed to parse input as GroupedSnapshot.\");\n }\n process.exit(1);\n }\n\n const elementCount = countElements(snapshot);\n\n if (!isJsonOutput) {\n logInfo(`Analyzing ${pc.cyan(String(elementCount))} elements`);\n }\n\n // Check if there are analyzable groups\n if (!hasAnalyzableGroups(snapshot)) {\n const result: ConsistencyResult = {\n violations: [],\n elementCount,\n analysisTime: 0,\n };\n\n if (isJsonOutput) {\n printJSON(result);\n } else {\n logWarning(\"No groups with 2+ elements to analyze.\");\n }\n return;\n }\n\n // Prepare Ollama\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n\n // Analyze with core function\n let result: ConsistencyResult;\n if (isJsonOutput) {\n result = await analyzeConsistency(snapshot, {});\n } else {\n result = await withSpinner(\"Analyzing with LLM\", async () => {\n return await analyzeConsistency(snapshot, {});\n });\n }\n\n // Output results\n if (isJsonOutput) {\n printJSON(result);\n } else {\n console.log();\n console.log(formatConsistencyViolations(result.violations));\n\n if (result.violations.length > 0) {\n logInfo(\n `Analysis completed in ${pc.dim(String(result.analysisTime) + \"ms\")}`\n );\n } else {\n logSuccess(\n `Analysis completed in ${pc.dim(String(result.analysisTime) + \"ms\")}`\n );\n }\n }\n\n // Exit with error code if violations found\n if (result.violations.length > 0) {\n process.exit(1);\n }\n } catch (error) {\n if (isJsonOutput) {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n violations: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Analysis failed\");\n }\n process.exit(1);\n }\n}\n","/**\n * Update command - updates existing style guide with new styles\n */\n\nimport { dirname, resolve } from \"path\";\nimport {\n createStyleSummary,\n parseStyleGuide,\n mergeStyleGuides,\n styleGuideToMarkdown,\n} from \"uilint-core\";\nimport {\n readStyleGuide,\n writeStyleGuide,\n findStyleGuidePath,\n ensureOllamaReady,\n readTailwindThemeTokens,\n} from \"uilint-core/node\";\nimport { getInput, type InputOptions } from \"../utils/input.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport {\n intro,\n outro,\n withSpinner,\n note,\n logSuccess,\n logInfo,\n logError,\n pc,\n} from \"../utils/prompts.js\";\n\nexport interface UpdateOptions extends InputOptions {\n styleguide?: string;\n llm?: boolean;\n}\n\nexport async function update(options: UpdateOptions): Promise<void> {\n intro(\"Update Style Guide\");\n\n try {\n const projectPath = process.cwd();\n const styleGuidePath =\n options.styleguide || findStyleGuidePath(projectPath);\n\n if (!styleGuidePath) {\n logError(\"No style guide found\");\n note(\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} first (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n \"Tip\"\n );\n await flushLangfuse();\n process.exit(1);\n }\n\n logInfo(`Using styleguide: ${pc.dim(styleGuidePath)}`);\n\n // Read existing style guide\n const existingContent = await readStyleGuide(styleGuidePath);\n const existingGuide = parseStyleGuide(existingContent);\n\n // Get input\n let snapshot;\n try {\n snapshot = await withSpinner(\"Analyzing project\", async () => {\n return await getInput(options);\n });\n } catch {\n logError(\"No input provided. Use --input-file or pipe HTML to stdin.\");\n await flushLangfuse();\n process.exit(1);\n }\n\n logInfo(`Found ${pc.cyan(String(snapshot.elementCount))} elements`);\n\n const tailwindSearchDir = options.inputFile\n ? dirname(resolve(projectPath, options.inputFile))\n : projectPath;\n const tailwindTheme = readTailwindThemeTokens(tailwindSearchDir);\n\n if (options.llm) {\n // Use LLM to suggest updates\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n\n const result = await withSpinner(\n \"Analyzing styles with LLM\",\n async () => {\n const client = await createLLMClient({});\n const styleSummary = createStyleSummary(snapshot.styles, {\n html: snapshot.html,\n tailwindTheme,\n });\n return await client.analyzeStyles(styleSummary, existingContent);\n }\n );\n\n if (result.issues.length > 0) {\n const suggestions = result.issues.map((issue) => {\n let line = `• ${issue.message}`;\n if (issue.suggestion) {\n line += `\\n ${pc.cyan(\"→\")} ${issue.suggestion}`;\n }\n return line;\n });\n\n note(\n suggestions.join(\"\\n\\n\"),\n `Found ${result.issues.length} suggestion(s)`\n );\n logInfo(\"Edit the styleguide manually to apply these changes.\");\n outro(\"Analysis complete\");\n } else {\n logSuccess(\"Style guide is up to date!\");\n outro(\"No changes needed\");\n }\n } else {\n // Parse new styles and merge\n const updatedContent = await withSpinner(\"Merging styles\", async () => {\n // Create a new guide from detected styles\n const mergedColors = new Map(snapshot.styles.colors);\n for (const m of (snapshot.html || \"\").matchAll(/#[A-Fa-f0-9]{6}\\b/g)) {\n const hex = (m[0] || \"\").toUpperCase();\n if (!hex) continue;\n mergedColors.set(hex, (mergedColors.get(hex) || 0) + 1);\n }\n\n const detectedColors = [...mergedColors.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5)\n .map(([value], index) => ({\n name: `Color ${index + 1}`,\n value: value.toUpperCase(),\n usage: \"\",\n }));\n\n const detectedGuide = {\n colors: detectedColors,\n typography: [],\n spacing: [],\n components: [],\n };\n\n // Merge with existing\n const mergedGuide = mergeStyleGuides(existingGuide, detectedGuide);\n return styleGuideToMarkdown(mergedGuide);\n });\n\n // Check if there are any changes\n if (updatedContent === existingContent) {\n logSuccess(\"Style guide is already up to date!\");\n outro(\"No changes needed\");\n return;\n }\n\n // Write updated style guide\n await withSpinner(\"Writing styleguide\", async () => {\n await writeStyleGuide(styleGuidePath, updatedContent);\n });\n\n note(`Updated: ${pc.dim(styleGuidePath)}`, \"Success\");\n outro(\"Style guide updated!\");\n }\n } catch (error) {\n logError(error instanceof Error ? error.message : \"Update failed\");\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * UILint WebSocket Server\n *\n * Provides real-time lint results for the UI overlay.\n *\n * Protocol:\n * - Client -> Server: { type: 'lint:file', filePath: string, requestId?: string }\n * - Client -> Server: { type: 'lint:element', filePath: string, dataLoc: string, requestId?: string }\n * - Client -> Server: { type: 'subscribe:file', filePath: string }\n * - Client -> Server: { type: 'cache:invalidate', filePath?: string }\n * - Client -> Server: { type: 'config:set', key: string, value: any }\n * - Client -> Server: { type: 'rule:config:set', ruleId: string, severity: 'error'|'warn'|'off', options?: object, requestId?: string }\n * - Server -> Client: { type: 'lint:result', filePath: string, issues: Issue[], requestId?: string }\n * - Server -> Client: { type: 'lint:progress', filePath: string, phase: string, requestId?: string }\n * - Server -> Client: { type: 'file:changed', filePath: string }\n * - Server -> Client: { type: 'config:update', key: string, value: any }\n * - Server -> Client: { type: 'rule:config:result', ruleId: string, severity: string, options?: object, success: boolean, error?: string, requestId?: string }\n * - Server -> Client: { type: 'rule:config:changed', ruleId: string, severity: string, options?: object }\n * - Server -> Client: { type: 'duplicates:indexing:start' }\n * - Server -> Client: { type: 'duplicates:indexing:progress', message: string, current?: number, total?: number }\n * - Server -> Client: { type: 'duplicates:indexing:complete', added: number, modified: number, deleted: number, totalChunks: number, duration: number }\n * - Server -> Client: { type: 'duplicates:indexing:error', error: string }\n * - Server -> Client: { type: 'coverage:setup:start' }\n * - Server -> Client: { type: 'coverage:setup:progress', message: string, phase: string }\n * - Server -> Client: { type: 'coverage:setup:complete', packageAdded: boolean, configModified: boolean, testsRan: boolean, coverageGenerated: boolean, duration: number, error?: string }\n * - Server -> Client: { type: 'coverage:setup:error', error: string }\n * - Client -> Server: { type: 'coverage:request', requestId?: string }\n * - Server -> Client: { type: 'coverage:result', coverage: object, timestamp: number, requestId?: string }\n * - Server -> Client: { type: 'coverage:error', error: string, requestId?: string }\n * - Client -> Server: { type: 'source:fetch', filePath: string, requestId?: string }\n * - Server -> Client: { type: 'source:result', filePath: string, content: string, totalLines: number, relativePath: string, requestId?: string }\n * - Server -> Client: { type: 'source:error', filePath: string, error: string, requestId?: string }\n * - Client -> Server: { type: 'screenshot:save', dataUrl: string, route: string, timestamp: number, requestId?: string }\n * - Server -> Client: { type: 'screenshot:saved', filename: string, path: string, requestId?: string }\n * - Server -> Client: { type: 'screenshot:error', error: string, requestId?: string }\n */\n\nimport {\n existsSync,\n statSync,\n readdirSync,\n readFileSync,\n mkdirSync,\n writeFileSync,\n unlinkSync,\n} from \"fs\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"http\";\nimport { createRequire } from \"module\";\nimport { dirname, resolve, relative, join, parse } from \"path\";\nimport { URL } from \"url\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { watch, type FSWatcher } from \"chokidar\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\n\n// Vision analysis is dynamically imported from uilint-vision/node when needed.\n// This removes the hard dependency on the vision plugin package.\nimport {\n detectNextAppRouter,\n findNextAppRouterProjects,\n} from \"../utils/next-detect.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport {\n logWarning,\n pc,\n} from \"../utils/prompts.js\";\nimport {\n enableDashboard,\n disableDashboard,\n isDashboardEnabled,\n logLint,\n logLintDone,\n logSubscribe,\n logCacheInvalidate,\n logVisionAnalyze,\n logVisionDone,\n logVisionCheck,\n logSemanticAnalyze,\n logSemanticDone,\n logSemanticSkipped,\n logConfigSet,\n logRuleConfigSet,\n logScreenshotSave,\n logScreenshotSaved,\n logCoverageResult,\n logClientConnect,\n logClientDisconnect,\n logServerError,\n logServerWarning,\n logServerInfo,\n logRuleInternalError,\n setWorkspaceInfo,\n setServerRunning,\n updateSubscriptionCount,\n updateCacheCount,\n startBackgroundTask,\n updateBackgroundTaskProgress,\n completeBackgroundTask,\n registerPlugin,\n setPluginStatus,\n updatePluginProgress,\n setPluginModel,\n} from \"./serve/dashboard/logger.js\";\nimport type { PluginId } from \"./serve/dashboard/types.js\";\nimport { ruleRegistry, type RuleOptionSchema } from \"uilint-eslint\";\nimport {\n findEslintConfigFile,\n updateRuleSeverityInConfig,\n updateRuleConfigInConfig,\n readRuleConfigsFromConfig,\n} from \"../utils/eslint-config-inject.js\";\nimport { detectCoverageSetup } from \"../utils/coverage-detect.js\";\nimport {\n prepareCoverage,\n needsCoveragePreparation,\n} from \"../utils/coverage-prepare.js\";\nimport { enrichIssuesWithScopeInfo } from \"../utils/eslint-utils.js\";\nimport { discoverPlugins, loadPluginESLintRules } from \"../utils/plugin-loader.js\";\n\n// ---------------------------------------------------------------------------\n// Sentinel issue detection (generic, driven by rule metadata)\n// ---------------------------------------------------------------------------\n// Rules with fallible backends (LLM, external services) can declare\n// `sentinelMessageIds` in their metadata. Issues reported with those\n// messageIds are internal error signals, not user-facing lint issues.\n// The serve command logs them to the dashboard and filters them out.\n//\n// Built lazily so that dynamically registered plugin rules are included.\n// ---------------------------------------------------------------------------\n\n/** Lazily built set of \"ruleId:messageId\" keys for fast sentinel lookup */\nlet _sentinelKeys: Set<string> | null = null;\n\nfunction getSentinelKeys(): Set<string> {\n if (!_sentinelKeys) {\n _sentinelKeys = new Set<string>();\n for (const rule of ruleRegistry) {\n if (rule.sentinelMessageIds) {\n for (const mid of rule.sentinelMessageIds) {\n _sentinelKeys.add(`uilint/${rule.id}:${mid}`);\n }\n }\n }\n }\n return _sentinelKeys;\n}\n\n/**\n * Check if a lint issue is a sentinel (internal error) that should be\n * filtered from client results and logged to the dashboard instead.\n */\nfunction isSentinelIssue(issue: LintIssue): boolean {\n if (!issue.ruleId || !issue.messageId) return false;\n return getSentinelKeys().has(`${issue.ruleId}:${issue.messageId}`);\n}\n\nexport interface ServeOptions {\n port?: number;\n /** Disable dashboard UI (use simple logging) */\n noDashboard?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Port discovery constants\n// ---------------------------------------------------------------------------\nexport const DEFAULT_PORT = 9234;\nexport const PORT_RANGE_SIZE = 10;\n\n/**\n * Try to listen on a port. Resolves true if available, false if in use.\n */\nfunction isPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const srv = createServer();\n srv.once(\"error\", () => {\n resolve(false);\n });\n srv.once(\"listening\", () => {\n srv.close(() => resolve(true));\n });\n srv.listen(port, \"127.0.0.1\");\n });\n}\n\n/**\n * Find an available port starting from `preferred`, scanning up to\n * PORT_RANGE_SIZE ports.\n */\nasync function findAvailablePort(preferred: number): Promise<number> {\n for (let offset = 0; offset < PORT_RANGE_SIZE; offset++) {\n const port = preferred + offset;\n if (await isPortAvailable(port)) return port;\n }\n throw new Error(\n `No available ports in range ${preferred}–${preferred + PORT_RANGE_SIZE - 1}`\n );\n}\n\nexport interface LintIssue {\n line: number;\n column?: number;\n message: string;\n ruleId?: string;\n /** ESLint messageId (e.g. \"semanticIssue\", \"analysisError\") — used for sentinel detection */\n messageId?: string;\n dataLoc?: string;\n scopeInfo?: {\n enclosingScope: string | null;\n scopeType:\n | \"function\"\n | \"arrow-function\"\n | \"component\"\n | \"hook\"\n | \"method\"\n | \"class\"\n | \"module\";\n parentScope?: string;\n jsxElementType?: string;\n };\n}\n\n// Message types\ninterface LintFileMessage {\n type: \"lint:file\";\n filePath: string;\n requestId?: string;\n}\n\ninterface LintElementMessage {\n type: \"lint:element\";\n filePath: string;\n dataLoc: string;\n requestId?: string;\n}\n\ninterface SubscribeFileMessage {\n type: \"subscribe:file\";\n filePath: string;\n}\n\ninterface CacheInvalidateMessage {\n type: \"cache:invalidate\";\n filePath?: string;\n}\n\ninterface VisionAnalyzeMessage {\n type: \"vision:analyze\";\n route: string;\n timestamp: number;\n screenshot?: string;\n /** Screenshot filename persisted under `.uilint/screenshots/` (e.g. uilint-...png) */\n screenshotFile?: string;\n manifest: Record<string, unknown>[];\n requestId?: string;\n}\n\ninterface VisionCheckMessage {\n type: \"vision:check\";\n requestId?: string;\n}\n\ninterface ConfigSetMessage {\n type: \"config:set\";\n key: string;\n value: unknown;\n}\n\ninterface RuleConfigSetMessage {\n type: \"rule:config:set\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n requestId?: string;\n}\n\ninterface SourceFetchMessage {\n type: \"source:fetch\";\n filePath: string;\n requestId?: string;\n}\n\ninterface ScreenshotSaveMessage {\n type: \"screenshot:save\";\n dataUrl: string;\n route: string;\n timestamp: number;\n requestId?: string;\n}\n\ntype ClientMessage =\n | LintFileMessage\n | LintElementMessage\n | SubscribeFileMessage\n | CacheInvalidateMessage\n | VisionAnalyzeMessage\n | VisionCheckMessage\n | ConfigSetMessage\n | RuleConfigSetMessage\n | CoverageRequestMessage\n | SourceFetchMessage\n | ScreenshotSaveMessage;\n\ninterface LintResultMessage {\n type: \"lint:result\";\n filePath: string;\n issues: LintIssue[];\n requestId?: string;\n}\n\ninterface LintProgressMessage {\n type: \"lint:progress\";\n filePath: string;\n phase: string;\n requestId?: string;\n}\n\ninterface FileChangedMessage {\n type: \"file:changed\";\n filePath: string;\n}\n\ninterface WorkspaceInfoMessage {\n type: \"workspace:info\";\n /**\n * Absolute path to the Next.js app project root (dir containing app/ or src/app/).\n * This is the base dir we should use to resolve `data-loc` relative file paths.\n */\n appRoot: string;\n workspaceRoot: string;\n serverCwd: string;\n}\n\ninterface WorkspaceCapabilitiesMessage {\n type: \"workspace:capabilities\";\n postToolUseHook: {\n enabled: boolean;\n provider: \"claude\" | \"cursor\" | null;\n };\n}\n\ninterface VisionResultMessage {\n type: \"vision:result\";\n route: string;\n issues: Record<string, unknown>[];\n analysisTime: number;\n error?: string;\n requestId?: string;\n}\n\ninterface VisionProgressMessage {\n type: \"vision:progress\";\n route: string;\n phase: string;\n requestId?: string;\n}\n\ninterface VisionStatusMessage {\n type: \"vision:status\";\n available: boolean;\n model?: string;\n requestId?: string;\n}\n\ninterface RulesMetadataMessage {\n type: \"rules:metadata\";\n rules: Array<{\n id: string;\n name: string;\n description: string;\n category: string;\n defaultSeverity: \"error\" | \"warn\" | \"off\";\n /** Current severity from ESLint config (may differ from default) */\n currentSeverity?: \"error\" | \"warn\" | \"off\";\n /** Current options from ESLint config */\n currentOptions?: Record<string, unknown>;\n docs?: string;\n optionSchema?: RuleOptionSchema;\n defaultOptions?: unknown[];\n }>;\n}\n\ninterface ConfigUpdateMessage {\n type: \"config:update\";\n key: string;\n value: unknown;\n}\n\ninterface RuleConfigResultMessage {\n type: \"rule:config:result\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n success: boolean;\n error?: string;\n requestId?: string;\n}\n\ninterface RuleConfigChangedMessage {\n type: \"rule:config:changed\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n}\n\n// Duplicates indexing messages\ninterface DuplicatesIndexingStartMessage {\n type: \"duplicates:indexing:start\";\n}\n\ninterface DuplicatesIndexingProgressMessage {\n type: \"duplicates:indexing:progress\";\n message: string;\n current?: number;\n total?: number;\n}\n\ninterface DuplicatesIndexingCompleteMessage {\n type: \"duplicates:indexing:complete\";\n added: number;\n modified: number;\n deleted: number;\n totalChunks: number;\n duration: number;\n}\n\ninterface DuplicatesIndexingErrorMessage {\n type: \"duplicates:indexing:error\";\n error: string;\n}\n\n// Coverage heatmap messages\ninterface CoverageRequestMessage {\n type: \"coverage:request\";\n requestId?: string;\n}\n\ninterface CoverageResultMessage {\n type: \"coverage:result\";\n coverage: Record<string, unknown>;\n timestamp: number;\n requestId?: string;\n}\n\ninterface CoverageErrorMessage {\n type: \"coverage:error\";\n error: string;\n requestId?: string;\n}\n\n// Coverage setup messages (existing)\ninterface CoverageSetupStartMessage {\n type: \"coverage:setup:start\";\n}\n\ninterface CoverageSetupProgressMessage {\n type: \"coverage:setup:progress\";\n message: string;\n phase: string;\n}\n\ninterface CoverageSetupCompleteMessage {\n type: \"coverage:setup:complete\";\n packageAdded: boolean;\n configModified: boolean;\n testsRan: boolean;\n coverageGenerated: boolean;\n duration: number;\n error?: string;\n}\n\ninterface CoverageSetupErrorMessage {\n type: \"coverage:setup:error\";\n error: string;\n}\n\ninterface SourceResultMessage {\n type: \"source:result\";\n filePath: string;\n content: string;\n totalLines: number;\n relativePath: string;\n requestId?: string;\n}\n\ninterface SourceErrorMessage {\n type: \"source:error\";\n filePath: string;\n error: string;\n requestId?: string;\n}\n\ninterface ScreenshotSavedMessage {\n type: \"screenshot:saved\";\n filename: string;\n path: string;\n requestId?: string;\n}\n\ninterface ScreenshotErrorMessage {\n type: \"screenshot:error\";\n error: string;\n requestId?: string;\n}\n\n// Generic plugin operation progress messages\ninterface PluginOperationStartMessage {\n type: \"plugin:operation:start\";\n pluginId: string;\n operationName: string;\n message?: string;\n}\n\ninterface PluginOperationProgressMessage {\n type: \"plugin:operation:progress\";\n pluginId: string;\n operationName: string;\n current?: number;\n total?: number;\n message?: string;\n}\n\ninterface PluginOperationCompleteMessage {\n type: \"plugin:operation:complete\";\n pluginId: string;\n operationName: string;\n message?: string;\n}\n\ninterface PluginOperationErrorMessage {\n type: \"plugin:operation:error\";\n pluginId: string;\n operationName: string;\n error: string;\n}\n\ntype ServerMessage =\n | LintResultMessage\n | LintProgressMessage\n | FileChangedMessage\n | WorkspaceInfoMessage\n | WorkspaceCapabilitiesMessage\n | VisionResultMessage\n | VisionProgressMessage\n | VisionStatusMessage\n | RulesMetadataMessage\n | ConfigUpdateMessage\n | RuleConfigResultMessage\n | RuleConfigChangedMessage\n | DuplicatesIndexingStartMessage\n | DuplicatesIndexingProgressMessage\n | DuplicatesIndexingCompleteMessage\n | DuplicatesIndexingErrorMessage\n | CoverageResultMessage\n | CoverageErrorMessage\n | CoverageSetupStartMessage\n | CoverageSetupProgressMessage\n | CoverageSetupCompleteMessage\n | CoverageSetupErrorMessage\n | SourceResultMessage\n | SourceErrorMessage\n | ScreenshotSavedMessage\n | ScreenshotErrorMessage\n | PluginOperationStartMessage\n | PluginOperationProgressMessage\n | PluginOperationCompleteMessage\n | PluginOperationErrorMessage;\n\nfunction pickAppRoot(params: { cwd: string; workspaceRoot: string }): string {\n const { cwd, workspaceRoot } = params;\n\n // If started from a Next.js app root (app/ or src/app/ exists), use cwd.\n if (detectNextAppRouter(cwd)) return cwd;\n\n // Otherwise, try to discover Next apps from the workspace root.\n const matches = findNextAppRouterProjects(workspaceRoot, { maxDepth: 5 });\n if (matches.length === 0) return cwd;\n if (matches.length === 1) return matches[0]!.projectPath;\n\n // Prefer a project that contains the current cwd (common in monorepos).\n const containing = matches.find(\n (m) => cwd === m.projectPath || cwd.startsWith(m.projectPath + \"/\")\n );\n if (containing) return containing.projectPath;\n\n // Fallback: pick the first match deterministically.\n return matches[0]!.projectPath;\n}\n\n/**\n * Detect if a post-tool-use hook is configured for Claude or Cursor.\n * These hooks can automatically run ESLint when files are edited.\n */\nfunction detectPostToolUseHook(projectRoot: string): {\n enabled: boolean;\n provider: \"claude\" | \"cursor\" | null;\n} {\n // Check Claude settings.json for PostToolUse hooks\n const claudeSettingsPath = join(projectRoot, \".claude\", \"settings.json\");\n if (existsSync(claudeSettingsPath)) {\n try {\n const content = readFileSync(claudeSettingsPath, \"utf-8\");\n const settings = JSON.parse(content);\n const hooks = settings.hooks?.PostToolUse;\n if (Array.isArray(hooks)) {\n // Check if any hook matches Edit or Write tools\n const hasEditHook = hooks.some(\n (h: { matcher?: string }) =>\n h.matcher?.includes(\"Edit\") || h.matcher?.includes(\"Write\")\n );\n if (hasEditHook) {\n return { enabled: true, provider: \"claude\" };\n }\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n // Check Cursor hooks.json\n const cursorHooksPath = join(projectRoot, \".cursor\", \"hooks.json\");\n if (existsSync(cursorHooksPath)) {\n try {\n const content = readFileSync(cursorHooksPath, \"utf-8\");\n const hooks = JSON.parse(content);\n if (hooks.hooks?.afterFileEdit?.length > 0) {\n return { enabled: true, provider: \"cursor\" };\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n return { enabled: false, provider: null };\n}\n\n// Simple in-memory cache\ninterface CacheEntry {\n issues: LintIssue[];\n mtimeMs: number;\n timestamp: number;\n}\n\nconst cache = new Map<string, CacheEntry>();\n\n// Separate caches for two-pass lint\nconst fastCache = new Map<string, CacheEntry>();\nconst semanticCache = new Map<string, CacheEntry>();\n\n/** Minimal ESLint API surface used by the serve command. */\ninterface ESLintInstance {\n lintFiles(files: string[]): Promise<Array<{ messages: Record<string, unknown>[] }>>;\n}\n\n// ESLint instances cached per detected project root\nconst eslintInstances = new Map<string, unknown>();\n\n// ESLint instances with semantic rule disabled (for fast pass)\nconst eslintFastInstances = new Map<string, unknown>();\n\n// Vision module is dynamically imported to avoid hard dependency on uilint-vision.\nlet visionModule: Record<string, unknown> | null = null;\nlet visionAnalyzer: unknown = null;\n\nasync function getVisionModule(): Promise<Record<string, unknown> | null> {\n if (visionModule) return visionModule;\n try {\n visionModule = await import(\"uilint-vision/node\");\n return visionModule;\n } catch {\n return null;\n }\n}\n\nasync function getVisionAnalyzerInstance(): Promise<unknown> {\n if (visionAnalyzer) return visionAnalyzer;\n const mod = await getVisionModule();\n if (!mod) return null;\n visionAnalyzer = (mod as Record<string, (...args: unknown[]) => unknown>).getVisionAnalyzer();\n return visionAnalyzer;\n}\n\n// =============================================================================\n// Ollama Mutex (tracked)\n// =============================================================================\n// Prevents concurrent Ollama model usage between plugins. Ollama needs to swap\n// models in/out of VRAM, and concurrent requests cause contention and slowdowns.\n// Tracks current holder and queue for dashboard display.\n\nlet ollamaMutexPromise: Promise<void> = Promise.resolve();\nlet ollamaMutexHolder: PluginId | null = null;\nconst ollamaMutexQueue: PluginId[] = [];\n\n/**\n * Acquire exclusive access to Ollama. Returns a release function.\n * Tracks the requester for dashboard display.\n *\n * Usage:\n * const release = await acquireOllamaMutex(\"semantic\");\n * try { ... } finally { release(); }\n */\nfunction acquireOllamaMutex(pluginId: PluginId): Promise<() => void> {\n let release: () => void;\n const prev = ollamaMutexPromise;\n ollamaMutexPromise = new Promise<void>((resolve) => {\n release = resolve;\n });\n\n // Mark this plugin as waiting in the queue\n ollamaMutexQueue.push(pluginId);\n setPluginStatus(pluginId, \"waiting-for-ollama\", \"Queued for Ollama...\");\n\n return prev.then(() => {\n // Granted: remove from queue, mark as holder\n const idx = ollamaMutexQueue.indexOf(pluginId);\n if (idx !== -1) ollamaMutexQueue.splice(idx, 1);\n ollamaMutexHolder = pluginId;\n setPluginStatus(pluginId, \"using-ollama\", \"Using Ollama...\");\n\n return () => {\n // Release: clear holder tracking\n if (ollamaMutexHolder === pluginId) {\n ollamaMutexHolder = null;\n }\n release!();\n };\n });\n}\n\n// Semantic analysis batch progress tracking.\n// Counts files that pass validation and commit to LLM analysis.\nlet semanticFilesRequested = 0;\nlet semanticFilesCompleted = 0;\nlet semanticIdleResetTimer: ReturnType<typeof setTimeout> | null = null;\n\n/** Push current batch progress to the dashboard. */\nfunction updateSemanticBatchProgress(message: string): void {\n const progress =\n semanticFilesRequested > 0\n ? Math.round((semanticFilesCompleted / semanticFilesRequested) * 100)\n : 0;\n updatePluginProgress(\n \"semantic\",\n progress,\n semanticFilesCompleted,\n semanticFilesRequested,\n message\n );\n}\n\n/**\n * Mark one semantic file as done (success or error).\n * If all queued files are finished, show terminal status and schedule idle reset.\n * Otherwise, update batch progress and stay active.\n */\nfunction completeSemanticFile(\n terminalStatus: \"complete\" | \"error\",\n message: string\n): void {\n semanticFilesCompleted++;\n\n if (semanticFilesCompleted >= semanticFilesRequested) {\n const summary =\n terminalStatus === \"complete\"\n ? `Done: ${semanticFilesCompleted} file(s) analyzed`\n : message;\n setPluginStatus(\"semantic\", terminalStatus, summary);\n semanticIdleResetTimer = setTimeout(() => {\n setPluginStatus(\"semantic\", \"idle\");\n semanticFilesRequested = 0;\n semanticFilesCompleted = 0;\n semanticIdleResetTimer = null;\n }, 3000);\n } else {\n updateSemanticBatchProgress(\n `${semanticFilesCompleted}/${semanticFilesRequested} files analyzed`\n );\n }\n}\n\n// Default styleguide search root for vision analysis (set when `serve()` starts)\nlet serverAppRootForVision = process.cwd();\n\nfunction isValidScreenshotFilename(filename: string): boolean {\n // Only allow alphanumeric, hyphens, underscores, and dots; must end with a safe image extension.\n const validPattern = /^[a-zA-Z0-9_-]+\\.(png|jpeg|jpg)$/;\n return validPattern.test(filename) && !filename.includes(\"..\");\n}\n\n// Cache resolved paths for incoming filePath strings\nconst resolvedPathCache = new Map<string, string>();\n\n// File subscriptions: absolutePath -> Set of clients (and the original client filePath string)\nconst subscriptions = new Map<\n string,\n Set<{ ws: WebSocket; clientFilePath: string }>\n>();\n\n// File watcher\nlet fileWatcher: FSWatcher | null = null;\n\n// Basic client tracking for CLI feedback\nlet connectedClients = 0;\n\n// Local require (from uilint deps) for TSX parsing\nconst localRequire = createRequire(import.meta.url);\n\ntype JsxElementSpan = {\n start: number;\n end: number;\n dataLoc: string;\n};\n\nfunction buildLineStarts(code: string): number[] {\n const starts: number[] = [0];\n for (let i = 0; i < code.length; i++) {\n if (code.charCodeAt(i) === 10) starts.push(i + 1); // \\n\n }\n return starts;\n}\n\nfunction offsetFromLineCol(\n lineStarts: number[],\n line1: number,\n col0: number,\n codeLength: number\n): number {\n const lineIndex = Math.max(0, Math.min(lineStarts.length - 1, line1 - 1));\n const base = lineStarts[lineIndex] ?? 0;\n return Math.max(0, Math.min(codeLength, base + Math.max(0, col0)));\n}\n\nfunction buildJsxElementSpans(\n code: string,\n dataLocFile: string\n): JsxElementSpan[] {\n \n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => Record<string, unknown>;\n };\n\n const ast = parse(code, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n\n const spans: JsxElementSpan[] = [];\n\n function walk(node: Record<string, unknown>): void {\n if (!node || typeof node !== \"object\") return;\n\n // Prefer mapping to JSXElement range so we can capture nested ownership precisely.\n if (node.type === \"JSXElement\") {\n const range = node.range as [number, number] | undefined;\n const opening = node.openingElement as Record<string, unknown> | undefined;\n const loc = (opening?.loc as Record<string, unknown> | undefined)?.start as Record<string, unknown> | undefined;\n if (\n range &&\n typeof range[0] === \"number\" &&\n typeof range[1] === \"number\" &&\n loc &&\n typeof loc.line === \"number\" &&\n typeof loc.column === \"number\"\n ) {\n const dataLoc = `${dataLocFile}:${loc.line}:${loc.column}`;\n spans.push({ start: range[0], end: range[1], dataLoc });\n }\n }\n\n for (const key of Object.keys(node)) {\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) walk(item as Record<string, unknown>);\n } else if (child && typeof child === \"object\") {\n walk(child as Record<string, unknown>);\n }\n }\n }\n\n walk(ast);\n\n // Keep spans small-first to make “smallest containing span” selection fast.\n spans.sort((a, b) => a.end - a.start - (b.end - b.start));\n return spans;\n}\n\nfunction mapMessageToDataLoc(params: {\n spans: JsxElementSpan[];\n lineStarts: number[];\n codeLength: number;\n messageLine1: number;\n messageCol1?: number;\n}): string | undefined {\n const col0 =\n typeof params.messageCol1 === \"number\"\n ? Math.max(0, params.messageCol1 - 1)\n : 0;\n const offset = offsetFromLineCol(\n params.lineStarts,\n params.messageLine1,\n col0,\n params.codeLength\n );\n\n // Pick the smallest JSXElement range that contains this offset.\n for (const s of params.spans) {\n if (s.start <= offset && offset < s.end) return s.dataLoc;\n }\n return undefined;\n}\n\n/**\n * Known ESLint config filenames (flat + legacy).\n */\nconst ESLINT_CONFIG_FILES = [\n // Flat config (ESLint v9+)\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n \"eslint.config.ts\",\n // Legacy config\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n];\n\n/**\n * Find a project root directory for ESLint by walking upward from a file dir.\n */\nfunction findESLintCwd(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 30; i++) {\n for (const cfg of ESLINT_CONFIG_FILES) {\n if (existsSync(join(dir, cfg))) return dir;\n }\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\nfunction normalizePathSlashes(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\n/**\n * Match `jsx-loc-plugin` behavior:\n * - Use a stable, project-relative path when possible, otherwise absolute.\n */\nfunction normalizeDataLocFilePath(\n absoluteFilePath: string,\n projectCwd: string\n): string {\n const abs = normalizePathSlashes(resolve(absoluteFilePath));\n const cwd = normalizePathSlashes(resolve(projectCwd));\n if (abs === cwd || abs.startsWith(cwd + \"/\")) {\n return normalizePathSlashes(relative(cwd, abs));\n }\n return abs;\n}\n\nfunction resolveRequestedFilePath(filePath: string): string {\n // Absolute (POSIX) or Windows drive path\n if (filePath.startsWith(\"/\") || /^[A-Za-z]:[\\\\/]/.test(filePath)) {\n return resolve(filePath);\n }\n\n const cached = resolvedPathCache.get(filePath);\n if (cached) return cached;\n\n const cwd = process.cwd();\n const fromCwd = resolve(cwd, filePath);\n if (existsSync(fromCwd)) {\n resolvedPathCache.set(filePath, fromCwd);\n return fromCwd;\n }\n\n const wsRoot = findWorkspaceRoot(cwd);\n const fromWs = resolve(wsRoot, filePath);\n if (existsSync(fromWs)) {\n resolvedPathCache.set(filePath, fromWs);\n return fromWs;\n }\n\n // Monorepo helper: try common workspace folders (apps/*, packages/*)\n // Example: filePath=\"app/page.tsx\" -> apps/test-app/app/page.tsx\n for (const top of [\"apps\", \"packages\"]) {\n const base = join(wsRoot, top);\n if (!existsSync(base)) continue;\n try {\n const entries = readdirSync(base, { withFileTypes: true });\n for (const ent of entries) {\n if (!ent.isDirectory()) continue;\n const p = resolve(base, ent.name, filePath);\n if (existsSync(p)) {\n resolvedPathCache.set(filePath, p);\n return p;\n }\n }\n } catch {\n // ignore\n }\n }\n\n // Cache deterministic fallback so repeated requests don't thrash\n resolvedPathCache.set(filePath, fromCwd);\n return fromCwd;\n}\n\nasync function getESLintForProject(projectCwd: string): Promise<unknown> {\n const cached = eslintInstances.get(projectCwd);\n if (cached) return cached;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n\n const mod = req(\"eslint\") as Record<string, unknown>;\n const modDefault = mod?.default as Record<string, unknown> | undefined;\n const ESLintCtor =\n mod?.ESLint ?? modDefault?.ESLint ?? mod?.default ?? mod;\n if (!ESLintCtor) return null;\n\n const Ctor = ESLintCtor as new (opts: Record<string, unknown>) => unknown;\n const eslint = new Ctor({ cwd: projectCwd });\n eslintInstances.set(projectCwd, eslint);\n return eslint;\n } catch {\n return null;\n }\n}\n\n/**\n * Create an ESLint instance with rule overrides (for two-pass lint).\n * Uses ESLint 9 flat config's overrideConfig option.\n */\nasync function getESLintWithOverrides(\n projectCwd: string,\n overrideRules: Record<string, string>,\n instanceCache: Map<string, unknown>\n): Promise<unknown> {\n const cacheKey = `${projectCwd}::${JSON.stringify(overrideRules)}`;\n const cached = instanceCache.get(cacheKey);\n if (cached) return cached;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n const mod = req(\"eslint\") as Record<string, unknown>;\n const modDefault = mod?.default as Record<string, unknown> | undefined;\n const ESLintCtor =\n mod?.ESLint ?? modDefault?.ESLint ?? mod?.default ?? mod;\n if (!ESLintCtor) return null;\n\n const Ctor = ESLintCtor as new (opts: Record<string, unknown>) => unknown;\n const eslint = new Ctor({\n cwd: projectCwd,\n overrideConfig: { rules: overrideRules },\n });\n instanceCache.set(cacheKey, eslint);\n return eslint;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if the semantic rule is enabled in the ESLint config.\n */\nfunction isSemanticRuleEnabled(): boolean {\n const eslintConfigPath = findEslintConfigFile(serverAppRootForVision);\n if (!eslintConfigPath) return false;\n\n const ruleConfigs = readRuleConfigsFromConfig(eslintConfigPath);\n const semanticConfig = ruleConfigs.get(\"semantic\");\n if (!semanticConfig) return false;\n\n return semanticConfig.severity !== \"off\";\n}\n\n/**\n * Process raw ESLint messages into LintIssue[] with JSX mapping and scope info.\n * Shared between fast and semantic passes.\n */\nfunction processLintResults(\n absolutePath: string,\n projectCwd: string,\n messages: Record<string, unknown>[],\n onProgress: (phase: string) => void\n): LintIssue[] {\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n let spans: JsxElementSpan[] = [];\n let lineStarts: number[] = [];\n let codeLength = 0;\n let fileCode: string | null = null;\n\n try {\n onProgress(\"Building JSX map...\");\n fileCode = readFileSync(absolutePath, \"utf-8\");\n codeLength = fileCode.length;\n lineStarts = buildLineStarts(fileCode);\n spans = buildJsxElementSpans(fileCode, dataLocFile);\n onProgress(`JSX map: ${spans.length} element(s)`);\n } catch (e) {\n onProgress(\"JSX map failed (falling back to unmapped issues)\");\n logServerError(\"JSX map failed\", e instanceof Error ? e.message : String(e));\n spans = [];\n lineStarts = [];\n codeLength = 0;\n fileCode = null;\n }\n\n let issues: LintIssue[] = messages\n .filter((m: Record<string, unknown>) => typeof m?.message === \"string\")\n .map((m: Record<string, unknown>) => {\n const line = typeof m.line === \"number\" ? m.line : 1;\n const column = typeof m.column === \"number\" ? m.column : undefined;\n const mappedDataLoc =\n spans.length > 0 && lineStarts.length > 0 && codeLength > 0\n ? mapMessageToDataLoc({\n spans,\n lineStarts,\n codeLength,\n messageLine1: line,\n messageCol1: column,\n })\n : undefined;\n return {\n line,\n column,\n message: m.message as string,\n ruleId: typeof m.ruleId === \"string\" ? m.ruleId : undefined,\n messageId: typeof m.messageId === \"string\" ? m.messageId : undefined,\n dataLoc: mappedDataLoc,\n } satisfies LintIssue;\n });\n\n const mappedCount = issues.filter((i) => Boolean(i.dataLoc)).length;\n if (issues.length > 0) {\n onProgress(`Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`);\n }\n\n // Enrich issues with scope information\n if (fileCode && issues.length > 0) {\n onProgress(\"Extracting scope info...\");\n issues = enrichIssuesWithScopeInfo(issues, fileCode);\n const scopeCount = issues.filter((i) => Boolean(i.scopeInfo)).length;\n onProgress(`Enriched ${scopeCount}/${issues.length} issue(s) with scope info`);\n }\n\n return issues;\n}\n\n/**\n * Fast lint pass: runs all rules EXCEPT semantic.\n * Non-blocking (no spawnSync calls).\n */\nasync function lintFileFast(\n filePath: string,\n onProgress: (phase: string) => void\n): Promise<LintIssue[]> {\n const absolutePath = resolveRequestedFilePath(filePath);\n\n if (!existsSync(absolutePath)) {\n onProgress(`File not found: ${pc.dim(absolutePath)}`);\n return [];\n }\n\n const mtimeMs = (() => {\n try { return statSync(absolutePath).mtimeMs; } catch { return 0; }\n })();\n\n // Check fast-pass cache\n const cached = fastCache.get(absolutePath);\n if (cached && cached.mtimeMs === mtimeMs) {\n onProgress(\"Cache hit (unchanged)\");\n return cached.issues;\n }\n\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n onProgress(`Resolving ESLint project... ${pc.dim(projectCwd)}`);\n\n const eslint = await getESLintWithOverrides(\n projectCwd,\n { \"uilint/semantic\": \"off\" },\n eslintFastInstances\n );\n if (!eslint) {\n logWarning(\n `ESLint not found in project. Install it in ${pc.dim(projectCwd)} to enable server-side linting.`\n );\n onProgress(\"ESLint not available (install eslint in this project)\");\n return [];\n }\n\n try {\n onProgress(\"Running ESLint...\");\n const results = await (eslint as ESLintInstance).lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n const issues = processLintResults(absolutePath, projectCwd, messages, onProgress);\n\n fastCache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n logServerError(\"ESLint fast pass failed\", error instanceof Error ? error.message : String(error));\n return [];\n }\n}\n\n/**\n * Semantic lint pass: runs ALL ESLint rules then filters to only semantic results.\n * This blocks the event loop via spawnSync in the semantic rule, so it should\n * be called from a deferred context (setImmediate).\n */\nasync function lintFileSemantic(\n filePath: string,\n onProgress: (phase: string) => void\n): Promise<LintIssue[]> {\n const absolutePath = resolveRequestedFilePath(filePath);\n\n if (!existsSync(absolutePath)) return [];\n\n const mtimeMs = (() => {\n try { return statSync(absolutePath).mtimeMs; } catch { return 0; }\n })();\n\n // Check semantic-pass cache\n const cached = semanticCache.get(absolutePath);\n if (cached && cached.mtimeMs === mtimeMs) {\n onProgress(\"Semantic cache hit (unchanged)\");\n return cached.issues;\n }\n\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n // Use the default ESLint instance (all rules enabled including semantic)\n const eslint = await getESLintForProject(projectCwd);\n if (!eslint) return [];\n\n try {\n onProgress(\"Running semantic analysis...\");\n const results = await (eslint as ESLintInstance).lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n // Filter to only semantic rule results\n const semanticMessages = messages.filter(\n (m: Record<string, unknown>) => m.ruleId === \"uilint/semantic\"\n );\n\n if (semanticMessages.length === 0) return [];\n\n const issues = processLintResults(absolutePath, projectCwd, semanticMessages, onProgress);\n\n semanticCache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n logServerError(\"Semantic pass failed\", error instanceof Error ? error.message : String(error));\n return [];\n }\n}\n\n/**\n * Run semantic analysis asynchronously using OllamaClient.\n * Unlike lintFileSemantic (which runs ESLint + spawnSync), this calls Ollama\n * directly via its HTTP API, writes results to the ESLint rule's disk cache,\n * and sends lint:result to the client. Completely non-blocking.\n */\nasync function runSemanticAnalysisAsync(\n filePath: string,\n ws: WebSocket,\n requestId?: string\n): Promise<void> {\n const startTime = Date.now();\n logSemanticAnalyze(filePath, requestId);\n\n const absolutePath = resolveRequestedFilePath(filePath);\n if (!existsSync(absolutePath)) {\n logSemanticSkipped(filePath, \"file not found\");\n return;\n }\n\n // Read the semantic rule's config to get the model\n const eslintConfigPath = findEslintConfigFile(serverAppRootForVision);\n const ruleConfigs = eslintConfigPath\n ? readRuleConfigsFromConfig(eslintConfigPath)\n : new Map<string, { severity: \"error\" | \"warn\" | \"off\"; options?: Record<string, unknown> }>();\n const semanticConfig = ruleConfigs.get(\"semantic\");\n const model = (semanticConfig?.options?.model as string) || \"qwen3-vl:8b-instruct\";\n const styleguidePath = (semanticConfig?.options?.styleguidePath as string) || undefined;\n setPluginModel(\"semantic\", model);\n\n // Load styleguide\n const { getStyleguide, hashContentSync, setCacheEntry, getCacheEntry } = await import(\"uilint-eslint\");\n const fileDir = dirname(absolutePath);\n const { content: styleguide } = getStyleguide(fileDir, styleguidePath);\n if (!styleguide) {\n logSemanticSkipped(filePath, \"no styleguide found\");\n return;\n }\n\n // Read and hash file contents\n let fileContent: string;\n try {\n fileContent = readFileSync(absolutePath, \"utf-8\");\n } catch {\n logSemanticSkipped(filePath, \"file read error\");\n return;\n }\n\n const fileHash = hashContentSync(fileContent);\n const styleguideHash = hashContentSync(styleguide);\n\n // Find project root for cache\n const projectRoot = findWorkspaceRoot(fileDir) || fileDir;\n const relativeFilePath = relative(projectRoot, absolutePath);\n\n // Check if cache is already fresh\n const cached = getCacheEntry(projectRoot, relativeFilePath, fileHash, styleguideHash);\n if (cached) {\n logSemanticSkipped(filePath, \"cache fresh\");\n return;\n }\n\n // Track this file in the semantic batch progress\n if (semanticIdleResetTimer) {\n clearTimeout(semanticIdleResetTimer);\n semanticIdleResetTimer = null;\n }\n semanticFilesRequested++;\n updateSemanticBatchProgress(\n `Queued ${relative(serverAppRootForVision, absolutePath)}...`\n );\n\n // Report progress\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Running semantic analysis (async)...\",\n });\n\n startBackgroundTask(\"semantic-analysis\", \"Semantic Analysis\", `Analyzing ${filePath}...`);\n broadcast({\n type: \"plugin:operation:start\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n message: `Analyzing ${relative(serverAppRootForVision, absolutePath)}...`,\n });\n\n // Acquire mutex to avoid Ollama model contention\n const release = await acquireOllamaMutex(\"semantic\");\n\n try {\n const { OllamaClient, buildSourceScanPrompt } = await import(\"uilint-core/node\");\n const client = new OllamaClient({ model });\n\n const ok = await client.isAvailable();\n if (!ok) {\n logServerWarning(\"Semantic analysis: Ollama not available\");\n updateBackgroundTaskProgress(\"semantic-analysis\", 0, 0, 0, \"Ollama not available\");\n completeBackgroundTask(\"semantic-analysis\", undefined, \"Ollama not available\");\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n error: \"Ollama not available\",\n });\n completeSemanticFile(\"error\", \"Ollama not available\");\n return;\n }\n\n updateBackgroundTaskProgress(\"semantic-analysis\", 50, 0, 0, \"Waiting for LLM response...\");\n updateSemanticBatchProgress(\n `Analyzing ${relative(serverAppRootForVision, absolutePath)}...`\n );\n broadcast({\n type: \"plugin:operation:progress\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n message: \"Waiting for LLM response...\",\n });\n\n const prompt = buildSourceScanPrompt(fileContent, styleguide, {\n filePath: relative(serverAppRootForVision, absolutePath),\n });\n\n const responseText = await client.complete(prompt, { json: true });\n const parsed = JSON.parse(responseText) as {\n issues?: Array<{ line?: number; column?: number; message?: string }>;\n };\n\n const issues = (parsed.issues || []).map((issue) => ({\n line: issue.line || 1,\n column: issue.column,\n message: issue.message || \"Semantic issue detected\",\n ruleId: \"uilint/semantic\",\n severity: 1 as const,\n }));\n\n // Write to the ESLint rule's disk cache\n setCacheEntry(projectRoot, relativeFilePath, {\n fileHash,\n styleguideHash,\n issues,\n timestamp: Date.now(),\n });\n\n // Convert to LintIssue format for the WS result\n const fileDir2 = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir2);\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n const lintIssues: LintIssue[] = issues.map((issue) => ({\n ruleId: \"uilint/semantic\",\n severity: issue.severity,\n message: issue.message,\n line: issue.line,\n column: issue.column || 0,\n nodeType: null,\n source: null,\n dataLoc: `${dataLocFile}:${issue.line}:${issue.column || 0}`,\n }));\n\n // Always send results (even if empty) so client knows analysis finished\n sendMessage(ws, {\n type: \"lint:result\",\n filePath,\n requestId,\n issues: lintIssues,\n });\n\n const elapsed = Date.now() - startTime;\n const msg = `${issues.length} issue(s) found`;\n logSemanticDone(filePath, issues.length, elapsed);\n completeBackgroundTask(\"semantic-analysis\", msg);\n completeSemanticFile(\"complete\", msg);\n broadcast({\n type: \"plugin:operation:complete\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n message: msg,\n });\n\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (semantic: ${issues.length} issues)`,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logServerError(\"Async semantic analysis failed\", errorMessage);\n completeBackgroundTask(\"semantic-analysis\", undefined, errorMessage);\n completeSemanticFile(\"error\", errorMessage);\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n error: errorMessage,\n });\n } finally {\n release();\n }\n}\n\n/**\n * Run vision analysis in the background (fire-and-forget).\n * Extracted from the vision:analyze handler to avoid blocking handleMessage.\n */\nasync function runVisionAnalysisInBackground(\n ws: WebSocket,\n message: VisionAnalyzeMessage\n): Promise<void> {\n const { route, timestamp, screenshot, screenshotFile, manifest, requestId } = message;\n\n setPluginStatus(\"vision\", \"processing\", `Analyzing ${route}...`);\n startBackgroundTask(\"vision-analysis\", \"Vision Analysis\", `Analyzing ${route}...`);\n broadcast({\n type: \"plugin:operation:start\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n message: `Analyzing ${route}...`,\n });\n\n const visionMod = await getVisionModule();\n if (!visionMod) {\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: 0,\n error: \"uilint-vision is not installed\",\n requestId,\n });\n completeBackgroundTask(\"vision-analysis\", undefined, \"uilint-vision not installed\");\n setPluginStatus(\"vision\", \"error\", \"uilint-vision not installed\");\n setTimeout(() => setPluginStatus(\"vision\", \"idle\"), 3000);\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n error: \"uilint-vision not installed\",\n });\n return;\n }\n\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase: \"Starting vision analysis...\",\n });\n\n const startedAt = Date.now();\n const analyzer = await getVisionAnalyzerInstance();\n\n updateBackgroundTaskProgress(\"vision-analysis\", 10, 0, 0, \"Waiting for Ollama...\");\n\n // Acquire exclusive access to Ollama to avoid model contention\n const releaseOllama = await acquireOllamaMutex(\"vision\");\n\n try {\n const analyzerObj = analyzer as Record<string, unknown> | null;\n const analyzerModel =\n typeof analyzerObj?.getModel === \"function\" ? (analyzerObj.getModel as () => string)() : undefined;\n const analyzerBaseUrl =\n typeof analyzerObj?.getBaseUrl === \"function\" ? (analyzerObj.getBaseUrl as () => string)() : undefined;\n\n if (analyzerModel) {\n setPluginModel(\"vision\", analyzerModel);\n }\n\n if (!screenshot) {\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: Date.now() - startedAt,\n error: \"No screenshot provided for vision analysis\",\n requestId,\n });\n completeBackgroundTask(\"vision-analysis\", undefined, \"No screenshot provided\");\n setPluginStatus(\"vision\", \"error\", \"No screenshot provided\");\n setTimeout(() => setPluginStatus(\"vision\", \"idle\"), 3000);\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n error: \"No screenshot provided\",\n });\n return;\n }\n\n updateBackgroundTaskProgress(\"vision-analysis\", 30, 0, 0, \"Running vision analysis...\");\n broadcast({\n type: \"plugin:operation:progress\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n message: \"Running vision analysis...\",\n });\n\n const result = await (visionMod as Record<string, (...args: unknown[]) => Promise<Record<string, unknown>>>).runVisionAnalysis({\n imageBase64: screenshot,\n manifest,\n projectPath: serverAppRootForVision,\n baseUrl: analyzerBaseUrl,\n model: analyzerModel,\n analyzer,\n onPhase: (phase: string) => {\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase,\n });\n updateBackgroundTaskProgress(\"vision-analysis\", 50, 0, 0, phase);\n },\n pathResolver: resolvePathSpecifier,\n }) as Record<string, unknown>;\n\n // Write markdown report (best-effort)\n if (typeof screenshotFile === \"string\" && screenshotFile.length > 0) {\n if (isValidScreenshotFilename(screenshotFile)) {\n const screenshotsDir = join(serverAppRootForVision, \".uilint\", \"screenshots\");\n const imagePath = join(screenshotsDir, screenshotFile);\n try {\n if (existsSync(imagePath)) {\n const report = (visionMod as Record<string, (...args: unknown[]) => Record<string, unknown>>).writeVisionMarkdownReport({\n imagePath,\n route,\n timestamp,\n visionModel: result.visionModel,\n baseUrl: result.baseUrl,\n analysisTimeMs: result.analysisTime,\n prompt: result.prompt ?? null,\n rawResponse: result.rawResponse ?? null,\n metadata: {\n screenshotFile: parse(imagePath).base,\n appRoot: serverAppRootForVision,\n manifestElements: manifest.length,\n requestId: requestId ?? null,\n },\n });\n logServerInfo(`Wrote vision report`, report.outPath as string);\n }\n } catch (e) {\n logServerWarning(\n `Failed to write vision report for ${screenshotFile}`,\n e instanceof Error ? e.message : String(e)\n );\n }\n }\n }\n\n const elapsed = Date.now() - startedAt;\n const resultIssues = result.issues as Record<string, unknown>[];\n logVisionDone(route, resultIssues.length, elapsed);\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: resultIssues,\n analysisTime: result.analysisTime as number,\n requestId,\n });\n\n const msg = `${resultIssues.length} issue(s) in ${(elapsed / 1000).toFixed(1)}s`;\n completeBackgroundTask(\"vision-analysis\", msg);\n setPluginStatus(\"vision\", \"complete\", msg);\n setTimeout(() => setPluginStatus(\"vision\", \"idle\"), 3000);\n broadcast({\n type: \"plugin:operation:complete\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n message: msg,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const elapsed = Date.now() - startedAt;\n logServerError(`Vision analysis failed for ${route}`, errorMessage);\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: elapsed,\n error: errorMessage,\n requestId,\n });\n completeBackgroundTask(\"vision-analysis\", undefined, errorMessage);\n setPluginStatus(\"vision\", \"error\", errorMessage);\n setTimeout(() => setPluginStatus(\"vision\", \"idle\"), 3000);\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n error: errorMessage,\n });\n } finally {\n releaseOllama();\n }\n}\n\n/**\n * Lint a file and return issues (legacy single-pass, used for backwards compat)\n */\nasync function _lintFile(\n filePath: string,\n onProgress: (phase: string) => void\n): Promise<LintIssue[]> {\n const absolutePath = resolveRequestedFilePath(filePath);\n\n // Check if file exists\n if (!existsSync(absolutePath)) {\n onProgress(`File not found: ${pc.dim(absolutePath)}`);\n return [];\n }\n\n const mtimeMs = (() => {\n try {\n return statSync(absolutePath).mtimeMs;\n } catch {\n return 0;\n }\n })();\n\n // Check cache (mtime-based)\n const cached = cache.get(absolutePath);\n if (cached && cached.mtimeMs === mtimeMs) {\n onProgress(\"Cache hit (unchanged)\");\n return cached.issues;\n }\n\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n onProgress(`Resolving ESLint project... ${pc.dim(projectCwd)}`);\n\n const eslint = await getESLintForProject(projectCwd);\n if (!eslint) {\n logWarning(\n `ESLint not found in project. Install it in ${pc.dim(\n projectCwd\n )} to enable server-side linting.`\n );\n onProgress(\"ESLint not available (install eslint in this project)\");\n return [];\n }\n\n try {\n onProgress(\"Running ESLint...\");\n const results = await (eslint as ESLintInstance).lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n let spans: JsxElementSpan[] = [];\n let lineStarts: number[] = [];\n let codeLength = 0;\n let fileCode: string | null = null;\n\n try {\n onProgress(\"Building JSX map...\");\n fileCode = readFileSync(absolutePath, \"utf-8\");\n codeLength = fileCode.length;\n lineStarts = buildLineStarts(fileCode);\n spans = buildJsxElementSpans(fileCode, dataLocFile);\n onProgress(`JSX map: ${spans.length} element(s)`);\n } catch (e) {\n // If parsing fails, we still return ESLint messages (unmapped).\n onProgress(\"JSX map failed (falling back to unmapped issues)\");\n logServerError(\n \"JSX map failed\",\n e instanceof Error ? e.message : String(e)\n );\n spans = [];\n lineStarts = [];\n codeLength = 0;\n fileCode = null;\n }\n\n let issues: LintIssue[] = messages\n .filter((m: Record<string, unknown>) => typeof m?.message === \"string\")\n .map((m: Record<string, unknown>) => {\n const line = typeof m.line === \"number\" ? m.line : 1;\n const column = typeof m.column === \"number\" ? m.column : undefined;\n const mappedDataLoc =\n spans.length > 0 && lineStarts.length > 0 && codeLength > 0\n ? mapMessageToDataLoc({\n spans,\n lineStarts,\n codeLength,\n messageLine1: line,\n messageCol1: column,\n })\n : undefined;\n return {\n line,\n column,\n message: m.message as string,\n ruleId: typeof m.ruleId === \"string\" ? m.ruleId : undefined,\n messageId: typeof m.messageId === \"string\" ? m.messageId : undefined,\n dataLoc: mappedDataLoc,\n } satisfies LintIssue;\n });\n\n const mappedCount = issues.filter((i) => Boolean(i.dataLoc)).length;\n if (issues.length > 0) {\n onProgress(\n `Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`\n );\n }\n\n // Enrich issues with scope information\n if (fileCode && issues.length > 0) {\n onProgress(\"Extracting scope info...\");\n issues = enrichIssuesWithScopeInfo(issues, fileCode);\n const scopeCount = issues.filter((i) => Boolean(i.scopeInfo)).length;\n onProgress(\n `Enriched ${scopeCount}/${issues.length} issue(s) with scope info`\n );\n }\n\n cache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n logServerError(\n \"ESLint failed\",\n error instanceof Error ? error.message : String(error)\n );\n return [];\n }\n}\n\n/**\n * Send message to client\n */\nfunction sendMessage(ws: WebSocket, message: ServerMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(message));\n }\n}\n\n/**\n * Handle incoming client message\n */\nasync function handleMessage(ws: WebSocket, data: string): Promise<void> {\n let message: ClientMessage;\n try {\n message = JSON.parse(data) as ClientMessage;\n } catch {\n return;\n }\n\n // Server-side tracing to confirm activity\n if (message.type === \"lint:file\" || message.type === \"lint:element\") {\n const fp = (message as LintFileMessage | LintElementMessage).filePath;\n const rid = (message as LintFileMessage | LintElementMessage).requestId;\n logLint(fp ?? \"\", rid);\n } else if (message.type === \"subscribe:file\") {\n logSubscribe(message.filePath);\n } else if (message.type === \"cache:invalidate\") {\n logCacheInvalidate(message.filePath);\n } else if (message.type === \"vision:analyze\") {\n // Logged in handler for more detailed output\n } else if (message.type === \"vision:check\") {\n // Logged in handler\n } else if (message.type === \"config:set\") {\n // Logged in handler\n } else if (message.type === \"screenshot:save\") {\n const rid = (message as ScreenshotSaveMessage).requestId;\n logScreenshotSave(message.route, rid);\n }\n\n switch (message.type) {\n case \"lint:file\": {\n const { filePath, requestId } = message;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Starting...\",\n });\n\n const startedAt = Date.now();\n const resolved = resolveRequestedFilePath(filePath);\n if (!existsSync(resolved)) {\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n logServerWarning(\n `File not found: ${filePath}`,\n `resolved: ${resolved}, cwd: ${cwd}, wsRoot: ${wsRoot}`\n );\n }\n\n // === PASS 1: Fast rules (non-blocking, no spawnSync) ===\n const fastIssues = await lintFileFast(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n const fastElapsed = Date.now() - startedAt;\n\n // Filter sentinel issues from fast results\n const fastSentinels = fastIssues.filter(isSentinelIssue);\n for (const se of fastSentinels) {\n logRuleInternalError(se.ruleId ?? \"unknown\", filePath, se.message);\n }\n const fastClientIssues = fastIssues.filter((i) => !isSentinelIssue(i));\n\n logLintDone(filePath, fastClientIssues.length, fastElapsed);\n updateCacheCount(fastCache.size + semanticCache.size);\n\n // Send fast results immediately\n sendMessage(ws, { type: \"lint:result\", filePath, requestId, issues: fastClientIssues });\n\n // Send Done for fast pass immediately\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${fastClientIssues.length} issues, ${fastElapsed}ms)`,\n });\n\n // === PASS 2: Semantic analysis (async, non-blocking) ===\n if (isSemanticRuleEnabled()) {\n runSemanticAnalysisAsync(filePath, ws, requestId).catch((err) => {\n logServerError(\"Async semantic analysis failed\", err instanceof Error ? err.message : String(err));\n });\n } else {\n logSemanticSkipped(filePath, \"rule not enabled\");\n }\n break;\n }\n\n case \"lint:element\": {\n const { filePath, dataLoc, requestId } = message;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Starting...\",\n });\n\n const startedAt = Date.now();\n\n // === PASS 1: Fast rules ===\n const fastIssues = await lintFileFast(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n const fastSentinels = fastIssues.filter(isSentinelIssue);\n for (const se of fastSentinels) {\n logRuleInternalError(se.ruleId ?? \"unknown\", filePath, se.message);\n }\n\n const fastFiltered = fastIssues\n .filter((i) => !isSentinelIssue(i))\n .filter((issue) => issue.dataLoc === dataLoc);\n\n // Send fast results immediately\n sendMessage(ws, { type: \"lint:result\", filePath, requestId, issues: fastFiltered });\n\n // Send Done for fast pass immediately\n {\n const elapsed = Date.now() - startedAt;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${fastFiltered.length} issues, ${elapsed}ms)`,\n });\n }\n\n // === PASS 2: Semantic analysis (async, non-blocking) ===\n if (isSemanticRuleEnabled()) {\n runSemanticAnalysisAsync(filePath, ws, requestId).catch((err) => {\n logServerError(\"Async semantic analysis failed\", err instanceof Error ? err.message : String(err));\n });\n } else {\n logSemanticSkipped(filePath, \"rule not enabled\");\n }\n break;\n }\n\n case \"subscribe:file\": {\n const { filePath } = message;\n const absolutePath = resolveRequestedFilePath(filePath);\n\n // Add to subscriptions\n let subscribers = subscriptions.get(absolutePath);\n if (!subscribers) {\n subscribers = new Set();\n subscriptions.set(absolutePath, subscribers);\n\n // Start watching this file\n if (fileWatcher) {\n fileWatcher.add(absolutePath);\n }\n }\n subscribers.add({ ws, clientFilePath: filePath });\n\n // Update subscription count in dashboard\n updateSubscriptionCount(subscriptions.size);\n break;\n }\n\n case \"cache:invalidate\": {\n const { filePath } = message;\n if (filePath) {\n const absolutePath = resolveRequestedFilePath(filePath);\n cache.delete(absolutePath);\n fastCache.delete(absolutePath);\n semanticCache.delete(absolutePath);\n } else {\n cache.clear();\n fastCache.clear();\n semanticCache.clear();\n }\n // Update cache count in dashboard\n updateCacheCount(cache.size + fastCache.size + semanticCache.size);\n break;\n }\n\n case \"vision:analyze\": {\n const visionMsg = message as VisionAnalyzeMessage;\n logVisionAnalyze(visionMsg.route, visionMsg.requestId);\n\n // Fire-and-forget: run vision analysis in background\n runVisionAnalysisInBackground(ws, visionMsg).catch((err) => {\n logServerError(\"Vision analysis failed\", err instanceof Error ? err.message : String(err));\n });\n break;\n }\n\n case \"vision:check\": {\n const { requestId } = message as VisionCheckMessage;\n logVisionCheck(requestId);\n\n try {\n const analyzer = await getVisionAnalyzerInstance();\n if (!analyzer) {\n sendMessage(ws, { type: \"vision:status\", available: false, requestId });\n break;\n }\n const analyzerObj = analyzer as Record<string, unknown>;\n const model = typeof analyzerObj.getModel === \"function\" ? (analyzerObj.getModel as () => string)() : undefined;\n sendMessage(ws, { type: \"vision:status\", available: true, model, requestId });\n } catch {\n sendMessage(ws, { type: \"vision:status\", available: false, requestId });\n }\n break;\n }\n\n case \"config:set\": {\n const { key, value } = message;\n handleConfigSet(key, value);\n break;\n }\n\n case \"rule:config:set\": {\n const { ruleId, severity, options, requestId } = message;\n handleRuleConfigSet(ws, ruleId, severity, options, requestId);\n break;\n }\n\n case \"source:fetch\": {\n const { filePath, requestId } = message;\n const absolutePath = resolveRequestedFilePath(filePath);\n\n if (!existsSync(absolutePath)) {\n sendMessage(ws, {\n type: \"source:error\",\n filePath,\n error: \"File not found\",\n requestId,\n });\n break;\n }\n\n try {\n const content = readFileSync(absolutePath, \"utf-8\");\n const totalLines = content.split(\"\\n\").length;\n const relativePath = normalizeDataLocFilePath(\n absolutePath,\n serverAppRootForVision\n );\n\n sendMessage(ws, {\n type: \"source:result\",\n filePath,\n content,\n totalLines,\n relativePath,\n requestId,\n });\n } catch (error) {\n sendMessage(ws, {\n type: \"source:error\",\n filePath,\n error: error instanceof Error ? error.message : \"Failed to read file\",\n requestId,\n });\n }\n break;\n }\n\n case \"coverage:request\": {\n const { requestId } = message;\n try {\n const coveragePath = join(\n serverAppRootForVision,\n \"coverage\",\n \"coverage-final.json\"\n );\n\n if (!existsSync(coveragePath)) {\n sendMessage(ws, {\n type: \"coverage:error\",\n error:\n \"Coverage data not found. Run tests with coverage first (e.g., `vitest run --coverage`)\",\n requestId,\n });\n break;\n }\n\n const coverageData = JSON.parse(readFileSync(coveragePath, \"utf-8\"));\n logCoverageResult(Object.keys(coverageData).length);\n\n sendMessage(ws, {\n type: \"coverage:result\",\n coverage: coverageData,\n timestamp: Date.now(),\n requestId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logServerError(`coverage:error`, errorMessage);\n sendMessage(ws, {\n type: \"coverage:error\",\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n\n case \"screenshot:save\": {\n const { dataUrl, route, timestamp, requestId } = message;\n\n try {\n // Validate the dataUrl is a valid base64 PNG data URL\n if (!dataUrl || typeof dataUrl !== \"string\") {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: \"Invalid dataUrl: must be a non-empty string\",\n requestId,\n });\n break;\n }\n\n const dataUrlPattern = /^data:image\\/png;base64,/;\n if (!dataUrlPattern.test(dataUrl)) {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error:\n \"Invalid dataUrl: must be a base64 PNG data URL (data:image/png;base64,...)\",\n requestId,\n });\n break;\n }\n\n // Extract base64 data\n const base64Data = dataUrl.replace(dataUrlPattern, \"\");\n\n // Sanitize route for filename (replace / with -, remove special chars)\n const sanitizedRoute =\n route\n .replace(/^\\//, \"\") // Remove leading slash\n .replace(/\\//g, \"-\") // Replace slashes with dashes\n .replace(/[^a-zA-Z0-9_-]/g, \"_\") || // Replace special chars with underscore\n \"root\"; // Default to \"root\" for empty route\n\n // Generate filename\n const filename = `uilint-${timestamp}-${sanitizedRoute}.png`;\n\n // Validate generated filename\n if (!isValidScreenshotFilename(filename)) {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: `Generated filename is invalid: ${filename}`,\n requestId,\n });\n break;\n }\n\n // Create screenshots directory if needed\n const screenshotsDir = join(\n serverAppRootForVision,\n \".uilint\",\n \"screenshots\"\n );\n if (!existsSync(screenshotsDir)) {\n mkdirSync(screenshotsDir, { recursive: true });\n }\n\n // Write the image file\n const imagePath = join(screenshotsDir, filename);\n const imageBuffer = Buffer.from(base64Data, \"base64\");\n writeFileSync(imagePath, imageBuffer);\n\n // Write JSON sidecar with metadata\n const sidecarFilename = filename.replace(/\\.png$/, \".json\");\n const sidecarPath = join(screenshotsDir, sidecarFilename);\n const sidecarData = {\n route,\n timestamp,\n filename,\n savedAt: new Date().toISOString(),\n };\n writeFileSync(sidecarPath, JSON.stringify(sidecarData, null, 2));\n\n logScreenshotSaved(filename, Math.round(imageBuffer.length / 1024));\n\n // Send success response\n sendMessage(ws, {\n type: \"screenshot:saved\",\n filename,\n path: imagePath,\n requestId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logServerError(`screenshot:error`, errorMessage);\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n }\n}\n\n/**\n * Handle client disconnect\n */\nfunction handleDisconnect(ws: WebSocket): void {\n // Remove from all subscriptions\n for (const [filePath, subscribers] of subscriptions.entries()) {\n for (const entry of subscribers) {\n if (entry.ws === ws) {\n subscribers.delete(entry);\n }\n }\n if (subscribers.size === 0) {\n subscriptions.delete(filePath);\n // Stop watching if no subscribers\n if (fileWatcher) {\n fileWatcher.unwatch(filePath);\n }\n }\n }\n // Update subscription count in dashboard\n updateSubscriptionCount(subscriptions.size);\n}\n\n/**\n * Handle file change\n */\nfunction handleFileChange(filePath: string): void {\n const subscribers = subscriptions.get(filePath);\n if (!subscribers || subscribers.size === 0) return;\n\n // Invalidate cache\n cache.delete(filePath);\n fastCache.delete(filePath);\n semanticCache.delete(filePath);\n\n // Notify subscribers\n for (const { ws, clientFilePath } of subscribers) {\n sendMessage(ws, { type: \"file:changed\", filePath: clientFilePath });\n }\n}\n\n/**\n * Handle coverage-final.json file change - broadcast new coverage data to all clients\n */\nfunction handleCoverageFileChange(filePath: string): void {\n try {\n const coverageData = JSON.parse(readFileSync(filePath, \"utf-8\"));\n logCoverageResult(Object.keys(coverageData).length);\n\n broadcast({\n type: \"coverage:result\",\n coverage: coverageData,\n timestamp: Date.now(),\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logServerError(`Failed to read coverage data`, errorMessage);\n broadcast({\n type: \"coverage:error\",\n error: `Failed to read coverage: ${errorMessage}`,\n });\n }\n}\n\n// In-memory config store (runtime only, for broadcasting to clients)\nconst configStore = new Map<string, unknown>();\n\n// Track connected clients for broadcasting\nconst connectedClientsSet = new Set<WebSocket>();\n\n/**\n * Broadcast config update to all connected clients\n */\nfunction broadcastConfigUpdate(key: string, value: unknown): void {\n const message: ConfigUpdateMessage = { type: \"config:update\", key, value };\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n/**\n * Handle config:set message\n */\nfunction handleConfigSet(key: string, value: unknown): void {\n configStore.set(key, value);\n logConfigSet(key, value);\n broadcastConfigUpdate(key, value);\n}\n\n/**\n * Broadcast rule config change to all connected clients\n */\nfunction broadcastRuleConfigChange(\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>\n): void {\n const message: RuleConfigChangedMessage = {\n type: \"rule:config:changed\",\n ruleId,\n severity,\n options,\n };\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n/**\n * Broadcast a message to all connected clients\n */\nfunction broadcast(message: ServerMessage): void {\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n// Duplicates indexing state\nlet isIndexing = false;\nlet reindexTimeout: NodeJS.Timeout | null = null;\nconst pendingIndexChanges = new Set<string>();\n\n/**\n * Build or update the duplicates index\n * Runs incrementally - very fast if no files changed\n */\nasync function buildDuplicatesIndex(appRoot: string): Promise<void> {\n if (isIndexing) {\n // Already indexing, skip\n return;\n }\n\n isIndexing = true;\n setPluginStatus(\"duplicates\", \"processing\", \"Preparing index...\");\n startBackgroundTask(\n \"duplicates-index\",\n \"Duplicates Index\",\n \"Waiting for Ollama...\"\n );\n\n // Acquire exclusive access to Ollama to avoid model contention\n const release = await acquireOllamaMutex(\"duplicates\");\n\n broadcast({ type: \"duplicates:indexing:start\" });\n broadcast({\n type: \"plugin:operation:start\",\n pluginId: \"duplicates\",\n operationName: \"indexing\",\n message: \"Building duplicates index...\",\n });\n\n try {\n const { indexDirectory } = await import(\"uilint-duplicates\");\n const result = await indexDirectory(appRoot, {\n onProgress: (message: string, current?: number, total?: number) => {\n // Update dashboard progress\n const progress =\n total && total > 0 ? Math.round(((current || 0) / total) * 100) : 0;\n updateBackgroundTaskProgress(\n \"duplicates-index\",\n progress,\n current,\n total,\n message\n );\n updatePluginProgress(\"duplicates\", progress, current, total, message);\n // Broadcast to connected clients\n broadcast({\n type: \"duplicates:indexing:progress\",\n message,\n current,\n total,\n });\n broadcast({\n type: \"plugin:operation:progress\",\n pluginId: \"duplicates\",\n operationName: \"indexing\",\n current,\n total,\n message,\n });\n },\n });\n\n const successMsg = `${result.totalChunks} chunks (${result.added} added, ${\n result.modified\n } modified, ${result.deleted} deleted) in ${(\n result.duration / 1000\n ).toFixed(1)}s`;\n completeBackgroundTask(\"duplicates-index\", `Index complete: ${successMsg}`);\n setPluginStatus(\"duplicates\", \"complete\", successMsg);\n setTimeout(() => setPluginStatus(\"duplicates\", \"idle\"), 3000);\n broadcast({\n type: \"duplicates:indexing:complete\",\n added: result.added,\n modified: result.modified,\n deleted: result.deleted,\n totalChunks: result.totalChunks,\n duration: result.duration,\n });\n broadcast({\n type: \"plugin:operation:complete\",\n pluginId: \"duplicates\",\n operationName: \"indexing\",\n message: successMsg,\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n completeBackgroundTask(\"duplicates-index\", undefined, msg);\n setPluginStatus(\"duplicates\", \"error\", msg);\n setTimeout(() => setPluginStatus(\"duplicates\", \"idle\"), 3000);\n broadcast({ type: \"duplicates:indexing:error\", error: msg });\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"duplicates\",\n operationName: \"indexing\",\n error: msg,\n });\n } finally {\n release();\n isIndexing = false;\n }\n}\n\n/**\n * Schedule a debounced re-index when source files change\n */\nfunction scheduleReindex(appRoot: string, filePath: string): void {\n // Only reindex for source files\n if (!/\\.(tsx?|jsx?)$/.test(filePath)) return;\n\n pendingIndexChanges.add(filePath);\n\n if (reindexTimeout) clearTimeout(reindexTimeout);\n reindexTimeout = setTimeout(async () => {\n const count = pendingIndexChanges.size;\n pendingIndexChanges.clear();\n logServerInfo(`${count} file(s) changed, updating index...`);\n await buildDuplicatesIndex(appRoot);\n }, 2000); // 2 second debounce\n}\n\n// Coverage preparation state\nlet isPreparingCoverage = false;\n\n/**\n * Check if require-test-coverage rule is enabled in ESLint config\n */\nfunction isCoverageRuleEnabled(appRoot: string): boolean {\n const eslintConfigPath = findEslintConfigFile(appRoot);\n if (!eslintConfigPath) return false;\n\n const ruleConfigs = readRuleConfigsFromConfig(eslintConfigPath);\n const coverageConfig = ruleConfigs.get(\"require-test-coverage\");\n if (!coverageConfig) return false;\n\n // Rule is enabled if severity is not \"off\"\n return coverageConfig.severity !== \"off\";\n}\n\n/**\n * Prepare coverage data for require-test-coverage rule.\n * Runs only on startup:\n * - Installs @vitest/coverage-v8 if missing\n * - Adds coverage config to vitest.config.ts if missing\n * - Runs tests with coverage to generate coverage-final.json\n */\nasync function buildCoverageData(appRoot: string): Promise<void> {\n if (isPreparingCoverage) return;\n\n isPreparingCoverage = true;\n\n try {\n // Check if coverage rule is enabled\n if (!isCoverageRuleEnabled(appRoot)) {\n logServerInfo(\"Coverage rule not enabled, skipping preparation\");\n return;\n }\n\n // Detect current setup\n const setup = detectCoverageSetup(appRoot);\n\n // Check if preparation needed\n if (!needsCoveragePreparation(setup)) {\n logServerInfo(\"Coverage data is up-to-date\");\n return;\n }\n\n // Run preparation\n startBackgroundTask(\"coverage-prep\", \"Coverage Prep\", \"Starting...\");\n broadcast({ type: \"coverage:setup:start\" });\n\n // Check environment variables for skipping\n const skipPackageInstall = process.env.UILINT_SKIP_COVERAGE_INSTALL === \"1\";\n const skipTests = process.env.UILINT_SKIP_COVERAGE_TESTS === \"1\";\n\n const result = await prepareCoverage({\n appRoot,\n skipPackageInstall,\n skipTests,\n silent: isDashboardEnabled(),\n onProgress: (message, phase) => {\n updateBackgroundTaskProgress(\n \"coverage-prep\",\n 50,\n undefined,\n undefined,\n message\n );\n broadcast({ type: \"coverage:setup:progress\", message, phase });\n },\n });\n\n if (result.error) {\n // Continue with warning on test failures (don't block server startup)\n completeBackgroundTask(\"coverage-prep\", undefined, result.error);\n } else {\n const parts = [];\n if (result.packageAdded) parts.push(\"package installed\");\n if (result.configModified) parts.push(\"config modified\");\n if (result.testsRan) parts.push(\"tests ran\");\n if (result.coverageGenerated) parts.push(\"coverage generated\");\n\n completeBackgroundTask(\n \"coverage-prep\",\n `Coverage prepared: ${parts.join(\", \")} in ${(\n result.duration / 1000\n ).toFixed(1)}s`\n );\n }\n\n broadcast({\n type: \"coverage:setup:complete\",\n ...result,\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n completeBackgroundTask(\"coverage-prep\", undefined, msg);\n broadcast({ type: \"coverage:setup:error\", error: msg });\n } finally {\n isPreparingCoverage = false;\n }\n}\n\n/**\n * Handle rule:config:set message\n * Updates the ESLint config file and broadcasts the change to all clients\n */\nfunction handleRuleConfigSet(\n ws: WebSocket,\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>,\n requestId?: string\n): void {\n // Normalize ruleId - strip \"uilint/\" prefix if present since\n // updateRuleSeverityInConfig adds it internally\n const normalizedRuleId = ruleId.startsWith(\"uilint/\")\n ? ruleId.slice(\"uilint/\".length)\n : ruleId;\n\n logRuleConfigSet(normalizedRuleId, severity, !!options);\n\n // Find the ESLint config file\n const configPath = findEslintConfigFile(serverAppRootForVision);\n if (!configPath) {\n const error = `No ESLint config file found in ${serverAppRootForVision}`;\n logServerError(error);\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: false,\n error,\n requestId,\n });\n return;\n }\n\n // Update the config file\n let result;\n if (options && Object.keys(options).length > 0) {\n // Update severity AND options\n result = updateRuleConfigInConfig(\n configPath,\n normalizedRuleId,\n severity,\n options\n );\n } else {\n // Update severity only\n result = updateRuleSeverityInConfig(configPath, normalizedRuleId, severity);\n }\n\n if (result.success) {\n logServerInfo(`Updated uilint/${normalizedRuleId} -> ${severity}`);\n\n // Clear ESLint instance cache to pick up the new config\n eslintInstances.clear();\n eslintFastInstances.clear();\n cache.clear();\n fastCache.clear();\n semanticCache.clear();\n updateCacheCount(0);\n\n // Send success response to requesting client\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: true,\n requestId,\n });\n\n // Broadcast change to all connected clients\n broadcastRuleConfigChange(ruleId, severity, options);\n } else {\n logServerError(`Failed to update rule: ${result.error}`);\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: false,\n error: result.error,\n requestId,\n });\n }\n}\n\n/**\n * Start the WebSocket server\n */\nexport async function serve(options: ServeOptions): Promise<void> {\n const preferredPort = options.port || DEFAULT_PORT;\n\n // Determine if we should use the dashboard UI\n // Enable dashboard if TTY and not explicitly disabled\n const useDashboardUI = process.stdout.isTTY && !options.noDashboard;\n\n if (useDashboardUI) {\n enableDashboard();\n // Register all Ollama-consuming plugins with the dashboard.\n // Model names are defaults; corrected lazily via setPluginModel() when each plugin runs.\n registerPlugin(\"semantic\", \"Semantic\", \"qwen3-vl:8b-instruct\");\n registerPlugin(\"vision\", \"Vision\", \"gemma3:4b\");\n registerPlugin(\"duplicates\", \"Duplicates\", \"nomic-embed-text\");\n } else {\n disableDashboard();\n }\n\n // Load plugin ESLint rules before anything accesses the registries.\n // This triggers auto-registration of plugin rules if installed.\n const pluginManifests = await discoverPlugins();\n await loadPluginESLintRules(pluginManifests);\n\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n const appRoot = pickAppRoot({ cwd, workspaceRoot: wsRoot });\n serverAppRootForVision = appRoot;\n\n // Set workspace info in dashboard\n setWorkspaceInfo(wsRoot, appRoot, cwd);\n\n // Create file watcher\n fileWatcher = watch([], {\n persistent: true,\n ignoreInitial: true,\n });\n\n fileWatcher.on(\"change\", (path) => {\n const resolvedPath = resolve(path);\n\n // Check if coverage-final.json changed - broadcast to all clients\n if (resolvedPath.endsWith(\"coverage-final.json\")) {\n handleCoverageFileChange(resolvedPath);\n return;\n }\n\n handleFileChange(resolvedPath);\n // Also schedule re-indexing for duplicates detection\n scheduleReindex(appRoot, resolvedPath);\n });\n\n // Watch coverage-final.json for changes\n const coveragePath = join(appRoot, \"coverage\", \"coverage-final.json\");\n if (existsSync(coveragePath)) {\n fileWatcher.add(coveragePath);\n logServerInfo(`Watching coverage`, coveragePath);\n }\n\n // Find an available port (auto-increment if preferred port is in use)\n const port = await findAvailablePort(preferredPort);\n if (port !== preferredPort) {\n logServerInfo(`Port ${preferredPort} in use, using ${port}`);\n }\n\n // Create HTTP server with discovery endpoint and WebSocket upgrade\n const httpServer = createServer((req: IncomingMessage, res: ServerResponse) => {\n // CORS preflight\n if (req.method === \"OPTIONS\") {\n res.writeHead(204, {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type\",\n });\n res.end();\n return;\n }\n\n const parsedUrl = new URL(req.url ?? \"/\", `http://localhost:${port}`);\n\n if (parsedUrl.pathname === \"/_uilint/info\") {\n const probePath = parsedUrl.searchParams.get(\"probe\");\n let probeExists: boolean | undefined;\n if (probePath) {\n // Check if the probed file exists relative to appRoot\n const absolute = join(appRoot, probePath);\n probeExists = existsSync(absolute);\n }\n\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n res.end(\n JSON.stringify({\n appRoot,\n workspaceRoot: wsRoot,\n serverCwd: cwd,\n port,\n pid: process.pid,\n ...(probeExists !== undefined && { probeExists }),\n })\n );\n return;\n }\n\n res.writeHead(404);\n res.end();\n });\n\n // Create WebSocket server in noServer mode (HTTP server handles upgrade)\n const wss = new WebSocketServer({ noServer: true });\n\n httpServer.on(\"upgrade\", (request, socket, head) => {\n wss.handleUpgrade(request, socket, head, (ws) => {\n wss.emit(\"connection\", ws, request);\n });\n });\n\n // Start listening\n httpServer.listen(port, \"127.0.0.1\");\n\n // Write port file so other tools can find this server\n const portFilePath = join(appRoot, \".uilint\", \"port\");\n const uilintDir = join(appRoot, \".uilint\");\n if (!existsSync(uilintDir)) mkdirSync(uilintDir, { recursive: true });\n writeFileSync(portFilePath, String(port), \"utf-8\");\n\n /** Clean up port file on shutdown */\n function removePortFile(): void {\n try {\n unlinkSync(portFilePath);\n } catch {\n // Ignore — file may already be gone\n }\n }\n\n // WebSocket keepalive: ping all clients every 30 seconds to detect stale connections\n const PING_INTERVAL = 30_000;\n const aliveClients = new WeakSet<WebSocket>();\n const pingInterval = setInterval(() => {\n for (const ws of connectedClientsSet) {\n if (!aliveClients.has(ws)) {\n ws.terminate();\n continue;\n }\n aliveClients.delete(ws);\n if (ws.readyState === WebSocket.OPEN) {\n ws.ping();\n }\n }\n }, PING_INTERVAL);\n\n // Start building the duplicates index in the background\n // This runs incrementally - very fast if nothing changed\n buildDuplicatesIndex(appRoot).catch((err) => {\n logServerError(`Failed to build duplicates index`, err.message);\n });\n\n // Prepare coverage data for require-test-coverage rule (startup only)\n // This installs packages, modifies config, and runs tests if needed\n buildCoverageData(appRoot).catch((err) => {\n // Don't block server startup on coverage failures\n logServerWarning(`Failed to prepare coverage`, err.message);\n });\n\n wss.on(\"connection\", (ws) => {\n connectedClients += 1;\n connectedClientsSet.add(ws);\n aliveClients.add(ws);\n logClientConnect(connectedClients);\n\n // Track keepalive\n ws.on(\"pong\", () => {\n aliveClients.add(ws);\n });\n\n // Send workspace info to client on connect\n sendMessage(ws, {\n type: \"workspace:info\",\n appRoot,\n workspaceRoot: wsRoot,\n serverCwd: cwd,\n });\n\n // Send workspace capabilities (hook availability, etc.)\n const hookInfo = detectPostToolUseHook(appRoot);\n sendMessage(ws, {\n type: \"workspace:capabilities\",\n postToolUseHook: hookInfo,\n });\n if (hookInfo.enabled) {\n logServerInfo(`Post-tool-use hook detected: ${hookInfo.provider}`);\n }\n\n // Read current rule configs from ESLint config file\n const eslintConfigPath = findEslintConfigFile(appRoot);\n const currentRuleConfigs = eslintConfigPath\n ? readRuleConfigsFromConfig(eslintConfigPath)\n : new Map<\n string,\n {\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n }\n >();\n\n // Send installed rules metadata (only rules that exist in the ESLint config)\n // Include current severities from the ESLint config so UI reflects saved state\n // Use full rule IDs (uilint/...) for consistency with ESLint output\n sendMessage(ws, {\n type: \"rules:metadata\",\n rules: ruleRegistry\n .filter((rule) => currentRuleConfigs.has(rule.id))\n .map((rule) => {\n const currentConfig = currentRuleConfigs.get(rule.id);\n return {\n id: `uilint/${rule.id}`,\n name: rule.name,\n description: rule.description,\n category: rule.category,\n defaultSeverity: rule.defaultSeverity,\n currentSeverity: currentConfig?.severity,\n currentOptions: currentConfig?.options,\n docs: rule.docs,\n optionSchema: rule.optionSchema,\n defaultOptions: rule.defaultOptions,\n };\n }),\n });\n\n // Send current config state to new client\n for (const [key, value] of configStore) {\n sendMessage(ws, { type: \"config:update\", key, value });\n }\n\n ws.on(\"message\", (data) => {\n handleMessage(ws, data.toString());\n });\n\n ws.on(\"close\", () => {\n connectedClients = Math.max(0, connectedClients - 1);\n connectedClientsSet.delete(ws);\n logClientDisconnect(connectedClients);\n handleDisconnect(ws);\n });\n\n ws.on(\"error\", (error) => {\n logServerError(`WebSocket error`, error.message);\n });\n });\n\n wss.on(\"error\", (error) => {\n logServerError(`Server error`, error.message);\n });\n\n // Set server as running in dashboard\n setServerRunning(port);\n\n // Render dashboard or keep server running\n if (useDashboardUI) {\n // Dynamic import to avoid loading Ink in non-TTY environments\n const { renderDashboard } = await import(\"./serve/dashboard/render.js\");\n const { waitUntilExit } = renderDashboard({\n onQuit: () => {\n clearInterval(pingInterval);\n wss.close();\n httpServer.close();\n fileWatcher?.close();\n removePortFile();\n },\n onRebuildIndex: () => {\n buildDuplicatesIndex(appRoot);\n },\n });\n\n // Wait for dashboard to exit\n await waitUntilExit();\n } else {\n // Keep the server running in non-TTY mode\n await new Promise<void>((resolve) => {\n process.on(\"SIGINT\", () => {\n logServerInfo(\"Shutting down...\");\n clearInterval(pingInterval);\n wss.close();\n httpServer.close();\n fileWatcher?.close();\n removePortFile();\n resolve();\n });\n });\n }\n}\n","/**\n * Dashboard logger adapter\n *\n * Provides logging functions that either update the dashboard store\n * or fall back to console logging for non-TTY environments.\n */\n\nimport { getDashboardStore } from \"./store.js\";\nimport type { ActivityType, ActivityCategory, PluginId, PluginLifecycle } from \"./types.js\";\nimport pc from \"picocolors\";\n\n/**\n * Derive a coarse category from an activity type for log filtering.\n */\nfunction deriveCategory(\n type: ActivityType,\n isError?: boolean\n): ActivityCategory {\n if (isError || type === \"error\") return \"errors\";\n if (type === \"warning\") return \"errors\";\n if (type.startsWith(\"vision:\")) return \"vision\";\n if (type.startsWith(\"semantic:\")) return \"semantic\";\n if (type.startsWith(\"lint:\")) return \"lint\";\n return \"system\";\n}\n\n// Simple console logging functions that work in any environment (including non-TTY)\n// These use direct console.log instead of @clack/prompts which can suppress output\nfunction consoleInfo(message: string): void {\n console.log(pc.blue(\"i\") + \" \" + message);\n}\n\nfunction consoleSuccess(message: string): void {\n console.log(pc.green(\"\\u2713\") + \" \" + message);\n}\n\nfunction consoleWarning(message: string): void {\n console.log(pc.yellow(\"\\u26A0\") + \" \" + message);\n}\n\nfunction consoleError(message: string): void {\n console.log(pc.red(\"\\u2717\") + \" \" + message);\n}\n\nlet useDashboard = false;\n\n/**\n * Enable dashboard mode (disables console logging)\n */\nexport function enableDashboard(): void {\n useDashboard = true;\n}\n\n/**\n * Disable dashboard mode (enables console logging)\n */\nexport function disableDashboard(): void {\n useDashboard = false;\n}\n\n/**\n * Check if dashboard mode is enabled\n */\nexport function isDashboardEnabled(): boolean {\n return useDashboard;\n}\n\n/**\n * Log an activity to the dashboard or console\n */\nexport function logActivity(\n type: ActivityType,\n message: string,\n detail?: string,\n isError?: boolean,\n isWarning?: boolean\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n const category = deriveCategory(type, isError);\n store.addActivity({ type, message, detail, isError, isWarning, category });\n } else {\n // Fall back to console logging\n const prefix = `${pc.dim(\"[ws]\")} `;\n if (isError) {\n consoleError(prefix + message + (detail ? `\\n ${detail}` : \"\"));\n } else if (isWarning) {\n consoleWarning(prefix + message + (detail ? `\\n ${detail}` : \"\"));\n } else {\n consoleInfo(prefix + message + (detail ? `\\n ${detail}` : \"\"));\n }\n }\n}\n\n/**\n * Log a lint operation\n */\nexport function logLint(filePath: string, requestId?: string): void {\n const msg = filePath + (requestId ? ` (req ${requestId})` : \"\");\n logActivity(\"lint:file\", msg);\n}\n\n/**\n * Log a lint completion\n */\nexport function logLintDone(\n filePath: string,\n issueCount: number,\n elapsedMs: number\n): void {\n logActivity(\n \"lint:done\",\n `${filePath} \\u2192 ${issueCount} issue(s) (${elapsedMs}ms)`\n );\n}\n\n/**\n * Log a file subscription\n */\nexport function logSubscribe(filePath: string): void {\n logActivity(\"subscribe\", filePath);\n}\n\n/**\n * Log a cache invalidation\n */\nexport function logCacheInvalidate(filePath?: string): void {\n logActivity(\"cache:invalidate\", filePath ?? \"(all)\");\n}\n\n/**\n * Log a vision analysis start\n */\nexport function logVisionAnalyze(route: string, requestId?: string): void {\n const msg = route + (requestId ? ` (req ${requestId})` : \"\");\n logActivity(\"vision:analyze\", msg);\n}\n\n/**\n * Log a vision analysis completion\n */\nexport function logVisionDone(\n route: string,\n issueCount: number,\n elapsedMs: number\n): void {\n logActivity(\n \"vision:done\",\n `${route} \\u2192 ${issueCount} issue(s) (${elapsedMs}ms)`\n );\n}\n\n/**\n * Log a vision check\n */\nexport function logVisionCheck(requestId?: string): void {\n logActivity(\"vision:check\", requestId ? `(req ${requestId})` : \"\");\n}\n\n/**\n * Log a semantic analysis start\n */\nexport function logSemanticAnalyze(\n filePath: string,\n requestId?: string\n): void {\n const msg = filePath + (requestId ? ` (req ${requestId})` : \"\");\n logActivity(\"semantic:analyze\", msg);\n}\n\n/**\n * Log a semantic analysis completion\n */\nexport function logSemanticDone(\n filePath: string,\n issueCount: number,\n elapsedMs: number\n): void {\n logActivity(\n \"semantic:done\",\n `${filePath} \\u2192 ${issueCount} issue(s) (${elapsedMs}ms)`\n );\n}\n\n/**\n * Log a semantic analysis skip (cache hit, rule disabled, missing styleguide, etc.)\n */\nexport function logSemanticSkipped(filePath: string, reason: string): void {\n logActivity(\"semantic:skip\", `${filePath} \\u2014 ${reason}`);\n}\n\n/**\n * Log a config set operation\n */\nexport function logConfigSet(key: string, value: unknown): void {\n logActivity(\"config:set\", `${key} = ${JSON.stringify(value)}`);\n}\n\n/**\n * Log a rule config set operation\n */\nexport function logRuleConfigSet(\n ruleId: string,\n severity: string,\n hasOptions: boolean\n): void {\n logActivity(\n \"rule:config:set\",\n `${ruleId} \\u2192 ${severity}${hasOptions ? \" (with options)\" : \"\"}`\n );\n}\n\n/**\n * Log a screenshot save\n */\nexport function logScreenshotSave(route: string, requestId?: string): void {\n const msg = route + (requestId ? ` (req ${requestId})` : \"\");\n logActivity(\"screenshot:save\", msg);\n}\n\n/**\n * Log a screenshot saved\n */\nexport function logScreenshotSaved(filename: string, sizeKb: number): void {\n logActivity(\"screenshot:saved\", `${filename} (${sizeKb}kb)`);\n}\n\n/**\n * Log a coverage request\n */\nexport function logCoverageRequest(): void {\n logActivity(\"coverage:request\", \"\");\n}\n\n/**\n * Log a coverage result\n */\nexport function logCoverageResult(fileCount: number): void {\n logActivity(\"coverage:result\", `${fileCount} files`);\n}\n\n/**\n * Log a file change notification\n */\nexport function logFileChanged(filePath: string): void {\n logActivity(\"file:changed\", filePath);\n}\n\n/**\n * Log a client connection\n */\nexport function logClientConnect(totalClients: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.incrementClients();\n store.addActivity({\n type: \"client:connect\",\n message: `(${totalClients} total)`,\n });\n } else {\n consoleInfo(`Client connected (${totalClients} total)`);\n }\n}\n\n/**\n * Log a client disconnection\n */\nexport function logClientDisconnect(totalClients: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.decrementClients();\n store.addActivity({\n type: \"client:disconnect\",\n message: `(${totalClients} total)`,\n });\n } else {\n consoleInfo(`Client disconnected (${totalClients} total)`);\n }\n}\n\n/**\n * Log an error\n */\nexport function logServerError(message: string, detail?: string): void {\n logActivity(\"error\", message, detail, true);\n}\n\n/**\n * Log a warning\n */\nexport function logServerWarning(message: string, detail?: string): void {\n logActivity(\"warning\", message, detail, false, true);\n}\n\n/**\n * Log an info message\n */\nexport function logServerInfo(message: string, detail?: string): void {\n logActivity(\"info\", message, detail);\n}\n\n/**\n * Set workspace info in dashboard\n */\nexport function setWorkspaceInfo(\n workspaceRoot: string,\n appRoot: string,\n serverCwd: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setWorkspace({ workspaceRoot, appRoot, serverCwd });\n } else {\n consoleInfo(`Workspace root: ${pc.dim(workspaceRoot)}`);\n consoleInfo(`App root: ${pc.dim(appRoot)}`);\n consoleInfo(`Server cwd: ${pc.dim(serverCwd)}`);\n }\n}\n\n/**\n * Set server as running\n */\nexport function setServerRunning(port: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setPort(port);\n store.setRunning(true);\n } else {\n consoleSuccess(\n `UILint WebSocket server running on ${pc.cyan(`ws://localhost:${port}`)}`\n );\n consoleInfo(\"Press Ctrl+C to stop\");\n }\n}\n\n/**\n * Update subscription count\n */\nexport function updateSubscriptionCount(count: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.updateStats({ subscriptions: count });\n }\n}\n\n/**\n * Update cache entry count\n */\nexport function updateCacheCount(count: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setCacheEntries(count);\n }\n}\n\n/**\n * Background task management\n */\nexport function startBackgroundTask(\n id: string,\n name: string,\n message?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setBackgroundTask({\n id,\n name,\n status: \"running\",\n progress: 0,\n message,\n });\n } else {\n consoleInfo(`${pc.blue(name)}...`);\n }\n}\n\nexport function updateBackgroundTaskProgress(\n id: string,\n progress: number,\n current?: number,\n total?: number,\n message?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.updateBackgroundTaskProgress(id, progress, current, total, message);\n } else if (message) {\n if (current !== undefined && total !== undefined) {\n consoleInfo(` ${message} (${current}/${total})`);\n } else {\n consoleInfo(` ${message}`);\n }\n }\n}\n\nexport function completeBackgroundTask(\n id: string,\n successMessage?: string,\n error?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.completeBackgroundTask(id, error);\n } else {\n if (error) {\n consoleError(`Failed: ${error}`);\n } else if (successMessage) {\n consoleSuccess(successMessage);\n }\n }\n}\n\n/**\n * Log a rule internal/sentinel error.\n *\n * Sentinel errors are internal failures from rules with fallible backends\n * (e.g. LLM unavailable, index not built). They are filtered from client\n * results and only shown in the dashboard/server logs.\n */\nexport function logRuleInternalError(\n ruleId: string,\n filePath: string,\n detail: string\n): void {\n logActivity(\"error\", `Rule error [${ruleId}] ${filePath}`, detail, true);\n}\n\n// ============================================================================\n// Plugin status (Ollama-consuming plugins)\n// ============================================================================\n\n/**\n * Register a plugin with the dashboard. Call once during server startup.\n */\nexport function registerPlugin(\n id: PluginId,\n name: string,\n model: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.registerPlugin(id, name, model);\n } else {\n consoleInfo(`Plugin registered: ${name} (${model})`);\n }\n}\n\n/**\n * Update a plugin's lifecycle status in the dashboard.\n */\nexport function setPluginStatus(\n id: PluginId,\n status: PluginLifecycle,\n message?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setPluginState(id, {\n status,\n message,\n error: status === \"error\" ? message : undefined,\n // Clear progress on terminal states\n ...(status === \"idle\" || status === \"complete\" || status === \"error\"\n ? { progress: undefined, current: undefined, total: undefined }\n : {}),\n });\n } else if (status === \"error\") {\n consoleError(`Plugin ${id}: ${message}`);\n }\n}\n\n/**\n * Update a plugin's progress during an operation.\n */\nexport function updatePluginProgress(\n id: PluginId,\n progress: number,\n current?: number,\n total?: number,\n message?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setPluginState(id, { progress, current, total, message });\n }\n}\n\n/**\n * Update a plugin's model name (useful when determined lazily at runtime).\n */\nexport function setPluginModel(id: PluginId, model: string): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setPluginState(id, { model });\n }\n}\n","/**\n * Shared ESLint Utilities\n *\n * Common functions for ESLint integration, JSX parsing, and data-loc mapping.\n * Extracted from serve.ts to be reusable across commands.\n */\n\nimport { existsSync, readFileSync } from \"fs\";\n\n/** Generic AST node type. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AstNode = Record<string, any>;\nimport { createRequire } from \"module\";\nimport { dirname, resolve, relative, join } from \"path\";\nimport { findEnclosingScopeBatch } from \"../scope-extractor.js\";\n\n/**\n * JSX element span with character offsets and data-loc\n */\nexport type JsxElementSpan = {\n start: number;\n end: number;\n dataLoc: string;\n};\n\n/**\n * Lint issue structure\n */\nexport interface LintIssue {\n line: number;\n column?: number;\n message: string;\n ruleId?: string;\n dataLoc?: string;\n scopeInfo?: {\n enclosingScope: string | null;\n scopeType: \"function\" | \"arrow-function\" | \"component\" | \"hook\" | \"method\" | \"class\" | \"module\";\n parentScope?: string;\n jsxElementType?: string;\n };\n}\n\n/**\n * Known ESLint config filenames (flat + legacy).\n */\nexport const ESLINT_CONFIG_FILES = [\n // Flat config (ESLint v9+)\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n \"eslint.config.ts\",\n // Legacy config\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n];\n\n/**\n * Build an array of line start offsets for fast line/column -> offset conversion.\n */\nexport function buildLineStarts(code: string): number[] {\n const starts: number[] = [0];\n for (let i = 0; i < code.length; i++) {\n if (code.charCodeAt(i) === 10) starts.push(i + 1); // \\n\n }\n return starts;\n}\n\n/**\n * Convert line (1-indexed) and column (0-indexed) to character offset.\n */\nexport function offsetFromLineCol(\n lineStarts: number[],\n line1: number,\n col0: number,\n codeLength: number\n): number {\n const lineIndex = Math.max(0, Math.min(lineStarts.length - 1, line1 - 1));\n const base = lineStarts[lineIndex] ?? 0;\n return Math.max(0, Math.min(codeLength, base + Math.max(0, col0)));\n}\n\n/**\n * Parse JSX/TSX code and build a list of JSX element spans with data-loc values.\n * The data-loc is computed from the opening element's location.\n */\nexport function buildJsxElementSpans(\n code: string,\n dataLocFile: string\n): JsxElementSpan[] {\n // Use local require to get the TypeScript ESTree parser\n const localRequire = createRequire(import.meta.url);\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => AstNode;\n };\n\n const ast = parse(code, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n\n const spans: JsxElementSpan[] = [];\n\n function walk(node: AstNode): void {\n if (!node || typeof node !== \"object\") return;\n\n // Prefer mapping to JSXElement range so we can capture nested ownership precisely.\n if (node.type === \"JSXElement\") {\n const range = node.range as [number, number] | undefined;\n const opening = node.openingElement;\n const loc = opening?.loc?.start;\n if (\n range &&\n typeof range[0] === \"number\" &&\n typeof range[1] === \"number\" &&\n loc &&\n typeof loc.line === \"number\" &&\n typeof loc.column === \"number\"\n ) {\n const dataLoc = `${dataLocFile}:${loc.line}:${loc.column}`;\n spans.push({ start: range[0], end: range[1], dataLoc });\n }\n }\n\n for (const key of Object.keys(node)) {\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) walk(item);\n } else if (child && typeof child === \"object\") {\n walk(child);\n }\n }\n }\n\n walk(ast);\n\n // Keep spans small-first to make \"smallest containing span\" selection fast.\n spans.sort((a, b) => a.end - a.start - (b.end - b.start));\n return spans;\n}\n\n/**\n * Map an ESLint message (line/column) to the smallest containing JSX element's data-loc.\n */\nexport function mapMessageToDataLoc(params: {\n spans: JsxElementSpan[];\n lineStarts: number[];\n codeLength: number;\n messageLine1: number;\n messageCol1?: number;\n}): string | undefined {\n const col0 =\n typeof params.messageCol1 === \"number\"\n ? Math.max(0, params.messageCol1 - 1)\n : 0;\n const offset = offsetFromLineCol(\n params.lineStarts,\n params.messageLine1,\n col0,\n params.codeLength\n );\n\n // Pick the smallest JSXElement range that contains this offset.\n for (const s of params.spans) {\n if (s.start <= offset && offset < s.end) return s.dataLoc;\n }\n return undefined;\n}\n\n/**\n * Normalize path separators to forward slashes.\n */\nexport function normalizePathSlashes(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\n/**\n * Match `jsx-loc-plugin` behavior:\n * - Use a stable, project-relative path when possible, otherwise absolute.\n */\nexport function normalizeDataLocFilePath(\n absoluteFilePath: string,\n projectCwd: string\n): string {\n const abs = normalizePathSlashes(resolve(absoluteFilePath));\n const cwd = normalizePathSlashes(resolve(projectCwd));\n if (abs === cwd || abs.startsWith(cwd + \"/\")) {\n return normalizePathSlashes(relative(cwd, abs));\n }\n return abs;\n}\n\n/**\n * Find a project root directory for ESLint by walking upward from a file dir.\n */\nexport function findESLintCwd(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 30; i++) {\n for (const cfg of ESLINT_CONFIG_FILES) {\n if (existsSync(join(dir, cfg))) return dir;\n }\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\n// ESLint instances cached per detected project root\nconst eslintInstances = new Map<string, unknown>();\n\n/**\n * Get or create an ESLint instance for a project directory.\n */\nexport async function getESLintForProject(projectCwd: string): Promise<unknown> {\n const cached = eslintInstances.get(projectCwd);\n if (cached) return cached;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n const mod = req(\"eslint\");\n const ESLintCtor =\n mod?.ESLint ?? mod?.default?.ESLint ?? mod?.default ?? mod;\n if (!ESLintCtor) return null;\n\n const eslint = new ESLintCtor({ cwd: projectCwd });\n eslintInstances.set(projectCwd, eslint);\n return eslint;\n } catch {\n return null;\n }\n}\n\n/**\n * Clear the ESLint instance cache (useful for testing or config changes)\n */\nexport function clearESLintCache(): void {\n eslintInstances.clear();\n}\n\n/**\n * Lint a single file and return issues with data-loc mapping.\n */\nexport async function lintFileWithDataLoc(\n absolutePath: string,\n projectCwd: string,\n onProgress?: (phase: string) => void\n): Promise<LintIssue[]> {\n const progress = onProgress ?? (() => {});\n\n if (!existsSync(absolutePath)) {\n progress(`File not found: ${absolutePath}`);\n return [];\n }\n\n progress(`Resolving ESLint project... ${projectCwd}`);\n\n const eslint = await getESLintForProject(projectCwd);\n if (!eslint) {\n progress(\"ESLint not available\");\n return [];\n }\n\n try {\n progress(\"Running ESLint...\");\n const results = await (eslint as { lintFiles(files: string[]): Promise<Array<{ messages: Record<string, unknown>[] }>> }).lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n let spans: JsxElementSpan[] = [];\n let lineStarts: number[] = [];\n let codeLength = 0;\n let fileCode: string | null = null;\n\n try {\n progress(\"Building JSX map...\");\n fileCode = readFileSync(absolutePath, \"utf-8\");\n codeLength = fileCode.length;\n lineStarts = buildLineStarts(fileCode);\n spans = buildJsxElementSpans(fileCode, dataLocFile);\n progress(`JSX map: ${spans.length} element(s)`);\n } catch {\n // If parsing fails, we still return ESLint messages (unmapped).\n progress(\"JSX map failed (falling back to unmapped issues)\");\n spans = [];\n lineStarts = [];\n codeLength = 0;\n fileCode = null;\n }\n\n let issues: LintIssue[] = messages\n .filter((m: Record<string, unknown>) => typeof m?.message === \"string\")\n .map((m: Record<string, unknown>) => {\n const line = typeof m.line === \"number\" ? m.line : 1;\n const column = typeof m.column === \"number\" ? m.column : undefined;\n const mappedDataLoc =\n spans.length > 0 && lineStarts.length > 0 && codeLength > 0\n ? mapMessageToDataLoc({\n spans,\n lineStarts,\n codeLength,\n messageLine1: line,\n messageCol1: column,\n })\n : undefined;\n return {\n line,\n column,\n message: m.message as string,\n ruleId: typeof m.ruleId === \"string\" ? m.ruleId : undefined,\n dataLoc: mappedDataLoc,\n } satisfies LintIssue;\n });\n\n const mappedCount = issues.filter((i) => Boolean(i.dataLoc)).length;\n if (issues.length > 0) {\n progress(`Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`);\n }\n\n // Enrich issues with scope information\n if (fileCode && issues.length > 0) {\n progress(\"Extracting scope info...\");\n issues = enrichIssuesWithScopeInfo(issues, fileCode);\n const scopeCount = issues.filter((i) => Boolean(i.scopeInfo)).length;\n progress(`Enriched ${scopeCount}/${issues.length} issue(s) with scope info`);\n }\n\n return issues;\n } catch (error) {\n progress(`ESLint failed: ${error instanceof Error ? error.message : String(error)}`);\n return [];\n }\n}\n\n/**\n * Extract source snippet around a given line\n */\nexport function extractSourceSnippet(\n code: string,\n centerLine: number,\n contextLines: number = 3\n): { lines: string[]; startLine: number; endLine: number } {\n const allLines = code.split(\"\\n\");\n const startLine = Math.max(1, centerLine - contextLines);\n const endLine = Math.min(allLines.length, centerLine + contextLines);\n\n return {\n lines: allLines.slice(startLine - 1, endLine),\n startLine,\n endLine,\n };\n}\n\n/**\n * Enrich lint issues with scope information.\n *\n * Uses the scope-extractor to add context about where each issue occurs\n * in the code (function name, component name, hook, etc.). Uses batch\n * processing for efficiency when handling multiple issues in the same file.\n *\n * Gracefully degrades: if parsing fails, issues are returned without scopeInfo.\n *\n * @param issues - Array of lint issues to enrich\n * @param code - Source code of the file\n * @returns Issues with scopeInfo added (when available)\n */\nexport function enrichIssuesWithScopeInfo(\n issues: LintIssue[],\n code: string\n): LintIssue[] {\n if (issues.length === 0) {\n return issues;\n }\n\n // Extract positions from issues\n const positions = issues.map((issue) => ({\n line: issue.line,\n column: issue.column ?? 0,\n }));\n\n // Batch extract scope info for all positions\n const scopeInfos = findEnclosingScopeBatch(code, positions);\n\n // Merge scope info back into issues\n return issues.map((issue, index) => {\n const scopeInfo = scopeInfos[index];\n if (scopeInfo) {\n return { ...issue, scopeInfo };\n }\n // If scope extraction failed, return issue without scopeInfo\n return issue;\n });\n}\n","/**\n * Scope Extractor Utility\n *\n * Extracts enclosing context (function name, component name, etc.) from AST\n * based on line/column position. Used to enrich ESLint issues with context\n * about where they occur in the code.\n */\n\nimport { createRequire } from \"module\";\n\n/** Generic AST node type used throughout scope extraction. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AstNode = Record<string, any>;\n\n/**\n * Scope information extracted from AST\n */\nexport interface ScopeInfo {\n /** Name of the enclosing scope: \"handleClick\", \"Button\", \"useEffect\", etc. */\n enclosingScope: string | null;\n /** Type of scope */\n scopeType:\n | \"function\"\n | \"arrow-function\"\n | \"component\"\n | \"hook\"\n | \"method\"\n | \"class\"\n | \"module\";\n /** For nested functions, the parent scope name */\n parentScope?: string;\n /** If inside JSX, the element type (e.g., \"div\", \"Button\") */\n jsxElementType?: string;\n}\n\n/**\n * Options for scope extraction\n */\nexport interface ScopeExtractorOptions {\n /** Parser to use (defaults to \"typescript\" which handles both TS and JS) */\n parser?: \"babel\" | \"typescript\";\n}\n\n/**\n * Internal representation of a scope boundary in the AST\n */\ninterface ScopeBoundary {\n name: string | null;\n type: ScopeInfo[\"scopeType\"];\n start: number;\n end: number;\n line: number;\n column: number;\n}\n\n/**\n * Check if a name represents a React component (PascalCase)\n */\nfunction isComponentName(name: string | null): boolean {\n if (!name) return false;\n // Component names start with uppercase letter\n return /^[A-Z]/.test(name);\n}\n\n/**\n * Check if a name represents a React hook (starts with \"use\")\n */\nfunction isHookName(name: string | null): boolean {\n if (!name) return false;\n return /^use[A-Z]/.test(name);\n}\n\n/**\n * Check if a function body contains JSX return\n */\nfunction containsJsxReturn(node: AstNode): boolean {\n if (!node) return false;\n\n // Direct JSX return\n if (node.type === \"JSXElement\" || node.type === \"JSXFragment\") {\n return true;\n }\n\n // Check block body for return statements with JSX\n if (node.type === \"BlockStatement\" && node.body) {\n for (const stmt of node.body) {\n if (stmt.type === \"ReturnStatement\" && stmt.argument) {\n if (\n stmt.argument.type === \"JSXElement\" ||\n stmt.argument.type === \"JSXFragment\"\n ) {\n return true;\n }\n // Check for conditional expressions returning JSX\n if (stmt.argument.type === \"ConditionalExpression\") {\n if (\n stmt.argument.consequent?.type === \"JSXElement\" ||\n stmt.argument.consequent?.type === \"JSXFragment\" ||\n stmt.argument.alternate?.type === \"JSXElement\" ||\n stmt.argument.alternate?.type === \"JSXFragment\"\n ) {\n return true;\n }\n }\n }\n }\n }\n\n return false;\n}\n\n/**\n * Determine the scope type for a function based on its characteristics\n */\nfunction determineScopeType(\n name: string | null,\n isArrow: boolean,\n isMethod: boolean,\n returnsJsx: boolean,\n isExportDefault: boolean = false\n): ScopeInfo[\"scopeType\"] {\n if (isMethod) return \"method\";\n if (isHookName(name)) return \"hook\";\n // Export default functions returning JSX are components\n if (isExportDefault && returnsJsx) return \"component\";\n if (isComponentName(name) && returnsJsx) return \"component\";\n if (isArrow) return \"arrow-function\";\n return \"function\";\n}\n\n/**\n * Get the name from various identifier patterns\n */\nfunction getIdentifierName(node: AstNode): string | null {\n if (!node) return null;\n if (node.type === \"Identifier\") return node.name;\n if (node.type === \"PrivateIdentifier\") return `#${node.name}`;\n return null;\n}\n\n/**\n * Extract the JSX element type from a JSXElement node\n */\nfunction getJsxElementType(node: AstNode): string | null {\n if (!node || node.type !== \"JSXElement\") return null;\n const opening = node.openingElement;\n if (!opening || !opening.name) return null;\n\n const name = opening.name;\n if (name.type === \"JSXIdentifier\") return name.name;\n if (name.type === \"JSXMemberExpression\") {\n // Handle Foo.Bar\n const parts: string[] = [];\n let current = name;\n while (current) {\n if (current.type === \"JSXMemberExpression\") {\n parts.unshift(current.property.name);\n current = current.object;\n } else if (current.type === \"JSXIdentifier\") {\n parts.unshift(current.name);\n break;\n } else {\n break;\n }\n }\n return parts.join(\".\");\n }\n return null;\n}\n\n/**\n * Convert line (1-indexed) and column (0-indexed) to character offset\n */\nfunction lineColToOffset(code: string, line: number, column: number): number {\n const lines = code.split(\"\\n\");\n let offset = 0;\n for (let i = 0; i < line - 1 && i < lines.length; i++) {\n offset += lines[i].length + 1; // +1 for newline\n }\n return offset + column;\n}\n\n/**\n * Walk AST and collect all scope boundaries\n */\nfunction collectScopeBoundaries(ast: AstNode): ScopeBoundary[] {\n const boundaries: ScopeBoundary[] = [];\n\n function walk(node: AstNode, parentName: string | null = null): void {\n if (!node || typeof node !== \"object\") return;\n\n const range = node.range as [number, number] | undefined;\n const loc = node.loc;\n\n // Function Declaration: function foo() {}\n if (node.type === \"FunctionDeclaration\") {\n const name = getIdentifierName(node.id);\n const returnsJsx = containsJsxReturn(node.body);\n const scopeType = determineScopeType(name, false, false, returnsJsx);\n\n if (range && loc) {\n boundaries.push({\n name,\n type: scopeType,\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n // Walk body with this function as parent\n walk(node.body, name);\n return;\n }\n\n // Arrow Function Expression: const foo = () => {}\n if (node.type === \"ArrowFunctionExpression\") {\n // Try to get name from parent VariableDeclarator\n const name: string | null = null;\n const returnsJsx = containsJsxReturn(node.body);\n\n if (range && loc) {\n const scopeType = determineScopeType(name, true, false, returnsJsx);\n boundaries.push({\n name,\n type: scopeType,\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n walk(node.body, name || parentName);\n return;\n }\n\n // Function Expression: const foo = function() {}\n if (node.type === \"FunctionExpression\") {\n const name = getIdentifierName(node.id);\n const returnsJsx = containsJsxReturn(node.body);\n const scopeType = determineScopeType(name, false, false, returnsJsx);\n\n if (range && loc) {\n boundaries.push({\n name,\n type: scopeType,\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n walk(node.body, name || parentName);\n return;\n }\n\n // Variable Declarator with function: const foo = () => {} or const foo = function() {}\n if (node.type === \"VariableDeclarator\" && node.init) {\n const varName = getIdentifierName(node.id);\n const init = node.init;\n\n if (\n init.type === \"ArrowFunctionExpression\" ||\n init.type === \"FunctionExpression\"\n ) {\n // For named function expressions like `const handler = function processData() {}`\n // prefer the function's own name over the variable name\n const funcOwnName = getIdentifierName(init.id);\n const effectiveName = funcOwnName || varName;\n\n const returnsJsx = containsJsxReturn(init.body);\n const isArrow = init.type === \"ArrowFunctionExpression\";\n const scopeType = determineScopeType(effectiveName, isArrow, false, returnsJsx);\n\n const initRange = init.range as [number, number] | undefined;\n const initLoc = init.loc;\n\n if (initRange && initLoc) {\n // Update any existing boundary for this arrow/function to have the name\n const existing = boundaries.find(\n (b) => b.start === initRange[0] && b.end === initRange[1]\n );\n if (existing) {\n existing.name = effectiveName;\n existing.type = scopeType;\n } else {\n boundaries.push({\n name: effectiveName,\n type: scopeType,\n start: initRange[0],\n end: initRange[1],\n line: initLoc.start.line,\n column: initLoc.start.column,\n });\n }\n }\n\n walk(init.body, effectiveName);\n return;\n }\n }\n\n // Method Definition: class methods and object methods\n if (node.type === \"MethodDefinition\" || node.type === \"Property\") {\n const isMethod =\n node.type === \"MethodDefinition\" ||\n (node.type === \"Property\" && node.method);\n\n if (isMethod && node.value) {\n const name = getIdentifierName(node.key);\n const returnsJsx = containsJsxReturn(node.value.body);\n const scopeType = determineScopeType(name, false, true, returnsJsx);\n\n if (range && loc) {\n boundaries.push({\n name,\n type: scopeType,\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n walk(node.value.body, name);\n return;\n }\n }\n\n // Class Declaration: class Foo {}\n if (node.type === \"ClassDeclaration\" || node.type === \"ClassExpression\") {\n const name = getIdentifierName(node.id);\n\n if (range && loc) {\n boundaries.push({\n name,\n type: \"class\",\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n // Walk class body\n if (node.body) {\n walk(node.body, name);\n }\n return;\n }\n\n // Export default function/class\n if (node.type === \"ExportDefaultDeclaration\" && node.declaration) {\n const decl = node.declaration;\n\n if (decl.type === \"FunctionDeclaration\") {\n // Named export default: export default function Foo() {}\n const name = getIdentifierName(decl.id);\n const returnsJsx = containsJsxReturn(decl.body);\n // Pass isExportDefault=true for anonymous export defaults returning JSX\n const scopeType = determineScopeType(name, false, false, returnsJsx, !name);\n\n const declRange = decl.range as [number, number] | undefined;\n const declLoc = decl.loc;\n\n if (declRange && declLoc) {\n boundaries.push({\n name: name || \"default\",\n type: scopeType,\n start: declRange[0],\n end: declRange[1],\n line: declLoc.start.line,\n column: declLoc.start.column,\n });\n }\n\n walk(decl.body, name || \"default\");\n return;\n }\n\n if (decl.type === \"ClassDeclaration\") {\n // The class declaration itself will be visited\n walk(decl, parentName);\n return;\n }\n\n // Anonymous export default function/arrow\n if (\n decl.type === \"FunctionExpression\" ||\n decl.type === \"ArrowFunctionExpression\"\n ) {\n const funcOwnName = getIdentifierName(decl.id);\n const name = funcOwnName || \"default\";\n const returnsJsx = containsJsxReturn(decl.body);\n const isArrow = decl.type === \"ArrowFunctionExpression\";\n // Pass isExportDefault=true for anonymous export defaults returning JSX\n const scopeType = determineScopeType(name, isArrow, false, returnsJsx, !funcOwnName);\n\n const declRange = decl.range as [number, number] | undefined;\n const declLoc = decl.loc;\n\n if (declRange && declLoc) {\n boundaries.push({\n name,\n type: scopeType,\n start: declRange[0],\n end: declRange[1],\n line: declLoc.start.line,\n column: declLoc.start.column,\n });\n }\n\n walk(decl.body, name);\n return;\n }\n }\n\n // Walk all children\n for (const key of Object.keys(node)) {\n if (key === \"loc\" || key === \"range\" || key === \"parent\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n walk(item, parentName);\n }\n } else if (child && typeof child === \"object\" && child.type) {\n walk(child, parentName);\n }\n }\n }\n\n walk(ast);\n return boundaries;\n}\n\n/**\n * Find the innermost JSX element containing a position\n */\nfunction findContainingJsxElement(ast: AstNode, offset: number): string | null {\n // Use object wrapper to help TypeScript understand closure mutation\n const result: { innermost: { type: string; size: number } | null } = {\n innermost: null,\n };\n\n function walk(node: AstNode): void {\n if (!node || typeof node !== \"object\") return;\n\n if (node.type === \"JSXElement\") {\n const range = node.range as [number, number] | undefined;\n if (range && range[0] <= offset && offset < range[1]) {\n const size = range[1] - range[0];\n if (!result.innermost || size < result.innermost.size) {\n const elementType = getJsxElementType(node);\n if (elementType) {\n result.innermost = { type: elementType, size };\n }\n }\n }\n }\n\n for (const key of Object.keys(node)) {\n if (key === \"loc\" || key === \"range\" || key === \"parent\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) walk(item);\n } else if (child && typeof child === \"object\" && child.type) {\n walk(child);\n }\n }\n }\n\n walk(ast);\n return result.innermost?.type ?? null;\n}\n\n/**\n * Find the enclosing scope for a given line/column position in source code.\n *\n * @param source - The source code to parse\n * @param line - Line number (1-indexed)\n * @param column - Column number (0-indexed)\n * @param options - Parser options\n * @returns Scope information or null if at module level\n */\nexport function findEnclosingScope(\n source: string,\n line: number,\n column: number,\n _options?: ScopeExtractorOptions\n): ScopeInfo | null {\n // Use typescript-estree parser (handles both TS and JS/JSX)\n const localRequire = createRequire(import.meta.url);\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => AstNode;\n };\n\n let ast: AstNode;\n try {\n ast = parse(source, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n } catch {\n return null;\n }\n\n const offset = lineColToOffset(source, line, column);\n const boundaries = collectScopeBoundaries(ast);\n\n // Find all scopes containing this offset, sorted by size (smallest first)\n const containingScopes = boundaries\n .filter((b) => b.start <= offset && offset < b.end)\n .sort((a, b) => a.end - a.start - (b.end - b.start));\n\n // Find JSX element context\n const jsxElementType = findContainingJsxElement(ast, offset);\n\n // If no containing scope, return module scope\n if (containingScopes.length === 0) {\n return {\n enclosingScope: null,\n scopeType: \"module\",\n jsxElementType: jsxElementType ?? undefined,\n };\n }\n\n const innermost = containingScopes[0];\n const parent = containingScopes.length > 1 ? containingScopes[1] : null;\n\n // Handle anonymous functions\n const scopeName = innermost.name || \"anonymous\";\n\n return {\n enclosingScope: scopeName,\n scopeType: innermost.type,\n parentScope: parent?.name ?? undefined,\n jsxElementType: jsxElementType ?? undefined,\n };\n}\n\n/**\n * Batch extract scope information for multiple positions in the same source.\n * More efficient than calling findEnclosingScope multiple times.\n *\n * @param source - The source code to parse\n * @param positions - Array of {line, column} positions\n * @param options - Parser options\n * @returns Array of scope information (null for errors)\n */\nexport function findEnclosingScopeBatch(\n source: string,\n positions: Array<{ line: number; column: number }>,\n _options?: ScopeExtractorOptions\n): Array<ScopeInfo | null> {\n // Use typescript-estree parser\n const localRequire = createRequire(import.meta.url);\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => AstNode;\n };\n\n let ast: AstNode;\n try {\n ast = parse(source, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n } catch {\n return positions.map(() => null);\n }\n\n const boundaries = collectScopeBoundaries(ast);\n\n return positions.map(({ line, column }) => {\n const offset = lineColToOffset(source, line, column);\n\n // Find all scopes containing this offset, sorted by size (smallest first)\n const containingScopes = boundaries\n .filter((b) => b.start <= offset && offset < b.end)\n .sort((a, b) => a.end - a.start - (b.end - b.start));\n\n // Find JSX element context\n const jsxElementType = findContainingJsxElement(ast, offset);\n\n // If no containing scope, return module scope\n if (containingScopes.length === 0) {\n return {\n enclosingScope: null,\n scopeType: \"module\" as const,\n jsxElementType: jsxElementType ?? undefined,\n };\n }\n\n const innermost = containingScopes[0];\n const parent = containingScopes.length > 1 ? containingScopes[1] : null;\n\n // Handle anonymous functions\n const scopeName = innermost.name || \"anonymous\";\n\n return {\n enclosingScope: scopeName,\n scopeType: innermost.type,\n parentScope: parent?.name ?? undefined,\n jsxElementType: jsxElementType ?? undefined,\n };\n });\n}\n","/**\n * Vision command - analyze a screenshot with Ollama vision models\n *\n * Mirrors the \"scan\" command UX (debug flags, JSON/text output), but operates on images.\n */\n\nimport { dirname, resolve, join } from \"path\";\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n} from \"fs\";\nimport { ensureOllamaReady, STYLEGUIDE_PATHS } from \"uilint-core/node\";\n\n// Vision module is dynamically imported to avoid hard dependency on uilint-vision.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _visionNodeModule: any = null;\nasync function loadVisionModule() {\n if (_visionNodeModule) return _visionNodeModule;\n try {\n _visionNodeModule = await import(\"uilint-vision/node\");\n return _visionNodeModule;\n } catch {\n return null;\n }\n}\n// Re-declare the key types locally so the rest of the file compiles\n// without importing from uilint-vision.\ntype ElementManifest = {\n id: string;\n text: string;\n dataLoc: string;\n rect: { x: number; y: number; width: number; height: number };\n tagName: string;\n role?: string;\n instanceCount?: number;\n};\ntype VisionIssue = {\n elementText: string;\n dataLoc?: string;\n message: string;\n category: string;\n severity: string;\n suggestion?: string;\n};\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n note,\n logInfo,\n logWarning,\n logError,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface VisionOptions {\n /** Path to a screenshot image (png/jpg). */\n image?: string;\n /** Path to a `.json` sidecar containing { manifest, ... } (as saved by the Next screenshot route). */\n sidecar?: string;\n /** Inline manifest JSON string (array). */\n manifestJson?: string;\n /** Path to a manifest JSON file (array). */\n manifestFile?: string;\n /** Explicit route label (used in output and debug dump). */\n route?: string;\n /** Path to style guide file or project dir (same semantics as scan.ts). */\n styleguide?: string;\n /** Output format */\n output?: \"text\" | \"json\";\n /** List available `.uilint/screenshots/*.json` sidecars and exit */\n list?: boolean;\n /** Optional screenshots directory to list from (default: nearest `.uilint/screenshots`) */\n screenshotsDir?: string;\n /** Stream model output/progress (text mode only; JSON output stays non-streaming) */\n stream?: boolean;\n /** Ollama base URL (default: http://localhost:11434) */\n baseUrl?: string;\n /** Vision model override (default: UILINT_DEFAULT_VISION_MODEL) */\n model?: string;\n /** Enable debug logging (stderr only; never pollutes JSON stdout). Can also be enabled via UILINT_DEBUG=1 */\n debug?: boolean;\n /** Print full prompt/styleguide (can be very large). Can also be enabled via UILINT_DEBUG_FULL=1 */\n debugFull?: boolean;\n /** Dump payload to file. Can also be set via UILINT_DEBUG_DUMP=/path */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: VisionOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: VisionOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: VisionOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nfunction findScreenshotsDirUpwards(startDir: string): string | null {\n let dir = startDir;\n for (let i = 0; i < 20; i++) {\n const candidate = join(dir, \".uilint\", \"screenshots\");\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\ntype ScreenshotSidecarSummary = {\n path: string;\n filename: string;\n timestamp?: number;\n route?: string;\n issueCount?: number;\n};\n\nfunction listScreenshotSidecars(dirPath: string): ScreenshotSidecarSummary[] {\n if (!existsSync(dirPath)) return [];\n const entries = readdirSync(dirPath)\n .filter((f) => f.endsWith(\".json\"))\n .map((f) => join(dirPath, f));\n\n const out: ScreenshotSidecarSummary[] = [];\n for (const p of entries) {\n try {\n const json = loadJsonFile<Record<string, unknown>>(p);\n const analysisResult = json?.analysisResult as Record<string, unknown> | undefined;\n const issues = Array.isArray(json?.issues)\n ? json.issues\n : analysisResult?.issues;\n out.push({\n path: p,\n filename:\n (json?.filename as string) || (json?.screenshotFile as string) || p.split(\"/\").pop() || p,\n timestamp:\n typeof json?.timestamp === \"number\" ? json.timestamp : undefined,\n route: typeof json?.route === \"string\" ? json.route : undefined,\n issueCount: Array.isArray(issues) ? issues.length : undefined,\n });\n } catch {\n out.push({\n path: p,\n filename: p.split(\"/\").pop() || p,\n });\n }\n }\n\n // Newest first (fallback to filename sort)\n out.sort((a, b) => {\n const at = a.timestamp ?? 0;\n const bt = b.timestamp ?? 0;\n if (at !== bt) return bt - at;\n return b.path.localeCompare(a.path);\n });\n\n return out;\n}\n\nfunction readImageAsBase64(imagePath: string): {\n base64: string;\n sizeBytes: number;\n} {\n const bytes = readFileSync(imagePath);\n return { base64: bytes.toString(\"base64\"), sizeBytes: bytes.byteLength };\n}\n\nfunction loadJsonFile<T>(filePath: string): T {\n const raw = readFileSync(filePath, \"utf-8\");\n return JSON.parse(raw) as T;\n}\n\nfunction formatIssuesText(issues: VisionIssue[]): string {\n if (issues.length === 0) return \"No vision issues found.\\n\";\n return (\n issues\n .map((i) => {\n const sev = i.severity || \"info\";\n const cat = i.category || \"other\";\n const where = i.dataLoc ? ` (${i.dataLoc})` : \"\";\n return `- [${sev}/${cat}] ${i.message}${where}`;\n })\n .join(\"\\n\") + \"\\n\"\n );\n}\n\nexport async function vision(options: VisionOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) intro(\"Vision (Screenshot) Analysis\");\n\n // Load vision module dynamically\n const visionMod = await loadVisionModule();\n if (!visionMod) {\n logError(\"uilint-vision is not installed. Run: pnpm add uilint-vision\");\n process.exit(1);\n }\n\n const UILINT_DEFAULT_VISION_MODEL = visionMod.UILINT_DEFAULT_VISION_MODEL;\n const resolveVisionStyleGuide = visionMod.resolveVisionStyleGuide;\n const runVisionAnalysis = visionMod.runVisionAnalysis;\n const writeVisionMarkdownReport = visionMod.writeVisionMarkdownReport;\n\n try {\n const projectPath = process.cwd();\n\n // List mode (no analysis)\n if (options.list) {\n const base =\n (options.screenshotsDir\n ? resolvePathSpecifier(options.screenshotsDir, projectPath)\n : null) || findScreenshotsDirUpwards(projectPath);\n\n if (!base) {\n if (isJsonOutput) {\n printJSON({ screenshotsDir: null, sidecars: [] });\n } else {\n logWarning(\n \"No `.uilint/screenshots` directory found (walked up from cwd).\"\n );\n }\n await flushLangfuse();\n return;\n }\n\n const sidecars = listScreenshotSidecars(base);\n if (isJsonOutput) {\n printJSON({ screenshotsDir: base, sidecars });\n } else {\n logInfo(`Screenshots dir: ${pc.dim(base)}`);\n if (sidecars.length === 0) {\n process.stdout.write(\"No sidecars found.\\n\");\n } else {\n process.stdout.write(\n sidecars\n .map((s, idx) => {\n const stamp = s.timestamp\n ? new Date(s.timestamp).toLocaleString()\n : \"(no timestamp)\";\n const route = s.route ? ` ${pc.dim(s.route)}` : \"\";\n const count =\n typeof s.issueCount === \"number\"\n ? ` ${pc.dim(`(${s.issueCount} issues)`)}`\n : \"\";\n return `${idx === 0 ? \"*\" : \"-\"} ${s.path}${pc.dim(\n ` — ${stamp}`\n )}${route}${count}`;\n })\n .join(\"\\n\") + \"\\n\"\n );\n process.stdout.write(\n pc.dim(\n `Tip: run \\`uilint vision --sidecar <path>\\` (the newest is marked with \"*\").\\n`\n )\n );\n }\n }\n await flushLangfuse();\n return;\n }\n\n // Resolve inputs\n const imagePath = options.image\n ? resolvePathSpecifier(options.image, projectPath)\n : undefined;\n const sidecarPath = options.sidecar\n ? resolvePathSpecifier(options.sidecar, projectPath)\n : undefined;\n const manifestFilePath = options.manifestFile\n ? resolvePathSpecifier(options.manifestFile, projectPath)\n : undefined;\n\n if (!imagePath && !sidecarPath) {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", issues: [] });\n } else {\n logError(\"No input provided. Use --image or --sidecar.\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n if (imagePath && !existsSync(imagePath)) {\n throw new Error(`Image not found: ${imagePath}`);\n }\n if (sidecarPath && !existsSync(sidecarPath)) {\n throw new Error(`Sidecar not found: ${sidecarPath}`);\n }\n if (manifestFilePath && !existsSync(manifestFilePath)) {\n throw new Error(`Manifest file not found: ${manifestFilePath}`);\n }\n\n // Load sidecar if provided (supports the Next screenshot route payload)\n const sidecar = sidecarPath\n ? loadJsonFile<{\n filename?: string;\n screenshotFile?: string;\n route?: string;\n manifest?: unknown;\n analysisResult?: unknown;\n issues?: unknown;\n }>(sidecarPath)\n : null;\n\n const routeLabel =\n options.route ||\n (typeof sidecar?.route === \"string\" ? sidecar.route : undefined) ||\n (sidecarPath ? `(from ${sidecarPath})` : \"(unknown)\");\n\n // Manifest sources (priority: --manifest-json > --manifest-file > sidecar.manifest)\n let manifest: ElementManifest[] | null = null;\n if (options.manifestJson) {\n manifest = JSON.parse(options.manifestJson) as ElementManifest[];\n } else if (manifestFilePath) {\n manifest = loadJsonFile<ElementManifest[]>(manifestFilePath);\n } else if (sidecar && Array.isArray(sidecar.manifest)) {\n manifest = sidecar.manifest as ElementManifest[];\n }\n\n if (!manifest || manifest.length === 0) {\n throw new Error(\n \"No manifest provided. Supply --manifest-json, --manifest-file, or a sidecar JSON with a `manifest` array.\"\n );\n }\n\n // Styleguide resolution: same semantics as scan.ts (path/file/dir), with a good default start dir.\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n const startPath =\n (imagePath ?? sidecarPath ?? manifestFilePath ?? undefined) || undefined;\n\n {\n const resolved = await resolveVisionStyleGuide({\n projectPath,\n styleguide: options.styleguide,\n startDir: startPath ? dirname(startPath) : projectPath,\n pathResolver: resolvePathSpecifier,\n });\n styleGuide = resolved.styleGuide;\n styleguideLocation = resolved.styleguideLocation;\n }\n\n if (styleguideLocation && styleGuide) {\n if (!isJsonOutput)\n logSuccess(`Using styleguide: ${pc.dim(styleguideLocation)}`);\n } else if (!styleGuide && !isJsonOutput) {\n logWarning(\"No styleguide found\");\n note(\n [\n `Searched in: ${options.styleguide || projectPath}`,\n \"\",\n \"Looked for:\",\n ...STYLEGUIDE_PATHS.map((p) => ` • ${p}`),\n \"\",\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n ].join(\"\\n\"),\n \"Missing Styleguide\"\n );\n }\n\n debugLog(dbg, \"Vision input (high-level)\", {\n imagePath: imagePath ?? null,\n sidecarPath: sidecarPath ?? null,\n manifestFile: manifestFilePath ?? null,\n manifestElements: manifest.length,\n route: routeLabel,\n styleguideLocation,\n styleGuideLength: styleGuide ? styleGuide.length : 0,\n });\n\n // Prepare Ollama (ensure model exists & server up)\n const visionModel = options.model || UILINT_DEFAULT_VISION_MODEL;\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady({\n model: visionModel,\n baseUrl: options.baseUrl,\n });\n });\n } else {\n await ensureOllamaReady({ model: visionModel, baseUrl: options.baseUrl });\n }\n const prepEndNs = nsNow();\n\n // Load screenshot bytes\n const resolvedImagePath =\n imagePath ||\n (() => {\n // If sidecar contains screenshotFile and is relative, resolve relative to the sidecar dir.\n const screenshotFile =\n typeof sidecar?.screenshotFile === \"string\"\n ? sidecar.screenshotFile\n : typeof sidecar?.filename === \"string\"\n ? sidecar.filename\n : undefined;\n if (!screenshotFile) return null;\n const baseDir = sidecarPath ? dirname(sidecarPath) : projectPath;\n const abs = resolve(baseDir, screenshotFile);\n return abs;\n })();\n\n if (!resolvedImagePath) {\n throw new Error(\n \"No image path could be resolved. Provide --image or a sidecar with `screenshotFile`/`filename`.\"\n );\n }\n if (!existsSync(resolvedImagePath)) {\n throw new Error(`Image not found: ${resolvedImagePath}`);\n }\n\n const { base64, sizeBytes } = readImageAsBase64(resolvedImagePath);\n debugLog(dbg, \"Image loaded\", {\n imagePath: resolvedImagePath,\n sizeBytes,\n base64Length: base64.length,\n });\n\n if (dbgFull && styleGuide) {\n debugLog(dbg, \"Styleguide (full)\", styleGuide);\n } else if (dbg && styleGuide) {\n debugLog(dbg, \"Styleguide (preview)\", preview(styleGuide, 800));\n }\n\n // Run analysis (optionally show streaming progress in text mode)\n let result: {\n issues: VisionIssue[];\n analysisTime: number;\n prompt?: string;\n rawResponse?: string;\n } | null = null;\n\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n\n if (isJsonOutput) {\n result = await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n pathResolver: resolvePathSpecifier,\n });\n } else {\n if (options.stream) {\n let lastStatus = \"\";\n let printedAnyText = false;\n let inThinking = false;\n result = await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!printedAnyText) {\n printedAnyText = true;\n console.error(pc.dim(\"[vision] streaming:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n inThinking = true;\n } else if (!inThinking) {\n process.stderr.write(pc.dim(\"\\n\\nThinking:\\n\"));\n inThinking = true;\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n\n // If we got a text delta, stream it directly\n if (delta) {\n if (!printedAnyText) {\n printedAnyText = true;\n console.error(pc.dim(\"[vision] streaming:\"));\n }\n if (inThinking) {\n process.stderr.write(pc.dim(\"\\n\\nAnswer:\\n\"));\n inThinking = false;\n }\n // Stream raw text to stderr to avoid corrupting stdout.\n process.stderr.write(delta);\n return;\n }\n\n // Fallback to status output (latest line / heartbeats).\n const line = (latestLine || \"\").trim();\n if (!line || line === lastStatus) return;\n lastStatus = line;\n console.error(pc.dim(\"[vision]\"), line);\n },\n pathResolver: resolvePathSpecifier,\n });\n } else {\n result = await withSpinner(\n \"Analyzing screenshot with vision model\",\n async (s) => {\n return await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta))\n firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n const maxLen = 60;\n const displayLine =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(displayLine || \"...\")}`);\n },\n pathResolver: resolvePathSpecifier,\n });\n }\n );\n }\n }\n\n const analysisEndNs = nsNow();\n\n const issues = result?.issues ?? [];\n\n if (isJsonOutput) {\n printJSON({\n route: routeLabel,\n model: visionModel,\n issues,\n analysisTime: result?.analysisTime ?? 0,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n });\n } else {\n logInfo(`Route: ${pc.dim(routeLabel)}`);\n logInfo(`Model: ${pc.dim(visionModel)}`);\n process.stdout.write(formatIssuesText(issues));\n\n // Pretty timings (TTY-only so we don't clutter non-interactive usage)\n if (process.stdout.isTTY) {\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n result?.analysisTime\n ? pc.dim(`(core analysisTime: ${formatMs(result.analysisTime)})`)\n : pc.dim(\"(core analysisTime: n/a)\"),\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n }\n\n // Write markdown report alongside the image (best-effort; never affects stdout JSON).\n try {\n writeVisionMarkdownReport({\n imagePath: resolvedImagePath,\n route: routeLabel,\n visionModel,\n baseUrl: options.baseUrl ?? \"http://localhost:11434\",\n analysisTimeMs: result?.analysisTime ?? 0,\n prompt: result?.prompt ?? null,\n rawResponse: result?.rawResponse ?? null,\n metadata: {\n imageSizeBytes: sizeBytes,\n styleguideLocation,\n },\n });\n debugLog(dbg, \"Wrote .vision.md report alongside image\");\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write .vision.md report\",\n e instanceof Error ? e.message : e\n );\n }\n\n // Exit with error code if issues found\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (options.output === \"json\") {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(\n error instanceof Error ? error.message : \"Vision analysis failed\"\n );\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n await flushLangfuse();\n}\n","/**\n * UILint Config Command\n *\n * Allows setting configuration options that are broadcast to connected clients.\n *\n * Usage:\n * uilint config set position <x,y> - Set floating icon position\n * uilint config set position top-center - Use preset position\n * uilint config get position - Get current position (from server)\n * uilint config set rule <ruleId>:<severity> [optionsJson] - Set rule config\n *\n * Examples:\n * uilint config set rule consistent-dark-mode:warn\n * uilint config set rule no-prop-drilling-depth:error '{\"maxDepth\":3}'\n * uilint config set rule no-mixed-component-libraries:off\n */\n\nimport { WebSocket } from \"ws\";\nimport { logInfo, logSuccess, logError, pc } from \"../utils/prompts.js\";\n\nexport interface ConfigOptions {\n port?: number;\n}\n\n/** Parse position value from string */\nfunction parsePosition(\n value: string\n): { x: number; y: number } | { preset: string } | null {\n // Check for presets\n const presets: Record<string, true> = {\n \"top-center\": true,\n \"top-left\": true,\n \"top-right\": true,\n \"bottom-center\": true,\n \"bottom-left\": true,\n \"bottom-right\": true,\n };\n\n if (presets[value]) {\n return { preset: value };\n }\n\n // Try to parse as x,y coordinates\n const match = value.match(/^(\\d+),(\\d+)$/);\n if (match) {\n return { x: parseInt(match[1], 10), y: parseInt(match[2], 10) };\n }\n\n return null;\n}\n\n/** Convert preset to position (approximate, client will recalculate) */\nfunction presetToPosition(preset: string): { x: number; y: number } {\n // These are approximate defaults - the client can recalculate based on viewport\n const positions: Record<string, { x: number; y: number }> = {\n \"top-center\": { x: 500, y: 30 },\n \"top-left\": { x: 60, y: 30 },\n \"top-right\": { x: 940, y: 30 },\n \"bottom-center\": { x: 500, y: 700 },\n \"bottom-left\": { x: 60, y: 700 },\n \"bottom-right\": { x: 940, y: 700 },\n };\n return positions[preset] || { x: 500, y: 30 };\n}\n\n/** Parse rule configuration from value string */\nfunction parseRuleConfig(value: string): {\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n} | null {\n // Format: <ruleId>:<severity>\n const match = value.match(/^([^:]+):(error|warn|off)$/);\n if (!match) {\n return null;\n }\n return {\n ruleId: match[1],\n severity: match[2] as \"error\" | \"warn\" | \"off\",\n };\n}\n\n/** Parse options JSON string */\nfunction parseOptionsJson(optionsStr: string | undefined): Record<string, unknown> | undefined {\n if (!optionsStr) {\n return undefined;\n }\n try {\n const parsed = JSON.parse(optionsStr);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return undefined;\n }\n return parsed as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Send config message via WebSocket\n */\nasync function sendConfigMessage(\n port: number,\n key: string,\n value: unknown\n): Promise<boolean> {\n return new Promise((resolve) => {\n const url = `ws://localhost:${port}`;\n const ws = new WebSocket(url);\n let resolved = false;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n ws.close();\n resolve(false);\n }\n }, 5000);\n\n ws.on(\"open\", () => {\n const message = JSON.stringify({ type: \"config:set\", key, value });\n ws.send(message);\n\n // Give the server time to process and broadcast\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n ws.close();\n resolve(true);\n }\n }, 100);\n });\n\n ws.on(\"error\", () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve(false);\n }\n });\n });\n}\n\n/**\n * Send rule config message via WebSocket and wait for result\n */\nasync function sendRuleConfigMessage(\n port: number,\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>\n): Promise<{ success: boolean; error?: string }> {\n return new Promise((resolve) => {\n const url = `ws://localhost:${port}`;\n const ws = new WebSocket(url);\n let resolved = false;\n const requestId = `cli-${Date.now()}`;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n ws.close();\n resolve({ success: false, error: \"Request timed out\" });\n }\n }, 10000);\n\n ws.on(\"open\", () => {\n const message = JSON.stringify({\n type: \"rule:config:set\",\n ruleId,\n severity,\n options,\n requestId,\n });\n ws.send(message);\n });\n\n ws.on(\"message\", (data: Buffer) => {\n try {\n const msg = JSON.parse(data.toString());\n if (msg.type === \"rule:config:result\" && msg.requestId === requestId) {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n ws.close();\n resolve({\n success: msg.success,\n error: msg.error,\n });\n }\n }\n } catch {\n // Ignore parse errors\n }\n });\n\n ws.on(\"error\", () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve({ success: false, error: \"Connection error\" });\n }\n });\n });\n}\n\n/**\n * Handle config set command\n */\nasync function handleSet(\n key: string,\n value: string,\n port: number,\n extraArg?: string\n): Promise<void> {\n switch (key) {\n case \"position\": {\n const parsed = parsePosition(value);\n if (!parsed) {\n logError(\n `Invalid position value: ${value}\\n` +\n `Expected format: x,y (e.g., 100,50) or preset (top-center, top-left, etc.)`\n );\n process.exit(1);\n }\n\n let position: { x: number; y: number };\n if (\"preset\" in parsed) {\n position = presetToPosition(parsed.preset);\n logInfo(`Using preset \"${parsed.preset}\" → (${position.x}, ${position.y})`);\n } else {\n position = parsed;\n }\n\n const success = await sendConfigMessage(\n port,\n \"floatingIconPosition\",\n position\n );\n\n if (success) {\n logSuccess(\n `Set floating icon position to (${position.x}, ${position.y})`\n );\n } else {\n logError(\n `Failed to set position. Is the server running?\\n` +\n `Start it with: ${pc.bold(\"npx uilint serve\")}`\n );\n process.exit(1);\n }\n break;\n }\n\n case \"rule\": {\n const parsed = parseRuleConfig(value);\n if (!parsed) {\n logError(\n `Invalid rule config: ${value}\\n` +\n `Expected format: <ruleId>:<severity>\\n` +\n ` severity: error, warn, or off\\n\\n` +\n `Examples:\\n` +\n ` uilint config set rule consistent-dark-mode:warn\\n` +\n ` uilint config set rule no-prop-drilling-depth:error '{\"maxDepth\":3}'`\n );\n process.exit(1);\n }\n\n // Parse optional options JSON from extra argument\n const options = parseOptionsJson(extraArg);\n if (extraArg && !options) {\n logError(\n `Invalid options JSON: ${extraArg}\\n` +\n `Expected a valid JSON object, e.g., '{\"maxDepth\": 3}'`\n );\n process.exit(1);\n }\n\n logInfo(\n `Setting rule \"${parsed.ruleId}\" to ${parsed.severity}` +\n (options ? ` with options: ${JSON.stringify(options)}` : \"\")\n );\n\n const result = await sendRuleConfigMessage(\n port,\n parsed.ruleId,\n parsed.severity,\n options\n );\n\n if (result.success) {\n logSuccess(\n `Rule \"${parsed.ruleId}\" set to ${parsed.severity}` +\n (options ? ` with options` : \"\")\n );\n } else {\n logError(\n result.error ||\n `Failed to set rule config. Is the server running?\\n` +\n `Start it with: ${pc.bold(\"npx uilint serve\")}`\n );\n process.exit(1);\n }\n break;\n }\n\n default:\n logError(`Unknown config key: ${key}`);\n logInfo(`Available keys: position, rule`);\n process.exit(1);\n }\n}\n\n/**\n * Handle config get command\n */\nasync function handleGet(key: string, _port: number): Promise<void> {\n switch (key) {\n case \"position\":\n logInfo(\n `Position is stored in the browser's localStorage.\\n` +\n `To view it, check your browser's dev tools:\\n` +\n ` localStorage.getItem(\"uilint:floatingIconPosition\")`\n );\n break;\n\n default:\n logError(`Unknown config key: ${key}`);\n logInfo(`Available keys: position`);\n process.exit(1);\n }\n}\n\n/**\n * Config command entry point\n */\nexport async function config(\n action: string,\n key: string,\n value?: string,\n extraArg?: string,\n options: ConfigOptions = {}\n): Promise<void> {\n const port = options.port || 9234;\n\n switch (action) {\n case \"set\":\n if (!value) {\n logError(`Missing value for config set ${key}`);\n process.exit(1);\n }\n await handleSet(key, value, port, extraArg);\n break;\n\n case \"get\":\n await handleGet(key, port);\n break;\n\n default:\n logError(`Unknown action: ${action}`);\n logInfo(`Usage: uilint config <set|get> <key> [value] [options]`);\n process.exit(1);\n }\n}\n","/**\n * Duplicates command - semantic code duplicate detection\n */\n\nimport { Command } from \"commander\";\nimport { indexCommand } from \"./index-cmd.js\";\nimport { findCommand } from \"./find.js\";\nimport { searchCommand } from \"./search.js\";\nimport { similarCommand } from \"./similar.js\";\n\nexport function createDuplicatesCommand(): Command {\n const duplicates = new Command(\"duplicates\")\n .description(\"Semantic code duplicate detection\");\n\n // Add subcommands\n duplicates.addCommand(indexCommand());\n duplicates.addCommand(findCommand());\n duplicates.addCommand(searchCommand());\n duplicates.addCommand(similarCommand());\n\n return duplicates;\n}\n","/**\n * Index command - build or update the semantic duplicates index\n */\n\nimport { Command } from \"commander\";\n\nimport chalk from \"chalk\";\nimport ora from \"ora\";\n\nexport function indexCommand(): Command {\n return new Command(\"index\")\n .description(\"Build or update the semantic duplicates index\")\n .option(\"--force\", \"Rebuild index from scratch\")\n .option(\"--model <name>\", \"Embedding model (default: nomic-embed-text)\")\n .option(\n \"--exclude <glob>\",\n \"Exclude patterns (repeatable)\",\n (val: string, prev: string[]) => [...prev, val],\n [] as string[]\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n const { indexDirectory } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n let spinner: ReturnType<typeof ora> | undefined;\n if (!isJson) {\n spinner = ora(\"Initializing indexer...\").start();\n }\n\n try {\n const result = await indexDirectory(projectRoot, {\n force: options.force,\n model: options.model,\n exclude: options.exclude,\n onProgress: (message, current, total) => {\n if (spinner) {\n if (current && total) {\n spinner.text = `${message} (${current}/${total})`;\n } else {\n spinner.text = message;\n }\n }\n },\n });\n\n if (isJson) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n spinner?.succeed(chalk.green(\"Index complete\"));\n console.log();\n console.log(chalk.bold(\"Index Statistics:\"));\n console.log(` Files added: ${result.added}`);\n console.log(` Files modified: ${result.modified}`);\n console.log(` Files deleted: ${result.deleted}`);\n console.log(` Total chunks: ${result.totalChunks}`);\n console.log(` Duration: ${(result.duration / 1000).toFixed(2)}s`);\n }\n } catch (error) {\n if (spinner) {\n spinner.fail(chalk.red(\"Index failed\"));\n }\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Find command - find semantic duplicate groups\n */\n\nimport { Command } from \"commander\";\nimport { relative } from \"path\";\nimport chalk from \"chalk\";\nimport type { ChunkKind } from \"uilint-duplicates\";\n\nexport function findCommand(): Command {\n return new Command(\"find\")\n .description(\"Find semantic duplicate groups in the codebase\")\n .option(\n \"--threshold <n>\",\n \"Similarity threshold 0-1 (default: 0.75)\",\n parseFloat\n )\n .option(\"--min-size <n>\", \"Minimum group size (default: 2)\", parseInt)\n .option(\"--kind <type>\", \"Filter: component, hook, function\")\n .option(\n \"--confidence <level>\",\n \"Minimum confidence: high, medium, low (default: low)\"\n )\n .option(\"--no-structural\", \"Disable structural similarity boost\")\n .option(\"--same-file\", \"Include duplicates within the same file\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n const { findDuplicates } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n try {\n const groups = await findDuplicates({\n path: projectRoot,\n threshold: options.threshold,\n minGroupSize: options.minSize,\n kind: options.kind as ChunkKind | undefined,\n confidenceLevel: options.confidence as \"high\" | \"medium\" | \"low\" | undefined,\n useStructuralBoost: options.structural !== false,\n includeSameFile: options.sameFile ?? false,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ groups }, null, 2));\n return;\n }\n\n if (groups.length === 0) {\n console.log(chalk.green(\"No semantic duplicates found.\"));\n return;\n }\n\n console.log(\n chalk.bold(\n `Found ${groups.length} duplicate group${groups.length > 1 ? \"s\" : \"\"}:\\n`\n )\n );\n\n groups.forEach((group, idx) => {\n const similarity = Math.round(group.avgSimilarity * 100);\n const confidenceEmoji =\n group.confidence === \"high\" ? \"🔴\" :\n group.confidence === \"medium\" ? \"🟡\" : \"🟢\";\n const confidenceColor =\n group.confidence === \"high\" ? chalk.red :\n group.confidence === \"medium\" ? chalk.yellow : chalk.green;\n\n console.log(\n chalk.bold(\n `${confidenceEmoji} Duplicate Group ${idx + 1} ` +\n `(${confidenceColor(`${similarity}% - ${group.confidence} confidence`)}, ` +\n `${group.members.length} occurrences):`\n )\n );\n\n group.members.forEach((member) => {\n const relPath = relative(projectRoot, member.filePath);\n const location = `${relPath}:${member.startLine}-${member.endLine}`;\n const name = member.name || \"(anonymous)\";\n const score =\n member.score === 1.0\n ? \"\"\n : chalk.dim(` (${Math.round(member.score * 100)}%)`);\n console.log(` ${chalk.cyan(location.padEnd(50))} ${name}${score}`);\n });\n\n const suggestion =\n group.confidence === \"high\"\n ? `Strongly recommend consolidating into a single reusable ${group.kind}`\n : group.confidence === \"medium\"\n ? `Consider extracting shared logic into a reusable ${group.kind}`\n : `Optional: Review if a common abstraction makes sense`;\n\n console.log(chalk.dim(` → ${suggestion}\\n`));\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Search command - semantic search for code\n */\n\nimport { Command } from \"commander\";\nimport { relative } from \"path\";\nimport chalk from \"chalk\";\n\nexport function searchCommand(): Command {\n return new Command(\"search\")\n .description(\"Semantic search for similar code\")\n .argument(\"<query>\", \"Search query (natural language)\")\n .option(\"-k, --top <n>\", \"Number of results (default: 10)\", parseInt)\n .option(\"--threshold <n>\", \"Minimum similarity (default: 0.5)\", parseFloat)\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (query: string, options) => {\n const { searchSimilar } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n try {\n const results = await searchSimilar(query, {\n path: projectRoot,\n top: options.top,\n threshold: options.threshold,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ results }, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow(\"No matching code found.\"));\n return;\n }\n\n console.log(chalk.bold(`Found ${results.length} matching results:\\n`));\n\n results.forEach((result, idx) => {\n const relPath = relative(projectRoot, result.filePath);\n const location = `${relPath}:${result.startLine}-${result.endLine}`;\n const name = result.name || \"(anonymous)\";\n const score = Math.round(result.score * 100);\n const kindLabel = result.kind.padEnd(10);\n\n console.log(\n `${chalk.dim(`${idx + 1}.`)} ${chalk.cyan(location)}`\n );\n console.log(\n ` ${chalk.dim(kindLabel)} ${chalk.bold(name)} ${chalk.green(`(${score}% similar)`)}`\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Similar command - find code similar to a specific location\n */\n\nimport { Command } from \"commander\";\nimport { relative, resolve, isAbsolute } from \"path\";\nimport chalk from \"chalk\";\n\nexport function similarCommand(): Command {\n return new Command(\"similar\")\n .description(\"Find code similar to a specific location\")\n .argument(\"<location>\", \"File location in format file:line (e.g., src/Button.tsx:15)\")\n .option(\"-k, --top <n>\", \"Number of results (default: 10)\", parseInt)\n .option(\"--threshold <n>\", \"Minimum similarity (default: 0.7)\", parseFloat)\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (location: string, options) => {\n const { findSimilarAtLocation } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n // Parse location\n const colonIdx = location.lastIndexOf(\":\");\n if (colonIdx === -1) {\n const message = \"Invalid location format. Use file:line (e.g., src/Button.tsx:15)\";\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n\n const filePart = location.slice(0, colonIdx);\n const linePart = location.slice(colonIdx + 1);\n const line = parseInt(linePart, 10);\n\n if (isNaN(line)) {\n const message = `Invalid line number: ${linePart}`;\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n\n const filePath = isAbsolute(filePart)\n ? filePart\n : resolve(projectRoot, filePart);\n\n try {\n const results = await findSimilarAtLocation({\n path: projectRoot,\n filePath,\n line,\n top: options.top,\n threshold: options.threshold ?? 0.7,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ results }, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow(\"No similar code found.\"));\n return;\n }\n\n console.log(\n chalk.bold(\n `Found ${results.length} similar code locations to ${relative(projectRoot, filePath)}:${line}:\\n`\n )\n );\n\n results.forEach((result, idx) => {\n const relPath = relative(projectRoot, result.filePath);\n const locationStr = `${relPath}:${result.startLine}-${result.endLine}`;\n const name = result.name || \"(anonymous)\";\n const score = Math.round(result.score * 100);\n const kindLabel = result.kind.padEnd(10);\n\n console.log(\n `${chalk.dim(`${idx + 1}.`)} ${chalk.cyan(locationStr)}`\n );\n console.log(\n ` ${chalk.dim(kindLabel)} ${chalk.bold(name)} ${chalk.green(`(${score}% similar)`)}`\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Build Manifest Command\n *\n * Generates a static lint manifest for production deployment.\n *\n * Usage:\n * uilint build-manifest [options]\n *\n * Options:\n * -o, --output <path> Output path (default: .uilint/manifest.json)\n * --include <patterns...> File patterns to include (default: **\\/*.tsx **\\/*.jsx)\n * --exclude <patterns...> File patterns to exclude\n * --no-snippets Exclude source code snippets\n * --context-lines <n> Number of context lines for snippets (default: 3)\n * --pretty Pretty-print JSON output\n */\n\nimport { Command } from \"commander\";\nimport { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport { dirname, resolve } from \"path\";\nimport { generateManifest } from \"./generator.js\";\nimport { logInfo, logSuccess, logError, pc } from \"../../utils/prompts.js\";\nimport { discoverPlugins, loadPluginESLintRules } from \"../../utils/plugin-loader.js\";\n\n/**\n * Create the build-manifest command\n */\nexport function createManifestCommand(): Command {\n const cmd = new Command(\"build-manifest\")\n .description(\"Generate static lint manifest for production deployment\")\n .option(\"-o, --output <path>\", \"Output path for manifest\", \".uilint/manifest.json\")\n .option(\"--include <patterns...>\", \"File patterns to include\")\n .option(\"--exclude <patterns...>\", \"File patterns to exclude\")\n .option(\"--no-snippets\", \"Exclude source code snippets from manifest\")\n .option(\"--context-lines <n>\", \"Number of context lines for snippets\", \"3\")\n .option(\"--pretty\", \"Pretty-print JSON output\")\n .option(\"--quiet\", \"Suppress progress output\")\n .action(async (options) => {\n await buildManifest({\n output: options.output,\n include: options.include,\n exclude: options.exclude,\n includeSnippets: options.snippets !== false,\n contextLines: parseInt(options.contextLines, 10),\n pretty: options.pretty,\n quiet: options.quiet,\n });\n });\n\n return cmd;\n}\n\ninterface BuildManifestOptions {\n output: string;\n include?: string[];\n exclude?: string[];\n includeSnippets: boolean;\n contextLines: number;\n pretty?: boolean;\n quiet?: boolean;\n}\n\n/**\n * Build manifest action\n */\nasync function buildManifest(options: BuildManifestOptions): Promise<void> {\n // Load plugin ESLint rules so plugin rules appear in the registry\n const pluginManifests = await discoverPlugins();\n await loadPluginESLintRules(pluginManifests);\n\n const startTime = Date.now();\n const outputPath = resolve(process.cwd(), options.output);\n\n if (!options.quiet) {\n logInfo(`Building lint manifest...`);\n logInfo(`Output: ${pc.dim(outputPath)}`);\n }\n\n try {\n const manifest = await generateManifest({\n cwd: process.cwd(),\n include: options.include,\n exclude: options.exclude,\n includeSnippets: options.includeSnippets,\n snippetContextLines: options.contextLines,\n onProgress: options.quiet\n ? undefined\n : (message, current, total) => {\n if (current !== undefined && total !== undefined) {\n logInfo(` [${current}/${total}] ${message}`);\n } else {\n logInfo(` ${message}`);\n }\n },\n });\n\n // Ensure output directory exists\n const outputDir = dirname(outputPath);\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Write manifest\n const json = options.pretty\n ? JSON.stringify(manifest, null, 2)\n : JSON.stringify(manifest);\n\n writeFileSync(outputPath, json, \"utf-8\");\n\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);\n const sizeKb = Math.round(Buffer.byteLength(json) / 1024);\n\n if (!options.quiet) {\n logSuccess(`Manifest generated in ${elapsed}s`);\n logInfo(` Files scanned: ${pc.bold(String(manifest.summary.filesScanned))}`);\n logInfo(` Files with issues: ${pc.bold(String(manifest.summary.filesWithIssues))}`);\n logInfo(` Total issues: ${pc.bold(String(manifest.summary.totalIssues))}`);\n if (manifest.summary.bySeverity.error > 0) {\n logInfo(` Errors: ${pc.red(String(manifest.summary.bySeverity.error))}`);\n }\n if (manifest.summary.bySeverity.warn > 0) {\n logInfo(` Warnings: ${pc.yellow(String(manifest.summary.bySeverity.warn))}`);\n }\n logInfo(` Output size: ${pc.dim(`${sizeKb}kb`)}`);\n\n if (manifest.commitSha) {\n logInfo(` Git commit: ${pc.dim(manifest.commitSha.substring(0, 7))}`);\n }\n if (manifest.branch) {\n logInfo(` Git branch: ${pc.dim(manifest.branch)}`);\n }\n\n logSuccess(`Wrote ${pc.cyan(options.output)}`);\n }\n\n // Exit with error code if there are errors\n if (manifest.summary.bySeverity.error > 0) {\n process.exitCode = 1;\n }\n } catch (error) {\n logError(`Failed to generate manifest: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n}\n\n// Re-export types and generator\nexport * from \"./types.js\";\nexport { generateManifest } from \"./generator.js\";\n","/**\n * Manifest Generator\n *\n * Scans all JSX/TSX files in a project and generates a static\n * lint manifest for remote/production deployments.\n */\n\nimport { readFileSync } from \"fs\";\nimport { resolve, dirname, relative } from \"path\";\nimport { glob } from \"glob\";\nimport { execSync } from \"child_process\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\nimport { ruleRegistry } from \"uilint-eslint\";\nimport { findEslintConfigFile, readRuleConfigsFromConfig } from \"../../utils/eslint-config-inject.js\";\nimport {\n findESLintCwd,\n lintFileWithDataLoc,\n extractSourceSnippet,\n normalizeDataLocFilePath,\n type LintIssue,\n} from \"../../utils/eslint-utils.js\";\nimport { findEnclosingScopeBatch } from \"../../scope-extractor.js\";\nimport type {\n LintManifest,\n ManifestFileEntry,\n ManifestIssue,\n ManifestRuleMeta,\n SourceSnippet,\n GenerateManifestOptions,\n} from \"./types.js\";\n\n/**\n * Default glob patterns for JSX/TSX files\n */\nconst DEFAULT_INCLUDE = [\"**/*.tsx\", \"**/*.jsx\"];\n\n/**\n * Default glob patterns to exclude\n */\nconst DEFAULT_EXCLUDE = [\n \"node_modules/**\",\n \"dist/**\",\n \".next/**\",\n \"build/**\",\n \"coverage/**\",\n \".uilint/**\",\n \"**/*.test.tsx\",\n \"**/*.test.jsx\",\n \"**/*.spec.tsx\",\n \"**/*.spec.jsx\",\n];\n\n/**\n * Get git information if available\n */\nfunction getGitInfo(cwd: string): { commitSha?: string; branch?: string } {\n try {\n const commitSha = execSync(\"git rev-parse HEAD\", {\n cwd,\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n\n const branch = execSync(\"git rev-parse --abbrev-ref HEAD\", {\n cwd,\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n\n return { commitSha, branch };\n } catch {\n return {};\n }\n}\n\n/**\n * Build rule metadata for the manifest\n */\nfunction buildRuleMetadata(appRoot: string): ManifestRuleMeta[] {\n // Read current rule configs from ESLint config file\n const eslintConfigPath = findEslintConfigFile(appRoot);\n const currentRuleConfigs = eslintConfigPath\n ? readRuleConfigsFromConfig(eslintConfigPath)\n : new Map<string, { severity: \"error\" | \"warn\" | \"off\"; options?: Record<string, unknown> }>();\n\n // Only include rules that are configured in the ESLint config\n // readRuleConfigsFromConfig strips the \"uilint/\" prefix, so match on bare rule.id\n return ruleRegistry\n .filter((rule) => currentRuleConfigs.has(rule.id))\n .map((rule) => {\n const currentConfig = currentRuleConfigs.get(rule.id);\n return {\n id: `uilint/${rule.id}`,\n name: rule.name,\n description: rule.description,\n category: rule.category,\n defaultSeverity: rule.defaultSeverity,\n currentSeverity: currentConfig?.severity,\n docs: rule.docs,\n optionSchema: rule.optionSchema,\n };\n });\n}\n\n/**\n * Generate a lint manifest for a project\n */\nexport async function generateManifest(\n options: GenerateManifestOptions = {}\n): Promise<LintManifest> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const include = options.include ?? DEFAULT_INCLUDE;\n const exclude = options.exclude ?? DEFAULT_EXCLUDE;\n // Default to including full source content (for production mode source display)\n const includeSource = options.includeSource ?? true;\n // Snippets are deprecated but still supported for backwards compatibility\n const includeSnippets = options.includeSnippets ?? false;\n const snippetContextLines = options.snippetContextLines ?? 3;\n const onProgress = options.onProgress ?? (() => {});\n\n onProgress(\"Finding workspace root...\");\n const workspaceRoot = findWorkspaceRoot(cwd);\n const appRoot = cwd;\n\n onProgress(\"Scanning for JSX/TSX files...\");\n\n // Find all matching files\n const files = await glob(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n nodir: true,\n });\n\n onProgress(`Found ${files.length} files to scan`);\n\n // Get git info\n const gitInfo = getGitInfo(cwd);\n\n // Build rule metadata\n const rules = buildRuleMetadata(appRoot);\n onProgress(`Loaded ${rules.length} rule definitions`);\n\n // Process each file\n const manifestFiles: ManifestFileEntry[] = [];\n let totalIssues = 0;\n let errorCount = 0;\n let warnCount = 0;\n\n for (let i = 0; i < files.length; i++) {\n const absolutePath = files[i]!;\n const relativePath = relative(cwd, absolutePath);\n\n onProgress(`Linting ${relativePath}...`, i + 1, files.length);\n\n // Find ESLint project root for this file\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n // Lint the file\n const issues = await lintFileWithDataLoc(absolutePath, projectCwd);\n\n if (issues.length === 0) continue;\n\n // Filter issues that have dataLoc\n const filteredIssues = issues.filter(\n (issue): issue is LintIssue & { dataLoc: string } => Boolean(issue.dataLoc)\n );\n\n if (filteredIssues.length === 0) continue;\n\n // Read file content for source inclusion and scope extraction\n let fileContent: string | undefined;\n let snippets: Record<string, SourceSnippet> | undefined;\n\n try {\n fileContent = readFileSync(absolutePath, \"utf-8\");\n } catch {\n // Skip source/snippets if file can't be read\n fileContent = undefined;\n }\n\n // Extract scope information for all issues in this file (optimized: parse AST once)\n let scopeInfos: Array<ReturnType<typeof findEnclosingScopeBatch>[number]> = [];\n if (fileContent) {\n try {\n const positions = filteredIssues.map((issue) => ({\n line: issue.line,\n column: issue.column ?? 0,\n }));\n scopeInfos = findEnclosingScopeBatch(fileContent, positions);\n } catch {\n // Scope extraction failed - continue without scope info\n scopeInfos = filteredIssues.map(() => null);\n }\n }\n\n // Convert to manifest format with scope info\n const manifestIssues: ManifestIssue[] = filteredIssues.map((issue, index) => ({\n line: issue.line,\n column: issue.column,\n message: issue.message,\n ruleId: issue.ruleId,\n dataLoc: issue.dataLoc,\n scopeInfo: scopeInfos[index] ?? undefined,\n }));\n\n // Include snippets if requested (deprecated, for backwards compatibility)\n if (includeSnippets && fileContent) {\n snippets = {};\n\n // Group issues by dataLoc to avoid duplicate snippets\n const issuesByDataLoc = new Map<string, ManifestIssue>();\n for (const issue of manifestIssues) {\n if (!issuesByDataLoc.has(issue.dataLoc)) {\n issuesByDataLoc.set(issue.dataLoc, issue);\n }\n }\n\n for (const [dataLoc, issue] of issuesByDataLoc) {\n snippets[dataLoc] = extractSourceSnippet(fileContent, issue.line, snippetContextLines);\n }\n }\n\n // Count by severity\n for (const issue of manifestIssues) {\n if (issue.ruleId) {\n // Check rule config for severity (rules now have full IDs)\n const rule = rules.find((r) => r.id === issue.ruleId);\n const severity = rule?.currentSeverity ?? rule?.defaultSeverity ?? \"warn\";\n if (severity === \"error\") {\n errorCount++;\n } else {\n warnCount++;\n }\n } else {\n warnCount++;\n }\n }\n\n totalIssues += manifestIssues.length;\n\n // Use the normalized relative path for the manifest\n const dataLocFilePath = normalizeDataLocFilePath(absolutePath, projectCwd);\n\n manifestFiles.push({\n filePath: dataLocFilePath,\n issues: manifestIssues,\n // Include full source content for production mode source display\n content: includeSource ? fileContent : undefined,\n // Include snippets if explicitly requested (deprecated)\n snippets: includeSnippets ? snippets : undefined,\n });\n }\n\n onProgress(`Scan complete: ${totalIssues} issues in ${manifestFiles.length} files`);\n\n return {\n version: \"1.0\",\n generatedAt: new Date().toISOString(),\n workspaceRoot,\n appRoot,\n commitSha: gitInfo.commitSha,\n branch: gitInfo.branch,\n files: manifestFiles,\n rules,\n summary: {\n filesScanned: files.length,\n filesWithIssues: manifestFiles.length,\n totalIssues,\n bySeverity: {\n error: errorCount,\n warn: warnCount,\n },\n },\n };\n}\n","/**\n * Socket CLI Command\n *\n * Provides a CLI interface for interacting with the UILint socket server.\n * Useful for testing, debugging, and scripting.\n *\n * Usage:\n * uilint socket # Start interactive REPL\n * uilint socket lint:file <path> # Lint a file\n * uilint socket vision:check # Check vision availability\n * uilint socket listen # Listen for all messages\n */\n\nimport { Command } from \"commander\";\nimport { readFileSync, existsSync } from \"fs\";\nimport chalk from \"chalk\";\nimport { createSocketClient, SocketClient } from \"./client.js\";\nimport type { ServerMessage, ElementManifest } from \"./types.js\";\n\nexport interface SocketOptions {\n port: number;\n debug: boolean;\n json: boolean;\n timeout: number;\n}\n\n/**\n * Format a message for display\n */\nfunction formatMessage(msg: ServerMessage, json: boolean): string {\n if (json) {\n return JSON.stringify(msg, null, 2);\n }\n\n switch (msg.type) {\n case \"lint:result\": {\n const lines = [`${chalk.cyan(\"lint:result\")} ${msg.filePath}`];\n if (msg.issues.length === 0) {\n lines.push(chalk.green(\" No issues found\"));\n } else {\n for (const issue of msg.issues) {\n const loc = issue.column\n ? `${issue.line}:${issue.column}`\n : `${issue.line}`;\n const rule = issue.ruleId ? chalk.dim(` [${issue.ruleId}]`) : \"\";\n lines.push(` ${chalk.yellow(loc)} ${issue.message}${rule}`);\n }\n }\n return lines.join(\"\\n\");\n }\n\n case \"vision:status\": {\n if (msg.available) {\n return `${chalk.cyan(\"vision:status\")} ${chalk.green(\"available\")} (${msg.model})`;\n }\n return `${chalk.cyan(\"vision:status\")} ${chalk.red(\"not available\")}`;\n }\n\n case \"vision:result\": {\n const lines = [\n `${chalk.cyan(\"vision:result\")} ${msg.route} (${msg.analysisTime}ms)`,\n ];\n if (msg.error) {\n lines.push(chalk.red(` Error: ${msg.error}`));\n } else if (msg.issues.length === 0) {\n lines.push(chalk.green(\" No issues found\"));\n } else {\n for (const issue of msg.issues) {\n const severity =\n issue.severity === \"error\"\n ? chalk.red(\"error\")\n : issue.severity === \"warning\"\n ? chalk.yellow(\"warn\")\n : chalk.blue(\"info\");\n lines.push(` ${severity} [${issue.category}] ${issue.message}`);\n if (issue.dataLoc) {\n lines.push(chalk.dim(` at ${issue.dataLoc}`));\n }\n }\n }\n return lines.join(\"\\n\");\n }\n\n case \"workspace:info\":\n return `${chalk.cyan(\"workspace:info\")}\\n appRoot: ${msg.appRoot}\\n workspaceRoot: ${msg.workspaceRoot}`;\n\n case \"rules:metadata\":\n return `${chalk.cyan(\"rules:metadata\")} ${msg.rules.length} rules available`;\n\n case \"source:result\":\n return `${chalk.cyan(\"source:result\")} ${msg.filePath} (${msg.totalLines} lines)`;\n\n case \"source:error\":\n return `${chalk.cyan(\"source:error\")} ${msg.filePath}: ${chalk.red(msg.error)}`;\n\n case \"coverage:result\":\n return `${chalk.cyan(\"coverage:result\")} Coverage data received`;\n\n case \"coverage:error\":\n return `${chalk.cyan(\"coverage:error\")} ${chalk.red(msg.error)}`;\n\n case \"rule:config:result\":\n if (msg.success) {\n return `${chalk.cyan(\"rule:config:result\")} ${msg.ruleId} -> ${msg.severity}`;\n }\n return `${chalk.cyan(\"rule:config:result\")} ${msg.ruleId} ${chalk.red(\"failed\")}: ${msg.error}`;\n\n case \"duplicates:indexing:start\":\n return `${chalk.cyan(\"duplicates:indexing:start\")}`;\n\n case \"duplicates:indexing:progress\":\n return `${chalk.cyan(\"duplicates:indexing:progress\")} ${msg.message}`;\n\n case \"duplicates:indexing:complete\":\n return `${chalk.cyan(\"duplicates:indexing:complete\")} ${msg.totalChunks} chunks in ${msg.duration}ms`;\n\n case \"duplicates:indexing:error\":\n return `${chalk.cyan(\"duplicates:indexing:error\")} ${chalk.red(msg.error)}`;\n\n case \"file:changed\":\n return `${chalk.cyan(\"file:changed\")} ${msg.filePath}`;\n\n case \"config:update\":\n return `${chalk.cyan(\"config:update\")} ${msg.key} = ${JSON.stringify(msg.value)}`;\n\n default:\n return `${chalk.cyan(msg.type)} ${JSON.stringify(msg)}`;\n }\n}\n\n/**\n * Run interactive REPL mode\n */\nasync function runRepl(client: SocketClient, options: SocketOptions): Promise<void> {\n const readline = await import(\"readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n prompt: chalk.green(\"uilint> \"),\n });\n\n console.log(chalk.bold(\"\\nUILint Socket REPL\"));\n console.log(\"Type 'help' for available commands, 'exit' to quit.\\n\");\n\n // Set up message handler\n client.onMessage((msg) => {\n console.log(\"\\n\" + formatMessage(msg, options.json));\n rl.prompt();\n });\n\n // Wait for initial messages\n try {\n await client.waitForWorkspaceInfo(2000);\n } catch {\n // Ignore timeout\n }\n\n rl.prompt();\n\n rl.on(\"line\", async (line) => {\n const trimmed = line.trim();\n if (!trimmed) {\n rl.prompt();\n return;\n }\n\n const [cmd, ...args] = trimmed.split(/\\s+/);\n\n try {\n switch (cmd) {\n case \"help\":\n console.log(`\nAvailable commands:\n lint:file <path> Lint a file\n lint:element <path> <dataLoc> Lint a specific element\n vision:check Check if vision is available\n vision:analyze <route> <manifestFile> [screenshotFile]\n Run vision analysis\n source:fetch <path> Fetch source code\n coverage:request Request coverage data\n rule:config <ruleId> <severity> [optionsJson]\n Set rule configuration\n config:set <key> <value> Set a config value\n subscribe <path> Subscribe to file changes\n invalidate [path] Invalidate cache\n messages Show queued messages\n clear Clear message queue\n json Toggle JSON output\n exit Exit REPL\n`);\n break;\n\n case \"lint:file\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: lint:file <path>\"));\n } else {\n const result = await client.lintFile(args[0], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"lint:element\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: lint:element <path> <dataLoc>\"));\n } else {\n const result = await client.lintElement(args[0], args[1], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"vision:check\": {\n const result = await client.visionCheck(options.timeout);\n console.log(formatMessage(result, options.json));\n break;\n }\n\n case \"vision:analyze\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: vision:analyze <route> <manifestFile> [screenshotFile]\"));\n } else {\n const manifestPath = args[1];\n if (!existsSync(manifestPath)) {\n console.log(chalk.red(`Manifest file not found: ${manifestPath}`));\n } else {\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf-8\")) as ElementManifest[];\n const params: {\n route: string;\n manifest: ElementManifest[];\n screenshotFile?: string;\n screenshot?: string;\n } = { route: args[0], manifest };\n\n if (args[2]) {\n if (existsSync(args[2])) {\n // Read as base64\n const imageBuffer = readFileSync(args[2]);\n params.screenshot = imageBuffer.toString(\"base64\");\n } else {\n console.log(chalk.red(`Screenshot file not found: ${args[2]}`));\n break;\n }\n }\n\n const result = await client.visionAnalyze(params, options.timeout);\n console.log(formatMessage(result, options.json));\n }\n }\n break;\n\n case \"source:fetch\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: source:fetch <path>\"));\n } else {\n const result = await client.fetchSource(args[0], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"coverage:request\": {\n const result = await client.requestCoverage(options.timeout);\n console.log(formatMessage(result, options.json));\n break;\n }\n\n case \"rule:config\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: rule:config <ruleId> <severity> [optionsJson]\"));\n } else {\n const severity = args[1] as \"error\" | \"warn\" | \"off\";\n const ruleOptions = args[2] ? JSON.parse(args[2]) : undefined;\n const result = await client.setRuleConfig(args[0], severity, ruleOptions, options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"config:set\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: config:set <key> <value>\"));\n } else {\n let value: unknown = args[1];\n try {\n value = JSON.parse(args[1]);\n } catch {\n // Keep as string\n }\n client.setConfig(args[0], value);\n console.log(chalk.green(`Set ${args[0]} = ${JSON.stringify(value)}`));\n }\n break;\n\n case \"subscribe\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: subscribe <path>\"));\n } else {\n client.subscribeFile(args[0]);\n console.log(chalk.green(`Subscribed to ${args[0]}`));\n }\n break;\n\n case \"invalidate\":\n client.invalidateCache(args[0]);\n console.log(chalk.green(args[0] ? `Invalidated ${args[0]}` : \"Invalidated all cache\"));\n break;\n\n case \"messages\": {\n const msgs = client.getMessages();\n if (msgs.length === 0) {\n console.log(chalk.dim(\"No queued messages\"));\n } else {\n for (const msg of msgs) {\n console.log(formatMessage(msg, options.json));\n }\n }\n break;\n }\n\n case \"clear\":\n client.clearMessages();\n console.log(chalk.green(\"Message queue cleared\"));\n break;\n\n case \"json\":\n options.json = !options.json;\n console.log(chalk.green(`JSON output ${options.json ? \"enabled\" : \"disabled\"}`));\n break;\n\n case \"exit\":\n case \"quit\":\n client.disconnect();\n rl.close();\n process.exit(0);\n break;\n\n default:\n console.log(chalk.red(`Unknown command: ${cmd}. Type 'help' for available commands.`));\n }\n } catch (err) {\n console.log(chalk.red(`Error: ${(err as Error).message}`));\n }\n\n rl.prompt();\n });\n\n rl.on(\"close\", () => {\n client.disconnect();\n process.exit(0);\n });\n}\n\n/**\n * Run listen mode (print all messages)\n */\nasync function runListen(\n client: SocketClient,\n options: SocketOptions,\n filter?: string\n): Promise<void> {\n console.log(chalk.bold(\"\\nListening for messages...\"));\n if (filter) {\n console.log(chalk.dim(`Filter: ${filter}`));\n }\n console.log(chalk.dim(\"Press Ctrl+C to stop.\\n\"));\n\n client.onMessage((msg) => {\n if (filter && !msg.type.includes(filter.replace(\"*\", \"\"))) {\n return;\n }\n console.log(formatMessage(msg, options.json));\n });\n\n // Keep running\n await new Promise(() => {});\n}\n\n/**\n * Create the socket command\n */\nexport function createSocketCommand(): Command {\n const cmd = new Command(\"socket\")\n .description(\"Interact with the UILint socket server\")\n .option(\"-p, --port <number>\", \"Socket server port\", \"9234\")\n .option(\"-d, --debug\", \"Enable debug logging\", false)\n .option(\"-j, --json\", \"Output JSON format\", false)\n .option(\"-t, --timeout <ms>\", \"Request timeout in milliseconds\", \"30000\");\n\n // Default action: start REPL\n cmd.action(async (cmdOptions) => {\n const options: SocketOptions = {\n port: parseInt(cmdOptions.port, 10),\n debug: cmdOptions.debug,\n json: cmdOptions.json,\n timeout: parseInt(cmdOptions.timeout, 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await runRepl(client, options);\n } catch (err) {\n console.error(chalk.red(`Failed to connect: ${(err as Error).message}`));\n console.error(chalk.dim(`Make sure the server is running: uilint serve -p ${options.port}`));\n process.exit(1);\n }\n });\n\n // listen subcommand\n cmd\n .command(\"listen\")\n .description(\"Listen for all messages from the server\")\n .option(\"-f, --filter <pattern>\", \"Filter messages by type pattern (e.g., lint:*, vision:*)\")\n .action(async (subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"30000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await runListen(client, options, subOptions.filter);\n } catch (err) {\n console.error(chalk.red(`Failed to connect: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // lint:file subcommand\n cmd\n .command(\"lint:file <path>\")\n .description(\"Lint a file and output results\")\n .action(async (filePath, _subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"30000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await client.waitForWorkspaceInfo(2000).catch(() => {});\n const result = await client.lintFile(filePath, options.timeout);\n console.log(formatMessage(result, options.json));\n client.disconnect();\n process.exit(result.issues.length > 0 ? 1 : 0);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // vision:check subcommand\n cmd\n .command(\"vision:check\")\n .description(\"Check if vision analysis is available\")\n .action(async (_subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n const result = await client.visionCheck(options.timeout);\n console.log(formatMessage(result, options.json));\n client.disconnect();\n process.exit(result.available ? 0 : 1);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // source:fetch subcommand\n cmd\n .command(\"source:fetch <path>\")\n .description(\"Fetch source code for a file\")\n .action(async (filePath, _subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await client.waitForWorkspaceInfo(2000).catch(() => {});\n const result = await client.fetchSource(filePath, options.timeout);\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else if (result.type === \"source:result\") {\n console.log(result.content);\n } else {\n console.error(chalk.red(`Error: ${result.error}`));\n }\n client.disconnect();\n process.exit(result.type === \"source:result\" ? 0 : 1);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // rules subcommand\n cmd\n .command(\"rules\")\n .description(\"List available rules\")\n .action(async (_subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n const metadata = await client.waitForRulesMetadata(options.timeout);\n\n if (options.json) {\n console.log(JSON.stringify(metadata.rules, null, 2));\n } else {\n console.log(chalk.bold(`\\n${metadata.rules.length} rules available:\\n`));\n for (const rule of metadata.rules) {\n const severity =\n rule.currentSeverity === \"error\"\n ? chalk.red(\"error\")\n : rule.currentSeverity === \"warn\"\n ? chalk.yellow(\"warn\")\n : chalk.dim(\"off\");\n console.log(` ${chalk.cyan(rule.id)} [${severity}]`);\n console.log(chalk.dim(` ${rule.description}`));\n }\n }\n\n client.disconnect();\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n return cmd;\n}\n\n// Re-export types and client for programmatic use\nexport { SocketClient, createSocketClient } from \"./client.js\";\nexport { SocketTestHarness, createTestHarness } from \"./test-harness.js\";\nexport type * from \"./types.js\";\n","/**\n * Socket Client\n *\n * WebSocket client for communicating with the UILint socket server.\n * Provides request/response correlation and message handling.\n */\n\nimport WebSocket from \"ws\";\nimport type {\n ClientMessage,\n ServerMessage,\n LintResultMessage,\n SourceResultMessage,\n SourceErrorMessage,\n CoverageResultMessage,\n CoverageErrorMessage,\n RuleConfigResultMessage,\n WorkspaceInfoMessage,\n RulesMetadataMessage,\n ElementManifest,\n VisionStatusMessage,\n VisionResultMessage,\n} from \"./types.js\";\n\nexport interface SocketClientOptions {\n /** WebSocket URL (default: ws://localhost:9234) */\n url?: string;\n /** Port number (convenience, overrides url) */\n port?: number;\n /** Enable debug logging */\n debug?: boolean;\n /** Connection timeout in ms (default: 10000) */\n connectTimeout?: number;\n}\n\ntype MessageHandler = (message: ServerMessage) => void;\n\ninterface PendingRequest {\n predicate: (msg: ServerMessage) => boolean;\n resolve: (msg: ServerMessage) => void;\n reject: (err: Error) => void;\n timeout: NodeJS.Timeout;\n}\n\nexport class SocketClient {\n private ws: WebSocket | null = null;\n private url: string;\n private debug: boolean;\n private connectTimeout: number;\n private connected = false;\n private connectionPromise: Promise<void> | null = null;\n private pendingRequests: PendingRequest[] = [];\n private messageQueue: ServerMessage[] = [];\n private messageHandlers: MessageHandler[] = [];\n\n constructor(options: SocketClientOptions = {}) {\n const port = options.port || 9234;\n this.url = options.url || `ws://localhost:${port}`;\n this.debug = options.debug || false;\n this.connectTimeout = options.connectTimeout || 10000;\n }\n\n /**\n * Connect to the socket server\n */\n async connect(): Promise<void> {\n if (this.connected) return;\n if (this.connectionPromise) return this.connectionPromise;\n\n this.connectionPromise = new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Connection timeout to ${this.url}`));\n }, this.connectTimeout);\n\n this.ws = new WebSocket(this.url);\n\n this.ws.on(\"open\", () => {\n clearTimeout(timeout);\n this.connected = true;\n this.log(\"Connected to\", this.url);\n resolve();\n });\n\n this.ws.on(\"message\", (data: WebSocket.Data) => {\n try {\n const message = JSON.parse(data.toString()) as ServerMessage;\n this.log(\"Received:\", message.type);\n this.handleMessage(message);\n } catch (e) {\n console.error(\"Failed to parse message:\", e);\n }\n });\n\n this.ws.on(\"error\", (err) => {\n clearTimeout(timeout);\n if (!this.connected) {\n reject(err);\n } else {\n console.error(\"WebSocket error:\", err);\n }\n });\n\n this.ws.on(\"close\", () => {\n this.connected = false;\n this.log(\"Disconnected\");\n // Reject all pending requests\n for (const req of this.pendingRequests) {\n clearTimeout(req.timeout);\n req.reject(new Error(\"Disconnected\"));\n }\n this.pendingRequests = [];\n });\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Disconnect from the server\n */\n disconnect(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n this.connected = false;\n this.connectionPromise = null;\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Add a handler for all incoming messages\n */\n onMessage(handler: MessageHandler): () => void {\n this.messageHandlers.push(handler);\n return () => {\n this.messageHandlers = this.messageHandlers.filter((h) => h !== handler);\n };\n }\n\n /**\n * Send a raw message\n */\n send(message: ClientMessage): void {\n if (!this.ws || !this.connected) {\n throw new Error(\"Not connected\");\n }\n this.log(\"Sending:\", message.type);\n this.ws.send(JSON.stringify(message));\n }\n\n /**\n * Wait for a message matching the predicate\n */\n waitFor(\n predicate: (msg: ServerMessage) => boolean,\n timeout = 30000\n ): Promise<ServerMessage> {\n // Check existing messages first\n const existing = this.messageQueue.find(predicate);\n if (existing) {\n this.messageQueue = this.messageQueue.filter((m) => m !== existing);\n return Promise.resolve(existing);\n }\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingRequests = this.pendingRequests.filter(\n (r) => r.timeout !== timeoutId\n );\n reject(new Error(`Timeout waiting for message (${timeout}ms)`));\n }, timeout);\n\n this.pendingRequests.push({\n predicate,\n resolve,\n reject,\n timeout: timeoutId,\n });\n });\n }\n\n /**\n * Generate a unique request ID\n */\n private generateRequestId(): string {\n return `cli-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n // ==========================================================================\n // High-Level API Methods\n // ==========================================================================\n\n /**\n * Wait for workspace info (sent on connect)\n */\n async waitForWorkspaceInfo(timeout = 5000): Promise<WorkspaceInfoMessage> {\n const existing = this.messageQueue.find((m) => m.type === \"workspace:info\");\n if (existing) {\n return existing as WorkspaceInfoMessage;\n }\n return (await this.waitFor(\n (msg) => msg.type === \"workspace:info\",\n timeout\n )) as WorkspaceInfoMessage;\n }\n\n /**\n * Wait for rules metadata (sent on connect)\n */\n async waitForRulesMetadata(timeout = 5000): Promise<RulesMetadataMessage> {\n const existing = this.messageQueue.find((m) => m.type === \"rules:metadata\");\n if (existing) {\n return existing as RulesMetadataMessage;\n }\n return (await this.waitFor(\n (msg) => msg.type === \"rules:metadata\",\n timeout\n )) as RulesMetadataMessage;\n }\n\n /**\n * Lint a file\n */\n async lintFile(filePath: string, timeout = 30000): Promise<LintResultMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"lint:file\", filePath, requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"lint:result\" &&\n (msg as LintResultMessage).requestId === requestId,\n timeout\n )) as LintResultMessage;\n }\n\n /**\n * Lint a specific element\n */\n async lintElement(\n filePath: string,\n dataLoc: string,\n timeout = 30000\n ): Promise<LintResultMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"lint:element\", filePath, dataLoc, requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"lint:result\" &&\n (msg as LintResultMessage).requestId === requestId,\n timeout\n )) as LintResultMessage;\n }\n\n /**\n * Check if vision analysis is available\n * Note: Vision types live in the plugin package; messages still flow through the WebSocket.\n */\n async visionCheck(timeout = 10000): Promise<VisionStatusMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"vision:check\", requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"vision:status\" &&\n (msg as VisionStatusMessage).requestId === requestId,\n timeout\n )) as VisionStatusMessage;\n }\n\n /**\n * Run vision analysis\n * Note: Vision types live in the plugin package; messages still flow through the WebSocket.\n */\n async visionAnalyze(\n params: {\n route: string;\n manifest: ElementManifest[];\n screenshot?: string;\n screenshotFile?: string;\n },\n timeout = 120000\n ): Promise<VisionResultMessage> {\n const requestId = this.generateRequestId();\n this.send({\n type: \"vision:analyze\",\n route: params.route,\n timestamp: Date.now(),\n screenshot: params.screenshot,\n screenshotFile: params.screenshotFile,\n manifest: params.manifest,\n requestId,\n });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"vision:result\" &&\n (msg as VisionResultMessage).requestId === requestId,\n timeout\n )) as VisionResultMessage;\n }\n\n /**\n * Fetch source code\n */\n async fetchSource(\n filePath: string,\n timeout = 10000\n ): Promise<SourceResultMessage | SourceErrorMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"source:fetch\", filePath, requestId });\n return (await this.waitFor(\n (msg) =>\n (msg.type === \"source:result\" || msg.type === \"source:error\") &&\n ((msg as SourceResultMessage).requestId === requestId ||\n (msg as SourceErrorMessage).requestId === requestId),\n timeout\n )) as SourceResultMessage | SourceErrorMessage;\n }\n\n /**\n * Request coverage data\n */\n async requestCoverage(\n timeout = 30000\n ): Promise<CoverageResultMessage | CoverageErrorMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"coverage:request\", requestId });\n return (await this.waitFor(\n (msg) =>\n (msg.type === \"coverage:result\" || msg.type === \"coverage:error\") &&\n ((msg as CoverageResultMessage).requestId === requestId ||\n (msg as CoverageErrorMessage).requestId === requestId),\n timeout\n )) as CoverageResultMessage | CoverageErrorMessage;\n }\n\n /**\n * Set rule configuration\n */\n async setRuleConfig(\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>,\n timeout = 10000\n ): Promise<RuleConfigResultMessage> {\n const requestId = this.generateRequestId();\n this.send({\n type: \"rule:config:set\",\n ruleId,\n severity,\n options,\n requestId,\n });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"rule:config:result\" &&\n (msg as RuleConfigResultMessage).requestId === requestId,\n timeout\n )) as RuleConfigResultMessage;\n }\n\n /**\n * Set a configuration value\n */\n setConfig(key: string, value: unknown): void {\n this.send({ type: \"config:set\", key, value });\n }\n\n /**\n * Subscribe to file changes\n */\n subscribeFile(filePath: string): void {\n this.send({ type: \"subscribe:file\", filePath });\n }\n\n /**\n * Invalidate cache\n */\n invalidateCache(filePath?: string): void {\n this.send({ type: \"cache:invalidate\", filePath });\n }\n\n /**\n * Get all queued messages\n */\n getMessages(): ServerMessage[] {\n return [...this.messageQueue];\n }\n\n /**\n * Clear message queue\n */\n clearMessages(): void {\n this.messageQueue = [];\n }\n\n private handleMessage(message: ServerMessage): void {\n // Notify all handlers\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n\n // Check if any pending request matches\n for (let i = 0; i < this.pendingRequests.length; i++) {\n const req = this.pendingRequests[i]!;\n if (req.predicate(message)) {\n clearTimeout(req.timeout);\n this.pendingRequests.splice(i, 1);\n req.resolve(message);\n return;\n }\n }\n\n // Otherwise queue it\n this.messageQueue.push(message);\n }\n\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.log(\"[SocketClient]\", ...args);\n }\n }\n}\n\n/**\n * Create a connected socket client\n */\nexport async function createSocketClient(\n options: SocketClientOptions = {}\n): Promise<SocketClient> {\n const client = new SocketClient(options);\n await client.connect();\n return client;\n}\n"],"mappings":"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","names":["Command","resolve","existsSync","formatViolationsText","sanitizeIssues","findWorkspaceRoot","resolve","resolve","existsSync","sanitizeIssues","formatViolationsText","dirname","resolve","existsSync","mkdirSync","writeFileSync","ensureOllamaReady","readStyleGuide","findStyleGuidePath","findWorkspaceRoot","findUILintStyleGuideUpwards","envTruthy","preview","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","existsSync","readStyleGuide","findUILintStyleGuideUpwards","dirname","findStyleGuidePath","findWorkspaceRoot","ensureOllamaReady","mkdirSync","writeFileSync","ensureOllamaReady","readStdin","resolve","result","ensureOllamaReady","dirname","resolve","createStyleSummary","readStyleGuide","findStyleGuidePath","ensureOllamaReady","readTailwindThemeTokens","findStyleGuidePath","readStyleGuide","dirname","resolve","readTailwindThemeTokens","ensureOllamaReady","createStyleSummary","existsSync","statSync","readFileSync","mkdirSync","writeFileSync","createRequire","dirname","resolve","relative","join","findWorkspaceRoot","pc","pc","existsSync","createRequire","dirname","resolve","join","localRequire","parse","localRequire","createRequire","parse","resolve","existsSync","join","dirname","existsSync","resolve","join","existsSync","readFileSync","eslintInstances","createRequire","buildLineStarts","offsetFromLineCol","buildJsxElementSpans","parse","mapMessageToDataLoc","ESLINT_CONFIG_FILES","findESLintCwd","dirname","normalizePathSlashes","normalizeDataLocFilePath","relative","findWorkspaceRoot","createRequire","join","normalizeDataLocFilePath","readFileSync","buildLineStarts","buildJsxElementSpans","mapMessageToDataLoc","existsSync","statSync","dirname","findESLintCwd","existsSync","dirname","readFileSync","findWorkspaceRoot","relative","OllamaClient","buildSourceScanPrompt","findESLintCwd","normalizeDataLocFilePath","join","existsSync","findWorkspaceRoot","readFileSync","normalizeDataLocFilePath","join","mkdirSync","writeFileSync","eslintInstances","resolve","dirname","resolve","join","existsSync","readFileSync","readdirSync","ensureOllamaReady","STYLEGUIDE_PATHS","envTruthy","preview","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","join","existsSync","dirname","readdirSync","readFileSync","STYLEGUIDE_PATHS","ensureOllamaReady","WebSocket","resolve","WebSocket","config","Command","chalk","Command","relative","chalk","Command","relative","chalk","Command","relative","resolve","isAbsolute","chalk","Command","readFileSync","dirname","join","Command","existsSync","mkdirSync","writeFileSync","dirname","resolve","readFileSync","resolve","dirname","relative","findWorkspaceRoot","ruleRegistry","ruleRegistry","resolve","findWorkspaceRoot","relative","dirname","readFileSync","Command","resolve","dirname","existsSync","mkdirSync","writeFileSync","Command","readFileSync","existsSync","chalk","WebSocket","resolve","chalk","existsSync","readFileSync","Command","Command","dirname","join","readFileSync","config","discoverPlugins"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/scan.ts","../src/utils/input.ts","../src/utils/path-specifiers.ts","../src/utils/llm-client.ts","../src/utils/timing.ts","../src/utils/output.ts","../src/commands/analyze.ts","../src/commands/consistency.ts","../src/commands/update.ts","../src/commands/serve.ts","../src/commands/serve/dashboard/logger.ts","../src/utils/eslint-utils.ts","../src/scope-extractor.ts","../src/commands/vision.ts","../src/commands/config.ts","../src/commands/duplicates/index.ts","../src/commands/duplicates/index-cmd.ts","../src/commands/duplicates/find.ts","../src/commands/duplicates/search.ts","../src/commands/duplicates/similar.ts","../src/commands/manifest/index.ts","../src/commands/manifest/generator.ts","../src/commands/socket/index.ts","../src/commands/socket/client.ts"],"sourcesContent":["/**\n * UILint CLI - AI-powered UI consistency checking\n */\n\nimport { Command } from \"commander\";\nimport { scan } from \"./commands/scan.js\";\nimport { analyze } from \"./commands/analyze.js\";\nimport { consistency } from \"./commands/consistency.js\";\nimport { update } from \"./commands/update.js\";\nimport { serve } from \"./commands/serve.js\";\nimport { vision } from \"./commands/vision.js\";\nimport { config } from \"./commands/config.js\";\nimport { createDuplicatesCommand } from \"./commands/duplicates/index.js\";\nimport { readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nfunction assertNodeVersion(minMajor: number, minMinor: number): void {\n const ver = process.versions.node || \"\";\n const parts = ver.split(\".\");\n const major = Number.parseInt(parts[0] || \"\", 10);\n const minor = Number.parseInt(parts[1] || \"\", 10);\n\n const meetsRequirement =\n Number.isFinite(major) &&\n Number.isFinite(minor) &&\n (major > minMajor || (major === minMajor && minor >= minMinor));\n\n if (!meetsRequirement) {\n // Keep this dependency-free and stdout/stderr friendly.\n\n console.error(\n `uilint requires Node.js >= ${minMajor}.${minMinor}.0. You are running Node.js ${ver}.`\n );\n process.exit(1);\n }\n}\n\n// Required by dependencies: chokidar, jsdom, readdirp, etc.\nassertNodeVersion(20, 19);\n\nconst program = new Command();\n\nfunction getCLIVersion(): string {\n try {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as {\n version?: string;\n };\n return pkg.version || \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nprogram\n .name(\"uilint\")\n .description(\"AI-powered UI consistency checker\")\n .version(getCLIVersion());\n\n// Analyze command\nprogram\n .command(\"analyze\")\n .description(\n \"Analyze a source file/snippet for style issues (data-loc aware)\"\n )\n .option(\"-f, --input-file <path>\", \"Path to a source file to analyze\")\n .option(\"--source-code <code>\", \"Source code to analyze (string)\")\n .option(\"--file-path <path>\", \"File path label shown in the prompt\")\n .option(\"--style-guide <text>\", \"Inline styleguide content to use\")\n .option(\"--styleguide-path <path>\", \"Path to a style guide file\")\n .option(\"--component-name <name>\", \"Component name for focused analysis\")\n .option(\"--component-line <n>\", \"Component line number (integer)\", (v) =>\n parseInt(v, 10)\n )\n .option(\"--include-children\", \"Scope: selected element + children\")\n .option(\n \"--data-loc <value>\",\n \"data-loc value (repeatable) in format path:line:column\",\n (v, prev: string[] | undefined) => (prev ? [...prev, v] : [v]),\n []\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--stream\", \"Stream progress while analyzing (text mode UI only)\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/source/styleguide (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full LLM payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await analyze({\n inputFile: options.inputFile,\n sourceCode: options.sourceCode,\n filePath: options.filePath,\n styleGuide: options.styleGuide,\n styleguidePath: options.styleguidePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n output: options.output,\n stream: options.stream,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Scan command\nprogram\n .command(\"scan\")\n .description(\"Scan HTML for UI consistency issues\")\n .option(\"-f, --input-file <path>\", \"Path to HTML file to scan\")\n .option(\"-j, --input-json <json>\", \"JSON input with html and styles\")\n .option(\"-s, --styleguide <path>\", \"Path to style guide file\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/style summary/styleguide (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full LLM payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await scan({\n inputFile: options.inputFile,\n inputJson: options.inputJson,\n styleguide: options.styleguide,\n output: options.output,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Consistency command\nprogram\n .command(\"consistency\")\n .description(\"Analyze grouped DOM elements for visual inconsistencies\")\n .option(\"-j, --input-json <json>\", \"JSON input with GroupedSnapshot\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n await consistency({\n inputJson: options.inputJson,\n output: options.output,\n });\n });\n\n// Update command\nprogram\n .command(\"update\")\n .description(\"Update existing style guide with new styles\")\n .option(\"-f, --input-file <path>\", \"Path to HTML file to analyze\")\n .option(\"-j, --input-json <json>\", \"JSON input with html and styles\")\n .option(\"-s, --styleguide <path>\", \"Path to style guide file\")\n .option(\"--llm\", \"Use LLM to suggest updates\")\n .action(async (options) => {\n await update({\n inputFile: options.inputFile,\n inputJson: options.inputJson,\n styleguide: options.styleguide,\n llm: options.llm,\n });\n });\n\n// Init command — plugin flags are added dynamically below in main()\nconst initCommand = program\n .command(\"init\")\n .description(\"Initialize UILint integration\")\n .option(\"--force\", \"Overwrite existing configuration files\")\n .option(\"--react\", \"Install React DevTool (non-interactive)\")\n .option(\"--eslint\", \"Install ESLint rules (non-interactive)\")\n .option(\"--genstyleguide\", \"Generate styleguide (non-interactive)\")\n .option(\"--skill\", \"Install Claude skill (non-interactive)\")\n // Known plugin flags are registered statically so they work even when\n // the plugin packages are not yet installed (the whole point of `init`).\n .option(\"--vision\", \"Install Vision Analysis plugin\")\n .option(\"--semantic\", \"Install Semantic Analysis plugin\")\n .option(\"--duplicates\", \"Install Duplicates Detection plugin\");\n\n// Remove command\nprogram\n .command(\"remove\")\n .description(\"Remove UILint components from your project\")\n .option(\"--dry-run\", \"Preview changes without removing anything\")\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\n .action(async (options) => {\n const { removeUI } = await import(\"./commands/remove-ui.js\");\n await removeUI({ dryRun: options.dryRun, yes: options.yes });\n });\n\n// Serve command - WebSocket server for UI overlay\nprogram\n .command(\"serve\")\n .description(\"Start WebSocket server for real-time UI linting\")\n .option(\"-p, --port <number>\", \"Port to listen on\", \"9234\")\n .option(\"--no-dashboard\", \"Disable dashboard UI (use simple logging)\")\n .action(async (options) => {\n await serve({\n port: parseInt(options.port, 10),\n noDashboard: !options.dashboard,\n });\n });\n\n// Vision command\nprogram\n .command(\"vision\")\n .description(\n \"Analyze a screenshot with Ollama vision models (requires a manifest)\"\n )\n .option(\"--list\", \"List available .uilint/screenshots sidecars and exit\")\n .option(\n \"--screenshots-dir <path>\",\n \"Screenshots directory for --list (default: nearest .uilint/screenshots)\"\n )\n .option(\"--image <path>\", \"Path to a screenshot image (png/jpg)\")\n .option(\n \"--sidecar <path>\",\n \"Path to a .uilint/screenshots/*.json sidecar (contains manifest + metadata)\"\n )\n .option(\"--manifest-file <path>\", \"Path to a manifest JSON file (array)\")\n .option(\"--manifest-json <json>\", \"Inline manifest JSON (array)\")\n .option(\"--route <route>\", \"Optional route label (e.g., /todos)\")\n .option(\n \"-s, --styleguide <path>\",\n \"Path to style guide file OR project directory (falls back to upward search)\"\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--model <name>\", \"Ollama vision model override\", undefined)\n .option(\n \"--base-url <url>\",\n \"Ollama base URL (default: http://localhost:11434)\"\n )\n .option(\"--stream\", \"Stream model output/progress to stderr (text mode only)\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/styleguide and include base64 in dumps (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full analysis payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await vision({\n list: options.list,\n screenshotsDir: options.screenshotsDir,\n image: options.image,\n sidecar: options.sidecar,\n manifestFile: options.manifestFile,\n manifestJson: options.manifestJson,\n route: options.route,\n styleguide: options.styleguide,\n output: options.output,\n model: options.model,\n baseUrl: options.baseUrl,\n stream: options.stream,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Config command\nprogram\n .command(\"config\")\n .description(\"Get or set UILint configuration options\")\n .argument(\"<action>\", \"Action: set or get\")\n .argument(\"<key>\", \"Config key (e.g., position, rule)\")\n .argument(\"[value]\", \"Value to set (for set action)\")\n .argument(\"[extraArg]\", \"Extra argument (e.g., options JSON for rule config)\")\n .option(\"-p, --port <number>\", \"WebSocket server port\", \"9234\")\n .action(async (action, key, value, extraArg, options) => {\n await config(action, key, value, extraArg, {\n port: parseInt(options.port, 10),\n });\n });\n\n// Duplicates command group - semantic code duplicate detection\nprogram.addCommand(createDuplicatesCommand());\n\n// Build manifest command - generate static lint manifest for production\nimport { createManifestCommand } from \"./commands/manifest/index.js\";\nprogram.addCommand(createManifestCommand());\n\n// Socket command - CLI for interacting with socket server\nimport { createSocketCommand } from \"./commands/socket/index.js\";\nprogram.addCommand(createSocketCommand());\n\n// Upgrade command - update installed rules\nprogram\n .command(\"upgrade\")\n .description(\"Update installed ESLint rules to latest versions\")\n .option(\"--check\", \"Show available updates without applying\")\n .option(\"-y, --yes\", \"Auto-confirm all updates\")\n .option(\"--dry-run\", \"Show what would change without modifying files\")\n .option(\"--rule <id>\", \"Upgrade only a specific rule\")\n .action(async (options) => {\n const { upgrade } = await import(\"./commands/upgrade.js\");\n await upgrade({\n check: options.check,\n yes: options.yes,\n dryRun: options.dryRun,\n rule: options.rule,\n });\n });\n\n// Discover plugin manifests and wire up the init command dynamically\nasync function main() {\n const { discoverPlugins } = await import(\"./utils/plugin-loader.js\");\n const pluginManifests = await discoverPlugins();\n\n // Known plugin flags that are statically registered on initCommand.\n // These ensure `init --vision` etc. work even before plugins are installed.\n const KNOWN_PLUGIN_FLAGS = [\"vision\", \"semantic\", \"duplicates\"];\n\n // Add a --<flag> option for each discovered plugin (skips already-registered ones)\n for (const manifest of pluginManifests) {\n if (!KNOWN_PLUGIN_FLAGS.includes(manifest.cliFlag)) {\n initCommand.option(`--${manifest.cliFlag}`, manifest.cliDescription);\n }\n }\n\n // Wire up the init action handler (after plugin options are registered)\n initCommand.action(async (options) => {\n // Collect plugin flags: merge statically-known flags with dynamically-discovered ones\n const allFlags = new Set([\n ...KNOWN_PLUGIN_FLAGS,\n ...pluginManifests.map((m) => m.cliFlag),\n ]);\n const plugins = [...allFlags].filter((flag) => options[flag]);\n\n const { initUI } = await import(\"./commands/init-ui.js\");\n await initUI({\n force: options.force,\n react: options.react,\n eslint: options.eslint,\n genstyleguide: options.genstyleguide,\n skill: options.skill,\n plugins: plugins.length > 0 ? plugins : undefined,\n });\n });\n\n await program.parseAsync();\n}\n\nmain();\n","/**\n * Scan command - scans HTML for UI consistency issues\n */\n\nimport { dirname, resolve } from \"path\";\nimport { existsSync, mkdirSync, statSync, writeFileSync } from \"fs\";\nimport {\n createStyleSummary,\n buildAnalysisPrompt,\n buildSourceAnalysisPrompt,\n formatViolationsText,\n sanitizeIssues,\n ensureOllamaReady,\n readStyleGuide,\n findStyleGuidePath,\n findUILintStyleGuideUpwards,\n STYLEGUIDE_PATHS,\n readTailwindThemeTokens,\n} from \"uilint-core/node\";\nimport {\n getScanInput,\n type InputOptions,\n type ScanInput,\n} from \"../utils/input.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n createSpinner,\n note,\n logInfo,\n logWarning,\n logError,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface ScanOptions extends InputOptions {\n styleguide?: string;\n output?: \"text\" | \"json\";\n /**\n * Enable debug logging (stderr only; never pollutes JSON stdout).\n * Can also be enabled via UILINT_DEBUG=1\n */\n debug?: boolean;\n /**\n * Print full prompt/styleSummary/styleGuide to stderr (can be very large).\n * Can also be enabled via UILINT_DEBUG_FULL=1\n */\n debugFull?: boolean;\n /**\n * Dump full LLM payload (prompt + inputs) to a JSON file.\n * Can also be set via UILINT_DEBUG_DUMP=/path/to/file-or-dir\n */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: ScanOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: ScanOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: ScanOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nexport async function scan(options: ScanOptions): Promise<void> {\n // For JSON output, skip the fancy UI\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) {\n intro(\"Scan for UI Issues\");\n }\n\n try {\n // Get input\n let snapshot: ScanInput;\n try {\n const normalizedOptions: ScanOptions = {\n ...options,\n inputFile: options.inputFile\n ? resolvePathSpecifier(options.inputFile, process.cwd())\n : options.inputFile,\n };\n if (isJsonOutput) {\n snapshot = await getScanInput(normalizedOptions);\n } else {\n snapshot = await withSpinner(\"Parsing input\", async () => {\n return await getScanInput(normalizedOptions);\n });\n }\n } catch {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", issues: [] });\n } else {\n logError(\"No input provided. Use --input-file or pipe HTML to stdin.\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n debugLog(dbg, \"Input options\", {\n inputFile: options.inputFile,\n inputJson: options.inputJson ? \"(provided)\" : undefined,\n styleguide: options.styleguide,\n output: options.output,\n });\n\n if (snapshot.kind === \"dom\") {\n const dom = snapshot.snapshot;\n debugLog(dbg, \"Parsed snapshot (high-level)\", {\n elementCount: dom.elementCount,\n timestamp: dom.timestamp,\n htmlLength: dom.html.length,\n styles: {\n colors: dom.styles.colors.size,\n fontSizes: dom.styles.fontSizes.size,\n fontFamilies: dom.styles.fontFamilies.size,\n fontWeights: dom.styles.fontWeights.size,\n spacing: dom.styles.spacing.size,\n borderRadius: dom.styles.borderRadius.size,\n },\n });\n if (dbgFull) {\n debugLog(dbg, \"Snapshot HTML (full)\", dom.html);\n } else if (dbg) {\n debugLog(dbg, \"Snapshot HTML (preview)\", preview(dom.html, 800));\n }\n\n if (!isJsonOutput) {\n logInfo(`Scanning ${pc.cyan(String(dom.elementCount))} elements`);\n }\n } else {\n debugLog(dbg, \"Parsed source input (high-level)\", {\n inputPath: snapshot.inputPath,\n extension: snapshot.extension,\n length: snapshot.source.length,\n lines: snapshot.source.split(\"\\n\").length,\n });\n if (dbgFull) {\n debugLog(dbg, \"Source (full)\", snapshot.source);\n } else if (dbg) {\n debugLog(dbg, \"Source (preview)\", preview(snapshot.source, 1200));\n }\n\n if (!isJsonOutput) {\n logInfo(\n `Scanning ${pc.cyan(snapshot.extension || \"source\")} (${pc.cyan(\n String(snapshot.source.split(\"\\n\").length)\n )} lines)`\n );\n }\n }\n\n // Get style guide\n // --styleguide can be either:\n // 1. Direct path to a styleguide file (e.g., /path/to/.uilint/styleguide.md)\n // 2. Path to a project directory to search in\n // 3. Not provided - search from cwd\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n const projectPath = process.cwd();\n\n if (options.styleguide) {\n const styleguideArg = resolvePathSpecifier(\n options.styleguide,\n projectPath\n );\n if (existsSync(styleguideArg)) {\n const stat = statSync(styleguideArg);\n if (stat.isFile()) {\n // Direct path to styleguide file\n styleguideLocation = styleguideArg;\n styleGuide = await readStyleGuide(styleguideArg);\n } else if (stat.isDirectory()) {\n // Path to project directory - search within it\n styleguideLocation = findStyleGuidePath(styleguideArg);\n if (styleguideLocation) {\n styleGuide = await readStyleGuide(styleguideLocation);\n }\n }\n } else {\n if (!isJsonOutput) {\n logWarning(`Styleguide not found: ${styleguideArg}`);\n }\n }\n } else {\n // No --styleguide provided:\n // Prefer searching upward from the input file directory for `.uilint/styleguide.md`\n // (helps when running from repo root but scanning a nested app/package).\n const startPath =\n snapshot.kind === \"source\"\n ? snapshot.inputPath\n : snapshot.kind === \"dom\"\n ? snapshot.inputPath\n : undefined;\n if (startPath) {\n styleguideLocation = findUILintStyleGuideUpwards(dirname(startPath));\n }\n\n // Fallback: search from cwd\n styleguideLocation =\n styleguideLocation ?? findStyleGuidePath(projectPath);\n if (styleguideLocation) {\n styleGuide = await readStyleGuide(styleguideLocation);\n }\n }\n\n if (styleguideLocation && styleGuide) {\n if (!isJsonOutput) {\n logSuccess(`Using styleguide: ${pc.dim(styleguideLocation)}`);\n }\n } else if (!styleGuide) {\n if (!isJsonOutput) {\n logWarning(\"No styleguide found\");\n note(\n [\n `Searched in: ${options.styleguide || projectPath}`,\n \"\",\n \"Looked for:\",\n ...STYLEGUIDE_PATHS.map((p) => ` • ${p}`),\n \"\",\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n ].join(\"\\n\"),\n \"Missing Styleguide\"\n );\n }\n }\n\n debugLog(dbg, \"Styleguide resolved\", {\n styleguideArg: options.styleguide,\n styleguideLocation: styleguideLocation ?? null,\n styleGuideLength: styleGuide ? styleGuide.length : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Styleguide contents (full)\", styleGuide ?? \"\");\n } else if (dbg && styleGuide) {\n debugLog(dbg, \"Styleguide contents (preview)\", preview(styleGuide, 800));\n }\n\n // Create style summary\n const tailwindSearchDir =\n (snapshot.kind === \"source\" || snapshot.kind === \"dom\") &&\n snapshot.inputPath\n ? dirname(snapshot.inputPath)\n : projectPath;\n const tailwindTheme = readTailwindThemeTokens(tailwindSearchDir);\n const styleSummary =\n snapshot.kind === \"dom\"\n ? createStyleSummary(snapshot.snapshot.styles, {\n html: snapshot.snapshot.html,\n tailwindTheme,\n })\n : null;\n\n debugLog(dbg, \"Tailwind context\", {\n tailwindSearchDir,\n tailwindTheme: tailwindTheme\n ? {\n configPath: tailwindTheme.configPath,\n colors: tailwindTheme.colors.length,\n spacingKeys: tailwindTheme.spacingKeys.length,\n borderRadiusKeys: tailwindTheme.borderRadiusKeys.length,\n fontFamilyKeys: tailwindTheme.fontFamilyKeys.length,\n fontSizeKeys: tailwindTheme.fontSizeKeys.length,\n }\n : null,\n });\n\n debugLog(dbg, \"Style summary (stats)\", {\n length: styleSummary ? styleSummary.length : 0,\n lines: styleSummary ? styleSummary.split(\"\\n\").length : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Style summary (full)\", styleSummary ?? \"\");\n } else if (dbg && styleSummary) {\n debugLog(dbg, \"Style summary (preview)\", preview(styleSummary, 800));\n }\n\n // Prepare Ollama\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n const prepEndNs = nsNow();\n\n // Call Ollama for analysis\n const client = await createLLMClient({});\n let result;\n\n // Build the exact prompt (this is what analyzeStyles() uses internally)\n const prompt =\n snapshot.kind === \"dom\"\n ? buildAnalysisPrompt(styleSummary ?? \"\", styleGuide)\n : buildSourceAnalysisPrompt(snapshot.source, styleGuide, {\n filePath: snapshot.inputPath,\n languageHint: snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n });\n debugLog(dbg, \"LLM request (high-level)\", {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: !isJsonOutput,\n promptLength: prompt.length,\n promptLines: prompt.split(\"\\n\").length,\n });\n\n if (dbgFull) {\n debugLog(dbg, \"LLM prompt (full)\", prompt);\n } else if (dbg) {\n debugLog(dbg, \"LLM prompt (preview)\", preview(prompt, 1200));\n }\n\n if (dbgDump) {\n try {\n const now = new Date();\n const safeStamp = now.toISOString().replace(/[:.]/g, \"-\");\n const resolved = resolve(process.cwd(), dbgDump);\n const dumpFile =\n resolved.endsWith(\".json\") || resolved.endsWith(\".jsonl\")\n ? resolved\n : resolve(resolved, `scan-debug-${safeStamp}.json`);\n\n // If path looks like a directory (or a non-json file), ensure dir exists.\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: now.toISOString(),\n options: {\n inputFile: options.inputFile,\n inputJson: options.inputJson ? \"(provided)\" : undefined,\n styleguide: options.styleguide,\n styleguideLocation,\n output: options.output,\n model: client.getModel(),\n },\n snapshot: {\n kind: snapshot.kind,\n ...(snapshot.kind === \"dom\"\n ? {\n elementCount: snapshot.snapshot.elementCount,\n timestamp: snapshot.snapshot.timestamp,\n html: snapshot.snapshot.html,\n styles: {\n colors: [...snapshot.snapshot.styles.colors.entries()],\n fontSizes: [\n ...snapshot.snapshot.styles.fontSizes.entries(),\n ],\n fontFamilies: [\n ...snapshot.snapshot.styles.fontFamilies.entries(),\n ],\n fontWeights: [\n ...snapshot.snapshot.styles.fontWeights.entries(),\n ],\n spacing: [\n ...snapshot.snapshot.styles.spacing.entries(),\n ],\n borderRadius: [\n ...snapshot.snapshot.styles.borderRadius.entries(),\n ],\n },\n }\n : {\n inputPath: snapshot.inputPath,\n extension: snapshot.extension,\n source: snapshot.source,\n }),\n },\n styleGuide,\n styleSummary,\n prompt,\n tailwindTheme,\n llmRequest: {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: !isJsonOutput,\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n debugLog(dbg, `Wrote debug dump to ${dumpFile}`);\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write debug dump\",\n e instanceof Error ? e.message : e\n );\n }\n }\n\n if (isJsonOutput) {\n result =\n snapshot.kind === \"dom\"\n ? await client.analyzeStyles(styleSummary ?? \"\", styleGuide)\n : await client.analyzeSource(snapshot.source, styleGuide, undefined, {\n filePath: snapshot.inputPath,\n languageHint: snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n });\n } else {\n // Use streaming to show progress\n const s = createSpinner();\n s.start(\"Analyzing with LLM\");\n let thinkingStarted = false;\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n\n const onProgress = (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ): void => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!thinkingStarted) {\n thinkingStarted = true;\n s.stop(pc.dim(\"[scan] streaming thinking:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n // Truncate line if too long for terminal\n const maxLen = 60;\n const displayLine =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(displayLine || \"...\")}`);\n };\n\n try {\n result =\n snapshot.kind === \"dom\"\n ? await client.analyzeStyles(\n styleSummary ?? \"\",\n styleGuide,\n onProgress\n )\n : await client.analyzeSource(\n snapshot.source,\n styleGuide,\n onProgress,\n {\n filePath: snapshot.inputPath,\n languageHint:\n snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n }\n );\n s.stop(pc.green(\"✓ \") + \"Analyzing with LLM\");\n\n if (process.stdout.isTTY) {\n const analysisEndNs = nsNow();\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n result?.analysisTime\n ? pc.dim(`(core analysisTime: ${formatMs(result.analysisTime)})`)\n : pc.dim(\"(core analysisTime: n/a)\"),\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n } catch (error) {\n s.stop(pc.red(\"✗ \") + \"Analyzing with LLM\");\n throw error;\n }\n }\n\n // Sanitize (enforce violations-only output)\n const issues = sanitizeIssues(result.issues);\n\n // Output results\n if (isJsonOutput) {\n printJSON({\n issues,\n analysisTime: result.analysisTime,\n elementCount:\n snapshot.kind === \"dom\" ? snapshot.snapshot.elementCount : 0,\n });\n } else {\n // Minimal output: list violations only, plus footer to consult the style guide.\n process.stdout.write(\n formatViolationsText(issues, { includeFooter: issues.length > 0 }) +\n \"\\n\"\n );\n }\n\n // Exit with error code if issues found\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (options.output === \"json\") {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Scan failed\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * Input handling utilities for CLI\n */\n\nimport { readFile } from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport { extname } from \"path\";\nimport {\n parseCLIInput,\n hasStdin,\n readStdin,\n type DOMSnapshot,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"./path-specifiers.js\";\n\nexport interface InputOptions {\n inputFile?: string;\n inputJson?: string;\n}\n\nexport type ScanInput =\n | {\n kind: \"dom\";\n snapshot: DOMSnapshot;\n source: \"json\" | \"file\" | \"stdin\";\n inputPath?: string;\n }\n | {\n kind: \"source\";\n source: string;\n inputPath: string;\n extension: string;\n };\n\nfunction isHtmlLikeExtension(ext: string): boolean {\n return ext === \".html\" || ext === \".htm\";\n}\n\nfunction isJsonLikeExtension(ext: string): boolean {\n return ext === \".json\";\n}\n\n/**\n * Gets input from various sources: stdin, file, or JSON string\n */\nexport async function getInput(options: InputOptions): Promise<DOMSnapshot> {\n // Priority: explicit JSON > explicit file > stdin\n if (options.inputJson) {\n return parseCLIInput(options.inputJson);\n }\n\n if (options.inputFile) {\n const filePath = resolvePathSpecifier(options.inputFile, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.inputFile}`);\n }\n const content = await readFile(filePath, \"utf-8\");\n return parseCLIInput(content);\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No input provided via stdin\");\n }\n return parseCLIInput(content);\n }\n\n throw new Error(\n \"No input provided. Use --input-file, --input-json, or pipe content to stdin.\"\n );\n}\n\n/**\n * Gets scan input:\n * - If input is a file and it's not HTML/JSON, treat it as raw source (TSX/JSX/etc).\n * - Otherwise, treat it as HTML/DOM input (including JSON-wrapped snapshots).\n */\nexport async function getScanInput(options: InputOptions): Promise<ScanInput> {\n // Priority: explicit JSON > explicit file > stdin\n if (options.inputJson) {\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(options.inputJson),\n source: \"json\",\n };\n }\n\n if (options.inputFile) {\n const filePath = resolvePathSpecifier(options.inputFile, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.inputFile}`);\n }\n const content = await readFile(filePath, \"utf-8\");\n const ext = extname(filePath).toLowerCase();\n\n if (isHtmlLikeExtension(ext) || isJsonLikeExtension(ext)) {\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(content),\n source: \"file\",\n inputPath: filePath,\n };\n }\n\n return {\n kind: \"source\",\n source: content,\n inputPath: filePath,\n extension: ext,\n };\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No input provided via stdin\");\n }\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(content),\n source: \"stdin\",\n };\n }\n\n throw new Error(\n \"No input provided. Use --input-file, --input-json, or pipe content to stdin.\"\n );\n}\n\n/**\n * Gets code input from various sources\n */\nexport async function getCodeInput(options: {\n code?: string;\n file?: string;\n}): Promise<string> {\n if (options.code) {\n return options.code;\n }\n\n if (options.file) {\n const filePath = resolvePathSpecifier(options.file, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.file}`);\n }\n return readFile(filePath, \"utf-8\");\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No code provided via stdin\");\n }\n return content;\n }\n\n throw new Error(\n \"No code provided. Use --code, provide a file, or pipe to stdin.\"\n );\n}\n\n/**\n * Validates that a path exists\n */\nexport function validatePath(path: string, description: string): void {\n if (!existsSync(path)) {\n throw new Error(`${description} not found: ${path}`);\n }\n}\n","/**\n * Path specifier utilities for CLI.\n *\n * We support \"workspace-relative\" specifiers using a leading \"@\", e.g.:\n * - @apps/test-app/app/page.tsx\n * - @apps/test-app/.uilint/styleguide.md\n *\n * This mirrors how some tools (and humans) refer to \"repo-relative\" paths.\n */\n\nimport { isAbsolute, resolve } from \"path\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\n\n/**\n * Resolve a user-provided path specifier into an absolute filesystem path.\n *\n * Rules:\n * - Absolute paths are left absolute (normalized with resolve()).\n * - \"@<path>\" is resolved relative to the workspace root (pnpm-workspace/.git).\n * - Everything else is resolved relative to cwd.\n */\nexport function resolvePathSpecifier(\n spec: string,\n cwd: string = process.cwd()\n): string {\n const raw = (spec ?? \"\").trim();\n if (!raw) return resolve(cwd, spec);\n\n if (raw.startsWith(\"@\")) {\n const workspaceRoot = findWorkspaceRoot(cwd);\n let rest = raw.slice(1);\n if (rest.startsWith(\"/\")) rest = rest.slice(1);\n // Note: resolve(workspaceRoot, rest) is safe even if rest contains \"..\";\n // callers that need a security boundary should validate separately.\n return resolve(workspaceRoot, rest);\n }\n\n if (isAbsolute(raw)) return resolve(raw);\n return resolve(cwd, raw);\n}\n","/**\n * LLM Client Factory with Optional Langfuse Instrumentation\n *\n * This module provides a centralized way to create OllamaClient instances\n * with optional Langfuse tracing enabled. Langfuse is only loaded if:\n * 1. LANGFUSE_ENABLED=1 (or true/yes)\n * 2. LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY are set\n */\n\nimport { config } from \"dotenv\";\nimport { join } from \"path\";\nimport {\n OllamaClient,\n type LLMInstrumentationCallbacks,\n type InstrumentationSpan,\n findWorkspaceRoot,\n} from \"uilint-core/node\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { LangfuseSpanProcessor } from \"@langfuse/otel\";\nimport {\n startActiveObservation,\n startObservation,\n type LangfuseObservation,\n type LangfuseGeneration,\n} from \"@langfuse/tracing\";\n\n// Load .env.local from workspace root\nlet envLoaded = false;\nfunction loadEnvLocal(): void {\n if (envLoaded) return;\n envLoaded = true;\n\n const workspaceRoot = findWorkspaceRoot(process.cwd());\n const envLocalPath = join(workspaceRoot, \".env.local\");\n\n // Load .env.local if it exists (dotenv will silently skip if file doesn't exist)\n config({ path: envLocalPath });\n}\n\n// Load environment variables immediately on module load\nloadEnvLocal();\n\n// Lazy-loaded instrumentation\nlet langfuseInitialized = false;\nlet langfuseInstrumentation: LLMInstrumentationCallbacks | undefined;\nlet sdkInstance: NodeSDK | undefined;\nlet spanProcessor: LangfuseSpanProcessor | undefined;\n\n/**\n * Checks if Langfuse is enabled via environment variable\n */\nfunction isLangfuseEnabled(): boolean {\n const enabled = process.env.LANGFUSE_ENABLED;\n if (!enabled) return false;\n return (\n enabled === \"1\" ||\n enabled.toLowerCase() === \"true\" ||\n enabled.toLowerCase() === \"yes\"\n );\n}\n\n/**\n * Initialize Langfuse if enabled. This is called automatically on first client creation,\n * but can also be called explicitly at app startup.\n */\nexport async function initializeLangfuseIfEnabled(): Promise<void> {\n if (langfuseInitialized) return;\n langfuseInitialized = true;\n\n if (!isLangfuseEnabled()) {\n return;\n }\n\n const publicKey = process.env.LANGFUSE_PUBLIC_KEY;\n const secretKey = process.env.LANGFUSE_SECRET_KEY;\n\n if (!publicKey || !secretKey) {\n console.error(\n \"[uilint] LANGFUSE_ENABLED=1 but missing LANGFUSE_PUBLIC_KEY or LANGFUSE_SECRET_KEY\"\n );\n return;\n }\n\n try {\n const baseUrl = process.env.LANGFUSE_BASE_URL || \"http://localhost:3333\";\n\n // Create the span processor with immediate export mode for CLI usage\n spanProcessor = new LangfuseSpanProcessor({\n publicKey,\n secretKey,\n baseUrl,\n // Use immediate mode to ensure spans are exported right away in CLI context\n exportMode: \"immediate\",\n });\n\n // Initialize OpenTelemetry with LangfuseSpanProcessor\n const sdk = new NodeSDK({\n spanProcessors: [spanProcessor],\n });\n\n sdk.start();\n sdkInstance = sdk;\n\n // Create instrumentation callbacks using @langfuse/tracing\n // Use startActiveObservation at top level to create the trace context\n langfuseInstrumentation = {\n onGenerationStart: ({\n name,\n model,\n prompt,\n metadata,\n }: {\n name: string;\n model: string;\n prompt: string;\n metadata?: Record<string, unknown>;\n }): InstrumentationSpan => {\n // We need to bridge the callback-based startActiveObservation with our\n // synchronous start / async end pattern. Use a promise to control when the trace ends.\n let resolveTrace: () => void;\n let generationRef: LangfuseGeneration | undefined;\n let _traceRef: LangfuseObservation | undefined;\n let endData:\n | {\n output: string;\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n error?: string;\n };\n }\n | undefined;\n\n // Start the active observation (trace) - this runs the callback immediately\n // but doesn't resolve until we call resolveTrace()\n const tracePromise = startActiveObservation(\n `uilint-${name}`,\n async (span) => {\n _traceRef = span;\n span.update({\n input: { operation: name },\n metadata: {\n ...metadata,\n source: \"uilint\",\n },\n });\n\n // Create the generation as a child - startObservation within startActiveObservation\n // automatically nests under the active trace\n generationRef = startObservation(\n name,\n {\n model,\n input: prompt,\n metadata: {\n ...metadata,\n source: \"uilint\",\n },\n },\n { asType: \"generation\" }\n );\n\n // Wait for end() to be called before completing the trace\n await new Promise<void>((resolve) => {\n resolveTrace = resolve;\n });\n\n // Now process the end data\n if (endData && generationRef) {\n const usageDetails: Record<string, number> | undefined =\n endData.usage\n ? Object.fromEntries(\n Object.entries({\n input: endData.usage.promptTokens,\n output: endData.usage.completionTokens,\n total: endData.usage.totalTokens,\n }).filter(([, v]) => v !== undefined) as [\n string,\n number\n ][]\n )\n : undefined;\n\n // End the generation\n generationRef.update({\n output: endData.output,\n usageDetails:\n usageDetails && Object.keys(usageDetails).length > 0\n ? usageDetails\n : undefined,\n metadata: endData.usage?.error\n ? { ...metadata, error: endData.usage.error }\n : metadata,\n });\n generationRef.end();\n\n // Update the trace output\n span.update({\n output: endData.usage?.error\n ? `Error: ${endData.usage.error}`\n : \"completed\",\n });\n }\n // The trace automatically ends when the callback completes\n }\n );\n\n // Handle any errors from the trace promise\n tracePromise.catch((error) => {\n console.error(\"[uilint] Langfuse trace error:\", error);\n });\n\n return {\n end: (\n output: string,\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n error?: string;\n }\n ) => {\n // Store the end data and resolve the trace promise\n endData = { output, usage };\n if (resolveTrace) {\n resolveTrace();\n }\n },\n };\n },\n };\n\n console.error(`[uilint] Langfuse tracing enabled (${baseUrl})`);\n } catch (error) {\n console.error(\n \"[uilint] Failed to initialize Langfuse:\",\n error instanceof Error ? error.message : error\n );\n }\n}\n\n/**\n * Creates an OllamaClient with optional Langfuse instrumentation.\n * Automatically initializes Langfuse on first call if enabled.\n */\nexport async function createLLMClient(options: {\n model?: string;\n baseUrl?: string;\n timeout?: number;\n}): Promise<OllamaClient> {\n // Initialize Langfuse on first client creation\n await initializeLangfuseIfEnabled();\n\n return new OllamaClient({\n ...options,\n instrumentation: langfuseInstrumentation,\n });\n}\n\n/**\n * Flushes Langfuse traces. Call this before process exit to ensure all traces are sent.\n */\nexport async function flushLangfuse(): Promise<void> {\n // Force flush the span processor first to ensure all pending spans are sent\n if (spanProcessor) {\n try {\n await spanProcessor.forceFlush();\n } catch (error) {\n console.error(\n \"[uilint] Failed to flush Langfuse spans:\",\n error instanceof Error ? error.message : error\n );\n }\n }\n\n // Then shutdown the SDK\n if (sdkInstance) {\n try {\n await sdkInstance.shutdown();\n } catch (error) {\n console.error(\n \"[uilint] Failed to shutdown OpenTelemetry SDK:\",\n error instanceof Error ? error.message : error\n );\n }\n }\n}\n\n/**\n * Returns true if Langfuse is currently initialized and active.\n */\nexport function isLangfuseActive(): boolean {\n return spanProcessor !== undefined;\n}\n\n// Register shutdown handler\nlet shutdownRegistered = false;\nfunction registerShutdownHandler(): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n\n const cleanup = async () => {\n await flushLangfuse();\n };\n\n process.on(\"beforeExit\", cleanup);\n process.on(\"SIGINT\", async () => {\n await cleanup();\n process.exit(130);\n });\n process.on(\"SIGTERM\", async () => {\n await cleanup();\n process.exit(143);\n });\n}\n\n// Auto-register on module load\nregisterShutdownHandler();\n","/**\n * High-precision timing helpers for CLI UX\n */\n\nexport function nsNow(): bigint {\n return process.hrtime.bigint();\n}\n\nexport function nsToMs(ns: bigint): number {\n return Number(ns) / 1_000_000;\n}\n\nexport function formatMs(ms: number): string {\n if (!Number.isFinite(ms)) return \"n/a\";\n if (ms < 1000) return `${ms.toFixed(ms < 10 ? 2 : ms < 100 ? 1 : 0)}ms`;\n const s = ms / 1000;\n if (s < 60) return `${s.toFixed(s < 10 ? 2 : 1)}s`;\n const m = Math.floor(s / 60);\n const rem = s - m * 60;\n return `${m}m ${rem.toFixed(rem < 10 ? 1 : 0)}s`;\n}\n\nexport function maybeMs(ms: number | null | undefined): string {\n return ms == null ? \"n/a\" : formatMs(ms);\n}\n","/**\n * Output formatting utilities for CLI\n */\n\nimport chalk from \"chalk\";\nimport {\n formatViolationsText,\n sanitizeIssues,\n type UILintIssue,\n} from \"uilint-core\";\n\n/**\n * Formats UILint issues for console output\n */\nexport function formatIssues(issues: UILintIssue[]): string {\n const sanitized = sanitizeIssues(issues);\n const text = formatViolationsText(sanitized, {\n includeFooter: sanitized.length > 0,\n });\n // Preserve existing callers expecting a string; apply minimal coloring only.\n return sanitized.length === 0 ? chalk.green(text) : text;\n}\n\n/**\n * Prints JSON output\n */\nexport function printJSON(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\n/**\n * Prints an error message\n */\nexport function printError(message: string): void {\n console.error(chalk.red(`Error: ${message}`));\n}\n\n/**\n * Prints a success message\n */\nexport function printSuccess(message: string): void {\n console.log(chalk.green(`✓ ${message}`));\n}\n\n/**\n * Prints a warning message\n */\nexport function printWarning(message: string): void {\n console.log(chalk.yellow(`⚠️ ${message}`));\n}\n\n/**\n * Prints an info message\n */\nexport function printInfo(message: string): void {\n console.log(chalk.blue(`ℹ ${message}`));\n}\n\n/**\n * Prints a debug/path message (dimmed)\n */\nexport function printPath(label: string, path: string): void {\n console.log(chalk.gray(` ${label}: ${chalk.dim(path)}`));\n}\n\n/**\n * Prints a styled box for important messages\n */\nexport function printBox(\n title: string,\n lines: string[],\n style: \"warning\" | \"error\" | \"info\" = \"info\"\n): void {\n const colors = {\n warning: { border: chalk.yellow, title: chalk.yellow.bold, icon: \"⚠\" },\n error: { border: chalk.red, title: chalk.red.bold, icon: \"✖\" },\n info: { border: chalk.blue, title: chalk.blue.bold, icon: \"ℹ\" },\n };\n const { border, title: titleColor, icon } = colors[style];\n\n const maxLen = Math.max(title.length, ...lines.map((l) => l.length)) + 4;\n const horizontal = \"─\".repeat(maxLen);\n\n console.log();\n console.log(border(`╭${horizontal}╮`));\n console.log(border(`│ ${icon} ${titleColor(title.padEnd(maxLen - 3))}│`));\n console.log(border(`├${horizontal}┤`));\n lines.forEach((line) => {\n console.log(border(`│ ${chalk.gray(line.padEnd(maxLen - 1))}│`));\n });\n console.log(border(`╰${horizontal}╯`));\n console.log();\n}\n\n/**\n * Prints styleguide status information\n */\nexport function printStyleguideNotFound(\n searchedPaths: string[],\n projectPath: string\n): void {\n printBox(\n \"No styleguide found\",\n [\n `Searched in: ${projectPath}`,\n \"\",\n \"Looked for:\",\n ...searchedPaths.map((p) => ` • ${p}`),\n \"\",\n \"To create one, run:\",\n ` ${chalk.cyan(\"/genstyleguide\")} ${chalk.gray(\"(Cursor)\")}`,\n ],\n \"warning\"\n );\n}\n\n/**\n * Prints styleguide found confirmation\n */\nexport function printStyleguideFound(path: string): void {\n console.log(chalk.green(`📋 Using styleguide: ${chalk.dim(path)}`));\n}\n","/**\n * Analyze command - analyzes a source file/snippet for style issues (data-loc aware)\n */\n\nimport { dirname, resolve } from \"path\";\nimport { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport {\n buildSourceScanPrompt,\n ensureOllamaReady,\n readStyleGuide,\n findStyleGuidePath,\n findWorkspaceRoot,\n findUILintStyleGuideUpwards,\n} from \"uilint-core/node\";\nimport { getCodeInput } from \"../utils/input.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n createSpinner,\n note,\n logError,\n logWarning,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\ntype UILintScanIssue = {\n line?: number;\n message: string;\n dataLoc?: string;\n};\n\nexport interface AnalyzeOptions {\n // Input\n inputFile?: string;\n sourceCode?: string;\n\n // Styleguide\n styleGuide?: string;\n styleguidePath?: string;\n\n // Prompt context\n filePath?: string;\n componentName?: string;\n componentLine?: number;\n includeChildren?: boolean;\n dataLoc?: string[]; // repeatable\n\n // LLM\n stream?: boolean;\n\n // Output\n output?: \"text\" | \"json\";\n\n /**\n * Enable debug logging (stderr only; never pollutes JSON stdout).\n * Can also be enabled via UILINT_DEBUG=1\n */\n debug?: boolean;\n /**\n * Print full prompt/styleguide to stderr (can be very large).\n * Can also be enabled via UILINT_DEBUG_FULL=1\n */\n debugFull?: boolean;\n /**\n * Dump full LLM payload (prompt + inputs) to a JSON file.\n * Can also be set via UILINT_DEBUG_DUMP=/path/to/file-or-dir\n */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: AnalyzeOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: AnalyzeOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: AnalyzeOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nasync function resolveStyleGuideForAnalyze(options: {\n styleGuide?: string;\n styleguidePath?: string;\n inputFile?: string;\n}): Promise<{ content: string | null; path: string | null }> {\n // 1) Inline (highest priority)\n if (options.styleGuide && typeof options.styleGuide === \"string\") {\n return { content: options.styleGuide, path: null };\n }\n\n // 2) Explicit path\n if (options.styleguidePath && typeof options.styleguidePath === \"string\") {\n const p = resolvePathSpecifier(options.styleguidePath, process.cwd());\n if (existsSync(p)) {\n return { content: await readStyleGuide(p), path: p };\n }\n return { content: null, path: null };\n }\n\n // 3) Env var pin\n const env = process.env.UILINT_STYLEGUIDE_PATH;\n if (env && env.trim()) {\n const p = resolvePathSpecifier(env.trim(), process.cwd());\n if (existsSync(p)) {\n return { content: await readStyleGuide(p), path: p };\n }\n }\n\n // 4) Smarter default: walk upward from the input file dir looking for `.uilint/styleguide.md`\n if (options.inputFile) {\n const absInput = resolvePathSpecifier(options.inputFile, process.cwd());\n const found = findUILintStyleGuideUpwards(dirname(absInput));\n if (found) return { content: await readStyleGuide(found), path: found };\n }\n\n // 5) Fallbacks: cwd, then workspace root (monorepo)\n const cwdPath = findStyleGuidePath(process.cwd());\n if (cwdPath) return { content: await readStyleGuide(cwdPath), path: cwdPath };\n\n const wsRoot = findWorkspaceRoot(process.cwd());\n const wsPath = findStyleGuidePath(wsRoot);\n if (wsPath) return { content: await readStyleGuide(wsPath), path: wsPath };\n\n return { content: null, path: null };\n}\n\nfunction formatScanIssuesText(issues: UILintScanIssue[]): string {\n if (issues.length === 0) return pc.green(\"No issues found.\");\n const lines = issues.map((i) => {\n const line = typeof i.line === \"number\" ? `Line ${i.line}: ` : \"\";\n const loc = i.dataLoc ? ` ${pc.dim(`(${i.dataLoc})`)}` : \"\";\n return `- ${line}${i.message}${loc}`;\n });\n return lines.join(\"\\n\");\n}\n\nexport async function analyze(options: AnalyzeOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) {\n intro(\"Analyze Source Code\");\n }\n\n try {\n debugLog(dbg, \"Input options\", {\n inputFile: options.inputFile,\n sourceCode: options.sourceCode ? \"(provided)\" : undefined,\n styleGuide: options.styleGuide ? \"(inline)\" : undefined,\n styleguidePath: options.styleguidePath,\n filePath: options.filePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n stream: options.stream,\n output: options.output,\n });\n\n // Input\n const sourceCode = await getCodeInput({\n code: options.sourceCode,\n file: options.inputFile\n ? resolvePathSpecifier(options.inputFile)\n : undefined,\n });\n\n debugLog(dbg, \"Source code (high-level)\", {\n length: sourceCode.length,\n lines: sourceCode.split(\"\\n\").length,\n });\n if (dbgFull) {\n debugLog(dbg, \"Source code (full)\", sourceCode);\n } else if (dbg) {\n debugLog(dbg, \"Source code (preview)\", preview(sourceCode, 800));\n }\n\n const resolvedStyle = await resolveStyleGuideForAnalyze({\n styleGuide: options.styleGuide,\n styleguidePath: options.styleguidePath,\n inputFile: options.inputFile,\n });\n\n debugLog(dbg, \"Styleguide resolved\", {\n styleGuideArg:\n options.styleguidePath ?? options.styleGuide ? \"(inline)\" : null,\n styleguideLocation: resolvedStyle.path,\n styleGuideLength: resolvedStyle.content\n ? resolvedStyle.content.length\n : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Styleguide contents (full)\", resolvedStyle.content ?? \"\");\n } else if (dbg && resolvedStyle.content) {\n debugLog(\n dbg,\n \"Styleguide contents (preview)\",\n preview(resolvedStyle.content, 800)\n );\n }\n\n if (!resolvedStyle.content && !isJsonOutput) {\n logWarning(\"No styleguide found (analyzing without it)\");\n } else if (resolvedStyle.path && !isJsonOutput) {\n logSuccess(`Using styleguide: ${pc.dim(resolvedStyle.path)}`);\n }\n\n // Prepare Ollama\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n const prepEndNs = nsNow();\n\n const client = await createLLMClient({});\n\n const promptContext = {\n filePath:\n options.filePath ||\n (options.inputFile ? options.inputFile : undefined) ||\n \"component.tsx\",\n componentName: options.componentName,\n componentLine:\n typeof options.componentLine === \"number\"\n ? options.componentLine\n : undefined,\n includeChildren: options.includeChildren === true,\n dataLocs: Array.isArray(options.dataLoc) ? options.dataLoc : undefined,\n };\n\n const prompt = buildSourceScanPrompt(\n sourceCode,\n resolvedStyle.content,\n promptContext\n );\n\n debugLog(dbg, \"LLM request (high-level)\", {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: options.stream ?? false,\n promptLength: prompt.length,\n promptLines: prompt.split(\"\\n\").length,\n });\n\n if (dbgFull) {\n debugLog(dbg, \"LLM prompt (full)\", prompt);\n } else if (dbg) {\n debugLog(dbg, \"LLM prompt (preview)\", preview(prompt, 1200));\n }\n\n // Debug dump\n if (dbgDump) {\n try {\n const now = new Date();\n const safeStamp = now.toISOString().replace(/[:.]/g, \"-\");\n const resolved = resolve(process.cwd(), dbgDump);\n const dumpFile =\n resolved.endsWith(\".json\") || resolved.endsWith(\".jsonl\")\n ? resolved\n : resolve(resolved, `analyze-debug-${safeStamp}.json`);\n\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: now.toISOString(),\n command: \"analyze\",\n options: {\n inputFile: options.inputFile,\n sourceCode: options.sourceCode ? \"(provided)\" : undefined,\n styleGuide: options.styleGuide ? \"(inline)\" : undefined,\n styleguidePath: options.styleguidePath,\n styleguideLocation: resolvedStyle.path,\n filePath: options.filePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n model: client.getModel(),\n stream: options.stream,\n output: options.output,\n },\n input: {\n sourceCode,\n sourceLines: sourceCode.split(\"\\n\").length,\n },\n styleGuide: resolvedStyle.content,\n promptContext,\n prompt,\n llmRequest: {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: options.stream ?? false,\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n debugLog(dbg, `Wrote debug dump to ${dumpFile}`);\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write debug dump\",\n e instanceof Error ? e.message : e\n );\n }\n }\n\n let responseText = \"\";\n if (options.stream) {\n if (!isJsonOutput) {\n const s = createSpinner();\n s.start(\"Analyzing with LLM\");\n let thinkingStarted = false;\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n try {\n responseText = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!thinkingStarted) {\n thinkingStarted = true;\n s.stop(pc.dim(\"[analyze] streaming thinking:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n const maxLen = 60;\n const line =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(line || \"...\")}`);\n },\n });\n s.stop(pc.green(\"✓ \") + \"Analyzing with LLM\");\n\n if (process.stdout.isTTY) {\n const analysisEndNs = nsNow();\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n } catch (e) {\n s.stop(pc.red(\"✗ \") + \"Analyzing with LLM\");\n throw e;\n }\n } else {\n responseText = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: () => {\n // JSON mode: never write progress to stdout\n },\n });\n }\n } else {\n responseText = await client.complete(prompt, { json: true });\n }\n\n const parsed = JSON.parse(responseText) as { issues?: UILintScanIssue[] };\n const issues = Array.isArray(parsed.issues) ? parsed.issues : [];\n\n if (isJsonOutput) {\n printJSON({ issues });\n } else {\n process.stdout.write(formatScanIssuesText(issues) + \"\\n\");\n }\n\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (isJsonOutput) {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Analyze failed\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * Consistency command - analyzes grouped DOM elements for visual inconsistencies\n */\n\nimport { createInterface } from \"readline\";\nimport {\n parseGroupedSnapshot,\n analyzeConsistency,\n formatConsistencyViolations,\n countElements,\n hasAnalyzableGroups,\n type ConsistencyResult,\n} from \"uilint-core\";\nimport { ensureOllamaReady } from \"uilint-core/node\";\nimport {\n intro,\n withSpinner,\n logInfo,\n logError,\n logSuccess,\n logWarning,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface ConsistencyOptions {\n inputJson?: string;\n output?: \"text\" | \"json\";\n}\n\n/**\n * Reads JSON input from stdin\n */\nasync function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = \"\";\n const rl = createInterface({ input: process.stdin });\n rl.on(\"line\", (line) => {\n data += line;\n });\n rl.on(\"close\", () => {\n resolve(data);\n });\n });\n}\n\n/**\n * Main consistency analysis command\n */\nexport async function consistency(options: ConsistencyOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n\n if (!isJsonOutput) {\n intro(\"UI Consistency Analysis\");\n }\n\n try {\n // Get input\n let inputJson = options.inputJson;\n if (!inputJson) {\n // Check if stdin has data\n if (!process.stdin.isTTY) {\n inputJson = await readStdin();\n }\n }\n\n if (!inputJson) {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", violations: [] });\n } else {\n logError(\"No input provided. Use --input-json or pipe JSON to stdin.\");\n }\n process.exit(1);\n }\n\n // Parse snapshot\n const snapshot = parseGroupedSnapshot(inputJson);\n if (!snapshot) {\n if (isJsonOutput) {\n printJSON({ error: \"Invalid JSON input\", violations: [] });\n } else {\n logError(\"Failed to parse input as GroupedSnapshot.\");\n }\n process.exit(1);\n }\n\n const elementCount = countElements(snapshot);\n\n if (!isJsonOutput) {\n logInfo(`Analyzing ${pc.cyan(String(elementCount))} elements`);\n }\n\n // Check if there are analyzable groups\n if (!hasAnalyzableGroups(snapshot)) {\n const result: ConsistencyResult = {\n violations: [],\n elementCount,\n analysisTime: 0,\n };\n\n if (isJsonOutput) {\n printJSON(result);\n } else {\n logWarning(\"No groups with 2+ elements to analyze.\");\n }\n return;\n }\n\n // Prepare Ollama\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n\n // Analyze with core function\n let result: ConsistencyResult;\n if (isJsonOutput) {\n result = await analyzeConsistency(snapshot, {});\n } else {\n result = await withSpinner(\"Analyzing with LLM\", async () => {\n return await analyzeConsistency(snapshot, {});\n });\n }\n\n // Output results\n if (isJsonOutput) {\n printJSON(result);\n } else {\n console.log();\n console.log(formatConsistencyViolations(result.violations));\n\n if (result.violations.length > 0) {\n logInfo(\n `Analysis completed in ${pc.dim(String(result.analysisTime) + \"ms\")}`\n );\n } else {\n logSuccess(\n `Analysis completed in ${pc.dim(String(result.analysisTime) + \"ms\")}`\n );\n }\n }\n\n // Exit with error code if violations found\n if (result.violations.length > 0) {\n process.exit(1);\n }\n } catch (error) {\n if (isJsonOutput) {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n violations: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Analysis failed\");\n }\n process.exit(1);\n }\n}\n","/**\n * Update command - updates existing style guide with new styles\n */\n\nimport { dirname, resolve } from \"path\";\nimport {\n createStyleSummary,\n parseStyleGuide,\n mergeStyleGuides,\n styleGuideToMarkdown,\n} from \"uilint-core\";\nimport {\n readStyleGuide,\n writeStyleGuide,\n findStyleGuidePath,\n ensureOllamaReady,\n readTailwindThemeTokens,\n} from \"uilint-core/node\";\nimport { getInput, type InputOptions } from \"../utils/input.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport {\n intro,\n outro,\n withSpinner,\n note,\n logSuccess,\n logInfo,\n logError,\n pc,\n} from \"../utils/prompts.js\";\n\nexport interface UpdateOptions extends InputOptions {\n styleguide?: string;\n llm?: boolean;\n}\n\nexport async function update(options: UpdateOptions): Promise<void> {\n intro(\"Update Style Guide\");\n\n try {\n const projectPath = process.cwd();\n const styleGuidePath =\n options.styleguide || findStyleGuidePath(projectPath);\n\n if (!styleGuidePath) {\n logError(\"No style guide found\");\n note(\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} first (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n \"Tip\"\n );\n await flushLangfuse();\n process.exit(1);\n }\n\n logInfo(`Using styleguide: ${pc.dim(styleGuidePath)}`);\n\n // Read existing style guide\n const existingContent = await readStyleGuide(styleGuidePath);\n const existingGuide = parseStyleGuide(existingContent);\n\n // Get input\n let snapshot;\n try {\n snapshot = await withSpinner(\"Analyzing project\", async () => {\n return await getInput(options);\n });\n } catch {\n logError(\"No input provided. Use --input-file or pipe HTML to stdin.\");\n await flushLangfuse();\n process.exit(1);\n }\n\n logInfo(`Found ${pc.cyan(String(snapshot.elementCount))} elements`);\n\n const tailwindSearchDir = options.inputFile\n ? dirname(resolve(projectPath, options.inputFile))\n : projectPath;\n const tailwindTheme = readTailwindThemeTokens(tailwindSearchDir);\n\n if (options.llm) {\n // Use LLM to suggest updates\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n\n const result = await withSpinner(\n \"Analyzing styles with LLM\",\n async () => {\n const client = await createLLMClient({});\n const styleSummary = createStyleSummary(snapshot.styles, {\n html: snapshot.html,\n tailwindTheme,\n });\n return await client.analyzeStyles(styleSummary, existingContent);\n }\n );\n\n if (result.issues.length > 0) {\n const suggestions = result.issues.map((issue) => {\n let line = `• ${issue.message}`;\n if (issue.suggestion) {\n line += `\\n ${pc.cyan(\"→\")} ${issue.suggestion}`;\n }\n return line;\n });\n\n note(\n suggestions.join(\"\\n\\n\"),\n `Found ${result.issues.length} suggestion(s)`\n );\n logInfo(\"Edit the styleguide manually to apply these changes.\");\n outro(\"Analysis complete\");\n } else {\n logSuccess(\"Style guide is up to date!\");\n outro(\"No changes needed\");\n }\n } else {\n // Parse new styles and merge\n const updatedContent = await withSpinner(\"Merging styles\", async () => {\n // Create a new guide from detected styles\n const mergedColors = new Map(snapshot.styles.colors);\n for (const m of (snapshot.html || \"\").matchAll(/#[A-Fa-f0-9]{6}\\b/g)) {\n const hex = (m[0] || \"\").toUpperCase();\n if (!hex) continue;\n mergedColors.set(hex, (mergedColors.get(hex) || 0) + 1);\n }\n\n const detectedColors = [...mergedColors.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5)\n .map(([value], index) => ({\n name: `Color ${index + 1}`,\n value: value.toUpperCase(),\n usage: \"\",\n }));\n\n const detectedGuide = {\n colors: detectedColors,\n typography: [],\n spacing: [],\n components: [],\n };\n\n // Merge with existing\n const mergedGuide = mergeStyleGuides(existingGuide, detectedGuide);\n return styleGuideToMarkdown(mergedGuide);\n });\n\n // Check if there are any changes\n if (updatedContent === existingContent) {\n logSuccess(\"Style guide is already up to date!\");\n outro(\"No changes needed\");\n return;\n }\n\n // Write updated style guide\n await withSpinner(\"Writing styleguide\", async () => {\n await writeStyleGuide(styleGuidePath, updatedContent);\n });\n\n note(`Updated: ${pc.dim(styleGuidePath)}`, \"Success\");\n outro(\"Style guide updated!\");\n }\n } catch (error) {\n logError(error instanceof Error ? error.message : \"Update failed\");\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * UILint WebSocket Server\n *\n * Provides real-time lint results for the UI overlay.\n *\n * Protocol:\n * - Client -> Server: { type: 'lint:file', filePath: string, requestId?: string }\n * - Client -> Server: { type: 'lint:element', filePath: string, dataLoc: string, requestId?: string }\n * - Client -> Server: { type: 'subscribe:file', filePath: string }\n * - Client -> Server: { type: 'cache:invalidate', filePath?: string }\n * - Client -> Server: { type: 'config:set', key: string, value: any }\n * - Client -> Server: { type: 'rule:config:set', ruleId: string, severity: 'error'|'warn'|'off', options?: object, requestId?: string }\n * - Server -> Client: { type: 'lint:result', filePath: string, issues: Issue[], requestId?: string }\n * - Server -> Client: { type: 'lint:progress', filePath: string, phase: string, requestId?: string }\n * - Server -> Client: { type: 'file:changed', filePath: string }\n * - Server -> Client: { type: 'config:update', key: string, value: any }\n * - Server -> Client: { type: 'rule:config:result', ruleId: string, severity: string, options?: object, success: boolean, error?: string, requestId?: string }\n * - Server -> Client: { type: 'rule:config:changed', ruleId: string, severity: string, options?: object }\n * - Server -> Client: { type: 'duplicates:indexing:start' }\n * - Server -> Client: { type: 'duplicates:indexing:progress', message: string, current?: number, total?: number }\n * - Server -> Client: { type: 'duplicates:indexing:complete', added: number, modified: number, deleted: number, totalChunks: number, duration: number }\n * - Server -> Client: { type: 'duplicates:indexing:error', error: string }\n * - Server -> Client: { type: 'coverage:setup:start' }\n * - Server -> Client: { type: 'coverage:setup:progress', message: string, phase: string }\n * - Server -> Client: { type: 'coverage:setup:complete', packageAdded: boolean, configModified: boolean, testsRan: boolean, coverageGenerated: boolean, duration: number, error?: string }\n * - Server -> Client: { type: 'coverage:setup:error', error: string }\n * - Client -> Server: { type: 'coverage:request', requestId?: string }\n * - Server -> Client: { type: 'coverage:result', coverage: object, timestamp: number, requestId?: string }\n * - Server -> Client: { type: 'coverage:error', error: string, requestId?: string }\n * - Client -> Server: { type: 'source:fetch', filePath: string, requestId?: string }\n * - Server -> Client: { type: 'source:result', filePath: string, content: string, totalLines: number, relativePath: string, requestId?: string }\n * - Server -> Client: { type: 'source:error', filePath: string, error: string, requestId?: string }\n * - Client -> Server: { type: 'screenshot:save', dataUrl: string, route: string, timestamp: number, requestId?: string }\n * - Server -> Client: { type: 'screenshot:saved', filename: string, path: string, requestId?: string }\n * - Server -> Client: { type: 'screenshot:error', error: string, requestId?: string }\n */\n\nimport {\n existsSync,\n statSync,\n readdirSync,\n readFileSync,\n mkdirSync,\n writeFileSync,\n unlinkSync,\n} from \"fs\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"http\";\nimport { createRequire } from \"module\";\nimport { dirname, resolve, relative, join, parse } from \"path\";\nimport { URL } from \"url\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { watch, type FSWatcher } from \"chokidar\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\n\n// Vision analysis is dynamically imported from uilint-vision/node when needed.\n// This removes the hard dependency on the vision plugin package.\nimport {\n detectNextAppRouter,\n findNextAppRouterProjects,\n} from \"../utils/next-detect.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { logWarning, pc } from \"../utils/prompts.js\";\nimport {\n enableDashboard,\n disableDashboard,\n isDashboardEnabled,\n logLint,\n logLintDone,\n logSubscribe,\n logCacheInvalidate,\n logVisionAnalyze,\n logVisionDone,\n logVisionCheck,\n logSemanticAnalyze,\n logSemanticDone,\n logSemanticSkipped,\n logConfigSet,\n logRuleConfigSet,\n logScreenshotSave,\n logScreenshotSaved,\n logCoverageResult,\n logClientConnect,\n logClientDisconnect,\n logServerError,\n logServerWarning,\n logServerInfo,\n logRuleInternalError,\n setWorkspaceInfo,\n setServerRunning,\n updateSubscriptionCount,\n updateCacheCount,\n startBackgroundTask,\n updateBackgroundTaskProgress,\n completeBackgroundTask,\n registerPlugin,\n setPluginStatus,\n updatePluginProgress,\n setPluginModel,\n} from \"./serve/dashboard/logger.js\";\nimport type { PluginId } from \"./serve/dashboard/types.js\";\nimport { ruleRegistry, type RuleOptionSchema } from \"uilint-eslint\";\nimport {\n findEslintConfigFile,\n updateRuleSeverityInConfig,\n updateRuleConfigInConfig,\n readRuleConfigsFromConfig,\n} from \"../utils/eslint-config-inject.js\";\nimport { detectCoverageSetup } from \"../utils/coverage-detect.js\";\nimport {\n prepareCoverage,\n needsCoveragePreparation,\n} from \"../utils/coverage-prepare.js\";\nimport { enrichIssuesWithScopeInfo } from \"../utils/eslint-utils.js\";\nimport {\n discoverPlugins,\n loadPluginESLintRules,\n} from \"../utils/plugin-loader.js\";\n\n// ---------------------------------------------------------------------------\n// Sentinel issue detection (generic, driven by rule metadata)\n// ---------------------------------------------------------------------------\n// Rules with fallible backends (LLM, external services) can declare\n// `sentinelMessageIds` in their metadata. Issues reported with those\n// messageIds are internal error signals, not user-facing lint issues.\n// The serve command logs them to the dashboard and filters them out.\n//\n// Built lazily so that dynamically registered plugin rules are included.\n// ---------------------------------------------------------------------------\n\n/** Lazily built set of \"ruleId:messageId\" keys for fast sentinel lookup */\nlet _sentinelKeys: Set<string> | null = null;\n\nfunction getSentinelKeys(): Set<string> {\n if (!_sentinelKeys) {\n _sentinelKeys = new Set<string>();\n for (const rule of ruleRegistry) {\n if (rule.sentinelMessageIds) {\n for (const mid of rule.sentinelMessageIds) {\n _sentinelKeys.add(`uilint/${rule.id}:${mid}`);\n }\n }\n }\n }\n return _sentinelKeys;\n}\n\n/**\n * Check if a lint issue is a sentinel (internal error) that should be\n * filtered from client results and logged to the dashboard instead.\n */\nfunction isSentinelIssue(issue: LintIssue): boolean {\n if (!issue.ruleId || !issue.messageId) return false;\n return getSentinelKeys().has(`${issue.ruleId}:${issue.messageId}`);\n}\n\nexport interface ServeOptions {\n port?: number;\n /** Disable dashboard UI (use simple logging) */\n noDashboard?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Port discovery constants\n// ---------------------------------------------------------------------------\nexport const DEFAULT_PORT = 9234;\nexport const PORT_RANGE_SIZE = 10;\n\n/**\n * Try to listen on a port. Resolves true if available, false if in use.\n */\nfunction isPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const srv = createServer();\n srv.once(\"error\", () => {\n resolve(false);\n });\n srv.once(\"listening\", () => {\n srv.close(() => resolve(true));\n });\n srv.listen(port, \"127.0.0.1\");\n });\n}\n\n/**\n * Find an available port starting from `preferred`, scanning up to\n * PORT_RANGE_SIZE ports.\n */\nasync function findAvailablePort(preferred: number): Promise<number> {\n for (let offset = 0; offset < PORT_RANGE_SIZE; offset++) {\n const port = preferred + offset;\n if (await isPortAvailable(port)) return port;\n }\n throw new Error(\n `No available ports in range ${preferred}–${\n preferred + PORT_RANGE_SIZE - 1\n }`\n );\n}\n\nexport interface LintIssue {\n line: number;\n column?: number;\n message: string;\n ruleId?: string;\n /** ESLint messageId (e.g. \"semanticIssue\", \"analysisError\") — used for sentinel detection */\n messageId?: string;\n dataLoc?: string;\n scopeInfo?: {\n enclosingScope: string | null;\n scopeType:\n | \"function\"\n | \"arrow-function\"\n | \"component\"\n | \"hook\"\n | \"method\"\n | \"class\"\n | \"module\";\n parentScope?: string;\n jsxElementType?: string;\n };\n}\n\n// Message types\ninterface LintFileMessage {\n type: \"lint:file\";\n filePath: string;\n requestId?: string;\n}\n\ninterface LintElementMessage {\n type: \"lint:element\";\n filePath: string;\n dataLoc: string;\n requestId?: string;\n}\n\ninterface SubscribeFileMessage {\n type: \"subscribe:file\";\n filePath: string;\n}\n\ninterface CacheInvalidateMessage {\n type: \"cache:invalidate\";\n filePath?: string;\n}\n\ninterface VisionAnalyzeMessage {\n type: \"vision:analyze\";\n route: string;\n timestamp: number;\n screenshot?: string;\n /** Screenshot filename persisted under `.uilint/screenshots/` (e.g. uilint-...png) */\n screenshotFile?: string;\n manifest: Record<string, unknown>[];\n requestId?: string;\n}\n\ninterface VisionCheckMessage {\n type: \"vision:check\";\n requestId?: string;\n}\n\ninterface ConfigSetMessage {\n type: \"config:set\";\n key: string;\n value: unknown;\n}\n\ninterface RuleConfigSetMessage {\n type: \"rule:config:set\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n requestId?: string;\n}\n\ninterface SourceFetchMessage {\n type: \"source:fetch\";\n filePath: string;\n requestId?: string;\n}\n\ninterface ScreenshotSaveMessage {\n type: \"screenshot:save\";\n dataUrl: string;\n route: string;\n timestamp: number;\n requestId?: string;\n}\n\ntype ClientMessage =\n | LintFileMessage\n | LintElementMessage\n | SubscribeFileMessage\n | CacheInvalidateMessage\n | VisionAnalyzeMessage\n | VisionCheckMessage\n | ConfigSetMessage\n | RuleConfigSetMessage\n | CoverageRequestMessage\n | SourceFetchMessage\n | ScreenshotSaveMessage;\n\ninterface LintResultMessage {\n type: \"lint:result\";\n filePath: string;\n issues: LintIssue[];\n requestId?: string;\n}\n\ninterface LintProgressMessage {\n type: \"lint:progress\";\n filePath: string;\n phase: string;\n requestId?: string;\n}\n\ninterface FileChangedMessage {\n type: \"file:changed\";\n filePath: string;\n}\n\ninterface WorkspaceInfoMessage {\n type: \"workspace:info\";\n /**\n * Absolute path to the Next.js app project root (dir containing app/ or src/app/).\n * This is the base dir we should use to resolve `data-loc` relative file paths.\n */\n appRoot: string;\n workspaceRoot: string;\n serverCwd: string;\n}\n\ninterface WorkspaceCapabilitiesMessage {\n type: \"workspace:capabilities\";\n postToolUseHook: {\n enabled: boolean;\n provider: \"claude\" | \"cursor\" | null;\n };\n}\n\ninterface VisionResultMessage {\n type: \"vision:result\";\n route: string;\n issues: Record<string, unknown>[];\n analysisTime: number;\n error?: string;\n requestId?: string;\n}\n\ninterface VisionProgressMessage {\n type: \"vision:progress\";\n route: string;\n phase: string;\n requestId?: string;\n}\n\ninterface VisionStatusMessage {\n type: \"vision:status\";\n available: boolean;\n model?: string;\n requestId?: string;\n}\n\ninterface RulesMetadataMessage {\n type: \"rules:metadata\";\n rules: Array<{\n id: string;\n name: string;\n description: string;\n category: string;\n defaultSeverity: \"error\" | \"warn\" | \"off\";\n /** Current severity from ESLint config (may differ from default) */\n currentSeverity?: \"error\" | \"warn\" | \"off\";\n /** Current options from ESLint config */\n currentOptions?: Record<string, unknown>;\n docs?: string;\n optionSchema?: RuleOptionSchema;\n defaultOptions?: unknown[];\n }>;\n}\n\ninterface ConfigUpdateMessage {\n type: \"config:update\";\n key: string;\n value: unknown;\n}\n\ninterface RuleConfigResultMessage {\n type: \"rule:config:result\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n success: boolean;\n error?: string;\n requestId?: string;\n}\n\ninterface RuleConfigChangedMessage {\n type: \"rule:config:changed\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n}\n\n// Duplicates indexing messages\ninterface DuplicatesIndexingStartMessage {\n type: \"duplicates:indexing:start\";\n}\n\ninterface DuplicatesIndexingProgressMessage {\n type: \"duplicates:indexing:progress\";\n message: string;\n current?: number;\n total?: number;\n}\n\ninterface DuplicatesIndexingCompleteMessage {\n type: \"duplicates:indexing:complete\";\n added: number;\n modified: number;\n deleted: number;\n totalChunks: number;\n duration: number;\n}\n\ninterface DuplicatesIndexingErrorMessage {\n type: \"duplicates:indexing:error\";\n error: string;\n}\n\n// Coverage heatmap messages\ninterface CoverageRequestMessage {\n type: \"coverage:request\";\n requestId?: string;\n}\n\ninterface CoverageResultMessage {\n type: \"coverage:result\";\n coverage: Record<string, unknown>;\n timestamp: number;\n requestId?: string;\n}\n\ninterface CoverageErrorMessage {\n type: \"coverage:error\";\n error: string;\n requestId?: string;\n}\n\n// Coverage setup messages (existing)\ninterface CoverageSetupStartMessage {\n type: \"coverage:setup:start\";\n}\n\ninterface CoverageSetupProgressMessage {\n type: \"coverage:setup:progress\";\n message: string;\n phase: string;\n}\n\ninterface CoverageSetupCompleteMessage {\n type: \"coverage:setup:complete\";\n packageAdded: boolean;\n configModified: boolean;\n testsRan: boolean;\n coverageGenerated: boolean;\n duration: number;\n error?: string;\n}\n\ninterface CoverageSetupErrorMessage {\n type: \"coverage:setup:error\";\n error: string;\n}\n\ninterface SourceResultMessage {\n type: \"source:result\";\n filePath: string;\n content: string;\n totalLines: number;\n relativePath: string;\n requestId?: string;\n}\n\ninterface SourceErrorMessage {\n type: \"source:error\";\n filePath: string;\n error: string;\n requestId?: string;\n}\n\ninterface ScreenshotSavedMessage {\n type: \"screenshot:saved\";\n filename: string;\n path: string;\n requestId?: string;\n}\n\ninterface ScreenshotErrorMessage {\n type: \"screenshot:error\";\n error: string;\n requestId?: string;\n}\n\n// Generic plugin operation progress messages\ninterface PluginOperationStartMessage {\n type: \"plugin:operation:start\";\n pluginId: string;\n operationName: string;\n message?: string;\n}\n\ninterface PluginOperationProgressMessage {\n type: \"plugin:operation:progress\";\n pluginId: string;\n operationName: string;\n current?: number;\n total?: number;\n message?: string;\n}\n\ninterface PluginOperationCompleteMessage {\n type: \"plugin:operation:complete\";\n pluginId: string;\n operationName: string;\n message?: string;\n}\n\ninterface PluginOperationErrorMessage {\n type: \"plugin:operation:error\";\n pluginId: string;\n operationName: string;\n error: string;\n}\n\ntype ServerMessage =\n | LintResultMessage\n | LintProgressMessage\n | FileChangedMessage\n | WorkspaceInfoMessage\n | WorkspaceCapabilitiesMessage\n | VisionResultMessage\n | VisionProgressMessage\n | VisionStatusMessage\n | RulesMetadataMessage\n | ConfigUpdateMessage\n | RuleConfigResultMessage\n | RuleConfigChangedMessage\n | DuplicatesIndexingStartMessage\n | DuplicatesIndexingProgressMessage\n | DuplicatesIndexingCompleteMessage\n | DuplicatesIndexingErrorMessage\n | CoverageResultMessage\n | CoverageErrorMessage\n | CoverageSetupStartMessage\n | CoverageSetupProgressMessage\n | CoverageSetupCompleteMessage\n | CoverageSetupErrorMessage\n | SourceResultMessage\n | SourceErrorMessage\n | ScreenshotSavedMessage\n | ScreenshotErrorMessage\n | PluginOperationStartMessage\n | PluginOperationProgressMessage\n | PluginOperationCompleteMessage\n | PluginOperationErrorMessage;\n\nfunction pickAppRoot(params: { cwd: string; workspaceRoot: string }): string {\n const { cwd, workspaceRoot } = params;\n\n // If started from a Next.js app root (app/ or src/app/ exists), use cwd.\n if (detectNextAppRouter(cwd)) return cwd;\n\n // Otherwise, try to discover Next apps from the workspace root.\n const matches = findNextAppRouterProjects(workspaceRoot, { maxDepth: 5 });\n if (matches.length === 0) return cwd;\n if (matches.length === 1) return matches[0]!.projectPath;\n\n // Prefer a project that contains the current cwd (common in monorepos).\n const containing = matches.find(\n (m) => cwd === m.projectPath || cwd.startsWith(m.projectPath + \"/\")\n );\n if (containing) return containing.projectPath;\n\n // Fallback: pick the first match deterministically.\n return matches[0]!.projectPath;\n}\n\n/**\n * Detect if a post-tool-use hook is configured for Claude or Cursor.\n * These hooks can automatically run ESLint when files are edited.\n */\nfunction detectPostToolUseHook(projectRoot: string): {\n enabled: boolean;\n provider: \"claude\" | \"cursor\" | null;\n} {\n // Check Claude settings.json for PostToolUse hooks\n const claudeSettingsPath = join(projectRoot, \".claude\", \"settings.json\");\n if (existsSync(claudeSettingsPath)) {\n try {\n const content = readFileSync(claudeSettingsPath, \"utf-8\");\n const settings = JSON.parse(content);\n const hooks = settings.hooks?.PostToolUse;\n if (Array.isArray(hooks)) {\n // Check if any hook matches Edit or Write tools\n const hasEditHook = hooks.some(\n (h: { matcher?: string }) =>\n h.matcher?.includes(\"Edit\") || h.matcher?.includes(\"Write\")\n );\n if (hasEditHook) {\n return { enabled: true, provider: \"claude\" };\n }\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n // Check Cursor hooks.json\n const cursorHooksPath = join(projectRoot, \".cursor\", \"hooks.json\");\n if (existsSync(cursorHooksPath)) {\n try {\n const content = readFileSync(cursorHooksPath, \"utf-8\");\n const hooks = JSON.parse(content);\n if (hooks.hooks?.afterFileEdit?.length > 0) {\n return { enabled: true, provider: \"cursor\" };\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n return { enabled: false, provider: null };\n}\n\n// Simple in-memory cache\ninterface CacheEntry {\n issues: LintIssue[];\n mtimeMs: number;\n timestamp: number;\n}\n\nconst cache = new Map<string, CacheEntry>();\n\n// Separate caches for two-pass lint\nconst fastCache = new Map<string, CacheEntry>();\nconst semanticCache = new Map<string, CacheEntry>();\n\n/** Minimal ESLint API surface used by the serve command. */\ninterface ESLintInstance {\n lintFiles(\n files: string[]\n ): Promise<Array<{ messages: Record<string, unknown>[] }>>;\n}\n\n// ESLint instances cached per detected project root\nconst eslintInstances = new Map<string, unknown>();\n\n// ESLint instances with semantic rule disabled (for fast pass)\nconst eslintFastInstances = new Map<string, unknown>();\n\n// Vision module is dynamically imported to avoid hard dependency on uilint-vision.\nlet visionModule: Record<string, unknown> | null = null;\nlet visionAnalyzer: unknown = null;\n\nasync function getVisionModule(): Promise<Record<string, unknown> | null> {\n if (visionModule) return visionModule;\n try {\n visionModule = await import(\"uilint-vision/node\");\n return visionModule;\n } catch {\n return null;\n }\n}\n\nasync function getVisionAnalyzerInstance(): Promise<unknown> {\n if (visionAnalyzer) return visionAnalyzer;\n const mod = await getVisionModule();\n if (!mod) return null;\n visionAnalyzer = (\n mod as Record<string, (...args: unknown[]) => unknown>\n ).getVisionAnalyzer();\n return visionAnalyzer;\n}\n\n// =============================================================================\n// Ollama Mutex (tracked)\n// =============================================================================\n// Prevents concurrent Ollama model usage between plugins. Ollama needs to swap\n// models in/out of VRAM, and concurrent requests cause contention and slowdowns.\n// Tracks current holder and queue for dashboard display.\n\nlet ollamaMutexPromise: Promise<void> = Promise.resolve();\nlet ollamaMutexHolder: PluginId | null = null;\nconst ollamaMutexQueue: PluginId[] = [];\n\n/**\n * Acquire exclusive access to Ollama. Returns a release function.\n * Tracks the requester for dashboard display.\n *\n * Usage:\n * const release = await acquireOllamaMutex(\"semantic\");\n * try { ... } finally { release(); }\n */\nfunction acquireOllamaMutex(pluginId: PluginId): Promise<() => void> {\n let release: () => void;\n const prev = ollamaMutexPromise;\n ollamaMutexPromise = new Promise<void>((resolve) => {\n release = resolve;\n });\n\n // Mark this plugin as waiting in the queue\n ollamaMutexQueue.push(pluginId);\n setPluginStatus(pluginId, \"waiting-for-ollama\", \"Queued for Ollama...\");\n\n return prev.then(() => {\n // Granted: remove from queue, mark as holder\n const idx = ollamaMutexQueue.indexOf(pluginId);\n if (idx !== -1) ollamaMutexQueue.splice(idx, 1);\n ollamaMutexHolder = pluginId;\n setPluginStatus(pluginId, \"using-ollama\", \"Using Ollama...\");\n\n return () => {\n // Release: clear holder tracking\n if (ollamaMutexHolder === pluginId) {\n ollamaMutexHolder = null;\n }\n release!();\n };\n });\n}\n\n// Semantic analysis batch progress tracking.\n// Counts files that pass validation and commit to LLM analysis.\nlet semanticFilesRequested = 0;\nlet semanticFilesCompleted = 0;\nlet semanticIdleResetTimer: ReturnType<typeof setTimeout> | null = null;\n\n/** Push current batch progress to the dashboard. */\nfunction updateSemanticBatchProgress(message: string): void {\n const progress =\n semanticFilesRequested > 0\n ? Math.round((semanticFilesCompleted / semanticFilesRequested) * 100)\n : 0;\n updatePluginProgress(\n \"semantic\",\n progress,\n semanticFilesCompleted,\n semanticFilesRequested,\n message\n );\n}\n\n/**\n * Mark one semantic file as done (success or error).\n * If all queued files are finished, show terminal status and schedule idle reset.\n * Otherwise, update batch progress and stay active.\n */\nfunction completeSemanticFile(\n terminalStatus: \"complete\" | \"error\",\n message: string\n): void {\n semanticFilesCompleted++;\n\n if (semanticFilesCompleted >= semanticFilesRequested) {\n const summary =\n terminalStatus === \"complete\"\n ? `Done: ${semanticFilesCompleted} file(s) analyzed`\n : message;\n setPluginStatus(\"semantic\", terminalStatus, summary);\n semanticIdleResetTimer = setTimeout(() => {\n setPluginStatus(\"semantic\", \"idle\");\n semanticFilesRequested = 0;\n semanticFilesCompleted = 0;\n semanticIdleResetTimer = null;\n }, 3000);\n } else {\n updateSemanticBatchProgress(\n `${semanticFilesCompleted}/${semanticFilesRequested} files analyzed`\n );\n }\n}\n\n// Default styleguide search root for vision analysis (set when `serve()` starts)\nlet serverAppRootForVision = process.cwd();\n\nfunction isValidScreenshotFilename(filename: string): boolean {\n // Only allow alphanumeric, hyphens, underscores, and dots; must end with a safe image extension.\n const validPattern = /^[a-zA-Z0-9_-]+\\.(png|jpeg|jpg)$/;\n return validPattern.test(filename) && !filename.includes(\"..\");\n}\n\n// Cache resolved paths for incoming filePath strings\nconst resolvedPathCache = new Map<string, string>();\n\n// File subscriptions: absolutePath -> Set of clients (and the original client filePath string)\nconst subscriptions = new Map<\n string,\n Set<{ ws: WebSocket; clientFilePath: string }>\n>();\n\n// File watcher\nlet fileWatcher: FSWatcher | null = null;\n\n// Basic client tracking for CLI feedback\nlet connectedClients = 0;\n\n// Local require (from uilint deps) for TSX parsing\nconst localRequire = createRequire(import.meta.url);\n\ntype JsxElementSpan = {\n start: number;\n end: number;\n dataLoc: string;\n};\n\nfunction buildLineStarts(code: string): number[] {\n const starts: number[] = [0];\n for (let i = 0; i < code.length; i++) {\n if (code.charCodeAt(i) === 10) starts.push(i + 1); // \\n\n }\n return starts;\n}\n\nfunction offsetFromLineCol(\n lineStarts: number[],\n line1: number,\n col0: number,\n codeLength: number\n): number {\n const lineIndex = Math.max(0, Math.min(lineStarts.length - 1, line1 - 1));\n const base = lineStarts[lineIndex] ?? 0;\n return Math.max(0, Math.min(codeLength, base + Math.max(0, col0)));\n}\n\nfunction buildJsxElementSpans(\n code: string,\n dataLocFile: string\n): JsxElementSpan[] {\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (\n src: string,\n options: Record<string, unknown>\n ) => Record<string, unknown>;\n };\n\n const ast = parse(code, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n\n const spans: JsxElementSpan[] = [];\n\n function walk(node: Record<string, unknown>): void {\n if (!node || typeof node !== \"object\") return;\n\n // Prefer mapping to JSXElement range so we can capture nested ownership precisely.\n if (node.type === \"JSXElement\") {\n const range = node.range as [number, number] | undefined;\n const opening = node.openingElement as\n | Record<string, unknown>\n | undefined;\n const loc = (opening?.loc as Record<string, unknown> | undefined)\n ?.start as Record<string, unknown> | undefined;\n if (\n range &&\n typeof range[0] === \"number\" &&\n typeof range[1] === \"number\" &&\n loc &&\n typeof loc.line === \"number\" &&\n typeof loc.column === \"number\"\n ) {\n const dataLoc = `${dataLocFile}:${loc.line}:${loc.column}`;\n spans.push({ start: range[0], end: range[1], dataLoc });\n }\n }\n\n for (const key of Object.keys(node)) {\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) walk(item as Record<string, unknown>);\n } else if (child && typeof child === \"object\") {\n walk(child as Record<string, unknown>);\n }\n }\n }\n\n walk(ast);\n\n // Keep spans small-first to make “smallest containing span” selection fast.\n spans.sort((a, b) => a.end - a.start - (b.end - b.start));\n return spans;\n}\n\nfunction mapMessageToDataLoc(params: {\n spans: JsxElementSpan[];\n lineStarts: number[];\n codeLength: number;\n messageLine1: number;\n messageCol1?: number;\n}): string | undefined {\n const col0 =\n typeof params.messageCol1 === \"number\"\n ? Math.max(0, params.messageCol1 - 1)\n : 0;\n const offset = offsetFromLineCol(\n params.lineStarts,\n params.messageLine1,\n col0,\n params.codeLength\n );\n\n // Pick the smallest JSXElement range that contains this offset.\n for (const s of params.spans) {\n if (s.start <= offset && offset < s.end) return s.dataLoc;\n }\n return undefined;\n}\n\n/**\n * Known ESLint config filenames (flat + legacy).\n */\nconst ESLINT_CONFIG_FILES = [\n // Flat config (ESLint v9+)\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n \"eslint.config.ts\",\n // Legacy config\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n];\n\n/**\n * Find a project root directory for ESLint by walking upward from a file dir.\n */\nfunction findESLintCwd(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 30; i++) {\n for (const cfg of ESLINT_CONFIG_FILES) {\n if (existsSync(join(dir, cfg))) return dir;\n }\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\nfunction normalizePathSlashes(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\n/**\n * Match `jsx-loc-plugin` behavior:\n * - Use a stable, project-relative path when possible, otherwise absolute.\n */\nfunction normalizeDataLocFilePath(\n absoluteFilePath: string,\n projectCwd: string\n): string {\n const abs = normalizePathSlashes(resolve(absoluteFilePath));\n const cwd = normalizePathSlashes(resolve(projectCwd));\n if (abs === cwd || abs.startsWith(cwd + \"/\")) {\n return normalizePathSlashes(relative(cwd, abs));\n }\n return abs;\n}\n\nfunction resolveRequestedFilePath(filePath: string): string {\n // Absolute (POSIX) or Windows drive path\n if (filePath.startsWith(\"/\") || /^[A-Za-z]:[\\\\/]/.test(filePath)) {\n return resolve(filePath);\n }\n\n const cached = resolvedPathCache.get(filePath);\n if (cached) return cached;\n\n const cwd = process.cwd();\n const fromCwd = resolve(cwd, filePath);\n if (existsSync(fromCwd)) {\n resolvedPathCache.set(filePath, fromCwd);\n return fromCwd;\n }\n\n const wsRoot = findWorkspaceRoot(cwd);\n const fromWs = resolve(wsRoot, filePath);\n if (existsSync(fromWs)) {\n resolvedPathCache.set(filePath, fromWs);\n return fromWs;\n }\n\n // Monorepo helper: try common workspace folders (apps/*, packages/*)\n // Example: filePath=\"app/page.tsx\" -> apps/test-app/app/page.tsx\n for (const top of [\"apps\", \"packages\"]) {\n const base = join(wsRoot, top);\n if (!existsSync(base)) continue;\n try {\n const entries = readdirSync(base, { withFileTypes: true });\n for (const ent of entries) {\n if (!ent.isDirectory()) continue;\n const p = resolve(base, ent.name, filePath);\n if (existsSync(p)) {\n resolvedPathCache.set(filePath, p);\n return p;\n }\n }\n } catch {\n // ignore\n }\n }\n\n // Cache deterministic fallback so repeated requests don't thrash\n resolvedPathCache.set(filePath, fromCwd);\n return fromCwd;\n}\n\nasync function getESLintForProject(projectCwd: string): Promise<unknown> {\n const cached = eslintInstances.get(projectCwd);\n if (cached) return cached;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n\n const mod = req(\"eslint\") as Record<string, unknown>;\n const modDefault = mod?.default as Record<string, unknown> | undefined;\n const ESLintCtor = mod?.ESLint ?? modDefault?.ESLint ?? mod?.default ?? mod;\n if (!ESLintCtor) return null;\n\n const Ctor = ESLintCtor as new (opts: Record<string, unknown>) => unknown;\n const eslint = new Ctor({ cwd: projectCwd });\n eslintInstances.set(projectCwd, eslint);\n return eslint;\n } catch {\n return null;\n }\n}\n\n/**\n * Create an ESLint instance with rule overrides (for two-pass lint).\n * Uses ESLint 9 flat config's overrideConfig option.\n */\nasync function getESLintWithOverrides(\n projectCwd: string,\n overrideRules: Record<string, string>,\n instanceCache: Map<string, unknown>\n): Promise<unknown> {\n const cacheKey = `${projectCwd}::${JSON.stringify(overrideRules)}`;\n const cached = instanceCache.get(cacheKey);\n if (cached) return cached;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n const mod = req(\"eslint\") as Record<string, unknown>;\n const modDefault = mod?.default as Record<string, unknown> | undefined;\n const ESLintCtor = mod?.ESLint ?? modDefault?.ESLint ?? mod?.default ?? mod;\n if (!ESLintCtor) return null;\n\n const Ctor = ESLintCtor as new (opts: Record<string, unknown>) => unknown;\n const eslint = new Ctor({\n cwd: projectCwd,\n overrideConfig: { rules: overrideRules },\n });\n instanceCache.set(cacheKey, eslint);\n return eslint;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if the semantic rule is enabled in the ESLint config.\n */\nfunction isSemanticRuleEnabled(): boolean {\n const eslintConfigPath = findEslintConfigFile(serverAppRootForVision);\n if (!eslintConfigPath) return false;\n\n const ruleConfigs = readRuleConfigsFromConfig(eslintConfigPath);\n const semanticConfig = ruleConfigs.get(\"semantic\");\n if (!semanticConfig) return false;\n\n return semanticConfig.severity !== \"off\";\n}\n\n/**\n * Process raw ESLint messages into LintIssue[] with JSX mapping and scope info.\n * Shared between fast and semantic passes.\n */\nfunction processLintResults(\n absolutePath: string,\n projectCwd: string,\n messages: Record<string, unknown>[],\n onProgress: (phase: string) => void\n): LintIssue[] {\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n let spans: JsxElementSpan[] = [];\n let lineStarts: number[] = [];\n let codeLength = 0;\n let fileCode: string | null = null;\n\n try {\n onProgress(\"Building JSX map...\");\n fileCode = readFileSync(absolutePath, \"utf-8\");\n codeLength = fileCode.length;\n lineStarts = buildLineStarts(fileCode);\n spans = buildJsxElementSpans(fileCode, dataLocFile);\n onProgress(`JSX map: ${spans.length} element(s)`);\n } catch (e) {\n onProgress(\"JSX map failed (falling back to unmapped issues)\");\n logServerError(\n \"JSX map failed\",\n e instanceof Error ? e.message : String(e)\n );\n spans = [];\n lineStarts = [];\n codeLength = 0;\n fileCode = null;\n }\n\n let issues: LintIssue[] = messages\n .filter((m: Record<string, unknown>) => typeof m?.message === \"string\")\n .map((m: Record<string, unknown>) => {\n const line = typeof m.line === \"number\" ? m.line : 1;\n const column = typeof m.column === \"number\" ? m.column : undefined;\n const mappedDataLoc =\n spans.length > 0 && lineStarts.length > 0 && codeLength > 0\n ? mapMessageToDataLoc({\n spans,\n lineStarts,\n codeLength,\n messageLine1: line,\n messageCol1: column,\n })\n : undefined;\n return {\n line,\n column,\n message: m.message as string,\n ruleId: typeof m.ruleId === \"string\" ? m.ruleId : undefined,\n messageId: typeof m.messageId === \"string\" ? m.messageId : undefined,\n dataLoc: mappedDataLoc,\n } satisfies LintIssue;\n });\n\n const mappedCount = issues.filter((i) => Boolean(i.dataLoc)).length;\n if (issues.length > 0) {\n onProgress(\n `Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`\n );\n }\n\n // Enrich issues with scope information\n if (fileCode && issues.length > 0) {\n onProgress(\"Extracting scope info...\");\n issues = enrichIssuesWithScopeInfo(issues, fileCode);\n const scopeCount = issues.filter((i) => Boolean(i.scopeInfo)).length;\n onProgress(\n `Enriched ${scopeCount}/${issues.length} issue(s) with scope info`\n );\n }\n\n return issues;\n}\n\n/**\n * Fast lint pass: runs all rules EXCEPT semantic.\n * Non-blocking (no spawnSync calls).\n */\nasync function lintFileFast(\n filePath: string,\n onProgress: (phase: string) => void\n): Promise<LintIssue[]> {\n const absolutePath = resolveRequestedFilePath(filePath);\n\n if (!existsSync(absolutePath)) {\n onProgress(`File not found: ${pc.dim(absolutePath)}`);\n return [];\n }\n\n const mtimeMs = (() => {\n try {\n return statSync(absolutePath).mtimeMs;\n } catch {\n return 0;\n }\n })();\n\n // Check fast-pass cache\n const cached = fastCache.get(absolutePath);\n if (cached && cached.mtimeMs === mtimeMs) {\n onProgress(\"Cache hit (unchanged)\");\n return cached.issues;\n }\n\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n onProgress(`Resolving ESLint project... ${pc.dim(projectCwd)}`);\n\n const eslint = await getESLintWithOverrides(\n projectCwd,\n { \"uilint/semantic\": \"off\" },\n eslintFastInstances\n );\n if (!eslint) {\n logWarning(\n `ESLint not found in project. Install it in ${pc.dim(\n projectCwd\n )} to enable server-side linting.`\n );\n onProgress(\"ESLint not available (install eslint in this project)\");\n return [];\n }\n\n try {\n onProgress(\"Running ESLint...\");\n const results = await (eslint as ESLintInstance).lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n const issues = processLintResults(\n absolutePath,\n projectCwd,\n messages,\n onProgress\n );\n\n fastCache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n logServerError(\n \"ESLint fast pass failed\",\n error instanceof Error ? error.message : String(error)\n );\n return [];\n }\n}\n\n/**\n * Semantic lint pass: runs ALL ESLint rules then filters to only semantic results.\n * This blocks the event loop via spawnSync in the semantic rule, so it should\n * be called from a deferred context (setImmediate).\n */\nasync function lintFileSemantic(\n filePath: string,\n onProgress: (phase: string) => void\n): Promise<LintIssue[]> {\n const absolutePath = resolveRequestedFilePath(filePath);\n\n if (!existsSync(absolutePath)) return [];\n\n const mtimeMs = (() => {\n try {\n return statSync(absolutePath).mtimeMs;\n } catch {\n return 0;\n }\n })();\n\n // Check semantic-pass cache\n const cached = semanticCache.get(absolutePath);\n if (cached && cached.mtimeMs === mtimeMs) {\n onProgress(\"Semantic cache hit (unchanged)\");\n return cached.issues;\n }\n\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n // Use the default ESLint instance (all rules enabled including semantic)\n const eslint = await getESLintForProject(projectCwd);\n if (!eslint) return [];\n\n try {\n onProgress(\"Running semantic analysis...\");\n const results = await (eslint as ESLintInstance).lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n // Filter to only semantic rule results\n const semanticMessages = messages.filter(\n (m: Record<string, unknown>) => m.ruleId === \"uilint/semantic\"\n );\n\n if (semanticMessages.length === 0) return [];\n\n const issues = processLintResults(\n absolutePath,\n projectCwd,\n semanticMessages,\n onProgress\n );\n\n semanticCache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n logServerError(\n \"Semantic pass failed\",\n error instanceof Error ? error.message : String(error)\n );\n return [];\n }\n}\n\n/**\n * Run semantic analysis asynchronously using OllamaClient.\n * Unlike lintFileSemantic (which runs ESLint + spawnSync), this calls Ollama\n * directly via its HTTP API, writes results to the ESLint rule's disk cache,\n * and sends lint:result to the client. Completely non-blocking.\n */\nasync function runSemanticAnalysisAsync(\n filePath: string,\n ws: WebSocket,\n requestId?: string\n): Promise<void> {\n const startTime = Date.now();\n logSemanticAnalyze(filePath, requestId);\n\n const absolutePath = resolveRequestedFilePath(filePath);\n if (!existsSync(absolutePath)) {\n logSemanticSkipped(filePath, \"file not found\");\n return;\n }\n\n // Read the semantic rule's config to get the model\n const eslintConfigPath = findEslintConfigFile(serverAppRootForVision);\n const ruleConfigs = eslintConfigPath\n ? readRuleConfigsFromConfig(eslintConfigPath)\n : new Map<\n string,\n {\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n }\n >();\n const semanticConfig = ruleConfigs.get(\"semantic\");\n const model =\n (semanticConfig?.options?.model as string) || \"qwen3-vl:8b-instruct\";\n const styleguidePath =\n (semanticConfig?.options?.styleguidePath as string) || undefined;\n setPluginModel(\"semantic\", model);\n\n // Load styleguide\n const { getStyleguide, hashContentSync, setCacheEntry, getCacheEntry } =\n await import(\"uilint-eslint\");\n const fileDir = dirname(absolutePath);\n const { content: styleguide } = getStyleguide(fileDir, styleguidePath);\n if (!styleguide) {\n logSemanticSkipped(filePath, \"no styleguide found\");\n return;\n }\n\n // Read and hash file contents\n let fileContent: string;\n try {\n fileContent = readFileSync(absolutePath, \"utf-8\");\n } catch {\n logSemanticSkipped(filePath, \"file read error\");\n return;\n }\n\n const fileHash = hashContentSync(fileContent);\n const styleguideHash = hashContentSync(styleguide);\n\n // Find project root for cache\n const projectRoot = findWorkspaceRoot(fileDir) || fileDir;\n const relativeFilePath = relative(projectRoot, absolutePath);\n\n // Check if cache is already fresh\n const cached = getCacheEntry(\n projectRoot,\n relativeFilePath,\n fileHash,\n styleguideHash\n );\n if (cached) {\n logSemanticSkipped(filePath, \"cache fresh\");\n return;\n }\n\n // Track this file in the semantic batch progress\n if (semanticIdleResetTimer) {\n clearTimeout(semanticIdleResetTimer);\n semanticIdleResetTimer = null;\n }\n semanticFilesRequested++;\n updateSemanticBatchProgress(\n `Queued ${relative(serverAppRootForVision, absolutePath)}...`\n );\n\n // Report progress\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Running semantic analysis (async)...\",\n });\n\n startBackgroundTask(\n \"semantic-analysis\",\n \"Semantic Analysis\",\n `Analyzing ${filePath}...`\n );\n broadcast({\n type: \"plugin:operation:start\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n message: `Analyzing ${relative(serverAppRootForVision, absolutePath)}...`,\n });\n\n // Acquire mutex to avoid Ollama model contention\n const release = await acquireOllamaMutex(\"semantic\");\n\n try {\n const { OllamaClient, buildSourceScanPrompt } = await import(\n \"uilint-core/node\"\n );\n const client = new OllamaClient({ model });\n\n const ok = await client.isAvailable();\n if (!ok) {\n logServerWarning(\"Semantic analysis: Ollama not available\");\n updateBackgroundTaskProgress(\n \"semantic-analysis\",\n 0,\n 0,\n 0,\n \"Ollama not available\"\n );\n completeBackgroundTask(\n \"semantic-analysis\",\n undefined,\n \"Ollama not available\"\n );\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n error: \"Ollama not available\",\n });\n completeSemanticFile(\"error\", \"Ollama not available\");\n return;\n }\n\n updateBackgroundTaskProgress(\n \"semantic-analysis\",\n 50,\n 0,\n 0,\n \"Waiting for LLM response...\"\n );\n updateSemanticBatchProgress(\n `Analyzing ${relative(serverAppRootForVision, absolutePath)}...`\n );\n broadcast({\n type: \"plugin:operation:progress\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n message: \"Waiting for LLM response...\",\n });\n\n const prompt = buildSourceScanPrompt(fileContent, styleguide, {\n filePath: relative(serverAppRootForVision, absolutePath),\n });\n\n const responseText = await client.complete(prompt, { json: true });\n const parsed = JSON.parse(responseText) as {\n issues?: Array<{ line?: number; column?: number; message?: string }>;\n };\n\n const issues = (parsed.issues || []).map((issue) => ({\n line: issue.line || 1,\n column: issue.column,\n message: issue.message || \"Semantic issue detected\",\n ruleId: \"uilint/semantic\",\n severity: 1 as const,\n }));\n\n // Write to the ESLint rule's disk cache\n setCacheEntry(projectRoot, relativeFilePath, {\n fileHash,\n styleguideHash,\n issues,\n timestamp: Date.now(),\n });\n\n // Convert to LintIssue format for the WS result\n const fileDir2 = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir2);\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n const lintIssues: LintIssue[] = issues.map((issue) => ({\n ruleId: \"uilint/semantic\",\n severity: issue.severity,\n message: issue.message,\n line: issue.line,\n column: issue.column || 0,\n nodeType: null,\n source: null,\n dataLoc: `${dataLocFile}:${issue.line}:${issue.column || 0}`,\n }));\n\n // Always send results (even if empty) so client knows analysis finished\n sendMessage(ws, {\n type: \"lint:result\",\n filePath,\n requestId,\n issues: lintIssues,\n });\n\n const elapsed = Date.now() - startTime;\n const msg = `${issues.length} issue(s) found`;\n logSemanticDone(filePath, issues.length, elapsed);\n completeBackgroundTask(\"semantic-analysis\", msg);\n completeSemanticFile(\"complete\", msg);\n broadcast({\n type: \"plugin:operation:complete\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n message: msg,\n });\n\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (semantic: ${issues.length} issues)`,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logServerError(\"Async semantic analysis failed\", errorMessage);\n completeBackgroundTask(\"semantic-analysis\", undefined, errorMessage);\n completeSemanticFile(\"error\", errorMessage);\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"semantic\",\n operationName: \"analysis\",\n error: errorMessage,\n });\n } finally {\n release();\n }\n}\n\n/**\n * Run vision analysis in the background (fire-and-forget).\n * Extracted from the vision:analyze handler to avoid blocking handleMessage.\n */\nasync function runVisionAnalysisInBackground(\n ws: WebSocket,\n message: VisionAnalyzeMessage\n): Promise<void> {\n const { route, timestamp, screenshot, screenshotFile, manifest, requestId } =\n message;\n\n setPluginStatus(\"vision\", \"processing\", `Analyzing ${route}...`);\n startBackgroundTask(\n \"vision-analysis\",\n \"Vision Analysis\",\n `Analyzing ${route}...`\n );\n broadcast({\n type: \"plugin:operation:start\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n message: `Analyzing ${route}...`,\n });\n\n const visionMod = await getVisionModule();\n if (!visionMod) {\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: 0,\n error: \"uilint-vision is not installed\",\n requestId,\n });\n completeBackgroundTask(\n \"vision-analysis\",\n undefined,\n \"uilint-vision not installed\"\n );\n setPluginStatus(\"vision\", \"error\", \"uilint-vision not installed\");\n setTimeout(() => setPluginStatus(\"vision\", \"idle\"), 3000);\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n error: \"uilint-vision not installed\",\n });\n return;\n }\n\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase: \"Starting vision analysis...\",\n });\n\n const startedAt = Date.now();\n const analyzer = await getVisionAnalyzerInstance();\n\n updateBackgroundTaskProgress(\n \"vision-analysis\",\n 10,\n 0,\n 0,\n \"Waiting for Ollama...\"\n );\n\n // Acquire exclusive access to Ollama to avoid model contention\n const releaseOllama = await acquireOllamaMutex(\"vision\");\n\n try {\n const analyzerObj = analyzer as Record<string, unknown> | null;\n const analyzerModel =\n typeof analyzerObj?.getModel === \"function\"\n ? (analyzerObj.getModel as () => string)()\n : undefined;\n const analyzerBaseUrl =\n typeof analyzerObj?.getBaseUrl === \"function\"\n ? (analyzerObj.getBaseUrl as () => string)()\n : undefined;\n\n if (analyzerModel) {\n setPluginModel(\"vision\", analyzerModel);\n }\n\n if (!screenshot) {\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: Date.now() - startedAt,\n error: \"No screenshot provided for vision analysis\",\n requestId,\n });\n completeBackgroundTask(\n \"vision-analysis\",\n undefined,\n \"No screenshot provided\"\n );\n setPluginStatus(\"vision\", \"error\", \"No screenshot provided\");\n setTimeout(() => setPluginStatus(\"vision\", \"idle\"), 3000);\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n error: \"No screenshot provided\",\n });\n return;\n }\n\n updateBackgroundTaskProgress(\n \"vision-analysis\",\n 30,\n 0,\n 0,\n \"Running vision analysis...\"\n );\n broadcast({\n type: \"plugin:operation:progress\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n message: \"Running vision analysis...\",\n });\n\n const result = (await (\n visionMod as Record<\n string,\n (...args: unknown[]) => Promise<Record<string, unknown>>\n >\n ).runVisionAnalysis({\n imageBase64: screenshot,\n manifest,\n projectPath: serverAppRootForVision,\n baseUrl: analyzerBaseUrl,\n model: analyzerModel,\n analyzer,\n onPhase: (phase: string) => {\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase,\n });\n updateBackgroundTaskProgress(\"vision-analysis\", 50, 0, 0, phase);\n },\n pathResolver: resolvePathSpecifier,\n })) as Record<string, unknown>;\n\n // Write markdown report (best-effort)\n if (typeof screenshotFile === \"string\" && screenshotFile.length > 0) {\n if (isValidScreenshotFilename(screenshotFile)) {\n const screenshotsDir = join(\n serverAppRootForVision,\n \".uilint\",\n \"screenshots\"\n );\n const imagePath = join(screenshotsDir, screenshotFile);\n try {\n if (existsSync(imagePath)) {\n const report = (\n visionMod as Record<\n string,\n (...args: unknown[]) => Record<string, unknown>\n >\n ).writeVisionMarkdownReport({\n imagePath,\n route,\n timestamp,\n visionModel: result.visionModel,\n baseUrl: result.baseUrl,\n analysisTimeMs: result.analysisTime,\n prompt: result.prompt ?? null,\n rawResponse: result.rawResponse ?? null,\n metadata: {\n screenshotFile: parse(imagePath).base,\n appRoot: serverAppRootForVision,\n manifestElements: manifest.length,\n requestId: requestId ?? null,\n },\n });\n logServerInfo(`Wrote vision report`, report.outPath as string);\n }\n } catch (e) {\n logServerWarning(\n `Failed to write vision report for ${screenshotFile}`,\n e instanceof Error ? e.message : String(e)\n );\n }\n }\n }\n\n const elapsed = Date.now() - startedAt;\n const resultIssues = result.issues as Record<string, unknown>[];\n logVisionDone(route, resultIssues.length, elapsed);\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: resultIssues,\n analysisTime: result.analysisTime as number,\n requestId,\n });\n\n const msg = `${resultIssues.length} issue(s) in ${(elapsed / 1000).toFixed(\n 1\n )}s`;\n completeBackgroundTask(\"vision-analysis\", msg);\n setPluginStatus(\"vision\", \"complete\", msg);\n setTimeout(() => setPluginStatus(\"vision\", \"idle\"), 3000);\n broadcast({\n type: \"plugin:operation:complete\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n message: msg,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const elapsed = Date.now() - startedAt;\n logServerError(`Vision analysis failed for ${route}`, errorMessage);\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: elapsed,\n error: errorMessage,\n requestId,\n });\n completeBackgroundTask(\"vision-analysis\", undefined, errorMessage);\n setPluginStatus(\"vision\", \"error\", errorMessage);\n setTimeout(() => setPluginStatus(\"vision\", \"idle\"), 3000);\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"vision\",\n operationName: \"analysis\",\n error: errorMessage,\n });\n } finally {\n releaseOllama();\n }\n}\n\n/**\n * Lint a file and return issues (legacy single-pass, used for backwards compat)\n */\nasync function _lintFile(\n filePath: string,\n onProgress: (phase: string) => void\n): Promise<LintIssue[]> {\n const absolutePath = resolveRequestedFilePath(filePath);\n\n // Check if file exists\n if (!existsSync(absolutePath)) {\n onProgress(`File not found: ${pc.dim(absolutePath)}`);\n return [];\n }\n\n const mtimeMs = (() => {\n try {\n return statSync(absolutePath).mtimeMs;\n } catch {\n return 0;\n }\n })();\n\n // Check cache (mtime-based)\n const cached = cache.get(absolutePath);\n if (cached && cached.mtimeMs === mtimeMs) {\n onProgress(\"Cache hit (unchanged)\");\n return cached.issues;\n }\n\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n onProgress(`Resolving ESLint project... ${pc.dim(projectCwd)}`);\n\n const eslint = await getESLintForProject(projectCwd);\n if (!eslint) {\n logWarning(\n `ESLint not found in project. Install it in ${pc.dim(\n projectCwd\n )} to enable server-side linting.`\n );\n onProgress(\"ESLint not available (install eslint in this project)\");\n return [];\n }\n\n try {\n onProgress(\"Running ESLint...\");\n const results = await (eslint as ESLintInstance).lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n let spans: JsxElementSpan[] = [];\n let lineStarts: number[] = [];\n let codeLength = 0;\n let fileCode: string | null = null;\n\n try {\n onProgress(\"Building JSX map...\");\n fileCode = readFileSync(absolutePath, \"utf-8\");\n codeLength = fileCode.length;\n lineStarts = buildLineStarts(fileCode);\n spans = buildJsxElementSpans(fileCode, dataLocFile);\n onProgress(`JSX map: ${spans.length} element(s)`);\n } catch (e) {\n // If parsing fails, we still return ESLint messages (unmapped).\n onProgress(\"JSX map failed (falling back to unmapped issues)\");\n logServerError(\n \"JSX map failed\",\n e instanceof Error ? e.message : String(e)\n );\n spans = [];\n lineStarts = [];\n codeLength = 0;\n fileCode = null;\n }\n\n let issues: LintIssue[] = messages\n .filter((m: Record<string, unknown>) => typeof m?.message === \"string\")\n .map((m: Record<string, unknown>) => {\n const line = typeof m.line === \"number\" ? m.line : 1;\n const column = typeof m.column === \"number\" ? m.column : undefined;\n const mappedDataLoc =\n spans.length > 0 && lineStarts.length > 0 && codeLength > 0\n ? mapMessageToDataLoc({\n spans,\n lineStarts,\n codeLength,\n messageLine1: line,\n messageCol1: column,\n })\n : undefined;\n return {\n line,\n column,\n message: m.message as string,\n ruleId: typeof m.ruleId === \"string\" ? m.ruleId : undefined,\n messageId: typeof m.messageId === \"string\" ? m.messageId : undefined,\n dataLoc: mappedDataLoc,\n } satisfies LintIssue;\n });\n\n const mappedCount = issues.filter((i) => Boolean(i.dataLoc)).length;\n if (issues.length > 0) {\n onProgress(\n `Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`\n );\n }\n\n // Enrich issues with scope information\n if (fileCode && issues.length > 0) {\n onProgress(\"Extracting scope info...\");\n issues = enrichIssuesWithScopeInfo(issues, fileCode);\n const scopeCount = issues.filter((i) => Boolean(i.scopeInfo)).length;\n onProgress(\n `Enriched ${scopeCount}/${issues.length} issue(s) with scope info`\n );\n }\n\n cache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n logServerError(\n \"ESLint failed\",\n error instanceof Error ? error.message : String(error)\n );\n return [];\n }\n}\n\n/**\n * Send message to client\n */\nfunction sendMessage(ws: WebSocket, message: ServerMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(message));\n }\n}\n\n/**\n * Handle incoming client message\n */\nasync function handleMessage(ws: WebSocket, data: string): Promise<void> {\n let message: ClientMessage;\n try {\n message = JSON.parse(data) as ClientMessage;\n } catch {\n return;\n }\n\n // Server-side tracing to confirm activity\n if (message.type === \"lint:file\" || message.type === \"lint:element\") {\n const fp = (message as LintFileMessage | LintElementMessage).filePath;\n const rid = (message as LintFileMessage | LintElementMessage).requestId;\n logLint(fp ?? \"\", rid);\n } else if (message.type === \"subscribe:file\") {\n logSubscribe(message.filePath);\n } else if (message.type === \"cache:invalidate\") {\n logCacheInvalidate(message.filePath);\n } else if (message.type === \"vision:analyze\") {\n // Logged in handler for more detailed output\n } else if (message.type === \"vision:check\") {\n // Logged in handler\n } else if (message.type === \"config:set\") {\n // Logged in handler\n } else if (message.type === \"screenshot:save\") {\n const rid = (message as ScreenshotSaveMessage).requestId;\n logScreenshotSave(message.route, rid);\n }\n\n switch (message.type) {\n case \"lint:file\": {\n const { filePath, requestId } = message;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Starting...\",\n });\n\n const startedAt = Date.now();\n const resolved = resolveRequestedFilePath(filePath);\n if (!existsSync(resolved)) {\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n logServerWarning(\n `File not found: ${filePath}`,\n `resolved: ${resolved}, cwd: ${cwd}, wsRoot: ${wsRoot}`\n );\n }\n\n // === PASS 1: Fast rules (non-blocking, no spawnSync) ===\n const fastIssues = await lintFileFast(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n const fastElapsed = Date.now() - startedAt;\n\n // Filter sentinel issues from fast results\n const fastSentinels = fastIssues.filter(isSentinelIssue);\n for (const se of fastSentinels) {\n logRuleInternalError(se.ruleId ?? \"unknown\", filePath, se.message);\n }\n const fastClientIssues = fastIssues.filter((i) => !isSentinelIssue(i));\n\n logLintDone(filePath, fastClientIssues.length, fastElapsed);\n updateCacheCount(fastCache.size + semanticCache.size);\n\n // Send fast results immediately\n sendMessage(ws, {\n type: \"lint:result\",\n filePath,\n requestId,\n issues: fastClientIssues,\n });\n\n // Send Done for fast pass immediately\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${fastClientIssues.length} issues, ${fastElapsed}ms)`,\n });\n\n // === PASS 2: Semantic analysis (async, non-blocking) ===\n if (isSemanticRuleEnabled()) {\n runSemanticAnalysisAsync(filePath, ws, requestId).catch((err) => {\n logServerError(\n \"Async semantic analysis failed\",\n err instanceof Error ? err.message : String(err)\n );\n });\n } else {\n logSemanticSkipped(filePath, \"rule not enabled\");\n }\n break;\n }\n\n case \"lint:element\": {\n const { filePath, dataLoc, requestId } = message;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Starting...\",\n });\n\n const startedAt = Date.now();\n\n // === PASS 1: Fast rules ===\n const fastIssues = await lintFileFast(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n const fastSentinels = fastIssues.filter(isSentinelIssue);\n for (const se of fastSentinels) {\n logRuleInternalError(se.ruleId ?? \"unknown\", filePath, se.message);\n }\n\n const fastFiltered = fastIssues\n .filter((i) => !isSentinelIssue(i))\n .filter((issue) => issue.dataLoc === dataLoc);\n\n // Send fast results immediately\n sendMessage(ws, {\n type: \"lint:result\",\n filePath,\n requestId,\n issues: fastFiltered,\n });\n\n // Send Done for fast pass immediately\n {\n const elapsed = Date.now() - startedAt;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${fastFiltered.length} issues, ${elapsed}ms)`,\n });\n }\n\n // === PASS 2: Semantic analysis (async, non-blocking) ===\n if (isSemanticRuleEnabled()) {\n runSemanticAnalysisAsync(filePath, ws, requestId).catch((err) => {\n logServerError(\n \"Async semantic analysis failed\",\n err instanceof Error ? err.message : String(err)\n );\n });\n } else {\n logSemanticSkipped(filePath, \"rule not enabled\");\n }\n break;\n }\n\n case \"subscribe:file\": {\n const { filePath } = message;\n const absolutePath = resolveRequestedFilePath(filePath);\n\n // Add to subscriptions\n let subscribers = subscriptions.get(absolutePath);\n if (!subscribers) {\n subscribers = new Set();\n subscriptions.set(absolutePath, subscribers);\n\n // Start watching this file\n if (fileWatcher) {\n fileWatcher.add(absolutePath);\n }\n }\n subscribers.add({ ws, clientFilePath: filePath });\n\n // Update subscription count in dashboard\n updateSubscriptionCount(subscriptions.size);\n break;\n }\n\n case \"cache:invalidate\": {\n const { filePath } = message;\n if (filePath) {\n const absolutePath = resolveRequestedFilePath(filePath);\n cache.delete(absolutePath);\n fastCache.delete(absolutePath);\n semanticCache.delete(absolutePath);\n } else {\n cache.clear();\n fastCache.clear();\n semanticCache.clear();\n }\n // Update cache count in dashboard\n updateCacheCount(cache.size + fastCache.size + semanticCache.size);\n break;\n }\n\n case \"vision:analyze\": {\n const visionMsg = message as VisionAnalyzeMessage;\n logVisionAnalyze(visionMsg.route, visionMsg.requestId);\n\n // Fire-and-forget: run vision analysis in background\n runVisionAnalysisInBackground(ws, visionMsg).catch((err) => {\n logServerError(\n \"Vision analysis failed\",\n err instanceof Error ? err.message : String(err)\n );\n });\n break;\n }\n\n case \"vision:check\": {\n const { requestId } = message as VisionCheckMessage;\n logVisionCheck(requestId);\n\n try {\n const analyzer = await getVisionAnalyzerInstance();\n if (!analyzer) {\n sendMessage(ws, {\n type: \"vision:status\",\n available: false,\n requestId,\n });\n break;\n }\n const analyzerObj = analyzer as Record<string, unknown>;\n const model =\n typeof analyzerObj.getModel === \"function\"\n ? (analyzerObj.getModel as () => string)()\n : undefined;\n sendMessage(ws, {\n type: \"vision:status\",\n available: true,\n model,\n requestId,\n });\n } catch {\n sendMessage(ws, { type: \"vision:status\", available: false, requestId });\n }\n break;\n }\n\n case \"config:set\": {\n const { key, value } = message;\n handleConfigSet(key, value);\n break;\n }\n\n case \"rule:config:set\": {\n const { ruleId, severity, options, requestId } = message;\n handleRuleConfigSet(ws, ruleId, severity, options, requestId);\n break;\n }\n\n case \"source:fetch\": {\n const { filePath, requestId } = message;\n const absolutePath = resolveRequestedFilePath(filePath);\n\n if (!existsSync(absolutePath)) {\n sendMessage(ws, {\n type: \"source:error\",\n filePath,\n error: \"File not found\",\n requestId,\n });\n break;\n }\n\n try {\n const content = readFileSync(absolutePath, \"utf-8\");\n const totalLines = content.split(\"\\n\").length;\n const relativePath = normalizeDataLocFilePath(\n absolutePath,\n serverAppRootForVision\n );\n\n sendMessage(ws, {\n type: \"source:result\",\n filePath,\n content,\n totalLines,\n relativePath,\n requestId,\n });\n } catch (error) {\n sendMessage(ws, {\n type: \"source:error\",\n filePath,\n error: error instanceof Error ? error.message : \"Failed to read file\",\n requestId,\n });\n }\n break;\n }\n\n case \"coverage:request\": {\n const { requestId } = message;\n try {\n const coveragePath = join(\n serverAppRootForVision,\n \"coverage\",\n \"coverage-final.json\"\n );\n\n if (!existsSync(coveragePath)) {\n sendMessage(ws, {\n type: \"coverage:error\",\n error:\n \"Coverage data not found. Run tests with coverage first (e.g., `vitest run --coverage`)\",\n requestId,\n });\n break;\n }\n\n const coverageData = JSON.parse(readFileSync(coveragePath, \"utf-8\"));\n logCoverageResult(Object.keys(coverageData).length);\n\n sendMessage(ws, {\n type: \"coverage:result\",\n coverage: coverageData,\n timestamp: Date.now(),\n requestId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logServerError(`coverage:error`, errorMessage);\n sendMessage(ws, {\n type: \"coverage:error\",\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n\n case \"screenshot:save\": {\n const { dataUrl, route, timestamp, requestId } = message;\n\n try {\n // Validate the dataUrl is a valid base64 PNG data URL\n if (!dataUrl || typeof dataUrl !== \"string\") {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: \"Invalid dataUrl: must be a non-empty string\",\n requestId,\n });\n break;\n }\n\n const dataUrlPattern = /^data:image\\/png;base64,/;\n if (!dataUrlPattern.test(dataUrl)) {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error:\n \"Invalid dataUrl: must be a base64 PNG data URL (data:image/png;base64,...)\",\n requestId,\n });\n break;\n }\n\n // Extract base64 data\n const base64Data = dataUrl.replace(dataUrlPattern, \"\");\n\n // Sanitize route for filename (replace / with -, remove special chars)\n const sanitizedRoute =\n route\n .replace(/^\\//, \"\") // Remove leading slash\n .replace(/\\//g, \"-\") // Replace slashes with dashes\n .replace(/[^a-zA-Z0-9_-]/g, \"_\") || // Replace special chars with underscore\n \"root\"; // Default to \"root\" for empty route\n\n // Generate filename\n const filename = `uilint-${timestamp}-${sanitizedRoute}.png`;\n\n // Validate generated filename\n if (!isValidScreenshotFilename(filename)) {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: `Generated filename is invalid: ${filename}`,\n requestId,\n });\n break;\n }\n\n // Create screenshots directory if needed\n const screenshotsDir = join(\n serverAppRootForVision,\n \".uilint\",\n \"screenshots\"\n );\n if (!existsSync(screenshotsDir)) {\n mkdirSync(screenshotsDir, { recursive: true });\n }\n\n // Write the image file\n const imagePath = join(screenshotsDir, filename);\n const imageBuffer = Buffer.from(base64Data, \"base64\");\n writeFileSync(imagePath, imageBuffer);\n\n // Write JSON sidecar with metadata\n const sidecarFilename = filename.replace(/\\.png$/, \".json\");\n const sidecarPath = join(screenshotsDir, sidecarFilename);\n const sidecarData = {\n route,\n timestamp,\n filename,\n savedAt: new Date().toISOString(),\n };\n writeFileSync(sidecarPath, JSON.stringify(sidecarData, null, 2));\n\n logScreenshotSaved(filename, Math.round(imageBuffer.length / 1024));\n\n // Send success response\n sendMessage(ws, {\n type: \"screenshot:saved\",\n filename,\n path: imagePath,\n requestId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logServerError(`screenshot:error`, errorMessage);\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n }\n}\n\n/**\n * Handle client disconnect\n */\nfunction handleDisconnect(ws: WebSocket): void {\n // Remove from all subscriptions\n for (const [filePath, subscribers] of subscriptions.entries()) {\n for (const entry of subscribers) {\n if (entry.ws === ws) {\n subscribers.delete(entry);\n }\n }\n if (subscribers.size === 0) {\n subscriptions.delete(filePath);\n // Stop watching if no subscribers\n if (fileWatcher) {\n fileWatcher.unwatch(filePath);\n }\n }\n }\n // Update subscription count in dashboard\n updateSubscriptionCount(subscriptions.size);\n}\n\n/**\n * Handle file change\n */\nfunction handleFileChange(filePath: string): void {\n const subscribers = subscriptions.get(filePath);\n if (!subscribers || subscribers.size === 0) return;\n\n // Invalidate cache\n cache.delete(filePath);\n fastCache.delete(filePath);\n semanticCache.delete(filePath);\n\n // Notify subscribers\n for (const { ws, clientFilePath } of subscribers) {\n sendMessage(ws, { type: \"file:changed\", filePath: clientFilePath });\n }\n}\n\n/**\n * Handle coverage-final.json file change - broadcast new coverage data to all clients\n */\nfunction handleCoverageFileChange(filePath: string): void {\n try {\n const coverageData = JSON.parse(readFileSync(filePath, \"utf-8\"));\n logCoverageResult(Object.keys(coverageData).length);\n\n broadcast({\n type: \"coverage:result\",\n coverage: coverageData,\n timestamp: Date.now(),\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logServerError(`Failed to read coverage data`, errorMessage);\n broadcast({\n type: \"coverage:error\",\n error: `Failed to read coverage: ${errorMessage}`,\n });\n }\n}\n\n// In-memory config store (runtime only, for broadcasting to clients)\nconst configStore = new Map<string, unknown>();\n\n// Track connected clients for broadcasting\nconst connectedClientsSet = new Set<WebSocket>();\n\n/**\n * Broadcast config update to all connected clients\n */\nfunction broadcastConfigUpdate(key: string, value: unknown): void {\n const message: ConfigUpdateMessage = { type: \"config:update\", key, value };\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n/**\n * Handle config:set message\n */\nfunction handleConfigSet(key: string, value: unknown): void {\n configStore.set(key, value);\n logConfigSet(key, value);\n broadcastConfigUpdate(key, value);\n}\n\n/**\n * Broadcast rule config change to all connected clients\n */\nfunction broadcastRuleConfigChange(\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>\n): void {\n const message: RuleConfigChangedMessage = {\n type: \"rule:config:changed\",\n ruleId,\n severity,\n options,\n };\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n/**\n * Broadcast a message to all connected clients\n */\nfunction broadcast(message: ServerMessage): void {\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n// Duplicates indexing state\nlet isIndexing = false;\nlet reindexTimeout: NodeJS.Timeout | null = null;\nconst pendingIndexChanges = new Set<string>();\n\n/**\n * Build or update the duplicates index\n * Runs incrementally - very fast if no files changed\n */\nasync function buildDuplicatesIndex(appRoot: string): Promise<void> {\n if (isIndexing) {\n // Already indexing, skip\n return;\n }\n\n isIndexing = true;\n setPluginStatus(\"duplicates\", \"processing\", \"Preparing index...\");\n startBackgroundTask(\n \"duplicates-index\",\n \"Duplicates Index\",\n \"Waiting for Ollama...\"\n );\n\n // Acquire exclusive access to Ollama to avoid model contention\n const release = await acquireOllamaMutex(\"duplicates\");\n\n broadcast({ type: \"duplicates:indexing:start\" });\n broadcast({\n type: \"plugin:operation:start\",\n pluginId: \"duplicates\",\n operationName: \"indexing\",\n message: \"Building duplicates index...\",\n });\n\n try {\n const { indexDirectory } = await import(\"uilint-duplicates\");\n const result = await indexDirectory(appRoot, {\n onProgress: (message: string, current?: number, total?: number) => {\n // Update dashboard progress\n const progress =\n total && total > 0 ? Math.round(((current || 0) / total) * 100) : 0;\n updateBackgroundTaskProgress(\n \"duplicates-index\",\n progress,\n current,\n total,\n message\n );\n updatePluginProgress(\"duplicates\", progress, current, total, message);\n // Broadcast to connected clients\n broadcast({\n type: \"duplicates:indexing:progress\",\n message,\n current,\n total,\n });\n broadcast({\n type: \"plugin:operation:progress\",\n pluginId: \"duplicates\",\n operationName: \"indexing\",\n current,\n total,\n message,\n });\n },\n });\n\n const successMsg = `${result.totalChunks} chunks (${result.added} added, ${\n result.modified\n } modified, ${result.deleted} deleted) in ${(\n result.duration / 1000\n ).toFixed(1)}s`;\n completeBackgroundTask(\"duplicates-index\", `Index complete: ${successMsg}`);\n setPluginStatus(\"duplicates\", \"complete\", successMsg);\n setTimeout(() => setPluginStatus(\"duplicates\", \"idle\"), 3000);\n broadcast({\n type: \"duplicates:indexing:complete\",\n added: result.added,\n modified: result.modified,\n deleted: result.deleted,\n totalChunks: result.totalChunks,\n duration: result.duration,\n });\n broadcast({\n type: \"plugin:operation:complete\",\n pluginId: \"duplicates\",\n operationName: \"indexing\",\n message: successMsg,\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n completeBackgroundTask(\"duplicates-index\", undefined, msg);\n setPluginStatus(\"duplicates\", \"error\", msg);\n setTimeout(() => setPluginStatus(\"duplicates\", \"idle\"), 3000);\n broadcast({ type: \"duplicates:indexing:error\", error: msg });\n broadcast({\n type: \"plugin:operation:error\",\n pluginId: \"duplicates\",\n operationName: \"indexing\",\n error: msg,\n });\n } finally {\n release();\n isIndexing = false;\n }\n}\n\n/**\n * Schedule a debounced re-index when source files change\n */\nfunction scheduleReindex(appRoot: string, filePath: string): void {\n // Only reindex for source files\n if (!/\\.(tsx?|jsx?)$/.test(filePath)) return;\n\n pendingIndexChanges.add(filePath);\n\n if (reindexTimeout) clearTimeout(reindexTimeout);\n reindexTimeout = setTimeout(async () => {\n const count = pendingIndexChanges.size;\n pendingIndexChanges.clear();\n logServerInfo(`${count} file(s) changed, updating index...`);\n await buildDuplicatesIndex(appRoot);\n }, 2000); // 2 second debounce\n}\n\n// Coverage preparation state\nlet isPreparingCoverage = false;\n\n/**\n * Check if require-test-coverage rule is enabled in ESLint config\n */\nfunction isCoverageRuleEnabled(appRoot: string): boolean {\n const eslintConfigPath = findEslintConfigFile(appRoot);\n if (!eslintConfigPath) return false;\n\n const ruleConfigs = readRuleConfigsFromConfig(eslintConfigPath);\n const coverageConfig = ruleConfigs.get(\"require-test-coverage\");\n if (!coverageConfig) return false;\n\n // Rule is enabled if severity is not \"off\"\n return coverageConfig.severity !== \"off\";\n}\n\n/**\n * Prepare coverage data for require-test-coverage rule.\n * Runs only on startup:\n * - Installs @vitest/coverage-v8 if missing\n * - Adds coverage config to vitest.config.ts if missing\n * - Runs tests with coverage to generate coverage-final.json\n */\nasync function buildCoverageData(appRoot: string): Promise<void> {\n if (isPreparingCoverage) return;\n\n isPreparingCoverage = true;\n\n try {\n // Check if coverage rule is enabled\n if (!isCoverageRuleEnabled(appRoot)) {\n logServerInfo(\"Coverage rule not enabled, skipping preparation\");\n return;\n }\n\n // Detect current setup\n const setup = detectCoverageSetup(appRoot);\n\n // Check if preparation needed\n if (!needsCoveragePreparation(setup)) {\n logServerInfo(\"Coverage data is up-to-date\");\n return;\n }\n\n // Run preparation\n startBackgroundTask(\"coverage-prep\", \"Coverage Prep\", \"Starting...\");\n broadcast({ type: \"coverage:setup:start\" });\n\n // Check environment variables for skipping\n const skipPackageInstall = process.env.UILINT_SKIP_COVERAGE_INSTALL === \"1\";\n const skipTests = process.env.UILINT_SKIP_COVERAGE_TESTS === \"1\";\n\n const result = await prepareCoverage({\n appRoot,\n skipPackageInstall,\n skipTests,\n silent: isDashboardEnabled(),\n onProgress: (message, phase) => {\n updateBackgroundTaskProgress(\n \"coverage-prep\",\n 50,\n undefined,\n undefined,\n message\n );\n broadcast({ type: \"coverage:setup:progress\", message, phase });\n },\n });\n\n if (result.error) {\n // Continue with warning on test failures (don't block server startup)\n completeBackgroundTask(\"coverage-prep\", undefined, result.error);\n } else {\n const parts = [];\n if (result.packageAdded) parts.push(\"package installed\");\n if (result.configModified) parts.push(\"config modified\");\n if (result.testsRan) parts.push(\"tests ran\");\n if (result.coverageGenerated) parts.push(\"coverage generated\");\n\n completeBackgroundTask(\n \"coverage-prep\",\n `Coverage prepared: ${parts.join(\", \")} in ${(\n result.duration / 1000\n ).toFixed(1)}s`\n );\n }\n\n broadcast({\n type: \"coverage:setup:complete\",\n ...result,\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n completeBackgroundTask(\"coverage-prep\", undefined, msg);\n broadcast({ type: \"coverage:setup:error\", error: msg });\n } finally {\n isPreparingCoverage = false;\n }\n}\n\n/**\n * Handle rule:config:set message\n * Updates the ESLint config file and broadcasts the change to all clients\n */\nfunction handleRuleConfigSet(\n ws: WebSocket,\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>,\n requestId?: string\n): void {\n // Normalize ruleId - strip \"uilint/\" prefix if present since\n // updateRuleSeverityInConfig adds it internally\n const normalizedRuleId = ruleId.startsWith(\"uilint/\")\n ? ruleId.slice(\"uilint/\".length)\n : ruleId;\n\n logRuleConfigSet(normalizedRuleId, severity, !!options);\n\n // Find the ESLint config file\n const configPath = findEslintConfigFile(serverAppRootForVision);\n if (!configPath) {\n const error = `No ESLint config file found in ${serverAppRootForVision}`;\n logServerError(error);\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: false,\n error,\n requestId,\n });\n return;\n }\n\n // Update the config file\n let result;\n if (options && Object.keys(options).length > 0) {\n // Update severity AND options\n result = updateRuleConfigInConfig(\n configPath,\n normalizedRuleId,\n severity,\n options\n );\n } else {\n // Update severity only\n result = updateRuleSeverityInConfig(configPath, normalizedRuleId, severity);\n }\n\n if (result.success) {\n logServerInfo(`Updated uilint/${normalizedRuleId} -> ${severity}`);\n\n // Clear ESLint instance cache to pick up the new config\n eslintInstances.clear();\n eslintFastInstances.clear();\n cache.clear();\n fastCache.clear();\n semanticCache.clear();\n updateCacheCount(0);\n\n // Send success response to requesting client\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: true,\n requestId,\n });\n\n // Broadcast change to all connected clients\n broadcastRuleConfigChange(ruleId, severity, options);\n } else {\n logServerError(`Failed to update rule: ${result.error}`);\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: false,\n error: result.error,\n requestId,\n });\n }\n}\n\n/**\n * Start the WebSocket server\n */\nexport async function serve(options: ServeOptions): Promise<void> {\n const preferredPort = options.port || DEFAULT_PORT;\n\n // Determine if we should use the dashboard UI\n // Enable dashboard if TTY and not explicitly disabled\n const useDashboardUI = process.stdout.isTTY && !options.noDashboard;\n\n if (useDashboardUI) {\n enableDashboard();\n // Register all Ollama-consuming plugins with the dashboard.\n // Model names are defaults; corrected lazily via setPluginModel() when each plugin runs.\n registerPlugin(\"semantic\", \"Semantic\", \"qwen3-vl:8b-instruct\");\n registerPlugin(\"vision\", \"Vision\", \"qwen3-vl:8b-instruct\");\n registerPlugin(\"duplicates\", \"Duplicates\", \"nomic-embed-text\");\n } else {\n disableDashboard();\n }\n\n // Load plugin ESLint rules before anything accesses the registries.\n // This triggers auto-registration of plugin rules if installed.\n const pluginManifests = await discoverPlugins();\n await loadPluginESLintRules(pluginManifests);\n\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n const appRoot = pickAppRoot({ cwd, workspaceRoot: wsRoot });\n serverAppRootForVision = appRoot;\n\n // Set workspace info in dashboard\n setWorkspaceInfo(wsRoot, appRoot, cwd);\n\n // Create file watcher\n fileWatcher = watch([], {\n persistent: true,\n ignoreInitial: true,\n });\n\n fileWatcher.on(\"change\", (path) => {\n const resolvedPath = resolve(path);\n\n // Check if coverage-final.json changed - broadcast to all clients\n if (resolvedPath.endsWith(\"coverage-final.json\")) {\n handleCoverageFileChange(resolvedPath);\n return;\n }\n\n handleFileChange(resolvedPath);\n // Also schedule re-indexing for duplicates detection\n scheduleReindex(appRoot, resolvedPath);\n });\n\n // Watch coverage-final.json for changes\n const coveragePath = join(appRoot, \"coverage\", \"coverage-final.json\");\n if (existsSync(coveragePath)) {\n fileWatcher.add(coveragePath);\n logServerInfo(`Watching coverage`, coveragePath);\n }\n\n // Find an available port (auto-increment if preferred port is in use)\n const port = await findAvailablePort(preferredPort);\n if (port !== preferredPort) {\n logServerInfo(`Port ${preferredPort} in use, using ${port}`);\n }\n\n // Create HTTP server with discovery endpoint and WebSocket upgrade\n const httpServer = createServer(\n (req: IncomingMessage, res: ServerResponse) => {\n // CORS preflight\n if (req.method === \"OPTIONS\") {\n res.writeHead(204, {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type\",\n });\n res.end();\n return;\n }\n\n const parsedUrl = new URL(req.url ?? \"/\", `http://localhost:${port}`);\n\n if (parsedUrl.pathname === \"/_uilint/info\") {\n const probePath = parsedUrl.searchParams.get(\"probe\");\n let probeExists: boolean | undefined;\n if (probePath) {\n // Check if the probed file exists relative to appRoot\n const absolute = join(appRoot, probePath);\n probeExists = existsSync(absolute);\n }\n\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n res.end(\n JSON.stringify({\n appRoot,\n workspaceRoot: wsRoot,\n serverCwd: cwd,\n port,\n pid: process.pid,\n ...(probeExists !== undefined && { probeExists }),\n })\n );\n return;\n }\n\n res.writeHead(404);\n res.end();\n }\n );\n\n // Create WebSocket server in noServer mode (HTTP server handles upgrade)\n const wss = new WebSocketServer({ noServer: true });\n\n httpServer.on(\"upgrade\", (request, socket, head) => {\n wss.handleUpgrade(request, socket, head, (ws) => {\n wss.emit(\"connection\", ws, request);\n });\n });\n\n // Start listening\n httpServer.listen(port, \"127.0.0.1\");\n\n // Write port file so other tools can find this server\n const portFilePath = join(appRoot, \".uilint\", \"port\");\n const uilintDir = join(appRoot, \".uilint\");\n if (!existsSync(uilintDir)) mkdirSync(uilintDir, { recursive: true });\n writeFileSync(portFilePath, String(port), \"utf-8\");\n\n /** Clean up port file on shutdown */\n function removePortFile(): void {\n try {\n unlinkSync(portFilePath);\n } catch {\n // Ignore — file may already be gone\n }\n }\n\n // WebSocket keepalive: ping all clients every 30 seconds to detect stale connections\n const PING_INTERVAL = 30_000;\n const aliveClients = new WeakSet<WebSocket>();\n const pingInterval = setInterval(() => {\n for (const ws of connectedClientsSet) {\n if (!aliveClients.has(ws)) {\n ws.terminate();\n continue;\n }\n aliveClients.delete(ws);\n if (ws.readyState === WebSocket.OPEN) {\n ws.ping();\n }\n }\n }, PING_INTERVAL);\n\n // Start building the duplicates index in the background\n // This runs incrementally - very fast if nothing changed\n buildDuplicatesIndex(appRoot).catch((err) => {\n logServerError(`Failed to build duplicates index`, err.message);\n });\n\n // Prepare coverage data for require-test-coverage rule (startup only)\n // This installs packages, modifies config, and runs tests if needed\n buildCoverageData(appRoot).catch((err) => {\n // Don't block server startup on coverage failures\n logServerWarning(`Failed to prepare coverage`, err.message);\n });\n\n wss.on(\"connection\", (ws) => {\n connectedClients += 1;\n connectedClientsSet.add(ws);\n aliveClients.add(ws);\n logClientConnect(connectedClients);\n\n // Track keepalive\n ws.on(\"pong\", () => {\n aliveClients.add(ws);\n });\n\n // Send workspace info to client on connect\n sendMessage(ws, {\n type: \"workspace:info\",\n appRoot,\n workspaceRoot: wsRoot,\n serverCwd: cwd,\n });\n\n // Send workspace capabilities (hook availability, etc.)\n const hookInfo = detectPostToolUseHook(appRoot);\n sendMessage(ws, {\n type: \"workspace:capabilities\",\n postToolUseHook: hookInfo,\n });\n if (hookInfo.enabled) {\n logServerInfo(`Post-tool-use hook detected: ${hookInfo.provider}`);\n }\n\n // Read current rule configs from ESLint config file\n const eslintConfigPath = findEslintConfigFile(appRoot);\n const currentRuleConfigs = eslintConfigPath\n ? readRuleConfigsFromConfig(eslintConfigPath)\n : new Map<\n string,\n {\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n }\n >();\n\n // Send installed rules metadata (only rules that exist in the ESLint config)\n // Include current severities from the ESLint config so UI reflects saved state\n // Use full rule IDs (uilint/...) for consistency with ESLint output\n sendMessage(ws, {\n type: \"rules:metadata\",\n rules: ruleRegistry\n .filter((rule) => currentRuleConfigs.has(rule.id))\n .map((rule) => {\n const currentConfig = currentRuleConfigs.get(rule.id);\n return {\n id: `uilint/${rule.id}`,\n name: rule.name,\n description: rule.description,\n category: rule.category,\n defaultSeverity: rule.defaultSeverity,\n currentSeverity: currentConfig?.severity,\n currentOptions: currentConfig?.options,\n docs: rule.docs,\n optionSchema: rule.optionSchema,\n defaultOptions: rule.defaultOptions,\n };\n }),\n });\n\n // Send current config state to new client\n for (const [key, value] of configStore) {\n sendMessage(ws, { type: \"config:update\", key, value });\n }\n\n ws.on(\"message\", (data) => {\n handleMessage(ws, data.toString());\n });\n\n ws.on(\"close\", () => {\n connectedClients = Math.max(0, connectedClients - 1);\n connectedClientsSet.delete(ws);\n logClientDisconnect(connectedClients);\n handleDisconnect(ws);\n });\n\n ws.on(\"error\", (error) => {\n logServerError(`WebSocket error`, error.message);\n });\n });\n\n wss.on(\"error\", (error) => {\n logServerError(`Server error`, error.message);\n });\n\n // Set server as running in dashboard\n setServerRunning(port);\n\n // Render dashboard or keep server running\n if (useDashboardUI) {\n // Dynamic import to avoid loading Ink in non-TTY environments\n const { renderDashboard } = await import(\"./serve/dashboard/render.js\");\n const { waitUntilExit } = renderDashboard({\n onQuit: () => {\n clearInterval(pingInterval);\n wss.close();\n httpServer.close();\n fileWatcher?.close();\n removePortFile();\n },\n onRebuildIndex: () => {\n buildDuplicatesIndex(appRoot);\n },\n });\n\n // Wait for dashboard to exit\n await waitUntilExit();\n } else {\n // Keep the server running in non-TTY mode\n await new Promise<void>((resolve) => {\n process.on(\"SIGINT\", () => {\n logServerInfo(\"Shutting down...\");\n clearInterval(pingInterval);\n wss.close();\n httpServer.close();\n fileWatcher?.close();\n removePortFile();\n resolve();\n });\n });\n }\n}\n","/**\n * Dashboard logger adapter\n *\n * Provides logging functions that either update the dashboard store\n * or fall back to console logging for non-TTY environments.\n */\n\nimport { getDashboardStore } from \"./store.js\";\nimport type { ActivityType, ActivityCategory, PluginId, PluginLifecycle } from \"./types.js\";\nimport pc from \"picocolors\";\n\n/**\n * Derive a coarse category from an activity type for log filtering.\n */\nfunction deriveCategory(\n type: ActivityType,\n isError?: boolean\n): ActivityCategory {\n if (isError || type === \"error\") return \"errors\";\n if (type === \"warning\") return \"errors\";\n if (type.startsWith(\"vision:\")) return \"vision\";\n if (type.startsWith(\"semantic:\")) return \"semantic\";\n if (type.startsWith(\"lint:\")) return \"lint\";\n return \"system\";\n}\n\n// Simple console logging functions that work in any environment (including non-TTY)\n// These use direct console.log instead of @clack/prompts which can suppress output\nfunction consoleInfo(message: string): void {\n console.log(pc.blue(\"i\") + \" \" + message);\n}\n\nfunction consoleSuccess(message: string): void {\n console.log(pc.green(\"\\u2713\") + \" \" + message);\n}\n\nfunction consoleWarning(message: string): void {\n console.log(pc.yellow(\"\\u26A0\") + \" \" + message);\n}\n\nfunction consoleError(message: string): void {\n console.log(pc.red(\"\\u2717\") + \" \" + message);\n}\n\nlet useDashboard = false;\n\n/**\n * Enable dashboard mode (disables console logging)\n */\nexport function enableDashboard(): void {\n useDashboard = true;\n}\n\n/**\n * Disable dashboard mode (enables console logging)\n */\nexport function disableDashboard(): void {\n useDashboard = false;\n}\n\n/**\n * Check if dashboard mode is enabled\n */\nexport function isDashboardEnabled(): boolean {\n return useDashboard;\n}\n\n/**\n * Log an activity to the dashboard or console\n */\nexport function logActivity(\n type: ActivityType,\n message: string,\n detail?: string,\n isError?: boolean,\n isWarning?: boolean\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n const category = deriveCategory(type, isError);\n store.addActivity({ type, message, detail, isError, isWarning, category });\n } else {\n // Fall back to console logging\n const prefix = `${pc.dim(\"[ws]\")} `;\n if (isError) {\n consoleError(prefix + message + (detail ? `\\n ${detail}` : \"\"));\n } else if (isWarning) {\n consoleWarning(prefix + message + (detail ? `\\n ${detail}` : \"\"));\n } else {\n consoleInfo(prefix + message + (detail ? `\\n ${detail}` : \"\"));\n }\n }\n}\n\n/**\n * Log a lint operation\n */\nexport function logLint(filePath: string, requestId?: string): void {\n const msg = filePath + (requestId ? ` (req ${requestId})` : \"\");\n logActivity(\"lint:file\", msg);\n}\n\n/**\n * Log a lint completion\n */\nexport function logLintDone(\n filePath: string,\n issueCount: number,\n elapsedMs: number\n): void {\n logActivity(\n \"lint:done\",\n `${filePath} \\u2192 ${issueCount} issue(s) (${elapsedMs}ms)`\n );\n}\n\n/**\n * Log a file subscription\n */\nexport function logSubscribe(filePath: string): void {\n logActivity(\"subscribe\", filePath);\n}\n\n/**\n * Log a cache invalidation\n */\nexport function logCacheInvalidate(filePath?: string): void {\n logActivity(\"cache:invalidate\", filePath ?? \"(all)\");\n}\n\n/**\n * Log a vision analysis start\n */\nexport function logVisionAnalyze(route: string, requestId?: string): void {\n const msg = route + (requestId ? ` (req ${requestId})` : \"\");\n logActivity(\"vision:analyze\", msg);\n}\n\n/**\n * Log a vision analysis completion\n */\nexport function logVisionDone(\n route: string,\n issueCount: number,\n elapsedMs: number\n): void {\n logActivity(\n \"vision:done\",\n `${route} \\u2192 ${issueCount} issue(s) (${elapsedMs}ms)`\n );\n}\n\n/**\n * Log a vision check\n */\nexport function logVisionCheck(requestId?: string): void {\n logActivity(\"vision:check\", requestId ? `(req ${requestId})` : \"\");\n}\n\n/**\n * Log a semantic analysis start\n */\nexport function logSemanticAnalyze(\n filePath: string,\n requestId?: string\n): void {\n const msg = filePath + (requestId ? ` (req ${requestId})` : \"\");\n logActivity(\"semantic:analyze\", msg);\n}\n\n/**\n * Log a semantic analysis completion\n */\nexport function logSemanticDone(\n filePath: string,\n issueCount: number,\n elapsedMs: number\n): void {\n logActivity(\n \"semantic:done\",\n `${filePath} \\u2192 ${issueCount} issue(s) (${elapsedMs}ms)`\n );\n}\n\n/**\n * Log a semantic analysis skip (cache hit, rule disabled, missing styleguide, etc.)\n */\nexport function logSemanticSkipped(filePath: string, reason: string): void {\n logActivity(\"semantic:skip\", `${filePath} \\u2014 ${reason}`);\n}\n\n/**\n * Log a config set operation\n */\nexport function logConfigSet(key: string, value: unknown): void {\n logActivity(\"config:set\", `${key} = ${JSON.stringify(value)}`);\n}\n\n/**\n * Log a rule config set operation\n */\nexport function logRuleConfigSet(\n ruleId: string,\n severity: string,\n hasOptions: boolean\n): void {\n logActivity(\n \"rule:config:set\",\n `${ruleId} \\u2192 ${severity}${hasOptions ? \" (with options)\" : \"\"}`\n );\n}\n\n/**\n * Log a screenshot save\n */\nexport function logScreenshotSave(route: string, requestId?: string): void {\n const msg = route + (requestId ? ` (req ${requestId})` : \"\");\n logActivity(\"screenshot:save\", msg);\n}\n\n/**\n * Log a screenshot saved\n */\nexport function logScreenshotSaved(filename: string, sizeKb: number): void {\n logActivity(\"screenshot:saved\", `${filename} (${sizeKb}kb)`);\n}\n\n/**\n * Log a coverage request\n */\nexport function logCoverageRequest(): void {\n logActivity(\"coverage:request\", \"\");\n}\n\n/**\n * Log a coverage result\n */\nexport function logCoverageResult(fileCount: number): void {\n logActivity(\"coverage:result\", `${fileCount} files`);\n}\n\n/**\n * Log a file change notification\n */\nexport function logFileChanged(filePath: string): void {\n logActivity(\"file:changed\", filePath);\n}\n\n/**\n * Log a client connection\n */\nexport function logClientConnect(totalClients: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.incrementClients();\n store.addActivity({\n type: \"client:connect\",\n message: `(${totalClients} total)`,\n });\n } else {\n consoleInfo(`Client connected (${totalClients} total)`);\n }\n}\n\n/**\n * Log a client disconnection\n */\nexport function logClientDisconnect(totalClients: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.decrementClients();\n store.addActivity({\n type: \"client:disconnect\",\n message: `(${totalClients} total)`,\n });\n } else {\n consoleInfo(`Client disconnected (${totalClients} total)`);\n }\n}\n\n/**\n * Log an error\n */\nexport function logServerError(message: string, detail?: string): void {\n logActivity(\"error\", message, detail, true);\n}\n\n/**\n * Log a warning\n */\nexport function logServerWarning(message: string, detail?: string): void {\n logActivity(\"warning\", message, detail, false, true);\n}\n\n/**\n * Log an info message\n */\nexport function logServerInfo(message: string, detail?: string): void {\n logActivity(\"info\", message, detail);\n}\n\n/**\n * Set workspace info in dashboard\n */\nexport function setWorkspaceInfo(\n workspaceRoot: string,\n appRoot: string,\n serverCwd: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setWorkspace({ workspaceRoot, appRoot, serverCwd });\n } else {\n consoleInfo(`Workspace root: ${pc.dim(workspaceRoot)}`);\n consoleInfo(`App root: ${pc.dim(appRoot)}`);\n consoleInfo(`Server cwd: ${pc.dim(serverCwd)}`);\n }\n}\n\n/**\n * Set server as running\n */\nexport function setServerRunning(port: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setPort(port);\n store.setRunning(true);\n } else {\n consoleSuccess(\n `UILint WebSocket server running on ${pc.cyan(`ws://localhost:${port}`)}`\n );\n consoleInfo(\"Press Ctrl+C to stop\");\n }\n}\n\n/**\n * Update subscription count\n */\nexport function updateSubscriptionCount(count: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.updateStats({ subscriptions: count });\n }\n}\n\n/**\n * Update cache entry count\n */\nexport function updateCacheCount(count: number): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setCacheEntries(count);\n }\n}\n\n/**\n * Background task management\n */\nexport function startBackgroundTask(\n id: string,\n name: string,\n message?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setBackgroundTask({\n id,\n name,\n status: \"running\",\n progress: 0,\n message,\n });\n } else {\n consoleInfo(`${pc.blue(name)}...`);\n }\n}\n\nexport function updateBackgroundTaskProgress(\n id: string,\n progress: number,\n current?: number,\n total?: number,\n message?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.updateBackgroundTaskProgress(id, progress, current, total, message);\n } else if (message) {\n if (current !== undefined && total !== undefined) {\n consoleInfo(` ${message} (${current}/${total})`);\n } else {\n consoleInfo(` ${message}`);\n }\n }\n}\n\nexport function completeBackgroundTask(\n id: string,\n successMessage?: string,\n error?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.completeBackgroundTask(id, error);\n } else {\n if (error) {\n consoleError(`Failed: ${error}`);\n } else if (successMessage) {\n consoleSuccess(successMessage);\n }\n }\n}\n\n/**\n * Log a rule internal/sentinel error.\n *\n * Sentinel errors are internal failures from rules with fallible backends\n * (e.g. LLM unavailable, index not built). They are filtered from client\n * results and only shown in the dashboard/server logs.\n */\nexport function logRuleInternalError(\n ruleId: string,\n filePath: string,\n detail: string\n): void {\n logActivity(\"error\", `Rule error [${ruleId}] ${filePath}`, detail, true);\n}\n\n// ============================================================================\n// Plugin status (Ollama-consuming plugins)\n// ============================================================================\n\n/**\n * Register a plugin with the dashboard. Call once during server startup.\n */\nexport function registerPlugin(\n id: PluginId,\n name: string,\n model: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.registerPlugin(id, name, model);\n } else {\n consoleInfo(`Plugin registered: ${name} (${model})`);\n }\n}\n\n/**\n * Update a plugin's lifecycle status in the dashboard.\n */\nexport function setPluginStatus(\n id: PluginId,\n status: PluginLifecycle,\n message?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setPluginState(id, {\n status,\n message,\n error: status === \"error\" ? message : undefined,\n // Clear progress on terminal states\n ...(status === \"idle\" || status === \"complete\" || status === \"error\"\n ? { progress: undefined, current: undefined, total: undefined }\n : {}),\n });\n } else if (status === \"error\") {\n consoleError(`Plugin ${id}: ${message}`);\n }\n}\n\n/**\n * Update a plugin's progress during an operation.\n */\nexport function updatePluginProgress(\n id: PluginId,\n progress: number,\n current?: number,\n total?: number,\n message?: string\n): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setPluginState(id, { progress, current, total, message });\n }\n}\n\n/**\n * Update a plugin's model name (useful when determined lazily at runtime).\n */\nexport function setPluginModel(id: PluginId, model: string): void {\n if (useDashboard) {\n const store = getDashboardStore();\n store.setPluginState(id, { model });\n }\n}\n","/**\n * Shared ESLint Utilities\n *\n * Common functions for ESLint integration, JSX parsing, and data-loc mapping.\n * Extracted from serve.ts to be reusable across commands.\n */\n\nimport { existsSync, readFileSync } from \"fs\";\n\n/** Generic AST node type. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AstNode = Record<string, any>;\nimport { createRequire } from \"module\";\nimport { dirname, resolve, relative, join } from \"path\";\nimport { findEnclosingScopeBatch } from \"../scope-extractor.js\";\n\n/**\n * JSX element span with character offsets and data-loc\n */\nexport type JsxElementSpan = {\n start: number;\n end: number;\n dataLoc: string;\n};\n\n/**\n * Lint issue structure\n */\nexport interface LintIssue {\n line: number;\n column?: number;\n message: string;\n ruleId?: string;\n dataLoc?: string;\n scopeInfo?: {\n enclosingScope: string | null;\n scopeType: \"function\" | \"arrow-function\" | \"component\" | \"hook\" | \"method\" | \"class\" | \"module\";\n parentScope?: string;\n jsxElementType?: string;\n };\n}\n\n/**\n * Known ESLint config filenames (flat + legacy).\n */\nexport const ESLINT_CONFIG_FILES = [\n // Flat config (ESLint v9+)\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n \"eslint.config.ts\",\n // Legacy config\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n];\n\n/**\n * Build an array of line start offsets for fast line/column -> offset conversion.\n */\nexport function buildLineStarts(code: string): number[] {\n const starts: number[] = [0];\n for (let i = 0; i < code.length; i++) {\n if (code.charCodeAt(i) === 10) starts.push(i + 1); // \\n\n }\n return starts;\n}\n\n/**\n * Convert line (1-indexed) and column (0-indexed) to character offset.\n */\nexport function offsetFromLineCol(\n lineStarts: number[],\n line1: number,\n col0: number,\n codeLength: number\n): number {\n const lineIndex = Math.max(0, Math.min(lineStarts.length - 1, line1 - 1));\n const base = lineStarts[lineIndex] ?? 0;\n return Math.max(0, Math.min(codeLength, base + Math.max(0, col0)));\n}\n\n/**\n * Parse JSX/TSX code and build a list of JSX element spans with data-loc values.\n * The data-loc is computed from the opening element's location.\n */\nexport function buildJsxElementSpans(\n code: string,\n dataLocFile: string\n): JsxElementSpan[] {\n // Use local require to get the TypeScript ESTree parser\n const localRequire = createRequire(import.meta.url);\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => AstNode;\n };\n\n const ast = parse(code, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n\n const spans: JsxElementSpan[] = [];\n\n function walk(node: AstNode): void {\n if (!node || typeof node !== \"object\") return;\n\n // Prefer mapping to JSXElement range so we can capture nested ownership precisely.\n if (node.type === \"JSXElement\") {\n const range = node.range as [number, number] | undefined;\n const opening = node.openingElement;\n const loc = opening?.loc?.start;\n if (\n range &&\n typeof range[0] === \"number\" &&\n typeof range[1] === \"number\" &&\n loc &&\n typeof loc.line === \"number\" &&\n typeof loc.column === \"number\"\n ) {\n const dataLoc = `${dataLocFile}:${loc.line}:${loc.column}`;\n spans.push({ start: range[0], end: range[1], dataLoc });\n }\n }\n\n for (const key of Object.keys(node)) {\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) walk(item);\n } else if (child && typeof child === \"object\") {\n walk(child);\n }\n }\n }\n\n walk(ast);\n\n // Keep spans small-first to make \"smallest containing span\" selection fast.\n spans.sort((a, b) => a.end - a.start - (b.end - b.start));\n return spans;\n}\n\n/**\n * Map an ESLint message (line/column) to the smallest containing JSX element's data-loc.\n */\nexport function mapMessageToDataLoc(params: {\n spans: JsxElementSpan[];\n lineStarts: number[];\n codeLength: number;\n messageLine1: number;\n messageCol1?: number;\n}): string | undefined {\n const col0 =\n typeof params.messageCol1 === \"number\"\n ? Math.max(0, params.messageCol1 - 1)\n : 0;\n const offset = offsetFromLineCol(\n params.lineStarts,\n params.messageLine1,\n col0,\n params.codeLength\n );\n\n // Pick the smallest JSXElement range that contains this offset.\n for (const s of params.spans) {\n if (s.start <= offset && offset < s.end) return s.dataLoc;\n }\n return undefined;\n}\n\n/**\n * Normalize path separators to forward slashes.\n */\nexport function normalizePathSlashes(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\n/**\n * Match `jsx-loc-plugin` behavior:\n * - Use a stable, project-relative path when possible, otherwise absolute.\n */\nexport function normalizeDataLocFilePath(\n absoluteFilePath: string,\n projectCwd: string\n): string {\n const abs = normalizePathSlashes(resolve(absoluteFilePath));\n const cwd = normalizePathSlashes(resolve(projectCwd));\n if (abs === cwd || abs.startsWith(cwd + \"/\")) {\n return normalizePathSlashes(relative(cwd, abs));\n }\n return abs;\n}\n\n/**\n * Find a project root directory for ESLint by walking upward from a file dir.\n */\nexport function findESLintCwd(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 30; i++) {\n for (const cfg of ESLINT_CONFIG_FILES) {\n if (existsSync(join(dir, cfg))) return dir;\n }\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\n// ESLint instances cached per detected project root\nconst eslintInstances = new Map<string, unknown>();\n\n/**\n * Get or create an ESLint instance for a project directory.\n */\nexport async function getESLintForProject(projectCwd: string): Promise<unknown> {\n const cached = eslintInstances.get(projectCwd);\n if (cached) return cached;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n const mod = req(\"eslint\");\n const ESLintCtor =\n mod?.ESLint ?? mod?.default?.ESLint ?? mod?.default ?? mod;\n if (!ESLintCtor) return null;\n\n const eslint = new ESLintCtor({ cwd: projectCwd });\n eslintInstances.set(projectCwd, eslint);\n return eslint;\n } catch {\n return null;\n }\n}\n\n/**\n * Clear the ESLint instance cache (useful for testing or config changes)\n */\nexport function clearESLintCache(): void {\n eslintInstances.clear();\n}\n\n/**\n * Lint a single file and return issues with data-loc mapping.\n */\nexport async function lintFileWithDataLoc(\n absolutePath: string,\n projectCwd: string,\n onProgress?: (phase: string) => void\n): Promise<LintIssue[]> {\n const progress = onProgress ?? (() => {});\n\n if (!existsSync(absolutePath)) {\n progress(`File not found: ${absolutePath}`);\n return [];\n }\n\n progress(`Resolving ESLint project... ${projectCwd}`);\n\n const eslint = await getESLintForProject(projectCwd);\n if (!eslint) {\n progress(\"ESLint not available\");\n return [];\n }\n\n try {\n progress(\"Running ESLint...\");\n const results = await (eslint as { lintFiles(files: string[]): Promise<Array<{ messages: Record<string, unknown>[] }>> }).lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n let spans: JsxElementSpan[] = [];\n let lineStarts: number[] = [];\n let codeLength = 0;\n let fileCode: string | null = null;\n\n try {\n progress(\"Building JSX map...\");\n fileCode = readFileSync(absolutePath, \"utf-8\");\n codeLength = fileCode.length;\n lineStarts = buildLineStarts(fileCode);\n spans = buildJsxElementSpans(fileCode, dataLocFile);\n progress(`JSX map: ${spans.length} element(s)`);\n } catch {\n // If parsing fails, we still return ESLint messages (unmapped).\n progress(\"JSX map failed (falling back to unmapped issues)\");\n spans = [];\n lineStarts = [];\n codeLength = 0;\n fileCode = null;\n }\n\n let issues: LintIssue[] = messages\n .filter((m: Record<string, unknown>) => typeof m?.message === \"string\")\n .map((m: Record<string, unknown>) => {\n const line = typeof m.line === \"number\" ? m.line : 1;\n const column = typeof m.column === \"number\" ? m.column : undefined;\n const mappedDataLoc =\n spans.length > 0 && lineStarts.length > 0 && codeLength > 0\n ? mapMessageToDataLoc({\n spans,\n lineStarts,\n codeLength,\n messageLine1: line,\n messageCol1: column,\n })\n : undefined;\n return {\n line,\n column,\n message: m.message as string,\n ruleId: typeof m.ruleId === \"string\" ? m.ruleId : undefined,\n dataLoc: mappedDataLoc,\n } satisfies LintIssue;\n });\n\n const mappedCount = issues.filter((i) => Boolean(i.dataLoc)).length;\n if (issues.length > 0) {\n progress(`Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`);\n }\n\n // Enrich issues with scope information\n if (fileCode && issues.length > 0) {\n progress(\"Extracting scope info...\");\n issues = enrichIssuesWithScopeInfo(issues, fileCode);\n const scopeCount = issues.filter((i) => Boolean(i.scopeInfo)).length;\n progress(`Enriched ${scopeCount}/${issues.length} issue(s) with scope info`);\n }\n\n return issues;\n } catch (error) {\n progress(`ESLint failed: ${error instanceof Error ? error.message : String(error)}`);\n return [];\n }\n}\n\n/**\n * Extract source snippet around a given line\n */\nexport function extractSourceSnippet(\n code: string,\n centerLine: number,\n contextLines: number = 3\n): { lines: string[]; startLine: number; endLine: number } {\n const allLines = code.split(\"\\n\");\n const startLine = Math.max(1, centerLine - contextLines);\n const endLine = Math.min(allLines.length, centerLine + contextLines);\n\n return {\n lines: allLines.slice(startLine - 1, endLine),\n startLine,\n endLine,\n };\n}\n\n/**\n * Enrich lint issues with scope information.\n *\n * Uses the scope-extractor to add context about where each issue occurs\n * in the code (function name, component name, hook, etc.). Uses batch\n * processing for efficiency when handling multiple issues in the same file.\n *\n * Gracefully degrades: if parsing fails, issues are returned without scopeInfo.\n *\n * @param issues - Array of lint issues to enrich\n * @param code - Source code of the file\n * @returns Issues with scopeInfo added (when available)\n */\nexport function enrichIssuesWithScopeInfo(\n issues: LintIssue[],\n code: string\n): LintIssue[] {\n if (issues.length === 0) {\n return issues;\n }\n\n // Extract positions from issues\n const positions = issues.map((issue) => ({\n line: issue.line,\n column: issue.column ?? 0,\n }));\n\n // Batch extract scope info for all positions\n const scopeInfos = findEnclosingScopeBatch(code, positions);\n\n // Merge scope info back into issues\n return issues.map((issue, index) => {\n const scopeInfo = scopeInfos[index];\n if (scopeInfo) {\n return { ...issue, scopeInfo };\n }\n // If scope extraction failed, return issue without scopeInfo\n return issue;\n });\n}\n","/**\n * Scope Extractor Utility\n *\n * Extracts enclosing context (function name, component name, etc.) from AST\n * based on line/column position. Used to enrich ESLint issues with context\n * about where they occur in the code.\n */\n\nimport { createRequire } from \"module\";\n\n/** Generic AST node type used throughout scope extraction. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AstNode = Record<string, any>;\n\n/**\n * Scope information extracted from AST\n */\nexport interface ScopeInfo {\n /** Name of the enclosing scope: \"handleClick\", \"Button\", \"useEffect\", etc. */\n enclosingScope: string | null;\n /** Type of scope */\n scopeType:\n | \"function\"\n | \"arrow-function\"\n | \"component\"\n | \"hook\"\n | \"method\"\n | \"class\"\n | \"module\";\n /** For nested functions, the parent scope name */\n parentScope?: string;\n /** If inside JSX, the element type (e.g., \"div\", \"Button\") */\n jsxElementType?: string;\n}\n\n/**\n * Options for scope extraction\n */\nexport interface ScopeExtractorOptions {\n /** Parser to use (defaults to \"typescript\" which handles both TS and JS) */\n parser?: \"babel\" | \"typescript\";\n}\n\n/**\n * Internal representation of a scope boundary in the AST\n */\ninterface ScopeBoundary {\n name: string | null;\n type: ScopeInfo[\"scopeType\"];\n start: number;\n end: number;\n line: number;\n column: number;\n}\n\n/**\n * Check if a name represents a React component (PascalCase)\n */\nfunction isComponentName(name: string | null): boolean {\n if (!name) return false;\n // Component names start with uppercase letter\n return /^[A-Z]/.test(name);\n}\n\n/**\n * Check if a name represents a React hook (starts with \"use\")\n */\nfunction isHookName(name: string | null): boolean {\n if (!name) return false;\n return /^use[A-Z]/.test(name);\n}\n\n/**\n * Check if a function body contains JSX return\n */\nfunction containsJsxReturn(node: AstNode): boolean {\n if (!node) return false;\n\n // Direct JSX return\n if (node.type === \"JSXElement\" || node.type === \"JSXFragment\") {\n return true;\n }\n\n // Check block body for return statements with JSX\n if (node.type === \"BlockStatement\" && node.body) {\n for (const stmt of node.body) {\n if (stmt.type === \"ReturnStatement\" && stmt.argument) {\n if (\n stmt.argument.type === \"JSXElement\" ||\n stmt.argument.type === \"JSXFragment\"\n ) {\n return true;\n }\n // Check for conditional expressions returning JSX\n if (stmt.argument.type === \"ConditionalExpression\") {\n if (\n stmt.argument.consequent?.type === \"JSXElement\" ||\n stmt.argument.consequent?.type === \"JSXFragment\" ||\n stmt.argument.alternate?.type === \"JSXElement\" ||\n stmt.argument.alternate?.type === \"JSXFragment\"\n ) {\n return true;\n }\n }\n }\n }\n }\n\n return false;\n}\n\n/**\n * Determine the scope type for a function based on its characteristics\n */\nfunction determineScopeType(\n name: string | null,\n isArrow: boolean,\n isMethod: boolean,\n returnsJsx: boolean,\n isExportDefault: boolean = false\n): ScopeInfo[\"scopeType\"] {\n if (isMethod) return \"method\";\n if (isHookName(name)) return \"hook\";\n // Export default functions returning JSX are components\n if (isExportDefault && returnsJsx) return \"component\";\n if (isComponentName(name) && returnsJsx) return \"component\";\n if (isArrow) return \"arrow-function\";\n return \"function\";\n}\n\n/**\n * Get the name from various identifier patterns\n */\nfunction getIdentifierName(node: AstNode): string | null {\n if (!node) return null;\n if (node.type === \"Identifier\") return node.name;\n if (node.type === \"PrivateIdentifier\") return `#${node.name}`;\n return null;\n}\n\n/**\n * Extract the JSX element type from a JSXElement node\n */\nfunction getJsxElementType(node: AstNode): string | null {\n if (!node || node.type !== \"JSXElement\") return null;\n const opening = node.openingElement;\n if (!opening || !opening.name) return null;\n\n const name = opening.name;\n if (name.type === \"JSXIdentifier\") return name.name;\n if (name.type === \"JSXMemberExpression\") {\n // Handle Foo.Bar\n const parts: string[] = [];\n let current = name;\n while (current) {\n if (current.type === \"JSXMemberExpression\") {\n parts.unshift(current.property.name);\n current = current.object;\n } else if (current.type === \"JSXIdentifier\") {\n parts.unshift(current.name);\n break;\n } else {\n break;\n }\n }\n return parts.join(\".\");\n }\n return null;\n}\n\n/**\n * Convert line (1-indexed) and column (0-indexed) to character offset\n */\nfunction lineColToOffset(code: string, line: number, column: number): number {\n const lines = code.split(\"\\n\");\n let offset = 0;\n for (let i = 0; i < line - 1 && i < lines.length; i++) {\n offset += lines[i].length + 1; // +1 for newline\n }\n return offset + column;\n}\n\n/**\n * Walk AST and collect all scope boundaries\n */\nfunction collectScopeBoundaries(ast: AstNode): ScopeBoundary[] {\n const boundaries: ScopeBoundary[] = [];\n\n function walk(node: AstNode, parentName: string | null = null): void {\n if (!node || typeof node !== \"object\") return;\n\n const range = node.range as [number, number] | undefined;\n const loc = node.loc;\n\n // Function Declaration: function foo() {}\n if (node.type === \"FunctionDeclaration\") {\n const name = getIdentifierName(node.id);\n const returnsJsx = containsJsxReturn(node.body);\n const scopeType = determineScopeType(name, false, false, returnsJsx);\n\n if (range && loc) {\n boundaries.push({\n name,\n type: scopeType,\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n // Walk body with this function as parent\n walk(node.body, name);\n return;\n }\n\n // Arrow Function Expression: const foo = () => {}\n if (node.type === \"ArrowFunctionExpression\") {\n // Try to get name from parent VariableDeclarator\n const name: string | null = null;\n const returnsJsx = containsJsxReturn(node.body);\n\n if (range && loc) {\n const scopeType = determineScopeType(name, true, false, returnsJsx);\n boundaries.push({\n name,\n type: scopeType,\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n walk(node.body, name || parentName);\n return;\n }\n\n // Function Expression: const foo = function() {}\n if (node.type === \"FunctionExpression\") {\n const name = getIdentifierName(node.id);\n const returnsJsx = containsJsxReturn(node.body);\n const scopeType = determineScopeType(name, false, false, returnsJsx);\n\n if (range && loc) {\n boundaries.push({\n name,\n type: scopeType,\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n walk(node.body, name || parentName);\n return;\n }\n\n // Variable Declarator with function: const foo = () => {} or const foo = function() {}\n if (node.type === \"VariableDeclarator\" && node.init) {\n const varName = getIdentifierName(node.id);\n const init = node.init;\n\n if (\n init.type === \"ArrowFunctionExpression\" ||\n init.type === \"FunctionExpression\"\n ) {\n // For named function expressions like `const handler = function processData() {}`\n // prefer the function's own name over the variable name\n const funcOwnName = getIdentifierName(init.id);\n const effectiveName = funcOwnName || varName;\n\n const returnsJsx = containsJsxReturn(init.body);\n const isArrow = init.type === \"ArrowFunctionExpression\";\n const scopeType = determineScopeType(effectiveName, isArrow, false, returnsJsx);\n\n const initRange = init.range as [number, number] | undefined;\n const initLoc = init.loc;\n\n if (initRange && initLoc) {\n // Update any existing boundary for this arrow/function to have the name\n const existing = boundaries.find(\n (b) => b.start === initRange[0] && b.end === initRange[1]\n );\n if (existing) {\n existing.name = effectiveName;\n existing.type = scopeType;\n } else {\n boundaries.push({\n name: effectiveName,\n type: scopeType,\n start: initRange[0],\n end: initRange[1],\n line: initLoc.start.line,\n column: initLoc.start.column,\n });\n }\n }\n\n walk(init.body, effectiveName);\n return;\n }\n }\n\n // Method Definition: class methods and object methods\n if (node.type === \"MethodDefinition\" || node.type === \"Property\") {\n const isMethod =\n node.type === \"MethodDefinition\" ||\n (node.type === \"Property\" && node.method);\n\n if (isMethod && node.value) {\n const name = getIdentifierName(node.key);\n const returnsJsx = containsJsxReturn(node.value.body);\n const scopeType = determineScopeType(name, false, true, returnsJsx);\n\n if (range && loc) {\n boundaries.push({\n name,\n type: scopeType,\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n walk(node.value.body, name);\n return;\n }\n }\n\n // Class Declaration: class Foo {}\n if (node.type === \"ClassDeclaration\" || node.type === \"ClassExpression\") {\n const name = getIdentifierName(node.id);\n\n if (range && loc) {\n boundaries.push({\n name,\n type: \"class\",\n start: range[0],\n end: range[1],\n line: loc.start.line,\n column: loc.start.column,\n });\n }\n\n // Walk class body\n if (node.body) {\n walk(node.body, name);\n }\n return;\n }\n\n // Export default function/class\n if (node.type === \"ExportDefaultDeclaration\" && node.declaration) {\n const decl = node.declaration;\n\n if (decl.type === \"FunctionDeclaration\") {\n // Named export default: export default function Foo() {}\n const name = getIdentifierName(decl.id);\n const returnsJsx = containsJsxReturn(decl.body);\n // Pass isExportDefault=true for anonymous export defaults returning JSX\n const scopeType = determineScopeType(name, false, false, returnsJsx, !name);\n\n const declRange = decl.range as [number, number] | undefined;\n const declLoc = decl.loc;\n\n if (declRange && declLoc) {\n boundaries.push({\n name: name || \"default\",\n type: scopeType,\n start: declRange[0],\n end: declRange[1],\n line: declLoc.start.line,\n column: declLoc.start.column,\n });\n }\n\n walk(decl.body, name || \"default\");\n return;\n }\n\n if (decl.type === \"ClassDeclaration\") {\n // The class declaration itself will be visited\n walk(decl, parentName);\n return;\n }\n\n // Anonymous export default function/arrow\n if (\n decl.type === \"FunctionExpression\" ||\n decl.type === \"ArrowFunctionExpression\"\n ) {\n const funcOwnName = getIdentifierName(decl.id);\n const name = funcOwnName || \"default\";\n const returnsJsx = containsJsxReturn(decl.body);\n const isArrow = decl.type === \"ArrowFunctionExpression\";\n // Pass isExportDefault=true for anonymous export defaults returning JSX\n const scopeType = determineScopeType(name, isArrow, false, returnsJsx, !funcOwnName);\n\n const declRange = decl.range as [number, number] | undefined;\n const declLoc = decl.loc;\n\n if (declRange && declLoc) {\n boundaries.push({\n name,\n type: scopeType,\n start: declRange[0],\n end: declRange[1],\n line: declLoc.start.line,\n column: declLoc.start.column,\n });\n }\n\n walk(decl.body, name);\n return;\n }\n }\n\n // Walk all children\n for (const key of Object.keys(node)) {\n if (key === \"loc\" || key === \"range\" || key === \"parent\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n walk(item, parentName);\n }\n } else if (child && typeof child === \"object\" && child.type) {\n walk(child, parentName);\n }\n }\n }\n\n walk(ast);\n return boundaries;\n}\n\n/**\n * Find the innermost JSX element containing a position\n */\nfunction findContainingJsxElement(ast: AstNode, offset: number): string | null {\n // Use object wrapper to help TypeScript understand closure mutation\n const result: { innermost: { type: string; size: number } | null } = {\n innermost: null,\n };\n\n function walk(node: AstNode): void {\n if (!node || typeof node !== \"object\") return;\n\n if (node.type === \"JSXElement\") {\n const range = node.range as [number, number] | undefined;\n if (range && range[0] <= offset && offset < range[1]) {\n const size = range[1] - range[0];\n if (!result.innermost || size < result.innermost.size) {\n const elementType = getJsxElementType(node);\n if (elementType) {\n result.innermost = { type: elementType, size };\n }\n }\n }\n }\n\n for (const key of Object.keys(node)) {\n if (key === \"loc\" || key === \"range\" || key === \"parent\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) walk(item);\n } else if (child && typeof child === \"object\" && child.type) {\n walk(child);\n }\n }\n }\n\n walk(ast);\n return result.innermost?.type ?? null;\n}\n\n/**\n * Find the enclosing scope for a given line/column position in source code.\n *\n * @param source - The source code to parse\n * @param line - Line number (1-indexed)\n * @param column - Column number (0-indexed)\n * @param options - Parser options\n * @returns Scope information or null if at module level\n */\nexport function findEnclosingScope(\n source: string,\n line: number,\n column: number,\n _options?: ScopeExtractorOptions\n): ScopeInfo | null {\n // Use typescript-estree parser (handles both TS and JS/JSX)\n const localRequire = createRequire(import.meta.url);\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => AstNode;\n };\n\n let ast: AstNode;\n try {\n ast = parse(source, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n } catch {\n return null;\n }\n\n const offset = lineColToOffset(source, line, column);\n const boundaries = collectScopeBoundaries(ast);\n\n // Find all scopes containing this offset, sorted by size (smallest first)\n const containingScopes = boundaries\n .filter((b) => b.start <= offset && offset < b.end)\n .sort((a, b) => a.end - a.start - (b.end - b.start));\n\n // Find JSX element context\n const jsxElementType = findContainingJsxElement(ast, offset);\n\n // If no containing scope, return module scope\n if (containingScopes.length === 0) {\n return {\n enclosingScope: null,\n scopeType: \"module\",\n jsxElementType: jsxElementType ?? undefined,\n };\n }\n\n const innermost = containingScopes[0];\n const parent = containingScopes.length > 1 ? containingScopes[1] : null;\n\n // Handle anonymous functions\n const scopeName = innermost.name || \"anonymous\";\n\n return {\n enclosingScope: scopeName,\n scopeType: innermost.type,\n parentScope: parent?.name ?? undefined,\n jsxElementType: jsxElementType ?? undefined,\n };\n}\n\n/**\n * Batch extract scope information for multiple positions in the same source.\n * More efficient than calling findEnclosingScope multiple times.\n *\n * @param source - The source code to parse\n * @param positions - Array of {line, column} positions\n * @param options - Parser options\n * @returns Array of scope information (null for errors)\n */\nexport function findEnclosingScopeBatch(\n source: string,\n positions: Array<{ line: number; column: number }>,\n _options?: ScopeExtractorOptions\n): Array<ScopeInfo | null> {\n // Use typescript-estree parser\n const localRequire = createRequire(import.meta.url);\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => AstNode;\n };\n\n let ast: AstNode;\n try {\n ast = parse(source, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n } catch {\n return positions.map(() => null);\n }\n\n const boundaries = collectScopeBoundaries(ast);\n\n return positions.map(({ line, column }) => {\n const offset = lineColToOffset(source, line, column);\n\n // Find all scopes containing this offset, sorted by size (smallest first)\n const containingScopes = boundaries\n .filter((b) => b.start <= offset && offset < b.end)\n .sort((a, b) => a.end - a.start - (b.end - b.start));\n\n // Find JSX element context\n const jsxElementType = findContainingJsxElement(ast, offset);\n\n // If no containing scope, return module scope\n if (containingScopes.length === 0) {\n return {\n enclosingScope: null,\n scopeType: \"module\" as const,\n jsxElementType: jsxElementType ?? undefined,\n };\n }\n\n const innermost = containingScopes[0];\n const parent = containingScopes.length > 1 ? containingScopes[1] : null;\n\n // Handle anonymous functions\n const scopeName = innermost.name || \"anonymous\";\n\n return {\n enclosingScope: scopeName,\n scopeType: innermost.type,\n parentScope: parent?.name ?? undefined,\n jsxElementType: jsxElementType ?? undefined,\n };\n });\n}\n","/**\n * Vision command - analyze a screenshot with Ollama vision models\n *\n * Mirrors the \"scan\" command UX (debug flags, JSON/text output), but operates on images.\n */\n\nimport { dirname, resolve, join } from \"path\";\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n} from \"fs\";\nimport { ensureOllamaReady, STYLEGUIDE_PATHS } from \"uilint-core/node\";\n\n// Vision module is dynamically imported to avoid hard dependency on uilint-vision.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _visionNodeModule: any = null;\nasync function loadVisionModule() {\n if (_visionNodeModule) return _visionNodeModule;\n try {\n _visionNodeModule = await import(\"uilint-vision/node\");\n return _visionNodeModule;\n } catch {\n return null;\n }\n}\n// Re-declare the key types locally so the rest of the file compiles\n// without importing from uilint-vision.\ntype ElementManifest = {\n id: string;\n text: string;\n dataLoc: string;\n rect: { x: number; y: number; width: number; height: number };\n tagName: string;\n role?: string;\n instanceCount?: number;\n};\ntype VisionIssue = {\n elementText: string;\n dataLoc?: string;\n message: string;\n category: string;\n severity: string;\n suggestion?: string;\n};\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n note,\n logInfo,\n logWarning,\n logError,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface VisionOptions {\n /** Path to a screenshot image (png/jpg). */\n image?: string;\n /** Path to a `.json` sidecar containing { manifest, ... } (as saved by the Next screenshot route). */\n sidecar?: string;\n /** Inline manifest JSON string (array). */\n manifestJson?: string;\n /** Path to a manifest JSON file (array). */\n manifestFile?: string;\n /** Explicit route label (used in output and debug dump). */\n route?: string;\n /** Path to style guide file or project dir (same semantics as scan.ts). */\n styleguide?: string;\n /** Output format */\n output?: \"text\" | \"json\";\n /** List available `.uilint/screenshots/*.json` sidecars and exit */\n list?: boolean;\n /** Optional screenshots directory to list from (default: nearest `.uilint/screenshots`) */\n screenshotsDir?: string;\n /** Stream model output/progress (text mode only; JSON output stays non-streaming) */\n stream?: boolean;\n /** Ollama base URL (default: http://localhost:11434) */\n baseUrl?: string;\n /** Vision model override (default: UILINT_DEFAULT_VISION_MODEL) */\n model?: string;\n /** Enable debug logging (stderr only; never pollutes JSON stdout). Can also be enabled via UILINT_DEBUG=1 */\n debug?: boolean;\n /** Print full prompt/styleguide (can be very large). Can also be enabled via UILINT_DEBUG_FULL=1 */\n debugFull?: boolean;\n /** Dump payload to file. Can also be set via UILINT_DEBUG_DUMP=/path */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: VisionOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: VisionOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: VisionOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nfunction findScreenshotsDirUpwards(startDir: string): string | null {\n let dir = startDir;\n for (let i = 0; i < 20; i++) {\n const candidate = join(dir, \".uilint\", \"screenshots\");\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\ntype ScreenshotSidecarSummary = {\n path: string;\n filename: string;\n timestamp?: number;\n route?: string;\n issueCount?: number;\n};\n\nfunction listScreenshotSidecars(dirPath: string): ScreenshotSidecarSummary[] {\n if (!existsSync(dirPath)) return [];\n const entries = readdirSync(dirPath)\n .filter((f) => f.endsWith(\".json\"))\n .map((f) => join(dirPath, f));\n\n const out: ScreenshotSidecarSummary[] = [];\n for (const p of entries) {\n try {\n const json = loadJsonFile<Record<string, unknown>>(p);\n const analysisResult = json?.analysisResult as Record<string, unknown> | undefined;\n const issues = Array.isArray(json?.issues)\n ? json.issues\n : analysisResult?.issues;\n out.push({\n path: p,\n filename:\n (json?.filename as string) || (json?.screenshotFile as string) || p.split(\"/\").pop() || p,\n timestamp:\n typeof json?.timestamp === \"number\" ? json.timestamp : undefined,\n route: typeof json?.route === \"string\" ? json.route : undefined,\n issueCount: Array.isArray(issues) ? issues.length : undefined,\n });\n } catch {\n out.push({\n path: p,\n filename: p.split(\"/\").pop() || p,\n });\n }\n }\n\n // Newest first (fallback to filename sort)\n out.sort((a, b) => {\n const at = a.timestamp ?? 0;\n const bt = b.timestamp ?? 0;\n if (at !== bt) return bt - at;\n return b.path.localeCompare(a.path);\n });\n\n return out;\n}\n\nfunction readImageAsBase64(imagePath: string): {\n base64: string;\n sizeBytes: number;\n} {\n const bytes = readFileSync(imagePath);\n return { base64: bytes.toString(\"base64\"), sizeBytes: bytes.byteLength };\n}\n\nfunction loadJsonFile<T>(filePath: string): T {\n const raw = readFileSync(filePath, \"utf-8\");\n return JSON.parse(raw) as T;\n}\n\nfunction formatIssuesText(issues: VisionIssue[]): string {\n if (issues.length === 0) return \"No vision issues found.\\n\";\n return (\n issues\n .map((i) => {\n const sev = i.severity || \"info\";\n const cat = i.category || \"other\";\n const where = i.dataLoc ? ` (${i.dataLoc})` : \"\";\n return `- [${sev}/${cat}] ${i.message}${where}`;\n })\n .join(\"\\n\") + \"\\n\"\n );\n}\n\nexport async function vision(options: VisionOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) intro(\"Vision (Screenshot) Analysis\");\n\n // Load vision module dynamically\n const visionMod = await loadVisionModule();\n if (!visionMod) {\n logError(\"uilint-vision is not installed. Run: pnpm add uilint-vision\");\n process.exit(1);\n }\n\n const UILINT_DEFAULT_VISION_MODEL = visionMod.UILINT_DEFAULT_VISION_MODEL;\n const resolveVisionStyleGuide = visionMod.resolveVisionStyleGuide;\n const runVisionAnalysis = visionMod.runVisionAnalysis;\n const writeVisionMarkdownReport = visionMod.writeVisionMarkdownReport;\n\n try {\n const projectPath = process.cwd();\n\n // List mode (no analysis)\n if (options.list) {\n const base =\n (options.screenshotsDir\n ? resolvePathSpecifier(options.screenshotsDir, projectPath)\n : null) || findScreenshotsDirUpwards(projectPath);\n\n if (!base) {\n if (isJsonOutput) {\n printJSON({ screenshotsDir: null, sidecars: [] });\n } else {\n logWarning(\n \"No `.uilint/screenshots` directory found (walked up from cwd).\"\n );\n }\n await flushLangfuse();\n return;\n }\n\n const sidecars = listScreenshotSidecars(base);\n if (isJsonOutput) {\n printJSON({ screenshotsDir: base, sidecars });\n } else {\n logInfo(`Screenshots dir: ${pc.dim(base)}`);\n if (sidecars.length === 0) {\n process.stdout.write(\"No sidecars found.\\n\");\n } else {\n process.stdout.write(\n sidecars\n .map((s, idx) => {\n const stamp = s.timestamp\n ? new Date(s.timestamp).toLocaleString()\n : \"(no timestamp)\";\n const route = s.route ? ` ${pc.dim(s.route)}` : \"\";\n const count =\n typeof s.issueCount === \"number\"\n ? ` ${pc.dim(`(${s.issueCount} issues)`)}`\n : \"\";\n return `${idx === 0 ? \"*\" : \"-\"} ${s.path}${pc.dim(\n ` — ${stamp}`\n )}${route}${count}`;\n })\n .join(\"\\n\") + \"\\n\"\n );\n process.stdout.write(\n pc.dim(\n `Tip: run \\`uilint vision --sidecar <path>\\` (the newest is marked with \"*\").\\n`\n )\n );\n }\n }\n await flushLangfuse();\n return;\n }\n\n // Resolve inputs\n const imagePath = options.image\n ? resolvePathSpecifier(options.image, projectPath)\n : undefined;\n const sidecarPath = options.sidecar\n ? resolvePathSpecifier(options.sidecar, projectPath)\n : undefined;\n const manifestFilePath = options.manifestFile\n ? resolvePathSpecifier(options.manifestFile, projectPath)\n : undefined;\n\n if (!imagePath && !sidecarPath) {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", issues: [] });\n } else {\n logError(\"No input provided. Use --image or --sidecar.\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n if (imagePath && !existsSync(imagePath)) {\n throw new Error(`Image not found: ${imagePath}`);\n }\n if (sidecarPath && !existsSync(sidecarPath)) {\n throw new Error(`Sidecar not found: ${sidecarPath}`);\n }\n if (manifestFilePath && !existsSync(manifestFilePath)) {\n throw new Error(`Manifest file not found: ${manifestFilePath}`);\n }\n\n // Load sidecar if provided (supports the Next screenshot route payload)\n const sidecar = sidecarPath\n ? loadJsonFile<{\n filename?: string;\n screenshotFile?: string;\n route?: string;\n manifest?: unknown;\n analysisResult?: unknown;\n issues?: unknown;\n }>(sidecarPath)\n : null;\n\n const routeLabel =\n options.route ||\n (typeof sidecar?.route === \"string\" ? sidecar.route : undefined) ||\n (sidecarPath ? `(from ${sidecarPath})` : \"(unknown)\");\n\n // Manifest sources (priority: --manifest-json > --manifest-file > sidecar.manifest)\n let manifest: ElementManifest[] | null = null;\n if (options.manifestJson) {\n manifest = JSON.parse(options.manifestJson) as ElementManifest[];\n } else if (manifestFilePath) {\n manifest = loadJsonFile<ElementManifest[]>(manifestFilePath);\n } else if (sidecar && Array.isArray(sidecar.manifest)) {\n manifest = sidecar.manifest as ElementManifest[];\n }\n\n if (!manifest || manifest.length === 0) {\n throw new Error(\n \"No manifest provided. Supply --manifest-json, --manifest-file, or a sidecar JSON with a `manifest` array.\"\n );\n }\n\n // Styleguide resolution: same semantics as scan.ts (path/file/dir), with a good default start dir.\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n const startPath =\n (imagePath ?? sidecarPath ?? manifestFilePath ?? undefined) || undefined;\n\n {\n const resolved = await resolveVisionStyleGuide({\n projectPath,\n styleguide: options.styleguide,\n startDir: startPath ? dirname(startPath) : projectPath,\n pathResolver: resolvePathSpecifier,\n });\n styleGuide = resolved.styleGuide;\n styleguideLocation = resolved.styleguideLocation;\n }\n\n if (styleguideLocation && styleGuide) {\n if (!isJsonOutput)\n logSuccess(`Using styleguide: ${pc.dim(styleguideLocation)}`);\n } else if (!styleGuide && !isJsonOutput) {\n logWarning(\"No styleguide found\");\n note(\n [\n `Searched in: ${options.styleguide || projectPath}`,\n \"\",\n \"Looked for:\",\n ...STYLEGUIDE_PATHS.map((p) => ` • ${p}`),\n \"\",\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n ].join(\"\\n\"),\n \"Missing Styleguide\"\n );\n }\n\n debugLog(dbg, \"Vision input (high-level)\", {\n imagePath: imagePath ?? null,\n sidecarPath: sidecarPath ?? null,\n manifestFile: manifestFilePath ?? null,\n manifestElements: manifest.length,\n route: routeLabel,\n styleguideLocation,\n styleGuideLength: styleGuide ? styleGuide.length : 0,\n });\n\n // Prepare Ollama (ensure model exists & server up)\n const visionModel = options.model || UILINT_DEFAULT_VISION_MODEL;\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady({\n model: visionModel,\n baseUrl: options.baseUrl,\n });\n });\n } else {\n await ensureOllamaReady({ model: visionModel, baseUrl: options.baseUrl });\n }\n const prepEndNs = nsNow();\n\n // Load screenshot bytes\n const resolvedImagePath =\n imagePath ||\n (() => {\n // If sidecar contains screenshotFile and is relative, resolve relative to the sidecar dir.\n const screenshotFile =\n typeof sidecar?.screenshotFile === \"string\"\n ? sidecar.screenshotFile\n : typeof sidecar?.filename === \"string\"\n ? sidecar.filename\n : undefined;\n if (!screenshotFile) return null;\n const baseDir = sidecarPath ? dirname(sidecarPath) : projectPath;\n const abs = resolve(baseDir, screenshotFile);\n return abs;\n })();\n\n if (!resolvedImagePath) {\n throw new Error(\n \"No image path could be resolved. Provide --image or a sidecar with `screenshotFile`/`filename`.\"\n );\n }\n if (!existsSync(resolvedImagePath)) {\n throw new Error(`Image not found: ${resolvedImagePath}`);\n }\n\n const { base64, sizeBytes } = readImageAsBase64(resolvedImagePath);\n debugLog(dbg, \"Image loaded\", {\n imagePath: resolvedImagePath,\n sizeBytes,\n base64Length: base64.length,\n });\n\n if (dbgFull && styleGuide) {\n debugLog(dbg, \"Styleguide (full)\", styleGuide);\n } else if (dbg && styleGuide) {\n debugLog(dbg, \"Styleguide (preview)\", preview(styleGuide, 800));\n }\n\n // Run analysis (optionally show streaming progress in text mode)\n let result: {\n issues: VisionIssue[];\n analysisTime: number;\n prompt?: string;\n rawResponse?: string;\n } | null = null;\n\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n\n if (isJsonOutput) {\n result = await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n pathResolver: resolvePathSpecifier,\n });\n } else {\n if (options.stream) {\n let lastStatus = \"\";\n let printedAnyText = false;\n let inThinking = false;\n result = await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!printedAnyText) {\n printedAnyText = true;\n console.error(pc.dim(\"[vision] streaming:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n inThinking = true;\n } else if (!inThinking) {\n process.stderr.write(pc.dim(\"\\n\\nThinking:\\n\"));\n inThinking = true;\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n\n // If we got a text delta, stream it directly\n if (delta) {\n if (!printedAnyText) {\n printedAnyText = true;\n console.error(pc.dim(\"[vision] streaming:\"));\n }\n if (inThinking) {\n process.stderr.write(pc.dim(\"\\n\\nAnswer:\\n\"));\n inThinking = false;\n }\n // Stream raw text to stderr to avoid corrupting stdout.\n process.stderr.write(delta);\n return;\n }\n\n // Fallback to status output (latest line / heartbeats).\n const line = (latestLine || \"\").trim();\n if (!line || line === lastStatus) return;\n lastStatus = line;\n console.error(pc.dim(\"[vision]\"), line);\n },\n pathResolver: resolvePathSpecifier,\n });\n } else {\n result = await withSpinner(\n \"Analyzing screenshot with vision model\",\n async (s) => {\n return await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta))\n firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n const maxLen = 60;\n const displayLine =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(displayLine || \"...\")}`);\n },\n pathResolver: resolvePathSpecifier,\n });\n }\n );\n }\n }\n\n const analysisEndNs = nsNow();\n\n const issues = result?.issues ?? [];\n\n if (isJsonOutput) {\n printJSON({\n route: routeLabel,\n model: visionModel,\n issues,\n analysisTime: result?.analysisTime ?? 0,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n });\n } else {\n logInfo(`Route: ${pc.dim(routeLabel)}`);\n logInfo(`Model: ${pc.dim(visionModel)}`);\n process.stdout.write(formatIssuesText(issues));\n\n // Pretty timings (TTY-only so we don't clutter non-interactive usage)\n if (process.stdout.isTTY) {\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n result?.analysisTime\n ? pc.dim(`(core analysisTime: ${formatMs(result.analysisTime)})`)\n : pc.dim(\"(core analysisTime: n/a)\"),\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n }\n\n // Write markdown report alongside the image (best-effort; never affects stdout JSON).\n try {\n writeVisionMarkdownReport({\n imagePath: resolvedImagePath,\n route: routeLabel,\n visionModel,\n baseUrl: options.baseUrl ?? \"http://localhost:11434\",\n analysisTimeMs: result?.analysisTime ?? 0,\n prompt: result?.prompt ?? null,\n rawResponse: result?.rawResponse ?? null,\n metadata: {\n imageSizeBytes: sizeBytes,\n styleguideLocation,\n },\n });\n debugLog(dbg, \"Wrote .vision.md report alongside image\");\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write .vision.md report\",\n e instanceof Error ? e.message : e\n );\n }\n\n // Exit with error code if issues found\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (options.output === \"json\") {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(\n error instanceof Error ? error.message : \"Vision analysis failed\"\n );\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n await flushLangfuse();\n}\n","/**\n * UILint Config Command\n *\n * Allows setting configuration options that are broadcast to connected clients.\n *\n * Usage:\n * uilint config set position <x,y> - Set floating icon position\n * uilint config set position top-center - Use preset position\n * uilint config get position - Get current position (from server)\n * uilint config set rule <ruleId>:<severity> [optionsJson] - Set rule config\n *\n * Examples:\n * uilint config set rule consistent-dark-mode:warn\n * uilint config set rule no-prop-drilling-depth:error '{\"maxDepth\":3}'\n * uilint config set rule no-mixed-component-libraries:off\n */\n\nimport { WebSocket } from \"ws\";\nimport { logInfo, logSuccess, logError, pc } from \"../utils/prompts.js\";\n\nexport interface ConfigOptions {\n port?: number;\n}\n\n/** Parse position value from string */\nfunction parsePosition(\n value: string\n): { x: number; y: number } | { preset: string } | null {\n // Check for presets\n const presets: Record<string, true> = {\n \"top-center\": true,\n \"top-left\": true,\n \"top-right\": true,\n \"bottom-center\": true,\n \"bottom-left\": true,\n \"bottom-right\": true,\n };\n\n if (presets[value]) {\n return { preset: value };\n }\n\n // Try to parse as x,y coordinates\n const match = value.match(/^(\\d+),(\\d+)$/);\n if (match) {\n return { x: parseInt(match[1], 10), y: parseInt(match[2], 10) };\n }\n\n return null;\n}\n\n/** Convert preset to position (approximate, client will recalculate) */\nfunction presetToPosition(preset: string): { x: number; y: number } {\n // These are approximate defaults - the client can recalculate based on viewport\n const positions: Record<string, { x: number; y: number }> = {\n \"top-center\": { x: 500, y: 30 },\n \"top-left\": { x: 60, y: 30 },\n \"top-right\": { x: 940, y: 30 },\n \"bottom-center\": { x: 500, y: 700 },\n \"bottom-left\": { x: 60, y: 700 },\n \"bottom-right\": { x: 940, y: 700 },\n };\n return positions[preset] || { x: 500, y: 30 };\n}\n\n/** Parse rule configuration from value string */\nfunction parseRuleConfig(value: string): {\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n} | null {\n // Format: <ruleId>:<severity>\n const match = value.match(/^([^:]+):(error|warn|off)$/);\n if (!match) {\n return null;\n }\n return {\n ruleId: match[1],\n severity: match[2] as \"error\" | \"warn\" | \"off\",\n };\n}\n\n/** Parse options JSON string */\nfunction parseOptionsJson(optionsStr: string | undefined): Record<string, unknown> | undefined {\n if (!optionsStr) {\n return undefined;\n }\n try {\n const parsed = JSON.parse(optionsStr);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return undefined;\n }\n return parsed as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Send config message via WebSocket\n */\nasync function sendConfigMessage(\n port: number,\n key: string,\n value: unknown\n): Promise<boolean> {\n return new Promise((resolve) => {\n const url = `ws://localhost:${port}`;\n const ws = new WebSocket(url);\n let resolved = false;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n ws.close();\n resolve(false);\n }\n }, 5000);\n\n ws.on(\"open\", () => {\n const message = JSON.stringify({ type: \"config:set\", key, value });\n ws.send(message);\n\n // Give the server time to process and broadcast\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n ws.close();\n resolve(true);\n }\n }, 100);\n });\n\n ws.on(\"error\", () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve(false);\n }\n });\n });\n}\n\n/**\n * Send rule config message via WebSocket and wait for result\n */\nasync function sendRuleConfigMessage(\n port: number,\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>\n): Promise<{ success: boolean; error?: string }> {\n return new Promise((resolve) => {\n const url = `ws://localhost:${port}`;\n const ws = new WebSocket(url);\n let resolved = false;\n const requestId = `cli-${Date.now()}`;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n ws.close();\n resolve({ success: false, error: \"Request timed out\" });\n }\n }, 10000);\n\n ws.on(\"open\", () => {\n const message = JSON.stringify({\n type: \"rule:config:set\",\n ruleId,\n severity,\n options,\n requestId,\n });\n ws.send(message);\n });\n\n ws.on(\"message\", (data: Buffer) => {\n try {\n const msg = JSON.parse(data.toString());\n if (msg.type === \"rule:config:result\" && msg.requestId === requestId) {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n ws.close();\n resolve({\n success: msg.success,\n error: msg.error,\n });\n }\n }\n } catch {\n // Ignore parse errors\n }\n });\n\n ws.on(\"error\", () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve({ success: false, error: \"Connection error\" });\n }\n });\n });\n}\n\n/**\n * Handle config set command\n */\nasync function handleSet(\n key: string,\n value: string,\n port: number,\n extraArg?: string\n): Promise<void> {\n switch (key) {\n case \"position\": {\n const parsed = parsePosition(value);\n if (!parsed) {\n logError(\n `Invalid position value: ${value}\\n` +\n `Expected format: x,y (e.g., 100,50) or preset (top-center, top-left, etc.)`\n );\n process.exit(1);\n }\n\n let position: { x: number; y: number };\n if (\"preset\" in parsed) {\n position = presetToPosition(parsed.preset);\n logInfo(`Using preset \"${parsed.preset}\" → (${position.x}, ${position.y})`);\n } else {\n position = parsed;\n }\n\n const success = await sendConfigMessage(\n port,\n \"floatingIconPosition\",\n position\n );\n\n if (success) {\n logSuccess(\n `Set floating icon position to (${position.x}, ${position.y})`\n );\n } else {\n logError(\n `Failed to set position. Is the server running?\\n` +\n `Start it with: ${pc.bold(\"npx uilint serve\")}`\n );\n process.exit(1);\n }\n break;\n }\n\n case \"rule\": {\n const parsed = parseRuleConfig(value);\n if (!parsed) {\n logError(\n `Invalid rule config: ${value}\\n` +\n `Expected format: <ruleId>:<severity>\\n` +\n ` severity: error, warn, or off\\n\\n` +\n `Examples:\\n` +\n ` uilint config set rule consistent-dark-mode:warn\\n` +\n ` uilint config set rule no-prop-drilling-depth:error '{\"maxDepth\":3}'`\n );\n process.exit(1);\n }\n\n // Parse optional options JSON from extra argument\n const options = parseOptionsJson(extraArg);\n if (extraArg && !options) {\n logError(\n `Invalid options JSON: ${extraArg}\\n` +\n `Expected a valid JSON object, e.g., '{\"maxDepth\": 3}'`\n );\n process.exit(1);\n }\n\n logInfo(\n `Setting rule \"${parsed.ruleId}\" to ${parsed.severity}` +\n (options ? ` with options: ${JSON.stringify(options)}` : \"\")\n );\n\n const result = await sendRuleConfigMessage(\n port,\n parsed.ruleId,\n parsed.severity,\n options\n );\n\n if (result.success) {\n logSuccess(\n `Rule \"${parsed.ruleId}\" set to ${parsed.severity}` +\n (options ? ` with options` : \"\")\n );\n } else {\n logError(\n result.error ||\n `Failed to set rule config. Is the server running?\\n` +\n `Start it with: ${pc.bold(\"npx uilint serve\")}`\n );\n process.exit(1);\n }\n break;\n }\n\n default:\n logError(`Unknown config key: ${key}`);\n logInfo(`Available keys: position, rule`);\n process.exit(1);\n }\n}\n\n/**\n * Handle config get command\n */\nasync function handleGet(key: string, _port: number): Promise<void> {\n switch (key) {\n case \"position\":\n logInfo(\n `Position is stored in the browser's localStorage.\\n` +\n `To view it, check your browser's dev tools:\\n` +\n ` localStorage.getItem(\"uilint:floatingIconPosition\")`\n );\n break;\n\n default:\n logError(`Unknown config key: ${key}`);\n logInfo(`Available keys: position`);\n process.exit(1);\n }\n}\n\n/**\n * Config command entry point\n */\nexport async function config(\n action: string,\n key: string,\n value?: string,\n extraArg?: string,\n options: ConfigOptions = {}\n): Promise<void> {\n const port = options.port || 9234;\n\n switch (action) {\n case \"set\":\n if (!value) {\n logError(`Missing value for config set ${key}`);\n process.exit(1);\n }\n await handleSet(key, value, port, extraArg);\n break;\n\n case \"get\":\n await handleGet(key, port);\n break;\n\n default:\n logError(`Unknown action: ${action}`);\n logInfo(`Usage: uilint config <set|get> <key> [value] [options]`);\n process.exit(1);\n }\n}\n","/**\n * Duplicates command - semantic code duplicate detection\n */\n\nimport { Command } from \"commander\";\nimport { indexCommand } from \"./index-cmd.js\";\nimport { findCommand } from \"./find.js\";\nimport { searchCommand } from \"./search.js\";\nimport { similarCommand } from \"./similar.js\";\n\nexport function createDuplicatesCommand(): Command {\n const duplicates = new Command(\"duplicates\")\n .description(\"Semantic code duplicate detection\");\n\n // Add subcommands\n duplicates.addCommand(indexCommand());\n duplicates.addCommand(findCommand());\n duplicates.addCommand(searchCommand());\n duplicates.addCommand(similarCommand());\n\n return duplicates;\n}\n","/**\n * Index command - build or update the semantic duplicates index\n */\n\nimport { Command } from \"commander\";\n\nimport chalk from \"chalk\";\nimport ora from \"ora\";\n\nexport function indexCommand(): Command {\n return new Command(\"index\")\n .description(\"Build or update the semantic duplicates index\")\n .option(\"--force\", \"Rebuild index from scratch\")\n .option(\"--model <name>\", \"Embedding model (default: nomic-embed-text)\")\n .option(\n \"--exclude <glob>\",\n \"Exclude patterns (repeatable)\",\n (val: string, prev: string[]) => [...prev, val],\n [] as string[]\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n const { indexDirectory } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n let spinner: ReturnType<typeof ora> | undefined;\n if (!isJson) {\n spinner = ora(\"Initializing indexer...\").start();\n }\n\n try {\n const result = await indexDirectory(projectRoot, {\n force: options.force,\n model: options.model,\n exclude: options.exclude,\n onProgress: (message, current, total) => {\n if (spinner) {\n if (current && total) {\n spinner.text = `${message} (${current}/${total})`;\n } else {\n spinner.text = message;\n }\n }\n },\n });\n\n if (isJson) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n spinner?.succeed(chalk.green(\"Index complete\"));\n console.log();\n console.log(chalk.bold(\"Index Statistics:\"));\n console.log(` Files added: ${result.added}`);\n console.log(` Files modified: ${result.modified}`);\n console.log(` Files deleted: ${result.deleted}`);\n console.log(` Total chunks: ${result.totalChunks}`);\n console.log(` Duration: ${(result.duration / 1000).toFixed(2)}s`);\n }\n } catch (error) {\n if (spinner) {\n spinner.fail(chalk.red(\"Index failed\"));\n }\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Find command - find semantic duplicate groups\n */\n\nimport { Command } from \"commander\";\nimport { relative } from \"path\";\nimport chalk from \"chalk\";\nimport type { ChunkKind } from \"uilint-duplicates\";\n\nexport function findCommand(): Command {\n return new Command(\"find\")\n .description(\"Find semantic duplicate groups in the codebase\")\n .option(\n \"--threshold <n>\",\n \"Similarity threshold 0-1 (default: 0.75)\",\n parseFloat\n )\n .option(\"--min-size <n>\", \"Minimum group size (default: 2)\", parseInt)\n .option(\"--kind <type>\", \"Filter: component, hook, function\")\n .option(\n \"--confidence <level>\",\n \"Minimum confidence: high, medium, low (default: low)\"\n )\n .option(\"--no-structural\", \"Disable structural similarity boost\")\n .option(\"--same-file\", \"Include duplicates within the same file\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n const { findDuplicates } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n try {\n const groups = await findDuplicates({\n path: projectRoot,\n threshold: options.threshold,\n minGroupSize: options.minSize,\n kind: options.kind as ChunkKind | undefined,\n confidenceLevel: options.confidence as \"high\" | \"medium\" | \"low\" | undefined,\n useStructuralBoost: options.structural !== false,\n includeSameFile: options.sameFile ?? false,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ groups }, null, 2));\n return;\n }\n\n if (groups.length === 0) {\n console.log(chalk.green(\"No semantic duplicates found.\"));\n return;\n }\n\n console.log(\n chalk.bold(\n `Found ${groups.length} duplicate group${groups.length > 1 ? \"s\" : \"\"}:\\n`\n )\n );\n\n groups.forEach((group, idx) => {\n const similarity = Math.round(group.avgSimilarity * 100);\n const confidenceEmoji =\n group.confidence === \"high\" ? \"🔴\" :\n group.confidence === \"medium\" ? \"🟡\" : \"🟢\";\n const confidenceColor =\n group.confidence === \"high\" ? chalk.red :\n group.confidence === \"medium\" ? chalk.yellow : chalk.green;\n\n console.log(\n chalk.bold(\n `${confidenceEmoji} Duplicate Group ${idx + 1} ` +\n `(${confidenceColor(`${similarity}% - ${group.confidence} confidence`)}, ` +\n `${group.members.length} occurrences):`\n )\n );\n\n group.members.forEach((member) => {\n const relPath = relative(projectRoot, member.filePath);\n const location = `${relPath}:${member.startLine}-${member.endLine}`;\n const name = member.name || \"(anonymous)\";\n const score =\n member.score === 1.0\n ? \"\"\n : chalk.dim(` (${Math.round(member.score * 100)}%)`);\n console.log(` ${chalk.cyan(location.padEnd(50))} ${name}${score}`);\n });\n\n const suggestion =\n group.confidence === \"high\"\n ? `Strongly recommend consolidating into a single reusable ${group.kind}`\n : group.confidence === \"medium\"\n ? `Consider extracting shared logic into a reusable ${group.kind}`\n : `Optional: Review if a common abstraction makes sense`;\n\n console.log(chalk.dim(` → ${suggestion}\\n`));\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Search command - semantic search for code\n */\n\nimport { Command } from \"commander\";\nimport { relative } from \"path\";\nimport chalk from \"chalk\";\n\nexport function searchCommand(): Command {\n return new Command(\"search\")\n .description(\"Semantic search for similar code\")\n .argument(\"<query>\", \"Search query (natural language)\")\n .option(\"-k, --top <n>\", \"Number of results (default: 10)\", parseInt)\n .option(\"--threshold <n>\", \"Minimum similarity (default: 0.5)\", parseFloat)\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (query: string, options) => {\n const { searchSimilar } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n try {\n const results = await searchSimilar(query, {\n path: projectRoot,\n top: options.top,\n threshold: options.threshold,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ results }, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow(\"No matching code found.\"));\n return;\n }\n\n console.log(chalk.bold(`Found ${results.length} matching results:\\n`));\n\n results.forEach((result, idx) => {\n const relPath = relative(projectRoot, result.filePath);\n const location = `${relPath}:${result.startLine}-${result.endLine}`;\n const name = result.name || \"(anonymous)\";\n const score = Math.round(result.score * 100);\n const kindLabel = result.kind.padEnd(10);\n\n console.log(\n `${chalk.dim(`${idx + 1}.`)} ${chalk.cyan(location)}`\n );\n console.log(\n ` ${chalk.dim(kindLabel)} ${chalk.bold(name)} ${chalk.green(`(${score}% similar)`)}`\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Similar command - find code similar to a specific location\n */\n\nimport { Command } from \"commander\";\nimport { relative, resolve, isAbsolute } from \"path\";\nimport chalk from \"chalk\";\n\nexport function similarCommand(): Command {\n return new Command(\"similar\")\n .description(\"Find code similar to a specific location\")\n .argument(\"<location>\", \"File location in format file:line (e.g., src/Button.tsx:15)\")\n .option(\"-k, --top <n>\", \"Number of results (default: 10)\", parseInt)\n .option(\"--threshold <n>\", \"Minimum similarity (default: 0.7)\", parseFloat)\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (location: string, options) => {\n const { findSimilarAtLocation } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n // Parse location\n const colonIdx = location.lastIndexOf(\":\");\n if (colonIdx === -1) {\n const message = \"Invalid location format. Use file:line (e.g., src/Button.tsx:15)\";\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n\n const filePart = location.slice(0, colonIdx);\n const linePart = location.slice(colonIdx + 1);\n const line = parseInt(linePart, 10);\n\n if (isNaN(line)) {\n const message = `Invalid line number: ${linePart}`;\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n\n const filePath = isAbsolute(filePart)\n ? filePart\n : resolve(projectRoot, filePart);\n\n try {\n const results = await findSimilarAtLocation({\n path: projectRoot,\n filePath,\n line,\n top: options.top,\n threshold: options.threshold ?? 0.7,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ results }, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow(\"No similar code found.\"));\n return;\n }\n\n console.log(\n chalk.bold(\n `Found ${results.length} similar code locations to ${relative(projectRoot, filePath)}:${line}:\\n`\n )\n );\n\n results.forEach((result, idx) => {\n const relPath = relative(projectRoot, result.filePath);\n const locationStr = `${relPath}:${result.startLine}-${result.endLine}`;\n const name = result.name || \"(anonymous)\";\n const score = Math.round(result.score * 100);\n const kindLabel = result.kind.padEnd(10);\n\n console.log(\n `${chalk.dim(`${idx + 1}.`)} ${chalk.cyan(locationStr)}`\n );\n console.log(\n ` ${chalk.dim(kindLabel)} ${chalk.bold(name)} ${chalk.green(`(${score}% similar)`)}`\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Build Manifest Command\n *\n * Generates a static lint manifest for production deployment.\n *\n * Usage:\n * uilint build-manifest [options]\n *\n * Options:\n * -o, --output <path> Output path (default: .uilint/manifest.json)\n * --include <patterns...> File patterns to include (default: **\\/*.tsx **\\/*.jsx)\n * --exclude <patterns...> File patterns to exclude\n * --no-snippets Exclude source code snippets\n * --context-lines <n> Number of context lines for snippets (default: 3)\n * --pretty Pretty-print JSON output\n */\n\nimport { Command } from \"commander\";\nimport { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport { dirname, resolve } from \"path\";\nimport { generateManifest } from \"./generator.js\";\nimport { logInfo, logSuccess, logError, pc } from \"../../utils/prompts.js\";\nimport { discoverPlugins, loadPluginESLintRules } from \"../../utils/plugin-loader.js\";\n\n/**\n * Create the build-manifest command\n */\nexport function createManifestCommand(): Command {\n const cmd = new Command(\"build-manifest\")\n .description(\"Generate static lint manifest for production deployment\")\n .option(\"-o, --output <path>\", \"Output path for manifest\", \".uilint/manifest.json\")\n .option(\"--include <patterns...>\", \"File patterns to include\")\n .option(\"--exclude <patterns...>\", \"File patterns to exclude\")\n .option(\"--no-snippets\", \"Exclude source code snippets from manifest\")\n .option(\"--context-lines <n>\", \"Number of context lines for snippets\", \"3\")\n .option(\"--pretty\", \"Pretty-print JSON output\")\n .option(\"--quiet\", \"Suppress progress output\")\n .action(async (options) => {\n await buildManifest({\n output: options.output,\n include: options.include,\n exclude: options.exclude,\n includeSnippets: options.snippets !== false,\n contextLines: parseInt(options.contextLines, 10),\n pretty: options.pretty,\n quiet: options.quiet,\n });\n });\n\n return cmd;\n}\n\ninterface BuildManifestOptions {\n output: string;\n include?: string[];\n exclude?: string[];\n includeSnippets: boolean;\n contextLines: number;\n pretty?: boolean;\n quiet?: boolean;\n}\n\n/**\n * Build manifest action\n */\nasync function buildManifest(options: BuildManifestOptions): Promise<void> {\n // Load plugin ESLint rules so plugin rules appear in the registry\n const pluginManifests = await discoverPlugins();\n await loadPluginESLintRules(pluginManifests);\n\n const startTime = Date.now();\n const outputPath = resolve(process.cwd(), options.output);\n\n if (!options.quiet) {\n logInfo(`Building lint manifest...`);\n logInfo(`Output: ${pc.dim(outputPath)}`);\n }\n\n try {\n const manifest = await generateManifest({\n cwd: process.cwd(),\n include: options.include,\n exclude: options.exclude,\n includeSnippets: options.includeSnippets,\n snippetContextLines: options.contextLines,\n onProgress: options.quiet\n ? undefined\n : (message, current, total) => {\n if (current !== undefined && total !== undefined) {\n logInfo(` [${current}/${total}] ${message}`);\n } else {\n logInfo(` ${message}`);\n }\n },\n });\n\n // Ensure output directory exists\n const outputDir = dirname(outputPath);\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Write manifest\n const json = options.pretty\n ? JSON.stringify(manifest, null, 2)\n : JSON.stringify(manifest);\n\n writeFileSync(outputPath, json, \"utf-8\");\n\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);\n const sizeKb = Math.round(Buffer.byteLength(json) / 1024);\n\n if (!options.quiet) {\n logSuccess(`Manifest generated in ${elapsed}s`);\n logInfo(` Files scanned: ${pc.bold(String(manifest.summary.filesScanned))}`);\n logInfo(` Files with issues: ${pc.bold(String(manifest.summary.filesWithIssues))}`);\n logInfo(` Total issues: ${pc.bold(String(manifest.summary.totalIssues))}`);\n if (manifest.summary.bySeverity.error > 0) {\n logInfo(` Errors: ${pc.red(String(manifest.summary.bySeverity.error))}`);\n }\n if (manifest.summary.bySeverity.warn > 0) {\n logInfo(` Warnings: ${pc.yellow(String(manifest.summary.bySeverity.warn))}`);\n }\n logInfo(` Output size: ${pc.dim(`${sizeKb}kb`)}`);\n\n if (manifest.commitSha) {\n logInfo(` Git commit: ${pc.dim(manifest.commitSha.substring(0, 7))}`);\n }\n if (manifest.branch) {\n logInfo(` Git branch: ${pc.dim(manifest.branch)}`);\n }\n\n logSuccess(`Wrote ${pc.cyan(options.output)}`);\n }\n\n // Exit with error code if there are errors\n if (manifest.summary.bySeverity.error > 0) {\n process.exitCode = 1;\n }\n } catch (error) {\n logError(`Failed to generate manifest: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n}\n\n// Re-export types and generator\nexport * from \"./types.js\";\nexport { generateManifest } from \"./generator.js\";\n","/**\n * Manifest Generator\n *\n * Scans all JSX/TSX files in a project and generates a static\n * lint manifest for remote/production deployments.\n */\n\nimport { readFileSync } from \"fs\";\nimport { resolve, dirname, relative } from \"path\";\nimport { glob } from \"glob\";\nimport { execSync } from \"child_process\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\nimport { ruleRegistry } from \"uilint-eslint\";\nimport { findEslintConfigFile, readRuleConfigsFromConfig } from \"../../utils/eslint-config-inject.js\";\nimport {\n findESLintCwd,\n lintFileWithDataLoc,\n extractSourceSnippet,\n normalizeDataLocFilePath,\n type LintIssue,\n} from \"../../utils/eslint-utils.js\";\nimport { findEnclosingScopeBatch } from \"../../scope-extractor.js\";\nimport type {\n LintManifest,\n ManifestFileEntry,\n ManifestIssue,\n ManifestRuleMeta,\n SourceSnippet,\n GenerateManifestOptions,\n} from \"./types.js\";\n\n/**\n * Default glob patterns for JSX/TSX files\n */\nconst DEFAULT_INCLUDE = [\"**/*.tsx\", \"**/*.jsx\"];\n\n/**\n * Default glob patterns to exclude\n */\nconst DEFAULT_EXCLUDE = [\n \"node_modules/**\",\n \"dist/**\",\n \".next/**\",\n \"build/**\",\n \"coverage/**\",\n \".uilint/**\",\n \"**/*.test.tsx\",\n \"**/*.test.jsx\",\n \"**/*.spec.tsx\",\n \"**/*.spec.jsx\",\n];\n\n/**\n * Get git information if available\n */\nfunction getGitInfo(cwd: string): { commitSha?: string; branch?: string } {\n try {\n const commitSha = execSync(\"git rev-parse HEAD\", {\n cwd,\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n\n const branch = execSync(\"git rev-parse --abbrev-ref HEAD\", {\n cwd,\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n\n return { commitSha, branch };\n } catch {\n return {};\n }\n}\n\n/**\n * Build rule metadata for the manifest\n */\nfunction buildRuleMetadata(appRoot: string): ManifestRuleMeta[] {\n // Read current rule configs from ESLint config file\n const eslintConfigPath = findEslintConfigFile(appRoot);\n const currentRuleConfigs = eslintConfigPath\n ? readRuleConfigsFromConfig(eslintConfigPath)\n : new Map<string, { severity: \"error\" | \"warn\" | \"off\"; options?: Record<string, unknown> }>();\n\n // Only include rules that are configured in the ESLint config\n // readRuleConfigsFromConfig strips the \"uilint/\" prefix, so match on bare rule.id\n return ruleRegistry\n .filter((rule) => currentRuleConfigs.has(rule.id))\n .map((rule) => {\n const currentConfig = currentRuleConfigs.get(rule.id);\n return {\n id: `uilint/${rule.id}`,\n name: rule.name,\n description: rule.description,\n category: rule.category,\n defaultSeverity: rule.defaultSeverity,\n currentSeverity: currentConfig?.severity,\n docs: rule.docs,\n optionSchema: rule.optionSchema,\n };\n });\n}\n\n/**\n * Generate a lint manifest for a project\n */\nexport async function generateManifest(\n options: GenerateManifestOptions = {}\n): Promise<LintManifest> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const include = options.include ?? DEFAULT_INCLUDE;\n const exclude = options.exclude ?? DEFAULT_EXCLUDE;\n // Default to including full source content (for production mode source display)\n const includeSource = options.includeSource ?? true;\n // Snippets are deprecated but still supported for backwards compatibility\n const includeSnippets = options.includeSnippets ?? false;\n const snippetContextLines = options.snippetContextLines ?? 3;\n const onProgress = options.onProgress ?? (() => {});\n\n onProgress(\"Finding workspace root...\");\n const workspaceRoot = findWorkspaceRoot(cwd);\n const appRoot = cwd;\n\n onProgress(\"Scanning for JSX/TSX files...\");\n\n // Find all matching files\n const files = await glob(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n nodir: true,\n });\n\n onProgress(`Found ${files.length} files to scan`);\n\n // Get git info\n const gitInfo = getGitInfo(cwd);\n\n // Build rule metadata\n const rules = buildRuleMetadata(appRoot);\n onProgress(`Loaded ${rules.length} rule definitions`);\n\n // Process each file\n const manifestFiles: ManifestFileEntry[] = [];\n let totalIssues = 0;\n let errorCount = 0;\n let warnCount = 0;\n\n for (let i = 0; i < files.length; i++) {\n const absolutePath = files[i]!;\n const relativePath = relative(cwd, absolutePath);\n\n onProgress(`Linting ${relativePath}...`, i + 1, files.length);\n\n // Find ESLint project root for this file\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n // Lint the file\n const issues = await lintFileWithDataLoc(absolutePath, projectCwd);\n\n if (issues.length === 0) continue;\n\n // Filter issues that have dataLoc\n const filteredIssues = issues.filter(\n (issue): issue is LintIssue & { dataLoc: string } => Boolean(issue.dataLoc)\n );\n\n if (filteredIssues.length === 0) continue;\n\n // Read file content for source inclusion and scope extraction\n let fileContent: string | undefined;\n let snippets: Record<string, SourceSnippet> | undefined;\n\n try {\n fileContent = readFileSync(absolutePath, \"utf-8\");\n } catch {\n // Skip source/snippets if file can't be read\n fileContent = undefined;\n }\n\n // Extract scope information for all issues in this file (optimized: parse AST once)\n let scopeInfos: Array<ReturnType<typeof findEnclosingScopeBatch>[number]> = [];\n if (fileContent) {\n try {\n const positions = filteredIssues.map((issue) => ({\n line: issue.line,\n column: issue.column ?? 0,\n }));\n scopeInfos = findEnclosingScopeBatch(fileContent, positions);\n } catch {\n // Scope extraction failed - continue without scope info\n scopeInfos = filteredIssues.map(() => null);\n }\n }\n\n // Convert to manifest format with scope info\n const manifestIssues: ManifestIssue[] = filteredIssues.map((issue, index) => ({\n line: issue.line,\n column: issue.column,\n message: issue.message,\n ruleId: issue.ruleId,\n dataLoc: issue.dataLoc,\n scopeInfo: scopeInfos[index] ?? undefined,\n }));\n\n // Include snippets if requested (deprecated, for backwards compatibility)\n if (includeSnippets && fileContent) {\n snippets = {};\n\n // Group issues by dataLoc to avoid duplicate snippets\n const issuesByDataLoc = new Map<string, ManifestIssue>();\n for (const issue of manifestIssues) {\n if (!issuesByDataLoc.has(issue.dataLoc)) {\n issuesByDataLoc.set(issue.dataLoc, issue);\n }\n }\n\n for (const [dataLoc, issue] of issuesByDataLoc) {\n snippets[dataLoc] = extractSourceSnippet(fileContent, issue.line, snippetContextLines);\n }\n }\n\n // Count by severity\n for (const issue of manifestIssues) {\n if (issue.ruleId) {\n // Check rule config for severity (rules now have full IDs)\n const rule = rules.find((r) => r.id === issue.ruleId);\n const severity = rule?.currentSeverity ?? rule?.defaultSeverity ?? \"warn\";\n if (severity === \"error\") {\n errorCount++;\n } else {\n warnCount++;\n }\n } else {\n warnCount++;\n }\n }\n\n totalIssues += manifestIssues.length;\n\n // Use the normalized relative path for the manifest\n const dataLocFilePath = normalizeDataLocFilePath(absolutePath, projectCwd);\n\n manifestFiles.push({\n filePath: dataLocFilePath,\n issues: manifestIssues,\n // Include full source content for production mode source display\n content: includeSource ? fileContent : undefined,\n // Include snippets if explicitly requested (deprecated)\n snippets: includeSnippets ? snippets : undefined,\n });\n }\n\n onProgress(`Scan complete: ${totalIssues} issues in ${manifestFiles.length} files`);\n\n return {\n version: \"1.0\",\n generatedAt: new Date().toISOString(),\n workspaceRoot,\n appRoot,\n commitSha: gitInfo.commitSha,\n branch: gitInfo.branch,\n files: manifestFiles,\n rules,\n summary: {\n filesScanned: files.length,\n filesWithIssues: manifestFiles.length,\n totalIssues,\n bySeverity: {\n error: errorCount,\n warn: warnCount,\n },\n },\n };\n}\n","/**\n * Socket CLI Command\n *\n * Provides a CLI interface for interacting with the UILint socket server.\n * Useful for testing, debugging, and scripting.\n *\n * Usage:\n * uilint socket # Start interactive REPL\n * uilint socket lint:file <path> # Lint a file\n * uilint socket vision:check # Check vision availability\n * uilint socket listen # Listen for all messages\n */\n\nimport { Command } from \"commander\";\nimport { readFileSync, existsSync } from \"fs\";\nimport chalk from \"chalk\";\nimport { createSocketClient, SocketClient } from \"./client.js\";\nimport type { ServerMessage, ElementManifest } from \"./types.js\";\n\nexport interface SocketOptions {\n port: number;\n debug: boolean;\n json: boolean;\n timeout: number;\n}\n\n/**\n * Format a message for display\n */\nfunction formatMessage(msg: ServerMessage, json: boolean): string {\n if (json) {\n return JSON.stringify(msg, null, 2);\n }\n\n switch (msg.type) {\n case \"lint:result\": {\n const lines = [`${chalk.cyan(\"lint:result\")} ${msg.filePath}`];\n if (msg.issues.length === 0) {\n lines.push(chalk.green(\" No issues found\"));\n } else {\n for (const issue of msg.issues) {\n const loc = issue.column\n ? `${issue.line}:${issue.column}`\n : `${issue.line}`;\n const rule = issue.ruleId ? chalk.dim(` [${issue.ruleId}]`) : \"\";\n lines.push(` ${chalk.yellow(loc)} ${issue.message}${rule}`);\n }\n }\n return lines.join(\"\\n\");\n }\n\n case \"vision:status\": {\n if (msg.available) {\n return `${chalk.cyan(\"vision:status\")} ${chalk.green(\"available\")} (${msg.model})`;\n }\n return `${chalk.cyan(\"vision:status\")} ${chalk.red(\"not available\")}`;\n }\n\n case \"vision:result\": {\n const lines = [\n `${chalk.cyan(\"vision:result\")} ${msg.route} (${msg.analysisTime}ms)`,\n ];\n if (msg.error) {\n lines.push(chalk.red(` Error: ${msg.error}`));\n } else if (msg.issues.length === 0) {\n lines.push(chalk.green(\" No issues found\"));\n } else {\n for (const issue of msg.issues) {\n const severity =\n issue.severity === \"error\"\n ? chalk.red(\"error\")\n : issue.severity === \"warning\"\n ? chalk.yellow(\"warn\")\n : chalk.blue(\"info\");\n lines.push(` ${severity} [${issue.category}] ${issue.message}`);\n if (issue.dataLoc) {\n lines.push(chalk.dim(` at ${issue.dataLoc}`));\n }\n }\n }\n return lines.join(\"\\n\");\n }\n\n case \"workspace:info\":\n return `${chalk.cyan(\"workspace:info\")}\\n appRoot: ${msg.appRoot}\\n workspaceRoot: ${msg.workspaceRoot}`;\n\n case \"rules:metadata\":\n return `${chalk.cyan(\"rules:metadata\")} ${msg.rules.length} rules available`;\n\n case \"source:result\":\n return `${chalk.cyan(\"source:result\")} ${msg.filePath} (${msg.totalLines} lines)`;\n\n case \"source:error\":\n return `${chalk.cyan(\"source:error\")} ${msg.filePath}: ${chalk.red(msg.error)}`;\n\n case \"coverage:result\":\n return `${chalk.cyan(\"coverage:result\")} Coverage data received`;\n\n case \"coverage:error\":\n return `${chalk.cyan(\"coverage:error\")} ${chalk.red(msg.error)}`;\n\n case \"rule:config:result\":\n if (msg.success) {\n return `${chalk.cyan(\"rule:config:result\")} ${msg.ruleId} -> ${msg.severity}`;\n }\n return `${chalk.cyan(\"rule:config:result\")} ${msg.ruleId} ${chalk.red(\"failed\")}: ${msg.error}`;\n\n case \"duplicates:indexing:start\":\n return `${chalk.cyan(\"duplicates:indexing:start\")}`;\n\n case \"duplicates:indexing:progress\":\n return `${chalk.cyan(\"duplicates:indexing:progress\")} ${msg.message}`;\n\n case \"duplicates:indexing:complete\":\n return `${chalk.cyan(\"duplicates:indexing:complete\")} ${msg.totalChunks} chunks in ${msg.duration}ms`;\n\n case \"duplicates:indexing:error\":\n return `${chalk.cyan(\"duplicates:indexing:error\")} ${chalk.red(msg.error)}`;\n\n case \"file:changed\":\n return `${chalk.cyan(\"file:changed\")} ${msg.filePath}`;\n\n case \"config:update\":\n return `${chalk.cyan(\"config:update\")} ${msg.key} = ${JSON.stringify(msg.value)}`;\n\n default:\n return `${chalk.cyan(msg.type)} ${JSON.stringify(msg)}`;\n }\n}\n\n/**\n * Run interactive REPL mode\n */\nasync function runRepl(client: SocketClient, options: SocketOptions): Promise<void> {\n const readline = await import(\"readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n prompt: chalk.green(\"uilint> \"),\n });\n\n console.log(chalk.bold(\"\\nUILint Socket REPL\"));\n console.log(\"Type 'help' for available commands, 'exit' to quit.\\n\");\n\n // Set up message handler\n client.onMessage((msg) => {\n console.log(\"\\n\" + formatMessage(msg, options.json));\n rl.prompt();\n });\n\n // Wait for initial messages\n try {\n await client.waitForWorkspaceInfo(2000);\n } catch {\n // Ignore timeout\n }\n\n rl.prompt();\n\n rl.on(\"line\", async (line) => {\n const trimmed = line.trim();\n if (!trimmed) {\n rl.prompt();\n return;\n }\n\n const [cmd, ...args] = trimmed.split(/\\s+/);\n\n try {\n switch (cmd) {\n case \"help\":\n console.log(`\nAvailable commands:\n lint:file <path> Lint a file\n lint:element <path> <dataLoc> Lint a specific element\n vision:check Check if vision is available\n vision:analyze <route> <manifestFile> [screenshotFile]\n Run vision analysis\n source:fetch <path> Fetch source code\n coverage:request Request coverage data\n rule:config <ruleId> <severity> [optionsJson]\n Set rule configuration\n config:set <key> <value> Set a config value\n subscribe <path> Subscribe to file changes\n invalidate [path] Invalidate cache\n messages Show queued messages\n clear Clear message queue\n json Toggle JSON output\n exit Exit REPL\n`);\n break;\n\n case \"lint:file\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: lint:file <path>\"));\n } else {\n const result = await client.lintFile(args[0], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"lint:element\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: lint:element <path> <dataLoc>\"));\n } else {\n const result = await client.lintElement(args[0], args[1], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"vision:check\": {\n const result = await client.visionCheck(options.timeout);\n console.log(formatMessage(result, options.json));\n break;\n }\n\n case \"vision:analyze\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: vision:analyze <route> <manifestFile> [screenshotFile]\"));\n } else {\n const manifestPath = args[1];\n if (!existsSync(manifestPath)) {\n console.log(chalk.red(`Manifest file not found: ${manifestPath}`));\n } else {\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf-8\")) as ElementManifest[];\n const params: {\n route: string;\n manifest: ElementManifest[];\n screenshotFile?: string;\n screenshot?: string;\n } = { route: args[0], manifest };\n\n if (args[2]) {\n if (existsSync(args[2])) {\n // Read as base64\n const imageBuffer = readFileSync(args[2]);\n params.screenshot = imageBuffer.toString(\"base64\");\n } else {\n console.log(chalk.red(`Screenshot file not found: ${args[2]}`));\n break;\n }\n }\n\n const result = await client.visionAnalyze(params, options.timeout);\n console.log(formatMessage(result, options.json));\n }\n }\n break;\n\n case \"source:fetch\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: source:fetch <path>\"));\n } else {\n const result = await client.fetchSource(args[0], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"coverage:request\": {\n const result = await client.requestCoverage(options.timeout);\n console.log(formatMessage(result, options.json));\n break;\n }\n\n case \"rule:config\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: rule:config <ruleId> <severity> [optionsJson]\"));\n } else {\n const severity = args[1] as \"error\" | \"warn\" | \"off\";\n const ruleOptions = args[2] ? JSON.parse(args[2]) : undefined;\n const result = await client.setRuleConfig(args[0], severity, ruleOptions, options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"config:set\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: config:set <key> <value>\"));\n } else {\n let value: unknown = args[1];\n try {\n value = JSON.parse(args[1]);\n } catch {\n // Keep as string\n }\n client.setConfig(args[0], value);\n console.log(chalk.green(`Set ${args[0]} = ${JSON.stringify(value)}`));\n }\n break;\n\n case \"subscribe\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: subscribe <path>\"));\n } else {\n client.subscribeFile(args[0]);\n console.log(chalk.green(`Subscribed to ${args[0]}`));\n }\n break;\n\n case \"invalidate\":\n client.invalidateCache(args[0]);\n console.log(chalk.green(args[0] ? `Invalidated ${args[0]}` : \"Invalidated all cache\"));\n break;\n\n case \"messages\": {\n const msgs = client.getMessages();\n if (msgs.length === 0) {\n console.log(chalk.dim(\"No queued messages\"));\n } else {\n for (const msg of msgs) {\n console.log(formatMessage(msg, options.json));\n }\n }\n break;\n }\n\n case \"clear\":\n client.clearMessages();\n console.log(chalk.green(\"Message queue cleared\"));\n break;\n\n case \"json\":\n options.json = !options.json;\n console.log(chalk.green(`JSON output ${options.json ? \"enabled\" : \"disabled\"}`));\n break;\n\n case \"exit\":\n case \"quit\":\n client.disconnect();\n rl.close();\n process.exit(0);\n break;\n\n default:\n console.log(chalk.red(`Unknown command: ${cmd}. Type 'help' for available commands.`));\n }\n } catch (err) {\n console.log(chalk.red(`Error: ${(err as Error).message}`));\n }\n\n rl.prompt();\n });\n\n rl.on(\"close\", () => {\n client.disconnect();\n process.exit(0);\n });\n}\n\n/**\n * Run listen mode (print all messages)\n */\nasync function runListen(\n client: SocketClient,\n options: SocketOptions,\n filter?: string\n): Promise<void> {\n console.log(chalk.bold(\"\\nListening for messages...\"));\n if (filter) {\n console.log(chalk.dim(`Filter: ${filter}`));\n }\n console.log(chalk.dim(\"Press Ctrl+C to stop.\\n\"));\n\n client.onMessage((msg) => {\n if (filter && !msg.type.includes(filter.replace(\"*\", \"\"))) {\n return;\n }\n console.log(formatMessage(msg, options.json));\n });\n\n // Keep running\n await new Promise(() => {});\n}\n\n/**\n * Create the socket command\n */\nexport function createSocketCommand(): Command {\n const cmd = new Command(\"socket\")\n .description(\"Interact with the UILint socket server\")\n .option(\"-p, --port <number>\", \"Socket server port\", \"9234\")\n .option(\"-d, --debug\", \"Enable debug logging\", false)\n .option(\"-j, --json\", \"Output JSON format\", false)\n .option(\"-t, --timeout <ms>\", \"Request timeout in milliseconds\", \"30000\");\n\n // Default action: start REPL\n cmd.action(async (cmdOptions) => {\n const options: SocketOptions = {\n port: parseInt(cmdOptions.port, 10),\n debug: cmdOptions.debug,\n json: cmdOptions.json,\n timeout: parseInt(cmdOptions.timeout, 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await runRepl(client, options);\n } catch (err) {\n console.error(chalk.red(`Failed to connect: ${(err as Error).message}`));\n console.error(chalk.dim(`Make sure the server is running: uilint serve -p ${options.port}`));\n process.exit(1);\n }\n });\n\n // listen subcommand\n cmd\n .command(\"listen\")\n .description(\"Listen for all messages from the server\")\n .option(\"-f, --filter <pattern>\", \"Filter messages by type pattern (e.g., lint:*, vision:*)\")\n .action(async (subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"30000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await runListen(client, options, subOptions.filter);\n } catch (err) {\n console.error(chalk.red(`Failed to connect: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // lint:file subcommand\n cmd\n .command(\"lint:file <path>\")\n .description(\"Lint a file and output results\")\n .action(async (filePath, _subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"30000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await client.waitForWorkspaceInfo(2000).catch(() => {});\n const result = await client.lintFile(filePath, options.timeout);\n console.log(formatMessage(result, options.json));\n client.disconnect();\n process.exit(result.issues.length > 0 ? 1 : 0);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // vision:check subcommand\n cmd\n .command(\"vision:check\")\n .description(\"Check if vision analysis is available\")\n .action(async (_subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n const result = await client.visionCheck(options.timeout);\n console.log(formatMessage(result, options.json));\n client.disconnect();\n process.exit(result.available ? 0 : 1);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // source:fetch subcommand\n cmd\n .command(\"source:fetch <path>\")\n .description(\"Fetch source code for a file\")\n .action(async (filePath, _subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await client.waitForWorkspaceInfo(2000).catch(() => {});\n const result = await client.fetchSource(filePath, options.timeout);\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else if (result.type === \"source:result\") {\n console.log(result.content);\n } else {\n console.error(chalk.red(`Error: ${result.error}`));\n }\n client.disconnect();\n process.exit(result.type === \"source:result\" ? 0 : 1);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // rules subcommand\n cmd\n .command(\"rules\")\n .description(\"List available rules\")\n .action(async (_subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n const metadata = await client.waitForRulesMetadata(options.timeout);\n\n if (options.json) {\n console.log(JSON.stringify(metadata.rules, null, 2));\n } else {\n console.log(chalk.bold(`\\n${metadata.rules.length} rules available:\\n`));\n for (const rule of metadata.rules) {\n const severity =\n rule.currentSeverity === \"error\"\n ? chalk.red(\"error\")\n : rule.currentSeverity === \"warn\"\n ? chalk.yellow(\"warn\")\n : chalk.dim(\"off\");\n console.log(` ${chalk.cyan(rule.id)} [${severity}]`);\n console.log(chalk.dim(` ${rule.description}`));\n }\n }\n\n client.disconnect();\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n return cmd;\n}\n\n// Re-export types and client for programmatic use\nexport { SocketClient, createSocketClient } from \"./client.js\";\nexport { SocketTestHarness, createTestHarness } from \"./test-harness.js\";\nexport type * from \"./types.js\";\n","/**\n * Socket Client\n *\n * WebSocket client for communicating with the UILint socket server.\n * Provides request/response correlation and message handling.\n */\n\nimport WebSocket from \"ws\";\nimport type {\n ClientMessage,\n ServerMessage,\n LintResultMessage,\n SourceResultMessage,\n SourceErrorMessage,\n CoverageResultMessage,\n CoverageErrorMessage,\n RuleConfigResultMessage,\n WorkspaceInfoMessage,\n RulesMetadataMessage,\n ElementManifest,\n VisionStatusMessage,\n VisionResultMessage,\n} from \"./types.js\";\n\nexport interface SocketClientOptions {\n /** WebSocket URL (default: ws://localhost:9234) */\n url?: string;\n /** Port number (convenience, overrides url) */\n port?: number;\n /** Enable debug logging */\n debug?: boolean;\n /** Connection timeout in ms (default: 10000) */\n connectTimeout?: number;\n}\n\ntype MessageHandler = (message: ServerMessage) => void;\n\ninterface PendingRequest {\n predicate: (msg: ServerMessage) => boolean;\n resolve: (msg: ServerMessage) => void;\n reject: (err: Error) => void;\n timeout: NodeJS.Timeout;\n}\n\nexport class SocketClient {\n private ws: WebSocket | null = null;\n private url: string;\n private debug: boolean;\n private connectTimeout: number;\n private connected = false;\n private connectionPromise: Promise<void> | null = null;\n private pendingRequests: PendingRequest[] = [];\n private messageQueue: ServerMessage[] = [];\n private messageHandlers: MessageHandler[] = [];\n\n constructor(options: SocketClientOptions = {}) {\n const port = options.port || 9234;\n this.url = options.url || `ws://localhost:${port}`;\n this.debug = options.debug || false;\n this.connectTimeout = options.connectTimeout || 10000;\n }\n\n /**\n * Connect to the socket server\n */\n async connect(): Promise<void> {\n if (this.connected) return;\n if (this.connectionPromise) return this.connectionPromise;\n\n this.connectionPromise = new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Connection timeout to ${this.url}`));\n }, this.connectTimeout);\n\n this.ws = new WebSocket(this.url);\n\n this.ws.on(\"open\", () => {\n clearTimeout(timeout);\n this.connected = true;\n this.log(\"Connected to\", this.url);\n resolve();\n });\n\n this.ws.on(\"message\", (data: WebSocket.Data) => {\n try {\n const message = JSON.parse(data.toString()) as ServerMessage;\n this.log(\"Received:\", message.type);\n this.handleMessage(message);\n } catch (e) {\n console.error(\"Failed to parse message:\", e);\n }\n });\n\n this.ws.on(\"error\", (err) => {\n clearTimeout(timeout);\n if (!this.connected) {\n reject(err);\n } else {\n console.error(\"WebSocket error:\", err);\n }\n });\n\n this.ws.on(\"close\", () => {\n this.connected = false;\n this.log(\"Disconnected\");\n // Reject all pending requests\n for (const req of this.pendingRequests) {\n clearTimeout(req.timeout);\n req.reject(new Error(\"Disconnected\"));\n }\n this.pendingRequests = [];\n });\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Disconnect from the server\n */\n disconnect(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n this.connected = false;\n this.connectionPromise = null;\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Add a handler for all incoming messages\n */\n onMessage(handler: MessageHandler): () => void {\n this.messageHandlers.push(handler);\n return () => {\n this.messageHandlers = this.messageHandlers.filter((h) => h !== handler);\n };\n }\n\n /**\n * Send a raw message\n */\n send(message: ClientMessage): void {\n if (!this.ws || !this.connected) {\n throw new Error(\"Not connected\");\n }\n this.log(\"Sending:\", message.type);\n this.ws.send(JSON.stringify(message));\n }\n\n /**\n * Wait for a message matching the predicate\n */\n waitFor(\n predicate: (msg: ServerMessage) => boolean,\n timeout = 30000\n ): Promise<ServerMessage> {\n // Check existing messages first\n const existing = this.messageQueue.find(predicate);\n if (existing) {\n this.messageQueue = this.messageQueue.filter((m) => m !== existing);\n return Promise.resolve(existing);\n }\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingRequests = this.pendingRequests.filter(\n (r) => r.timeout !== timeoutId\n );\n reject(new Error(`Timeout waiting for message (${timeout}ms)`));\n }, timeout);\n\n this.pendingRequests.push({\n predicate,\n resolve,\n reject,\n timeout: timeoutId,\n });\n });\n }\n\n /**\n * Generate a unique request ID\n */\n private generateRequestId(): string {\n return `cli-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n // ==========================================================================\n // High-Level API Methods\n // ==========================================================================\n\n /**\n * Wait for workspace info (sent on connect)\n */\n async waitForWorkspaceInfo(timeout = 5000): Promise<WorkspaceInfoMessage> {\n const existing = this.messageQueue.find((m) => m.type === \"workspace:info\");\n if (existing) {\n return existing as WorkspaceInfoMessage;\n }\n return (await this.waitFor(\n (msg) => msg.type === \"workspace:info\",\n timeout\n )) as WorkspaceInfoMessage;\n }\n\n /**\n * Wait for rules metadata (sent on connect)\n */\n async waitForRulesMetadata(timeout = 5000): Promise<RulesMetadataMessage> {\n const existing = this.messageQueue.find((m) => m.type === \"rules:metadata\");\n if (existing) {\n return existing as RulesMetadataMessage;\n }\n return (await this.waitFor(\n (msg) => msg.type === \"rules:metadata\",\n timeout\n )) as RulesMetadataMessage;\n }\n\n /**\n * Lint a file\n */\n async lintFile(filePath: string, timeout = 30000): Promise<LintResultMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"lint:file\", filePath, requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"lint:result\" &&\n (msg as LintResultMessage).requestId === requestId,\n timeout\n )) as LintResultMessage;\n }\n\n /**\n * Lint a specific element\n */\n async lintElement(\n filePath: string,\n dataLoc: string,\n timeout = 30000\n ): Promise<LintResultMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"lint:element\", filePath, dataLoc, requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"lint:result\" &&\n (msg as LintResultMessage).requestId === requestId,\n timeout\n )) as LintResultMessage;\n }\n\n /**\n * Check if vision analysis is available\n * Note: Vision types live in the plugin package; messages still flow through the WebSocket.\n */\n async visionCheck(timeout = 10000): Promise<VisionStatusMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"vision:check\", requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"vision:status\" &&\n (msg as VisionStatusMessage).requestId === requestId,\n timeout\n )) as VisionStatusMessage;\n }\n\n /**\n * Run vision analysis\n * Note: Vision types live in the plugin package; messages still flow through the WebSocket.\n */\n async visionAnalyze(\n params: {\n route: string;\n manifest: ElementManifest[];\n screenshot?: string;\n screenshotFile?: string;\n },\n timeout = 120000\n ): Promise<VisionResultMessage> {\n const requestId = this.generateRequestId();\n this.send({\n type: \"vision:analyze\",\n route: params.route,\n timestamp: Date.now(),\n screenshot: params.screenshot,\n screenshotFile: params.screenshotFile,\n manifest: params.manifest,\n requestId,\n });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"vision:result\" &&\n (msg as VisionResultMessage).requestId === requestId,\n timeout\n )) as VisionResultMessage;\n }\n\n /**\n * Fetch source code\n */\n async fetchSource(\n filePath: string,\n timeout = 10000\n ): Promise<SourceResultMessage | SourceErrorMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"source:fetch\", filePath, requestId });\n return (await this.waitFor(\n (msg) =>\n (msg.type === \"source:result\" || msg.type === \"source:error\") &&\n ((msg as SourceResultMessage).requestId === requestId ||\n (msg as SourceErrorMessage).requestId === requestId),\n timeout\n )) as SourceResultMessage | SourceErrorMessage;\n }\n\n /**\n * Request coverage data\n */\n async requestCoverage(\n timeout = 30000\n ): Promise<CoverageResultMessage | CoverageErrorMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"coverage:request\", requestId });\n return (await this.waitFor(\n (msg) =>\n (msg.type === \"coverage:result\" || msg.type === \"coverage:error\") &&\n ((msg as CoverageResultMessage).requestId === requestId ||\n (msg as CoverageErrorMessage).requestId === requestId),\n timeout\n )) as CoverageResultMessage | CoverageErrorMessage;\n }\n\n /**\n * Set rule configuration\n */\n async setRuleConfig(\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>,\n timeout = 10000\n ): Promise<RuleConfigResultMessage> {\n const requestId = this.generateRequestId();\n this.send({\n type: \"rule:config:set\",\n ruleId,\n severity,\n options,\n requestId,\n });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"rule:config:result\" &&\n (msg as RuleConfigResultMessage).requestId === requestId,\n timeout\n )) as RuleConfigResultMessage;\n }\n\n /**\n * Set a configuration value\n */\n setConfig(key: string, value: unknown): void {\n this.send({ type: \"config:set\", key, value });\n }\n\n /**\n * Subscribe to file changes\n */\n subscribeFile(filePath: string): void {\n this.send({ type: \"subscribe:file\", filePath });\n }\n\n /**\n * Invalidate cache\n */\n invalidateCache(filePath?: string): void {\n this.send({ type: \"cache:invalidate\", filePath });\n }\n\n /**\n * Get all queued messages\n */\n getMessages(): ServerMessage[] {\n return [...this.messageQueue];\n }\n\n /**\n * Clear message queue\n */\n clearMessages(): void {\n this.messageQueue = [];\n }\n\n private handleMessage(message: ServerMessage): void {\n // Notify all handlers\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n\n // Check if any pending request matches\n for (let i = 0; i < this.pendingRequests.length; i++) {\n const req = this.pendingRequests[i]!;\n if (req.predicate(message)) {\n clearTimeout(req.timeout);\n this.pendingRequests.splice(i, 1);\n req.resolve(message);\n return;\n }\n }\n\n // Otherwise queue it\n this.messageQueue.push(message);\n }\n\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.log(\"[SocketClient]\", ...args);\n }\n }\n}\n\n/**\n * Create a connected socket client\n */\nexport async function createSocketClient(\n options: SocketClientOptions = {}\n): Promise<SocketClient> {\n const client = new SocketClient(options);\n await client.connect();\n return client;\n}\n"],"mappings":"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","names":["Command","resolve","existsSync","formatViolationsText","sanitizeIssues","findWorkspaceRoot","resolve","resolve","existsSync","sanitizeIssues","formatViolationsText","dirname","resolve","existsSync","mkdirSync","writeFileSync","ensureOllamaReady","readStyleGuide","findStyleGuidePath","findWorkspaceRoot","findUILintStyleGuideUpwards","envTruthy","preview","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","existsSync","readStyleGuide","findUILintStyleGuideUpwards","dirname","findStyleGuidePath","findWorkspaceRoot","ensureOllamaReady","mkdirSync","writeFileSync","ensureOllamaReady","readStdin","resolve","result","ensureOllamaReady","dirname","resolve","createStyleSummary","readStyleGuide","findStyleGuidePath","ensureOllamaReady","readTailwindThemeTokens","findStyleGuidePath","readStyleGuide","dirname","resolve","readTailwindThemeTokens","ensureOllamaReady","createStyleSummary","existsSync","statSync","readFileSync","mkdirSync","writeFileSync","createRequire","dirname","resolve","relative","join","findWorkspaceRoot","pc","pc","existsSync","createRequire","dirname","resolve","join","localRequire","parse","localRequire","createRequire","parse","resolve","existsSync","join","dirname","existsSync","resolve","join","existsSync","readFileSync","eslintInstances","createRequire","buildLineStarts","offsetFromLineCol","buildJsxElementSpans","parse","mapMessageToDataLoc","ESLINT_CONFIG_FILES","findESLintCwd","dirname","normalizePathSlashes","normalizeDataLocFilePath","relative","findWorkspaceRoot","createRequire","join","normalizeDataLocFilePath","readFileSync","buildLineStarts","buildJsxElementSpans","mapMessageToDataLoc","existsSync","statSync","dirname","findESLintCwd","existsSync","dirname","readFileSync","findWorkspaceRoot","relative","OllamaClient","buildSourceScanPrompt","findESLintCwd","normalizeDataLocFilePath","join","existsSync","findWorkspaceRoot","readFileSync","normalizeDataLocFilePath","join","mkdirSync","writeFileSync","eslintInstances","resolve","dirname","resolve","join","existsSync","readFileSync","readdirSync","ensureOllamaReady","STYLEGUIDE_PATHS","envTruthy","preview","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","join","existsSync","dirname","readdirSync","readFileSync","STYLEGUIDE_PATHS","ensureOllamaReady","WebSocket","resolve","WebSocket","config","Command","chalk","Command","relative","chalk","Command","relative","chalk","Command","relative","resolve","isAbsolute","chalk","Command","readFileSync","dirname","join","Command","existsSync","mkdirSync","writeFileSync","dirname","resolve","readFileSync","resolve","dirname","relative","findWorkspaceRoot","ruleRegistry","ruleRegistry","resolve","findWorkspaceRoot","relative","dirname","readFileSync","Command","resolve","dirname","existsSync","mkdirSync","writeFileSync","Command","readFileSync","existsSync","chalk","WebSocket","resolve","chalk","existsSync","readFileSync","Command","Command","dirname","join","readFileSync","config","discoverPlugins"]}