@aiready/visualizer 0.7.4 → 0.7.6

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/cli.js CHANGED
@@ -4,7 +4,7 @@ import { spawn } from 'child_process';
4
4
  import path2, { dirname, resolve } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import fs from 'fs';
7
- import { Severity, generateHTML, UnifiedReportSchema, ToolName, normalizeAnalysisResult } from '@aiready/core';
7
+ import { Severity, generateHTML, UnifiedReportSchema, ToolName, normalizeAnalysisResult, normalizeSeverity } from '@aiready/core';
8
8
 
9
9
  var GRAPH_CONSTANTS = {
10
10
  DEFAULT_NODE_SIZE: 1,
@@ -55,13 +55,7 @@ function getPackageGroup(fp) {
55
55
  return parts.length > 1 ? parts[1] : parts[0];
56
56
  }
57
57
  function rankSeverity(s) {
58
- if (!s) return null;
59
- const ss = String(s).toLowerCase();
60
- if (ss.includes("critical")) return Severity.Critical;
61
- if (ss.includes("major")) return Severity.Major;
62
- if (ss.includes("minor")) return Severity.Minor;
63
- if (ss.includes("info")) return Severity.Info;
64
- return null;
58
+ return normalizeSeverity(s || void 0);
65
59
  }
66
60
  function getColorForSeverity(sev) {
67
61
  switch (sev) {
@@ -121,7 +115,11 @@ var GraphBuilder = class _GraphBuilder {
121
115
  if (source === target) return;
122
116
  const key = `${source}->${target}`;
123
117
  if (!this.edgesSet.has(key)) {
124
- this.edges.push({ source, target, type });
118
+ this.edges.push({
119
+ source,
120
+ target,
121
+ type
122
+ });
125
123
  this.edgesSet.add(key);
126
124
  }
127
125
  }
@@ -184,12 +182,43 @@ var GraphBuilder = class _GraphBuilder {
184
182
  if (Array.isArray(toolData)) return toolData;
185
183
  return toolData.results ?? toolData.issues ?? [];
186
184
  };
187
- this.processPatterns(builder, getResults(ToolName.PatternDetect, "patterns"), rootDir, bumpIssue);
185
+ this.processPatterns(
186
+ builder,
187
+ getResults(ToolName.PatternDetect, "patterns"),
188
+ rootDir,
189
+ bumpIssue
190
+ );
188
191
  this.processDuplicates(builder, report, rootDir, fileIssues);
189
- this.processContext(builder, getResults(ToolName.ContextAnalyzer, "context"), rootDir, bumpIssue);
190
- this.processToolResults(builder, ToolName.DocDrift, "docDrift", report, bumpIssue, "Doc-Drift Issue");
191
- this.processToolResults(builder, ToolName.DependencyHealth, "dependencyHealth", report, bumpIssue, "Dependency Issue");
192
- this.processToolResults(builder, ToolName.ContractEnforcement, "contractEnforcement", report, bumpIssue, "Contract Gap");
192
+ this.processContext(
193
+ builder,
194
+ getResults(ToolName.ContextAnalyzer, "context"),
195
+ rootDir,
196
+ bumpIssue
197
+ );
198
+ this.processToolResults(
199
+ builder,
200
+ ToolName.DocDrift,
201
+ "docDrift",
202
+ report,
203
+ bumpIssue,
204
+ "Doc-Drift Issue"
205
+ );
206
+ this.processToolResults(
207
+ builder,
208
+ ToolName.DependencyHealth,
209
+ "dependencyHealth",
210
+ report,
211
+ bumpIssue,
212
+ "Dependency Issue"
213
+ );
214
+ this.processToolResults(
215
+ builder,
216
+ ToolName.ContractEnforcement,
217
+ "contractEnforcement",
218
+ report,
219
+ bumpIssue,
220
+ "Contract Gap"
221
+ );
193
222
  return this.finalizeGraph(builder, fileIssues, report);
194
223
  }
195
224
  static processPatterns(builder, results, rootDir, bumpIssue) {
@@ -225,7 +254,11 @@ var GraphBuilder = class _GraphBuilder {
225
254
  const refs = extractReferencedPaths(issue.message);
226
255
  refs.forEach((ref) => {
227
256
  const target = path2.isAbsolute(ref) ? ref : path2.resolve(path2.dirname(file), ref);
228
- builder.addNode(target, "Referenced file", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
257
+ builder.addNode(
258
+ target,
259
+ "Referenced file",
260
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
261
+ );
229
262
  builder.addEdge(file, target, "reference");
230
263
  });
231
264
  const percMatch = (issue.message.match(/(\d+)%/) || [])[1];
@@ -234,11 +267,17 @@ var GraphBuilder = class _GraphBuilder {
234
267
  if (wantFuzzy) {
235
268
  const fileGroup = getPackageGroup(file);
236
269
  for (const [base, pathsSet] of basenameMap.entries()) {
237
- if (!issue.message.includes(base) || base === path2.basename(file)) continue;
270
+ if (!issue.message.includes(base) || base === path2.basename(file))
271
+ continue;
238
272
  for (const target of pathsSet) {
239
273
  const targetGroup = getPackageGroup(target);
240
- if (fileGroup !== targetGroup && !(perc !== null && perc >= GRAPH_CONSTANTS.FUZZY_MATCH_HIGH_THRESHOLD)) continue;
241
- builder.addNode(target, "Fuzzy match", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
274
+ if (fileGroup !== targetGroup && !(perc !== null && perc >= GRAPH_CONSTANTS.FUZZY_MATCH_HIGH_THRESHOLD))
275
+ continue;
276
+ builder.addNode(
277
+ target,
278
+ "Fuzzy match",
279
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
280
+ );
242
281
  builder.addEdge(file, target, "similarity");
243
282
  }
244
283
  }
@@ -250,8 +289,16 @@ var GraphBuilder = class _GraphBuilder {
250
289
  const patternData = report[ToolName.PatternDetect] || report.patternDetect || report.patterns || {};
251
290
  const duplicates = (Array.isArray(patternData.duplicates) ? patternData.duplicates : null) || (patternData.summary && Array.isArray(patternData.summary.duplicates) ? patternData.summary.duplicates : null) || (Array.isArray(report.duplicates) ? report.duplicates : []);
252
291
  duplicates.forEach((dup) => {
253
- builder.addNode(dup.file1, "Similarity target", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
254
- builder.addNode(dup.file2, "Similarity target", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
292
+ builder.addNode(
293
+ dup.file1,
294
+ "Similarity target",
295
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
296
+ );
297
+ builder.addNode(
298
+ dup.file2,
299
+ "Similarity target",
300
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
301
+ );
255
302
  builder.addEdge(dup.file1, dup.file2, "similarity");
256
303
  [dup.file1, dup.file2].forEach((file) => {
257
304
  const id = path2.resolve(rootDir, file);
@@ -267,7 +314,11 @@ var GraphBuilder = class _GraphBuilder {
267
314
  const normalized = normalizeAnalysisResult(ctx);
268
315
  const file = normalized.fileName;
269
316
  if (!file) return;
270
- builder.addNode(file, `Deps: ${ctx.dependencyCount || 0}`, GRAPH_CONSTANTS.DEFAULT_CONTEXT_SIZE);
317
+ builder.addNode(
318
+ file,
319
+ `Deps: ${ctx.dependencyCount || 0}`,
320
+ GRAPH_CONSTANTS.DEFAULT_CONTEXT_SIZE
321
+ );
271
322
  normalized.issues.forEach((issue) => {
272
323
  bumpIssue(file, issue.severity);
273
324
  });
@@ -277,8 +328,13 @@ var GraphBuilder = class _GraphBuilder {
277
328
  const resolvedTarget = path2.resolve(builder.rootDir, resolvedRel);
278
329
  const keyA = `${resolvedFile}->${resolvedTarget}`;
279
330
  const keyB = `${resolvedTarget}->${resolvedFile}`;
280
- if (builder["edgesSet"].has(keyA) || builder["edgesSet"].has(keyB)) return;
281
- builder.addNode(resolvedRel, "Related file", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
331
+ if (builder["edgesSet"].has(keyA) || builder["edgesSet"].has(keyB))
332
+ return;
333
+ builder.addNode(
334
+ resolvedRel,
335
+ "Related file",
336
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
337
+ );
282
338
  const node = builder["nodesMap"].get(resolvedTarget);
283
339
  if (node) {
284
340
  node.size = (node.size || 1) + 2;
@@ -298,7 +354,11 @@ var GraphBuilder = class _GraphBuilder {
298
354
  ];
299
355
  for (const p of possiblePaths) {
300
356
  if (fs.existsSync(p)) {
301
- builder.addNode(p, "Dependency", GRAPH_CONSTANTS.DEFAULT_DEPENDENCY_SIZE);
357
+ builder.addNode(
358
+ p,
359
+ "Dependency",
360
+ GRAPH_CONSTANTS.DEFAULT_DEPENDENCY_SIZE
361
+ );
302
362
  builder.addEdge(file, p, "dependency");
303
363
  break;
304
364
  }
@@ -343,10 +403,14 @@ var GraphBuilder = class _GraphBuilder {
343
403
  node.duplicates = record.duplicates || 0;
344
404
  node.color = getColorForSeverity(record.maxSeverity);
345
405
  node.group = getPackageGroup(node.id);
346
- if (record.maxSeverity === Severity.Critical) criticalIssues += record.count;
347
- else if (record.maxSeverity === Severity.Major) majorIssues += record.count;
348
- else if (record.maxSeverity === Severity.Minor) minorIssues += record.count;
349
- else if (record.maxSeverity === Severity.Info) infoIssues += record.count;
406
+ if (record.maxSeverity === Severity.Critical)
407
+ criticalIssues += record.count;
408
+ else if (record.maxSeverity === Severity.Major)
409
+ majorIssues += record.count;
410
+ else if (record.maxSeverity === Severity.Minor)
411
+ minorIssues += record.count;
412
+ else if (record.maxSeverity === Severity.Info)
413
+ infoIssues += record.count;
350
414
  } else {
351
415
  node.color = getColorForSeverity(null);
352
416
  node.group = getPackageGroup(node.id);
@@ -369,7 +433,11 @@ function createSampleGraph() {
369
433
  builder.addNode("src/components/Button.tsx", "Button", 15);
370
434
  builder.addNode("src/utils/helpers.ts", "helpers", 12);
371
435
  builder.addNode("src/services/api.ts", "api", 18);
372
- builder.addEdge("src/components/Button.tsx", "src/utils/helpers.ts", "dependency");
436
+ builder.addEdge(
437
+ "src/components/Button.tsx",
438
+ "src/utils/helpers.ts",
439
+ "dependency"
440
+ );
373
441
  builder.addEdge("src/utils/helpers.ts", "src/services/api.ts", "dependency");
374
442
  return builder.build();
375
443
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/graph/utils.ts","../src/graph/builder.ts","../src/cli/index.ts"],"names":["path","file","Severity","__filename","__dirname"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Graph builder utilities\n */\n\nimport path from 'path';\nimport { Severity } from '@aiready/core';\n\n/**\n * Constants for graph building\n */\nexport const GRAPH_CONSTANTS = {\n DEFAULT_NODE_SIZE: 1,\n DEFAULT_REFERENCE_SIZE: 5,\n DEFAULT_DEPENDENCY_SIZE: 2,\n DEFAULT_CONTEXT_SIZE: 10,\n FUZZY_MATCH_THRESHOLD: 50,\n FUZZY_MATCH_HIGH_THRESHOLD: 80,\n COLORS: {\n CRITICAL: '#ff4d4f',\n MAJOR: '#ff9900',\n MINOR: '#ffd666',\n INFO: '#91d5ff',\n DEFAULT: '#97c2fc',\n },\n SEVERITY_ORDER: {\n [Severity.Critical]: 3,\n [Severity.Major]: 2,\n [Severity.Minor]: 1,\n [Severity.Info]: 0,\n } as Record<Severity, number>,\n};\n\n/**\n * Normalizes a file path relative to a root directory for labels.\n */\nexport function normalizeLabel(filePath: string, rootDir: string): string {\n try {\n return path.relative(rootDir, filePath);\n } catch {\n return filePath;\n }\n}\n\n/**\n * Extracts absolute and relative file paths from a message string.\n */\nexport function extractReferencedPaths(message: string): string[] {\n if (!message || typeof message !== 'string') return [];\n const reAbs = /\\/(?:[\\w\\-.]+\\/)+[\\w\\-.]+\\.(?:ts|tsx|js|jsx|py|java|go)/g;\n const reRel =\n /(?:\\.\\/|\\.\\.\\/)(?:[\\w\\-.]+\\/)+[\\w\\-.]+\\.(?:ts|tsx|js|jsx|py|java|go)/g;\n const abs = (message.match(reAbs) ?? []) as string[];\n const rel = (message.match(reRel) ?? []) as string[];\n return abs.concat(rel);\n}\n\n/**\n * Determines the package or module group for a given file path.\n */\nexport function getPackageGroup(\n fp: string | null | undefined\n): string | undefined {\n if (!fp) return undefined;\n const parts = fp.split(path.sep);\n const pkgIdx = parts.indexOf('packages');\n if (pkgIdx >= 0 && parts.length > pkgIdx + 1)\n return `packages/${parts[pkgIdx + 1]}`;\n const landingIdx = parts.indexOf('landing');\n if (landingIdx >= 0) return 'landing';\n const scriptsIdx = parts.indexOf('scripts');\n if (scriptsIdx >= 0) return 'scripts';\n return parts.length > 1 ? parts[1] : parts[0];\n}\n\n/**\n * Ranks severity from a string or null.\n */\nexport function rankSeverity(s: string | null | undefined): Severity | null {\n if (!s) return null;\n const ss = String(s).toLowerCase();\n if (ss.includes('critical')) return Severity.Critical;\n if (ss.includes('major')) return Severity.Major;\n if (ss.includes('minor')) return Severity.Minor;\n if (ss.includes('info')) return Severity.Info;\n return null;\n}\n\n/**\n * Returns a color string for a given severity.\n */\nexport function getColorForSeverity(sev: Severity | null): string {\n switch (sev) {\n case Severity.Critical:\n return GRAPH_CONSTANTS.COLORS.CRITICAL;\n case Severity.Major:\n return GRAPH_CONSTANTS.COLORS.MAJOR;\n case Severity.Minor:\n return GRAPH_CONSTANTS.COLORS.MINOR;\n case Severity.Info:\n return GRAPH_CONSTANTS.COLORS.INFO;\n default:\n return GRAPH_CONSTANTS.COLORS.DEFAULT;\n }\n}\n","/**\n * Graph builder - transforms AIReady analysis results into graph data\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport {\n Severity,\n UnifiedReportSchema,\n ToolName,\n normalizeAnalysisResult,\n type Issue,\n} from '@aiready/core';\nimport type { GraphData, FileNode, DependencyEdge } from '../types';\nimport {\n GRAPH_CONSTANTS,\n normalizeLabel,\n extractReferencedPaths,\n getPackageGroup,\n rankSeverity,\n getColorForSeverity,\n} from './utils';\n\n/**\n * Metadata for tracking file-level issue aggregates during graph building.\n */\ninterface FileIssueRecord {\n count: number;\n maxSeverity: Severity | null;\n duplicates: number;\n}\n\n/**\n * GraphBuilder: programmatic builder and report-based builder.\n * @lastUpdated 2026-03-27\n */\nexport class GraphBuilder {\n private readonly rootDir: string;\n private readonly nodesMap: Map<string, FileNode>;\n private readonly edges: DependencyEdge[];\n private readonly edgesSet: Set<string>;\n\n constructor(rootDir = process.cwd()) {\n this.rootDir = rootDir;\n this.nodesMap = new Map();\n this.edges = [];\n this.edgesSet = new Set();\n }\n\n /**\n * Add a new node to the graph or update an existing one.\n */\n addNode(file: string, title = '', size = GRAPH_CONSTANTS.DEFAULT_NODE_SIZE): void {\n if (!file) return;\n const id = path.resolve(this.rootDir, file);\n const existingNode = this.nodesMap.get(id);\n\n if (!existingNode) {\n const node: FileNode = {\n id,\n path: id,\n label: normalizeLabel(id, this.rootDir),\n title,\n size: size,\n };\n this.nodesMap.set(id, node);\n } else {\n if (title && (!existingNode.title || !existingNode.title.includes(title))) {\n existingNode.title = (existingNode.title ? existingNode.title + '\\n' : '') + title;\n }\n if (size > (existingNode.size ?? 0)) {\n existingNode.size = size;\n }\n }\n }\n\n /**\n * Add a directed edge between two nodes in the graph.\n */\n addEdge(from: string, to: string, type: string = 'link'): void {\n if (!from || !to) return;\n const source = path.resolve(this.rootDir, from);\n const target = path.resolve(this.rootDir, to);\n if (source === target) return;\n\n const key = `${source}->${target}`;\n if (!this.edgesSet.has(key)) {\n this.edges.push({ source, target, type: type as any });\n this.edgesSet.add(key);\n }\n }\n\n /**\n * Build the final GraphData object from collected nodes and edges.\n */\n build(): GraphData {\n const nodes = Array.from(this.nodesMap.values());\n return {\n nodes,\n edges: [...this.edges],\n clusters: [],\n issues: [],\n metadata: {\n timestamp: new Date().toISOString(),\n totalFiles: nodes.length,\n totalDependencies: this.edges.length,\n analysisTypes: [],\n criticalIssues: 0,\n majorIssues: 0,\n minorIssues: 0,\n infoIssues: 0,\n },\n truncated: {\n nodes: false,\n edges: false,\n },\n };\n }\n\n /**\n * Static helper to build graph from an AIReady report JSON.\n */\n static buildFromReport(report: any, rootDir = process.cwd()): GraphData {\n const validation = UnifiedReportSchema.safeParse(report);\n if (!validation.success) {\n console.warn(\n 'Visualizer: Report does not fully match UnifiedReportSchema, proceeding with best-effort parsing.'\n );\n }\n\n const builder = new GraphBuilder(rootDir);\n const fileIssues = new Map<string, FileIssueRecord>();\n\n const bumpIssue = (file: string, severity?: Severity | null) => {\n if (!file) return;\n const id = path.resolve(rootDir, file);\n if (!fileIssues.has(id)) {\n fileIssues.set(id, { count: 0, maxSeverity: null, duplicates: 0 });\n }\n const record = fileIssues.get(id)!;\n record.count += 1;\n\n if (severity) {\n if (\n !record.maxSeverity ||\n GRAPH_CONSTANTS.SEVERITY_ORDER[severity] > GRAPH_CONSTANTS.SEVERITY_ORDER[record.maxSeverity]\n ) {\n record.maxSeverity = severity;\n }\n }\n };\n\n const getResults = (toolKey: string, legacyKey?: string): any[] => {\n const camelKey = toolKey.replace(/-([a-z])/g, (g) => g[1].toUpperCase());\n const toolData = report[toolKey] ?? report[camelKey] ?? (legacyKey ? report[legacyKey] : undefined);\n if (!toolData) return [];\n if (Array.isArray(toolData)) return toolData;\n return toolData.results ?? toolData.issues ?? [];\n };\n\n // 1. Process Pattern Detect\n this.processPatterns(builder, getResults(ToolName.PatternDetect, 'patterns'), rootDir, bumpIssue);\n\n // 2. Process Duplicates\n this.processDuplicates(builder, report, rootDir, fileIssues);\n\n // 3. Process Context Analyzer\n this.processContext(builder, getResults(ToolName.ContextAnalyzer, 'context'), rootDir, bumpIssue);\n\n // 4. Process Other Tools\n this.processToolResults(builder, ToolName.DocDrift, 'docDrift', report, bumpIssue, 'Doc-Drift Issue');\n this.processToolResults(builder, ToolName.DependencyHealth, 'dependencyHealth', report, bumpIssue, 'Dependency Issue');\n this.processToolResults(builder, ToolName.ContractEnforcement, 'contractEnforcement', report, bumpIssue, 'Contract Gap');\n\n return this.finalizeGraph(builder, fileIssues, report);\n }\n\n private static processPatterns(\n builder: GraphBuilder,\n results: any[],\n rootDir: string,\n bumpIssue: (file: string, sev?: Severity | null) => void\n ): void {\n const basenameMap = new Map<string, Set<string>>();\n results.forEach((p: any) => {\n const fileName = p.fileName ?? p.file;\n if (fileName) {\n const base = path.basename(fileName);\n if (!basenameMap.has(base)) basenameMap.set(base, new Set());\n basenameMap.get(base)!.add(fileName);\n }\n });\n\n results.forEach((entry: any) => {\n const normalized = normalizeAnalysisResult(entry);\n const file = normalized.fileName;\n if (!file) return;\n\n builder.addNode(\n file,\n `Issues: ${normalized.issues.length}`,\n normalized.metrics.tokenCost || GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE\n );\n\n // We use entry.issues directly if available to detect unspecified severity\n const rawIssues = Array.isArray(entry.issues) ? entry.issues : [];\n if (rawIssues.length > 0) {\n rawIssues.forEach((issue: any) => {\n bumpIssue(file, rankSeverity(issue.severity));\n });\n } else {\n normalized.issues.forEach((issue: Issue) => {\n bumpIssue(file, issue.severity);\n });\n }\n\n normalized.issues.forEach((issue: Issue) => {\n const refs = extractReferencedPaths(issue.message);\n refs.forEach((ref) => {\n const target = path.isAbsolute(ref) ? ref : path.resolve(path.dirname(file), ref);\n builder.addNode(target, 'Referenced file', GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);\n builder.addEdge(file, target, 'reference');\n });\n\n const percMatch = (issue.message.match(/(\\d+)%/) || [])[1];\n const perc = percMatch ? parseInt(percMatch, 10) : null;\n const wantFuzzy =\n issue.type === 'duplicate-pattern' ||\n /similar/i.test(issue.message) ||\n (perc !== null && perc >= GRAPH_CONSTANTS.FUZZY_MATCH_THRESHOLD);\n\n if (wantFuzzy) {\n const fileGroup = getPackageGroup(file);\n for (const [base, pathsSet] of basenameMap.entries()) {\n if (!issue.message.includes(base) || base === path.basename(file)) continue;\n for (const target of pathsSet) {\n const targetGroup = getPackageGroup(target);\n if (fileGroup !== targetGroup && !(perc !== null && perc >= GRAPH_CONSTANTS.FUZZY_MATCH_HIGH_THRESHOLD)) continue;\n builder.addNode(target, 'Fuzzy match', GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);\n builder.addEdge(file, target, 'similarity');\n }\n }\n }\n });\n });\n }\n\n private static processDuplicates(\n builder: GraphBuilder,\n report: any,\n rootDir: string,\n fileIssues: Map<string, FileIssueRecord>\n ): void {\n const patternData = report[ToolName.PatternDetect] || report.patternDetect || report.patterns || {};\n const duplicates =\n (Array.isArray(patternData.duplicates) ? patternData.duplicates : null) ||\n (patternData.summary && Array.isArray(patternData.summary.duplicates) ? patternData.summary.duplicates : null) ||\n (Array.isArray(report.duplicates) ? report.duplicates : []);\n\n duplicates.forEach((dup: any) => {\n builder.addNode(dup.file1, 'Similarity target', GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);\n builder.addNode(dup.file2, 'Similarity target', GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);\n builder.addEdge(dup.file1, dup.file2, 'similarity');\n\n [dup.file1, dup.file2].forEach((file) => {\n const id = path.resolve(rootDir, file);\n if (!fileIssues.has(id)) {\n fileIssues.set(id, { count: 0, maxSeverity: null, duplicates: 0 });\n }\n fileIssues.get(id)!.duplicates += 1;\n });\n });\n }\n\n private static processContext(\n builder: GraphBuilder,\n results: any[],\n rootDir: string,\n bumpIssue: (file: string, sev?: Severity | null) => void\n ): void {\n results.forEach((ctx: any) => {\n const normalized = normalizeAnalysisResult(ctx);\n const file = normalized.fileName;\n if (!file) return;\n\n builder.addNode(file, `Deps: ${ctx.dependencyCount || 0}`, GRAPH_CONSTANTS.DEFAULT_CONTEXT_SIZE);\n\n normalized.issues.forEach((issue: Issue) => {\n bumpIssue(file, issue.severity);\n });\n\n (ctx.relatedFiles ?? []).forEach((rel: string) => {\n const resolvedRel = path.isAbsolute(rel) ? rel : path.resolve(path.dirname(file), rel);\n const resolvedFile = path.resolve(builder.rootDir, file);\n const resolvedTarget = path.resolve(builder.rootDir, resolvedRel);\n\n const keyA = `${resolvedFile}->${resolvedTarget}`;\n const keyB = `${resolvedTarget}->${resolvedFile}`;\n\n if (builder['edgesSet'].has(keyA) || builder['edgesSet'].has(keyB)) return;\n\n builder.addNode(resolvedRel, 'Related file', GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);\n\n const node = builder['nodesMap'].get(resolvedTarget);\n if (node) {\n node.size = (node.size || 1) + 2;\n }\n builder.addEdge(file, resolvedRel, 'related');\n });\n\n const fileDir = path.dirname(path.resolve(builder.rootDir, file));\n (ctx.dependencyList ?? []).forEach((dep: string) => {\n if (dep.startsWith('.') || dep.startsWith('/')) {\n const possiblePaths = [\n path.resolve(fileDir, dep),\n path.resolve(fileDir, dep + '.ts'),\n path.resolve(fileDir, dep + '.tsx'),\n path.resolve(fileDir, dep + '.js'),\n path.resolve(fileDir, dep, 'index.ts'),\n path.resolve(fileDir, dep, 'index.tsx'),\n ];\n for (const p of possiblePaths) {\n if (fs.existsSync(p)) {\n builder.addNode(p, 'Dependency', GRAPH_CONSTANTS.DEFAULT_DEPENDENCY_SIZE);\n builder.addEdge(file, p, 'dependency');\n break;\n }\n }\n }\n });\n });\n }\n\n private static processToolResults(\n builder: GraphBuilder,\n toolName: ToolName,\n legacyKey: string,\n report: any,\n bumpIssue: (file: string, sev?: Severity | null) => void,\n title: string\n ): void {\n const camelKey = toolName.replace(/-([a-z])/g, (g) => g[1].toUpperCase());\n const toolData = report[toolName] ?? report[camelKey] ?? report[legacyKey];\n if (!toolData) return;\n\n const results = Array.isArray(toolData) ? toolData : toolData.results ?? toolData.issues ?? [];\n results.forEach((item: any) => {\n // Support flat format where item IS the issue (seen in tests and legacy outputs)\n if (!Array.isArray(item.issues) && (item.severity || item.message)) {\n const file = item.fileName ?? item.file ?? item.location?.file;\n if (file) {\n builder.addNode(file, title, GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);\n bumpIssue(file, rankSeverity(item.severity));\n }\n return;\n }\n\n const normalized = normalizeAnalysisResult(item);\n const file = normalized.fileName;\n if (file) {\n builder.addNode(file, title, GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);\n normalized.issues.forEach((issue) => {\n bumpIssue(file, issue.severity);\n });\n }\n });\n }\n\n private static finalizeGraph(builder: GraphBuilder, fileIssues: Map<string, FileIssueRecord>, report: any): GraphData {\n const graph = builder.build();\n\n let criticalIssues = 0;\n let majorIssues = 0;\n let minorIssues = 0;\n let infoIssues = 0;\n\n graph.nodes.forEach((node) => {\n const record = fileIssues.get(node.id);\n if (record) {\n node.duplicates = record.duplicates || 0;\n node.color = getColorForSeverity(record.maxSeverity);\n node.group = getPackageGroup(node.id);\n\n if (record.maxSeverity === Severity.Critical) criticalIssues += record.count;\n else if (record.maxSeverity === Severity.Major) majorIssues += record.count;\n else if (record.maxSeverity === Severity.Minor) minorIssues += record.count;\n else if (record.maxSeverity === Severity.Info) infoIssues += record.count;\n } else {\n node.color = getColorForSeverity(null);\n node.group = getPackageGroup(node.id);\n node.duplicates = 0;\n }\n });\n\n graph.metadata = {\n ...graph.metadata,\n criticalIssues,\n majorIssues,\n minorIssues,\n infoIssues,\n tokenBudget: report.scoring?.tokenBudget,\n };\n\n return graph;\n }\n}\n\n/**\n * Create a small sample graph for demonstration or testing purposes.\n */\nexport function createSampleGraph(): GraphData {\n const builder = new GraphBuilder(process.cwd());\n builder.addNode('src/components/Button.tsx', 'Button', 15);\n builder.addNode('src/utils/helpers.ts', 'helpers', 12);\n builder.addNode('src/services/api.ts', 'api', 18);\n builder.addEdge('src/components/Button.tsx', 'src/utils/helpers.ts', 'dependency');\n builder.addEdge('src/utils/helpers.ts', 'src/services/api.ts', 'dependency');\n return builder.build();\n}\n","#!/usr/bin/env node\n\n/**\n * CLI for AIReady Visualizer\n *\n * Usage:\n * aiready visualise # Start dev server (default)\n */\n\nimport { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { GraphBuilder, createSampleGraph } from '../graph/builder';\nimport { generateHTML } from '@aiready/core';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst WEB_PORT = 8000;\n\nconst program = new Command();\n\nprogram\n .name('aiready-visualize')\n .description(\n 'Generate interactive visualizations from AIReady analysis results'\n )\n .version('0.1.0')\n .option('-d, --dev', 'Start interactive web application (default)', true)\n .option('-o, --output <file>', 'Output HTML file for static generation')\n .passThroughOptions();\n\n/**\n * Start the interactive web dev server\n */\nfunction startDevServer(rootDir: string): void {\n const webDir = resolve(__dirname, '../web');\n\n console.log('🎯 AIReady Visualizer');\n console.log('🚀 Starting interactive web application...');\n console.log();\n console.log(`📁 Project root: ${rootDir}`);\n console.log(`🌐 Web server: http://localhost:${WEB_PORT}`);\n console.log();\n console.log('💡 The web app requires report data to visualize.');\n console.log(' Run \"pnpm aiready scan .\" then copy the report to:');\n console.log(` web/public/report-data.json`);\n console.log();\n console.log('Press Ctrl+C to stop the server.');\n console.log();\n\n // Start vite dev server\n const vite = spawn('pnpm', ['dev'], {\n cwd: webDir,\n stdio: 'inherit',\n shell: true,\n env: { ...process.env, FORCE_COLOR: '1' },\n });\n\n vite.on('error', (err) => {\n console.error('❌ Failed to start dev server:', err.message);\n process.exit(1);\n });\n}\n\nprogram\n .command('sample')\n .description('Generate a sample visualization for testing')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .option('--open', 'Open in browser')\n .action(async (options) => {\n const { writeFileSync } = await import('fs');\n const { exec } = await import('child_process');\n\n console.log('Generating sample visualization...');\n const graph = createSampleGraph();\n\n console.log(\n `\\nSample graph created with ${graph.nodes.length} nodes and ${graph.edges.length} edges`\n );\n\n const html = generateHTML(graph);\n const outputPath = resolve(options.output);\n writeFileSync(outputPath, html);\n\n console.log(`✅ HTML saved to: ${outputPath}`);\n\n if (options.open) {\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${opener} \"${outputPath}\"`);\n }\n });\n\nprogram\n .command('generate')\n .description('Generate visualization from analysis results')\n .argument('<input>', 'Input JSON file with analysis results')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .option('--open', 'Open in browser')\n .action(async (input, options) => {\n const { readFileSync, writeFileSync } = await import('fs');\n const { exec } = await import('child_process');\n\n console.log(`Reading analysis results from: ${input}`);\n const report = JSON.parse(readFileSync(input, 'utf-8'));\n\n const rootDir = process.cwd();\n const graph = GraphBuilder.buildFromReport(report, rootDir);\n\n console.log(\n `Graph built: ${graph.nodes.length} nodes, ${graph.edges.length} edges`\n );\n\n const html = generateHTML(graph);\n const outputPath = resolve(options.output);\n writeFileSync(outputPath, html);\n\n console.log(`✅ HTML saved to: ${outputPath}`);\n\n if (options.open) {\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${opener} \"${outputPath}\"`);\n }\n });\n\n// Handle default case: start dev server when no arguments provided\nconst args = process.argv.slice(2);\nif (\n args.length === 0 ||\n (args.length === 1 && (args[0] === '--dev' || args[0] === '-d'))\n) {\n startDevServer(process.cwd());\n} else {\n program.parse();\n}\n"]}
1
+ {"version":3,"sources":["../src/graph/utils.ts","../src/graph/builder.ts","../src/cli/index.ts"],"names":["path","file","Severity","__filename","__dirname"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Graph builder utilities\n */\n\nimport path from 'path';\nimport { Severity, normalizeSeverity } from '@aiready/core';\n\n/**\n * Constants for graph building\n */\nexport const GRAPH_CONSTANTS = {\n DEFAULT_NODE_SIZE: 1,\n DEFAULT_REFERENCE_SIZE: 5,\n DEFAULT_DEPENDENCY_SIZE: 2,\n DEFAULT_CONTEXT_SIZE: 10,\n FUZZY_MATCH_THRESHOLD: 50,\n FUZZY_MATCH_HIGH_THRESHOLD: 80,\n COLORS: {\n CRITICAL: '#ff4d4f',\n MAJOR: '#ff9900',\n MINOR: '#ffd666',\n INFO: '#91d5ff',\n DEFAULT: '#97c2fc',\n },\n SEVERITY_ORDER: {\n [Severity.Critical]: 3,\n [Severity.Major]: 2,\n [Severity.Minor]: 1,\n [Severity.Info]: 0,\n } as Record<Severity, number>,\n};\n\n/**\n * Normalizes a file path relative to a root directory for labels.\n */\nexport function normalizeLabel(filePath: string, rootDir: string): string {\n try {\n return path.relative(rootDir, filePath);\n } catch {\n return filePath;\n }\n}\n\n/**\n * Extracts absolute and relative file paths from a message string.\n */\nexport function extractReferencedPaths(message: string): string[] {\n if (!message || typeof message !== 'string') return [];\n const reAbs = /\\/(?:[\\w\\-.]+\\/)+[\\w\\-.]+\\.(?:ts|tsx|js|jsx|py|java|go)/g;\n const reRel =\n /(?:\\.\\/|\\.\\.\\/)(?:[\\w\\-.]+\\/)+[\\w\\-.]+\\.(?:ts|tsx|js|jsx|py|java|go)/g;\n const abs = (message.match(reAbs) ?? []) as string[];\n const rel = (message.match(reRel) ?? []) as string[];\n return abs.concat(rel);\n}\n\n/**\n * Determines the package or module group for a given file path.\n */\nexport function getPackageGroup(\n fp: string | null | undefined\n): string | undefined {\n if (!fp) return undefined;\n const parts = fp.split(path.sep);\n const pkgIdx = parts.indexOf('packages');\n if (pkgIdx >= 0 && parts.length > pkgIdx + 1)\n return `packages/${parts[pkgIdx + 1]}`;\n const landingIdx = parts.indexOf('landing');\n if (landingIdx >= 0) return 'landing';\n const scriptsIdx = parts.indexOf('scripts');\n if (scriptsIdx >= 0) return 'scripts';\n return parts.length > 1 ? parts[1] : parts[0];\n}\n\n/**\n * Ranks severity from a string or null.\n */\nexport function rankSeverity(s: string | null | undefined): Severity | null {\n return normalizeSeverity(s || undefined);\n}\n\n/**\n * Returns a color string for a given severity.\n */\nexport function getColorForSeverity(sev: Severity | null): string {\n switch (sev) {\n case Severity.Critical:\n return GRAPH_CONSTANTS.COLORS.CRITICAL;\n case Severity.Major:\n return GRAPH_CONSTANTS.COLORS.MAJOR;\n case Severity.Minor:\n return GRAPH_CONSTANTS.COLORS.MINOR;\n case Severity.Info:\n return GRAPH_CONSTANTS.COLORS.INFO;\n default:\n return GRAPH_CONSTANTS.COLORS.DEFAULT;\n }\n}\n","/**\n * Graph builder - transforms AIReady analysis results into graph data\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport {\n Severity,\n UnifiedReportSchema,\n ToolName,\n normalizeAnalysisResult,\n type Issue,\n} from '@aiready/core';\nimport type { GraphData, FileNode, DependencyEdge } from '../types';\nimport {\n GRAPH_CONSTANTS,\n normalizeLabel,\n extractReferencedPaths,\n getPackageGroup,\n rankSeverity,\n getColorForSeverity,\n} from './utils';\n\n/**\n * Metadata for tracking file-level issue aggregates during graph building.\n */\ninterface FileIssueRecord {\n count: number;\n maxSeverity: Severity | null;\n duplicates: number;\n}\n\n/**\n * GraphBuilder: programmatic builder and report-based builder.\n * @lastUpdated 2026-03-27\n */\nexport class GraphBuilder {\n private readonly rootDir: string;\n private readonly nodesMap: Map<string, FileNode>;\n private readonly edges: DependencyEdge[];\n private readonly edgesSet: Set<string>;\n\n constructor(rootDir = process.cwd()) {\n this.rootDir = rootDir;\n this.nodesMap = new Map();\n this.edges = [];\n this.edgesSet = new Set();\n }\n\n /**\n * Add a new node to the graph or update an existing one.\n */\n addNode(\n file: string,\n title = '',\n size = GRAPH_CONSTANTS.DEFAULT_NODE_SIZE\n ): void {\n if (!file) return;\n const id = path.resolve(this.rootDir, file);\n const existingNode = this.nodesMap.get(id);\n\n if (!existingNode) {\n const node: FileNode = {\n id,\n path: id,\n label: normalizeLabel(id, this.rootDir),\n title,\n size: size,\n };\n this.nodesMap.set(id, node);\n } else {\n if (\n title &&\n (!existingNode.title || !existingNode.title.includes(title))\n ) {\n existingNode.title =\n (existingNode.title ? existingNode.title + '\\n' : '') + title;\n }\n if (size > (existingNode.size ?? 0)) {\n existingNode.size = size;\n }\n }\n }\n\n /**\n * Add a directed edge between two nodes in the graph.\n */\n addEdge(from: string, to: string, type: string = 'link'): void {\n if (!from || !to) return;\n const source = path.resolve(this.rootDir, from);\n const target = path.resolve(this.rootDir, to);\n if (source === target) return;\n\n const key = `${source}->${target}`;\n if (!this.edgesSet.has(key)) {\n this.edges.push({\n source,\n target,\n type: type as 'dependency' | 'similar' | 'shared',\n });\n this.edgesSet.add(key);\n }\n }\n\n /**\n * Build the final GraphData object from collected nodes and edges.\n */\n build(): GraphData {\n const nodes = Array.from(this.nodesMap.values());\n return {\n nodes,\n edges: [...this.edges],\n clusters: [],\n issues: [],\n metadata: {\n timestamp: new Date().toISOString(),\n totalFiles: nodes.length,\n totalDependencies: this.edges.length,\n analysisTypes: [],\n criticalIssues: 0,\n majorIssues: 0,\n minorIssues: 0,\n infoIssues: 0,\n },\n truncated: {\n nodes: false,\n edges: false,\n },\n };\n }\n\n /**\n * Static helper to build graph from an AIReady report JSON.\n */\n static buildFromReport(report: any, rootDir = process.cwd()): GraphData {\n const validation = UnifiedReportSchema.safeParse(report);\n if (!validation.success) {\n console.warn(\n 'Visualizer: Report does not fully match UnifiedReportSchema, proceeding with best-effort parsing.'\n );\n }\n\n const builder = new GraphBuilder(rootDir);\n const fileIssues = new Map<string, FileIssueRecord>();\n\n const bumpIssue = (file: string, severity?: Severity | null) => {\n if (!file) return;\n const id = path.resolve(rootDir, file);\n if (!fileIssues.has(id)) {\n fileIssues.set(id, { count: 0, maxSeverity: null, duplicates: 0 });\n }\n const record = fileIssues.get(id)!;\n record.count += 1;\n\n if (severity) {\n if (\n !record.maxSeverity ||\n GRAPH_CONSTANTS.SEVERITY_ORDER[severity] >\n GRAPH_CONSTANTS.SEVERITY_ORDER[record.maxSeverity]\n ) {\n record.maxSeverity = severity;\n }\n }\n };\n\n const getResults = (toolKey: string, legacyKey?: string): any[] => {\n const camelKey = toolKey.replace(/-([a-z])/g, (g) => g[1].toUpperCase());\n const toolData =\n report[toolKey] ??\n report[camelKey] ??\n (legacyKey ? report[legacyKey] : undefined);\n if (!toolData) return [];\n if (Array.isArray(toolData)) return toolData;\n return toolData.results ?? toolData.issues ?? [];\n };\n\n // 1. Process Pattern Detect\n this.processPatterns(\n builder,\n getResults(ToolName.PatternDetect, 'patterns'),\n rootDir,\n bumpIssue\n );\n\n // 2. Process Duplicates\n this.processDuplicates(builder, report, rootDir, fileIssues);\n\n // 3. Process Context Analyzer\n this.processContext(\n builder,\n getResults(ToolName.ContextAnalyzer, 'context'),\n rootDir,\n bumpIssue\n );\n\n // 4. Process Other Tools\n this.processToolResults(\n builder,\n ToolName.DocDrift,\n 'docDrift',\n report,\n bumpIssue,\n 'Doc-Drift Issue'\n );\n this.processToolResults(\n builder,\n ToolName.DependencyHealth,\n 'dependencyHealth',\n report,\n bumpIssue,\n 'Dependency Issue'\n );\n this.processToolResults(\n builder,\n ToolName.ContractEnforcement,\n 'contractEnforcement',\n report,\n bumpIssue,\n 'Contract Gap'\n );\n\n return this.finalizeGraph(builder, fileIssues, report);\n }\n\n private static processPatterns(\n builder: GraphBuilder,\n results: any[],\n rootDir: string,\n bumpIssue: (file: string, sev?: Severity | null) => void\n ): void {\n const basenameMap = new Map<string, Set<string>>();\n results.forEach((p: any) => {\n const fileName = p.fileName ?? p.file;\n if (fileName) {\n const base = path.basename(fileName);\n if (!basenameMap.has(base)) basenameMap.set(base, new Set());\n basenameMap.get(base)!.add(fileName);\n }\n });\n\n results.forEach((entry: any) => {\n const normalized = normalizeAnalysisResult(entry);\n const file = normalized.fileName;\n if (!file) return;\n\n builder.addNode(\n file,\n `Issues: ${normalized.issues.length}`,\n normalized.metrics.tokenCost || GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE\n );\n\n // We use entry.issues directly if available to detect unspecified severity\n const rawIssues = Array.isArray(entry.issues) ? entry.issues : [];\n if (rawIssues.length > 0) {\n rawIssues.forEach((issue: any) => {\n bumpIssue(file, rankSeverity(issue.severity));\n });\n } else {\n normalized.issues.forEach((issue: Issue) => {\n bumpIssue(file, issue.severity);\n });\n }\n\n normalized.issues.forEach((issue: Issue) => {\n const refs = extractReferencedPaths(issue.message);\n refs.forEach((ref) => {\n const target = path.isAbsolute(ref)\n ? ref\n : path.resolve(path.dirname(file), ref);\n builder.addNode(\n target,\n 'Referenced file',\n GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE\n );\n builder.addEdge(file, target, 'reference');\n });\n\n const percMatch = (issue.message.match(/(\\d+)%/) || [])[1];\n const perc = percMatch ? parseInt(percMatch, 10) : null;\n const wantFuzzy =\n issue.type === 'duplicate-pattern' ||\n /similar/i.test(issue.message) ||\n (perc !== null && perc >= GRAPH_CONSTANTS.FUZZY_MATCH_THRESHOLD);\n\n if (wantFuzzy) {\n const fileGroup = getPackageGroup(file);\n for (const [base, pathsSet] of basenameMap.entries()) {\n if (!issue.message.includes(base) || base === path.basename(file))\n continue;\n for (const target of pathsSet) {\n const targetGroup = getPackageGroup(target);\n if (\n fileGroup !== targetGroup &&\n !(\n perc !== null &&\n perc >= GRAPH_CONSTANTS.FUZZY_MATCH_HIGH_THRESHOLD\n )\n )\n continue;\n builder.addNode(\n target,\n 'Fuzzy match',\n GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE\n );\n builder.addEdge(file, target, 'similarity');\n }\n }\n }\n });\n });\n }\n\n private static processDuplicates(\n builder: GraphBuilder,\n report: any,\n rootDir: string,\n fileIssues: Map<string, FileIssueRecord>\n ): void {\n const patternData =\n report[ToolName.PatternDetect] ||\n report.patternDetect ||\n report.patterns ||\n {};\n const duplicates =\n (Array.isArray(patternData.duplicates) ? patternData.duplicates : null) ||\n (patternData.summary && Array.isArray(patternData.summary.duplicates)\n ? patternData.summary.duplicates\n : null) ||\n (Array.isArray(report.duplicates) ? report.duplicates : []);\n\n duplicates.forEach((dup: any) => {\n builder.addNode(\n dup.file1,\n 'Similarity target',\n GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE\n );\n builder.addNode(\n dup.file2,\n 'Similarity target',\n GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE\n );\n builder.addEdge(dup.file1, dup.file2, 'similarity');\n\n [dup.file1, dup.file2].forEach((file) => {\n const id = path.resolve(rootDir, file);\n if (!fileIssues.has(id)) {\n fileIssues.set(id, { count: 0, maxSeverity: null, duplicates: 0 });\n }\n fileIssues.get(id)!.duplicates += 1;\n });\n });\n }\n\n private static processContext(\n builder: GraphBuilder,\n results: any[],\n rootDir: string,\n bumpIssue: (file: string, sev?: Severity | null) => void\n ): void {\n results.forEach((ctx: any) => {\n const normalized = normalizeAnalysisResult(ctx);\n const file = normalized.fileName;\n if (!file) return;\n\n builder.addNode(\n file,\n `Deps: ${ctx.dependencyCount || 0}`,\n GRAPH_CONSTANTS.DEFAULT_CONTEXT_SIZE\n );\n\n normalized.issues.forEach((issue: Issue) => {\n bumpIssue(file, issue.severity);\n });\n\n (ctx.relatedFiles ?? []).forEach((rel: string) => {\n const resolvedRel = path.isAbsolute(rel)\n ? rel\n : path.resolve(path.dirname(file), rel);\n const resolvedFile = path.resolve(builder.rootDir, file);\n const resolvedTarget = path.resolve(builder.rootDir, resolvedRel);\n\n const keyA = `${resolvedFile}->${resolvedTarget}`;\n const keyB = `${resolvedTarget}->${resolvedFile}`;\n\n if (builder['edgesSet'].has(keyA) || builder['edgesSet'].has(keyB))\n return;\n\n builder.addNode(\n resolvedRel,\n 'Related file',\n GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE\n );\n\n const node = builder['nodesMap'].get(resolvedTarget);\n if (node) {\n node.size = (node.size || 1) + 2;\n }\n builder.addEdge(file, resolvedRel, 'related');\n });\n\n const fileDir = path.dirname(path.resolve(builder.rootDir, file));\n (ctx.dependencyList ?? []).forEach((dep: string) => {\n if (dep.startsWith('.') || dep.startsWith('/')) {\n const possiblePaths = [\n path.resolve(fileDir, dep),\n path.resolve(fileDir, dep + '.ts'),\n path.resolve(fileDir, dep + '.tsx'),\n path.resolve(fileDir, dep + '.js'),\n path.resolve(fileDir, dep, 'index.ts'),\n path.resolve(fileDir, dep, 'index.tsx'),\n ];\n for (const p of possiblePaths) {\n if (fs.existsSync(p)) {\n builder.addNode(\n p,\n 'Dependency',\n GRAPH_CONSTANTS.DEFAULT_DEPENDENCY_SIZE\n );\n builder.addEdge(file, p, 'dependency');\n break;\n }\n }\n }\n });\n });\n }\n\n private static processToolResults(\n builder: GraphBuilder,\n toolName: ToolName,\n legacyKey: string,\n report: any,\n bumpIssue: (file: string, sev?: Severity | null) => void,\n title: string\n ): void {\n const camelKey = toolName.replace(/-([a-z])/g, (g) => g[1].toUpperCase());\n const toolData = report[toolName] ?? report[camelKey] ?? report[legacyKey];\n if (!toolData) return;\n\n const results = Array.isArray(toolData)\n ? toolData\n : (toolData.results ?? toolData.issues ?? []);\n results.forEach((item: any) => {\n // Support flat format where item IS the issue (seen in tests and legacy outputs)\n if (!Array.isArray(item.issues) && (item.severity || item.message)) {\n const file = item.fileName ?? item.file ?? item.location?.file;\n if (file) {\n builder.addNode(file, title, GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);\n bumpIssue(file, rankSeverity(item.severity));\n }\n return;\n }\n\n const normalized = normalizeAnalysisResult(item);\n const file = normalized.fileName;\n if (file) {\n builder.addNode(file, title, GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);\n normalized.issues.forEach((issue) => {\n bumpIssue(file, issue.severity);\n });\n }\n });\n }\n\n private static finalizeGraph(\n builder: GraphBuilder,\n fileIssues: Map<string, FileIssueRecord>,\n report: any\n ): GraphData {\n const graph = builder.build();\n\n let criticalIssues = 0;\n let majorIssues = 0;\n let minorIssues = 0;\n let infoIssues = 0;\n\n graph.nodes.forEach((node) => {\n const record = fileIssues.get(node.id);\n if (record) {\n node.duplicates = record.duplicates || 0;\n node.color = getColorForSeverity(record.maxSeverity);\n node.group = getPackageGroup(node.id);\n\n if (record.maxSeverity === Severity.Critical)\n criticalIssues += record.count;\n else if (record.maxSeverity === Severity.Major)\n majorIssues += record.count;\n else if (record.maxSeverity === Severity.Minor)\n minorIssues += record.count;\n else if (record.maxSeverity === Severity.Info)\n infoIssues += record.count;\n } else {\n node.color = getColorForSeverity(null);\n node.group = getPackageGroup(node.id);\n node.duplicates = 0;\n }\n });\n\n graph.metadata = {\n ...graph.metadata,\n criticalIssues,\n majorIssues,\n minorIssues,\n infoIssues,\n tokenBudget: report.scoring?.tokenBudget,\n };\n\n return graph;\n }\n}\n\n/**\n * Create a small sample graph for demonstration or testing purposes.\n */\nexport function createSampleGraph(): GraphData {\n const builder = new GraphBuilder(process.cwd());\n builder.addNode('src/components/Button.tsx', 'Button', 15);\n builder.addNode('src/utils/helpers.ts', 'helpers', 12);\n builder.addNode('src/services/api.ts', 'api', 18);\n builder.addEdge(\n 'src/components/Button.tsx',\n 'src/utils/helpers.ts',\n 'dependency'\n );\n builder.addEdge('src/utils/helpers.ts', 'src/services/api.ts', 'dependency');\n return builder.build();\n}\n","#!/usr/bin/env node\n\n/**\n * CLI for AIReady Visualizer\n *\n * Usage:\n * aiready visualise # Start dev server (default)\n */\n\nimport { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { GraphBuilder, createSampleGraph } from '../graph/builder';\nimport { generateHTML } from '@aiready/core';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst WEB_PORT = 8000;\n\nconst program = new Command();\n\nprogram\n .name('aiready-visualize')\n .description(\n 'Generate interactive visualizations from AIReady analysis results'\n )\n .version('0.1.0')\n .option('-d, --dev', 'Start interactive web application (default)', true)\n .option('-o, --output <file>', 'Output HTML file for static generation')\n .passThroughOptions();\n\n/**\n * Start the interactive web dev server\n */\nfunction startDevServer(rootDir: string): void {\n const webDir = resolve(__dirname, '../web');\n\n console.log('🎯 AIReady Visualizer');\n console.log('🚀 Starting interactive web application...');\n console.log();\n console.log(`📁 Project root: ${rootDir}`);\n console.log(`🌐 Web server: http://localhost:${WEB_PORT}`);\n console.log();\n console.log('💡 The web app requires report data to visualize.');\n console.log(' Run \"pnpm aiready scan .\" then copy the report to:');\n console.log(` web/public/report-data.json`);\n console.log();\n console.log('Press Ctrl+C to stop the server.');\n console.log();\n\n // Start vite dev server\n const vite = spawn('pnpm', ['dev'], {\n cwd: webDir,\n stdio: 'inherit',\n shell: true,\n env: { ...process.env, FORCE_COLOR: '1' },\n });\n\n vite.on('error', (err) => {\n console.error('❌ Failed to start dev server:', err.message);\n process.exit(1);\n });\n}\n\nprogram\n .command('sample')\n .description('Generate a sample visualization for testing')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .option('--open', 'Open in browser')\n .action(async (options) => {\n const { writeFileSync } = await import('fs');\n const { exec } = await import('child_process');\n\n console.log('Generating sample visualization...');\n const graph = createSampleGraph();\n\n console.log(\n `\\nSample graph created with ${graph.nodes.length} nodes and ${graph.edges.length} edges`\n );\n\n const html = generateHTML(graph);\n const outputPath = resolve(options.output);\n writeFileSync(outputPath, html);\n\n console.log(`✅ HTML saved to: ${outputPath}`);\n\n if (options.open) {\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${opener} \"${outputPath}\"`);\n }\n });\n\nprogram\n .command('generate')\n .description('Generate visualization from analysis results')\n .argument('<input>', 'Input JSON file with analysis results')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .option('--open', 'Open in browser')\n .action(async (input, options) => {\n const { readFileSync, writeFileSync } = await import('fs');\n const { exec } = await import('child_process');\n\n console.log(`Reading analysis results from: ${input}`);\n const report = JSON.parse(readFileSync(input, 'utf-8'));\n\n const rootDir = process.cwd();\n const graph = GraphBuilder.buildFromReport(report, rootDir);\n\n console.log(\n `Graph built: ${graph.nodes.length} nodes, ${graph.edges.length} edges`\n );\n\n const html = generateHTML(graph);\n const outputPath = resolve(options.output);\n writeFileSync(outputPath, html);\n\n console.log(`✅ HTML saved to: ${outputPath}`);\n\n if (options.open) {\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${opener} \"${outputPath}\"`);\n }\n });\n\n// Handle default case: start dev server when no arguments provided\nconst args = process.argv.slice(2);\nif (\n args.length === 0 ||\n (args.length === 1 && (args[0] === '--dev' || args[0] === '-d'))\n) {\n startDevServer(process.cwd());\n} else {\n program.parse();\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import path2 from 'path';
3
- import { Severity, UnifiedReportSchema, ToolName, normalizeAnalysisResult } from '@aiready/core';
3
+ import { Severity, UnifiedReportSchema, ToolName, normalizeAnalysisResult, normalizeSeverity } from '@aiready/core';
4
4
 
5
5
  // src/graph/builder.ts
6
6
  var GRAPH_CONSTANTS = {
@@ -52,13 +52,7 @@ function getPackageGroup(fp) {
52
52
  return parts.length > 1 ? parts[1] : parts[0];
53
53
  }
54
54
  function rankSeverity(s) {
55
- if (!s) return null;
56
- const ss = String(s).toLowerCase();
57
- if (ss.includes("critical")) return Severity.Critical;
58
- if (ss.includes("major")) return Severity.Major;
59
- if (ss.includes("minor")) return Severity.Minor;
60
- if (ss.includes("info")) return Severity.Info;
61
- return null;
55
+ return normalizeSeverity(s || void 0);
62
56
  }
63
57
  function getColorForSeverity(sev) {
64
58
  switch (sev) {
@@ -118,7 +112,11 @@ var GraphBuilder = class _GraphBuilder {
118
112
  if (source === target) return;
119
113
  const key = `${source}->${target}`;
120
114
  if (!this.edgesSet.has(key)) {
121
- this.edges.push({ source, target, type });
115
+ this.edges.push({
116
+ source,
117
+ target,
118
+ type
119
+ });
122
120
  this.edgesSet.add(key);
123
121
  }
124
122
  }
@@ -181,12 +179,43 @@ var GraphBuilder = class _GraphBuilder {
181
179
  if (Array.isArray(toolData)) return toolData;
182
180
  return toolData.results ?? toolData.issues ?? [];
183
181
  };
184
- this.processPatterns(builder, getResults(ToolName.PatternDetect, "patterns"), rootDir, bumpIssue);
182
+ this.processPatterns(
183
+ builder,
184
+ getResults(ToolName.PatternDetect, "patterns"),
185
+ rootDir,
186
+ bumpIssue
187
+ );
185
188
  this.processDuplicates(builder, report, rootDir, fileIssues);
186
- this.processContext(builder, getResults(ToolName.ContextAnalyzer, "context"), rootDir, bumpIssue);
187
- this.processToolResults(builder, ToolName.DocDrift, "docDrift", report, bumpIssue, "Doc-Drift Issue");
188
- this.processToolResults(builder, ToolName.DependencyHealth, "dependencyHealth", report, bumpIssue, "Dependency Issue");
189
- this.processToolResults(builder, ToolName.ContractEnforcement, "contractEnforcement", report, bumpIssue, "Contract Gap");
189
+ this.processContext(
190
+ builder,
191
+ getResults(ToolName.ContextAnalyzer, "context"),
192
+ rootDir,
193
+ bumpIssue
194
+ );
195
+ this.processToolResults(
196
+ builder,
197
+ ToolName.DocDrift,
198
+ "docDrift",
199
+ report,
200
+ bumpIssue,
201
+ "Doc-Drift Issue"
202
+ );
203
+ this.processToolResults(
204
+ builder,
205
+ ToolName.DependencyHealth,
206
+ "dependencyHealth",
207
+ report,
208
+ bumpIssue,
209
+ "Dependency Issue"
210
+ );
211
+ this.processToolResults(
212
+ builder,
213
+ ToolName.ContractEnforcement,
214
+ "contractEnforcement",
215
+ report,
216
+ bumpIssue,
217
+ "Contract Gap"
218
+ );
190
219
  return this.finalizeGraph(builder, fileIssues, report);
191
220
  }
192
221
  static processPatterns(builder, results, rootDir, bumpIssue) {
@@ -222,7 +251,11 @@ var GraphBuilder = class _GraphBuilder {
222
251
  const refs = extractReferencedPaths(issue.message);
223
252
  refs.forEach((ref) => {
224
253
  const target = path2.isAbsolute(ref) ? ref : path2.resolve(path2.dirname(file), ref);
225
- builder.addNode(target, "Referenced file", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
254
+ builder.addNode(
255
+ target,
256
+ "Referenced file",
257
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
258
+ );
226
259
  builder.addEdge(file, target, "reference");
227
260
  });
228
261
  const percMatch = (issue.message.match(/(\d+)%/) || [])[1];
@@ -231,11 +264,17 @@ var GraphBuilder = class _GraphBuilder {
231
264
  if (wantFuzzy) {
232
265
  const fileGroup = getPackageGroup(file);
233
266
  for (const [base, pathsSet] of basenameMap.entries()) {
234
- if (!issue.message.includes(base) || base === path2.basename(file)) continue;
267
+ if (!issue.message.includes(base) || base === path2.basename(file))
268
+ continue;
235
269
  for (const target of pathsSet) {
236
270
  const targetGroup = getPackageGroup(target);
237
- if (fileGroup !== targetGroup && !(perc !== null && perc >= GRAPH_CONSTANTS.FUZZY_MATCH_HIGH_THRESHOLD)) continue;
238
- builder.addNode(target, "Fuzzy match", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
271
+ if (fileGroup !== targetGroup && !(perc !== null && perc >= GRAPH_CONSTANTS.FUZZY_MATCH_HIGH_THRESHOLD))
272
+ continue;
273
+ builder.addNode(
274
+ target,
275
+ "Fuzzy match",
276
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
277
+ );
239
278
  builder.addEdge(file, target, "similarity");
240
279
  }
241
280
  }
@@ -247,8 +286,16 @@ var GraphBuilder = class _GraphBuilder {
247
286
  const patternData = report[ToolName.PatternDetect] || report.patternDetect || report.patterns || {};
248
287
  const duplicates = (Array.isArray(patternData.duplicates) ? patternData.duplicates : null) || (patternData.summary && Array.isArray(patternData.summary.duplicates) ? patternData.summary.duplicates : null) || (Array.isArray(report.duplicates) ? report.duplicates : []);
249
288
  duplicates.forEach((dup) => {
250
- builder.addNode(dup.file1, "Similarity target", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
251
- builder.addNode(dup.file2, "Similarity target", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
289
+ builder.addNode(
290
+ dup.file1,
291
+ "Similarity target",
292
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
293
+ );
294
+ builder.addNode(
295
+ dup.file2,
296
+ "Similarity target",
297
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
298
+ );
252
299
  builder.addEdge(dup.file1, dup.file2, "similarity");
253
300
  [dup.file1, dup.file2].forEach((file) => {
254
301
  const id = path2.resolve(rootDir, file);
@@ -264,7 +311,11 @@ var GraphBuilder = class _GraphBuilder {
264
311
  const normalized = normalizeAnalysisResult(ctx);
265
312
  const file = normalized.fileName;
266
313
  if (!file) return;
267
- builder.addNode(file, `Deps: ${ctx.dependencyCount || 0}`, GRAPH_CONSTANTS.DEFAULT_CONTEXT_SIZE);
314
+ builder.addNode(
315
+ file,
316
+ `Deps: ${ctx.dependencyCount || 0}`,
317
+ GRAPH_CONSTANTS.DEFAULT_CONTEXT_SIZE
318
+ );
268
319
  normalized.issues.forEach((issue) => {
269
320
  bumpIssue(file, issue.severity);
270
321
  });
@@ -274,8 +325,13 @@ var GraphBuilder = class _GraphBuilder {
274
325
  const resolvedTarget = path2.resolve(builder.rootDir, resolvedRel);
275
326
  const keyA = `${resolvedFile}->${resolvedTarget}`;
276
327
  const keyB = `${resolvedTarget}->${resolvedFile}`;
277
- if (builder["edgesSet"].has(keyA) || builder["edgesSet"].has(keyB)) return;
278
- builder.addNode(resolvedRel, "Related file", GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE);
328
+ if (builder["edgesSet"].has(keyA) || builder["edgesSet"].has(keyB))
329
+ return;
330
+ builder.addNode(
331
+ resolvedRel,
332
+ "Related file",
333
+ GRAPH_CONSTANTS.DEFAULT_REFERENCE_SIZE
334
+ );
279
335
  const node = builder["nodesMap"].get(resolvedTarget);
280
336
  if (node) {
281
337
  node.size = (node.size || 1) + 2;
@@ -295,7 +351,11 @@ var GraphBuilder = class _GraphBuilder {
295
351
  ];
296
352
  for (const p of possiblePaths) {
297
353
  if (fs.existsSync(p)) {
298
- builder.addNode(p, "Dependency", GRAPH_CONSTANTS.DEFAULT_DEPENDENCY_SIZE);
354
+ builder.addNode(
355
+ p,
356
+ "Dependency",
357
+ GRAPH_CONSTANTS.DEFAULT_DEPENDENCY_SIZE
358
+ );
299
359
  builder.addEdge(file, p, "dependency");
300
360
  break;
301
361
  }
@@ -340,10 +400,14 @@ var GraphBuilder = class _GraphBuilder {
340
400
  node.duplicates = record.duplicates || 0;
341
401
  node.color = getColorForSeverity(record.maxSeverity);
342
402
  node.group = getPackageGroup(node.id);
343
- if (record.maxSeverity === Severity.Critical) criticalIssues += record.count;
344
- else if (record.maxSeverity === Severity.Major) majorIssues += record.count;
345
- else if (record.maxSeverity === Severity.Minor) minorIssues += record.count;
346
- else if (record.maxSeverity === Severity.Info) infoIssues += record.count;
403
+ if (record.maxSeverity === Severity.Critical)
404
+ criticalIssues += record.count;
405
+ else if (record.maxSeverity === Severity.Major)
406
+ majorIssues += record.count;
407
+ else if (record.maxSeverity === Severity.Minor)
408
+ minorIssues += record.count;
409
+ else if (record.maxSeverity === Severity.Info)
410
+ infoIssues += record.count;
347
411
  } else {
348
412
  node.color = getColorForSeverity(null);
349
413
  node.group = getPackageGroup(node.id);
@@ -366,7 +430,11 @@ function createSampleGraph() {
366
430
  builder.addNode("src/components/Button.tsx", "Button", 15);
367
431
  builder.addNode("src/utils/helpers.ts", "helpers", 12);
368
432
  builder.addNode("src/services/api.ts", "api", 18);
369
- builder.addEdge("src/components/Button.tsx", "src/utils/helpers.ts", "dependency");
433
+ builder.addEdge(
434
+ "src/components/Button.tsx",
435
+ "src/utils/helpers.ts",
436
+ "dependency"
437
+ );
370
438
  builder.addEdge("src/utils/helpers.ts", "src/services/api.ts", "dependency");
371
439
  return builder.build();
372
440
  }