@fragments-sdk/cli 0.16.0 → 0.17.1

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.
Files changed (62) hide show
  1. package/dist/bin.js +24 -21
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{chunk-77AAP6R6.js → chunk-ANTWP3UG.js} +2 -2
  4. package/dist/{chunk-G6UVWMFU.js → chunk-B4A4ZEGS.js} +5 -5
  5. package/dist/{chunk-SJFSG7QF.js → chunk-FFCI6OVZ.js} +3 -1
  6. package/dist/chunk-FFCI6OVZ.js.map +1 -0
  7. package/dist/{chunk-XRADMHMV.js → chunk-HNHE64CR.js} +2 -2
  8. package/dist/{chunk-ACX7YWZW.js → chunk-MN3B2EE6.js} +2 -2
  9. package/dist/{chunk-QCN35LJU.js → chunk-SAQW37L5.js} +3 -2
  10. package/dist/chunk-SAQW37L5.js.map +1 -0
  11. package/dist/{chunk-OZZ4SVZX.js → chunk-SNZXGHL2.js} +2 -2
  12. package/dist/{chunk-ACFVKMVZ.js → chunk-VT2J62ND.js} +4 -4
  13. package/dist/{codebase-scanner-MQHUZC2G.js → codebase-scanner-2T5QIDBA.js} +2 -2
  14. package/dist/core/index.js +1 -1
  15. package/dist/{create-3ZFYQB3T.js → create-D44QD7MV.js} +2 -2
  16. package/dist/{doctor-4IDUM7HI.js → doctor-7B5N4JYU.js} +2 -2
  17. package/dist/{generate-VNUUWVWQ.js → generate-T47JZRVU.js} +3 -3
  18. package/dist/{govern-scan-HTACKYPF.js → govern-scan-KTGPDZVK.js} +187 -7
  19. package/dist/govern-scan-KTGPDZVK.js.map +1 -0
  20. package/dist/index.js +6 -6
  21. package/dist/{init-PXFRAQ64.js → init-2RGAY4W6.js} +5 -5
  22. package/dist/mcp-bin.js +2 -2
  23. package/dist/{scan-L4GWGEZX.js → scan-A2WJM54L.js} +6 -6
  24. package/dist/{scan-generate-74EYSAGH.js → scan-generate-LUSOHT36.js} +3 -3
  25. package/dist/{service-VELQHEWV.js → service-ROCP7TKG.js} +4 -4
  26. package/dist/{snapshot-DT4B6DPR.js → snapshot-B3SAW74Y.js} +2 -2
  27. package/dist/{static-viewer-E4OJWFDJ.js → static-viewer-7L6UEYTJ.js} +3 -3
  28. package/dist/{test-QJY2QO4X.js → test-PQDVDURE.js} +3 -3
  29. package/dist/{token-normalizer-56H4242J.js → token-normalizer-7TFCVDZL.js} +2 -2
  30. package/dist/{tokens-K6URXFPK.js → tokens-64FG5FDP.js} +5 -5
  31. package/dist/{tokens-generate-EL6IN536.js → tokens-generate-CL4LBBQA.js} +2 -2
  32. package/package.json +8 -8
  33. package/src/bin.ts +6 -0
  34. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +1 -1
  35. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +1 -1
  36. package/src/commands/govern-scan.ts +257 -5
  37. package/src/mcp/__tests__/server.integration.test.ts +9 -20
  38. package/src/service/enhance/codebase-scanner.ts +3 -2
  39. package/src/service/enhance/types.ts +3 -0
  40. package/dist/chunk-QCN35LJU.js.map +0 -1
  41. package/dist/chunk-SJFSG7QF.js.map +0 -1
  42. package/dist/govern-scan-HTACKYPF.js.map +0 -1
  43. /package/dist/{chunk-77AAP6R6.js.map → chunk-ANTWP3UG.js.map} +0 -0
  44. /package/dist/{chunk-G6UVWMFU.js.map → chunk-B4A4ZEGS.js.map} +0 -0
  45. /package/dist/{chunk-XRADMHMV.js.map → chunk-HNHE64CR.js.map} +0 -0
  46. /package/dist/{chunk-ACX7YWZW.js.map → chunk-MN3B2EE6.js.map} +0 -0
  47. /package/dist/{chunk-OZZ4SVZX.js.map → chunk-SNZXGHL2.js.map} +0 -0
  48. /package/dist/{chunk-ACFVKMVZ.js.map → chunk-VT2J62ND.js.map} +0 -0
  49. /package/dist/{codebase-scanner-MQHUZC2G.js.map → codebase-scanner-2T5QIDBA.js.map} +0 -0
  50. /package/dist/{create-3ZFYQB3T.js.map → create-D44QD7MV.js.map} +0 -0
  51. /package/dist/{doctor-4IDUM7HI.js.map → doctor-7B5N4JYU.js.map} +0 -0
  52. /package/dist/{generate-VNUUWVWQ.js.map → generate-T47JZRVU.js.map} +0 -0
  53. /package/dist/{init-PXFRAQ64.js.map → init-2RGAY4W6.js.map} +0 -0
  54. /package/dist/{scan-L4GWGEZX.js.map → scan-A2WJM54L.js.map} +0 -0
  55. /package/dist/{scan-generate-74EYSAGH.js.map → scan-generate-LUSOHT36.js.map} +0 -0
  56. /package/dist/{service-VELQHEWV.js.map → service-ROCP7TKG.js.map} +0 -0
  57. /package/dist/{snapshot-DT4B6DPR.js.map → snapshot-B3SAW74Y.js.map} +0 -0
  58. /package/dist/{static-viewer-E4OJWFDJ.js.map → static-viewer-7L6UEYTJ.js.map} +0 -0
  59. /package/dist/{test-QJY2QO4X.js.map → test-PQDVDURE.js.map} +0 -0
  60. /package/dist/{token-normalizer-56H4242J.js.map → token-normalizer-7TFCVDZL.js.map} +0 -0
  61. /package/dist/{tokens-K6URXFPK.js.map → tokens-64FG5FDP.js.map} +0 -0
  62. /package/dist/{tokens-generate-EL6IN536.js.map → tokens-generate-CL4LBBQA.js.map} +0 -0
@@ -422,6 +422,7 @@ async function scanCodebase(options) {
422
422
  rootDir,
423
423
  include = DEFAULT_INCLUDE,
424
424
  exclude = DEFAULT_EXCLUDE,
425
+ files: explicitFiles,
425
426
  componentNames,
426
427
  useCache = true,
427
428
  onProgress
@@ -440,7 +441,7 @@ async function scanCodebase(options) {
440
441
  currentFile: "",
441
442
  phase: "discovering"
442
443
  });
