uilint 0.2.8 → 0.2.10

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/prompts.ts","../src/utils/output.ts","../src/commands/analyze.ts","../src/commands/consistency.ts","../src/commands/update.ts","../src/commands/install.ts","../src/commands/install/analyze.ts","../src/utils/next-detect.ts","../src/utils/vite-detect.ts","../src/utils/package-detect.ts","../src/utils/package-manager.ts","../src/utils/eslint-config-inject.ts","../src/commands/install/plan.ts","../src/commands/install/constants.ts","../src/utils/skill-loader.ts","../src/utils/rule-loader.ts","../src/commands/install/execute.ts","../src/utils/react-inject.ts","../src/utils/next-config-inject.ts","../src/utils/vite-config-inject.ts","../src/utils/next-routes.ts","../src/commands/install/prompter.ts","../src/commands/serve.ts","../src/utils/vision-run.ts","../src/commands/vision.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 { install } from \"./commands/install.js\";\nimport { serve } from \"./commands/serve.js\";\nimport { vision } from \"./commands/vision.js\";\nimport { readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nfunction assertNodeVersion(minMajor: number): void {\n const ver = process.versions.node || \"\";\n const majorStr = ver.split(\".\")[0] || \"\";\n const major = Number.parseInt(majorStr, 10);\n\n if (!Number.isFinite(major) || major < minMajor) {\n // Keep this dependency-free and stdout/stderr friendly.\n // eslint-disable-next-line no-console\n console.error(\n `uilint requires Node.js >= ${minMajor}. You are running Node.js ${ver}.`\n );\n process.exit(1);\n }\n}\n\nassertNodeVersion(20);\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// Install command\nprogram\n .command(\"install\")\n .description(\"Install UILint integration\")\n .option(\"--force\", \"Overwrite existing configuration files\")\n .option(\"--genstyleguide\", \"Install /genstyleguide Cursor command\")\n .option(\"--eslint\", \"Install uilint-eslint plugin and configure ESLint\")\n .option(\n \"--routes\",\n \"Back-compat: install Next.js overlay (routes + deps + inject)\"\n )\n .option(\n \"--react\",\n \"Back-compat: install Next.js overlay (routes + deps + inject)\"\n )\n .action(async (options) => {\n await install({\n force: options.force,\n genstyleguide: options.genstyleguide,\n eslint: options.eslint,\n routes: options.routes,\n react: options.react,\n });\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 .action(async (options) => {\n await serve({\n port: parseInt(options.port, 10),\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\nprogram.parse();\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 readStyleGuideFromProject,\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 * Shared clack/prompts utilities for UILint CLI\n * Provides branded intro/outro, spinners, and common UI patterns\n */\n\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\n\n/**\n * Get the CLI version from package.json\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\n/**\n * Branded UILint intro with logo and version\n */\nexport function intro(title?: string): void {\n const version = getCLIVersion();\n const header = pc.bold(pc.cyan(\"◆ UILint\")) + pc.dim(` v${version}`);\n \n console.log();\n p.intro(title ? `${header} ${pc.dim(\"·\")} ${title}` : header);\n}\n\n/**\n * Styled outro with next steps\n */\nexport function outro(message: string): void {\n p.outro(pc.green(message));\n}\n\n/**\n * Cancel message when user exits\n */\nexport function cancel(message = \"Operation cancelled.\"): void {\n p.cancel(pc.yellow(message));\n process.exit(0);\n}\n\n/**\n * Check if user cancelled a prompt\n */\nexport function isCancel(value: unknown): value is symbol {\n return p.isCancel(value);\n}\n\n/**\n * Handle cancel check - exits if cancelled\n */\nexport function handleCancel<T>(value: T | symbol): T {\n if (p.isCancel(value)) {\n cancel();\n process.exit(0);\n }\n return value as T;\n}\n\n/**\n * Spinner wrapper with automatic error handling\n */\nexport async function withSpinner<T>(\n message: string,\n fn: (() => Promise<T>) | ((spinner: ReturnType<typeof p.spinner>) => Promise<T>)\n): Promise<T> {\n const s = p.spinner();\n s.start(message);\n try {\n const result =\n fn.length >= 1\n ? await (fn as (spinner: ReturnType<typeof p.spinner>) => Promise<T>)(s)\n : await (fn as () => Promise<T>)();\n s.stop(pc.green(\"✓ \") + message);\n return result;\n } catch (error) {\n s.stop(pc.red(\"✗ \") + message);\n throw error;\n }\n}\n\n/**\n * Spinner that can be updated\n */\nexport function createSpinner() {\n return p.spinner();\n}\n\n/**\n * Display a note box\n */\nexport function note(message: string, title?: string): void {\n p.note(message, title);\n}\n\n/**\n * Display a log message\n */\nexport function log(message: string): void {\n p.log.message(message);\n}\n\n/**\n * Display an info message\n */\nexport function logInfo(message: string): void {\n p.log.info(message);\n}\n\n/**\n * Display a success message\n */\nexport function logSuccess(message: string): void {\n p.log.success(message);\n}\n\n/**\n * Display a warning message\n */\nexport function logWarning(message: string): void {\n p.log.warn(message);\n}\n\n/**\n * Display an error message\n */\nexport function logError(message: string): void {\n p.log.error(message);\n}\n\n/**\n * Display a step message\n */\nexport function logStep(message: string): void {\n p.log.step(message);\n}\n\n/**\n * Select prompt wrapper\n */\nexport async function select<T extends string>(options: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n initialValue?: T;\n}): Promise<T> {\n const result = await p.select({\n message: options.message,\n options: options.options as { value: T; label: string; hint?: string }[],\n initialValue: options.initialValue,\n } as Parameters<typeof p.select>[0]);\n return handleCancel(result) as T;\n}\n\n/**\n * Confirm prompt wrapper\n */\nexport async function confirm(options: {\n message: string;\n initialValue?: boolean;\n}): Promise<boolean> {\n const result = await p.confirm({\n message: options.message,\n initialValue: options.initialValue ?? true,\n });\n return handleCancel(result);\n}\n\n/**\n * Text input prompt wrapper\n */\nexport async function text(options: {\n message: string;\n placeholder?: string;\n defaultValue?: string;\n validate?: (value: string) => string | Error | undefined;\n}): Promise<string> {\n const result = await p.text(options);\n return handleCancel(result);\n}\n\n/**\n * Multiselect prompt wrapper\n */\nexport async function multiselect<T extends string>(options: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n required?: boolean;\n initialValues?: T[];\n}): Promise<T[]> {\n const result = await p.multiselect({\n message: options.message,\n options: options.options as { value: T; label: string; hint?: string }[],\n required: options.required,\n initialValues: options.initialValues,\n } as Parameters<typeof p.multiselect>[0]);\n return handleCancel(result) as T[];\n}\n\n/**\n * Group of tasks displayed together\n */\nexport async function group<T extends Record<string, unknown>>(\n prompts: p.PromptGroup<T>,\n options?: p.PromptGroupOptions<T>\n): Promise<T> {\n const result = await p.group(prompts, options);\n return result;\n}\n\n// Re-export picocolors for consistent styling\nexport { pc };\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 * Install command - interactive setup wizard for UILint\n *\n * This is the main orchestrator that coordinates:\n * 1. Analyze - scan project state\n * 2. Gather choices - via prompts or CLI flags\n * 3. Plan - generate install plan\n * 4. Execute - perform side effects\n * 5. Display results\n *\n * The actual logic is split into separate modules for testability:\n * - install/analyze.ts - Project scanning\n * - install/plan.ts - Pure planning logic\n * - install/execute.ts - Side effect execution\n * - install/prompter.ts - User interaction abstraction\n */\n\nimport { join } from \"path\";\nimport { ruleRegistry } from \"uilint-eslint\";\nimport {\n intro,\n outro,\n note,\n logSuccess,\n logInfo,\n logWarning,\n withSpinner,\n pc,\n} from \"../utils/prompts.js\";\nimport { analyze } from \"./install/analyze.js\";\nimport { createPlan } from \"./install/plan.js\";\nimport { execute } from \"./install/execute.js\";\nimport {\n cliPrompter,\n gatherChoices,\n type Prompter,\n} from \"./install/prompter.js\";\nimport type {\n InstallOptions,\n InstallResult,\n ExecuteOptions,\n} from \"./install/types.js\";\n\n// Re-export types for external use\nexport type { InstallOptions } from \"./install/types.js\";\n\n/**\n * Display the installation results\n */\nfunction displayResults(result: InstallResult): void {\n const { summary } = result;\n const installedItems: string[] = [];\n\n // Commands\n if (summary.installedItems.includes(\"genstyleguide\")) {\n installedItems.push(\n `${pc.cyan(\"Command\")} → .cursor/commands/genstyleguide.md`\n );\n }\n\n // Next.js\n if (summary.nextApp) {\n installedItems.push(\n `${pc.cyan(\"Next Routes\")} → ${pc.dim(\n join(summary.nextApp.appRoot, \"api/.uilint\")\n )}`\n );\n installedItems.push(\n `${pc.cyan(\"Next Devtools\")} → ${pc.dim(\"<uilint-devtools /> injected\")}`\n );\n installedItems.push(\n `${pc.cyan(\"JSX Loc Plugin\")} → ${pc.dim(\n \"next.config wrapped with withJsxLoc\"\n )}`\n );\n }\n\n // Vite\n if (summary.viteApp) {\n installedItems.push(\n `${pc.cyan(\"Vite Devtools\")} → ${pc.dim(\"<uilint-devtools /> injected\")}`\n );\n installedItems.push(\n `${pc.cyan(\"JSX Loc Plugin\")} → ${pc.dim(\n \"vite.config plugins patched with jsxLoc()\"\n )}`\n );\n }\n\n // ESLint\n if (summary.eslintTargets.length > 0) {\n installedItems.push(\n `${pc.cyan(\"ESLint Plugin\")} → installed in ${\n summary.eslintTargets.length\n } package(s)`\n );\n for (let i = 0; i < summary.eslintTargets.length; i++) {\n const isLast = i === summary.eslintTargets.length - 1;\n const prefix = isLast ? \"└\" : \"├\";\n installedItems.push(\n ` ${pc.dim(prefix)} ${summary.eslintTargets[i].displayName}`\n );\n }\n installedItems.push(`${pc.cyan(\"Available Rules\")}:`);\n for (let i = 0; i < ruleRegistry.length; i++) {\n const isLast = i === ruleRegistry.length - 1;\n const prefix = isLast ? \"└\" : \"├\";\n const rule = ruleRegistry[i];\n const suffix =\n rule.id === \"semantic\" ? ` ${pc.dim(\"(LLM-powered)\")}` : \"\";\n installedItems.push(\n ` ${pc.dim(prefix)} ${pc.cyan(`uilint/${rule.id}`)}${suffix}`\n );\n }\n }\n\n note(installedItems.join(\"\\n\"), \"Installed\");\n\n // Next steps\n const steps: string[] = [];\n\n const hasStyleguide = summary.filesCreated.some((f) =>\n f.includes(\"styleguide.md\")\n );\n if (!hasStyleguide) {\n steps.push(`Create a styleguide: ${pc.cyan(\"/genstyleguide\")}`);\n }\n\n if (summary.installedItems.includes(\"genstyleguide\")) {\n steps.push(\"Restart Cursor to load the new configuration\");\n }\n\n if (summary.nextApp) {\n steps.push(\n \"Run your Next.js dev server - use Alt+Click on any element to inspect\"\n );\n }\n\n if (summary.viteApp) {\n steps.push(\n \"Run your Vite dev server - use Alt+Click on any element to inspect\"\n );\n }\n\n if (summary.eslintTargets.length > 0) {\n steps.push(`Run ${pc.cyan(\"npx eslint src/\")} to check for issues`);\n steps.push(\n `For real-time overlay integration, run ${pc.cyan(\n \"uilint serve\"\n )} alongside your dev server`\n );\n }\n\n if (steps.length > 0) {\n note(steps.join(\"\\n\"), \"Next Steps\");\n }\n}\n\n/**\n * Main install function - orchestrates the entire installation process\n *\n * @param options - CLI options\n * @param prompter - Prompter implementation (defaults to CLI prompts, can be mocked for tests)\n * @param executeOptions - Options for the execute phase (for testing)\n */\nexport async function install(\n options: InstallOptions = {},\n prompter: Prompter = cliPrompter,\n executeOptions: ExecuteOptions = {}\n): Promise<InstallResult> {\n const projectPath = process.cwd();\n\n intro(\"Setup Wizard\");\n\n // Phase 1: Analyze\n logInfo(\"Analyzing project...\");\n const state = await analyze(projectPath);\n\n // Phase 2: Gather choices\n const choices = await gatherChoices(state, options, prompter);\n\n if (choices.items.length === 0) {\n logWarning(\"No items selected for installation\");\n outro(\"Nothing to install\");\n return {\n success: true,\n actionsPerformed: [],\n dependencyResults: [],\n summary: {\n installedItems: [],\n filesCreated: [],\n filesModified: [],\n filesDeleted: [],\n dependenciesInstalled: [],\n eslintTargets: [],\n },\n };\n }\n\n // Phase 3: Plan\n const plan = createPlan(state, choices, { force: options.force });\n\n // Phase 4: Execute\n logInfo(\"Installing...\");\n\n // Execute actions with spinners for better UX\n const result = await withSpinner(\"Running installation\", async () => {\n return execute(plan, executeOptions);\n });\n\n // Handle any errors\n const failedActions = result.actionsPerformed.filter((r) => !r.success);\n const failedDeps = result.dependencyResults.filter((r) => !r.success);\n\n if (failedActions.length > 0) {\n for (const failed of failedActions) {\n logWarning(`Failed: ${failed.action.type} - ${failed.error}`);\n }\n }\n\n if (failedDeps.length > 0) {\n for (const failed of failedDeps) {\n logWarning(\n `Failed to install dependencies in ${failed.install.packagePath}: ${failed.error}`\n );\n }\n }\n\n // Phase 5: Display results\n displayResults(result);\n\n if (result.success) {\n outro(\"UILint installed successfully!\");\n } else {\n outro(\"UILint installation completed with some errors\");\n }\n\n return result;\n}\n","/**\n * Analyze phase - scan project and return ProjectState\n *\n * This is a pure scanning function with no prompts or mutations.\n * It aggregates detection from existing utilities to build a complete\n * picture of the project state.\n */\n\nimport { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\nimport {\n detectNextAppRouter,\n findNextAppRouterProjects,\n} from \"../../utils/next-detect.js\";\nimport {\n detectViteReact,\n findViteReactProjects,\n} from \"../../utils/vite-detect.js\";\nimport { findPackages } from \"../../utils/package-detect.js\";\nimport { detectPackageManager } from \"../../utils/package-manager.js\";\nimport {\n findEslintConfigFile,\n getEslintConfigFilename,\n getUilintEslintConfigInfoFromSource,\n} from \"../../utils/eslint-config-inject.js\";\nimport type {\n ProjectState,\n EslintPackageInfo,\n NextAppInfo,\n ViteAppInfo,\n} from \"./types.js\";\n\n// NOTE: uilint rule detection must ignore commented-out keys and handle spreads.\n// We re-use the AST-backed detector from eslint-config-inject.\n\n/**\n * Safely parse JSON file, returning undefined on error\n */\nfunction safeParseJson<T>(filePath: string): T | undefined {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n return JSON.parse(content) as T;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Analyze a project and return its state\n *\n * @param projectPath - The project directory to analyze (defaults to cwd)\n * @returns ProjectState describing what exists in the project\n */\nexport async function analyze(\n projectPath: string = process.cwd()\n): Promise<ProjectState> {\n // Find workspace root (may differ from projectPath in monorepos)\n const workspaceRoot = findWorkspaceRoot(projectPath);\n\n // Detect package manager\n const packageManager = detectPackageManager(projectPath);\n\n // .cursor directory\n const cursorDir = join(projectPath, \".cursor\");\n const cursorDirExists = existsSync(cursorDir);\n\n // Styleguide\n const styleguidePath = join(projectPath, \".uilint\", \"styleguide.md\");\n const styleguideExists = existsSync(styleguidePath);\n\n // Cursor commands\n const commandsDir = join(cursorDir, \"commands\");\n const genstyleguideExists = existsSync(join(commandsDir, \"genstyleguide.md\"));\n\n // Detect Next.js App Router projects\n const nextApps: NextAppInfo[] = [];\n const directDetection = detectNextAppRouter(projectPath);\n if (directDetection) {\n nextApps.push({ projectPath, detection: directDetection });\n } else {\n // Search in workspace for Next.js apps\n const matches = findNextAppRouterProjects(workspaceRoot, { maxDepth: 5 });\n for (const match of matches) {\n nextApps.push({\n projectPath: match.projectPath,\n detection: match.detection,\n });\n }\n }\n\n // Detect Vite + React projects\n const viteApps: ViteAppInfo[] = [];\n const directVite = detectViteReact(projectPath);\n if (directVite) {\n viteApps.push({ projectPath, detection: directVite });\n } else {\n const matches = findViteReactProjects(workspaceRoot, { maxDepth: 5 });\n for (const match of matches) {\n viteApps.push({\n projectPath: match.projectPath,\n detection: match.detection,\n });\n }\n }\n\n // Find all packages and enrich with ESLint info\n const rawPackages = findPackages(workspaceRoot);\n const packages: EslintPackageInfo[] = rawPackages.map((pkg) => {\n const eslintConfigPath = findEslintConfigFile(pkg.path);\n let eslintConfigFilename: string | null = null;\n let hasRules = false;\n let configuredRuleIds: string[] = [];\n\n if (eslintConfigPath) {\n eslintConfigFilename = getEslintConfigFilename(eslintConfigPath);\n try {\n const source = readFileSync(eslintConfigPath, \"utf-8\");\n const info = getUilintEslintConfigInfoFromSource(source);\n hasRules = info.configuredRuleIds.size > 0;\n configuredRuleIds = Array.from(info.configuredRuleIds);\n } catch {\n // Ignore read errors\n }\n }\n\n return {\n ...pkg,\n eslintConfigPath,\n eslintConfigFilename,\n hasUilintRules: hasRules,\n configuredRuleIds,\n };\n });\n\n return {\n projectPath,\n workspaceRoot,\n packageManager,\n cursorDir: {\n exists: cursorDirExists,\n path: cursorDir,\n },\n styleguide: {\n exists: styleguideExists,\n path: styleguidePath,\n },\n commands: {\n genstyleguide: genstyleguideExists,\n },\n nextApps,\n viteApps,\n packages,\n };\n}\n","import { existsSync, readdirSync } from \"fs\";\nimport { join } from \"path\";\n\nexport interface NextAppRouterDetection {\n /**\n * Relative path to the Next App Router root dir (either \"app\" or \"src/app\").\n */\n appRoot: string;\n /**\n * Absolute path to the App Router root dir.\n */\n appRootAbs: string;\n /**\n * Candidate entry files (relative paths) that are good injection targets.\n */\n candidates: string[];\n}\n\nfunction fileExists(projectPath: string, relPath: string): boolean {\n return existsSync(join(projectPath, relPath));\n}\n\nexport function detectNextAppRouter(\n projectPath: string\n): NextAppRouterDetection | null {\n const roots = [\"app\", join(\"src\", \"app\")];\n const candidates: string[] = [];\n\n let chosenRoot: string | null = null;\n for (const root of roots) {\n if (existsSync(join(projectPath, root))) {\n chosenRoot = root;\n break;\n }\n }\n\n if (!chosenRoot) return null;\n\n // Prioritize layout files (Next App Router canonical integration point).\n const entryCandidates = [\n join(chosenRoot, \"layout.tsx\"),\n join(chosenRoot, \"layout.jsx\"),\n join(chosenRoot, \"layout.ts\"),\n join(chosenRoot, \"layout.js\"),\n // Fallbacks (less ideal, but can work):\n join(chosenRoot, \"page.tsx\"),\n join(chosenRoot, \"page.jsx\"),\n ];\n\n for (const rel of entryCandidates) {\n if (fileExists(projectPath, rel)) candidates.push(rel);\n }\n\n // If nothing exists, still return detection so routes can be installed.\n return {\n appRoot: chosenRoot,\n appRootAbs: join(projectPath, chosenRoot),\n candidates,\n };\n}\n\nexport interface NextAppRouterProjectMatch {\n /**\n * Absolute path to the Next project root (dir containing app/ or src/app/).\n */\n projectPath: string;\n detection: NextAppRouterDetection;\n}\n\nconst DEFAULT_IGNORE_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \"dist\",\n \"build\",\n \"out\",\n \".turbo\",\n \".vercel\",\n \".cursor\",\n \"coverage\",\n \".uilint\",\n]);\n\n/**\n * Best-effort monorepo discovery for Next.js App Router apps.\n *\n * Walks down from `rootDir` looking for directories that contain `app/` or\n * `src/app/`. Skips common large/irrelevant dirs.\n */\nexport function findNextAppRouterProjects(\n rootDir: string,\n options?: { maxDepth?: number; ignoreDirs?: Set<string> }\n): NextAppRouterProjectMatch[] {\n const maxDepth = options?.maxDepth ?? 4;\n const ignoreDirs = options?.ignoreDirs ?? DEFAULT_IGNORE_DIRS;\n const results: NextAppRouterProjectMatch[] = [];\n const visited = new Set<string>();\n\n function walk(dir: string, depth: number) {\n if (depth > maxDepth) return;\n if (visited.has(dir)) return;\n visited.add(dir);\n\n const detection = detectNextAppRouter(dir);\n if (detection) {\n results.push({ projectPath: dir, detection });\n // Don't descend further once we found a project root (avoid nested hits).\n return;\n }\n\n let entries: Array<{ name: string; isDirectory: boolean }> = [];\n try {\n entries = readdirSync(dir, { withFileTypes: true }).map((d) => ({\n name: d.name,\n isDirectory: d.isDirectory(),\n }));\n } catch {\n return;\n }\n\n for (const ent of entries) {\n if (!ent.isDirectory) continue;\n if (ignoreDirs.has(ent.name)) continue;\n // Skip hidden dirs by default (except `src` which matters)\n if (ent.name.startsWith(\".\") && ent.name !== \".\") continue;\n walk(join(dir, ent.name), depth + 1);\n }\n }\n\n walk(rootDir, 0);\n return results;\n}\n","import { existsSync, readdirSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\n\nexport interface ViteReactDetection {\n /**\n * Relative path to the Vite config file (e.g. \"vite.config.ts\").\n */\n configFile: string;\n /**\n * Absolute path to the Vite config file.\n */\n configFileAbs: string;\n /**\n * Relative path to the source root (usually \"src\").\n */\n entryRoot: string;\n /**\n * Candidate entry files (relative paths) that are good injection targets.\n * For Vite+React this is usually `src/main.*`.\n */\n candidates: string[];\n}\n\nconst VITE_CONFIG_EXTS = [\".ts\", \".mjs\", \".js\", \".cjs\"];\n\nfunction findViteConfigFile(projectPath: string): string | null {\n for (const ext of VITE_CONFIG_EXTS) {\n const rel = `vite.config${ext}`;\n if (existsSync(join(projectPath, rel))) return rel;\n }\n return null;\n}\n\nfunction looksLikeReactPackage(projectPath: string): boolean {\n try {\n const pkgPath = join(projectPath, \"package.json\");\n if (!existsSync(pkgPath)) return false;\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n return \"react\" in deps || \"react-dom\" in deps;\n } catch {\n return false;\n }\n}\n\nfunction fileExists(projectPath: string, relPath: string): boolean {\n return existsSync(join(projectPath, relPath));\n}\n\nexport function detectViteReact(projectPath: string): ViteReactDetection | null {\n const configFile = findViteConfigFile(projectPath);\n if (!configFile) return null;\n\n // Overlay integration currently targets React apps.\n if (!looksLikeReactPackage(projectPath)) return null;\n\n // Prefer Vite defaults: src/main.(tsx|jsx|ts|js)\n const entryRoot = \"src\";\n const candidates: string[] = [];\n const entryCandidates = [\n join(entryRoot, \"main.tsx\"),\n join(entryRoot, \"main.jsx\"),\n join(entryRoot, \"main.ts\"),\n join(entryRoot, \"main.js\"),\n ];\n\n for (const rel of entryCandidates) {\n if (fileExists(projectPath, rel)) candidates.push(rel);\n }\n\n // If no main.* exists, try common fallbacks (some templates render in App.tsx)\n const fallbackCandidates = [\n join(entryRoot, \"App.tsx\"),\n join(entryRoot, \"App.jsx\"),\n ];\n for (const rel of fallbackCandidates) {\n if (!candidates.includes(rel) && fileExists(projectPath, rel)) {\n candidates.push(rel);\n }\n }\n\n return {\n configFile,\n configFileAbs: join(projectPath, configFile),\n entryRoot,\n candidates,\n };\n}\n\nexport interface ViteReactProjectMatch {\n /**\n * Absolute path to the Vite project root (dir containing vite.config.*).\n */\n projectPath: string;\n detection: ViteReactDetection;\n}\n\nconst DEFAULT_IGNORE_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \"dist\",\n \"build\",\n \"out\",\n \".turbo\",\n \".vercel\",\n \".cursor\",\n \"coverage\",\n \".uilint\",\n]);\n\n/**\n * Best-effort monorepo discovery for Vite + React apps.\n *\n * Walks down from `rootDir` looking for directories that contain `vite.config.*`\n * and whose package.json looks like a React project.\n */\nexport function findViteReactProjects(\n rootDir: string,\n options?: { maxDepth?: number; ignoreDirs?: Set<string> }\n): ViteReactProjectMatch[] {\n const maxDepth = options?.maxDepth ?? 4;\n const ignoreDirs = options?.ignoreDirs ?? DEFAULT_IGNORE_DIRS;\n const results: ViteReactProjectMatch[] = [];\n const visited = new Set<string>();\n\n function walk(dir: string, depth: number) {\n if (depth > maxDepth) return;\n if (visited.has(dir)) return;\n visited.add(dir);\n\n const detection = detectViteReact(dir);\n if (detection) {\n results.push({ projectPath: dir, detection });\n return;\n }\n\n let entries: Array<{ name: string; isDirectory: boolean }> = [];\n try {\n entries = readdirSync(dir, { withFileTypes: true }).map((d) => ({\n name: d.name,\n isDirectory: d.isDirectory(),\n }));\n } catch {\n return;\n }\n\n for (const ent of entries) {\n if (!ent.isDirectory) continue;\n if (ignoreDirs.has(ent.name)) continue;\n if (ent.name.startsWith(\".\") && ent.name !== \".\") continue;\n walk(join(dir, ent.name), depth + 1);\n }\n }\n\n walk(rootDir, 0);\n return results;\n}\n","/**\n * Package.json detection utilities for monorepo discovery\n */\n\nimport { existsSync, readdirSync, readFileSync } from \"fs\";\nimport { join, relative } from \"path\";\n\nexport interface PackageInfo {\n /** Absolute path to the package directory */\n path: string;\n /** Display name (relative path from workspace root) */\n displayPath: string;\n /** Package name from package.json */\n name: string;\n /** Whether this package has ESLint config */\n hasEslintConfig: boolean;\n /** Whether this appears to be a frontend/UI package */\n isFrontend: boolean;\n /** Whether this is the workspace root */\n isRoot: boolean;\n /** Whether this package uses TypeScript */\n isTypeScript: boolean;\n}\n\nconst DEFAULT_IGNORE_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \"dist\",\n \"build\",\n \"out\",\n \".turbo\",\n \".vercel\",\n \".cursor\",\n \"coverage\",\n \".uilint\",\n \".pnpm\",\n]);\n\nconst ESLINT_CONFIG_FILES = [\n \"eslint.config.js\",\n \"eslint.config.ts\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yml\",\n \".eslintrc.yaml\",\n \".eslintrc\",\n];\n\nconst FRONTEND_INDICATORS = [\n \"react\",\n \"react-dom\",\n \"next\",\n \"vue\",\n \"svelte\",\n \"@angular/core\",\n \"solid-js\",\n \"preact\",\n];\n\n/**\n * Check if a package.json indicates a frontend project\n */\nfunction isFrontendPackage(pkgJson: Record<string, unknown>): boolean {\n const deps = {\n ...(pkgJson.dependencies as Record<string, string> | undefined),\n ...(pkgJson.devDependencies as Record<string, string> | undefined),\n };\n\n return FRONTEND_INDICATORS.some((pkg) => pkg in deps);\n}\n\n/**\n * Check if a package uses TypeScript\n */\nfunction isTypeScriptPackage(dir: string, pkgJson: Record<string, unknown>): boolean {\n // Check for tsconfig.json\n if (existsSync(join(dir, \"tsconfig.json\"))) {\n return true;\n }\n\n // Check for typescript in dependencies\n const deps = {\n ...(pkgJson.dependencies as Record<string, string> | undefined),\n ...(pkgJson.devDependencies as Record<string, string> | undefined),\n };\n\n if (\"typescript\" in deps) {\n return true;\n }\n\n // Check ESLint config file extension (if .ts, it's TypeScript)\n for (const configFile of ESLINT_CONFIG_FILES) {\n if (configFile.endsWith(\".ts\") && existsSync(join(dir, configFile))) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if directory has ESLint config\n */\nfunction hasEslintConfig(dir: string): boolean {\n for (const file of ESLINT_CONFIG_FILES) {\n if (existsSync(join(dir, file))) {\n return true;\n }\n }\n\n // Also check package.json for eslintConfig field\n try {\n const pkgPath = join(dir, \"package.json\");\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n if (pkg.eslintConfig) return true;\n }\n } catch {\n // Ignore parse errors\n }\n\n return false;\n}\n\n/**\n * Find all packages in a workspace that could have ESLint installed\n */\nexport function findPackages(\n rootDir: string,\n options?: { maxDepth?: number; ignoreDirs?: Set<string> }\n): PackageInfo[] {\n const maxDepth = options?.maxDepth ?? 5;\n const ignoreDirs = options?.ignoreDirs ?? DEFAULT_IGNORE_DIRS;\n const results: PackageInfo[] = [];\n const visited = new Set<string>();\n\n function processPackage(dir: string, isRoot: boolean): PackageInfo | null {\n const pkgPath = join(dir, \"package.json\");\n if (!existsSync(pkgPath)) return null;\n\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n const name = pkg.name || relative(rootDir, dir) || \".\";\n\n return {\n path: dir,\n displayPath: relative(rootDir, dir) || \".\",\n name,\n hasEslintConfig: hasEslintConfig(dir),\n isFrontend: isFrontendPackage(pkg),\n isRoot,\n isTypeScript: isTypeScriptPackage(dir, pkg),\n };\n } catch {\n return null;\n }\n }\n\n function walk(dir: string, depth: number) {\n if (depth > maxDepth) return;\n if (visited.has(dir)) return;\n visited.add(dir);\n\n // Check for package.json in this dir\n const pkg = processPackage(dir, depth === 0);\n if (pkg) {\n results.push(pkg);\n }\n\n // Continue walking (even if we found a package - monorepos have nested packages)\n let entries: Array<{ name: string; isDirectory: boolean }> = [];\n try {\n entries = readdirSync(dir, { withFileTypes: true }).map((d) => ({\n name: d.name,\n isDirectory: d.isDirectory(),\n }));\n } catch {\n return;\n }\n\n for (const ent of entries) {\n if (!ent.isDirectory) continue;\n if (ignoreDirs.has(ent.name)) continue;\n if (ent.name.startsWith(\".\")) continue;\n walk(join(dir, ent.name), depth + 1);\n }\n }\n\n walk(rootDir, 0);\n\n // Sort: frontend packages first, then by path\n return results.sort((a, b) => {\n // Root package first\n if (a.isRoot && !b.isRoot) return -1;\n if (!a.isRoot && b.isRoot) return 1;\n // Frontend packages next\n if (a.isFrontend && !b.isFrontend) return -1;\n if (!a.isFrontend && b.isFrontend) return 1;\n // Then alphabetically by path\n return a.displayPath.localeCompare(b.displayPath);\n });\n}\n\n/**\n * Format package info for display in selection menu\n */\nexport function formatPackageOption(pkg: PackageInfo): {\n value: string;\n label: string;\n hint?: string;\n} {\n const hints: string[] = [];\n\n if (pkg.isRoot) hints.push(\"workspace root\");\n if (pkg.isFrontend) hints.push(\"frontend\");\n if (pkg.hasEslintConfig) hints.push(\"has ESLint config\");\n\n return {\n value: pkg.path,\n label:\n pkg.displayPath === \".\" ? pkg.name : `${pkg.name} (${pkg.displayPath})`,\n hint: hints.length > 0 ? hints.join(\", \") : undefined,\n };\n}\n","import { existsSync } from \"fs\";\nimport { spawn } from \"child_process\";\nimport { dirname, join } from \"path\";\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"npm\" | \"bun\";\n\nexport function detectPackageManager(projectPath: string): PackageManager {\n // Monorepo-friendly detection: walk up to find the lockfile/workspace marker.\n let dir = projectPath;\n for (;;) {\n // pnpm\n if (existsSync(join(dir, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(dir, \"pnpm-workspace.yaml\"))) return \"pnpm\";\n\n // yarn\n if (existsSync(join(dir, \"yarn.lock\"))) return \"yarn\";\n\n // bun\n if (existsSync(join(dir, \"bun.lockb\"))) return \"bun\";\n if (existsSync(join(dir, \"bun.lock\"))) return \"bun\";\n\n // npm\n if (existsSync(join(dir, \"package-lock.json\"))) return \"npm\";\n\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n // Default: npm (best-effort)\n return \"npm\";\n}\n\nfunction spawnAsync(\n command: string,\n args: string[],\n cwd: string\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else\n reject(new Error(`${command} ${args.join(\" \")} exited with ${code}`));\n });\n });\n}\n\nexport async function installDependencies(\n pm: PackageManager,\n projectPath: string,\n packages: string[]\n): Promise<void> {\n if (!packages.length) return;\n\n switch (pm) {\n case \"pnpm\":\n await spawnAsync(\"pnpm\", [\"add\", ...packages], projectPath);\n return;\n case \"yarn\":\n await spawnAsync(\"yarn\", [\"add\", ...packages], projectPath);\n return;\n case \"bun\":\n await spawnAsync(\"bun\", [\"add\", ...packages], projectPath);\n return;\n case \"npm\":\n default:\n await spawnAsync(\"npm\", [\"install\", \"--save\", ...packages], projectPath);\n return;\n }\n}\n","/**\n * Inject uilint-eslint rules into ESLint config\n *\n * Modifies eslint.config.{ts,mjs,js,cjs} to add uilint import and selected rules\n */\n\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { join, relative, dirname } from \"path\";\nimport type { RuleMetadata } from \"uilint-eslint\";\nimport { parseExpression, parseModule, generateCode } from \"magicast\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\n\nexport interface InstallEslintPluginOptions {\n projectPath: string;\n selectedRules: RuleMetadata[];\n force?: boolean;\n confirmAddMissingRules?: (\n relPath: string,\n missingRules: RuleMetadata[]\n ) => Promise<boolean>;\n}\n\nconst CONFIG_EXTENSIONS = [\".ts\", \".mjs\", \".js\", \".cjs\"];\n\n/**\n * Find the eslint.config file in a project\n */\nexport function findEslintConfigFile(projectPath: string): string | null {\n for (const ext of CONFIG_EXTENSIONS) {\n const configPath = join(projectPath, `eslint.config${ext}`);\n if (existsSync(configPath)) {\n return configPath;\n }\n }\n return null;\n}\n\n/**\n * Get the relative config filename for display\n */\nexport function getEslintConfigFilename(configPath: string): string {\n const parts = configPath.split(\"/\");\n return parts[parts.length - 1] || \"eslint.config.mjs\";\n}\n\n/**\n * Check if the source already has uilint rules configured\n */\nfunction hasUilintRules(source: string): boolean {\n return source.includes('\"uilint/') || source.includes(\"'uilint/\");\n}\n\n/**\n * Check if the source already has uilint imported\n */\nfunction hasUilintImport(source: string): boolean {\n return (\n source.includes('from \"uilint-eslint\"') ||\n source.includes(\"from 'uilint-eslint'\") ||\n source.includes('require(\"uilint-eslint\")') ||\n source.includes(\"require('uilint-eslint')\")\n );\n}\n\ntype UilintEslintConfigInfo = {\n /** Set of configured `uilint/*` rule IDs (without the `uilint/` prefix). */\n configuredRuleIds: Set<string>;\n /** Whether config appears to configure uilint rules. */\n configured: boolean;\n};\n\nfunction walkAst(node: any, visit: (n: any) => void): void {\n if (!node || typeof node !== \"object\") return;\n visit(node);\n for (const key of Object.keys(node)) {\n const v = (node as any)[key];\n if (!v) continue;\n if (Array.isArray(v)) {\n for (const item of v) walkAst(item, visit);\n } else if (typeof v === \"object\" && v.type) {\n walkAst(v, visit);\n }\n }\n}\n\nfunction isIdentifier(node: any, name?: string): boolean {\n return (\n !!node &&\n node.type === \"Identifier\" &&\n (name ? node.name === name : typeof node.name === \"string\")\n );\n}\n\nfunction isStringLiteral(node: any): node is { type: string; value: string } {\n return (\n !!node &&\n (node.type === \"StringLiteral\" || node.type === \"Literal\") &&\n typeof node.value === \"string\"\n );\n}\n\nfunction getObjectPropertyValue(obj: any, keyName: string): any | null {\n if (!obj || obj.type !== \"ObjectExpression\") return null;\n for (const prop of obj.properties ?? []) {\n if (!prop) continue;\n if (prop.type === \"ObjectProperty\" || prop.type === \"Property\") {\n const key = prop.key;\n const keyMatch =\n (key?.type === \"Identifier\" && key.name === keyName) ||\n (isStringLiteral(key) && key.value === keyName);\n if (keyMatch) return prop.value;\n }\n }\n return null;\n}\n\nfunction hasSpreadProperties(obj: any): boolean {\n if (!obj || obj.type !== \"ObjectExpression\") return false;\n return (obj.properties ?? []).some(\n (p: any) => p && (p.type === \"SpreadElement\" || p.type === \"SpreadProperty\")\n );\n}\n\nconst IGNORED_AST_KEYS = new Set([\n \"loc\",\n \"start\",\n \"end\",\n \"extra\",\n \"leadingComments\",\n \"trailingComments\",\n \"innerComments\",\n]);\n\nfunction normalizeAstForCompare(node: any): any {\n if (node === null) return null;\n if (node === undefined) return undefined;\n if (typeof node !== \"object\") return node;\n if (Array.isArray(node)) return node.map(normalizeAstForCompare);\n\n const out: Record<string, any> = {};\n const keys = Object.keys(node)\n .filter((k) => !IGNORED_AST_KEYS.has(k))\n .sort();\n for (const k of keys) {\n // Avoid proxy-ish or non-serializable fields if present.\n if (k.startsWith(\"$\")) continue;\n out[k] = normalizeAstForCompare(node[k]);\n }\n return out;\n}\n\nfunction astEquivalent(a: any, b: any): boolean {\n try {\n return (\n JSON.stringify(normalizeAstForCompare(a)) ===\n JSON.stringify(normalizeAstForCompare(b))\n );\n } catch {\n return false;\n }\n}\n\nfunction collectUilintRuleIdsFromRulesObject(rulesObj: any): Set<string> {\n const ids = new Set<string>();\n if (!rulesObj || rulesObj.type !== \"ObjectExpression\") return ids;\n for (const prop of rulesObj.properties ?? []) {\n if (!prop) continue;\n if (prop.type !== \"ObjectProperty\" && prop.type !== \"Property\") continue;\n const key = prop.key;\n if (!isStringLiteral(key)) continue;\n const val = key.value;\n if (typeof val !== \"string\") continue;\n if (val.startsWith(\"uilint/\")) {\n ids.add(val.slice(\"uilint/\".length));\n }\n }\n return ids;\n}\n\nfunction findExportedConfigArrayExpression(mod: any): {\n kind: \"esm\" | \"cjs\";\n arrayExpr: any;\n program: any;\n} | null {\n function unwrapExpression(expr: any): any {\n let e = expr;\n // Best-effort unwrap for TS/parenthesized wrappers. (These can appear if the\n // config is authored in TS/JS with type assertions or parentheses.)\n while (e) {\n if (e.type === \"TSAsExpression\" || e.type === \"TSNonNullExpression\") {\n e = e.expression;\n continue;\n }\n if (e.type === \"TSSatisfiesExpression\") {\n e = e.expression;\n continue;\n }\n if (e.type === \"ParenthesizedExpression\") {\n e = e.expression;\n continue;\n }\n break;\n }\n return e;\n }\n\n function resolveTopLevelIdentifierToArrayExpr(\n program: any,\n name: string\n ): any | null {\n if (!program || program.type !== \"Program\") return null;\n for (const stmt of program.body ?? []) {\n if (stmt?.type !== \"VariableDeclaration\") continue;\n for (const decl of stmt.declarations ?? []) {\n const id = decl?.id;\n if (!isIdentifier(id, name)) continue;\n const init = unwrapExpression(decl?.init);\n if (!init) return null;\n if (init.type === \"ArrayExpression\") return init;\n if (\n init.type === \"CallExpression\" &&\n isIdentifier(init.callee, \"defineConfig\") &&\n unwrapExpression(init.arguments?.[0])?.type === \"ArrayExpression\"\n ) {\n return unwrapExpression(init.arguments?.[0]);\n }\n return null;\n }\n }\n return null;\n }\n\n // Prefer reading directly from the program AST so we can handle:\n // - export default [ ... ]\n // - export default defineConfig([ ... ])\n // - export default eslintConfig; (where eslintConfig is a top-level array)\n const program = mod?.$ast;\n if (program && program.type === \"Program\") {\n for (const stmt of program.body ?? []) {\n if (!stmt || stmt.type !== \"ExportDefaultDeclaration\") continue;\n const decl = unwrapExpression(stmt.declaration);\n if (!decl) break;\n\n if (decl.type === \"ArrayExpression\") {\n return { kind: \"esm\", arrayExpr: decl, program };\n }\n if (\n decl.type === \"CallExpression\" &&\n isIdentifier(decl.callee, \"defineConfig\") &&\n unwrapExpression(decl.arguments?.[0])?.type === \"ArrayExpression\"\n ) {\n return {\n kind: \"esm\",\n arrayExpr: unwrapExpression(decl.arguments?.[0]),\n program,\n };\n }\n if (decl.type === \"Identifier\" && typeof decl.name === \"string\") {\n const resolved = resolveTopLevelIdentifierToArrayExpr(\n program,\n decl.name\n );\n if (resolved) return { kind: \"esm\", arrayExpr: resolved, program };\n }\n break;\n }\n }\n\n // CommonJS: module.exports = [ ... ] OR module.exports = defineConfig([ ... ])\n if (!program || program.type !== \"Program\") return null;\n\n for (const stmt of program.body ?? []) {\n if (!stmt || stmt.type !== \"ExpressionStatement\") continue;\n const expr = stmt.expression;\n if (!expr || expr.type !== \"AssignmentExpression\") continue;\n const left = expr.left;\n const right = expr.right;\n const isModuleExports =\n left?.type === \"MemberExpression\" &&\n isIdentifier(left.object, \"module\") &&\n isIdentifier(left.property, \"exports\");\n if (!isModuleExports) continue;\n\n if (right?.type === \"ArrayExpression\") {\n return { kind: \"cjs\", arrayExpr: right, program };\n }\n if (\n right?.type === \"CallExpression\" &&\n isIdentifier(right.callee, \"defineConfig\") &&\n right.arguments?.[0]?.type === \"ArrayExpression\"\n ) {\n return { kind: \"cjs\", arrayExpr: right.arguments[0], program };\n }\n if (right?.type === \"Identifier\" && typeof right.name === \"string\") {\n const resolved = resolveTopLevelIdentifierToArrayExpr(\n program,\n right.name\n );\n if (resolved) return { kind: \"cjs\", arrayExpr: resolved, program };\n }\n }\n\n return null;\n}\n\nfunction collectConfiguredUilintRuleIdsFromConfigArray(\n arrayExpr: any\n): Set<string> {\n const ids = new Set<string>();\n if (!arrayExpr || arrayExpr.type !== \"ArrayExpression\") return ids;\n for (const el of arrayExpr.elements ?? []) {\n if (!el || el.type !== \"ObjectExpression\") continue;\n const rules = getObjectPropertyValue(el, \"rules\");\n for (const id of collectUilintRuleIdsFromRulesObject(rules)) ids.add(id);\n }\n return ids;\n}\n\nfunction findExistingUilintRulesObject(arrayExpr: any): {\n configObj: any | null;\n rulesObj: any | null;\n safeToMutate: boolean;\n} {\n if (!arrayExpr || arrayExpr.type !== \"ArrayExpression\") {\n return { configObj: null, rulesObj: null, safeToMutate: false };\n }\n\n for (const el of arrayExpr.elements ?? []) {\n if (!el || el.type !== \"ObjectExpression\") continue;\n\n const plugins = getObjectPropertyValue(el, \"plugins\");\n const rules = getObjectPropertyValue(el, \"rules\");\n\n const hasUilintPlugin =\n plugins?.type === \"ObjectExpression\" &&\n getObjectPropertyValue(plugins, \"uilint\") !== null;\n\n const uilintIds = collectUilintRuleIdsFromRulesObject(rules);\n const hasUilintRules = uilintIds.size > 0;\n\n if (!hasUilintPlugin && !hasUilintRules) continue;\n\n const safe =\n rules?.type === \"ObjectExpression\" && !hasSpreadProperties(rules);\n return { configObj: el, rulesObj: rules, safeToMutate: safe };\n }\n\n return { configObj: null, rulesObj: null, safeToMutate: false };\n}\n\nfunction collectTopLevelBindings(program: any): Set<string> {\n const names = new Set<string>();\n if (!program || program.type !== \"Program\") return names;\n\n for (const stmt of program.body ?? []) {\n if (stmt?.type === \"VariableDeclaration\") {\n for (const decl of stmt.declarations ?? []) {\n const id = decl?.id;\n if (id?.type === \"Identifier\" && typeof id.name === \"string\") {\n names.add(id.name);\n }\n }\n } else if (stmt?.type === \"FunctionDeclaration\") {\n if (stmt.id?.type === \"Identifier\" && typeof stmt.id.name === \"string\") {\n names.add(stmt.id.name);\n }\n }\n }\n return names;\n}\n\nfunction chooseUniqueIdentifier(base: string, used: Set<string>): string {\n if (!used.has(base)) return base;\n let i = 2;\n while (used.has(`${base}${i}`)) i++;\n return `${base}${i}`;\n}\n\n/**\n * Add imports for local rules from .uilint/rules/\n */\nfunction addLocalRuleImportsAst(\n mod: any,\n selectedRules: RuleMetadata[],\n configPath: string,\n rulesRoot: string,\n fileExtension: string = \".js\"\n): { importNames: Map<string, string>; changed: boolean } {\n const importNames = new Map<string, string>();\n let changed = false;\n\n // Calculate relative path from config file to .uilint/rules/\n const configDir = dirname(configPath);\n const rulesDir = join(rulesRoot, \".uilint\", \"rules\");\n const relativeRulesPath = relative(configDir, rulesDir).replace(/\\\\/g, \"/\");\n\n // Ensure it starts with ./ or ../ (note: `.foo` is NOT a valid relative import)\n const normalizedRulesPath =\n relativeRulesPath.startsWith(\"./\") || relativeRulesPath.startsWith(\"../\")\n ? relativeRulesPath\n : `./${relativeRulesPath}`;\n\n const used = collectTopLevelBindings(mod.$ast);\n\n for (const rule of selectedRules) {\n // Generate a safe import name (e.g., noArbitraryTailwindRule)\n const importName = chooseUniqueIdentifier(\n `${rule.id\n .replace(/-([a-z])/g, (_: string, c: string) => c.toUpperCase())\n .replace(/^./, (c: string) => c.toUpperCase())}Rule`,\n used\n );\n importNames.set(rule.id, importName);\n used.add(importName);\n\n // Add import statement\n const rulePath = `${normalizedRulesPath}/${rule.id}${fileExtension}`;\n mod.imports.$add({\n imported: \"default\",\n local: importName,\n from: rulePath,\n });\n changed = true;\n }\n\n return { importNames, changed };\n}\n\n/**\n * Add require statements for local rules (CommonJS)\n */\nfunction addLocalRuleRequiresAst(\n program: any,\n selectedRules: RuleMetadata[],\n configPath: string,\n rulesRoot: string,\n fileExtension: string = \".js\"\n): { importNames: Map<string, string>; changed: boolean } {\n const importNames = new Map<string, string>();\n let changed = false;\n\n if (!program || program.type !== \"Program\") {\n return { importNames, changed };\n }\n\n // Calculate relative path from config file to .uilint/rules/\n const configDir = dirname(configPath);\n const rulesDir = join(rulesRoot, \".uilint\", \"rules\");\n const relativeRulesPath = relative(configDir, rulesDir).replace(/\\\\/g, \"/\");\n\n // Ensure it starts with ./ or ../ (note: `.foo` is NOT a valid relative require)\n const normalizedRulesPath =\n relativeRulesPath.startsWith(\"./\") || relativeRulesPath.startsWith(\"../\")\n ? relativeRulesPath\n : `./${relativeRulesPath}`;\n\n const used = collectTopLevelBindings(program);\n\n for (const rule of selectedRules) {\n // Generate a safe import name\n const importName = chooseUniqueIdentifier(\n `${rule.id\n .replace(/-([a-z])/g, (_: string, c: string) => c.toUpperCase())\n .replace(/^./, (c: string) => c.toUpperCase())}Rule`,\n used\n );\n importNames.set(rule.id, importName);\n used.add(importName);\n\n // Add require statement\n const rulePath = `${normalizedRulesPath}/${rule.id}${fileExtension}`;\n const stmtMod = parseModule(\n `const ${importName} = require(\"${rulePath}\");`\n );\n const stmt = (stmtMod.$ast as any).body?.[0];\n if (stmt) {\n // Place after a leading \"use strict\" if present.\n let insertAt = 0;\n const first = program.body?.[0];\n if (\n first?.type === \"ExpressionStatement\" &&\n first.expression?.type === \"StringLiteral\" &&\n first.expression.value === \"use strict\"\n ) {\n insertAt = 1;\n }\n program.body.splice(insertAt, 0, stmt);\n changed = true;\n }\n }\n\n return { importNames, changed };\n}\n\nfunction appendUilintConfigBlockToArray(\n arrayExpr: any,\n selectedRules: RuleMetadata[],\n ruleImportNames: Map<string, string>\n): void {\n // Build plugin object with local rule imports\n const pluginRulesCode = Array.from(ruleImportNames.entries())\n .map(([ruleId, importName]) => ` \"${ruleId}\": ${importName},`)\n .join(\"\\n\");\n\n const rulesPropsCode = selectedRules\n .map((r) => {\n const ruleKey = `uilint/${r.id}`;\n const valueCode =\n r.defaultOptions && r.defaultOptions.length > 0\n ? `[\"${r.defaultSeverity}\", ...${JSON.stringify(\n r.defaultOptions,\n null,\n 2\n )}]`\n : `\"${r.defaultSeverity}\"`;\n return ` \"${ruleKey}\": ${valueCode},`;\n })\n .join(\"\\n\");\n\n const blockCode = `{\n files: [\n \"src/**/*.{js,jsx,ts,tsx}\",\n \"app/**/*.{js,jsx,ts,tsx}\",\n \"pages/**/*.{js,jsx,ts,tsx}\",\n ],\n plugins: {\n uilint: {\n rules: {\n${pluginRulesCode}\n },\n },\n },\n rules: {\n${rulesPropsCode}\n },\n }`;\n\n const objExpr = (parseExpression(blockCode) as any).$ast;\n arrayExpr.elements.push(objExpr);\n}\n\nfunction getUilintEslintConfigInfoFromSourceAst(source: string):\n | {\n info: UilintEslintConfigInfo;\n mod: any;\n arrayExpr: any;\n kind: \"esm\" | \"cjs\";\n }\n | { error: string } {\n try {\n const mod = parseModule(source);\n const found = findExportedConfigArrayExpression(mod);\n if (!found) {\n return {\n error:\n \"Could not locate an exported ESLint flat config array (expected `export default [...]`, `export default defineConfig([...])`, `module.exports = [...]`, or `module.exports = defineConfig([...])`).\",\n };\n }\n\n const configuredRuleIds = collectConfiguredUilintRuleIdsFromConfigArray(\n found.arrayExpr\n );\n const existingUilint = findExistingUilintRulesObject(found.arrayExpr);\n const configured =\n configuredRuleIds.size > 0 || existingUilint.configObj !== null;\n\n return {\n info: { configuredRuleIds, configured },\n mod,\n arrayExpr: found.arrayExpr,\n kind: found.kind,\n };\n } catch {\n return {\n error:\n \"Unable to parse ESLint config as JavaScript. Please update it manually or simplify the config so it can be safely auto-modified.\",\n };\n }\n}\n\nexport function getUilintEslintConfigInfoFromSource(\n source: string\n): UilintEslintConfigInfo {\n const ast = getUilintEslintConfigInfoFromSourceAst(source);\n if (\"error\" in ast) {\n // Fallback (best-effort) to string heuristics for scan-only scenarios.\n const configuredRuleIds = extractConfiguredUilintRuleIds(source);\n return {\n configuredRuleIds,\n configured: configuredRuleIds.size > 0,\n };\n }\n return ast.info;\n}\n\nfunction findEsmExportedConfigArrayStartIndex(source: string): number | null {\n // Supported:\n // - export default [ ... ]\n // - export default defineConfig([ ... ])\n const patterns: RegExp[] = [\n /export\\s+default\\s+\\[/,\n /export\\s+default\\s+defineConfig\\s*\\(\\s*\\[/,\n ];\n\n for (const re of patterns) {\n const m = source.match(re);\n if (!m || m.index === undefined) continue;\n return m.index + m[0].length;\n }\n\n return null;\n}\n\nfunction findCommonJsExportedConfigArrayStartIndex(\n source: string\n): number | null {\n // Supported:\n // - module.exports = [ ... ]\n // - module.exports = defineConfig([ ... ]) (best-effort)\n const patterns: RegExp[] = [\n /module\\.exports\\s*=\\s*\\[/,\n /module\\.exports\\s*=\\s*defineConfig\\s*\\(\\s*\\[/,\n ];\n\n for (const re of patterns) {\n const m = source.match(re);\n if (!m || m.index === undefined) continue;\n return m.index + m[0].length;\n }\n\n return null;\n}\n\n/**\n * Extract configured uilint rule IDs from source.\n * Matches keys like: \"uilint/no-arbitrary-tailwind\": \"error\"\n */\nfunction extractConfiguredUilintRuleIds(source: string): Set<string> {\n const ids = new Set<string>();\n const re = /[\"']uilint\\/([^\"']+)[\"']\\s*:/g;\n for (const m of source.matchAll(re)) {\n if (m[1]) ids.add(m[1]);\n }\n return ids;\n}\n\nfunction getMissingSelectedRules(\n selectedRules: RuleMetadata[],\n configuredIds: Set<string>\n): RuleMetadata[] {\n return selectedRules.filter((r) => !configuredIds.has(r.id));\n}\n\n/**\n * Get rules that exist but need updating (different options or severity)\n */\nfunction buildDesiredRuleValueExpression(rule: RuleMetadata): string {\n if (rule.defaultOptions && rule.defaultOptions.length > 0) {\n // Match the shape we generate elsewhere: [\"severity\", ...[options...]]\n return `[\"${rule.defaultSeverity}\", ...${JSON.stringify(\n rule.defaultOptions,\n null,\n 2\n )}]`;\n }\n return `\"${rule.defaultSeverity}\"`;\n}\n\nfunction collectUilintRuleValueNodesFromConfigArray(\n arrayExpr: any\n): Map<string, any> {\n const out = new Map<string, any>();\n if (!arrayExpr || arrayExpr.type !== \"ArrayExpression\") return out;\n\n for (const el of arrayExpr.elements ?? []) {\n if (!el || el.type !== \"ObjectExpression\") continue;\n const rules = getObjectPropertyValue(el, \"rules\");\n if (!rules || rules.type !== \"ObjectExpression\") continue;\n\n for (const prop of rules.properties ?? []) {\n if (!prop) continue;\n if (prop.type !== \"ObjectProperty\" && prop.type !== \"Property\") continue;\n const key = prop.key;\n if (!isStringLiteral(key)) continue;\n const k = key.value;\n if (typeof k !== \"string\" || !k.startsWith(\"uilint/\")) continue;\n const id = k.slice(\"uilint/\".length);\n // First occurrence wins; that's enough for detecting up-to-date configs.\n if (!out.has(id)) out.set(id, prop.value);\n }\n }\n\n return out;\n}\n\nfunction getRulesNeedingUpdate(\n selectedRules: RuleMetadata[],\n configuredIds: Set<string>,\n arrayExpr: any\n): RuleMetadata[] {\n // Only consider rules that are already configured, and only update if the\n // existing severity/options differ from what we would generate.\n const existingVals = collectUilintRuleValueNodesFromConfigArray(arrayExpr);\n\n return selectedRules.filter((r) => {\n if (!configuredIds.has(r.id)) return false;\n const existing = existingVals.get(r.id);\n if (!existing) return true;\n\n const desiredExpr = buildDesiredRuleValueExpression(r);\n const desiredAst = (parseExpression(desiredExpr) as any).$ast;\n return !astEquivalent(existing, desiredAst);\n });\n}\n\n/**\n * Generate a single rule config string\n */\nfunction generateSingleRuleConfig(rule: RuleMetadata): string {\n const ruleKey = `\"uilint/${rule.id}\"`;\n\n if (rule.defaultOptions && rule.defaultOptions.length > 0) {\n // Rule with options\n const optionsStr = JSON.stringify(rule.defaultOptions, null, 6)\n .split(\"\\n\")\n .join(\"\\n \");\n return ` ${ruleKey}: [\"${rule.defaultSeverity}\", ...${optionsStr}],`;\n } else {\n // Simple rule\n return ` ${ruleKey}: \"${rule.defaultSeverity}\",`;\n }\n}\n\n/**\n * Add the uilint import to the source if not present\n */\nfunction ensureUilintImport(source: string, isCommonJS: boolean): string {\n if (hasUilintImport(source)) {\n return source;\n }\n\n const importLine = isCommonJS\n ? `const uilint = require(\"uilint-eslint\");\\n`\n : `import uilint from \"uilint-eslint\";\\n`;\n\n // Find the last import/require statement and insert after it\n const header = source.slice(0, Math.min(source.length, 5000));\n const importRegex = isCommonJS\n ? /^(?:const|var|let)\\s+.*?=\\s*require\\([^)]+\\);?\\s*$/gm\n : /^import[\\s\\S]*?;\\s*$/gm;\n\n let lastImportEnd = -1;\n for (const m of header.matchAll(importRegex)) {\n lastImportEnd = (m.index ?? 0) + m[0].length;\n }\n\n if (lastImportEnd !== -1) {\n return (\n source.slice(0, lastImportEnd) +\n \"\\n\" +\n importLine +\n source.slice(lastImportEnd)\n );\n }\n\n // No imports found, add at the beginning\n return importLine + source;\n}\n\n/**\n * Generate the rules config object from selected rules\n */\nfunction generateRulesConfig(selectedRules: RuleMetadata[]): string {\n const lines: string[] = [];\n\n for (const rule of selectedRules) {\n const ruleKey = `\"uilint/${rule.id}\"`;\n\n if (rule.defaultOptions && rule.defaultOptions.length > 0) {\n // Rule with options\n const optionsStr = JSON.stringify(rule.defaultOptions, null, 6)\n .split(\"\\n\")\n .join(\"\\n \");\n lines.push(\n ` ${ruleKey}: [\"${rule.defaultSeverity}\", ...${optionsStr}],`\n );\n } else {\n // Simple rule\n lines.push(` ${ruleKey}: \"${rule.defaultSeverity}\",`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction detectIndent(source: string, index: number): string {\n const lineStart = source.lastIndexOf(\"\\n\", index);\n const start = lineStart === -1 ? 0 : lineStart + 1;\n const line = source.slice(start, index);\n const m = line.match(/^\\s*/);\n return m?.[0] ?? \"\";\n}\n\n/**\n * Insert missing uilint rule keys into an existing `rules: { ... }` object\n * that already contains at least one \"uilint/\" key.\n *\n * This is intentionally a best-effort string transform (no JS AST dependency).\n */\nfunction insertMissingRulesIntoExistingRulesObject(\n source: string,\n missingRules: RuleMetadata[]\n): string {\n if (missingRules.length === 0) return source;\n\n // Anchor on an existing uilint rule key, then look backwards for the\n // nearest `rules:` preceding it.\n const uilintKeyMatch = source.match(/[\"']uilint\\/[^\"']+[\"']\\s*:/);\n if (!uilintKeyMatch || uilintKeyMatch.index === undefined) return source;\n\n const uilintKeyIndex = uilintKeyMatch.index;\n const searchStart = Math.max(0, uilintKeyIndex - 4000);\n const before = source.slice(searchStart, uilintKeyIndex);\n const rulesKwIndexRel = before.lastIndexOf(\"rules\");\n if (rulesKwIndexRel === -1) return source;\n\n const rulesKwIndex = searchStart + rulesKwIndexRel;\n const braceOpenIndex = source.indexOf(\"{\", rulesKwIndex);\n if (braceOpenIndex === -1 || braceOpenIndex > uilintKeyIndex) return source;\n\n // Find the matching closing brace for the rules object.\n let depth = 0;\n let braceCloseIndex = -1;\n for (let i = braceOpenIndex; i < source.length; i++) {\n const ch = source[i];\n if (ch === \"{\") depth++;\n else if (ch === \"}\") {\n depth--;\n if (depth === 0) {\n braceCloseIndex = i;\n break;\n }\n }\n }\n if (braceCloseIndex === -1) return source;\n\n const rulesIndent = detectIndent(source, braceOpenIndex);\n const entryIndent = rulesIndent + \" \";\n const entryTextRaw = generateRulesConfig(missingRules);\n const entryText = entryTextRaw\n .split(\"\\n\")\n .map((l) => (l.trim().length === 0 ? l : entryIndent + l.trimStart()))\n .join(\"\\n\");\n\n const insertion =\n (source.slice(braceOpenIndex + 1, braceCloseIndex).trim().length === 0\n ? \"\\n\"\n : \"\\n\") +\n entryText +\n \"\\n\" +\n rulesIndent;\n\n return (\n source.slice(0, braceCloseIndex) + insertion + source.slice(braceCloseIndex)\n );\n}\n\n/**\n * Find the end of a rule value in the source code\n * Handles: \"error\", [\"error\"], [\"error\", {...}], [\"error\", ...[{...}]]\n */\nfunction findRuleValueEnd(source: string, startIndex: number): number {\n let pos = startIndex;\n let depth = 0;\n let inString = false;\n let stringChar = \"\";\n let foundArray = false;\n\n while (pos < source.length) {\n const ch = source[pos];\n const prevCh = pos > 0 ? source[pos - 1] : \"\";\n\n // Handle string literals\n if (!inString && (ch === '\"' || ch === \"'\")) {\n inString = true;\n stringChar = ch;\n } else if (inString && ch === stringChar && prevCh !== \"\\\\\") {\n inString = false;\n } else if (!inString) {\n // Track brackets/braces\n if (ch === \"[\") {\n depth++;\n foundArray = true;\n } else if (ch === \"]\") {\n depth--;\n if (depth === 0 && foundArray) {\n // Found the end of the array\n pos++;\n // Skip whitespace and include trailing comma if present\n while (pos < source.length && /\\s/.test(source[pos])) {\n pos++;\n }\n if (pos < source.length && source[pos] === \",\") {\n pos++;\n }\n return pos;\n }\n } else if (ch === \"{\" || ch === \"(\") {\n depth++;\n } else if (ch === \"}\" || ch === \")\") {\n depth--;\n } else if (!foundArray && depth === 0) {\n // Simple string value - ends at comma or closing brace\n if (ch === \",\" || ch === \"}\") {\n return pos + (ch === \",\" ? 1 : 0);\n }\n }\n }\n\n pos++;\n }\n\n return pos;\n}\n\n/**\n * Update existing uilint rule configurations with new options/severity\n *\n * This finds existing rule entries and replaces them with updated configurations.\n * Uses a more robust approach to handle multi-line rules with spread syntax.\n */\nfunction updateExistingRulesWithNewOptions(\n source: string,\n rulesToUpdate: RuleMetadata[]\n): string {\n if (rulesToUpdate.length === 0) return source;\n\n let updated = source;\n\n // Process rules in reverse order to avoid index shifting issues\n for (let i = rulesToUpdate.length - 1; i >= 0; i--) {\n const rule = rulesToUpdate[i]!;\n const ruleKeyPattern = new RegExp(\n `[\"']uilint/${rule.id.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}[\"']\\\\s*:`,\n \"g\"\n );\n\n // Find all occurrences (should only be one, but be safe)\n const matches: Array<{ index: number; length: number }> = [];\n let match;\n while ((match = ruleKeyPattern.exec(updated)) !== null) {\n if (match.index !== undefined) {\n matches.push({ index: match.index, length: match[0].length });\n }\n }\n\n // Process matches in reverse order\n for (let j = matches.length - 1; j >= 0; j--) {\n const keyMatch = matches[j]!;\n const keyStart = keyMatch.index;\n const keyEnd = keyStart + keyMatch.length;\n\n // Find the value start (after colon and whitespace)\n let valueStart = keyEnd;\n while (valueStart < updated.length && /\\s/.test(updated[valueStart])) {\n valueStart++;\n }\n\n // Find the value end\n const valueEnd = findRuleValueEnd(updated, valueStart);\n\n // Generate new rule config\n const newRuleConfig = generateSingleRuleConfig(rule);\n\n // Find the indentation of the rule key line\n const indent = detectIndent(updated, keyStart);\n\n // Replace the old rule with the new one\n const before = updated.slice(0, keyStart);\n const after = updated.slice(valueEnd);\n\n updated = before + newRuleConfig + \"\\n\" + indent + after;\n }\n }\n\n return updated;\n}\n\n/**\n * Inject uilint rules into the export default array\n */\nfunction injectUilintRules(\n source: string,\n selectedRules: RuleMetadata[]\n): { source: string; injected: boolean } {\n if (hasUilintRules(source)) {\n // Already has uilint rules - don't inject again\n return { source, injected: false };\n }\n\n const rulesConfig = generateRulesConfig(selectedRules);\n\n const configBlock = ` {\n files: [\n \"src/**/*.{js,jsx,ts,tsx}\",\n \"app/**/*.{js,jsx,ts,tsx}\",\n \"pages/**/*.{js,jsx,ts,tsx}\",\n ],\n plugins: { uilint: uilint },\n rules: {\n${rulesConfig}\n },\n },`;\n\n const arrayStart = findEsmExportedConfigArrayStartIndex(source);\n if (arrayStart === null) {\n return { source, injected: false };\n }\n\n const afterExport = source.slice(arrayStart);\n\n // Insert at the beginning of the array (after opening bracket)\n // Add a newline if the array doesn't start on a new line\n const needsNewline = !afterExport.trimStart().startsWith(\"\\n\");\n const insertion = needsNewline\n ? \"\\n\" + configBlock + \"\\n\"\n : configBlock + \"\\n\";\n\n return {\n source: source.slice(0, arrayStart) + insertion + source.slice(arrayStart),\n injected: true,\n };\n}\n\n/**\n * Inject uilint rules into the CommonJS export\n */\nfunction injectUilintRulesCommonJS(\n source: string,\n selectedRules: RuleMetadata[]\n): { source: string; injected: boolean } {\n if (hasUilintRules(source)) {\n return { source, injected: false };\n }\n\n const rulesConfig = generateRulesConfig(selectedRules);\n\n const configBlock = ` {\n files: [\n \"src/**/*.{js,jsx,ts,tsx}\",\n \"app/**/*.{js,jsx,ts,tsx}\",\n \"pages/**/*.{js,jsx,ts,tsx}\",\n ],\n plugins: { uilint: uilint },\n rules: {\n${rulesConfig}\n },\n },`;\n\n const arrayStart = findCommonJsExportedConfigArrayStartIndex(source);\n if (arrayStart === null) {\n return { source, injected: false };\n }\n\n const afterExport = source.slice(arrayStart);\n const needsNewline = !afterExport.trimStart().startsWith(\"\\n\");\n const insertion = needsNewline\n ? \"\\n\" + configBlock + \"\\n\"\n : configBlock + \"\\n\";\n\n return {\n source: source.slice(0, arrayStart) + insertion + source.slice(arrayStart),\n injected: true,\n };\n}\n\n/**\n * Install uilint-eslint into eslint config\n */\nexport async function installEslintPlugin(\n opts: InstallEslintPluginOptions\n): Promise<{\n configFile: string | null;\n modified: boolean;\n missingRuleIds: string[];\n configured: boolean;\n error?: string;\n}> {\n const configPath = findEslintConfigFile(opts.projectPath);\n\n if (!configPath) {\n return {\n configFile: null,\n modified: false,\n missingRuleIds: [],\n configured: false,\n };\n }\n\n const configFilename = getEslintConfigFilename(configPath);\n const original = readFileSync(configPath, \"utf-8\");\n const isCommonJS = configPath.endsWith(\".cjs\");\n\n const ast = getUilintEslintConfigInfoFromSourceAst(original);\n if (\"error\" in ast) {\n return {\n configFile: configFilename,\n modified: false,\n missingRuleIds: [],\n configured: false,\n error: ast.error,\n };\n }\n\n const { info, mod, arrayExpr, kind } = ast;\n const configuredIds = info.configuredRuleIds;\n\n const missingRules = getMissingSelectedRules(\n opts.selectedRules,\n configuredIds\n );\n const rulesToUpdate = getRulesNeedingUpdate(\n opts.selectedRules,\n configuredIds,\n arrayExpr\n );\n\n // Decide what rules to apply, respecting prompts.\n let rulesToApply: RuleMetadata[] = [];\n if (!info.configured) {\n rulesToApply = opts.selectedRules;\n } else {\n // When already configured, we only apply updates + missing rules.\n rulesToApply = [...missingRules, ...rulesToUpdate];\n if (missingRules.length > 0 && !opts.force) {\n const ok = await opts.confirmAddMissingRules?.(\n configFilename,\n missingRules\n );\n if (!ok) {\n return {\n configFile: configFilename,\n modified: false,\n missingRuleIds: missingRules.map((r) => r.id),\n configured: true,\n };\n }\n }\n }\n\n if (rulesToApply.length === 0) {\n return {\n configFile: configFilename,\n modified: false,\n missingRuleIds: missingRules.map((r) => r.id),\n configured: info.configured,\n };\n }\n\n let modifiedAst = false;\n\n // Check if .uilint/rules/ directory exists alongside this target package/app.\n // (Also allow a fallback to workspace root for backwards compatibility.)\n const localRulesDir = join(opts.projectPath, \".uilint\", \"rules\");\n const workspaceRoot = findWorkspaceRoot(opts.projectPath);\n const workspaceRulesDir = join(workspaceRoot, \".uilint\", \"rules\");\n\n const rulesRoot = existsSync(localRulesDir)\n ? opts.projectPath\n : workspaceRoot;\n\n // Always use local rules (they should have been copied by the plan phase)\n // Detect file extension by checking what files exist\n let fileExtension = \".js\";\n if (rulesToApply.length > 0) {\n const firstRulePath = join(\n rulesRoot,\n \".uilint\",\n \"rules\",\n `${rulesToApply[0]!.id}.ts`\n );\n if (existsSync(firstRulePath)) {\n fileExtension = \".ts\";\n }\n }\n\n let ruleImportNames: Map<string, string> | undefined;\n\n // Add imports for local rules\n if (kind === \"esm\") {\n const result = addLocalRuleImportsAst(\n mod,\n rulesToApply,\n configPath,\n rulesRoot,\n fileExtension\n );\n ruleImportNames = result.importNames;\n if (result.changed) modifiedAst = true;\n } else {\n const result = addLocalRuleRequiresAst(\n mod.$ast,\n rulesToApply,\n configPath,\n rulesRoot,\n fileExtension\n );\n ruleImportNames = result.importNames;\n if (result.changed) modifiedAst = true;\n }\n\n // Add config block with local rules\n if (ruleImportNames && ruleImportNames.size > 0) {\n appendUilintConfigBlockToArray(arrayExpr, rulesToApply, ruleImportNames);\n modifiedAst = true;\n }\n\n // Ensure uilint-eslint import for utilities (createRule, etc.)\n if (!info.configured) {\n if (kind === \"esm\") {\n // Import createRule utility from uilint-eslint\n mod.imports.$add({\n imported: \"createRule\",\n local: \"createRule\",\n from: \"uilint-eslint\",\n });\n modifiedAst = true;\n } else {\n // CommonJS: add require for createRule\n const stmtMod = parseModule(\n `const { createRule } = require(\"uilint-eslint\");`\n );\n const stmt = (stmtMod.$ast as any).body?.[0];\n if (stmt) {\n let insertAt = 0;\n const first = mod.$ast.body?.[0];\n if (\n first?.type === \"ExpressionStatement\" &&\n first.expression?.type === \"StringLiteral\" &&\n first.expression.value === \"use strict\"\n ) {\n insertAt = 1;\n }\n mod.$ast.body.splice(insertAt, 0, stmt);\n modifiedAst = true;\n }\n }\n }\n\n const updated = modifiedAst ? generateCode(mod).code : original;\n\n if (updated !== original) {\n writeFileSync(configPath, updated, \"utf-8\");\n return {\n configFile: configFilename,\n modified: true,\n missingRuleIds: missingRules.map((r) => r.id),\n configured: getUilintEslintConfigInfoFromSource(updated).configured,\n };\n }\n\n return {\n configFile: configFilename,\n modified: false,\n missingRuleIds: missingRules.map((r) => r.id),\n configured: getUilintEslintConfigInfoFromSource(updated).configured,\n };\n}\n","/**\n * Plan phase - pure function generating InstallPlan from state + choices\n *\n * This function has NO I/O whatsoever. It takes the analyzed ProjectState,\n * user choices, and options, then returns an InstallPlan describing exactly\n * what actions to take.\n */\n\nimport { join } from \"path\";\nimport { createRequire } from \"module\";\nimport type { RuleMetadata } from \"uilint-eslint\";\nimport type {\n ProjectState,\n UserChoices,\n InstallPlan,\n InstallAction,\n DependencyInstall,\n PlanOptions,\n} from \"./types.js\";\nimport {\n GENSTYLEGUIDE_COMMAND_MD,\n} from \"./constants.js\";\nimport { loadSkill } from \"../../utils/skill-loader.js\";\nimport { loadSelectedRules } from \"../../utils/rule-loader.js\";\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Get the version range for a dependency from uilint's package.json\n */\nfunction getSelfDependencyVersionRange(pkgName: string): string | null {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const pkgJson = require(\"uilint/package.json\") as Record<string, unknown>;\n const deps = pkgJson?.dependencies as Record<string, string> | undefined;\n const optDeps = pkgJson?.optionalDependencies as\n | Record<string, string>\n | undefined;\n const peerDeps = pkgJson?.peerDependencies as\n | Record<string, string>\n | undefined;\n const v = deps?.[pkgName] ?? optDeps?.[pkgName] ?? peerDeps?.[pkgName];\n return typeof v === \"string\" ? v : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Convert package name to install specifier with version\n */\nfunction toInstallSpecifier(pkgName: string): string {\n const range = getSelfDependencyVersionRange(pkgName);\n if (!range) return pkgName;\n if (range.startsWith(\"workspace:\")) return pkgName;\n if (range.startsWith(\"file:\")) return pkgName;\n if (range.startsWith(\"link:\")) return pkgName;\n return `${pkgName}@${range}`;\n}\n\n/**\n * Create the install plan from project state and user choices\n *\n * @param state - The analyzed project state\n * @param choices - User's installation choices\n * @param options - Planning options (force, etc.)\n * @returns InstallPlan with all actions and dependencies\n */\nexport function createPlan(\n state: ProjectState,\n choices: UserChoices,\n options: PlanOptions = {}\n): InstallPlan {\n const actions: InstallAction[] = [];\n const dependencies: DependencyInstall[] = [];\n\n const { force = false } = options;\n const { items } = choices;\n\n // Ensure .cursor directory exists if needed\n const needsCursorDir =\n items.includes(\"genstyleguide\") ||\n items.includes(\"skill\");\n\n if (needsCursorDir && !state.cursorDir.exists) {\n actions.push({\n type: \"create_directory\",\n path: state.cursorDir.path,\n });\n }\n\n // =========================================================================\n // Genstyleguide Command\n // =========================================================================\n if (items.includes(\"genstyleguide\")) {\n const commandsDir = join(state.cursorDir.path, \"commands\");\n\n actions.push({\n type: \"create_directory\",\n path: commandsDir,\n });\n\n actions.push({\n type: \"create_file\",\n path: join(commandsDir, \"genstyleguide.md\"),\n content: GENSTYLEGUIDE_COMMAND_MD,\n });\n }\n\n // =========================================================================\n // Agent Skill Installation\n // =========================================================================\n if (items.includes(\"skill\")) {\n const skillsDir = join(state.cursorDir.path, \"skills\");\n\n // Create skills directory\n actions.push({\n type: \"create_directory\",\n path: skillsDir,\n });\n\n // Load and install the ui-consistency-enforcer skill\n try {\n const skill = loadSkill(\"ui-consistency-enforcer\");\n const skillDir = join(skillsDir, skill.name);\n\n // Create skill directory\n actions.push({\n type: \"create_directory\",\n path: skillDir,\n });\n\n // Create all skill files\n for (const file of skill.files) {\n const filePath = join(skillDir, file.relativePath);\n\n // Ensure subdirectories exist (e.g., references/)\n const fileDir = join(\n skillDir,\n file.relativePath.split(\"/\").slice(0, -1).join(\"/\")\n );\n if (fileDir !== skillDir && file.relativePath.includes(\"/\")) {\n actions.push({\n type: \"create_directory\",\n path: fileDir,\n });\n }\n\n actions.push({\n type: \"create_file\",\n path: filePath,\n content: file.content,\n });\n }\n } catch {\n // Skill not found - skip silently (shouldn't happen in normal install)\n }\n }\n\n // =========================================================================\n // Next.js Overlay Installation\n // =========================================================================\n if (items.includes(\"next\") && choices.next) {\n const { projectPath, detection } = choices.next;\n\n // Install Next.js routes\n actions.push({\n type: \"install_next_routes\",\n projectPath,\n appRoot: detection.appRoot,\n });\n\n // Install React overlay dependencies\n dependencies.push({\n packagePath: projectPath,\n packageManager: state.packageManager,\n packages: [\"uilint-react\", \"uilint-core\", \"jsx-loc-plugin\"],\n });\n\n // Inject <uilint-devtools /> web component into React\n actions.push({\n type: \"inject_react\",\n projectPath,\n appRoot: detection.appRoot,\n });\n\n // Inject jsx-loc-plugin into next.config\n actions.push({\n type: \"inject_next_config\",\n projectPath,\n });\n }\n\n // =========================================================================\n // Vite Overlay Installation\n // =========================================================================\n if (items.includes(\"vite\") && choices.vite) {\n const { projectPath, detection } = choices.vite;\n\n // Install React overlay dependencies\n dependencies.push({\n packagePath: projectPath,\n packageManager: state.packageManager,\n packages: [\"uilint-react\", \"uilint-core\", \"jsx-loc-plugin\"],\n });\n\n // Inject <uilint-devtools /> web component into React entry\n actions.push({\n type: \"inject_react\",\n projectPath,\n appRoot: detection.entryRoot,\n mode: \"vite\",\n });\n\n // Inject jsx-loc-plugin into vite.config\n actions.push({\n type: \"inject_vite_config\",\n projectPath,\n });\n }\n\n // =========================================================================\n // ESLint Plugin Installation\n // =========================================================================\n if (items.includes(\"eslint\") && choices.eslint) {\n const { packagePaths, selectedRules } = choices.eslint;\n\n for (const pkgPath of packagePaths) {\n const pkgInfo = state.packages.find((p) => p.path === pkgPath);\n\n // Create .uilint/rules directory alongside the target app (not at workspace root)\n const rulesDir = join(pkgPath, \".uilint\", \"rules\");\n actions.push({\n type: \"create_directory\",\n path: rulesDir,\n });\n\n // Load and copy rule files into this target package\n // Detect if this package uses TypeScript\n const isTypeScript = pkgInfo?.isTypeScript ?? true; // Default to TypeScript for safety\n const ruleFiles = loadSelectedRules(\n selectedRules.map((r) => r.id),\n {\n typescript: isTypeScript,\n }\n );\n for (const ruleFile of ruleFiles) {\n // Copy implementation file\n actions.push({\n type: \"create_file\",\n path: join(rulesDir, ruleFile.implementation.relativePath),\n content: ruleFile.implementation.content,\n });\n\n // Copy test file if it exists (only for TypeScript projects)\n if (ruleFile.test && isTypeScript) {\n actions.push({\n type: \"create_file\",\n path: join(rulesDir, ruleFile.test.relativePath),\n content: ruleFile.test.content,\n });\n }\n }\n\n // Install dependencies (still needed for utilities like createRule)\n dependencies.push({\n packagePath: pkgPath,\n packageManager: state.packageManager,\n packages: [toInstallSpecifier(\"uilint-eslint\"), \"typescript-eslint\"],\n });\n\n // Inject ESLint rules (will reference local .uilint/rules/ files)\n if (pkgInfo?.eslintConfigPath) {\n actions.push({\n type: \"inject_eslint\",\n packagePath: pkgPath,\n configPath: pkgInfo.eslintConfigPath,\n rules: selectedRules,\n hasExistingRules: pkgInfo.hasUilintRules,\n });\n }\n }\n\n // Add .uilint/.cache to .gitignore at workspace root\n const gitignorePath = join(state.workspaceRoot, \".gitignore\");\n actions.push({\n type: \"append_to_file\",\n path: gitignorePath,\n content: \"\\n# UILint cache\\n.uilint/.cache\\n\",\n ifNotContains: \".uilint/.cache\",\n });\n }\n\n return { actions, dependencies };\n}\n\n/**\n * Get the list of rules that are missing from a package's ESLint config\n */\nexport function getMissingRules(\n configuredRuleIds: string[],\n selectedRules: RuleMetadata[]\n): RuleMetadata[] {\n const configuredSet = new Set(configuredRuleIds);\n return selectedRules.filter((rule) => !configuredSet.has(rule.id));\n}\n","/**\n * Constants for the install command\n *\n * Contains file content templates for commands.\n */\n\n// ============================================================================\n// Cursor Commands\n// ============================================================================\n\nexport const GENSTYLEGUIDE_COMMAND_MD = `# React Style Guide Generator\n\nAnalyze the React UI codebase to produce a **prescriptive, semantic** style guide. Focus on consistency, intent, and relationships—not specific values.\n\n## Philosophy\n\n1. **Identify the intended architecture** from the best patterns in use\n2. **Prescribe semantic rules** — about consistency and relationships, not pixels\n3. **Stay general** — \"primary buttons should be visually consistent\" not \"buttons use px-4\"\n4. **Focus on intent** — what should FEEL the same, not what values to use\n\n## Analysis Steps\n\n### 1. Detect the Stack\n- Framework: Next.js (App Router? Pages?), Vite, CRA\n- Component system: shadcn, MUI, Chakra, Radix, custom\n- Styling: Tailwind, CSS Modules, styled-components\n- Forms: react-hook-form, Formik, native\n- State: React context, Zustand, Redux, Jotai\n\n### 2. Identify Best Patterns\nExamine the **best-written** components. Look at:\n- \\`components/ui/*\\` — the design system\n- Recently modified files — current standards\n- Shared layouts — structural patterns\n\n### 3. Infer Visual Hierarchy & Intent\nUnderstand the design language:\n- What distinguishes primary vs secondary actions?\n- How is visual hierarchy established?\n- What creates consistency across similar elements?\n\n## Output Format\n\nGenerate at \\`<nextjs app root>/.uilint/styleguide.md\\`:\n\\`\\`\\`yaml\n# Stack\nframework: \nstyling: \ncomponents: \ncomponent_path: \nforms: \n\n# Component Usage (MUST use these)\nuse:\n buttons: \n inputs: \n modals: \n cards: \n feedback: \n icons: \n links: \n\n# Semantic Rules (consistency & relationships)\nsemantics:\n hierarchy:\n - <e.g., \"primary actions must be visually distinct from secondary\">\n - <e.g., \"destructive actions should be visually cautionary\">\n - <e.g., \"page titles should be visually heavier than section titles\">\n consistency:\n - <e.g., \"all primary buttons should share the same visual weight\">\n - <e.g., \"form inputs should have uniform height and padding\">\n - <e.g., \"card padding should be consistent across the app\">\n - <e.g., \"interactive elements should have consistent hover/focus states\">\n spacing:\n - <e.g., \"use the spacing scale — no arbitrary values\">\n - <e.g., \"related elements should be closer than unrelated\">\n - <e.g., \"section spacing should be larger than element spacing\">\n layout:\n - <e.g., \"use gap for sibling spacing, not margin\">\n - <e.g., \"containers should have consistent max-width and padding\">\n\n# Patterns (structural, not values)\npatterns:\n forms: <e.g., \"FormField + Controller + zod schema\">\n conditionals: <e.g., \"cn() for class merging\">\n loading: <e.g., \"Skeleton for content, Spinner for actions\">\n errors: <e.g., \"ErrorBoundary at route, inline for forms\">\n responsive: <e.g., \"mobile-first, standard breakpoints only\">\n\n# Component Authoring\nauthoring:\n - <e.g., \"forwardRef for interactive components\">\n - <e.g., \"variants via CVA or component props, not className overrides\">\n - <e.g., \"extract when used 2+ times\">\n - <e.g., \"'use client' only when needed\">\n\n# Forbidden\nforbidden:\n - <e.g., \"inline style={{}}\">\n - <e.g., \"raw HTML elements when component exists\">\n - <e.g., \"arbitrary values — use scale\">\n - <e.g., \"className overrides that break visual consistency\">\n - <e.g., \"one-off spacing that doesn't match siblings\">\n\n# Legacy (if migration in progress)\nlegacy:\n - <e.g., \"old: CSS modules → new: Tailwind\">\n - <e.g., \"old: Formik → new: react-hook-form\">\n\n# Conventions\nconventions:\n - \n - \n - \n\\`\\`\\`\n\n## Rules\n\n- **Semantic over specific**: \"consistent padding\" not \"p-4\"\n- **Relationships over absolutes**: \"heavier than\" not \"font-bold\"\n- **Intent over implementation**: \"visually distinct\" not \"blue background\"\n- **Prescriptive**: Define target state, not current state\n- **Terse**: No prose. Fragments and short phrases only.\n- **Actionable**: Every rule should be human-verifiable\n- **Omit if N/A**: Skip sections that don't apply\n- **Max 5 items** per section — highest impact only\n`;\n\n","/**\n * Skill Loader Utility\n *\n * Loads Agent Skill files from the bundled skills directory for installation\n * into user projects. Skills follow the Agent Skills specification\n * (agentskills.io).\n */\n\nimport { readFileSync, readdirSync, statSync, existsSync } from \"fs\";\nimport { join, dirname, relative } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Represents a file in a skill directory\n */\nexport interface SkillFile {\n /** Relative path within the skill directory */\n relativePath: string;\n /** File content */\n content: string;\n}\n\n/**\n * Represents a complete skill ready for installation\n */\nexport interface Skill {\n /** Skill name (directory name) */\n name: string;\n /** All files in the skill */\n files: SkillFile[];\n}\n\n/**\n * Get the path to the bundled skills directory\n */\nfunction getSkillsDir(): string {\n // In development: packages/uilint/skills/\n // In production (installed): node_modules/uilint/dist/ -> ../skills/\n const devPath = join(__dirname, \"..\", \"..\", \"skills\");\n const prodPath = join(__dirname, \"..\", \"skills\");\n\n if (existsSync(devPath)) {\n return devPath;\n }\n if (existsSync(prodPath)) {\n return prodPath;\n }\n\n throw new Error(\n \"Could not find skills directory. This is a bug in uilint installation.\"\n );\n}\n\n/**\n * Recursively collect all files in a directory\n */\nfunction collectFiles(dir: string, baseDir: string): SkillFile[] {\n const files: SkillFile[] = [];\n const entries = readdirSync(dir);\n\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const stat = statSync(fullPath);\n\n if (stat.isDirectory()) {\n files.push(...collectFiles(fullPath, baseDir));\n } else if (stat.isFile()) {\n const relativePath = relative(baseDir, fullPath);\n const content = readFileSync(fullPath, \"utf-8\");\n files.push({ relativePath, content });\n }\n }\n\n return files;\n}\n\n/**\n * Load a specific skill by name\n */\nexport function loadSkill(name: string): Skill {\n const skillsDir = getSkillsDir();\n const skillDir = join(skillsDir, name);\n\n if (!existsSync(skillDir)) {\n throw new Error(`Skill \"${name}\" not found in ${skillsDir}`);\n }\n\n const skillMdPath = join(skillDir, \"SKILL.md\");\n if (!existsSync(skillMdPath)) {\n throw new Error(`Skill \"${name}\" is missing SKILL.md`);\n }\n\n const files = collectFiles(skillDir, skillDir);\n\n return { name, files };\n}\n\n/**\n * Load all available skills\n */\nexport function loadAllSkills(): Skill[] {\n const skillsDir = getSkillsDir();\n const entries = readdirSync(skillsDir);\n const skills: Skill[] = [];\n\n for (const entry of entries) {\n const skillDir = join(skillsDir, entry);\n const stat = statSync(skillDir);\n\n if (stat.isDirectory()) {\n const skillMdPath = join(skillDir, \"SKILL.md\");\n if (existsSync(skillMdPath)) {\n skills.push(loadSkill(entry));\n }\n }\n }\n\n return skills;\n}\n\n/**\n * Get the list of available skill names\n */\nexport function getAvailableSkillNames(): string[] {\n const skillsDir = getSkillsDir();\n const entries = readdirSync(skillsDir);\n const names: string[] = [];\n\n for (const entry of entries) {\n const skillDir = join(skillsDir, entry);\n const stat = statSync(skillDir);\n\n if (stat.isDirectory()) {\n const skillMdPath = join(skillDir, \"SKILL.md\");\n if (existsSync(skillMdPath)) {\n names.push(entry);\n }\n }\n }\n\n return names;\n}\n","/**\n * Rule Loader Utility\n *\n * Loads ESLint rule source files from the uilint-eslint package for installation\n * into user projects. Rules are copied to .uilint/rules/ in the target project.\n */\n\nimport { readFileSync, existsSync } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { createRequire } from \"module\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst require = createRequire(import.meta.url);\n\nfunction findNodeModulesPackageRoot(\n pkgName: string,\n startDir: string\n): string | null {\n let dir = startDir;\n while (true) {\n const candidate = join(dir, \"node_modules\", pkgName);\n if (existsSync(join(candidate, \"package.json\"))) return candidate;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nfunction getUilintEslintPackageRoot(): string {\n // Prefer a filesystem-based lookup first. This avoids Node resolution edge\n // cases with package.json \"exports\" (especially ESM-only packages), and works\n // well for monorepos + pnpm where node_modules contains symlinks.\n //\n // Search upwards from process.cwd() (the user's project) and from this file\n // location (for test/dev environments).\n const fromCwd = findNodeModulesPackageRoot(\"uilint-eslint\", process.cwd());\n if (fromCwd) return fromCwd;\n\n const fromHere = findNodeModulesPackageRoot(\"uilint-eslint\", __dirname);\n if (fromHere) return fromHere;\n\n // Last resort: try resolver-based lookup.\n try {\n const entry = require.resolve(\"uilint-eslint\"); // typically .../dist/index.js\n const entryDir = dirname(entry); // typically .../dist\n return dirname(entryDir); // package root\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(\n `Unable to locate uilint-eslint in node_modules (searched upwards from cwd and uilint's install path).\\n` +\n `Resolver error: ${msg}\\n` +\n `Fix: ensure uilint-eslint is installed in the target project (or workspace) and try again.`\n );\n }\n}\n\n/**\n * Represents a file for a rule (implementation or test)\n */\nexport interface RuleFile {\n /** Relative path within the rules directory (e.g., \"no-arbitrary-tailwind.ts\") */\n relativePath: string;\n /** File content */\n content: string;\n}\n\n/**\n * Represents a complete rule ready for installation\n */\nexport interface RuleFiles {\n /** Rule identifier (e.g., \"no-arbitrary-tailwind\") */\n ruleId: string;\n /** Implementation file */\n implementation: RuleFile;\n /** Test file (if exists) */\n test?: RuleFile;\n}\n\n/**\n * Get the path to the uilint-eslint package source directory\n */\nfunction getUilintEslintSrcDir(): string {\n // In development: packages/uilint-eslint/src/\n // In production (installed): node_modules/uilint-eslint/src/\n\n // Try workspace/dev path first (repo layout)\n const devPath = join(\n __dirname,\n \"..\",\n \"..\",\n \"..\",\n \"..\",\n \"uilint-eslint\",\n \"src\"\n );\n if (existsSync(devPath)) return devPath;\n\n // Try from installed package root (works with \"exports\")\n const pkgRoot = getUilintEslintPackageRoot();\n const srcPath = join(pkgRoot, \"src\");\n if (existsSync(srcPath)) return srcPath;\n\n throw new Error(\n 'Could not find uilint-eslint \"src/\" directory. If you are using a published install of uilint-eslint, ensure it includes source files, or run a JS-only rules install.'\n );\n}\n\n/**\n * Get the path to the uilint-eslint package dist directory\n */\nfunction getUilintEslintDistDir(): string {\n // In development: packages/uilint-eslint/dist/\n // In production (installed): node_modules/uilint-eslint/dist/\n\n // Try workspace/dev path first (repo layout)\n const devPath = join(\n __dirname,\n \"..\",\n \"..\",\n \"..\",\n \"..\",\n \"uilint-eslint\",\n \"dist\"\n );\n if (existsSync(devPath)) return devPath;\n\n // Try from installed package root (works with \"exports\")\n const pkgRoot = getUilintEslintPackageRoot();\n const distPath = join(pkgRoot, \"dist\");\n if (existsSync(distPath)) return distPath;\n\n throw new Error(\n 'Could not find uilint-eslint \"dist/\" directory. This is a bug in uilint installation.'\n );\n}\n\n/**\n * Transform rule content to fix imports for copied location\n * Changes imports from \"../utils/create-rule.js\" to \"uilint-eslint\"\n */\nfunction transformRuleContent(content: string): string {\n // Replace relative imports to utils with uilint-eslint imports\n // Pattern: import { ... } from \"../utils/create-rule.js\" or similar\n let transformed = content;\n\n // Replace: import { createRule } from \"../utils/create-rule.js\"\n transformed = transformed.replace(\n /import\\s+{\\s*createRule\\s*}\\s+from\\s+[\"']\\.\\.\\/utils\\/create-rule\\.js[\"'];?/g,\n 'import { createRule } from \"uilint-eslint\";'\n );\n\n // Replace: import createRule from \"../utils/create-rule.js\"\n transformed = transformed.replace(\n /import\\s+createRule\\s+from\\s+[\"']\\.\\.\\/utils\\/create-rule\\.js[\"'];?/g,\n 'import { createRule } from \"uilint-eslint\";'\n );\n\n // Replace other utility imports (cache, styleguide-loader, etc.)\n transformed = transformed.replace(\n /import\\s+{([^}]+)}\\s+from\\s+[\"']\\.\\.\\/utils\\/([^\"']+)\\.js[\"'];?/g,\n (match, imports, utilFile) => {\n // Check if it's a utility that's exported from uilint-eslint\n const utilsFromPackage = [\"cache\", \"styleguide-loader\", \"import-graph\"];\n if (utilsFromPackage.includes(utilFile)) {\n return `import {${imports}} from \"uilint-eslint\";`;\n }\n return match; // Keep original if not a known utility\n }\n );\n\n return transformed;\n}\n\n/**\n * Load a specific rule by ID\n */\nexport function loadRule(\n ruleId: string,\n options: { typescript: boolean } = { typescript: true }\n): RuleFiles {\n const { typescript } = options;\n const extension = typescript ? \".ts\" : \".js\";\n\n if (typescript) {\n // Load TypeScript source files\n const rulesDir = join(getUilintEslintSrcDir(), \"rules\");\n const implPath = join(rulesDir, `${ruleId}.ts`);\n const testPath = join(rulesDir, `${ruleId}.test.ts`);\n\n if (!existsSync(implPath)) {\n throw new Error(`Rule \"${ruleId}\" not found at ${implPath}`);\n }\n\n const rawContent = readFileSync(implPath, \"utf-8\");\n const transformedContent = transformRuleContent(rawContent);\n\n const implementation: RuleFile = {\n relativePath: `${ruleId}.ts`,\n content: transformedContent,\n };\n\n const test: RuleFile | undefined = existsSync(testPath)\n ? {\n relativePath: `${ruleId}.test.ts`,\n content: transformRuleContent(readFileSync(testPath, \"utf-8\")),\n }\n : undefined;\n\n return {\n ruleId,\n implementation,\n test,\n };\n } else {\n // Load compiled JavaScript files\n const rulesDir = join(getUilintEslintDistDir(), \"rules\");\n const implPath = join(rulesDir, `${ruleId}.js`);\n\n if (!existsSync(implPath)) {\n throw new Error(\n `Rule \"${ruleId}\" not found at ${implPath}. ` +\n `For JavaScript-only projects, uilint-eslint must be built to include compiled rule files in dist/rules/. ` +\n `If you're developing uilint-eslint, run 'pnpm build' in packages/uilint-eslint. ` +\n `If you're using a published package, ensure it includes the dist/ directory.`\n );\n }\n\n // Compiled JS files don't need transformation - they already use uilint-eslint imports\n const content = readFileSync(implPath, \"utf-8\");\n\n const implementation: RuleFile = {\n relativePath: `${ruleId}.js`,\n content,\n };\n\n // Test files are not compiled, so we don't copy them for JS projects\n return {\n ruleId,\n implementation,\n };\n }\n}\n\n/**\n * Load multiple rules by their IDs\n */\nexport function loadSelectedRules(\n ruleIds: string[],\n options: { typescript: boolean } = { typescript: true }\n): RuleFiles[] {\n return ruleIds.map((id) => loadRule(id, options));\n}\n\n/**\n * Get the list of available rule IDs from the registry\n */\nexport function getAvailableRuleIds(): string[] {\n try {\n // Import the rule registry from uilint-eslint\n const { ruleRegistry } = require(\"uilint-eslint\");\n return ruleRegistry.map((rule: { id: string }) => rule.id);\n } catch {\n // Fallback: try to read from filesystem\n const rulesDir = join(getUilintEslintSrcDir(), \"rules\");\n if (!existsSync(rulesDir)) {\n return [];\n }\n\n // This is a fallback - ideally we'd use the registry\n // But if we can't import it, we can at least try to list files\n const fs = require(\"fs\");\n const files = fs.readdirSync(rulesDir);\n return files\n .filter((f: string) => f.endsWith(\".ts\") && !f.endsWith(\".test.ts\"))\n .map((f: string) => f.replace(\".ts\", \"\"));\n }\n}\n","/**\n * Execute phase - perform side effects from InstallPlan\n *\n * This module takes an InstallPlan and performs all the actual file operations,\n * dependency installations, and config modifications.\n */\n\nimport {\n existsSync,\n mkdirSync,\n writeFileSync,\n readFileSync,\n unlinkSync,\n chmodSync,\n} from \"fs\";\nimport { dirname } from \"path\";\nimport type {\n InstallPlan,\n InstallAction,\n InstallResult,\n ActionResult,\n DependencyResult,\n InstallSummary,\n ExecuteOptions,\n InjectEslintAction,\n InjectReactAction,\n InjectNextConfigAction,\n InjectViteConfigAction,\n InstallNextRoutesAction,\n} from \"./types.js\";\nimport { installDependencies as defaultInstallDependencies } from \"../../utils/package-manager.js\";\nimport { installEslintPlugin } from \"../../utils/eslint-config-inject.js\";\nimport { installReactUILintOverlay } from \"../../utils/react-inject.js\";\nimport { installJsxLocPlugin } from \"../../utils/next-config-inject.js\";\nimport { installViteJsxLocPlugin } from \"../../utils/vite-config-inject.js\";\nimport { installNextUILintRoutes } from \"../../utils/next-routes.js\";\n\n/**\n * Execute a single action and return the result\n */\nasync function executeAction(\n action: InstallAction,\n options: ExecuteOptions\n): Promise<ActionResult> {\n const { dryRun = false } = options;\n\n try {\n switch (action.type) {\n case \"create_directory\": {\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Create directory: ${action.path}`,\n };\n }\n if (!existsSync(action.path)) {\n mkdirSync(action.path, { recursive: true });\n }\n return { action, success: true };\n }\n\n case \"create_file\": {\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Create file: ${action.path}${\n action.permissions\n ? ` (mode: ${action.permissions.toString(8)})`\n : \"\"\n }`,\n };\n }\n // Ensure parent directory exists\n const dir = dirname(action.path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(action.path, action.content, \"utf-8\");\n if (action.permissions) {\n chmodSync(action.path, action.permissions);\n }\n return { action, success: true };\n }\n\n case \"merge_json\": {\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Merge JSON into: ${action.path}`,\n };\n }\n let existing: Record<string, unknown> = {};\n if (existsSync(action.path)) {\n try {\n existing = JSON.parse(readFileSync(action.path, \"utf-8\"));\n } catch {\n // Start fresh if parse fails\n }\n }\n const merged = deepMerge(existing, action.merge);\n // Ensure parent directory exists\n const dir = dirname(action.path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(action.path, JSON.stringify(merged, null, 2), \"utf-8\");\n return { action, success: true };\n }\n\n case \"delete_file\": {\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Delete file: ${action.path}`,\n };\n }\n if (existsSync(action.path)) {\n unlinkSync(action.path);\n }\n return { action, success: true };\n }\n\n case \"append_to_file\": {\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Append to file: ${action.path}`,\n };\n }\n if (existsSync(action.path)) {\n const content = readFileSync(action.path, \"utf-8\");\n if (action.ifNotContains && content.includes(action.ifNotContains)) {\n // Already contains the content, skip\n return { action, success: true };\n }\n writeFileSync(action.path, content + action.content, \"utf-8\");\n }\n // If file doesn't exist, skip (don't create .gitignore from scratch)\n return { action, success: true };\n }\n\n case \"inject_eslint\": {\n return await executeInjectEslint(action, options);\n }\n\n case \"inject_react\": {\n return await executeInjectReact(action, options);\n }\n\n case \"inject_next_config\": {\n return await executeInjectNextConfig(action, options);\n }\n\n case \"inject_vite_config\": {\n return await executeInjectViteConfig(action, options);\n }\n\n case \"install_next_routes\": {\n return await executeInstallNextRoutes(action, options);\n }\n\n default: {\n // Exhaustiveness check\n const _exhaustive: never = action;\n return {\n action: _exhaustive,\n success: false,\n error: `Unknown action type`,\n };\n }\n }\n } catch (error) {\n return {\n action,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Execute ESLint injection\n */\nasync function executeInjectEslint(\n action: InjectEslintAction,\n options: ExecuteOptions\n): Promise<ActionResult> {\n const { dryRun = false } = options;\n\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Inject ESLint rules into: ${action.configPath}`,\n };\n }\n\n // Use the existing installEslintPlugin function\n // It handles all the complexity of parsing and modifying the config\n const result = await installEslintPlugin({\n projectPath: action.packagePath,\n selectedRules: action.rules,\n force: !action.hasExistingRules, // Don't force if already has rules\n // Auto-confirm for execute phase (choices were made during planning)\n confirmAddMissingRules: async () => true,\n });\n\n return {\n action,\n success: result.configFile !== null && result.configured,\n error:\n result.configFile === null\n ? \"No ESLint config found\"\n : result.configured\n ? undefined\n : result.error ?? \"Failed to configure uilint in ESLint config\",\n };\n}\n\n/**\n * Execute React overlay injection\n */\nasync function executeInjectReact(\n action: InjectReactAction,\n options: ExecuteOptions\n): Promise<ActionResult> {\n const { dryRun = false } = options;\n\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Inject <uilint-devtools /> into React app: ${action.projectPath}`,\n };\n }\n\n const result = await installReactUILintOverlay({\n projectPath: action.projectPath,\n appRoot: action.appRoot,\n mode: action.mode,\n force: false,\n // Auto-select first choice for execute phase\n confirmFileChoice: async (choices) => choices[0],\n });\n\n // Success if modified OR already configured (goal achieved either way)\n const success = result.modified || result.alreadyConfigured === true;\n\n return {\n action,\n success,\n error: success ? undefined : \"Failed to configure React overlay\",\n };\n}\n\n/**\n * Execute Vite config injection\n */\nasync function executeInjectViteConfig(\n action: InjectViteConfigAction,\n options: ExecuteOptions\n): Promise<ActionResult> {\n const { dryRun = false } = options;\n\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Inject jsx-loc-plugin into vite.config: ${action.projectPath}`,\n };\n }\n\n const result = await installViteJsxLocPlugin({\n projectPath: action.projectPath,\n force: false,\n });\n\n return {\n action,\n success: result.modified || result.configFile !== null,\n error: result.configFile === null ? \"No vite.config found\" : undefined,\n };\n}\n\n/**\n * Execute Next.js config injection\n */\nasync function executeInjectNextConfig(\n action: InjectNextConfigAction,\n options: ExecuteOptions\n): Promise<ActionResult> {\n const { dryRun = false } = options;\n\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Inject jsx-loc-plugin into next.config: ${action.projectPath}`,\n };\n }\n\n const result = await installJsxLocPlugin({\n projectPath: action.projectPath,\n force: false,\n });\n\n return {\n action,\n success: result.modified || result.configFile !== null,\n error: result.configFile === null ? \"No next.config found\" : undefined,\n };\n}\n\n/**\n * Execute Next.js routes installation\n */\nasync function executeInstallNextRoutes(\n action: InstallNextRoutesAction,\n options: ExecuteOptions\n): Promise<ActionResult> {\n const { dryRun = false } = options;\n\n if (dryRun) {\n return {\n action,\n success: true,\n wouldDo: `Install Next.js API routes: ${action.projectPath}`,\n };\n }\n\n await installNextUILintRoutes({\n projectPath: action.projectPath,\n appRoot: action.appRoot,\n force: false,\n });\n\n return { action, success: true };\n}\n\n/**\n * Deep merge two objects\n */\nfunction deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>\n): Record<string, unknown> {\n const result = { ...target };\n\n for (const key of Object.keys(source)) {\n const sourceVal = source[key];\n const targetVal = target[key];\n\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n targetVal &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(\n targetVal as Record<string, unknown>,\n sourceVal as Record<string, unknown>\n );\n } else {\n result[key] = sourceVal;\n }\n }\n\n return result;\n}\n\n/**\n * Build the install summary from results\n */\nfunction buildSummary(\n actionsPerformed: ActionResult[],\n dependencyResults: DependencyResult[],\n items: string[]\n): InstallSummary {\n const filesCreated: string[] = [];\n const filesModified: string[] = [];\n const filesDeleted: string[] = [];\n const eslintTargets: { displayName: string; configFile: string }[] = [];\n let nextApp: { appRoot: string } | undefined;\n let viteApp: { entryRoot: string } | undefined;\n\n for (const result of actionsPerformed) {\n if (!result.success) continue;\n\n const { action } = result;\n switch (action.type) {\n case \"create_file\":\n filesCreated.push(action.path);\n break;\n case \"merge_json\":\n case \"append_to_file\":\n filesModified.push(action.path);\n break;\n case \"delete_file\":\n filesDeleted.push(action.path);\n break;\n case \"inject_eslint\":\n filesModified.push(action.configPath);\n eslintTargets.push({\n displayName: action.packagePath,\n configFile: action.configPath,\n });\n break;\n case \"inject_react\":\n if (action.mode === \"vite\") {\n viteApp = { entryRoot: action.appRoot };\n } else {\n nextApp = { appRoot: action.appRoot };\n }\n break;\n case \"install_next_routes\":\n nextApp = { appRoot: action.appRoot };\n break;\n }\n }\n\n const dependenciesInstalled: { packagePath: string; packages: string[] }[] =\n [];\n for (const result of dependencyResults) {\n if (result.success && !result.skipped) {\n dependenciesInstalled.push({\n packagePath: result.install.packagePath,\n packages: result.install.packages,\n });\n }\n }\n\n return {\n installedItems: items as InstallSummary[\"installedItems\"],\n filesCreated,\n filesModified,\n filesDeleted,\n dependenciesInstalled,\n eslintTargets,\n nextApp,\n viteApp,\n };\n}\n\n/**\n * Execute an install plan\n *\n * @param plan - The install plan to execute\n * @param options - Execution options\n * @returns InstallResult with details of what was done\n */\nexport async function execute(\n plan: InstallPlan,\n options: ExecuteOptions = {}\n): Promise<InstallResult> {\n const { dryRun = false, installDependencies = defaultInstallDependencies } =\n options;\n\n const actionsPerformed: ActionResult[] = [];\n const dependencyResults: DependencyResult[] = [];\n\n // Execute all actions in order\n for (const action of plan.actions) {\n const result = await executeAction(action, options);\n actionsPerformed.push(result);\n }\n\n // Install dependencies\n for (const dep of plan.dependencies) {\n if (dryRun) {\n dependencyResults.push({\n install: dep,\n success: true,\n skipped: true,\n });\n continue;\n }\n\n try {\n await installDependencies(\n dep.packageManager,\n dep.packagePath,\n dep.packages\n );\n dependencyResults.push({\n install: dep,\n success: true,\n });\n } catch (error) {\n dependencyResults.push({\n install: dep,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Determine overall success\n const actionsFailed = actionsPerformed.filter((r) => !r.success);\n const depsFailed = dependencyResults.filter((r) => !r.success);\n const success = actionsFailed.length === 0 && depsFailed.length === 0;\n\n // Collect items from actions (reverse engineer what was installed)\n const items: string[] = [];\n for (const result of actionsPerformed) {\n if (!result.success) continue;\n const { action } = result;\n if (action.type === \"create_file\") {\n if (action.path.includes(\"genstyleguide.md\")) items.push(\"genstyleguide\");\n if (action.path.includes(\"/skills/\") && action.path.includes(\"SKILL.md\")) items.push(\"skill\");\n }\n if (action.type === \"inject_eslint\") items.push(\"eslint\");\n if (action.type === \"install_next_routes\") items.push(\"next\");\n if (action.type === \"inject_react\") {\n items.push(action.mode === \"vite\" ? \"vite\" : \"next\");\n }\n if (action.type === \"inject_vite_config\") items.push(\"vite\");\n }\n // Dedupe\n const uniqueItems = [...new Set(items)];\n\n const summary = buildSummary(\n actionsPerformed,\n dependencyResults,\n uniqueItems\n );\n\n return {\n success,\n actionsPerformed,\n dependencyResults,\n summary,\n };\n}\n","import { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { parseModule, generateCode } from \"magicast\";\n\nexport interface InstallReactOverlayOptions {\n projectPath: string;\n /**\n * Relative entry root:\n * - Next.js: \"app\" or \"src/app\"\n * - Vite: typically \"src\"\n */\n appRoot: string;\n /**\n * Injection mode:\n * - \"next\": wraps `{children}` (App Router layout/page)\n * - \"vite\": wraps the first `*.render(<...>)` argument\n */\n mode?: \"next\" | \"vite\";\n force?: boolean;\n /**\n * If multiple candidates are found, prompt user to choose.\n */\n confirmFileChoice?: (choices: string[]) => Promise<string>;\n}\n\n/**\n * Find top-level layout.* or page.* files in the app root.\n * Prefer layout.* over page.* (layouts are better for providers).\n */\nfunction getDefaultCandidates(projectPath: string, appRoot: string): string[] {\n // Vite entry files (prefer src/main.*)\n const viteMainCandidates = [\n join(appRoot, \"main.tsx\"),\n join(appRoot, \"main.jsx\"),\n join(appRoot, \"main.ts\"),\n join(appRoot, \"main.js\"),\n ];\n const existingViteMain = viteMainCandidates.filter((rel) =>\n existsSync(join(projectPath, rel))\n );\n if (existingViteMain.length > 0) return existingViteMain;\n\n // Vite fallback: src/App.* (some templates wire provider there)\n const viteAppCandidates = [join(appRoot, \"App.tsx\"), join(appRoot, \"App.jsx\")];\n const existingViteApp = viteAppCandidates.filter((rel) =>\n existsSync(join(projectPath, rel))\n );\n if (existingViteApp.length > 0) return existingViteApp;\n\n // Check layout files first (preferred)\n const layoutCandidates = [\n join(appRoot, \"layout.tsx\"),\n join(appRoot, \"layout.jsx\"),\n join(appRoot, \"layout.ts\"),\n join(appRoot, \"layout.js\"),\n ];\n\n const existingLayouts = layoutCandidates.filter((rel) =>\n existsSync(join(projectPath, rel))\n );\n\n if (existingLayouts.length > 0) {\n return existingLayouts;\n }\n\n // Fall back to page files if no layouts found\n const pageCandidates = [join(appRoot, \"page.tsx\"), join(appRoot, \"page.jsx\")];\n\n return pageCandidates.filter((rel) => existsSync(join(projectPath, rel)));\n}\n\nfunction isUseClientDirective(stmt: any): boolean {\n return (\n stmt?.type === \"ExpressionStatement\" &&\n stmt.expression?.type === \"StringLiteral\" &&\n stmt.expression.value === \"use client\"\n );\n}\n\nfunction findImportDeclaration(program: any, from: string): any | null {\n if (!program || program.type !== \"Program\") return null;\n for (const stmt of program.body ?? []) {\n if (stmt?.type !== \"ImportDeclaration\") continue;\n if (stmt.source?.value === from) return stmt;\n }\n return null;\n}\n\nfunction walkAst(node: any, visit: (n: any) => void): void {\n if (!node || typeof node !== \"object\") return;\n if (node.type) visit(node);\n for (const key of Object.keys(node)) {\n const v = (node as any)[key];\n if (!v) continue;\n if (Array.isArray(v)) {\n for (const item of v) walkAst(item, visit);\n } else if (typeof v === \"object\" && v.type) {\n walkAst(v, visit);\n }\n }\n}\n\nfunction ensureNamedImport(\n program: any,\n from: string,\n name: string\n): { changed: boolean } {\n if (!program || program.type !== \"Program\") return { changed: false };\n\n const existing = findImportDeclaration(program, from);\n if (existing) {\n const has = (existing.specifiers ?? []).some(\n (s: any) =>\n s?.type === \"ImportSpecifier\" &&\n (s.imported?.name === name || s.imported?.value === name)\n );\n if (has) return { changed: false };\n\n const spec = (parseModule(`import { ${name} } from \"${from}\";`).$ast as any)\n .body?.[0]?.specifiers?.[0];\n if (!spec) return { changed: false };\n\n existing.specifiers = [...(existing.specifiers ?? []), spec];\n return { changed: true };\n }\n\n // Insert a fresh import after directives, and after existing imports.\n const importDecl = (\n parseModule(`import { ${name} } from \"${from}\";`).$ast as any\n ).body?.[0];\n if (!importDecl) return { changed: false };\n\n const body = program.body ?? [];\n let insertAt = 0;\n while (insertAt < body.length && isUseClientDirective(body[insertAt])) {\n insertAt++;\n }\n // Skip over existing imports\n while (\n insertAt < body.length &&\n body[insertAt]?.type === \"ImportDeclaration\"\n ) {\n insertAt++;\n }\n program.body.splice(insertAt, 0, importDecl);\n return { changed: true };\n}\n\nfunction hasUILintDevtoolsJsx(program: any): boolean {\n let found = false;\n walkAst(program, (node) => {\n if (found) return;\n if (node.type !== \"JSXElement\") return;\n const name = node.openingElement?.name;\n // Check for both old UILintProvider and new uilint-devtools\n if (name?.type === \"JSXIdentifier\") {\n if (name.name === \"UILintProvider\" || name.name === \"uilint-devtools\") {\n found = true;\n }\n }\n });\n return found;\n}\n\n/**\n * Add <uilint-devtools /> element as a sibling to {children} in Next.js layouts.\n * This injects the devtools web component without wrapping the children.\n */\nfunction addDevtoolsElementNextJs(program: any): {\n changed: boolean;\n} {\n if (!program || program.type !== \"Program\") return { changed: false };\n if (hasUILintDevtoolsJsx(program)) return { changed: false };\n\n // Create the devtools JSX element: <uilint-devtools />\n const devtoolsMod = parseModule(\n 'const __uilint_devtools = (<uilint-devtools />);'\n );\n const devtoolsJsx =\n (devtoolsMod.$ast as any).body?.[0]?.declarations?.[0]?.init ?? null;\n if (!devtoolsJsx || devtoolsJsx.type !== \"JSXElement\")\n return { changed: false };\n\n // Find the return statement that contains {children} and add devtools as sibling\n let added = false;\n walkAst(program, (node) => {\n if (added) return;\n\n // Look for JSX elements that contain {children}\n if (node.type !== \"JSXElement\" && node.type !== \"JSXFragment\") return;\n\n const children = node.children ?? [];\n const childrenIndex = children.findIndex(\n (child: any) =>\n child?.type === \"JSXExpressionContainer\" &&\n child.expression?.type === \"Identifier\" &&\n child.expression.name === \"children\"\n );\n\n if (childrenIndex === -1) return;\n\n // Add devtools element after {children}\n children.splice(childrenIndex + 1, 0, devtoolsJsx);\n added = true;\n });\n\n if (!added) {\n throw new Error(\"Could not find `{children}` in target file to add devtools.\");\n }\n return { changed: true };\n}\n\n/**\n * Add <uilint-devtools /> element to Vite's render call.\n * Wraps the existing render argument in a fragment with the devtools element.\n */\nfunction addDevtoolsElementVite(program: any): {\n changed: boolean;\n} {\n if (!program || program.type !== \"Program\") return { changed: false };\n if (hasUILintDevtoolsJsx(program)) return { changed: false };\n\n // Create a fragment containing the original content + devtools:\n // <>...original...<uilint-devtools /></>\n let added = false;\n walkAst(program, (node) => {\n if (added) return;\n if (node.type !== \"CallExpression\") return;\n const callee = node.callee;\n // Match: something.render(<JSX />)\n if (callee?.type !== \"MemberExpression\") return;\n const prop = callee.property;\n const isRender =\n (prop?.type === \"Identifier\" && prop.name === \"render\") ||\n (prop?.type === \"StringLiteral\" && prop.value === \"render\") ||\n (prop?.type === \"Literal\" && prop.value === \"render\");\n if (!isRender) return;\n\n const arg0 = node.arguments?.[0];\n if (!arg0) return;\n if (arg0.type !== \"JSXElement\" && arg0.type !== \"JSXFragment\") return;\n\n // Create the devtools JSX element\n const devtoolsMod = parseModule(\n 'const __uilint_devtools = (<uilint-devtools />);'\n );\n const devtoolsJsx =\n (devtoolsMod.$ast as any).body?.[0]?.declarations?.[0]?.init ?? null;\n if (!devtoolsJsx) return;\n\n // Create a fragment wrapping original + devtools\n const fragmentMod = parseModule(\n 'const __fragment = (<></>);'\n );\n const fragmentJsx =\n (fragmentMod.$ast as any).body?.[0]?.declarations?.[0]?.init ?? null;\n if (!fragmentJsx) return;\n\n // Add original content and devtools as children of the fragment\n fragmentJsx.children = [arg0, devtoolsJsx];\n node.arguments[0] = fragmentJsx;\n added = true;\n });\n\n if (!added) {\n throw new Error(\n 'Could not find a `.render(<...>)` call to add devtools. Expected a React entry like `createRoot(...).render(<App />)`.'\n );\n }\n return { changed: true };\n}\n\n/**\n * Ensure a side-effect import exists in the program.\n * e.g., import \"uilint-react/devtools\";\n */\nfunction ensureSideEffectImport(\n program: any,\n from: string\n): { changed: boolean } {\n if (!program || program.type !== \"Program\") return { changed: false };\n\n // Check if import already exists\n const existing = findImportDeclaration(program, from);\n if (existing) return { changed: false };\n\n // Create a side-effect import\n const importDecl = (\n parseModule(`import \"${from}\";`).$ast as any\n ).body?.[0];\n if (!importDecl) return { changed: false };\n\n const body = program.body ?? [];\n let insertAt = 0;\n // Skip \"use client\" directive\n while (insertAt < body.length && isUseClientDirective(body[insertAt])) {\n insertAt++;\n }\n // Skip over existing imports\n while (\n insertAt < body.length &&\n body[insertAt]?.type === \"ImportDeclaration\"\n ) {\n insertAt++;\n }\n program.body.splice(insertAt, 0, importDecl);\n return { changed: true };\n}\n\nexport async function installReactUILintOverlay(\n opts: InstallReactOverlayOptions\n): Promise<{\n targetFile: string;\n modified: boolean;\n alreadyConfigured?: boolean;\n}> {\n const candidates = getDefaultCandidates(opts.projectPath, opts.appRoot);\n if (!candidates.length) {\n throw new Error(\n `No suitable entry files found under ${opts.appRoot} (expected Next.js layout/page or Vite main/App).`\n );\n }\n\n let chosen: string;\n\n // If there are multiple candidates, ask user to choose\n if (candidates.length > 1 && opts.confirmFileChoice) {\n chosen = await opts.confirmFileChoice(candidates);\n } else {\n // Single candidate - use it\n chosen = candidates[0]!;\n }\n\n const absTarget = join(opts.projectPath, chosen);\n const original = readFileSync(absTarget, \"utf-8\");\n\n let mod: any;\n try {\n mod = parseModule(original);\n } catch {\n throw new Error(\n `Unable to parse ${chosen} as JavaScript/TypeScript. Please update it manually.`\n );\n }\n\n const program = mod.$ast;\n\n // Check if already configured (either old UILintProvider or new devtools approach)\n const hasDevtoolsImport = !!findImportDeclaration(program, \"uilint-react/devtools\");\n const hasOldImport = !!findImportDeclaration(program, \"uilint-react\");\n const alreadyConfigured =\n (hasDevtoolsImport || hasOldImport) && hasUILintDevtoolsJsx(program);\n\n let changed = false;\n\n // Add side-effect import for the devtools web component\n const importRes = ensureSideEffectImport(program, \"uilint-react/devtools\");\n if (importRes.changed) changed = true;\n\n const mode = opts.mode ?? \"next\";\n const addRes =\n mode === \"vite\"\n ? addDevtoolsElementVite(program)\n : addDevtoolsElementNextJs(program);\n if (addRes.changed) changed = true;\n\n const updated = changed ? generateCode(mod).code : original;\n\n const modified = updated !== original;\n if (modified) {\n writeFileSync(absTarget, updated, \"utf-8\");\n }\n\n return {\n targetFile: chosen,\n modified,\n alreadyConfigured: alreadyConfigured && !modified,\n };\n}\n","/**\n * Inject jsx-loc-plugin into Next.js config\n *\n * Modifies next.config.{ts,js,mjs,cjs} to wrap the export with withJsxLoc()\n */\n\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { parseModule, generateCode } from \"magicast\";\n\nexport interface InstallJsxLocPluginOptions {\n projectPath: string;\n force?: boolean;\n}\n\nconst CONFIG_EXTENSIONS = [\".ts\", \".mjs\", \".js\", \".cjs\"];\n\n/**\n * Find the next.config file in a project\n */\nexport function findNextConfigFile(projectPath: string): string | null {\n for (const ext of CONFIG_EXTENSIONS) {\n const configPath = join(projectPath, `next.config${ext}`);\n if (existsSync(configPath)) {\n return configPath;\n }\n }\n return null;\n}\n\n/**\n * Get the relative config filename for display\n */\nexport function getNextConfigFilename(configPath: string): string {\n const parts = configPath.split(\"/\");\n return parts[parts.length - 1] || \"next.config.ts\";\n}\n\n/**\n * Check if the source already has withJsxLoc imported\n */\nfunction hasJsxLocImport(source: string): boolean {\n return (\n source.includes('from \"jsx-loc-plugin\"') ||\n source.includes(\"from 'jsx-loc-plugin'\")\n );\n}\n\n/**\n * Check if the source already uses withJsxLoc\n */\nfunction hasJsxLocWrapper(source: string): boolean {\n return source.includes(\"withJsxLoc(\");\n}\n\nfunction isIdentifier(node: any, name?: string): boolean {\n return (\n !!node &&\n node.type === \"Identifier\" &&\n (name ? node.name === name : typeof node.name === \"string\")\n );\n}\n\nfunction isStringLiteral(node: any): node is { type: string; value: string } {\n return (\n !!node &&\n (node.type === \"StringLiteral\" || node.type === \"Literal\") &&\n typeof node.value === \"string\"\n );\n}\n\nfunction ensureEsmWithJsxLocImport(program: any): { changed: boolean } {\n if (!program || program.type !== \"Program\") return { changed: false };\n\n // Find existing import from jsx-loc-plugin\n const existing = (program.body ?? []).find(\n (s: any) => s?.type === \"ImportDeclaration\" && s.source?.value === \"jsx-loc-plugin\"\n );\n\n if (existing) {\n const has = (existing.specifiers ?? []).some(\n (sp: any) =>\n sp?.type === \"ImportSpecifier\" &&\n (sp.imported?.name === \"withJsxLoc\" || sp.imported?.value === \"withJsxLoc\")\n );\n if (has) return { changed: false };\n\n const spec = (parseModule('import { withJsxLoc } from \"jsx-loc-plugin\";')\n .$ast as any).body?.[0]?.specifiers?.[0];\n if (!spec) return { changed: false };\n existing.specifiers = [...(existing.specifiers ?? []), spec];\n return { changed: true };\n }\n\n const importDecl = (parseModule('import { withJsxLoc } from \"jsx-loc-plugin\";')\n .$ast as any).body?.[0];\n if (!importDecl) return { changed: false };\n\n // Insert after last import\n const body = program.body ?? [];\n let insertAt = 0;\n while (insertAt < body.length && body[insertAt]?.type === \"ImportDeclaration\") {\n insertAt++;\n }\n program.body.splice(insertAt, 0, importDecl);\n return { changed: true };\n}\n\nfunction ensureCjsWithJsxLocRequire(program: any): { changed: boolean } {\n if (!program || program.type !== \"Program\") return { changed: false };\n\n // Detect an existing require(\"jsx-loc-plugin\") that binds withJsxLoc\n for (const stmt of program.body ?? []) {\n if (stmt?.type !== \"VariableDeclaration\") continue;\n for (const decl of stmt.declarations ?? []) {\n const init = decl?.init;\n if (\n init?.type === \"CallExpression\" &&\n isIdentifier(init.callee, \"require\") &&\n isStringLiteral(init.arguments?.[0]) &&\n init.arguments[0].value === \"jsx-loc-plugin\"\n ) {\n // If destructuring, ensure property exists\n if (decl.id?.type === \"ObjectPattern\") {\n const has = (decl.id.properties ?? []).some((p: any) => {\n if (p?.type !== \"ObjectProperty\" && p?.type !== \"Property\") return false;\n return isIdentifier(p.key, \"withJsxLoc\");\n });\n if (has) return { changed: false };\n const prop = (parseModule('const { withJsxLoc } = require(\"jsx-loc-plugin\");')\n .$ast as any).body?.[0]?.declarations?.[0]?.id?.properties?.[0];\n if (!prop) return { changed: false };\n decl.id.properties = [...(decl.id.properties ?? []), prop];\n return { changed: true };\n }\n\n // Already requiring the module in some other shape; don't try to rewrite.\n return { changed: false };\n }\n }\n }\n\n // Insert: const { withJsxLoc } = require(\"jsx-loc-plugin\");\n const reqDecl = (parseModule('const { withJsxLoc } = require(\"jsx-loc-plugin\");')\n .$ast as any).body?.[0];\n if (!reqDecl) return { changed: false };\n program.body.unshift(reqDecl);\n return { changed: true };\n}\n\nfunction wrapEsmExportDefault(program: any): { changed: boolean } {\n if (!program || program.type !== \"Program\") return { changed: false };\n\n const exportDecl = (program.body ?? []).find(\n (s: any) => s?.type === \"ExportDefaultDeclaration\"\n );\n if (!exportDecl) return { changed: false };\n\n const decl = exportDecl.declaration;\n if (\n decl?.type === \"CallExpression\" &&\n isIdentifier(decl.callee, \"withJsxLoc\")\n ) {\n return { changed: false };\n }\n\n exportDecl.declaration = {\n type: \"CallExpression\",\n callee: { type: \"Identifier\", name: \"withJsxLoc\" },\n arguments: [decl],\n };\n return { changed: true };\n}\n\nfunction wrapCjsModuleExports(program: any): { changed: boolean } {\n if (!program || program.type !== \"Program\") return { changed: false };\n\n for (const stmt of program.body ?? []) {\n if (!stmt || stmt.type !== \"ExpressionStatement\") continue;\n const expr = stmt.expression;\n if (!expr || expr.type !== \"AssignmentExpression\") continue;\n const left = expr.left;\n const right = expr.right;\n const isModuleExports =\n left?.type === \"MemberExpression\" &&\n isIdentifier(left.object, \"module\") &&\n isIdentifier(left.property, \"exports\");\n if (!isModuleExports) continue;\n\n if (\n right?.type === \"CallExpression\" &&\n isIdentifier(right.callee, \"withJsxLoc\")\n ) {\n return { changed: false };\n }\n\n expr.right = {\n type: \"CallExpression\",\n callee: { type: \"Identifier\", name: \"withJsxLoc\" },\n arguments: [right],\n };\n return { changed: true };\n }\n\n return { changed: false };\n}\n\n/**\n * Install jsx-loc-plugin into next.config\n */\nexport async function installJsxLocPlugin(\n opts: InstallJsxLocPluginOptions\n): Promise<{ configFile: string | null; modified: boolean }> {\n const configPath = findNextConfigFile(opts.projectPath);\n\n if (!configPath) {\n return { configFile: null, modified: false };\n }\n\n const configFilename = getNextConfigFilename(configPath);\n const original = readFileSync(configPath, \"utf-8\");\n\n let mod: any;\n try {\n mod = parseModule(original);\n } catch {\n return { configFile: configFilename, modified: false };\n }\n\n const program = mod.$ast;\n const isCjs = configPath.endsWith(\".cjs\");\n\n // No confirmOverwrite needed: injector is idempotent.\n\n let changed = false;\n if (isCjs) {\n const reqRes = ensureCjsWithJsxLocRequire(program);\n if (reqRes.changed) changed = true;\n const wrapRes = wrapCjsModuleExports(program);\n if (wrapRes.changed) changed = true;\n } else {\n const impRes = ensureEsmWithJsxLocImport(program);\n if (impRes.changed) changed = true;\n const wrapRes = wrapEsmExportDefault(program);\n if (wrapRes.changed) changed = true;\n }\n\n const updated = changed ? generateCode(mod).code : original;\n\n if (updated !== original) {\n writeFileSync(configPath, updated, \"utf-8\");\n return { configFile: configFilename, modified: true };\n }\n\n return { configFile: configFilename, modified: false };\n}\n","/**\n * Inject jsx-loc-plugin into Vite config\n *\n * Modifies vite.config.{ts,js,mjs,cjs} to add `jsxLoc()` to the `plugins` array.\n */\n\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { parseModule, generateCode } from \"magicast\";\n\nexport interface InstallViteJsxLocPluginOptions {\n projectPath: string;\n force?: boolean;\n}\n\nconst CONFIG_EXTENSIONS = [\".ts\", \".mjs\", \".js\", \".cjs\"];\n\nexport function findViteConfigFile(projectPath: string): string | null {\n for (const ext of CONFIG_EXTENSIONS) {\n const configPath = join(projectPath, `vite.config${ext}`);\n if (existsSync(configPath)) return configPath;\n }\n return null;\n}\n\nexport function getViteConfigFilename(configPath: string): string {\n const parts = configPath.split(\"/\");\n return parts[parts.length - 1] || \"vite.config.ts\";\n}\n\nfunction isIdentifier(node: any, name?: string): boolean {\n return (\n !!node &&\n node.type === \"Identifier\" &&\n (name ? node.name === name : typeof node.name === \"string\")\n );\n}\n\nfunction isStringLiteral(node: any): node is { type: string; value: string } {\n return (\n !!node &&\n (node.type === \"StringLiteral\" || node.type === \"Literal\") &&\n typeof node.value === \"string\"\n );\n}\n\nfunction unwrapExpression(expr: any): any {\n let e = expr;\n while (e) {\n if (e.type === \"TSAsExpression\" || e.type === \"TSNonNullExpression\") {\n e = e.expression;\n continue;\n }\n if (e.type === \"TSSatisfiesExpression\") {\n e = e.expression;\n continue;\n }\n if (e.type === \"ParenthesizedExpression\") {\n e = e.expression;\n continue;\n }\n break;\n }\n return e;\n}\n\nfunction findExportedConfigObjectExpression(mod: any): {\n kind: \"esm\" | \"cjs\";\n objExpr: any;\n program: any;\n} | null {\n const program = mod?.$ast;\n if (!program || program.type !== \"Program\") return null;\n\n // ESM: export default { ... } OR export default defineConfig({ ... })\n for (const stmt of program.body ?? []) {\n if (!stmt || stmt.type !== \"ExportDefaultDeclaration\") continue;\n const decl = unwrapExpression(stmt.declaration);\n if (!decl) break;\n\n if (decl.type === \"ObjectExpression\") {\n return { kind: \"esm\", objExpr: decl, program };\n }\n if (\n decl.type === \"CallExpression\" &&\n isIdentifier(decl.callee, \"defineConfig\") &&\n unwrapExpression(decl.arguments?.[0])?.type === \"ObjectExpression\"\n ) {\n return {\n kind: \"esm\",\n objExpr: unwrapExpression(decl.arguments?.[0]),\n program,\n };\n }\n break;\n }\n\n // CJS: module.exports = { ... } OR module.exports = defineConfig({ ... })\n for (const stmt of program.body ?? []) {\n if (!stmt || stmt.type !== \"ExpressionStatement\") continue;\n const expr = stmt.expression;\n if (!expr || expr.type !== \"AssignmentExpression\") continue;\n const left = expr.left;\n const right = unwrapExpression(expr.right);\n const isModuleExports =\n left?.type === \"MemberExpression\" &&\n isIdentifier(left.object, \"module\") &&\n isIdentifier(left.property, \"exports\");\n if (!isModuleExports) continue;\n\n if (right?.type === \"ObjectExpression\") {\n return { kind: \"cjs\", objExpr: right, program };\n }\n if (\n right?.type === \"CallExpression\" &&\n isIdentifier(right.callee, \"defineConfig\") &&\n unwrapExpression(right.arguments?.[0])?.type === \"ObjectExpression\"\n ) {\n return {\n kind: \"cjs\",\n objExpr: unwrapExpression(right.arguments?.[0]),\n program,\n };\n }\n }\n\n return null;\n}\n\nfunction getObjectProperty(obj: any, keyName: string): any | null {\n if (!obj || obj.type !== \"ObjectExpression\") return null;\n for (const prop of obj.properties ?? []) {\n if (!prop) continue;\n if (prop.type !== \"ObjectProperty\" && prop.type !== \"Property\") continue;\n const key = prop.key;\n const keyMatch =\n (key?.type === \"Identifier\" && key.name === keyName) ||\n (isStringLiteral(key) && key.value === keyName);\n if (keyMatch) return prop;\n }\n return null;\n}\n\nfunction ensureEsmJsxLocImport(program: any): { changed: boolean } {\n if (!program || program.type !== \"Program\") return { changed: false };\n\n // Find existing import from jsx-loc-plugin/vite\n const existing = (program.body ?? []).find(\n (s: any) =>\n s?.type === \"ImportDeclaration\" && s.source?.value === \"jsx-loc-plugin/vite\"\n );\n if (existing) {\n const has = (existing.specifiers ?? []).some(\n (sp: any) =>\n sp?.type === \"ImportSpecifier\" &&\n (sp.imported?.name === \"jsxLoc\" || sp.imported?.value === \"jsxLoc\")\n );\n if (has) return { changed: false };\n const spec = (\n parseModule('import { jsxLoc } from \"jsx-loc-plugin/vite\";').$ast as any\n ).body?.[0]?.specifiers?.[0];\n if (!spec) return { changed: false };\n existing.specifiers = [...(existing.specifiers ?? []), spec];\n return { changed: true };\n }\n\n const importDecl = (\n parseModule('import { jsxLoc } from \"jsx-loc-plugin/vite\";').$ast as any\n ).body?.[0];\n if (!importDecl) return { changed: false };\n\n // Insert after last import\n const body = program.body ?? [];\n let insertAt = 0;\n while (insertAt < body.length && body[insertAt]?.type === \"ImportDeclaration\") {\n insertAt++;\n }\n program.body.splice(insertAt, 0, importDecl);\n return { changed: true };\n}\n\nfunction ensureCjsJsxLocRequire(program: any): { changed: boolean } {\n if (!program || program.type !== \"Program\") return { changed: false };\n\n // Detect an existing require(\"jsx-loc-plugin/vite\") that binds jsxLoc\n for (const stmt of program.body ?? []) {\n if (stmt?.type !== \"VariableDeclaration\") continue;\n for (const decl of stmt.declarations ?? []) {\n const init = decl?.init;\n if (\n init?.type === \"CallExpression\" &&\n isIdentifier(init.callee, \"require\") &&\n isStringLiteral(init.arguments?.[0]) &&\n init.arguments[0].value === \"jsx-loc-plugin/vite\"\n ) {\n // If destructuring, ensure property exists\n if (decl.id?.type === \"ObjectPattern\") {\n const has = (decl.id.properties ?? []).some((p: any) => {\n if (p?.type !== \"ObjectProperty\" && p?.type !== \"Property\") return false;\n return isIdentifier(p.key, \"jsxLoc\");\n });\n if (has) return { changed: false };\n const prop = (\n parseModule('const { jsxLoc } = require(\"jsx-loc-plugin/vite\");')\n .$ast as any\n ).body?.[0]?.declarations?.[0]?.id?.properties?.[0];\n if (!prop) return { changed: false };\n decl.id.properties = [...(decl.id.properties ?? []), prop];\n return { changed: true };\n }\n return { changed: false };\n }\n }\n }\n\n // Insert: const { jsxLoc } = require(\"jsx-loc-plugin/vite\");\n const reqDecl = (\n parseModule('const { jsxLoc } = require(\"jsx-loc-plugin/vite\");').$ast as any\n ).body?.[0];\n if (!reqDecl) return { changed: false };\n program.body.unshift(reqDecl);\n return { changed: true };\n}\n\nfunction pluginsHasJsxLoc(arr: any): boolean {\n if (!arr || arr.type !== \"ArrayExpression\") return false;\n for (const el of arr.elements ?? []) {\n const e = unwrapExpression(el);\n if (!e) continue;\n if (e.type === \"CallExpression\" && isIdentifier(e.callee, \"jsxLoc\")) return true;\n }\n return false;\n}\n\nfunction ensurePluginsContainsJsxLoc(configObj: any): { changed: boolean } {\n const pluginsProp = getObjectProperty(configObj, \"plugins\");\n\n // No plugins: create plugins: [jsxLoc()]\n if (!pluginsProp) {\n const prop = (parseModule(\"export default { plugins: [jsxLoc()] };\").$ast as any)\n .body?.find((s: any) => s.type === \"ExportDefaultDeclaration\")\n ?.declaration?.properties?.find((p: any) => {\n const k = p?.key;\n return (k?.type === \"Identifier\" && k.name === \"plugins\") ||\n (isStringLiteral(k) && k.value === \"plugins\");\n });\n if (!prop) return { changed: false };\n configObj.properties = [...(configObj.properties ?? []), prop];\n return { changed: true };\n }\n\n const value = unwrapExpression(pluginsProp.value);\n if (!value) return { changed: false };\n\n // plugins: [ ... ]\n if (value.type === \"ArrayExpression\") {\n if (pluginsHasJsxLoc(value)) return { changed: false };\n const jsxLocCall = (parseModule(\"const __x = jsxLoc();\").$ast as any).body?.[0]\n ?.declarations?.[0]?.init;\n if (!jsxLocCall) return { changed: false };\n value.elements.push(jsxLocCall);\n return { changed: true };\n }\n\n // Non-array plugins: best-effort wrap into array with spread.\n // plugins: something -> plugins: [...something, jsxLoc()]\n const jsxLocCall = (parseModule(\"const __x = jsxLoc();\").$ast as any).body?.[0]\n ?.declarations?.[0]?.init;\n if (!jsxLocCall) return { changed: false };\n const spread = { type: \"SpreadElement\", argument: value };\n pluginsProp.value = { type: \"ArrayExpression\", elements: [spread, jsxLocCall] };\n return { changed: true };\n}\n\nexport async function installViteJsxLocPlugin(\n opts: InstallViteJsxLocPluginOptions\n): Promise<{ configFile: string | null; modified: boolean }> {\n const configPath = findViteConfigFile(opts.projectPath);\n if (!configPath) return { configFile: null, modified: false };\n\n const configFilename = getViteConfigFilename(configPath);\n const original = readFileSync(configPath, \"utf-8\");\n const isCjs = configPath.endsWith(\".cjs\");\n\n let mod: any;\n try {\n mod = parseModule(original);\n } catch {\n return { configFile: configFilename, modified: false };\n }\n\n const found = findExportedConfigObjectExpression(mod);\n if (!found) return { configFile: configFilename, modified: false };\n\n let changed = false;\n\n // Ensure import/require first (so generated code has the symbol)\n if (isCjs) {\n const reqRes = ensureCjsJsxLocRequire(found.program);\n if (reqRes.changed) changed = true;\n } else {\n const impRes = ensureEsmJsxLocImport(found.program);\n if (impRes.changed) changed = true;\n }\n\n const pluginsRes = ensurePluginsContainsJsxLoc(found.objExpr);\n if (pluginsRes.changed) changed = true;\n\n const updated = changed ? generateCode(mod).code : original;\n if (updated !== original) {\n writeFileSync(configPath, updated, \"utf-8\");\n return { configFile: configFilename, modified: true };\n }\n\n return { configFile: configFilename, modified: false };\n}\n","import { existsSync } from \"fs\";\nimport { mkdir, readdir, writeFile } from \"fs/promises\";\nimport { join } from \"path\";\n\nexport interface InstallNextRoutesOptions {\n projectPath: string;\n /**\n * Relative app root: \"app\" or \"src/app\"\n */\n appRoot: string;\n force?: boolean;\n}\n\nconst DEV_SOURCE_ROUTE_TS = `/**\n * Dev-only API route for fetching source files\n *\n * This route allows the UILint overlay to fetch and display source code\n * for components rendered on the page.\n *\n * Security:\n * - Only available in development mode\n * - Validates file path is within project root\n * - Only allows specific file extensions\n */\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport { readFileSync, existsSync } from \"fs\";\nimport { resolve, relative, dirname, extname, sep } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nexport const runtime = \"nodejs\";\n\n// Allowed file extensions\nconst ALLOWED_EXTENSIONS = new Set([\".tsx\", \".ts\", \".jsx\", \".js\", \".css\"]);\n\n/**\n * Best-effort: resolve the Next.js project root (the dir that owns .next/) even in monorepos.\n *\n * Why: In monorepos, process.cwd() might be the workspace root (it also has package.json),\n * which would incorrectly store/read files under the wrong directory.\n */\nfunction findNextProjectRoot(): string {\n // Prefer discovering via this route module's on-disk path.\n // In Next, route code is executed from within \".next/server/...\".\n try {\n const selfPath = fileURLToPath(import.meta.url);\n const marker = sep + \".next\" + sep;\n const idx = selfPath.lastIndexOf(marker);\n if (idx !== -1) {\n return selfPath.slice(0, idx);\n }\n } catch {\n // ignore\n }\n\n // Fallback: walk up from cwd looking for .next/\n let dir = process.cwd();\n for (let i = 0; i < 20; i++) {\n if (existsSync(resolve(dir, \".next\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n // Final fallback: cwd\n return process.cwd();\n}\n\n/**\n * Validate that a path is within the allowed directory\n */\nfunction isPathWithinRoot(filePath: string, root: string): boolean {\n const resolved = resolve(filePath);\n const resolvedRoot = resolve(root);\n return resolved.startsWith(resolvedRoot + \"/\") || resolved === resolvedRoot;\n}\n\n/**\n * Find workspace root by walking up looking for pnpm-workspace.yaml or .git\n */\nfunction findWorkspaceRoot(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 10; i++) {\n if (\n existsSync(resolve(dir, \"pnpm-workspace.yaml\")) ||\n existsSync(resolve(dir, \".git\"))\n ) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\nexport async function GET(request: NextRequest) {\n // Block in production\n if (process.env.NODE_ENV === \"production\") {\n return NextResponse.json(\n { error: \"Not available in production\" },\n { status: 404 }\n );\n }\n\n const { searchParams } = new URL(request.url);\n const filePath = searchParams.get(\"path\");\n\n if (!filePath) {\n return NextResponse.json(\n { error: \"Missing 'path' query parameter\" },\n { status: 400 }\n );\n }\n\n // Validate extension\n const ext = extname(filePath).toLowerCase();\n if (!ALLOWED_EXTENSIONS.has(ext)) {\n return NextResponse.json(\n { error: \\`File extension '\\${ext}' not allowed\\` },\n { status: 403 }\n );\n }\n\n // Find project root (prefer Next project root over workspace root)\n const projectRoot = findNextProjectRoot();\n\n // Resolve the file path\n const resolvedPath = resolve(filePath);\n\n // Security check: ensure path is within project root or workspace root\n const workspaceRoot = findWorkspaceRoot(projectRoot);\n const isWithinApp = isPathWithinRoot(resolvedPath, projectRoot);\n const isWithinWorkspace = isPathWithinRoot(resolvedPath, workspaceRoot);\n\n if (!isWithinApp && !isWithinWorkspace) {\n return NextResponse.json(\n { error: \"Path outside project directory\" },\n { status: 403 }\n );\n }\n\n // Check file exists\n if (!existsSync(resolvedPath)) {\n return NextResponse.json({ error: \"File not found\" }, { status: 404 });\n }\n\n try {\n const content = readFileSync(resolvedPath, \"utf-8\");\n const relativePath = relative(workspaceRoot, resolvedPath);\n\n return NextResponse.json({\n content,\n relativePath,\n projectRoot,\n workspaceRoot,\n });\n } catch (error) {\n console.error(\"[Dev Source API] Error reading file:\", error);\n return NextResponse.json({ error: \"Failed to read file\" }, { status: 500 });\n }\n}\n`;\n\nconst SCREENSHOT_ROUTE_TS = `/**\n * Dev-only API route for saving and retrieving vision analysis screenshots\n *\n * This route allows the UILint overlay to:\n * - POST: Save screenshots and element manifests for vision analysis\n * - GET: Retrieve screenshots or list available screenshots\n *\n * Security:\n * - Only available in development mode\n * - Saves to .uilint/screenshots/ directory within project\n */\n\nimport { NextRequest, NextResponse } from \"next/server\";\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from \"fs\";\nimport { resolve, join, dirname, basename, sep } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nexport const runtime = \"nodejs\";\n\n// Maximum screenshot size (10MB)\nconst MAX_SCREENSHOT_SIZE = 10 * 1024 * 1024;\n\n/**\n * Best-effort: resolve the Next.js project root (the dir that owns .next/) even in monorepos.\n */\nfunction findNextProjectRoot(): string {\n try {\n const selfPath = fileURLToPath(import.meta.url);\n const marker = sep + \".next\" + sep;\n const idx = selfPath.lastIndexOf(marker);\n if (idx !== -1) {\n return selfPath.slice(0, idx);\n }\n } catch {\n // ignore\n }\n\n let dir = process.cwd();\n for (let i = 0; i < 20; i++) {\n if (existsSync(resolve(dir, \".next\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n return process.cwd();\n}\n\n/**\n * Get the screenshots directory path, creating it if needed\n */\nfunction getScreenshotsDir(projectRoot: string): string {\n const screenshotsDir = join(projectRoot, \".uilint\", \"screenshots\");\n if (!existsSync(screenshotsDir)) {\n mkdirSync(screenshotsDir, { recursive: true });\n }\n return screenshotsDir;\n}\n\n/**\n * Validate filename to prevent path traversal\n */\nfunction isValidFilename(filename: string): boolean {\n // Only allow alphanumeric, hyphens, underscores, and dots\n // Must end with .png, .jpeg, .jpg, or .json\n const validPattern = /^[a-zA-Z0-9_-]+\\\\.(png|jpeg|jpg|json)$/;\n return validPattern.test(filename) && !filename.includes(\"..\");\n}\n\n/**\n * POST: Save a screenshot and optionally its manifest\n */\nexport async function POST(request: NextRequest) {\n // Block in production\n if (process.env.NODE_ENV === \"production\") {\n return NextResponse.json(\n { error: \"Not available in production\" },\n { status: 404 }\n );\n }\n\n try {\n const body = await request.json();\n const { filename, imageData, manifest, analysisResult } = body;\n\n if (!filename) {\n return NextResponse.json({ error: \"Missing 'filename'\" }, { status: 400 });\n }\n\n // Validate filename\n if (!isValidFilename(filename)) {\n return NextResponse.json(\n { error: \"Invalid filename format\" },\n { status: 400 }\n );\n }\n\n // Allow \"sidecar-only\" updates (manifest/analysisResult) without re-sending image bytes.\n const hasImageData = typeof imageData === \"string\" && imageData.length > 0;\n const hasSidecar =\n typeof manifest !== \"undefined\" || typeof analysisResult !== \"undefined\";\n\n if (!hasImageData && !hasSidecar) {\n return NextResponse.json(\n { error: \"Nothing to save (provide imageData and/or manifest/analysisResult)\" },\n { status: 400 }\n );\n }\n\n // Check size (image only)\n if (hasImageData && imageData.length > MAX_SCREENSHOT_SIZE) {\n return NextResponse.json(\n { error: \"Screenshot too large (max 10MB)\" },\n { status: 413 }\n );\n }\n\n const projectRoot = findNextProjectRoot();\n const screenshotsDir = getScreenshotsDir(projectRoot);\n\n const imagePath = join(screenshotsDir, filename);\n\n // Save the image (base64 data URL) if provided\n if (hasImageData) {\n const base64Data = imageData.includes(\",\")\n ? imageData.split(\",\")[1]\n : imageData;\n writeFileSync(imagePath, Buffer.from(base64Data, \"base64\"));\n }\n\n // Save manifest and analysis result as JSON sidecar\n if (hasSidecar) {\n const jsonFilename = filename.replace(/\\\\.(png|jpeg|jpg)$/, \".json\");\n const jsonPath = join(screenshotsDir, jsonFilename);\n\n // If a sidecar already exists, merge updates (lets us POST analysisResult later without re-sending image).\n let existing: any = null;\n if (existsSync(jsonPath)) {\n try {\n existing = JSON.parse(readFileSync(jsonPath, \"utf-8\"));\n } catch {\n existing = null;\n }\n }\n\n const routeFromAnalysis =\n analysisResult && typeof analysisResult === \"object\"\n ? (analysisResult as any).route\n : undefined;\n const issuesFromAnalysis =\n analysisResult && typeof analysisResult === \"object\"\n ? (analysisResult as any).issues\n : undefined;\n\n const jsonData = {\n ...(existing && typeof existing === \"object\" ? existing : {}),\n timestamp: Date.now(),\n filename,\n screenshotFile: filename,\n route:\n typeof routeFromAnalysis === \"string\"\n ? routeFromAnalysis\n : (existing as any)?.route ?? null,\n issues:\n Array.isArray(issuesFromAnalysis)\n ? issuesFromAnalysis\n : (existing as any)?.issues ?? null,\n manifest: typeof manifest === \"undefined\" ? existing?.manifest ?? null : manifest,\n analysisResult:\n typeof analysisResult === \"undefined\"\n ? existing?.analysisResult ?? null\n : analysisResult,\n };\n writeFileSync(jsonPath, JSON.stringify(jsonData, null, 2));\n }\n\n return NextResponse.json({\n success: true,\n path: imagePath,\n projectRoot,\n screenshotsDir,\n });\n } catch (error) {\n console.error(\"[Screenshot API] Error saving screenshot:\", error);\n return NextResponse.json(\n { error: \"Failed to save screenshot\" },\n { status: 500 }\n );\n }\n}\n\n/**\n * GET: Retrieve a screenshot or list available screenshots\n */\nexport async function GET(request: NextRequest) {\n // Block in production\n if (process.env.NODE_ENV === \"production\") {\n return NextResponse.json(\n { error: \"Not available in production\" },\n { status: 404 }\n );\n }\n\n const { searchParams } = new URL(request.url);\n const filename = searchParams.get(\"filename\");\n const list = searchParams.get(\"list\");\n\n const projectRoot = findNextProjectRoot();\n const screenshotsDir = getScreenshotsDir(projectRoot);\n\n // List mode: return all screenshots\n if (list === \"true\") {\n try {\n const files = readdirSync(screenshotsDir);\n const screenshots = files\n .filter((f) => /\\\\.(png|jpeg|jpg)$/.test(f))\n .map((f) => {\n const jsonFile = f.replace(/\\\\.(png|jpeg|jpg)$/, \".json\");\n const jsonPath = join(screenshotsDir, jsonFile);\n let metadata = null;\n if (existsSync(jsonPath)) {\n try {\n metadata = JSON.parse(readFileSync(jsonPath, \"utf-8\"));\n } catch {\n // Ignore parse errors\n }\n }\n return {\n filename: f,\n metadata,\n };\n })\n .sort((a, b) => {\n // Sort by timestamp descending (newest first)\n const aTime = a.metadata?.timestamp || 0;\n const bTime = b.metadata?.timestamp || 0;\n return bTime - aTime;\n });\n\n return NextResponse.json({ screenshots, projectRoot, screenshotsDir });\n } catch (error) {\n console.error(\"[Screenshot API] Error listing screenshots:\", error);\n return NextResponse.json(\n { error: \"Failed to list screenshots\" },\n { status: 500 }\n );\n }\n }\n\n // Retrieve mode: get specific screenshot\n if (!filename) {\n return NextResponse.json(\n { error: \"Missing 'filename' parameter\" },\n { status: 400 }\n );\n }\n\n if (!isValidFilename(filename)) {\n return NextResponse.json(\n { error: \"Invalid filename format\" },\n { status: 400 }\n );\n }\n\n const filePath = join(screenshotsDir, filename);\n\n if (!existsSync(filePath)) {\n return NextResponse.json(\n { error: \"Screenshot not found\" },\n { status: 404 }\n );\n }\n\n try {\n const content = readFileSync(filePath);\n \n // Determine content type\n const ext = filename.split(\".\").pop()?.toLowerCase();\n const contentType =\n ext === \"json\"\n ? \"application/json\"\n : ext === \"png\"\n ? \"image/png\"\n : \"image/jpeg\";\n\n if (ext === \"json\") {\n return NextResponse.json(JSON.parse(content.toString()));\n }\n\n return new NextResponse(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Cache-Control\": \"no-cache\",\n },\n });\n } catch (error) {\n console.error(\"[Screenshot API] Error reading screenshot:\", error);\n return NextResponse.json(\n { error: \"Failed to read screenshot\" },\n { status: 500 }\n );\n }\n}\n`;\n\nasync function writeRouteFile(\n absPath: string,\n relPath: string,\n content: string,\n opts: InstallNextRoutesOptions\n): Promise<void> {\n // This generator is deterministic; no confirmOverwrite prompts needed.\n // If a file exists and we're not forcing, just skip it.\n if (existsSync(absPath) && !opts.force) return;\n await writeFile(absPath, content, \"utf-8\");\n}\n\nexport async function installNextUILintRoutes(\n opts: InstallNextRoutesOptions\n): Promise<void> {\n const baseRel = join(opts.appRoot, \"api\", \".uilint\");\n const baseAbs = join(opts.projectPath, baseRel);\n\n // UILint API routes\n\n // Source file API (for source visualization in overlay)\n await mkdir(join(baseAbs, \"source\"), { recursive: true });\n\n await writeRouteFile(\n join(baseAbs, \"source\", \"route.ts\"),\n join(baseRel, \"source\", \"route.ts\"),\n DEV_SOURCE_ROUTE_TS,\n opts\n );\n\n // Screenshot API (for vision analysis screenshots)\n await mkdir(join(baseAbs, \"screenshots\"), { recursive: true });\n\n await writeRouteFile(\n join(baseAbs, \"screenshots\", \"route.ts\"),\n join(baseRel, \"screenshots\", \"route.ts\"),\n SCREENSHOT_ROUTE_TS,\n opts\n );\n}\n","/**\n * Prompter interface and CLI implementation\n *\n * The Prompter interface abstracts all interactive prompts, allowing\n * tests to provide canned responses instead of real user input.\n */\n\nimport type { RuleMetadata, OptionFieldSchema } from \"uilint-eslint\";\nimport { ruleRegistry } from \"uilint-eslint\";\nimport { confirm, select, multiselect, text, pc } from \"../../utils/prompts.js\";\nimport { formatPackageOption } from \"../../utils/package-detect.js\";\nimport type {\n InstallItem,\n NextAppInfo,\n ViteAppInfo,\n EslintPackageInfo,\n UserChoices,\n EslintChoices,\n NextChoices,\n ViteChoices,\n ProjectState,\n InstallOptions,\n} from \"./types.js\";\n\n// ============================================================================\n// Prompter Interface\n// ============================================================================\n\nexport interface Prompter {\n /**\n * Select which items to install\n */\n selectInstallItems(): Promise<InstallItem[]>;\n\n /**\n * Select which Next.js app to install into (when multiple found)\n */\n selectNextApp(apps: NextAppInfo[]): Promise<NextAppInfo>;\n\n /**\n * Select which Vite app to install into (when multiple found)\n */\n selectViteApp(apps: ViteAppInfo[]): Promise<ViteAppInfo>;\n\n /**\n * Select which packages to install ESLint plugin into\n */\n selectEslintPackages(packages: EslintPackageInfo[]): Promise<string[]>;\n\n /**\n * Select which ESLint rules to enable\n */\n selectEslintRules(): Promise<RuleMetadata[]>;\n\n /**\n * Select severity to apply to selected ESLint rules\n *\n * - \"warn\": configure all selected rules as warnings\n * - \"error\": configure all selected rules as errors\n * - \"defaults\": keep each rule's defaultSeverity from the registry\n */\n selectEslintRuleSeverity(): Promise<\"warn\" | \"error\" | \"defaults\">;\n\n /**\n * Ask whether to customize individual rule options\n */\n confirmCustomizeRuleOptions(): Promise<boolean>;\n\n /**\n * Configure a single rule's options based on its schema\n * Returns the configured options object\n */\n configureRuleOptions(\n rule: RuleMetadata\n ): Promise<Record<string, unknown> | undefined>;\n}\n\n// ============================================================================\n// CLI Prompter Implementation (uses @clack/prompts)\n// ============================================================================\n\nexport const cliPrompter: Prompter = {\n async selectInstallItems(): Promise<InstallItem[]> {\n return multiselect<InstallItem>({\n message: \"What would you like to install?\",\n options: [\n {\n value: \"eslint\",\n label: \"ESLint plugin\",\n hint: \"Installs uilint-eslint and configures eslint.config.*\",\n },\n {\n value: \"next\",\n label: \"UI overlay\",\n hint: \"Installs routes + devtools (Alt+Click to inspect)\",\n },\n {\n value: \"vite\",\n label: \"UI overlay (Vite)\",\n hint: \"Installs jsx-loc-plugin + devtools (Alt+Click to inspect)\",\n },\n {\n value: \"genstyleguide\",\n label: \"/genstyleguide command\",\n hint: \"Adds .cursor/commands/genstyleguide.md\",\n },\n {\n value: \"skill\",\n label: \"UI Consistency Agent Skill\",\n hint: \"Cursor agent skill for generating ESLint rules from UI patterns\",\n },\n ],\n required: true,\n initialValues: [\"eslint\", \"next\", \"genstyleguide\", \"skill\"],\n });\n },\n\n async selectNextApp(apps: NextAppInfo[]): Promise<NextAppInfo> {\n const chosen = await select<string>({\n message: \"Which Next.js App Router project should UILint install into?\",\n options: apps.map((app) => ({\n value: app.projectPath,\n label: app.projectPath,\n })),\n initialValue: apps[0].projectPath,\n });\n\n return apps.find((a) => a.projectPath === chosen) || apps[0];\n },\n\n async selectViteApp(apps: ViteAppInfo[]): Promise<ViteAppInfo> {\n const chosen = await select<string>({\n message: \"Which Vite + React project should UILint install into?\",\n options: apps.map((app) => ({\n value: app.projectPath,\n label: app.projectPath,\n })),\n initialValue: apps[0].projectPath,\n });\n\n return apps.find((a) => a.projectPath === chosen) || apps[0];\n },\n\n async selectEslintPackages(packages: EslintPackageInfo[]): Promise<string[]> {\n if (packages.length === 1) {\n const confirmed = await confirm({\n message: `Install ESLint plugin in ${pc.cyan(\n packages[0].displayPath\n )}?`,\n initialValue: true,\n });\n return confirmed ? [packages[0].path] : [];\n }\n\n // Pre-select first frontend packages\n const initialValues = packages\n .filter((p) => p.isFrontend)\n .map((p) => p.path)\n .slice(0, 1);\n\n return multiselect<string>({\n message: \"Which packages should have ESLint plugin installed?\",\n options: packages.map(formatPackageOption),\n required: false,\n initialValues:\n initialValues.length > 0 ? initialValues : [packages[0].path],\n });\n },\n\n async selectEslintRules(): Promise<RuleMetadata[]> {\n const selectedRuleIds = await multiselect<string>({\n message: \"Which rules would you like to enable?\",\n options: ruleRegistry.map((rule: RuleMetadata) => ({\n value: rule.id,\n label: rule.name,\n hint: rule.description,\n })),\n required: false,\n initialValues: ruleRegistry\n .filter(\n (r: RuleMetadata) => r.category === \"static\" || !r.requiresStyleguide\n )\n .map((r: RuleMetadata) => r.id),\n });\n\n return ruleRegistry.filter((r: RuleMetadata) =>\n selectedRuleIds.includes(r.id)\n );\n },\n\n async selectEslintRuleSeverity(): Promise<\"warn\" | \"error\" | \"defaults\"> {\n return select<\"warn\" | \"error\" | \"defaults\">({\n message: \"How strict should the selected ESLint rules be?\",\n options: [\n {\n value: \"warn\",\n label: \"Warn (recommended)\",\n hint: \"Safer default while you dial in your styleguide + rules\",\n },\n {\n value: \"error\",\n label: \"Error (strict)\",\n hint: \"Make selected rules fail CI\",\n },\n {\n value: \"defaults\",\n label: \"Use rule defaults\",\n hint: \"Some rules are warn, some are error (as defined by uilint-eslint)\",\n },\n ],\n initialValue: \"warn\",\n });\n },\n\n async confirmCustomizeRuleOptions(): Promise<boolean> {\n return confirm({\n message:\n \"Customize individual rule options? (spacing scale, thresholds, etc.)\",\n initialValue: false,\n });\n },\n\n async configureRuleOptions(\n rule: RuleMetadata\n ): Promise<Record<string, unknown> | undefined> {\n if (!rule.optionSchema || rule.optionSchema.fields.length === 0) {\n return undefined;\n }\n\n const options: Record<string, unknown> = {};\n\n for (const field of rule.optionSchema.fields) {\n const value = await promptForField(field, rule.name);\n if (value !== undefined) {\n options[field.key] = value;\n }\n }\n\n return Object.keys(options).length > 0 ? options : undefined;\n },\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Prompt for a single option field based on its schema\n */\nasync function promptForField(\n field: OptionFieldSchema,\n ruleName: string\n): Promise<unknown> {\n const message = `${pc.cyan(ruleName)} - ${field.label}`;\n\n switch (field.type) {\n case \"text\": {\n const result = await text({\n message,\n placeholder: field.placeholder,\n defaultValue:\n typeof field.defaultValue === \"string\"\n ? field.defaultValue\n : Array.isArray(field.defaultValue)\n ? field.defaultValue.join(\", \")\n : String(field.defaultValue),\n });\n // Special handling for comma-separated arrays (like spacing scale)\n if (field.key === \"scale\" && typeof result === \"string\") {\n const scale = result\n .split(\",\")\n .map((s) => parseFloat(s.trim()))\n .filter((n) => !isNaN(n));\n return scale.length > 0 ? scale : field.defaultValue;\n }\n return result || field.defaultValue;\n }\n\n case \"number\": {\n const result = await text({\n message,\n placeholder: field.placeholder || String(field.defaultValue),\n defaultValue: String(field.defaultValue),\n });\n const num = parseFloat(result);\n return isNaN(num) ? field.defaultValue : num;\n }\n\n case \"boolean\": {\n return await confirm({\n message,\n initialValue: Boolean(field.defaultValue),\n });\n }\n\n case \"select\": {\n if (!field.options) {\n return field.defaultValue;\n }\n // Convert all values to strings for select\n const stringOptions = field.options.map(\n (opt: { value: string | number; label: string }) => ({\n value: String(opt.value),\n label: opt.label,\n })\n );\n const result = await select<string>({\n message,\n options: stringOptions,\n initialValue: String(field.defaultValue),\n });\n // Convert back to original type if needed\n const originalOpt = field.options.find(\n (opt: { value: string | number; label: string }) =>\n String(opt.value) === result\n );\n return originalOpt?.value ?? result;\n }\n\n case \"multiselect\": {\n if (!field.options) {\n return field.defaultValue;\n }\n // Convert all values to strings for multiselect\n const stringOptions = field.options.map(\n (opt: { value: string | number; label: string }) => ({\n value: String(opt.value),\n label: opt.label,\n })\n );\n const result = await multiselect<string>({\n message,\n options: stringOptions,\n initialValues: Array.isArray(field.defaultValue)\n ? (field.defaultValue as unknown[]).map((v) => String(v))\n : [String(field.defaultValue)],\n });\n // Convert back to original types\n return result.map((selected) => {\n const originalOpt = field.options!.find(\n (opt: { value: string | number; label: string }) =>\n String(opt.value) === selected\n );\n return originalOpt?.value ?? selected;\n });\n }\n\n default:\n return field.defaultValue;\n }\n}\n\n// ============================================================================\n// Choice Gathering Logic\n// ============================================================================\n\n/**\n * Gather all user choices using the prompter or CLI flags\n */\nexport async function gatherChoices(\n state: ProjectState,\n options: InstallOptions,\n prompter: Prompter\n): Promise<UserChoices> {\n // Determine items from flags or prompts\n let items: InstallItem[];\n\n const hasExplicitFlags =\n options.genstyleguide !== undefined ||\n options.skill !== undefined ||\n options.routes !== undefined ||\n options.react !== undefined;\n\n if (hasExplicitFlags || options.eslint) {\n items = [];\n if (options.genstyleguide) items.push(\"genstyleguide\");\n if (options.skill) items.push(\"skill\");\n if (options.routes || options.react) items.push(\"next\");\n if (options.eslint) items.push(\"eslint\");\n } else {\n items = await prompter.selectInstallItems();\n }\n\n // Next.js app selection\n let nextChoices: NextChoices | undefined;\n if (items.includes(\"next\")) {\n if (state.nextApps.length === 0) {\n throw new Error(\n \"Could not find a Next.js App Router app root (expected app/ or src/app/). Run this from your Next.js project root.\"\n );\n } else if (state.nextApps.length === 1) {\n nextChoices = {\n projectPath: state.nextApps[0].projectPath,\n detection: state.nextApps[0].detection,\n };\n } else {\n const selected = await prompter.selectNextApp(state.nextApps);\n nextChoices = {\n projectPath: selected.projectPath,\n detection: selected.detection,\n };\n }\n }\n\n // Vite app selection\n let viteChoices: ViteChoices | undefined;\n if (items.includes(\"vite\")) {\n if (state.viteApps.length === 0) {\n throw new Error(\n \"Could not find a Vite + React project (expected vite.config.* + react deps). Run this from your Vite project root.\"\n );\n } else if (state.viteApps.length === 1) {\n viteChoices = {\n projectPath: state.viteApps[0].projectPath,\n detection: state.viteApps[0].detection,\n };\n } else {\n const selected = await prompter.selectViteApp(state.viteApps);\n viteChoices = {\n projectPath: selected.projectPath,\n detection: selected.detection,\n };\n }\n }\n\n // ESLint choices\n let eslintChoices: EslintChoices | undefined;\n if (items.includes(\"eslint\")) {\n // Filter to packages with ESLint config\n const packagesWithEslint = state.packages.filter(\n (p) => p.eslintConfigPath !== null\n );\n\n if (packagesWithEslint.length === 0) {\n throw new Error(\n \"No packages with eslint.config.{ts,mjs,js,cjs} found. Create an ESLint config first.\"\n );\n }\n\n const packagePaths = await prompter.selectEslintPackages(\n packagesWithEslint\n );\n\n if (packagePaths.length > 0) {\n let selectedRules = await prompter.selectEslintRules();\n\n // Apply a global severity choice (default: warn)\n const severity = await prompter.selectEslintRuleSeverity();\n if (severity !== \"defaults\") {\n selectedRules = selectedRules.map((rule) => ({\n ...rule,\n defaultSeverity: severity,\n }));\n }\n\n // Ask if user wants to customize individual rule options\n const hasConfigurableRules = selectedRules.some(\n (r) => r.optionSchema && r.optionSchema.fields.length > 0\n );\n\n if (hasConfigurableRules) {\n const customizeOptions = await prompter.confirmCustomizeRuleOptions();\n\n if (customizeOptions) {\n selectedRules = await configureRuleOptions(selectedRules, prompter);\n }\n }\n\n eslintChoices = { packagePaths, selectedRules };\n }\n }\n\n return {\n items,\n next: nextChoices,\n vite: viteChoices,\n eslint: eslintChoices,\n };\n}\n\n/**\n * Configure options for individual rules based on their schemas\n */\nasync function configureRuleOptions(\n rules: RuleMetadata[],\n prompter: Prompter\n): Promise<RuleMetadata[]> {\n const configured: RuleMetadata[] = [];\n\n for (const rule of rules) {\n if (rule.optionSchema && rule.optionSchema.fields.length > 0) {\n const options = await prompter.configureRuleOptions(rule);\n if (options) {\n // Merge with existing defaultOptions structure\n const existingOptions =\n rule.defaultOptions && rule.defaultOptions.length > 0\n ? (rule.defaultOptions[0] as Record<string, unknown>)\n : ({} as Record<string, unknown>);\n configured.push({\n ...rule,\n defaultOptions: [{ ...existingOptions, ...options }],\n });\n } else {\n configured.push(rule);\n }\n } else {\n // No configuration needed for this rule\n configured.push(rule);\n }\n }\n\n return configured;\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: 'vision:analyze', route: string, timestamp: number, screenshot?: string, screenshotFile?: string, manifest: ElementManifest[], 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: 'vision:result', route: string, issues: VisionIssue[], analysisTime: number, error?: string, requestId?: string }\n * - Server -> Client: { type: 'vision:progress', route: string, phase: string, requestId?: string }\n */\n\nimport { existsSync, statSync, readdirSync, readFileSync } from \"fs\";\nimport { createRequire } from \"module\";\nimport { dirname, resolve, relative, join, parse } from \"path\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { watch, type FSWatcher } from \"chokidar\";\nimport {\n findWorkspaceRoot,\n getVisionAnalyzer as getCoreVisionAnalyzer,\n} from \"uilint-core/node\";\nimport {\n detectNextAppRouter,\n findNextAppRouterProjects,\n} from \"../utils/next-detect.js\";\nimport {\n runVisionAnalysis,\n writeVisionMarkdownReport,\n} from \"../utils/vision-run.js\";\nimport {\n logInfo,\n logSuccess,\n logWarning,\n logError,\n pc,\n} from \"../utils/prompts.js\";\n\nexport interface ServeOptions {\n port?: number;\n}\n\nexport interface LintIssue {\n line: number;\n column?: number;\n message: string;\n ruleId?: string;\n dataLoc?: string;\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: ElementManifest[];\n requestId?: string;\n}\n\ntype ClientMessage =\n | LintFileMessage\n | LintElementMessage\n | SubscribeFileMessage\n | CacheInvalidateMessage\n | VisionAnalyzeMessage;\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 VisionResultMessage {\n type: \"vision:result\";\n route: string;\n issues: VisionIssue[];\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\ntype ServerMessage =\n | LintResultMessage\n | LintProgressMessage\n | FileChangedMessage\n | WorkspaceInfoMessage\n | VisionResultMessage\n | VisionProgressMessage;\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// 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// ESLint instances cached per detected project root\nconst eslintInstances = new Map<string, unknown>();\n\n// Vision analyzer instance (lazy loaded)\ntype VisionIssue = {\n elementText: string;\n dataLoc?: string;\n message: string;\n category: string;\n severity: string;\n suggestion?: string;\n};\n\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};\n\nlet visionAnalyzer: ReturnType<typeof getCoreVisionAnalyzer> | null = null;\n\nfunction getVisionAnalyzerInstance(): ReturnType<typeof getCoreVisionAnalyzer> {\n if (!visionAnalyzer) {\n visionAnalyzer = getCoreVisionAnalyzer();\n }\n return visionAnalyzer;\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 // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => any;\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: any): 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 as any)[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\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<any | null> {\n const cached = eslintInstances.get(projectCwd);\n if (cached) return cached as any;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n // eslint-disable-next-line @typescript-eslint/no-var-requires\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 * Lint a file and return issues\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.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\n try {\n onProgress(\"Building JSX map...\");\n const code = readFileSync(absolutePath, \"utf-8\");\n codeLength = code.length;\n lineStarts = buildLineStarts(code);\n spans = buildJsxElementSpans(code, 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 console.error(\"[uilint-serve] JSX map failed:\", e);\n spans = [];\n lineStarts = [];\n codeLength = 0;\n }\n\n const issues: LintIssue[] = messages\n .filter((m: any) => typeof m?.message === \"string\")\n .map((m: any) => {\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,\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 onProgress(\n `Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`\n );\n }\n\n cache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n console.error(\"[uilint-serve] ESLint failed:\", error);\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 any).filePath as string | undefined;\n const rid = (message as any).requestId as string | undefined;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(message.type)} ${pc.dim(fp ?? \"\")}${\n rid ? ` ${pc.dim(`(req ${rid})`)}` : \"\"\n }`\n );\n } else if (message.type === \"subscribe:file\") {\n logInfo(`${pc.dim(\"[ws]\")} subscribe:file ${pc.dim(message.filePath)}`);\n } else if (message.type === \"cache:invalidate\") {\n logInfo(\n `${pc.dim(\"[ws]\")} cache:invalidate ${pc.dim(\n message.filePath ?? \"(all)\"\n )}`\n );\n } else if (message.type === \"vision:analyze\") {\n // Logged in handler for more detailed output\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 logWarning(\n [\n `${pc.dim(\"[ws]\")} File not found for request`,\n ` filePath: ${pc.dim(filePath)}`,\n ` resolved: ${pc.dim(resolved)}`,\n ` cwd: ${pc.dim(cwd)}`,\n ` wsRoot: ${pc.dim(wsRoot)}`,\n ` hint: In monorepos, ensure paths like ${pc.dim(\n \"app/page.tsx\"\n )} exist under ${pc.dim(\"apps/*/\")} or use absolute paths.`,\n ].join(\"\\n\")\n );\n }\n\n const issues = await lintFile(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n const elapsed = Date.now() - startedAt;\n logInfo(\n `${pc.dim(\"[ws]\")} lint:file done ${pc.dim(filePath)} → ${pc.bold(\n `${issues.length}`\n )} issue(s) ${pc.dim(`(${elapsed}ms)`)}`\n );\n\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${issues.length} issues, ${elapsed}ms)`,\n });\n sendMessage(ws, { type: \"lint:result\", filePath, requestId, issues });\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 const issues = await lintFile(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n // Filter to only issues matching the dataLoc\n const filteredIssues = issues.filter(\n (issue) => issue.dataLoc === dataLoc\n );\n\n const elapsed = Date.now() - startedAt;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${filteredIssues.length} issues, ${elapsed}ms)`,\n });\n sendMessage(ws, {\n type: \"lint:result\",\n filePath,\n requestId,\n issues: filteredIssues,\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 break;\n }\n\n case \"cache:invalidate\": {\n const { filePath } = message;\n if (filePath) {\n const absolutePath = resolveRequestedFilePath(filePath);\n cache.delete(absolutePath);\n } else {\n cache.clear();\n }\n break;\n }\n\n case \"vision:analyze\": {\n const {\n route,\n timestamp,\n screenshot,\n screenshotFile,\n manifest,\n requestId,\n } = message;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(\"vision:analyze\")} ${pc.dim(route)}${\n requestId ? ` ${pc.dim(`(req ${requestId})`)}` : \"\"\n }`\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 = getVisionAnalyzerInstance();\n\n try {\n const screenshotBytes =\n typeof screenshot === \"string\" ? Buffer.byteLength(screenshot) : 0;\n const analyzerModel =\n typeof (analyzer as any).getModel === \"function\"\n ? ((analyzer as any).getModel() as string)\n : undefined;\n const analyzerBaseUrl =\n typeof (analyzer as any).getBaseUrl === \"function\"\n ? ((analyzer as any).getBaseUrl() as string)\n : undefined;\n logInfo(\n [\n `${pc.dim(\"[ws]\")} ${pc.dim(\"vision\")} details`,\n ` route: ${pc.dim(route)}`,\n ` requestId: ${pc.dim(requestId ?? \"(none)\")}`,\n ` manifest: ${pc.dim(String(manifest.length))} element(s)`,\n ` screenshot: ${pc.dim(\n screenshot ? `${Math.round(screenshotBytes / 1024)}kb` : \"none\"\n )}`,\n ` screenshotFile: ${pc.dim(screenshotFile ?? \"(none)\")}`,\n ` ollamaUrl: ${pc.dim(analyzerBaseUrl ?? \"(default)\")}`,\n ` visionModel: ${pc.dim(analyzerModel ?? \"(default)\")}`,\n ].join(\"\\n\")\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 break;\n }\n\n const result = await runVisionAnalysis({\n imageBase64: screenshot,\n manifest,\n projectPath: serverAppRootForVision,\n // In the overlay/server context, default to upward search from app root.\n baseUrl: analyzerBaseUrl,\n model: analyzerModel,\n analyzer: analyzer as any,\n onPhase: (phase) => {\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase,\n });\n },\n });\n\n // Write a markdown report alongside the saved screenshot (best-effort).\n if (typeof screenshotFile === \"string\" && screenshotFile.length > 0) {\n if (!isValidScreenshotFilename(screenshotFile)) {\n logWarning(\n `Skipping vision report write: invalid screenshotFile ${pc.dim(\n screenshotFile\n )}`\n );\n } else {\n const screenshotsDir = join(\n serverAppRootForVision,\n \".uilint\",\n \"screenshots\"\n );\n const imagePath = join(screenshotsDir, screenshotFile);\n try {\n if (!existsSync(imagePath)) {\n logWarning(\n `Skipping vision report write: screenshot file not found ${pc.dim(\n imagePath\n )}`\n );\n } else {\n const report = 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 logInfo(\n `${pc.dim(\"[ws]\")} wrote vision report ${pc.dim(\n report.outPath\n )}`\n );\n }\n } catch (e) {\n logWarning(\n `Failed to write vision report for ${pc.dim(screenshotFile)}: ${\n e instanceof Error ? e.message : String(e)\n }`\n );\n }\n }\n }\n\n const elapsed = Date.now() - startedAt;\n logInfo(\n `${pc.dim(\"[ws]\")} vision:analyze done ${pc.dim(route)} → ${pc.bold(\n `${result.issues.length}`\n )} issue(s) ${pc.dim(`(${elapsed}ms)`)}`\n );\n\n if (result.rawResponse) {\n logInfo(\n `${pc.dim(\"[ws]\")} vision rawResponse ${pc.dim(\n `${result.rawResponse.length} chars`\n )}`\n );\n }\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: result.issues,\n analysisTime: result.analysisTime,\n requestId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? error.stack : undefined;\n logError(\n [\n `Vision analysis failed`,\n ` route: ${route}`,\n ` requestId: ${requestId ?? \"(none)\"}`,\n ` error: ${errorMessage}`,\n stack ? ` stack:\\n${stack}` : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\")\n );\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: Date.now() - startedAt,\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}\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\n // Notify subscribers\n for (const { ws, clientFilePath } of subscribers) {\n sendMessage(ws, { type: \"file:changed\", filePath: clientFilePath });\n }\n}\n\n/**\n * Start the WebSocket server\n */\nexport async function serve(options: ServeOptions): Promise<void> {\n const port = options.port || 9234;\n\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n const appRoot = pickAppRoot({ cwd, workspaceRoot: wsRoot });\n serverAppRootForVision = appRoot;\n logInfo(`Workspace root: ${pc.dim(wsRoot)}`);\n logInfo(`App root: ${pc.dim(appRoot)}`);\n logInfo(`Server cwd: ${pc.dim(cwd)}`);\n\n // Create file watcher\n fileWatcher = watch([], {\n persistent: true,\n ignoreInitial: true,\n });\n\n fileWatcher.on(\"change\", (path) => {\n handleFileChange(resolve(path));\n });\n\n // Create WebSocket server\n const wss = new WebSocketServer({ port });\n\n wss.on(\"connection\", (ws) => {\n connectedClients += 1;\n logInfo(`Client connected (${connectedClients} total)`);\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 ws.on(\"message\", (data) => {\n handleMessage(ws, data.toString());\n });\n\n ws.on(\"close\", () => {\n connectedClients = Math.max(0, connectedClients - 1);\n logInfo(`Client disconnected (${connectedClients} total)`);\n handleDisconnect(ws);\n });\n\n ws.on(\"error\", (error) => {\n logError(`WebSocket error: ${error.message}`);\n });\n });\n\n wss.on(\"error\", (error) => {\n logError(`Server error: ${error.message}`);\n });\n\n logSuccess(\n `UILint WebSocket server running on ${pc.cyan(`ws://localhost:${port}`)}`\n );\n logInfo(\"Press Ctrl+C to stop\");\n\n // Keep the server running\n await new Promise<void>((resolve) => {\n process.on(\"SIGINT\", () => {\n logInfo(\"Shutting down...\");\n wss.close();\n fileWatcher?.close();\n resolve();\n });\n });\n}\n","import { dirname, join, parse } from \"path\";\nimport { existsSync, statSync, mkdirSync, writeFileSync } from \"fs\";\nimport {\n ensureOllamaReady,\n findStyleGuidePath,\n findUILintStyleGuideUpwards,\n readStyleGuide,\n VisionAnalyzer,\n UILINT_DEFAULT_VISION_MODEL,\n type ElementManifest,\n type VisionIssue,\n type VisionAnalysisResult,\n type StreamProgressCallback,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"./path-specifiers.js\";\n\nexport type ResolveVisionStyleGuideArgs = {\n /** Project root / cwd used to resolve relative path specifiers */\n projectPath: string;\n /** Path to style guide file OR project directory */\n styleguide?: string;\n /** A starting point for upward search (directory). Defaults to projectPath. */\n startDir?: string;\n};\n\nexport type ResolveVisionStyleGuideResult = {\n styleGuide: string | null;\n styleguideLocation: string | null;\n};\n\nexport async function resolveVisionStyleGuide(\n args: ResolveVisionStyleGuideArgs\n): Promise<ResolveVisionStyleGuideResult> {\n const projectPath = args.projectPath;\n const startDir = args.startDir ?? projectPath;\n\n if (args.styleguide) {\n const styleguideArg = resolvePathSpecifier(args.styleguide, projectPath);\n if (existsSync(styleguideArg)) {\n const stat = statSync(styleguideArg);\n if (stat.isFile()) {\n return {\n styleguideLocation: styleguideArg,\n styleGuide: await readStyleGuide(styleguideArg),\n };\n }\n if (stat.isDirectory()) {\n const found = findStyleGuidePath(styleguideArg);\n return {\n styleguideLocation: found,\n styleGuide: found ? await readStyleGuide(found) : null,\n };\n }\n }\n return { styleGuide: null, styleguideLocation: null };\n }\n\n const upwards = findUILintStyleGuideUpwards(startDir);\n const fallback = upwards ?? findStyleGuidePath(projectPath);\n return {\n styleguideLocation: fallback,\n styleGuide: fallback ? await readStyleGuide(fallback) : null,\n };\n}\n\nexport type RunVisionAnalysisArgs = {\n /** base64 image data (NO data: prefix) */\n imageBase64: string;\n manifest: ElementManifest[];\n /** Used to resolve styleguide arg and as default search root */\n projectPath: string;\n /** Path to style guide file OR directory; if omitted uses upward search */\n styleguide?: string;\n /** Directory for upward styleguide search; defaults to projectPath */\n styleguideStartDir?: string;\n /**\n * Override resolved styleguide content (lets callers do logging/notes based on resolution once).\n * If provided (even null), styleguide resolution is skipped.\n */\n styleGuide?: string | null;\n /**\n * Override resolved styleguide location (pairs with styleGuide override).\n * If provided, this is returned in the result.\n */\n styleguideLocation?: string | null;\n /** Ollama base URL (default: http://localhost:11434) */\n baseUrl?: string;\n /** Vision model override (default: UILINT_DEFAULT_VISION_MODEL) */\n model?: string;\n /**\n * Optional analyzer instance (lets servers reuse a singleton and lets tests inject a mock).\n * If omitted, a new `VisionAnalyzer` is created with baseUrl+model.\n */\n analyzer?: Pick<VisionAnalyzer, \"analyzeScreenshot\">;\n /** Optional streaming progress callback passed into the analyzer */\n onProgress?: StreamProgressCallback;\n /** Optional coarse-grained phase callback (good for spinners / WS progress) */\n onPhase?: (phase: string) => void;\n /** When true, skip calling `ensureOllamaReady` (caller is responsible). */\n skipEnsureOllama?: boolean;\n /** Optional debug dump destination (file path or directory) */\n debugDump?: string;\n /** When true, include base64 image and full styleguide in debug dump */\n debugDumpIncludeSensitive?: boolean;\n /** Optional extra metadata to include in debug dumps */\n debugDumpMetadata?: Record<string, unknown>;\n};\n\nexport type RunVisionAnalysisResult = {\n issues: VisionIssue[];\n analysisTime: number;\n prompt?: string;\n rawResponse?: string;\n styleguideLocation: string | null;\n visionModel: string;\n baseUrl: string;\n};\n\nconst ollamaReadyOnce = new Map<string, Promise<void>>();\n\nasync function ensureOllamaReadyCached(params: {\n model: string;\n baseUrl: string;\n}): Promise<void> {\n const key = `${params.baseUrl}::${params.model}`;\n const existing = ollamaReadyOnce.get(key);\n if (existing) return existing;\n\n const p = ensureOllamaReady({ model: params.model, baseUrl: params.baseUrl })\n .then(() => undefined)\n .catch((e) => {\n // If startup/pull fails, allow retry on next request.\n ollamaReadyOnce.delete(key);\n throw e;\n });\n ollamaReadyOnce.set(key, p);\n return p;\n}\n\nfunction writeVisionDebugDump(params: {\n dumpPath: string;\n now: Date;\n inputs: {\n imageBase64: string;\n manifest: ElementManifest[];\n styleguideLocation: string | null;\n styleGuide: string | null;\n };\n runtime: { visionModel: string; baseUrl: string };\n includeSensitive: boolean;\n metadata?: Record<string, unknown>;\n}): string {\n const resolvedDirOrFile = resolvePathSpecifier(\n params.dumpPath,\n process.cwd()\n );\n const safeStamp = params.now.toISOString().replace(/[:.]/g, \"-\");\n const dumpFile =\n resolvedDirOrFile.endsWith(\".json\") || resolvedDirOrFile.endsWith(\".jsonl\")\n ? resolvedDirOrFile\n : `${resolvedDirOrFile}/vision-debug-${safeStamp}.json`;\n\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: params.now.toISOString(),\n runtime: params.runtime,\n metadata: params.metadata ?? null,\n inputs: {\n imageBase64: params.includeSensitive\n ? params.inputs.imageBase64\n : \"(omitted; set debugDumpIncludeSensitive=true)\",\n manifest: params.inputs.manifest,\n styleguideLocation: params.inputs.styleguideLocation,\n styleGuide: params.includeSensitive\n ? params.inputs.styleGuide\n : \"(omitted; set debugDumpIncludeSensitive=true)\",\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n\n return dumpFile;\n}\n\nexport async function runVisionAnalysis(\n args: RunVisionAnalysisArgs\n): Promise<RunVisionAnalysisResult> {\n const visionModel = args.model || UILINT_DEFAULT_VISION_MODEL;\n const baseUrl = args.baseUrl ?? \"http://localhost:11434\";\n\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n\n if (args.styleGuide !== undefined) {\n styleGuide = args.styleGuide;\n styleguideLocation = args.styleguideLocation ?? null;\n } else {\n args.onPhase?.(\"Resolving styleguide...\");\n const resolved = await resolveVisionStyleGuide({\n projectPath: args.projectPath,\n styleguide: args.styleguide,\n startDir: args.styleguideStartDir,\n });\n styleGuide = resolved.styleGuide;\n styleguideLocation = resolved.styleguideLocation;\n }\n\n if (!args.skipEnsureOllama) {\n args.onPhase?.(\"Preparing Ollama...\");\n await ensureOllamaReadyCached({ model: visionModel, baseUrl });\n }\n\n if (args.debugDump) {\n writeVisionDebugDump({\n dumpPath: args.debugDump,\n now: new Date(),\n runtime: { visionModel, baseUrl },\n inputs: {\n imageBase64: args.imageBase64,\n manifest: args.manifest,\n styleguideLocation,\n styleGuide,\n },\n includeSensitive: Boolean(args.debugDumpIncludeSensitive),\n metadata: args.debugDumpMetadata,\n });\n }\n\n const analyzer =\n args.analyzer ??\n new VisionAnalyzer({\n baseUrl: args.baseUrl,\n visionModel,\n });\n\n args.onPhase?.(`Analyzing ${args.manifest.length} elements...`);\n const result: VisionAnalysisResult = await analyzer.analyzeScreenshot(\n args.imageBase64,\n args.manifest,\n {\n styleGuide,\n onProgress: args.onProgress,\n }\n );\n\n args.onPhase?.(\n `Done (${result.issues.length} issues, ${result.analysisTime}ms)`\n );\n\n return {\n issues: result.issues,\n analysisTime: result.analysisTime,\n // Prompt is available in newer uilint-core versions; keep this resilient across versions.\n prompt: (result as any).prompt,\n rawResponse: result.rawResponse,\n styleguideLocation,\n visionModel,\n baseUrl,\n };\n}\n\nexport type WriteVisionMarkdownReportArgs = {\n /** Absolute path to the source image file */\n imagePath: string;\n /** Route label (optional; included in report) */\n route?: string;\n /** Unix ms timestamp (optional; included in report) */\n timestamp?: number;\n visionModel?: string;\n baseUrl?: string;\n analysisTimeMs?: number;\n prompt?: string | null;\n rawResponse?: string | null;\n /** Extra JSON-ish metadata to include */\n metadata?: Record<string, unknown>;\n /**\n * Optional output path; if omitted, writes alongside the image:\n * `<basename>.vision.md`\n */\n outPath?: string;\n};\n\nexport function writeVisionMarkdownReport(\n args: WriteVisionMarkdownReportArgs\n): {\n outPath: string;\n content: string;\n} {\n const p = parse(args.imagePath);\n const outPath = args.outPath ?? join(p.dir, `${p.name || p.base}.vision.md`);\n\n const lines: string[] = [];\n lines.push(`# UILint Vision Report`);\n lines.push(``);\n lines.push(`- Image: \\`${p.base}\\``);\n if (args.route) lines.push(`- Route: \\`${args.route}\\``);\n if (typeof args.timestamp === \"number\") {\n lines.push(`- Timestamp: \\`${new Date(args.timestamp).toISOString()}\\``);\n }\n if (args.visionModel) lines.push(`- Model: \\`${args.visionModel}\\``);\n if (args.baseUrl) lines.push(`- Ollama baseUrl: \\`${args.baseUrl}\\``);\n if (typeof args.analysisTimeMs === \"number\")\n lines.push(`- Analysis time: \\`${args.analysisTimeMs}ms\\``);\n lines.push(`- Generated: \\`${new Date().toISOString()}\\``);\n lines.push(``);\n\n if (args.metadata && Object.keys(args.metadata).length > 0) {\n lines.push(`## Metadata`);\n lines.push(``);\n lines.push(\"```json\");\n lines.push(JSON.stringify(args.metadata, null, 2));\n lines.push(\"```\");\n lines.push(``);\n }\n\n lines.push(`## Prompt`);\n lines.push(``);\n lines.push(\"```text\");\n lines.push((args.prompt ?? \"\").trim());\n lines.push(\"```\");\n lines.push(``);\n\n lines.push(`## Raw Response`);\n lines.push(``);\n lines.push(\"```text\");\n lines.push((args.rawResponse ?? \"\").trim());\n lines.push(\"```\");\n lines.push(``);\n\n const content = lines.join(\"\\n\");\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, content, \"utf-8\");\n return { outPath, content };\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 mkdirSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n} from \"fs\";\nimport {\n ensureOllamaReady,\n STYLEGUIDE_PATHS,\n UILINT_DEFAULT_VISION_MODEL,\n type ElementManifest,\n type VisionIssue,\n} from \"uilint-core/node\";\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 resolveVisionStyleGuide,\n runVisionAnalysis,\n writeVisionMarkdownReport,\n} from \"../utils/vision-run.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<any>(p);\n const issues = Array.isArray(json?.issues)\n ? json.issues\n : json?.analysisResult?.issues;\n out.push({\n path: p,\n filename:\n json?.filename || json?.screenshotFile || 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 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 });\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 });\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 });\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 });\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"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["dirname","resolve","existsSync","formatViolationsText","sanitizeIssues","findWorkspaceRoot","resolve","join","__dirname","intro","outro","cancel","cancel","note","select","confirm","text","multiselect","text","resolve","intro","existsSync","dirname","note","p","sanitizeIssues","formatViolationsText","dirname","resolve","existsSync","mkdirSync","writeFileSync","ensureOllamaReady","readStyleGuide","findStyleGuidePath","findWorkspaceRoot","findUILintStyleGuideUpwards","envTruthy","preview","text","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","p","existsSync","readStyleGuide","findUILintStyleGuideUpwards","dirname","findStyleGuidePath","findWorkspaceRoot","intro","ensureOllamaReady","mkdirSync","writeFileSync","note","ensureOllamaReady","readStdin","resolve","intro","result","ensureOllamaReady","dirname","resolve","createStyleSummary","readStyleGuide","findStyleGuidePath","ensureOllamaReady","readTailwindThemeTokens","intro","findStyleGuidePath","note","readStyleGuide","dirname","resolve","readTailwindThemeTokens","ensureOllamaReady","createStyleSummary","outro","join","ruleRegistry","existsSync","readFileSync","join","findWorkspaceRoot","existsSync","join","existsSync","readdirSync","readFileSync","join","fileExists","DEFAULT_IGNORE_DIRS","existsSync","readdirSync","readFileSync","join","DEFAULT_IGNORE_DIRS","existsSync","dirname","join","resolve","existsSync","readFileSync","writeFileSync","join","relative","dirname","findWorkspaceRoot","p","unwrapExpression","program","dirname","join","relative","readFileSync","join","findWorkspaceRoot","existsSync","writeFileSync","analyze","findWorkspaceRoot","join","existsSync","readFileSync","join","createRequire","readFileSync","readdirSync","statSync","existsSync","join","dirname","relative","fileURLToPath","readFileSync","existsSync","join","dirname","fileURLToPath","__filename","__dirname","require","require","createRequire","join","p","existsSync","mkdirSync","writeFileSync","readFileSync","dirname","existsSync","readFileSync","writeFileSync","join","parseModule","generateCode","program","program","parseModule","join","readFileSync","generateCode","writeFileSync","existsSync","readFileSync","writeFileSync","join","parseModule","generateCode","CONFIG_EXTENSIONS","isIdentifier","isStringLiteral","program","parseModule","p","readFileSync","generateCode","writeFileSync","existsSync","readFileSync","writeFileSync","join","parseModule","generateCode","CONFIG_EXTENSIONS","findViteConfigFile","isIdentifier","isStringLiteral","program","p","jsxLocCall","existsSync","join","existsSync","mkdirSync","dirname","writeFileSync","readFileSync","installDependencies","multiselect","select","confirm","p","text","join","ruleRegistry","note","intro","analyze","outro","existsSync","statSync","readdirSync","readFileSync","createRequire","dirname","resolve","relative","join","parse","findWorkspaceRoot","dirname","join","existsSync","statSync","mkdirSync","writeFileSync","ensureOllamaReady","findStyleGuidePath","findUILintStyleGuideUpwards","readStyleGuide","existsSync","statSync","readStyleGuide","findStyleGuidePath","findUILintStyleGuideUpwards","p","ensureOllamaReady","mkdirSync","dirname","writeFileSync","join","createRequire","parse","ESLINT_CONFIG_FILES","existsSync","join","dirname","p","resolve","relative","findWorkspaceRoot","readdirSync","statSync","readFileSync","dirname","resolve","join","existsSync","readFileSync","readdirSync","ensureOllamaReady","STYLEGUIDE_PATHS","UILINT_DEFAULT_VISION_MODEL","envTruthy","preview","text","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","join","existsSync","dirname","readdirSync","p","readFileSync","intro","note","STYLEGUIDE_PATHS","UILINT_DEFAULT_VISION_MODEL","ensureOllamaReady","readFileSync","dirname","join","fileURLToPath","getCLIVersion","__dirname"]}
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/utils/vision-run.ts","../src/commands/vision.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 { readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nfunction assertNodeVersion(minMajor: number): void {\n const ver = process.versions.node || \"\";\n const majorStr = ver.split(\".\")[0] || \"\";\n const major = Number.parseInt(majorStr, 10);\n\n if (!Number.isFinite(major) || major < minMajor) {\n // Keep this dependency-free and stdout/stderr friendly.\n // eslint-disable-next-line no-console\n console.error(\n `uilint requires Node.js >= ${minMajor}. You are running Node.js ${ver}.`\n );\n process.exit(1);\n }\n}\n\nassertNodeVersion(20);\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// Install command\nprogram\n .command(\"install\")\n .description(\"Install UILint integration\")\n .option(\"--force\", \"Overwrite existing configuration files\")\n .action(async (options) => {\n const { installUI } = await import(\"./commands/install-ui.js\");\n await installUI({ force: options.force });\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 .action(async (options) => {\n await serve({\n port: parseInt(options.port, 10),\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\nprogram.parse();\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 readStyleGuideFromProject,\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: 'vision:analyze', route: string, timestamp: number, screenshot?: string, screenshotFile?: string, manifest: ElementManifest[], 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: 'vision:result', route: string, issues: VisionIssue[], analysisTime: number, error?: string, requestId?: string }\n * - Server -> Client: { type: 'vision:progress', route: string, phase: string, requestId?: string }\n */\n\nimport { existsSync, statSync, readdirSync, readFileSync } from \"fs\";\nimport { createRequire } from \"module\";\nimport { dirname, resolve, relative, join, parse } from \"path\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { watch, type FSWatcher } from \"chokidar\";\nimport {\n findWorkspaceRoot,\n getVisionAnalyzer as getCoreVisionAnalyzer,\n} from \"uilint-core/node\";\nimport {\n detectNextAppRouter,\n findNextAppRouterProjects,\n} from \"../utils/next-detect.js\";\nimport {\n runVisionAnalysis,\n writeVisionMarkdownReport,\n} from \"../utils/vision-run.js\";\nimport {\n logInfo,\n logSuccess,\n logWarning,\n logError,\n pc,\n} from \"../utils/prompts.js\";\n\nexport interface ServeOptions {\n port?: number;\n}\n\nexport interface LintIssue {\n line: number;\n column?: number;\n message: string;\n ruleId?: string;\n dataLoc?: string;\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: ElementManifest[];\n requestId?: string;\n}\n\ntype ClientMessage =\n | LintFileMessage\n | LintElementMessage\n | SubscribeFileMessage\n | CacheInvalidateMessage\n | VisionAnalyzeMessage;\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 VisionResultMessage {\n type: \"vision:result\";\n route: string;\n issues: VisionIssue[];\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\ntype ServerMessage =\n | LintResultMessage\n | LintProgressMessage\n | FileChangedMessage\n | WorkspaceInfoMessage\n | VisionResultMessage\n | VisionProgressMessage;\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// 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// ESLint instances cached per detected project root\nconst eslintInstances = new Map<string, unknown>();\n\n// Vision analyzer instance (lazy loaded)\ntype VisionIssue = {\n elementText: string;\n dataLoc?: string;\n message: string;\n category: string;\n severity: string;\n suggestion?: string;\n};\n\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};\n\nlet visionAnalyzer: ReturnType<typeof getCoreVisionAnalyzer> | null = null;\n\nfunction getVisionAnalyzerInstance(): ReturnType<typeof getCoreVisionAnalyzer> {\n if (!visionAnalyzer) {\n visionAnalyzer = getCoreVisionAnalyzer();\n }\n return visionAnalyzer;\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 // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => any;\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: any): 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 as any)[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\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<any | null> {\n const cached = eslintInstances.get(projectCwd);\n if (cached) return cached as any;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n // eslint-disable-next-line @typescript-eslint/no-var-requires\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 * Lint a file and return issues\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.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\n try {\n onProgress(\"Building JSX map...\");\n const code = readFileSync(absolutePath, \"utf-8\");\n codeLength = code.length;\n lineStarts = buildLineStarts(code);\n spans = buildJsxElementSpans(code, 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 console.error(\"[uilint-serve] JSX map failed:\", e);\n spans = [];\n lineStarts = [];\n codeLength = 0;\n }\n\n const issues: LintIssue[] = messages\n .filter((m: any) => typeof m?.message === \"string\")\n .map((m: any) => {\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,\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 onProgress(\n `Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`\n );\n }\n\n cache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n console.error(\"[uilint-serve] ESLint failed:\", error);\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 any).filePath as string | undefined;\n const rid = (message as any).requestId as string | undefined;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(message.type)} ${pc.dim(fp ?? \"\")}${\n rid ? ` ${pc.dim(`(req ${rid})`)}` : \"\"\n }`\n );\n } else if (message.type === \"subscribe:file\") {\n logInfo(`${pc.dim(\"[ws]\")} subscribe:file ${pc.dim(message.filePath)}`);\n } else if (message.type === \"cache:invalidate\") {\n logInfo(\n `${pc.dim(\"[ws]\")} cache:invalidate ${pc.dim(\n message.filePath ?? \"(all)\"\n )}`\n );\n } else if (message.type === \"vision:analyze\") {\n // Logged in handler for more detailed output\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 logWarning(\n [\n `${pc.dim(\"[ws]\")} File not found for request`,\n ` filePath: ${pc.dim(filePath)}`,\n ` resolved: ${pc.dim(resolved)}`,\n ` cwd: ${pc.dim(cwd)}`,\n ` wsRoot: ${pc.dim(wsRoot)}`,\n ` hint: In monorepos, ensure paths like ${pc.dim(\n \"app/page.tsx\"\n )} exist under ${pc.dim(\"apps/*/\")} or use absolute paths.`,\n ].join(\"\\n\")\n );\n }\n\n const issues = await lintFile(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n const elapsed = Date.now() - startedAt;\n logInfo(\n `${pc.dim(\"[ws]\")} lint:file done ${pc.dim(filePath)} → ${pc.bold(\n `${issues.length}`\n )} issue(s) ${pc.dim(`(${elapsed}ms)`)}`\n );\n\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${issues.length} issues, ${elapsed}ms)`,\n });\n sendMessage(ws, { type: \"lint:result\", filePath, requestId, issues });\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 const issues = await lintFile(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n // Filter to only issues matching the dataLoc\n const filteredIssues = issues.filter(\n (issue) => issue.dataLoc === dataLoc\n );\n\n const elapsed = Date.now() - startedAt;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${filteredIssues.length} issues, ${elapsed}ms)`,\n });\n sendMessage(ws, {\n type: \"lint:result\",\n filePath,\n requestId,\n issues: filteredIssues,\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 break;\n }\n\n case \"cache:invalidate\": {\n const { filePath } = message;\n if (filePath) {\n const absolutePath = resolveRequestedFilePath(filePath);\n cache.delete(absolutePath);\n } else {\n cache.clear();\n }\n break;\n }\n\n case \"vision:analyze\": {\n const {\n route,\n timestamp,\n screenshot,\n screenshotFile,\n manifest,\n requestId,\n } = message;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(\"vision:analyze\")} ${pc.dim(route)}${\n requestId ? ` ${pc.dim(`(req ${requestId})`)}` : \"\"\n }`\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 = getVisionAnalyzerInstance();\n\n try {\n const screenshotBytes =\n typeof screenshot === \"string\" ? Buffer.byteLength(screenshot) : 0;\n const analyzerModel =\n typeof (analyzer as any).getModel === \"function\"\n ? ((analyzer as any).getModel() as string)\n : undefined;\n const analyzerBaseUrl =\n typeof (analyzer as any).getBaseUrl === \"function\"\n ? ((analyzer as any).getBaseUrl() as string)\n : undefined;\n logInfo(\n [\n `${pc.dim(\"[ws]\")} ${pc.dim(\"vision\")} details`,\n ` route: ${pc.dim(route)}`,\n ` requestId: ${pc.dim(requestId ?? \"(none)\")}`,\n ` manifest: ${pc.dim(String(manifest.length))} element(s)`,\n ` screenshot: ${pc.dim(\n screenshot ? `${Math.round(screenshotBytes / 1024)}kb` : \"none\"\n )}`,\n ` screenshotFile: ${pc.dim(screenshotFile ?? \"(none)\")}`,\n ` ollamaUrl: ${pc.dim(analyzerBaseUrl ?? \"(default)\")}`,\n ` visionModel: ${pc.dim(analyzerModel ?? \"(default)\")}`,\n ].join(\"\\n\")\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 break;\n }\n\n const result = await runVisionAnalysis({\n imageBase64: screenshot,\n manifest,\n projectPath: serverAppRootForVision,\n // In the overlay/server context, default to upward search from app root.\n baseUrl: analyzerBaseUrl,\n model: analyzerModel,\n analyzer: analyzer as any,\n onPhase: (phase) => {\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase,\n });\n },\n });\n\n // Write a markdown report alongside the saved screenshot (best-effort).\n if (typeof screenshotFile === \"string\" && screenshotFile.length > 0) {\n if (!isValidScreenshotFilename(screenshotFile)) {\n logWarning(\n `Skipping vision report write: invalid screenshotFile ${pc.dim(\n screenshotFile\n )}`\n );\n } else {\n const screenshotsDir = join(\n serverAppRootForVision,\n \".uilint\",\n \"screenshots\"\n );\n const imagePath = join(screenshotsDir, screenshotFile);\n try {\n if (!existsSync(imagePath)) {\n logWarning(\n `Skipping vision report write: screenshot file not found ${pc.dim(\n imagePath\n )}`\n );\n } else {\n const report = 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 logInfo(\n `${pc.dim(\"[ws]\")} wrote vision report ${pc.dim(\n report.outPath\n )}`\n );\n }\n } catch (e) {\n logWarning(\n `Failed to write vision report for ${pc.dim(screenshotFile)}: ${\n e instanceof Error ? e.message : String(e)\n }`\n );\n }\n }\n }\n\n const elapsed = Date.now() - startedAt;\n logInfo(\n `${pc.dim(\"[ws]\")} vision:analyze done ${pc.dim(route)} → ${pc.bold(\n `${result.issues.length}`\n )} issue(s) ${pc.dim(`(${elapsed}ms)`)}`\n );\n\n if (result.rawResponse) {\n logInfo(\n `${pc.dim(\"[ws]\")} vision rawResponse ${pc.dim(\n `${result.rawResponse.length} chars`\n )}`\n );\n }\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: result.issues,\n analysisTime: result.analysisTime,\n requestId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? error.stack : undefined;\n logError(\n [\n `Vision analysis failed`,\n ` route: ${route}`,\n ` requestId: ${requestId ?? \"(none)\"}`,\n ` error: ${errorMessage}`,\n stack ? ` stack:\\n${stack}` : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\")\n );\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: Date.now() - startedAt,\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}\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\n // Notify subscribers\n for (const { ws, clientFilePath } of subscribers) {\n sendMessage(ws, { type: \"file:changed\", filePath: clientFilePath });\n }\n}\n\n/**\n * Start the WebSocket server\n */\nexport async function serve(options: ServeOptions): Promise<void> {\n const port = options.port || 9234;\n\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n const appRoot = pickAppRoot({ cwd, workspaceRoot: wsRoot });\n serverAppRootForVision = appRoot;\n logInfo(`Workspace root: ${pc.dim(wsRoot)}`);\n logInfo(`App root: ${pc.dim(appRoot)}`);\n logInfo(`Server cwd: ${pc.dim(cwd)}`);\n\n // Create file watcher\n fileWatcher = watch([], {\n persistent: true,\n ignoreInitial: true,\n });\n\n fileWatcher.on(\"change\", (path) => {\n handleFileChange(resolve(path));\n });\n\n // Create WebSocket server\n const wss = new WebSocketServer({ port });\n\n wss.on(\"connection\", (ws) => {\n connectedClients += 1;\n logInfo(`Client connected (${connectedClients} total)`);\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 ws.on(\"message\", (data) => {\n handleMessage(ws, data.toString());\n });\n\n ws.on(\"close\", () => {\n connectedClients = Math.max(0, connectedClients - 1);\n logInfo(`Client disconnected (${connectedClients} total)`);\n handleDisconnect(ws);\n });\n\n ws.on(\"error\", (error) => {\n logError(`WebSocket error: ${error.message}`);\n });\n });\n\n wss.on(\"error\", (error) => {\n logError(`Server error: ${error.message}`);\n });\n\n logSuccess(\n `UILint WebSocket server running on ${pc.cyan(`ws://localhost:${port}`)}`\n );\n logInfo(\"Press Ctrl+C to stop\");\n\n // Keep the server running\n await new Promise<void>((resolve) => {\n process.on(\"SIGINT\", () => {\n logInfo(\"Shutting down...\");\n wss.close();\n fileWatcher?.close();\n resolve();\n });\n });\n}\n","import { dirname, join, parse } from \"path\";\nimport { existsSync, statSync, mkdirSync, writeFileSync } from \"fs\";\nimport {\n ensureOllamaReady,\n findStyleGuidePath,\n findUILintStyleGuideUpwards,\n readStyleGuide,\n VisionAnalyzer,\n UILINT_DEFAULT_VISION_MODEL,\n type ElementManifest,\n type VisionIssue,\n type VisionAnalysisResult,\n type StreamProgressCallback,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"./path-specifiers.js\";\n\nexport type ResolveVisionStyleGuideArgs = {\n /** Project root / cwd used to resolve relative path specifiers */\n projectPath: string;\n /** Path to style guide file OR project directory */\n styleguide?: string;\n /** A starting point for upward search (directory). Defaults to projectPath. */\n startDir?: string;\n};\n\nexport type ResolveVisionStyleGuideResult = {\n styleGuide: string | null;\n styleguideLocation: string | null;\n};\n\nexport async function resolveVisionStyleGuide(\n args: ResolveVisionStyleGuideArgs\n): Promise<ResolveVisionStyleGuideResult> {\n const projectPath = args.projectPath;\n const startDir = args.startDir ?? projectPath;\n\n if (args.styleguide) {\n const styleguideArg = resolvePathSpecifier(args.styleguide, projectPath);\n if (existsSync(styleguideArg)) {\n const stat = statSync(styleguideArg);\n if (stat.isFile()) {\n return {\n styleguideLocation: styleguideArg,\n styleGuide: await readStyleGuide(styleguideArg),\n };\n }\n if (stat.isDirectory()) {\n const found = findStyleGuidePath(styleguideArg);\n return {\n styleguideLocation: found,\n styleGuide: found ? await readStyleGuide(found) : null,\n };\n }\n }\n return { styleGuide: null, styleguideLocation: null };\n }\n\n const upwards = findUILintStyleGuideUpwards(startDir);\n const fallback = upwards ?? findStyleGuidePath(projectPath);\n return {\n styleguideLocation: fallback,\n styleGuide: fallback ? await readStyleGuide(fallback) : null,\n };\n}\n\nexport type RunVisionAnalysisArgs = {\n /** base64 image data (NO data: prefix) */\n imageBase64: string;\n manifest: ElementManifest[];\n /** Used to resolve styleguide arg and as default search root */\n projectPath: string;\n /** Path to style guide file OR directory; if omitted uses upward search */\n styleguide?: string;\n /** Directory for upward styleguide search; defaults to projectPath */\n styleguideStartDir?: string;\n /**\n * Override resolved styleguide content (lets callers do logging/notes based on resolution once).\n * If provided (even null), styleguide resolution is skipped.\n */\n styleGuide?: string | null;\n /**\n * Override resolved styleguide location (pairs with styleGuide override).\n * If provided, this is returned in the result.\n */\n styleguideLocation?: string | null;\n /** Ollama base URL (default: http://localhost:11434) */\n baseUrl?: string;\n /** Vision model override (default: UILINT_DEFAULT_VISION_MODEL) */\n model?: string;\n /**\n * Optional analyzer instance (lets servers reuse a singleton and lets tests inject a mock).\n * If omitted, a new `VisionAnalyzer` is created with baseUrl+model.\n */\n analyzer?: Pick<VisionAnalyzer, \"analyzeScreenshot\">;\n /** Optional streaming progress callback passed into the analyzer */\n onProgress?: StreamProgressCallback;\n /** Optional coarse-grained phase callback (good for spinners / WS progress) */\n onPhase?: (phase: string) => void;\n /** When true, skip calling `ensureOllamaReady` (caller is responsible). */\n skipEnsureOllama?: boolean;\n /** Optional debug dump destination (file path or directory) */\n debugDump?: string;\n /** When true, include base64 image and full styleguide in debug dump */\n debugDumpIncludeSensitive?: boolean;\n /** Optional extra metadata to include in debug dumps */\n debugDumpMetadata?: Record<string, unknown>;\n};\n\nexport type RunVisionAnalysisResult = {\n issues: VisionIssue[];\n analysisTime: number;\n prompt?: string;\n rawResponse?: string;\n styleguideLocation: string | null;\n visionModel: string;\n baseUrl: string;\n};\n\nconst ollamaReadyOnce = new Map<string, Promise<void>>();\n\nasync function ensureOllamaReadyCached(params: {\n model: string;\n baseUrl: string;\n}): Promise<void> {\n const key = `${params.baseUrl}::${params.model}`;\n const existing = ollamaReadyOnce.get(key);\n if (existing) return existing;\n\n const p = ensureOllamaReady({ model: params.model, baseUrl: params.baseUrl })\n .then(() => undefined)\n .catch((e) => {\n // If startup/pull fails, allow retry on next request.\n ollamaReadyOnce.delete(key);\n throw e;\n });\n ollamaReadyOnce.set(key, p);\n return p;\n}\n\nfunction writeVisionDebugDump(params: {\n dumpPath: string;\n now: Date;\n inputs: {\n imageBase64: string;\n manifest: ElementManifest[];\n styleguideLocation: string | null;\n styleGuide: string | null;\n };\n runtime: { visionModel: string; baseUrl: string };\n includeSensitive: boolean;\n metadata?: Record<string, unknown>;\n}): string {\n const resolvedDirOrFile = resolvePathSpecifier(\n params.dumpPath,\n process.cwd()\n );\n const safeStamp = params.now.toISOString().replace(/[:.]/g, \"-\");\n const dumpFile =\n resolvedDirOrFile.endsWith(\".json\") || resolvedDirOrFile.endsWith(\".jsonl\")\n ? resolvedDirOrFile\n : `${resolvedDirOrFile}/vision-debug-${safeStamp}.json`;\n\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: params.now.toISOString(),\n runtime: params.runtime,\n metadata: params.metadata ?? null,\n inputs: {\n imageBase64: params.includeSensitive\n ? params.inputs.imageBase64\n : \"(omitted; set debugDumpIncludeSensitive=true)\",\n manifest: params.inputs.manifest,\n styleguideLocation: params.inputs.styleguideLocation,\n styleGuide: params.includeSensitive\n ? params.inputs.styleGuide\n : \"(omitted; set debugDumpIncludeSensitive=true)\",\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n\n return dumpFile;\n}\n\nexport async function runVisionAnalysis(\n args: RunVisionAnalysisArgs\n): Promise<RunVisionAnalysisResult> {\n const visionModel = args.model || UILINT_DEFAULT_VISION_MODEL;\n const baseUrl = args.baseUrl ?? \"http://localhost:11434\";\n\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n\n if (args.styleGuide !== undefined) {\n styleGuide = args.styleGuide;\n styleguideLocation = args.styleguideLocation ?? null;\n } else {\n args.onPhase?.(\"Resolving styleguide...\");\n const resolved = await resolveVisionStyleGuide({\n projectPath: args.projectPath,\n styleguide: args.styleguide,\n startDir: args.styleguideStartDir,\n });\n styleGuide = resolved.styleGuide;\n styleguideLocation = resolved.styleguideLocation;\n }\n\n if (!args.skipEnsureOllama) {\n args.onPhase?.(\"Preparing Ollama...\");\n await ensureOllamaReadyCached({ model: visionModel, baseUrl });\n }\n\n if (args.debugDump) {\n writeVisionDebugDump({\n dumpPath: args.debugDump,\n now: new Date(),\n runtime: { visionModel, baseUrl },\n inputs: {\n imageBase64: args.imageBase64,\n manifest: args.manifest,\n styleguideLocation,\n styleGuide,\n },\n includeSensitive: Boolean(args.debugDumpIncludeSensitive),\n metadata: args.debugDumpMetadata,\n });\n }\n\n const analyzer =\n args.analyzer ??\n new VisionAnalyzer({\n baseUrl: args.baseUrl,\n visionModel,\n });\n\n args.onPhase?.(`Analyzing ${args.manifest.length} elements...`);\n const result: VisionAnalysisResult = await analyzer.analyzeScreenshot(\n args.imageBase64,\n args.manifest,\n {\n styleGuide,\n onProgress: args.onProgress,\n }\n );\n\n args.onPhase?.(\n `Done (${result.issues.length} issues, ${result.analysisTime}ms)`\n );\n\n return {\n issues: result.issues,\n analysisTime: result.analysisTime,\n // Prompt is available in newer uilint-core versions; keep this resilient across versions.\n prompt: (result as any).prompt,\n rawResponse: result.rawResponse,\n styleguideLocation,\n visionModel,\n baseUrl,\n };\n}\n\nexport type WriteVisionMarkdownReportArgs = {\n /** Absolute path to the source image file */\n imagePath: string;\n /** Route label (optional; included in report) */\n route?: string;\n /** Unix ms timestamp (optional; included in report) */\n timestamp?: number;\n visionModel?: string;\n baseUrl?: string;\n analysisTimeMs?: number;\n prompt?: string | null;\n rawResponse?: string | null;\n /** Extra JSON-ish metadata to include */\n metadata?: Record<string, unknown>;\n /**\n * Optional output path; if omitted, writes alongside the image:\n * `<basename>.vision.md`\n */\n outPath?: string;\n};\n\nexport function writeVisionMarkdownReport(\n args: WriteVisionMarkdownReportArgs\n): {\n outPath: string;\n content: string;\n} {\n const p = parse(args.imagePath);\n const outPath = args.outPath ?? join(p.dir, `${p.name || p.base}.vision.md`);\n\n const lines: string[] = [];\n lines.push(`# UILint Vision Report`);\n lines.push(``);\n lines.push(`- Image: \\`${p.base}\\``);\n if (args.route) lines.push(`- Route: \\`${args.route}\\``);\n if (typeof args.timestamp === \"number\") {\n lines.push(`- Timestamp: \\`${new Date(args.timestamp).toISOString()}\\``);\n }\n if (args.visionModel) lines.push(`- Model: \\`${args.visionModel}\\``);\n if (args.baseUrl) lines.push(`- Ollama baseUrl: \\`${args.baseUrl}\\``);\n if (typeof args.analysisTimeMs === \"number\")\n lines.push(`- Analysis time: \\`${args.analysisTimeMs}ms\\``);\n lines.push(`- Generated: \\`${new Date().toISOString()}\\``);\n lines.push(``);\n\n if (args.metadata && Object.keys(args.metadata).length > 0) {\n lines.push(`## Metadata`);\n lines.push(``);\n lines.push(\"```json\");\n lines.push(JSON.stringify(args.metadata, null, 2));\n lines.push(\"```\");\n lines.push(``);\n }\n\n lines.push(`## Prompt`);\n lines.push(``);\n lines.push(\"```text\");\n lines.push((args.prompt ?? \"\").trim());\n lines.push(\"```\");\n lines.push(``);\n\n lines.push(`## Raw Response`);\n lines.push(``);\n lines.push(\"```text\");\n lines.push((args.rawResponse ?? \"\").trim());\n lines.push(\"```\");\n lines.push(``);\n\n const content = lines.join(\"\\n\");\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, content, \"utf-8\");\n return { outPath, content };\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 mkdirSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n} from \"fs\";\nimport {\n ensureOllamaReady,\n STYLEGUIDE_PATHS,\n UILINT_DEFAULT_VISION_MODEL,\n type ElementManifest,\n type VisionIssue,\n} from \"uilint-core/node\";\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 resolveVisionStyleGuide,\n runVisionAnalysis,\n writeVisionMarkdownReport,\n} from \"../utils/vision-run.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<any>(p);\n const issues = Array.isArray(json?.issues)\n ? json.issues\n : json?.analysisResult?.issues;\n out.push({\n path: p,\n filename:\n json?.filename || json?.screenshotFile || 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 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 });\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 });\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 });\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 });\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"],"mappings":"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","names":["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","dirname","resolve","join","parse","findWorkspaceRoot","dirname","join","existsSync","statSync","mkdirSync","writeFileSync","ensureOllamaReady","findStyleGuidePath","findUILintStyleGuideUpwards","readStyleGuide","existsSync","statSync","readStyleGuide","findStyleGuidePath","findUILintStyleGuideUpwards","ensureOllamaReady","mkdirSync","dirname","writeFileSync","join","parse","existsSync","join","dirname","resolve","findWorkspaceRoot","statSync","dirname","resolve","join","existsSync","readFileSync","readdirSync","ensureOllamaReady","STYLEGUIDE_PATHS","UILINT_DEFAULT_VISION_MODEL","envTruthy","preview","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","join","existsSync","dirname","readdirSync","readFileSync","STYLEGUIDE_PATHS","UILINT_DEFAULT_VISION_MODEL","ensureOllamaReady","readFileSync","dirname","join"]}