443
- const files = await fg(include, {
444
+ const files = explicitFiles ?? await fg(include, {
444
445
  cwd: absoluteRoot,
445
446
  ignore: exclude,
446
447
  absolute: true,
@@ -627,4 +628,4 @@ export {
627
628
  getScanStats,
628
629
  hasCachedAnalysis
629
630
  };
630
- //# sourceMappingURL=chunk-QCN35LJU.js.map
631
+ //# sourceMappingURL=chunk-SAQW37L5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/service/enhance/codebase-scanner.ts","../src/service/enhance/aggregator.ts","../src/service/enhance/cache.ts"],"sourcesContent":["/**\n * Full Codebase Scanner\n *\n * Scans entire codebase for component usage patterns with caching and progress.\n */\n\nimport fg from \"fast-glob\";\nimport { readFile } from \"node:fs/promises\";\nimport { relative, resolve, dirname, basename } from \"node:path\";\nimport type {\n ScanOptions,\n ScanProgress,\n UsageAnalysis,\n ComponentImport,\n ComponentUsage,\n FileChanges,\n AnalysisCache,\n} from \"./types.js\";\nimport { scanFile } from \"./scanner.js\";\nimport { aggregateAllUsages } from \"./aggregator.js\";\nimport {\n loadCache,\n saveCache,\n createEmptyCache,\n computeFileHash,\n isFileCached,\n updateCacheFile,\n removeCacheFile,\n getCachedFile,\n detectFileChanges,\n getCacheStats,\n} from \"./cache.js\";\n\n/**\n * Default patterns for files to scan\n */\nconst DEFAULT_INCLUDE = [\n \"**/*.tsx\",\n \"**/*.ts\",\n \"**/*.jsx\",\n \"**/*.js\",\n];\n\n/**\n * Default patterns for files to exclude\n */\nconst DEFAULT_EXCLUDE = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/coverage/**\",\n \"**/__tests__/**\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n \"**/*.stories.*\",\n \"**/*.fragment.*\",\n \"**/storybook-static/**\",\n];\n\n/**\n * Scan entire codebase for component usages\n */\nexport async function scanCodebase(\n options: ScanOptions\n): Promise<UsageAnalysis> {\n const {\n rootDir,\n include = DEFAULT_INCLUDE,\n exclude = DEFAULT_EXCLUDE,\n files: explicitFiles,\n componentNames,\n useCache = true,\n onProgress,\n } = options;\n\n const absoluteRoot = resolve(rootDir);\n\n // Load or create cache\n let cache: AnalysisCache | null = null;\n if (useCache) {\n cache = await loadCache(absoluteRoot);\n }\n if (!cache) {\n cache = createEmptyCache(absoluteRoot);\n }\n\n // Discover files — use explicit list when provided, otherwise glob\n onProgress?.({\n current: 0,\n total: 0,\n currentFile: \"\",\n phase: \"discovering\",\n });\n\n const files = explicitFiles ?? await fg(include, {\n cwd: absoluteRoot,\n ignore: exclude,\n absolute: true,\n onlyFiles: true,\n });\n\n const totalFiles = files.length;\n\n // Track components to find (if specific ones provided)\n const trackedComponents = componentNames\n ? new Set(componentNames)\n : undefined;\n\n // Collect all imports and usages\n const allImports: ComponentImport[] = [];\n const allUsages: ComponentUsage[] = [];\n const errorFiles: string[] = [];\n const componentSources = new Map<string, string>();\n\n // Process files\n for (let i = 0; i < files.length; i++) {\n const filePath = files[i];\n const relativePath = relative(absoluteRoot, filePath);\n\n onProgress?.({\n current: i + 1,\n total: totalFiles,\n currentFile: relativePath,\n phase: \"scanning\",\n });\n\n try {\n // Read file content for hash\n const content = await readFile(filePath, \"utf-8\");\n const fileHash = computeFileHash(content);\n\n // Check cache\n const cachedEntry = getCachedFile(cache, filePath);\n if (cachedEntry && cachedEntry.hash === fileHash) {\n // Use cached results\n allImports.push(...cachedEntry.imports);\n allUsages.push(...cachedEntry.usages);\n\n // Track component sources from imports\n for (const imp of cachedEntry.imports) {\n if (!componentSources.has(imp.componentName)) {\n const sourceFile = resolveImportSource(filePath, imp.source);\n if (sourceFile) {\n componentSources.set(imp.componentName, sourceFile);\n }\n }\n }\n continue;\n }\n\n // Scan file\n const { imports, usages } = await scanFile(filePath, trackedComponents);\n\n // Update cache\n updateCacheFile(cache, filePath, fileHash, imports, usages);\n\n allImports.push(...imports);\n allUsages.push(...usages);\n\n // Track component sources\n for (const imp of imports) {\n if (!componentSources.has(imp.componentName)) {\n const sourceFile = resolveImportSource(filePath, imp.source);\n if (sourceFile) {\n componentSources.set(imp.componentName, sourceFile);\n }\n }\n }\n } catch (error) {\n errorFiles.push(relativePath);\n console.warn(`Error scanning ${relativePath}:`, (error as Error).message);\n }\n }\n\n // Save cache\n if (useCache) {\n await saveCache(absoluteRoot, cache);\n }\n\n // Aggregate results\n onProgress?.({\n current: totalFiles,\n total: totalFiles,\n currentFile: \"\",\n phase: \"aggregating\",\n });\n\n const analysis = aggregateAllUsages(allUsages, allImports, componentSources);\n analysis.rootDir = absoluteRoot;\n analysis.totalFiles = totalFiles;\n analysis.errorFiles = errorFiles;\n\n return analysis;\n}\n\n/**\n * Perform incremental scan for changed files only\n */\nexport async function incrementalScan(\n rootDir: string,\n changes: FileChanges,\n existingCache: AnalysisCache,\n onProgress?: (progress: ScanProgress) => void\n): Promise<{ analysis: UsageAnalysis; cache: AnalysisCache }> {\n const absoluteRoot = resolve(rootDir);\n const cache = { ...existingCache, files: { ...existingCache.files } };\n\n // Remove deleted files from cache\n for (const filePath of changes.deleted) {\n removeCacheFile(cache, filePath);\n }\n\n // Files to scan (added + modified)\n const filesToScan = [...changes.added, ...changes.modified];\n const totalFiles = filesToScan.length;\n\n const allImports: ComponentImport[] = [];\n const allUsages: ComponentUsage[] = [];\n const errorFiles: string[] = [];\n const componentSources = new Map<string, string>();\n\n // First, collect unchanged file data from cache\n for (const filePath of changes.unchanged) {\n const cachedEntry = getCachedFile(cache, filePath);\n if (cachedEntry) {\n allImports.push(...cachedEntry.imports);\n allUsages.push(...cachedEntry.usages);\n\n for (const imp of cachedEntry.imports) {\n if (!componentSources.has(imp.componentName)) {\n const sourceFile = resolveImportSource(filePath, imp.source);\n if (sourceFile) {\n componentSources.set(imp.componentName, sourceFile);\n }\n }\n }\n }\n }\n\n // Scan changed files\n for (let i = 0; i < filesToScan.length; i++) {\n const filePath = filesToScan[i];\n const relativePath = relative(absoluteRoot, filePath);\n\n onProgress?.({\n current: i + 1,\n total: totalFiles,\n currentFile: relativePath,\n phase: \"scanning\",\n });\n\n try {\n const content = await readFile(filePath, \"utf-8\");\n const fileHash = computeFileHash(content);\n\n const { imports, usages } = await scanFile(filePath);\n\n updateCacheFile(cache, filePath, fileHash, imports, usages);\n\n allImports.push(...imports);\n allUsages.push(...usages);\n\n for (const imp of imports) {\n if (!componentSources.has(imp.componentName)) {\n const sourceFile = resolveImportSource(filePath, imp.source);\n if (sourceFile) {\n componentSources.set(imp.componentName, sourceFile);\n }\n }\n }\n } catch (error) {\n errorFiles.push(relativePath);\n }\n }\n\n // Save updated cache\n await saveCache(absoluteRoot, cache);\n\n // Aggregate\n const analysis = aggregateAllUsages(allUsages, allImports, componentSources);\n analysis.rootDir = absoluteRoot;\n analysis.totalFiles = changes.unchanged.length + filesToScan.length;\n analysis.errorFiles = errorFiles;\n\n return { analysis, cache };\n}\n\n/**\n * Resolve import source to absolute file path\n */\nfunction resolveImportSource(\n importingFile: string,\n source: string\n): string | null {\n // Skip node_modules imports\n if (!source.startsWith(\".\") && !source.startsWith(\"/\")) {\n return null;\n }\n\n const importDir = dirname(importingFile);\n\n // Try common extensions\n const extensions = [\"\", \".tsx\", \".ts\", \".jsx\", \".js\", \"/index.tsx\", \"/index.ts\"];\n for (const ext of extensions) {\n const fullPath = resolve(importDir, source + ext);\n // We don't check if file exists here for performance\n // The source path is mainly for reference\n if (ext === \"\" && source.endsWith(\".tsx\")) {\n return fullPath;\n }\n if (ext) {\n return resolve(importDir, source) + ext;\n }\n }\n\n return resolve(importDir, source);\n}\n\n/**\n * Get scan statistics for display\n */\nexport function getScanStats(analysis: UsageAnalysis): {\n totalFiles: number;\n totalComponents: number;\n totalUsages: number;\n topComponents: { name: string; usages: number }[];\n} {\n const totalUsages = Object.values(analysis.components).reduce(\n (sum, c) => sum + c.totalUsages,\n 0\n );\n\n const topComponents = Object.values(analysis.components)\n .map((c) => ({ name: c.name, usages: c.totalUsages }))\n .sort((a, b) => b.usages - a.usages)\n .slice(0, 10);\n\n return {\n totalFiles: analysis.totalFiles,\n totalComponents: analysis.totalComponents,\n totalUsages,\n topComponents,\n };\n}\n\n/**\n * Export for quick check if cache exists and is valid\n */\nexport async function hasCachedAnalysis(rootDir: string): Promise<boolean> {\n const cache = await loadCache(resolve(rootDir));\n if (!cache) return false;\n const stats = getCacheStats(cache);\n return stats.totalFiles > 0;\n}\n\n// Re-export types and utilities\nexport { loadCache, getCacheStats, detectFileChanges } from \"./cache.js\";\n","/**\n * Usage Pattern Aggregator\n *\n * Aggregates component usages into patterns for AI analysis.\n */\n\nimport type {\n ComponentUsage,\n ComponentImport,\n ComponentAnalysis,\n UsagePattern,\n FileContext,\n UsageAnalysis,\n} from \"./types.js\";\n\n/**\n * Aggregate usages for a single component into patterns\n */\nexport function aggregateComponentUsages(\n componentName: string,\n sourceFile: string,\n usages: ComponentUsage[],\n imports: ComponentImport[]\n): ComponentAnalysis {\n // Count unique files\n const uniqueFiles = new Set(usages.map((u) => u.filePath));\n\n // Group usages by prop pattern\n const patternMap = new Map<string, UsagePattern>();\n\n for (const usage of usages) {\n // Create a key from static props (sorted for consistency)\n const propKey = createPropKey(usage.props.static);\n\n const existing = patternMap.get(propKey);\n if (existing) {\n existing.count++;\n if (!existing.files.includes(usage.filePath)) {\n existing.files.push(usage.filePath);\n }\n if (existing.sampleContexts.length < 3) {\n existing.sampleContexts.push(usage.context);\n }\n } else {\n patternMap.set(propKey, {\n props: { ...usage.props.static },\n count: 1,\n files: [usage.filePath],\n sampleContexts: [usage.context],\n });\n }\n }\n\n // Sort patterns by frequency\n const patterns = Array.from(patternMap.values()).sort(\n (a, b) => b.count - a.count\n );\n\n // Classify file contexts\n const contextMap = new Map<FileContext, { count: number; files: string[] }>();\n\n for (const usage of usages) {\n const context = classifyFileContext(usage.filePath, usage.context);\n const existing = contextMap.get(context);\n if (existing) {\n existing.count++;\n if (!existing.files.includes(usage.filePath)) {\n existing.files.push(usage.filePath);\n }\n } else {\n contextMap.set(context, { count: 1, files: [usage.filePath] });\n }\n }\n\n // Convert to sorted array\n const contexts = Array.from(contextMap.entries())\n .map(([type, data]) => ({ type, ...data }))\n .sort((a, b) => b.count - a.count);\n\n return {\n name: componentName,\n sourceFile,\n totalUsages: usages.length,\n uniqueFiles: uniqueFiles.size,\n patterns,\n contexts,\n usages,\n imports,\n };\n}\n\n/**\n * Aggregate all usages across the codebase\n */\nexport function aggregateAllUsages(\n usages: ComponentUsage[],\n imports: ComponentImport[],\n componentSources: Map<string, string>\n): UsageAnalysis {\n // Group usages by component\n const usagesByComponent = new Map<string, ComponentUsage[]>();\n for (const usage of usages) {\n const existing = usagesByComponent.get(usage.componentName) ?? [];\n existing.push(usage);\n usagesByComponent.set(usage.componentName, existing);\n }\n\n // Group imports by component\n const importsByComponent = new Map<string, ComponentImport[]>();\n for (const imp of imports) {\n const existing = importsByComponent.get(imp.componentName) ?? [];\n existing.push(imp);\n importsByComponent.set(imp.componentName, existing);\n }\n\n // Build component analyses\n const components: Record<string, ComponentAnalysis> = {};\n const allComponentNames = new Set([\n ...usagesByComponent.keys(),\n ...importsByComponent.keys(),\n ]);\n\n for (const componentName of allComponentNames) {\n const componentUsages = usagesByComponent.get(componentName) ?? [];\n const componentImports = importsByComponent.get(componentName) ?? [];\n const sourceFile = componentSources.get(componentName) ?? \"unknown\";\n\n components[componentName] = aggregateComponentUsages(\n componentName,\n sourceFile,\n componentUsages,\n componentImports\n );\n }\n\n // Collect unique files\n const allFiles = new Set<string>();\n for (const usage of usages) {\n allFiles.add(usage.filePath);\n }\n for (const imp of imports) {\n allFiles.add(imp.filePath);\n }\n\n return {\n timestamp: new Date().toISOString(),\n rootDir: \"\", // Will be set by caller\n totalFiles: allFiles.size,\n totalComponents: Object.keys(components).length,\n components,\n errorFiles: [], // Will be populated by scanner\n };\n}\n\n/**\n * Create a stable key from props for pattern grouping\n */\nfunction createPropKey(props: Record<string, string | boolean | number>): string {\n const entries = Object.entries(props).sort(([a], [b]) => a.localeCompare(b));\n return entries.map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(\"|\");\n}\n\n/**\n * Classify file context based on path and content\n */\nfunction classifyFileContext(filePath: string, context: string): FileContext {\n const lowerPath = filePath.toLowerCase();\n const lowerContext = context.toLowerCase();\n\n // Check path patterns first\n if (\n lowerPath.includes(\"/modal\") ||\n lowerPath.includes(\"modal.\") ||\n lowerContext.includes(\"<modal\")\n ) {\n return \"modal\";\n }\n\n if (\n lowerPath.includes(\"/dialog\") ||\n lowerPath.includes(\"dialog.\") ||\n lowerContext.includes(\"<dialog\")\n ) {\n return \"dialog\";\n }\n\n if (\n lowerPath.includes(\"/form\") ||\n lowerPath.includes(\"form.\") ||\n lowerContext.includes(\"<form\") ||\n lowerContext.includes(\"onsubmit\")\n ) {\n return \"form\";\n }\n\n if (\n lowerPath.includes(\"/page\") ||\n lowerPath.includes(\"pages/\") ||\n lowerPath.includes(\"/routes/\")\n ) {\n return \"page\";\n }\n\n if (\n lowerPath.includes(\"/layout\") ||\n lowerPath.includes(\"layout.\") ||\n lowerPath.includes(\"/layouts/\")\n ) {\n return \"layout\";\n }\n\n if (\n lowerPath.includes(\"/card\") ||\n lowerPath.includes(\"card.\") ||\n lowerContext.includes(\"<card\")\n ) {\n return \"card\";\n }\n\n if (\n lowerPath.includes(\"/table\") ||\n lowerPath.includes(\"table.\") ||\n lowerContext.includes(\"<table\") ||\n lowerContext.includes(\"<tr\")\n ) {\n return \"table\";\n }\n\n if (\n lowerPath.includes(\"/list\") ||\n lowerPath.includes(\"list.\") ||\n lowerContext.includes(\"<ul\") ||\n lowerContext.includes(\"<ol\") ||\n lowerContext.includes(\"<li\")\n ) {\n return \"list\";\n }\n\n if (\n lowerPath.includes(\"/nav\") ||\n lowerPath.includes(\"navigation\") ||\n lowerContext.includes(\"<nav\")\n ) {\n return \"navigation\";\n }\n\n if (\n lowerPath.includes(\"/header\") ||\n lowerPath.includes(\"header.\") ||\n lowerContext.includes(\"<header\")\n ) {\n return \"header\";\n }\n\n if (\n lowerPath.includes(\"/footer\") ||\n lowerPath.includes(\"footer.\") ||\n lowerContext.includes(\"<footer\")\n ) {\n return \"footer\";\n }\n\n if (\n lowerPath.includes(\"/sidebar\") ||\n lowerPath.includes(\"sidebar.\") ||\n lowerContext.includes(\"<aside\")\n ) {\n return \"sidebar\";\n }\n\n return \"unknown\";\n}\n\n/**\n * Find common prop combinations across usages\n */\nexport function findCommonPropCombinations(\n usages: ComponentUsage[],\n minOccurrences: number = 3\n): { props: string[]; count: number }[] {\n const combinations = new Map<string, number>();\n\n for (const usage of usages) {\n // Get all prop names (static and dynamic)\n const allProps = [\n ...Object.keys(usage.props.static),\n ...usage.props.dynamic,\n ].sort();\n\n // Generate all combinations of 2+ props\n for (let size = 2; size <= Math.min(allProps.length, 4); size++) {\n for (const combo of combinations_k(allProps, size)) {\n const key = combo.join(\",\");\n combinations.set(key, (combinations.get(key) ?? 0) + 1);\n }\n }\n }\n\n // Filter and sort by frequency\n return Array.from(combinations.entries())\n .filter(([, count]) => count >= minOccurrences)\n .map(([key, count]) => ({ props: key.split(\",\"), count }))\n .sort((a, b) => b.count - a.count);\n}\n\n/**\n * Generate k-combinations of an array\n */\nfunction* combinations_k<T>(arr: T[], k: number): Generator<T[]> {\n if (k === 0) {\n yield [];\n return;\n }\n if (arr.length < k) return;\n\n for (let i = 0; i <= arr.length - k; i++) {\n for (const combo of combinations_k(arr.slice(i + 1), k - 1)) {\n yield [arr[i], ...combo];\n }\n }\n}\n\n/**\n * Component relationship with frequency data\n */\nexport interface ComponentRelation {\n /** Related component name */\n component: string;\n /** Type of relationship */\n relationship: \"parent\" | \"sibling\" | \"child\";\n /** How often this relationship occurs */\n frequency: number;\n /** Sample files where this relationship occurs */\n sampleFiles: string[];\n}\n\n/**\n * Infer component relationships from usage patterns\n *\n * Analyzes parent/sibling relationships from actual usage data:\n * - parent: Components that contain this component (from parentElement)\n * - sibling: Components that appear alongside this component in the same parent\n */\nexport function inferRelations(\n componentName: string,\n analysis: ComponentAnalysis,\n allAnalyses: Record<string, ComponentAnalysis>\n): ComponentRelation[] {\n const relations: ComponentRelation[] = [];\n const parentCounts = new Map<string, { count: number; files: string[] }>();\n const siblingCounts = new Map<string, { count: number; files: string[] }>();\n\n // Count parent relationships\n for (const usage of analysis.usages) {\n if (usage.parentElement && usage.parentElement !== \"div\" && usage.parentElement !== \"span\") {\n const parent = usage.parentElement;\n const existing = parentCounts.get(parent);\n if (existing) {\n existing.count++;\n if (!existing.files.includes(usage.filePath)) {\n existing.files.push(usage.filePath);\n }\n } else {\n parentCounts.set(parent, { count: 1, files: [usage.filePath] });\n }\n }\n }\n\n // Infer sibling relationships: other components used in the same files\n const filesWithThisComponent = new Set(analysis.usages.map((u) => u.filePath));\n\n for (const [otherName, otherAnalysis] of Object.entries(allAnalyses)) {\n if (otherName === componentName) continue;\n\n // Count how many files have both components\n let sharedFiles = 0;\n const sharedFileList: string[] = [];\n\n for (const usage of otherAnalysis.usages) {\n if (filesWithThisComponent.has(usage.filePath)) {\n if (!sharedFileList.includes(usage.filePath)) {\n sharedFiles++;\n sharedFileList.push(usage.filePath);\n }\n }\n }\n\n // Only include if they appear together frequently\n if (sharedFiles >= 3) {\n siblingCounts.set(otherName, {\n count: sharedFiles,\n files: sharedFileList.slice(0, 5),\n });\n }\n }\n\n // Convert to relations array (parents)\n for (const [parent, data] of parentCounts) {\n // Only include meaningful parent relationships (count >= 2)\n if (data.count >= 2) {\n relations.push({\n component: parent,\n relationship: \"parent\",\n frequency: data.count,\n sampleFiles: data.files.slice(0, 3),\n });\n }\n }\n\n // Convert to relations array (siblings)\n for (const [sibling, data] of siblingCounts) {\n relations.push({\n component: sibling,\n relationship: \"sibling\",\n frequency: data.count,\n sampleFiles: data.files.slice(0, 3),\n });\n }\n\n // Sort by frequency\n relations.sort((a, b) => b.frequency - a.frequency);\n\n return relations;\n}\n\n/**\n * Infer relations for all components in the analysis\n */\nexport function inferAllRelations(\n analysis: UsageAnalysis\n): Map<string, ComponentRelation[]> {\n const allRelations = new Map<string, ComponentRelation[]>();\n\n for (const [componentName, componentAnalysis] of Object.entries(analysis.components)) {\n const relations = inferRelations(componentName, componentAnalysis, analysis.components);\n if (relations.length > 0) {\n allRelations.set(componentName, relations);\n }\n }\n\n return allRelations;\n}\n\n/**\n * Summarize patterns for AI prompt\n */\nexport function summarizePatternsForPrompt(\n analysis: ComponentAnalysis,\n maxPatterns: number = 10,\n maxContexts: number = 5\n): string {\n const lines: string[] = [];\n\n lines.push(`## ${analysis.name}`);\n lines.push(`Total usages: ${analysis.totalUsages} across ${analysis.uniqueFiles} files`);\n lines.push(\"\");\n\n // Top patterns\n lines.push(\"### Usage Patterns (by frequency)\");\n const topPatterns = analysis.patterns.slice(0, maxPatterns);\n for (const pattern of topPatterns) {\n const propsStr = Object.entries(pattern.props)\n .map(([k, v]) => `${k}=${JSON.stringify(v)}`)\n .join(\", \");\n lines.push(`- ${propsStr || \"(no props)\"}: ${pattern.count} usages in ${pattern.files.length} files`);\n }\n lines.push(\"\");\n\n // File contexts\n lines.push(\"### File Contexts\");\n const topContexts = analysis.contexts.slice(0, maxContexts);\n for (const ctx of topContexts) {\n lines.push(`- ${ctx.type}: ${ctx.count} usages`);\n }\n lines.push(\"\");\n\n // Sample code contexts (one per pattern)\n lines.push(\"### Sample Usages\");\n for (const pattern of topPatterns.slice(0, 3)) {\n if (pattern.sampleContexts[0]) {\n lines.push(\"```tsx\");\n lines.push(pattern.sampleContexts[0].trim());\n lines.push(\"```\");\n lines.push(\"\");\n }\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * Analysis Cache Layer\n *\n * Caches file analysis results to enable fast incremental updates.\n */\n\nimport { readFile, writeFile, stat } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { join, dirname } from \"node:path\";\nimport { mkdir } from \"node:fs/promises\";\nimport type {\n AnalysisCache,\n FileCacheEntry,\n FileChanges,\n ComponentImport,\n ComponentUsage,\n CACHE_VERSION,\n} from \"./types.js\";\n\nconst CURRENT_CACHE_VERSION = 1;\nconst CACHE_FILENAME = \"analysis-cache.json\";\n\n/**\n * Get the cache file path for a project\n */\nexport function getCachePath(rootDir: string): string {\n return join(rootDir, \".fragments\", CACHE_FILENAME);\n}\n\n/**\n * Load cache from disk\n * Returns null if cache doesn't exist or is invalid\n */\nexport async function loadCache(rootDir: string): Promise<AnalysisCache | null> {\n const cachePath = getCachePath(rootDir);\n\n if (!existsSync(cachePath)) {\n return null;\n }\n\n try {\n const content = await readFile(cachePath, \"utf-8\");\n const cache = JSON.parse(content) as AnalysisCache;\n\n // Validate version\n if (cache.version !== CURRENT_CACHE_VERSION) {\n console.warn(\n `Cache version mismatch: expected ${CURRENT_CACHE_VERSION}, got ${cache.version}. Invalidating cache.`\n );\n return null;\n }\n\n // Validate root dir matches\n if (cache.rootDir !== rootDir) {\n console.warn(`Cache root mismatch. Invalidating cache.`);\n return null;\n }\n\n return cache;\n } catch (error) {\n console.warn(`Failed to load cache: ${(error as Error).message}`);\n return null;\n }\n}\n\n/**\n * Save cache to disk\n */\nexport async function saveCache(\n rootDir: string,\n cache: AnalysisCache\n): Promise<void> {\n const cachePath = getCachePath(rootDir);\n const cacheDir = dirname(cachePath);\n\n // Ensure .fragments directory exists\n if (!existsSync(cacheDir)) {\n await mkdir(cacheDir, { recursive: true });\n }\n\n cache.updatedAt = new Date().toISOString();\n await writeFile(cachePath, JSON.stringify(cache, null, 2));\n}\n\n/**\n * Create a new empty cache\n */\nexport function createEmptyCache(rootDir: string): AnalysisCache {\n const now = new Date().toISOString();\n return {\n version: CURRENT_CACHE_VERSION,\n createdAt: now,\n updatedAt: now,\n rootDir,\n files: {},\n };\n}\n\n/**\n * Compute content hash for a file\n */\nexport function computeFileHash(content: string): string {\n return createHash(\"md5\").update(content).digest(\"hex\");\n}\n\n/**\n * Compute file hash from disk\n */\nexport async function computeFileHashFromDisk(\n filePath: string\n): Promise<string> {\n const content = await readFile(filePath, \"utf-8\");\n return computeFileHash(content);\n}\n\n/**\n * Check if a file is cached and unchanged\n */\nexport function isFileCached(\n cache: AnalysisCache,\n filePath: string,\n currentHash: string\n): boolean {\n const entry = cache.files[filePath];\n if (!entry) return false;\n return entry.hash === currentHash;\n}\n\n/**\n * Get cached data for a file\n */\nexport function getCachedFile(\n cache: AnalysisCache,\n filePath: string\n): FileCacheEntry | null {\n return cache.files[filePath] ?? null;\n}\n\n/**\n * Update cache with results for a file\n */\nexport function updateCacheFile(\n cache: AnalysisCache,\n filePath: string,\n hash: string,\n imports: ComponentImport[],\n usages: ComponentUsage[]\n): void {\n cache.files[filePath] = {\n hash,\n timestamp: new Date().toISOString(),\n imports,\n usages,\n };\n}\n\n/**\n * Remove a file from cache\n */\nexport function removeCacheFile(cache: AnalysisCache, filePath: string): void {\n delete cache.files[filePath];\n}\n\n/**\n * Invalidate cache entries for specific files\n */\nexport function invalidateCache(\n cache: AnalysisCache,\n filePaths: string[]\n): void {\n for (const filePath of filePaths) {\n delete cache.files[filePath];\n }\n}\n\n/**\n * Detect file changes by comparing current files to cache\n */\nexport async function detectFileChanges(\n cache: AnalysisCache,\n currentFiles: string[],\n getFileHash: (filePath: string) => Promise<string>\n): Promise<FileChanges> {\n const changes: FileChanges = {\n added: [],\n modified: [],\n deleted: [],\n unchanged: [],\n };\n\n const currentFileSet = new Set(currentFiles);\n const cachedFileSet = new Set(Object.keys(cache.files));\n\n // Check for added and modified files\n for (const filePath of currentFiles) {\n const entry = cache.files[filePath];\n\n if (!entry) {\n changes.added.push(filePath);\n } else {\n const currentHash = await getFileHash(filePath);\n if (currentHash !== entry.hash) {\n changes.modified.push(filePath);\n } else {\n changes.unchanged.push(filePath);\n }\n }\n }\n\n // Check for deleted files\n for (const cachedFile of cachedFileSet) {\n if (!currentFileSet.has(cachedFile)) {\n changes.deleted.push(cachedFile);\n }\n }\n\n return changes;\n}\n\n/**\n * Get all cached imports\n */\nexport function getAllCachedImports(cache: AnalysisCache): ComponentImport[] {\n const imports: ComponentImport[] = [];\n for (const entry of Object.values(cache.files)) {\n imports.push(...entry.imports);\n }\n return imports;\n}\n\n/**\n * Get all cached usages\n */\nexport function getAllCachedUsages(cache: AnalysisCache): ComponentUsage[] {\n const usages: ComponentUsage[] = [];\n for (const entry of Object.values(cache.files)) {\n usages.push(...entry.usages);\n }\n return usages;\n}\n\n/**\n * Get cache statistics\n */\nexport function getCacheStats(cache: AnalysisCache): {\n totalFiles: number;\n totalImports: number;\n totalUsages: number;\n cacheAge: string;\n} {\n let totalImports = 0;\n let totalUsages = 0;\n\n for (const entry of Object.values(cache.files)) {\n totalImports += entry.imports.length;\n totalUsages += entry.usages.length;\n }\n\n const ageMs = Date.now() - new Date(cache.updatedAt).getTime();\n const ageMinutes = Math.round(ageMs / 60000);\n const cacheAge =\n ageMinutes < 60\n ? `${ageMinutes} minutes ago`\n : ageMinutes < 1440\n ? `${Math.round(ageMinutes / 60)} hours ago`\n : `${Math.round(ageMinutes / 1440)} days ago`;\n\n return {\n totalFiles: Object.keys(cache.files).length,\n totalImports,\n totalUsages,\n cacheAge,\n };\n}\n"],"mappings":"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","names":["readFile","dirname","readFile","dirname"]}
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
2
2
  import {
3
3
  BRAND
4
- } from "./chunk-SJFSG7QF.js";
4
+ } from "./chunk-FFCI6OVZ.js";
5
5
 
6
6
  // src/static-viewer.ts
7
7
  import { readFile } from "fs/promises";
@@ -616,4 +616,4 @@ export {
616
616
  generateStaticViewer,
617
617
  generateViewerFromJson
618
618
  };
619
- //# sourceMappingURL=chunk-OZZ4SVZX.js.map
619
+ //# sourceMappingURL=chunk-SNZXGHL2.js.map
@@ -6,7 +6,7 @@ import {
6
6
  extractComponentName,
7
7
  loadFragmentFile,
8
8
  parseFragmentFile
9
- } from "./chunk-XRADMHMV.js";
9
+ } from "./chunk-HNHE64CR.js";
10
10
  import {
11
11
  BrowserPool,
12
12
  CaptureEngine,
@@ -16,12 +16,12 @@ import {
16
16
  formatMs,
17
17
  generateHtmlReport,
18
18
  getGrade
19
- } from "./chunk-77AAP6R6.js";
19
+ } from "./chunk-ANTWP3UG.js";
20
20
  import {
21
21
  BRAND,
22
22
  DEFAULTS,
23
23
  fragmentDefinitionSchema
24
- } from "./chunk-SJFSG7QF.js";
24
+ } from "./chunk-FFCI6OVZ.js";
25
25
 
26
26
  // src/service/snippet-validation.ts
27
27
  import ts from "typescript";
@@ -1252,4 +1252,4 @@ export {
1252
1252
  runDiffCommand,
1253
1253
  runAnalyzeCommand
1254
1254
  };
1255
- //# sourceMappingURL=chunk-ACFVKMVZ.js.map
1255
+ //# sourceMappingURL=chunk-VT2J62ND.js.map
@@ -7,7 +7,7 @@ import {
7
7
  incrementalScan,
8
8
  loadCache,
9
9
  scanCodebase
10
- } from "./chunk-QCN35LJU.js";
10
+ } from "./chunk-SAQW37L5.js";
11
11
  import "./chunk-7DZC4YEV.js";
12
12
  export {
13
13
  detectFileChanges,
@@ -18,4 +18,4 @@ export {
18
18
  loadCache,
19
19
  scanCodebase
20
20
  };
21
- //# sourceMappingURL=codebase-scanner-MQHUZC2G.js.map
21
+ //# sourceMappingURL=codebase-scanner-2T5QIDBA.js.map
@@ -101,7 +101,7 @@ import {
101
101
  storyNameFromExport,
102
102
  toId,
103
103
  usePreviewVariantRuntime
104
- } from "../chunk-SJFSG7QF.js";
104
+ } from "../chunk-FFCI6OVZ.js";
105
105
  export {
106
106
  BRAND,
107
107
  DEFAULTS,
@@ -2,7 +2,7 @@ import { createRequire as __banner_createRequire } from 'module'; const require
2
2
  import "./chunk-D2CDBRNU.js";
3
3
  import {
4
4
  BRAND
5
- } from "./chunk-SJFSG7QF.js";
5
+ } from "./chunk-FFCI6OVZ.js";
6
6
 
7
7
  // src/commands/create.ts
8
8
  import { execSync } from "child_process";
@@ -1096,4 +1096,4 @@ export {
1096
1096
  generateNextjsProviders,
1097
1097
  generatePageCssModule
1098
1098
  };
1099
- //# sourceMappingURL=create-3ZFYQB3T.js.map
1099
+ //# sourceMappingURL=create-D44QD7MV.js.map
@@ -2,7 +2,7 @@ import { createRequire as __banner_createRequire } from 'module'; const require
2
2
  import "./chunk-D2CDBRNU.js";
3
3
  import {
4
4
  BRAND
5
- } from "./chunk-SJFSG7QF.js";
5
+ } from "./chunk-FFCI6OVZ.js";
6
6
 
7
7
  // src/commands/doctor.ts
8
8
  import { readFile, access } from "fs/promises";
@@ -382,4 +382,4 @@ ${BRAND.name} Doctor
382
382
  export {
383
383
  doctor
384
384
  };
385
- //# sourceMappingURL=doctor-4IDUM7HI.js.map
385
+ //# sourceMappingURL=doctor-7B5N4JYU.js.map
@@ -1,11 +1,11 @@
1
1
  import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
2
2
  import {
3
3
  extractPropsFromFile
4
- } from "./chunk-XRADMHMV.js";
4
+ } from "./chunk-HNHE64CR.js";
5
5
  import "./chunk-D2CDBRNU.js";
6
6
  import {
7
7
  BRAND
8
- } from "./chunk-SJFSG7QF.js";
8
+ } from "./chunk-FFCI6OVZ.js";
9
9
 
10
10
  // src/commands/generate.ts
11
11
  import { readFile, writeFile, access } from "fs/promises";
@@ -454,4 +454,4 @@ function inferStatus(filePath) {
454
454
  export {
455
455
  generate
456
456
  };
457
- //# sourceMappingURL=generate-VNUUWVWQ.js.map
457
+ //# sourceMappingURL=generate-T47JZRVU.js.map
@@ -2,12 +2,13 @@ import { createRequire as __banner_createRequire } from 'module'; const require
2
2
  import "./chunk-D2CDBRNU.js";
3
3
  import {
4
4
  BRAND
5
- } from "./chunk-SJFSG7QF.js";
5
+ } from "./chunk-FFCI6OVZ.js";
6
6
 
7
7
  // src/commands/govern-scan.ts
8
8
  import pc from "picocolors";
9
9
  import { resolve as resolve2, relative as relative2 } from "path";
10
- import { existsSync } from "fs";
10
+ import { existsSync, readFileSync } from "fs";
11
+ import { execSync } from "child_process";
11
12
 
12
13
  // src/commands/govern-scan-report.ts
13
14
  import { resolve, dirname, relative } from "path";
@@ -123,6 +124,48 @@ async function writeGovernScanReport(path, report) {
123
124
  }
124
125
 
125
126
  // src/commands/govern-scan.ts
127
+ var SCANNABLE_EXTENSIONS = /* @__PURE__ */ new Set([
128
+ ".tsx",
129
+ ".ts",
130
+ ".jsx",
131
+ ".js"
132
+ ]);
133
+ function getChangedFiles(rootDir, base) {
134
+ try {
135
+ const baseRef = base || detectMergeBase(rootDir);
136
+ if (!baseRef) return null;
137
+ const output = execSync(
138
+ `git diff --name-only --diff-filter=ACMR ${baseRef}...HEAD`,
139
+ { cwd: rootDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
140
+ );
141
+ return output.split("\n").map((f) => f.trim()).filter((f) => f && SCANNABLE_EXTENSIONS.has(f.slice(f.lastIndexOf(".")))).map((f) => resolve2(rootDir, f));
142
+ } catch {
143
+ return null;
144
+ }
145
+ }
146
+ function detectMergeBase(rootDir) {
147
+ try {
148
+ const remote = execSync("git rev-parse --abbrev-ref origin/HEAD", {
149
+ cwd: rootDir,
150
+ encoding: "utf-8",
151
+ stdio: ["pipe", "pipe", "pipe"]
152
+ }).trim();
153
+ if (remote) return remote;
154
+ } catch {
155
+ }
156
+ for (const candidate of ["origin/main", "origin/master"]) {
157
+ try {
158
+ execSync(`git rev-parse --verify ${candidate}`, {
159
+ cwd: rootDir,
160
+ encoding: "utf-8",
161
+ stdio: ["pipe", "pipe", "pipe"]
162
+ });
163
+ return candidate;
164
+ } catch {
165
+ }
166
+ }
167
+ return null;
168
+ }
126
169
  var SCAN_DEFAULT_RULES = {
127
170
  "safety/block-event-handlers": true,
128
171
  "safety/block-dangerous-props": true,
@@ -161,7 +204,7 @@ async function governScan(options = {}) {
161
204
  computeComponentHealth,
162
205
  computeScore
163
206
  } = await import("@fragments-sdk/govern");
164
- const { scanCodebase } = await import("./codebase-scanner-MQHUZC2G.js");
207
+ const { scanCodebase } = await import("./codebase-scanner-2T5QIDBA.js");
165
208
  const { usagesToSpec } = await import("./converter-7XM3Y6NJ.js");
166
209
  const format = options.format ?? "summary";
167
210
  const quiet = options.quiet ?? false;
@@ -186,9 +229,8 @@ ${BRAND.name} Governance Scan
186
229
  let registryMap;
187
230
  let hasRegistry = false;
188
231
  {
189
- const { readFileSync, existsSync: existsSync2 } = await import("fs");
190
232
  const fragmentsJsonPath = resolve2(rootDir, "fragments.json");
191
- if (existsSync2(fragmentsJsonPath)) {
233
+ if (existsSync(fragmentsJsonPath)) {
192
234
  try {
193
235
  const raw = readFileSync(fragmentsJsonPath, "utf-8");
194
236
  const parsed = JSON.parse(raw);
@@ -218,12 +260,34 @@ ${BRAND.name} Governance Scan
218
260
  adapters,
219
261
  registryMap ? { registry: { fragments: registryMap } } : void 0
220
262
  );
221
- if (!quiet) {
263
+ let diffFiles;
264
+ if (options.diff) {
265
+ const base = typeof options.diff === "string" ? options.diff : void 0;
266
+ const changed = getChangedFiles(rootDir, base);
267
+ if (changed && changed.length > 0) {
268
+ diffFiles = changed;
269
+ if (!quiet) {
270
+ console.log(pc.dim(` Diff mode: scanning ${changed.length} changed file(s)...
271
+ `));
272
+ }
273
+ } else if (changed && changed.length === 0) {
274
+ if (!quiet) {
275
+ console.log(pc.green(" No scannable files changed \u2014 all clear.\n"));
276
+ }
277
+ return { exitCode: 0 };
278
+ } else {
279
+ if (!quiet) {
280
+ console.log(pc.yellow(" Could not detect git diff \u2014 falling back to full scan.\n"));
281
+ }
282
+ }
283
+ }
284
+ if (!quiet && !diffFiles) {
222
285
  console.log(pc.dim(" Scanning files...\n"));
223
286
  }
224
287
  const analysis = await scanCodebase({
225
288
  rootDir,
226
289
  useCache: true,
290
+ files: diffFiles,
227
291
  onProgress: quiet ? void 0 : (progress) => {
228
292
  if (progress.phase === "scanning") {
229
293
  process.stdout.write(
@@ -349,8 +413,124 @@ ${BRAND.name} Governance Scan
349
413
  `));
350
414
  }
351
415
  }
416
+ if (options.apiKey) {
417
+ await reportToCloud({
418
+ apiKey: options.apiKey,
419
+ cloudUrl: options.cloudUrl,
420
+ verdicts: allVerdicts,
421
+ rootDir,
422
+ quiet,
423
+ diffOnly: !!diffFiles
424
+ });
425
+ }
352
426
  return { exitCode: passedFiles === totalFiles ? 0 : 1 };
353
427
  }
428
+ var DEFAULT_CLOUD_URL = "https://app.usefragments.com";
429
+ function detectGitMetadata() {
430
+ const env = process.env;
431
+ const meta = {};
432
+ if (env.GITHUB_SHA) meta.commitSha = env.GITHUB_SHA;
433
+ if (env.GITHUB_REPOSITORY) meta.repoFullName = env.GITHUB_REPOSITORY;
434
+ meta.branch = env.GITHUB_HEAD_REF || env.GITHUB_REF_NAME;
435
+ if (env.GITHUB_EVENT_NAME === "pull_request" && env.GITHUB_EVENT_PATH) {
436
+ try {
437
+ const event = JSON.parse(readFileSync(env.GITHUB_EVENT_PATH, "utf-8"));
438
+ if (event?.pull_request?.number) {
439
+ meta.pr = event.pull_request.number;
440
+ }
441
+ if (event?.pull_request?.head?.sha) {
442
+ meta.commitSha = event.pull_request.head?.sha;
443
+ }
444
+ } catch {
445
+ }
446
+ }
447
+ return meta;
448
+ }
449
+ async function reportToCloud(options) {
450
+ const { apiKey, verdicts, rootDir, quiet, diffOnly } = options;
451
+ const baseUrl = (options.cloudUrl || DEFAULT_CLOUD_URL).replace(/\/+$/, "");
452
+ const findings = [];
453
+ const { createHash } = await import("crypto");
454
+ for (const verdict of verdicts) {
455
+ for (const result of verdict.results) {
456
+ for (const v of result.violations) {
457
+ const severity = v.severity === "critical" || v.severity === "serious" ? "error" : v.severity === "moderate" ? "warning" : "info";
458
+ const fingerprint = createHash("sha256").update(`${v.rule}:${v.nodeType}:${v.nodeId}:${v.message}`).digest("hex").slice(0, 16);
459
+ let filePath;
460
+ let line;
461
+ let column;
462
+ if (v.filePath) {
463
+ filePath = v.filePath;
464
+ line = v.line;
465
+ column = v.column;
466
+ } else if (v.nodeId) {
467
+ const parts = v.nodeId.split(":");
468
+ if (parts.length >= 3) {
469
+ const col = parseInt(parts.pop(), 10);
470
+ const ln = parseInt(parts.pop(), 10);
471
+ const path = parts.join(":");
472
+ if (!isNaN(ln) && !isNaN(col) && path) {
473
+ filePath = path;
474
+ line = ln;
475
+ column = col;
476
+ }
477
+ }
478
+ if (!filePath) {
479
+ filePath = relative2(rootDir, v.nodeId);
480
+ }
481
+ }
482
+ findings.push({
483
+ ruleId: v.rule,
484
+ severity,
485
+ filePath,
486
+ line,
487
+ column,
488
+ rawValue: v.rawValue,
489
+ message: `[${result.validator}] ${v.message}`,
490
+ category: result.validator,
491
+ fingerprint,
492
+ suggestedToken: v.suggestion
493
+ });
494
+ }
495
+ }
496
+ }
497
+ if (!quiet) {
498
+ console.log(pc.dim(` Reporting ${findings.length} finding(s) to Fragments Cloud...`));
499
+ }
500
+ const gitMeta = detectGitMetadata();
501
+ try {
502
+ const response = await fetch(`${baseUrl}/api/govern/ingest`, {
503
+ method: "POST",
504
+ headers: {
505
+ "Content-Type": "application/json",
506
+ "Authorization": `Bearer ${apiKey}`
507
+ },
508
+ body: JSON.stringify({
509
+ findings,
510
+ source: "ci",
511
+ diffOnly: diffOnly ?? false,
512
+ ...gitMeta
513
+ })
514
+ });
515
+ if (!response.ok) {
516
+ const body2 = await response.json().catch(() => ({}));
517
+ const msg = body2.error ?? `HTTP ${response.status}`;
518
+ console.error(pc.red(` \u2717 Cloud report failed: ${msg}
519
+ `));
520
+ return;
521
+ }
522
+ const body = await response.json();
523
+ if (!quiet) {
524
+ console.log(
525
+ pc.green(` \u2713 Reported ${body.ingested ?? findings.length} finding(s) to Cloud`) + (body.orgSlug ? pc.dim(` (${body.orgSlug})`) : "") + "\n"
526
+ );
527
+ }
528
+ } catch (err) {
529
+ console.error(
530
+ pc.red(` \u2717 Cloud report failed: `) + pc.dim(err instanceof Error ? err.message : "Network error") + "\n"
531
+ );
532
+ }
533
+ }
354
534
  async function governWatch(options = {}) {
355
535
  const {
356
536
  loadPolicy,
@@ -449,4 +629,4 @@ export {
449
629
  governScan,
450
630
  governWatch
451
631
  };
452
- //# sourceMappingURL=govern-scan-HTACKYPF.js.map
632
+ //# sourceMappingURL=govern-scan-KTGPDZVK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/govern-scan.ts","../src/commands/govern-scan-report.ts"],"sourcesContent":["/**\n * govern scan / govern watch — Zero-config governance scanning\n *\n * Parses real JSX/TSX files via the existing codebase scanner, converts\n * component usages to UISpec, and runs governance checks per file.\n */\n\nimport pc from 'picocolors';\nimport { resolve, relative } from 'node:path';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { execSync } from 'node:child_process';\nimport { BRAND } from '../core/index.js';\nimport type { ComponentUsage } from '../service/enhance/types.js';\nimport type { GovernanceVerdict } from '@fragments-sdk/govern';\nimport {\n aggregateVerdicts,\n flattenComponentUsage,\n buildComplianceSummary,\n writeGovernScanReport,\n type GovernScanReport,\n} from './govern-scan-report.js';\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface GovernScanOptions {\n /** Root directory to scan (default: auto-detect) */\n dir?: string;\n /** Path to govern.config.ts */\n config?: string;\n /** Output format */\n format?: 'summary' | 'json' | 'sarif';\n /** Write an aggregated machine-readable JSON report */\n report?: string;\n /** Suppress non-error output */\n quiet?: boolean;\n /** Fragments Cloud API key — reports findings to Cloud */\n apiKey?: string;\n /** Fragments Cloud base URL (default: https://app.usefragments.com) */\n cloudUrl?: string;\n /** Only scan files changed vs a base ref (default base: auto-detected merge base) */\n diff?: boolean | string;\n}\n\nexport interface GovernWatchOptions extends GovernScanOptions {\n /** Debounce interval in ms (default: 300) */\n debounce?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Git diff helpers\n// ---------------------------------------------------------------------------\n\nconst SCANNABLE_EXTENSIONS = new Set([\n '.tsx', '.ts', '.jsx', '.js',\n]);\n\nfunction getChangedFiles(rootDir: string, base?: string): string[] | null {\n try {\n const baseRef = base || detectMergeBase(rootDir);\n if (!baseRef) return null;\n\n const output = execSync(\n `git diff --name-only --diff-filter=ACMR ${baseRef}...HEAD`,\n { cwd: rootDir, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },\n );\n\n return output\n .split('\\n')\n .map((f) => f.trim())\n .filter((f) => f && SCANNABLE_EXTENSIONS.has(f.slice(f.lastIndexOf('.'))))\n .map((f) => resolve(rootDir, f));\n } catch {\n return null;\n }\n}\n\nfunction detectMergeBase(rootDir: string): string | null {\n try {\n const remote = execSync('git rev-parse --abbrev-ref origin/HEAD', {\n cwd: rootDir, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n if (remote) return remote;\n } catch { /* fallback */ }\n\n for (const candidate of ['origin/main', 'origin/master']) {\n try {\n execSync(`git rev-parse --verify ${candidate}`, {\n cwd: rootDir, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'],\n });\n return candidate;\n } catch { /* try next */ }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Scan defaults — applied when no config file exists\n// ---------------------------------------------------------------------------\n\nconst SCAN_DEFAULT_RULES: Record<string, boolean | object> = {\n 'safety/block-event-handlers': true,\n 'safety/block-dangerous-props': true,\n 'safety/block-controlled-props': true,\n 'safety/block-function-props': true,\n 'safety/sanitize-hrefs': true,\n 'tokens/require-design-tokens': true,\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Auto-detect root directory by looking for common React project dirs\n */\nfunction detectRootDir(cwd: string): string {\n const candidates = ['src', 'app', 'pages', 'components'];\n for (const dir of candidates) {\n if (existsSync(resolve(cwd, dir))) {\n return cwd;\n }\n }\n return cwd;\n}\n\n/**\n * Group component usages by their source file\n */\nfunction groupByFile(usages: ComponentUsage[]): Map<string, ComponentUsage[]> {\n const grouped = new Map<string, ComponentUsage[]>();\n for (const usage of usages) {\n const existing = grouped.get(usage.filePath);\n if (existing) {\n existing.push(usage);\n } else {\n grouped.set(usage.filePath, [usage]);\n }\n }\n return grouped;\n}\n\n\n// ---------------------------------------------------------------------------\n// governScan\n// ---------------------------------------------------------------------------\n\nexport async function governScan(\n options: GovernScanOptions = {},\n): Promise<{ exitCode: number }> {\n const {\n loadPolicy,\n createEngine,\n buildAdaptersFromConfig,\n formatVerdict,\n computeComponentHealth,\n computeScore,\n } = await import('@fragments-sdk/govern');\n\n const { scanCodebase } = await import(\n '../service/enhance/codebase-scanner.js'\n );\n const { usagesToSpec } = await import(\n '../service/enhance/converter.js'\n );\n\n const format = options.format ?? 'summary';\n const quiet = options.quiet ?? false;\n\n if (!quiet) {\n console.log(pc.cyan(`\\n${BRAND.name} Governance Scan\\n`));\n }\n\n // 1. Resolve root directory\n const rootDir = resolve(options.dir ?? detectRootDir(process.cwd()));\n if (!quiet) {\n console.log(pc.dim(` Root: ${rootDir}\\n`));\n }\n\n // 2. Load policy — use scan defaults if no config exists\n let policy = await loadPolicy(options.config);\n const hasRules = Object.keys(policy.rules).length > 0;\n\n if (!hasRules) {\n policy = { ...policy, rules: SCAN_DEFAULT_RULES };\n if (!quiet) {\n console.log(pc.dim(' No config found — using scan defaults (safety + tokens)\\n'));\n }\n }\n\n // 3. Load contract registry for contract-aware scoring (if fragments.json exists)\n let registryMap: Record<string, unknown> | undefined;\n let hasRegistry = false;\n {\n const fragmentsJsonPath = resolve(rootDir, 'fragments.json');\n if (existsSync(fragmentsJsonPath)) {\n try {\n const raw = readFileSync(fragmentsJsonPath, 'utf-8');\n const parsed = JSON.parse(raw);\n if (parsed.fragments && Array.isArray(parsed.fragments)) {\n const map: Record<string, unknown> = {};\n for (const fragment of parsed.fragments) {\n if (fragment.meta?.name) {\n map[fragment.meta.name] = fragment;\n }\n }\n registryMap = map;\n hasRegistry = true;\n if (!quiet) {\n console.log(\n pc.dim(` Contract registry loaded (${parsed.fragments.length} components)\\n`),\n );\n }\n }\n } catch {\n // Invalid fragments.json — skip registry-aware summary\n }\n }\n }\n\n // 4. Build adapters from policy config\n const adapters = buildAdaptersFromConfig(policy.audit);\n\n // 5. Create engine (with registry for contract-aware validators)\n const engine = createEngine(\n policy,\n adapters,\n registryMap\n ? { registry: { fragments: registryMap as Record<string, Record<string, unknown>> } }\n : undefined,\n );\n\n // 6. Scan codebase (optionally scoped to changed files via --diff)\n let diffFiles: string[] | undefined;\n if (options.diff) {\n const base = typeof options.diff === 'string' ? options.diff : undefined;\n const changed = getChangedFiles(rootDir, base);\n if (changed && changed.length > 0) {\n diffFiles = changed;\n if (!quiet) {\n console.log(pc.dim(` Diff mode: scanning ${changed.length} changed file(s)...\\n`));\n }\n } else if (changed && changed.length === 0) {\n if (!quiet) {\n console.log(pc.green(' No scannable files changed — all clear.\\n'));\n }\n return { exitCode: 0 };\n } else {\n if (!quiet) {\n console.log(pc.yellow(' Could not detect git diff — falling back to full scan.\\n'));\n }\n }\n }\n\n if (!quiet && !diffFiles) {\n console.log(pc.dim(' Scanning files...\\n'));\n }\n\n const analysis = await scanCodebase({\n rootDir,\n useCache: true,\n files: diffFiles,\n onProgress: quiet\n ? undefined\n : (progress) => {\n if (progress.phase === 'scanning') {\n process.stdout.write(\n `\\r ${pc.dim(`[${progress.current}/${progress.total}]`)} ${pc.dim(relative(rootDir, progress.currentFile))}`,\n );\n }\n },\n });\n\n if (!quiet) {\n // Clear progress line\n process.stdout.write('\\r' + ' '.repeat(80) + '\\r');\n console.log(\n pc.dim(` Scanned ${analysis.totalFiles} files, found ${analysis.totalComponents} component types\\n`),\n );\n }\n\n // 7. Collect all usages across components\n const allUsages: ComponentUsage[] = [];\n for (const comp of Object.values(analysis.components)) {\n allUsages.push(...comp.usages);\n }\n\n if (allUsages.length === 0) {\n if (!quiet) {\n console.log(pc.yellow(' No component usages found.\\n'));\n }\n if (options.report) {\n const report: GovernScanReport = {\n verdict: aggregateVerdicts([], computeScore, 'ci'),\n componentUsage: [],\n };\n await writeGovernScanReport(options.report, report);\n if (!quiet) {\n console.log(pc.dim(` Wrote governance report: ${resolve(options.report)}\\n`));\n }\n }\n return { exitCode: 0 };\n }\n\n // 8. Group by file and run checks\n const grouped = groupByFile(allUsages);\n let totalFiles = 0;\n let passedFiles = 0;\n let totalViolations = 0;\n const violationCounts = new Map<string, number>();\n const allVerdicts: GovernanceVerdict[] = [];\n\n for (const [filePath, usages] of grouped) {\n const spec = usagesToSpec(usages, filePath, rootDir);\n const relPath = relative(rootDir, filePath);\n\n const verdict = await engine.check(spec, {\n runner: 'cli',\n input: relPath,\n });\n allVerdicts.push(verdict);\n\n totalFiles++;\n\n if (verdict.passed) {\n passedFiles++;\n } else {\n if (!quiet) {\n console.log(pc.red(` ✗ ${relPath}`));\n if (format === 'summary') {\n for (const result of verdict.results) {\n for (const v of result.violations) {\n const count = violationCounts.get(v.rule) ?? 0;\n violationCounts.set(v.rule, count + 1);\n totalViolations++;\n console.log(\n pc.dim(` ${v.severity} `) +\n pc.yellow(v.rule) +\n pc.dim(` — ${v.message}`),\n );\n if (v.nodeId) {\n console.log(pc.dim(` at ${v.nodeId}`));\n }\n }\n }\n }\n }\n }\n\n if (verdict.passed && !quiet && format === 'summary') {\n console.log(pc.green(` ✓ ${relPath}`) + pc.dim(` (${usages.length} components, score: ${verdict.score}/100)`));\n }\n\n // JSON/SARIF: print per-file\n if (format === 'json' || format === 'sarif') {\n const output = formatVerdict(verdict, format);\n console.log(output);\n }\n }\n\n // 8b. Compute component health\n const health = computeComponentHealth(allVerdicts, registryMap ?? {});\n\n // 9. Summary\n if (!quiet && format === 'summary') {\n console.log(pc.dim('\\n ─────────────────────────────────────\\n'));\n console.log(` Files checked: ${totalFiles}`);\n console.log(` Passed: ${passedFiles}/${totalFiles}`);\n console.log(` Violations: ${totalViolations}`);\n\n if (violationCounts.size > 0) {\n console.log(pc.dim('\\n Top violations:'));\n const sorted = [...violationCounts.entries()].sort((a, b) => b[1] - a[1]);\n for (const [rule, count] of sorted.slice(0, 5)) {\n console.log(pc.dim(` ${count}× `) + pc.yellow(rule));\n }\n }\n\n // Component health\n console.log(pc.dim('\\n Component Health:'));\n console.log(` Contract coverage: ${health.contractCoverage}% (${health.contractedComponents}/${health.totalComponents})`);\n console.log(` Compliance rate: ${health.overallCompliance}%`);\n\n if (health.uncontracted.length > 0) {\n console.log(pc.dim(` Uncontracted: ${health.uncontracted.slice(0, 5).join(', ')}${health.uncontracted.length > 5 ? ` (+${health.uncontracted.length - 5} more)` : ''}`));\n }\n\n console.log();\n\n if (passedFiles === totalFiles) {\n console.log(pc.green(` ✓ All files passed governance checks\\n`));\n } else {\n console.log(\n pc.red(` ✗ ${totalFiles - passedFiles} file(s) failed governance checks\\n`),\n );\n }\n }\n\n if (options.report) {\n const report: GovernScanReport = {\n verdict: aggregateVerdicts(allVerdicts, computeScore, 'ci'),\n componentUsage: flattenComponentUsage(allUsages, rootDir),\n };\n if (hasRegistry) {\n report.complianceSummary = buildComplianceSummary(health);\n }\n await writeGovernScanReport(options.report, report);\n if (!quiet) {\n console.log(pc.dim(` Wrote governance report: ${resolve(options.report)}\\n`));\n }\n }\n\n // Report to Fragments Cloud\n if (options.apiKey) {\n await reportToCloud({\n apiKey: options.apiKey,\n cloudUrl: options.cloudUrl,\n verdicts: allVerdicts,\n rootDir,\n quiet,\n diffOnly: !!diffFiles,\n });\n }\n\n return { exitCode: passedFiles === totalFiles ? 0 : 1 };\n}\n\n// ---------------------------------------------------------------------------\n// Cloud reporting\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_CLOUD_URL = 'https://app.usefragments.com';\n\ninterface CloudReportOptions {\n apiKey: string;\n cloudUrl?: string;\n verdicts: GovernanceVerdict[];\n rootDir: string;\n quiet: boolean;\n diffOnly?: boolean;\n}\n\nfunction detectGitMetadata(): {\n commitSha?: string;\n branch?: string;\n pr?: number;\n repoFullName?: string;\n} {\n const env = process.env;\n const meta: ReturnType<typeof detectGitMetadata> = {};\n\n if (env.GITHUB_SHA) meta.commitSha = env.GITHUB_SHA;\n if (env.GITHUB_REPOSITORY) meta.repoFullName = env.GITHUB_REPOSITORY;\n meta.branch = env.GITHUB_HEAD_REF || env.GITHUB_REF_NAME;\n\n if (env.GITHUB_EVENT_NAME === 'pull_request' && env.GITHUB_EVENT_PATH) {\n try {\n const event = JSON.parse(readFileSync(env.GITHUB_EVENT_PATH, 'utf-8'));\n if (event?.pull_request?.number) {\n meta.pr = event.pull_request.number;\n }\n if (event?.pull_request?.head?.sha) {\n meta.commitSha = event.pull_request.head?.sha;\n }\n } catch {\n // Event file unreadable — skip PR number\n }\n }\n\n return meta;\n}\n\nasync function reportToCloud(options: CloudReportOptions): Promise<void> {\n const { apiKey, verdicts, rootDir, quiet, diffOnly } = options;\n const baseUrl = (options.cloudUrl || DEFAULT_CLOUD_URL).replace(/\\/+$/, '');\n\n const findings: Array<{\n ruleId: string;\n severity: 'error' | 'warning' | 'info';\n filePath?: string;\n line?: number;\n column?: number;\n rawValue?: string;\n suggestedToken?: string;\n message: string;\n category?: string;\n fingerprint: string;\n }> = [];\n\n const { createHash } = await import('node:crypto');\n\n for (const verdict of verdicts) {\n for (const result of verdict.results) {\n for (const v of result.violations) {\n const severity = v.severity === 'critical' || v.severity === 'serious'\n ? 'error'\n : v.severity === 'moderate'\n ? 'warning'\n : 'info';\n\n const fingerprint = createHash('sha256')\n .update(`${v.rule}:${v.nodeType}:${v.nodeId}:${v.message}`)\n .digest('hex')\n .slice(0, 16);\n\n let filePath: string | undefined;\n let line: number | undefined;\n let column: number | undefined;\n\n if (v.filePath) {\n filePath = v.filePath;\n line = v.line;\n column = v.column;\n } else if (v.nodeId) {\n const parts = v.nodeId.split(':');\n if (parts.length >= 3) {\n const col = parseInt(parts.pop()!, 10);\n const ln = parseInt(parts.pop()!, 10);\n const path = parts.join(':');\n if (!isNaN(ln) && !isNaN(col) && path) {\n filePath = path;\n line = ln;\n column = col;\n }\n }\n if (!filePath) {\n filePath = relative(rootDir, v.nodeId);\n }\n }\n\n findings.push({\n ruleId: v.rule,\n severity,\n filePath,\n line,\n column,\n rawValue: v.rawValue,\n message: `[${result.validator}] ${v.message}`,\n category: result.validator,\n fingerprint,\n suggestedToken: v.suggestion,\n });\n }\n }\n }\n\n if (!quiet) {\n console.log(pc.dim(` Reporting ${findings.length} finding(s) to Fragments Cloud...`));\n }\n\n const gitMeta = detectGitMetadata();\n\n try {\n const response = await fetch(`${baseUrl}/api/govern/ingest`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n findings,\n source: 'ci',\n diffOnly: diffOnly ?? false,\n ...gitMeta,\n }),\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({}));\n const msg = (body as { error?: string }).error ?? `HTTP ${response.status}`;\n console.error(pc.red(` ✗ Cloud report failed: ${msg}\\n`));\n return;\n }\n\n const body = await response.json() as { ingested?: number; orgSlug?: string };\n if (!quiet) {\n console.log(\n pc.green(` ✓ Reported ${body.ingested ?? findings.length} finding(s) to Cloud`) +\n (body.orgSlug ? pc.dim(` (${body.orgSlug})`) : '') +\n '\\n',\n );\n }\n } catch (err) {\n console.error(\n pc.red(` ✗ Cloud report failed: `) +\n pc.dim(err instanceof Error ? err.message : 'Network error') +\n '\\n',\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// governWatch\n// ---------------------------------------------------------------------------\n\nexport async function governWatch(\n options: GovernWatchOptions = {},\n): Promise<void> {\n const {\n loadPolicy,\n createEngine,\n buildAdaptersFromConfig,\n formatVerdict,\n } = await import('@fragments-sdk/govern');\n\n const { scanFile } = await import('../service/enhance/scanner.js');\n const { usagesToSpec } = await import(\n '../service/enhance/converter.js'\n );\n\n const quiet = options.quiet ?? false;\n const debounceMs = options.debounce ?? 300;\n const format = options.format ?? 'summary';\n\n // 1. Run initial scan\n console.log(pc.cyan(`\\n${BRAND.name} Governance Watch\\n`));\n\n const { exitCode } = await governScan(options);\n if (!quiet) {\n console.log(\n pc.dim(` Initial scan ${exitCode === 0 ? 'passed' : 'completed with violations'}\\n`),\n );\n }\n\n // 2. Set up engine for incremental checks\n const rootDir = resolve(options.dir ?? detectRootDir(process.cwd()));\n let policy = await loadPolicy(options.config);\n if (Object.keys(policy.rules).length === 0) {\n policy = { ...policy, rules: SCAN_DEFAULT_RULES };\n }\n const adapters = buildAdaptersFromConfig(policy.audit);\n const engine = createEngine(policy, adapters);\n\n // 3. Watch for changes\n console.log(pc.dim(' Watching for changes... (Ctrl+C to stop)\\n'));\n\n const chokidar = await import('chokidar');\n\n const watcher = chokidar.watch(\n ['**/*.tsx', '**/*.ts', '**/*.jsx', '**/*.js'],\n {\n cwd: rootDir,\n ignoreInitial: true,\n ignored: [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/.next/**',\n '**/*.test.*',\n '**/*.spec.*',\n '**/*.stories.*',\n ],\n awaitWriteFinish: { stabilityThreshold: debounceMs },\n },\n );\n\n const handleChange = async (changedRelPath: string) => {\n const absolutePath = resolve(rootDir, changedRelPath);\n\n try {\n const { usages } = await scanFile(absolutePath);\n\n if (usages.length === 0) {\n if (!quiet) {\n console.log(pc.dim(` ○ ${changedRelPath} — no component usages`));\n }\n return;\n }\n\n const spec = usagesToSpec(usages, absolutePath, rootDir);\n const verdict = await engine.check(spec, {\n runner: 'cli',\n input: changedRelPath,\n });\n\n if (verdict.passed) {\n console.log(\n pc.green(` ✓ ${changedRelPath}`) +\n pc.dim(` (${usages.length} components, score: ${verdict.score}/100)`),\n );\n } else {\n console.log(pc.red(` ✗ ${changedRelPath}`));\n if (format === 'summary') {\n for (const result of verdict.results) {\n for (const v of result.violations) {\n console.log(\n pc.dim(` ${v.severity} `) +\n pc.yellow(v.rule) +\n pc.dim(` — ${v.message}`),\n );\n }\n }\n } else {\n console.log(formatVerdict(verdict, format));\n }\n }\n } catch (error) {\n if (!quiet) {\n console.log(\n pc.dim(` ⚠ ${changedRelPath} — `) +\n pc.yellow(error instanceof Error ? error.message : 'parse error'),\n );\n }\n }\n };\n\n watcher.on('change', handleChange);\n watcher.on('add', handleChange);\n\n // Keep process alive\n await new Promise(() => {});\n}\n","import { resolve, dirname, relative } from 'node:path';\nimport type {\n GovernanceVerdict,\n Severity,\n ComponentHealthSummary,\n Violation,\n} from '@fragments-sdk/govern';\nimport type { ComponentUsage } from '../service/enhance/types.js';\n\nexport interface FlatUsageEntry {\n component: string;\n file: string;\n occurrences: number;\n}\n\nexport interface ComplianceSummary {\n complianceRate: number;\n passingUsages: number;\n totalUsages: number;\n contractedCount: number;\n detectedCount: number;\n}\n\nexport interface GovernScanReport {\n verdict: GovernanceVerdict;\n componentUsage: FlatUsageEntry[];\n complianceSummary?: ComplianceSummary;\n}\n\nconst SEVERITY_RANK: Record<Severity, number> = {\n critical: 4,\n serious: 3,\n moderate: 2,\n minor: 1,\n};\n\nfunction mergeSeverity(a: Severity, b: Severity): Severity {\n return SEVERITY_RANK[a] >= SEVERITY_RANK[b] ? a : b;\n}\n\nexport function aggregateVerdicts(\n verdicts: GovernanceVerdict[],\n computeScore: (violations: Violation[]) => number,\n runner: string = 'cli',\n): GovernanceVerdict {\n if (verdicts.length === 0) {\n return {\n passed: true,\n score: 100,\n results: [],\n metadata: {\n runner,\n duration: 0,\n nodeCount: 0,\n componentTypes: [],\n },\n };\n }\n\n const byValidator = new Map<string, GovernanceVerdict['results'][number]>();\n let duration = 0;\n let nodeCount = 0;\n const componentTypes = new Set<string>();\n\n for (const verdict of verdicts) {\n duration += verdict.metadata.duration;\n nodeCount += verdict.metadata.nodeCount;\n for (const type of verdict.metadata.componentTypes) {\n componentTypes.add(type);\n }\n\n for (const result of verdict.results) {\n const existing = byValidator.get(result.validator);\n if (!existing) {\n byValidator.set(result.validator, {\n validator: result.validator,\n severity: result.severity,\n passed: result.passed,\n violations: [...result.violations],\n suggestions: result.suggestions ? [...result.suggestions] : undefined,\n });\n continue;\n }\n\n existing.passed = existing.passed && result.passed;\n existing.severity = mergeSeverity(existing.severity, result.severity);\n existing.violations.push(...result.violations);\n\n if (result.suggestions?.length) {\n const merged = existing.suggestions ?? [];\n merged.push(...result.suggestions);\n existing.suggestions = merged;\n }\n }\n }\n\n const results = [...byValidator.values()].sort((a, b) =>\n a.validator.localeCompare(b.validator),\n );\n const allViolations = results.flatMap((result) => result.violations);\n\n return {\n passed: verdicts.every((verdict) => verdict.passed),\n score: computeScore(allViolations),\n results,\n metadata: {\n runner,\n duration,\n nodeCount,\n componentTypes: [...componentTypes].sort(),\n },\n };\n}\n\nexport function flattenComponentUsage(\n usages: ComponentUsage[],\n rootDir: string,\n): FlatUsageEntry[] {\n const counts = new Map<string, number>();\n\n for (const usage of usages) {\n const relPath = relative(rootDir, usage.filePath);\n const key = `${relPath}\\u0000${usage.componentName}`;\n counts.set(key, (counts.get(key) ?? 0) + 1);\n }\n\n return [...counts.entries()]\n .map(([key, occurrences]) => {\n const separatorIndex = key.indexOf('\\u0000');\n const file = key.slice(0, separatorIndex);\n const component = key.slice(separatorIndex + 1);\n return { component, file, occurrences };\n })\n .sort((a, b) =>\n a.file === b.file\n ? a.component.localeCompare(b.component)\n : a.file.localeCompare(b.file),\n );\n}\n\nexport function buildComplianceSummary(\n health: ComponentHealthSummary,\n): ComplianceSummary {\n const usageTotals = Object.values(health.components).reduce(\n (acc, component) => {\n acc.passingUsages += component.passed;\n acc.totalUsages += component.total;\n return acc;\n },\n { passingUsages: 0, totalUsages: 0 },\n );\n\n return {\n complianceRate: health.overallCompliance,\n passingUsages: usageTotals.passingUsages,\n totalUsages: usageTotals.totalUsages,\n contractedCount: health.contractedComponents,\n detectedCount: health.totalComponents,\n };\n}\n\nexport async function writeGovernScanReport(\n path: string,\n report: GovernScanReport,\n): Promise<void> {\n const { mkdir, writeFile } = await import('node:fs/promises');\n const absPath = resolve(path);\n await mkdir(dirname(absPath), { recursive: true });\n await writeFile(absPath, JSON.stringify(report, null, 2), 'utf-8');\n}\n"],"mappings":"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","names":["resolve","relative","resolve","relative","body"]}
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { createRequire as __banner_createRequire } from 'module'; const require
2
2
  import {
3
3
  generateStaticViewer,
4
4
  generateViewerFromJson
5
- } from "./chunk-OZZ4SVZX.js";
5
+ } from "./chunk-SNZXGHL2.js";
6
6
  import {
7
7
  runAnalyzeCommand,
8
8
  runDiffCommand,
@@ -11,21 +11,21 @@ import {
11
11
  validateCoverage,
12
12
  validateSchema,
13
13
  validateSnippets
14
- } from "./chunk-ACFVKMVZ.js";
14
+ } from "./chunk-VT2J62ND.js";
15
15
  import {
16
16
  discoverComponentFiles,
17
17
  discoverFragmentFiles,
18
18
  extractComponentName,
19
19
  findConfigFile,
20
20
  loadConfig
21
- } from "./chunk-XRADMHMV.js";
22
- import "./chunk-77AAP6R6.js";
21
+ } from "./chunk-HNHE64CR.js";
22
+ import "./chunk-ANTWP3UG.js";
23
23
  import "./chunk-D2CDBRNU.js";
24
24
  import {
25
25
  defineBlock,
26
26
  defineFragment
27
- } from "./chunk-SJFSG7QF.js";
28
- import "./chunk-QCN35LJU.js";
27
+ } from "./chunk-FFCI6OVZ.js";
28
+ import "./chunk-SAQW37L5.js";
29
29
  import "./chunk-7DZC4YEV.js";
30
30
 
31
31
  // src/index.ts