@aiready/cli 0.9.41 → 0.9.45

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
@@ -25,15 +25,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/cli.ts
27
27
  var import_commander = require("commander");
28
- var import_fs5 = require("fs");
29
- var import_path7 = require("path");
28
+ var import_fs6 = require("fs");
29
+ var import_path8 = require("path");
30
30
  var import_url = require("url");
31
31
 
32
32
  // src/commands/scan.ts
33
- var import_chalk2 = __toESM(require("chalk"));
34
- var import_fs2 = require("fs");
35
- var import_path2 = require("path");
36
- var import_core = require("@aiready/core");
33
+ var import_chalk3 = __toESM(require("chalk"));
34
+ var import_fs3 = require("fs");
35
+ var import_path3 = require("path");
36
+ var import_core2 = require("@aiready/core");
37
37
 
38
38
  // src/index.ts
39
39
  var import_pattern_detect = require("@aiready/pattern-detect");
@@ -128,7 +128,8 @@ async function analyzeUnified(options) {
128
128
  const report = await analyzeDocDrift({
129
129
  rootDir: options.rootDir,
130
130
  include: options.include,
131
- exclude: options.exclude
131
+ exclude: options.exclude,
132
+ onProgress: options.onProgress
132
133
  });
133
134
  if (options.progressCallback) {
134
135
  options.progressCallback({ tool: "doc-drift", data: report });
@@ -141,7 +142,8 @@ async function analyzeUnified(options) {
141
142
  const report = await analyzeDeps({
142
143
  rootDir: options.rootDir,
143
144
  include: options.include,
144
- exclude: options.exclude
145
+ exclude: options.exclude,
146
+ onProgress: options.onProgress
145
147
  });
146
148
  if (options.progressCallback) {
147
149
  options.progressCallback({ tool: "deps-health", data: report });
@@ -154,7 +156,8 @@ async function analyzeUnified(options) {
154
156
  const report = await analyzeAiSignalClarity({
155
157
  rootDir: options.rootDir,
156
158
  include: options.include,
157
- exclude: options.exclude
159
+ exclude: options.exclude,
160
+ onProgress: options.onProgress
158
161
  });
159
162
  if (options.progressCallback) {
160
163
  options.progressCallback({ tool: "aiSignalClarity", data: report });
@@ -170,7 +173,8 @@ async function analyzeUnified(options) {
170
173
  const report = await analyzeAgentGrounding({
171
174
  rootDir: options.rootDir,
172
175
  include: options.include,
173
- exclude: options.exclude
176
+ exclude: options.exclude,
177
+ onProgress: options.onProgress
174
178
  });
175
179
  if (options.progressCallback) {
176
180
  options.progressCallback({ tool: "grounding", data: report });
@@ -183,7 +187,8 @@ async function analyzeUnified(options) {
183
187
  const report = await analyzeTestability({
184
188
  rootDir: options.rootDir,
185
189
  include: options.include,
186
- exclude: options.exclude
190
+ exclude: options.exclude,
191
+ onProgress: options.onProgress
187
192
  });
188
193
  if (options.progressCallback) {
189
194
  options.progressCallback({ tool: "testability", data: report });
@@ -196,7 +201,8 @@ async function analyzeUnified(options) {
196
201
  const report = await analyzeChangeAmplification({
197
202
  rootDir: options.rootDir,
198
203
  include: options.include,
199
- exclude: options.exclude
204
+ exclude: options.exclude,
205
+ onProgress: options.onProgress
200
206
  });
201
207
  if (options.progressCallback) {
202
208
  options.progressCallback({ tool: "changeAmplification", data: report });
@@ -332,11 +338,79 @@ function truncateArray(arr, cap = 8) {
332
338
  return shown.join(", ") + (more > 0 ? `, ... (+${more} more)` : "");
333
339
  }
334
340
 
341
+ // src/commands/upload.ts
342
+ var import_fs2 = __toESM(require("fs"));
343
+ var import_path2 = require("path");
344
+ var import_chalk2 = __toESM(require("chalk"));
345
+ var import_core = require("@aiready/core");
346
+ async function uploadAction(file, options) {
347
+ const startTime = Date.now();
348
+ const filePath = (0, import_path2.resolve)(process.cwd(), file);
349
+ const serverUrl = options.server || process.env.AIREADY_SERVER || "https://dev.platform.getaiready.dev";
350
+ const apiKey = options.apiKey || process.env.AIREADY_API_KEY;
351
+ if (!apiKey) {
352
+ console.error(import_chalk2.default.red("\u274C API Key is required for upload."));
353
+ console.log(import_chalk2.default.dim(" Set AIREADY_API_KEY environment variable or use --api-key flag."));
354
+ console.log(import_chalk2.default.dim(" Get an API key from https://getaiready.dev/dashboard"));
355
+ process.exit(1);
356
+ }
357
+ if (!import_fs2.default.existsSync(filePath)) {
358
+ console.error(import_chalk2.default.red(`\u274C File not found: ${filePath}`));
359
+ process.exit(1);
360
+ }
361
+ try {
362
+ console.log(import_chalk2.default.blue(`\u{1F680} Uploading report to ${serverUrl}...`));
363
+ const reportData = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
364
+ const repoId = options.repoId || reportData.repository?.repoId;
365
+ const res = await fetch(`${serverUrl}/api/analysis/upload`, {
366
+ method: "POST",
367
+ headers: {
368
+ "Content-Type": "application/json",
369
+ "Authorization": `Bearer ${apiKey}`
370
+ },
371
+ body: JSON.stringify({
372
+ data: reportData,
373
+ repoId
374
+ // Might be null, server will handle mapping
375
+ })
376
+ });
377
+ const result = await res.json();
378
+ if (!res.ok) {
379
+ console.error(import_chalk2.default.red(`\u274C Upload failed: ${result.error || res.statusText}`));
380
+ if (res.status === 401) {
381
+ console.log(import_chalk2.default.dim(" Hint: Your API key may be invalid or expired."));
382
+ }
383
+ process.exit(1);
384
+ }
385
+ const duration = ((Date.now() - startTime) / 1e3).toFixed(2);
386
+ console.log(import_chalk2.default.green(`
387
+ \u2705 Upload successful! (${duration}s)`));
388
+ console.log(import_chalk2.default.cyan(` View results: ${serverUrl}/dashboard`));
389
+ if (result.analysis) {
390
+ console.log(import_chalk2.default.dim(` Analysis ID: ${result.analysis.id}`));
391
+ console.log(import_chalk2.default.dim(` Score: ${result.analysis.aiScore}/100`));
392
+ }
393
+ } catch (error) {
394
+ (0, import_core.handleCLIError)(error, "Upload");
395
+ }
396
+ }
397
+ var uploadHelpText = `
398
+ EXAMPLES:
399
+ $ aiready upload report.json --api-key ar_...
400
+ $ aiready upload .aiready/latest.json
401
+ $ AIREADY_API_KEY=ar_... aiready upload report.json
402
+
403
+ ENVIRONMENT VARIABLES:
404
+ AIREADY_API_KEY Your platform API key
405
+ AIREADY_SERVER Custom platform URL (default: https://dev.platform.getaiready.dev)
406
+ `;
407
+
335
408
  // src/commands/scan.ts
336
409
  async function scanAction(directory, options) {
337
- console.log(import_chalk2.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
410
+ console.log(import_chalk3.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
338
411
  const startTime = Date.now();
339
- const resolvedDir = (0, import_path2.resolve)(process.cwd(), directory || ".");
412
+ const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory || ".");
413
+ const repoMetadata = (0, import_core2.getRepoMetadata)(resolvedDir);
340
414
  try {
341
415
  const defaults = {
342
416
  tools: [
@@ -379,7 +453,7 @@ async function scanAction(directory, options) {
379
453
  break;
380
454
  default:
381
455
  console.log(
382
- import_chalk2.default.yellow(
456
+ import_chalk3.default.yellow(
383
457
  `
384
458
  \u26A0\uFE0F Unknown profile '${options.profile}'. Using specified tools or defaults.`
385
459
  )
@@ -393,7 +467,7 @@ async function scanAction(directory, options) {
393
467
  if (profileTools) {
394
468
  cliOverrides.tools = profileTools;
395
469
  }
396
- const baseOptions = await (0, import_core.loadMergedConfig)(
470
+ const baseOptions = await (0, import_core2.loadMergedConfig)(
397
471
  resolvedDir,
398
472
  defaults,
399
473
  cliOverrides
@@ -411,22 +485,22 @@ async function scanAction(directory, options) {
411
485
  ...baseOptions
412
486
  };
413
487
  }
414
- console.log(import_chalk2.default.cyan("\n=== AIReady Run Preview ==="));
488
+ console.log(import_chalk3.default.cyan("\n=== AIReady Run Preview ==="));
415
489
  console.log(
416
- import_chalk2.default.white("Tools to run:"),
490
+ import_chalk3.default.white("Tools to run:"),
417
491
  (finalOptions.tools || ["patterns", "context", "consistency"]).join(", ")
418
492
  );
419
- console.log(import_chalk2.default.white("Will use settings from config and defaults."));
420
- console.log(import_chalk2.default.white("\nGeneral settings:"));
493
+ console.log(import_chalk3.default.white("Will use settings from config and defaults."));
494
+ console.log(import_chalk3.default.white("\nGeneral settings:"));
421
495
  if (finalOptions.rootDir)
422
- console.log(` rootDir: ${import_chalk2.default.bold(String(finalOptions.rootDir))}`);
496
+ console.log(` rootDir: ${import_chalk3.default.bold(String(finalOptions.rootDir))}`);
423
497
  if (finalOptions.include)
424
498
  console.log(
425
- ` include: ${import_chalk2.default.bold(truncateArray(finalOptions.include, 6))}`
499
+ ` include: ${import_chalk3.default.bold(truncateArray(finalOptions.include, 6))}`
426
500
  );
427
501
  if (finalOptions.exclude)
428
502
  console.log(
429
- ` exclude: ${import_chalk2.default.bold(truncateArray(finalOptions.exclude, 6))}`
503
+ ` exclude: ${import_chalk3.default.bold(truncateArray(finalOptions.exclude, 6))}`
430
504
  );
431
505
  if (finalOptions["pattern-detect"] || finalOptions.minSimilarity) {
432
506
  const patternDetectConfig = finalOptions["pattern-detect"] || {
@@ -440,40 +514,40 @@ async function scanAction(directory, options) {
440
514
  severity: finalOptions.severity,
441
515
  includeTests: finalOptions.includeTests
442
516
  };
443
- console.log(import_chalk2.default.white("\nPattern-detect settings:"));
517
+ console.log(import_chalk3.default.white("\nPattern-detect settings:"));
444
518
  console.log(
445
- ` minSimilarity: ${import_chalk2.default.bold(patternDetectConfig.minSimilarity ?? "default")}`
519
+ ` minSimilarity: ${import_chalk3.default.bold(patternDetectConfig.minSimilarity ?? "default")}`
446
520
  );
447
521
  console.log(
448
- ` minLines: ${import_chalk2.default.bold(patternDetectConfig.minLines ?? "default")}`
522
+ ` minLines: ${import_chalk3.default.bold(patternDetectConfig.minLines ?? "default")}`
449
523
  );
450
524
  if (patternDetectConfig.approx !== void 0)
451
525
  console.log(
452
- ` approx: ${import_chalk2.default.bold(String(patternDetectConfig.approx))}`
526
+ ` approx: ${import_chalk3.default.bold(String(patternDetectConfig.approx))}`
453
527
  );
454
528
  if (patternDetectConfig.minSharedTokens !== void 0)
455
529
  console.log(
456
- ` minSharedTokens: ${import_chalk2.default.bold(String(patternDetectConfig.minSharedTokens))}`
530
+ ` minSharedTokens: ${import_chalk3.default.bold(String(patternDetectConfig.minSharedTokens))}`
457
531
  );
458
532
  if (patternDetectConfig.maxCandidatesPerBlock !== void 0)
459
533
  console.log(
460
- ` maxCandidatesPerBlock: ${import_chalk2.default.bold(String(patternDetectConfig.maxCandidatesPerBlock))}`
534
+ ` maxCandidatesPerBlock: ${import_chalk3.default.bold(String(patternDetectConfig.maxCandidatesPerBlock))}`
461
535
  );
462
536
  if (patternDetectConfig.batchSize !== void 0)
463
537
  console.log(
464
- ` batchSize: ${import_chalk2.default.bold(String(patternDetectConfig.batchSize))}`
538
+ ` batchSize: ${import_chalk3.default.bold(String(patternDetectConfig.batchSize))}`
465
539
  );
466
540
  if (patternDetectConfig.streamResults !== void 0)
467
541
  console.log(
468
- ` streamResults: ${import_chalk2.default.bold(String(patternDetectConfig.streamResults))}`
542
+ ` streamResults: ${import_chalk3.default.bold(String(patternDetectConfig.streamResults))}`
469
543
  );
470
544
  if (patternDetectConfig.severity !== void 0)
471
545
  console.log(
472
- ` severity: ${import_chalk2.default.bold(String(patternDetectConfig.severity))}`
546
+ ` severity: ${import_chalk3.default.bold(String(patternDetectConfig.severity))}`
473
547
  );
474
548
  if (patternDetectConfig.includeTests !== void 0)
475
549
  console.log(
476
- ` includeTests: ${import_chalk2.default.bold(String(patternDetectConfig.includeTests))}`
550
+ ` includeTests: ${import_chalk3.default.bold(String(patternDetectConfig.includeTests))}`
477
551
  );
478
552
  }
479
553
  if (finalOptions["context-analyzer"] || finalOptions.maxDepth) {
@@ -484,57 +558,57 @@ async function scanAction(directory, options) {
484
558
  maxFragmentation: finalOptions.maxFragmentation,
485
559
  includeNodeModules: finalOptions.includeNodeModules
486
560
  };
487
- console.log(import_chalk2.default.white("\nContext-analyzer settings:"));
488
- console.log(` maxDepth: ${import_chalk2.default.bold(ca.maxDepth ?? "default")}`);
561
+ console.log(import_chalk3.default.white("\nContext-analyzer settings:"));
562
+ console.log(` maxDepth: ${import_chalk3.default.bold(ca.maxDepth ?? "default")}`);
489
563
  console.log(
490
- ` maxContextBudget: ${import_chalk2.default.bold(ca.maxContextBudget ?? "default")}`
564
+ ` maxContextBudget: ${import_chalk3.default.bold(ca.maxContextBudget ?? "default")}`
491
565
  );
492
566
  if (ca.minCohesion !== void 0)
493
- console.log(` minCohesion: ${import_chalk2.default.bold(String(ca.minCohesion))}`);
567
+ console.log(` minCohesion: ${import_chalk3.default.bold(String(ca.minCohesion))}`);
494
568
  if (ca.maxFragmentation !== void 0)
495
569
  console.log(
496
- ` maxFragmentation: ${import_chalk2.default.bold(String(ca.maxFragmentation))}`
570
+ ` maxFragmentation: ${import_chalk3.default.bold(String(ca.maxFragmentation))}`
497
571
  );
498
572
  if (ca.includeNodeModules !== void 0)
499
573
  console.log(
500
- ` includeNodeModules: ${import_chalk2.default.bold(String(ca.includeNodeModules))}`
574
+ ` includeNodeModules: ${import_chalk3.default.bold(String(ca.includeNodeModules))}`
501
575
  );
502
576
  }
503
577
  if (finalOptions.consistency) {
504
578
  const c = finalOptions.consistency;
505
- console.log(import_chalk2.default.white("\nConsistency settings:"));
579
+ console.log(import_chalk3.default.white("\nConsistency settings:"));
506
580
  console.log(
507
- ` checkNaming: ${import_chalk2.default.bold(String(c.checkNaming ?? true))}`
581
+ ` checkNaming: ${import_chalk3.default.bold(String(c.checkNaming ?? true))}`
508
582
  );
509
583
  console.log(
510
- ` checkPatterns: ${import_chalk2.default.bold(String(c.checkPatterns ?? true))}`
584
+ ` checkPatterns: ${import_chalk3.default.bold(String(c.checkPatterns ?? true))}`
511
585
  );
512
586
  console.log(
513
- ` checkArchitecture: ${import_chalk2.default.bold(String(c.checkArchitecture ?? false))}`
587
+ ` checkArchitecture: ${import_chalk3.default.bold(String(c.checkArchitecture ?? false))}`
514
588
  );
515
589
  if (c.minSeverity)
516
- console.log(` minSeverity: ${import_chalk2.default.bold(c.minSeverity)}`);
590
+ console.log(` minSeverity: ${import_chalk3.default.bold(c.minSeverity)}`);
517
591
  if (c.acceptedAbbreviations)
518
592
  console.log(
519
- ` acceptedAbbreviations: ${import_chalk2.default.bold(truncateArray(c.acceptedAbbreviations, 8))}`
593
+ ` acceptedAbbreviations: ${import_chalk3.default.bold(truncateArray(c.acceptedAbbreviations, 8))}`
520
594
  );
521
595
  if (c.shortWords)
522
596
  console.log(
523
- ` shortWords: ${import_chalk2.default.bold(truncateArray(c.shortWords, 8))}`
597
+ ` shortWords: ${import_chalk3.default.bold(truncateArray(c.shortWords, 8))}`
524
598
  );
525
599
  }
526
- console.log(import_chalk2.default.white("\nStarting analysis..."));
600
+ console.log(import_chalk3.default.white("\nStarting analysis..."));
527
601
  const progressCallback = (event) => {
528
- console.log(import_chalk2.default.cyan(`
602
+ console.log(import_chalk3.default.cyan(`
529
603
  --- ${event.tool.toUpperCase()} RESULTS ---`));
530
604
  try {
531
605
  if (event.tool === "patterns") {
532
606
  const pr = event.data;
533
607
  console.log(
534
- ` Duplicate patterns: ${import_chalk2.default.bold(String(pr.duplicates?.length || 0))}`
608
+ ` Duplicate patterns: ${import_chalk3.default.bold(String(pr.duplicates?.length || 0))}`
535
609
  );
536
610
  console.log(
537
- ` Files with pattern issues: ${import_chalk2.default.bold(String(pr.results?.length || 0))}`
611
+ ` Files with pattern issues: ${import_chalk3.default.bold(String(pr.results?.length || 0))}`
538
612
  );
539
613
  if (pr.duplicates && pr.duplicates.length > 0) {
540
614
  pr.duplicates.slice(0, 5).forEach((d, i) => {
@@ -556,12 +630,12 @@ async function scanAction(directory, options) {
556
630
  }
557
631
  if (pr.groups && pr.groups.length >= 0) {
558
632
  console.log(
559
- ` \u2705 Grouped ${import_chalk2.default.bold(String(pr.duplicates?.length || 0))} duplicates into ${import_chalk2.default.bold(String(pr.groups.length))} file pairs`
633
+ ` \u2705 Grouped ${import_chalk3.default.bold(String(pr.duplicates?.length || 0))} duplicates into ${import_chalk3.default.bold(String(pr.groups.length))} file pairs`
560
634
  );
561
635
  }
562
636
  if (pr.clusters && pr.clusters.length >= 0) {
563
637
  console.log(
564
- ` \u2705 Created ${import_chalk2.default.bold(String(pr.clusters.length))} refactor clusters`
638
+ ` \u2705 Created ${import_chalk3.default.bold(String(pr.clusters.length))} refactor clusters`
565
639
  );
566
640
  pr.clusters.slice(0, 3).forEach((cl, idx) => {
567
641
  const files = (cl.files || []).map((f) => f.path.split("/").pop()).join(", ");
@@ -573,7 +647,7 @@ async function scanAction(directory, options) {
573
647
  } else if (event.tool === "context") {
574
648
  const cr = event.data;
575
649
  console.log(
576
- ` Context issues found: ${import_chalk2.default.bold(String(cr.length || 0))}`
650
+ ` Context issues found: ${import_chalk3.default.bold(String(cr.length || 0))}`
577
651
  );
578
652
  cr.slice(0, 5).forEach((c, i) => {
579
653
  const msg = c.message ? ` - ${c.message}` : "";
@@ -584,7 +658,7 @@ async function scanAction(directory, options) {
584
658
  } else if (event.tool === "consistency") {
585
659
  const rep = event.data;
586
660
  console.log(
587
- ` Consistency totalIssues: ${import_chalk2.default.bold(String(rep.summary?.totalIssues || 0))}`
661
+ ` Consistency totalIssues: ${import_chalk3.default.bold(String(rep.summary?.totalIssues || 0))}`
588
662
  );
589
663
  if (rep.results && rep.results.length > 0) {
590
664
  const fileMap = /* @__PURE__ */ new Map();
@@ -619,7 +693,7 @@ async function scanAction(directory, options) {
619
693
  const remaining = files.length - topFiles.length;
620
694
  if (remaining > 0) {
621
695
  console.log(
622
- import_chalk2.default.dim(
696
+ import_chalk3.default.dim(
623
697
  ` ... and ${remaining} more files with issues (use --output json for full details)`
624
698
  )
625
699
  );
@@ -628,37 +702,37 @@ async function scanAction(directory, options) {
628
702
  } else if (event.tool === "doc-drift") {
629
703
  const dr = event.data;
630
704
  console.log(
631
- ` Issues found: ${import_chalk2.default.bold(String(dr.issues?.length || 0))}`
705
+ ` Issues found: ${import_chalk3.default.bold(String(dr.issues?.length || 0))}`
632
706
  );
633
707
  if (dr.rawData) {
634
708
  console.log(
635
- ` Signature Mismatches: ${import_chalk2.default.bold(dr.rawData.outdatedComments || 0)}`
709
+ ` Signature Mismatches: ${import_chalk3.default.bold(dr.rawData.outdatedComments || 0)}`
636
710
  );
637
711
  console.log(
638
- ` Undocumented Complexity: ${import_chalk2.default.bold(dr.rawData.undocumentedComplexity || 0)}`
712
+ ` Undocumented Complexity: ${import_chalk3.default.bold(dr.rawData.undocumentedComplexity || 0)}`
639
713
  );
640
714
  }
641
715
  } else if (event.tool === "deps-health") {
642
716
  const dr = event.data;
643
717
  console.log(
644
- ` Packages Analyzed: ${import_chalk2.default.bold(String(dr.summary?.packagesAnalyzed || 0))}`
718
+ ` Packages Analyzed: ${import_chalk3.default.bold(String(dr.summary?.packagesAnalyzed || 0))}`
645
719
  );
646
720
  if (dr.rawData) {
647
721
  console.log(
648
- ` Deprecated Packages: ${import_chalk2.default.bold(dr.rawData.deprecatedPackages || 0)}`
722
+ ` Deprecated Packages: ${import_chalk3.default.bold(dr.rawData.deprecatedPackages || 0)}`
649
723
  );
650
724
  console.log(
651
- ` AI Cutoff Skew Score: ${import_chalk2.default.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`
725
+ ` AI Cutoff Skew Score: ${import_chalk3.default.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`
652
726
  );
653
727
  }
654
728
  } else if (event.tool === "change-amplification" || event.tool === "changeAmplification") {
655
729
  const dr = event.data;
656
730
  console.log(
657
- ` Coupling issues: ${import_chalk2.default.bold(String(dr.issues?.length || 0))}`
731
+ ` Coupling issues: ${import_chalk3.default.bold(String(dr.issues?.length || 0))}`
658
732
  );
659
733
  if (dr.summary) {
660
734
  console.log(
661
- ` Complexity Score: ${import_chalk2.default.bold(dr.summary.score || 0)}/100`
735
+ ` Complexity Score: ${import_chalk3.default.bold(dr.summary.score || 0)}/100`
662
736
  );
663
737
  }
664
738
  }
@@ -669,38 +743,46 @@ async function scanAction(directory, options) {
669
743
  const results = await analyzeUnified({
670
744
  ...finalOptions,
671
745
  progressCallback,
746
+ onProgress: (processed, total, message) => {
747
+ process.stdout.write(
748
+ `\r\x1B[K [${processed}/${total}] ${message}...`
749
+ );
750
+ if (processed === total) {
751
+ process.stdout.write("\n");
752
+ }
753
+ },
672
754
  suppressToolConfig: true
673
755
  });
674
- console.log(import_chalk2.default.cyan("\n=== AIReady Run Summary ==="));
756
+ console.log(import_chalk3.default.cyan("\n=== AIReady Run Summary ==="));
675
757
  console.log(
676
- import_chalk2.default.white("Tools run:"),
758
+ import_chalk3.default.white("Tools run:"),
677
759
  (finalOptions.tools || ["patterns", "context", "consistency"]).join(", ")
678
760
  );
679
- console.log(import_chalk2.default.cyan("\nResults summary:"));
761
+ console.log(import_chalk3.default.cyan("\nResults summary:"));
680
762
  console.log(
681
- ` Total issues (all tools): ${import_chalk2.default.bold(String(results.summary.totalIssues || 0))}`
763
+ ` Total issues (all tools): ${import_chalk3.default.bold(String(results.summary.totalIssues || 0))}`
682
764
  );
683
765
  if (results.duplicates)
684
766
  console.log(
685
- ` Duplicate patterns found: ${import_chalk2.default.bold(String(results.duplicates.length || 0))}`
767
+ ` Duplicate patterns found: ${import_chalk3.default.bold(String(results.duplicates.length || 0))}`
686
768
  );
687
769
  if (results.patterns)
688
770
  console.log(
689
- ` Pattern files with issues: ${import_chalk2.default.bold(String(results.patterns.length || 0))}`
771
+ ` Pattern files with issues: ${import_chalk3.default.bold(String(results.patterns.length || 0))}`
690
772
  );
691
773
  if (results.context)
692
774
  console.log(
693
- ` Context issues: ${import_chalk2.default.bold(String(results.context.length || 0))}`
775
+ ` Context issues: ${import_chalk3.default.bold(String(results.context.length || 0))}`
694
776
  );
695
777
  console.log(
696
- ` Consistency issues: ${import_chalk2.default.bold(String(results.consistency?.summary?.totalIssues || 0))}`
778
+ ` Consistency issues: ${import_chalk3.default.bold(String(results.consistency?.summary?.totalIssues || 0))}`
697
779
  );
698
780
  if (results.changeAmplification)
699
781
  console.log(
700
- ` Change amplification: ${import_chalk2.default.bold(String(results.changeAmplification.summary?.score || 0))}/100`
782
+ ` Change amplification: ${import_chalk3.default.bold(String(results.changeAmplification.summary?.score || 0))}/100`
701
783
  );
702
- console.log(import_chalk2.default.cyan("===========================\n"));
703
- const elapsedTime = (0, import_core.getElapsedTime)(startTime);
784
+ console.log(import_chalk3.default.cyan("===========================\n"));
785
+ const elapsedTime = (0, import_core2.getElapsedTime)(startTime);
704
786
  void elapsedTime;
705
787
  let scoringResult;
706
788
  if (options.score || finalOptions.scoring?.showBreakdown) {
@@ -712,6 +794,16 @@ async function scanAction(directory, options) {
712
794
  results.duplicates,
713
795
  results.patterns?.length || 0
714
796
  );
797
+ const wastedTokens = results.duplicates.reduce((sum, d) => sum + (d.tokenCost || 0), 0);
798
+ patternScore.tokenBudget = (0, import_core2.calculateTokenBudget)({
799
+ totalContextTokens: wastedTokens * 2,
800
+ // Estimated context
801
+ wastedTokens: {
802
+ duplication: wastedTokens,
803
+ fragmentation: 0,
804
+ chattiness: 0
805
+ }
806
+ });
715
807
  toolScores.set("pattern-detect", patternScore);
716
808
  } catch (err) {
717
809
  void err;
@@ -722,6 +814,14 @@ async function scanAction(directory, options) {
722
814
  try {
723
815
  const ctxSummary = genContextSummary(results.context);
724
816
  const contextScore = calculateContextScore(ctxSummary);
817
+ contextScore.tokenBudget = (0, import_core2.calculateTokenBudget)({
818
+ totalContextTokens: ctxSummary.totalTokens,
819
+ wastedTokens: {
820
+ duplication: 0,
821
+ fragmentation: ctxSummary.totalPotentialSavings || 0,
822
+ chattiness: 0
823
+ }
824
+ });
725
825
  toolScores.set("context-analyzer", contextScore);
726
826
  } catch (err) {
727
827
  void err;
@@ -813,19 +913,19 @@ async function scanAction(directory, options) {
813
913
  }))
814
914
  });
815
915
  }
816
- const cliWeights = (0, import_core.parseWeightString)(options.weights);
916
+ const cliWeights = (0, import_core2.parseWeightString)(options.weights);
817
917
  if (toolScores.size > 0) {
818
- scoringResult = (0, import_core.calculateOverallScore)(
918
+ scoringResult = (0, import_core2.calculateOverallScore)(
819
919
  toolScores,
820
920
  finalOptions,
821
921
  cliWeights.size ? cliWeights : void 0
822
922
  );
823
- console.log(import_chalk2.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
824
- console.log(` ${(0, import_core.formatScore)(scoringResult)}`);
923
+ console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
924
+ console.log(` ${(0, import_core2.formatScore)(scoringResult)}`);
825
925
  if (options.compareTo) {
826
926
  try {
827
- const prevReportStr = (0, import_fs2.readFileSync)(
828
- (0, import_path2.resolve)(process.cwd(), options.compareTo),
927
+ const prevReportStr = (0, import_fs3.readFileSync)(
928
+ (0, import_path3.resolve)(process.cwd(), options.compareTo),
829
929
  "utf8"
830
930
  );
831
931
  const prevReport = JSON.parse(prevReportStr);
@@ -836,19 +936,19 @@ async function scanAction(directory, options) {
836
936
  console.log();
837
937
  if (diff > 0) {
838
938
  console.log(
839
- import_chalk2.default.green(
939
+ import_chalk3.default.green(
840
940
  ` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
841
941
  )
842
942
  );
843
943
  } else if (diff < 0) {
844
944
  console.log(
845
- import_chalk2.default.red(
945
+ import_chalk3.default.red(
846
946
  ` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
847
947
  )
848
948
  );
849
949
  } else {
850
950
  console.log(
851
- import_chalk2.default.blue(
951
+ import_chalk3.default.blue(
852
952
  ` \u2796 Trend: No change compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
853
953
  )
854
954
  );
@@ -859,7 +959,7 @@ async function scanAction(directory, options) {
859
959
  };
860
960
  } else {
861
961
  console.log(
862
- import_chalk2.default.yellow(
962
+ import_chalk3.default.yellow(
863
963
  `
864
964
  \u26A0\uFE0F Previous report at ${options.compareTo} does not contain an overall score.`
865
965
  )
@@ -868,27 +968,61 @@ async function scanAction(directory, options) {
868
968
  } catch (e) {
869
969
  void e;
870
970
  console.log(
871
- import_chalk2.default.yellow(
971
+ import_chalk3.default.yellow(
872
972
  `
873
973
  \u26A0\uFE0F Could not read or parse previous report at ${options.compareTo}.`
874
974
  )
875
975
  );
876
976
  }
877
977
  }
978
+ const totalWastedDuplication = Array.from(toolScores.values()).reduce((sum, s) => sum + (s.tokenBudget?.wastedTokens.bySource.duplication || 0), 0);
979
+ const totalWastedFragmentation = Array.from(toolScores.values()).reduce((sum, s) => sum + (s.tokenBudget?.wastedTokens.bySource.fragmentation || 0), 0);
980
+ const totalContext = Math.max(...Array.from(toolScores.values()).map((s) => s.tokenBudget?.totalContextTokens || 0));
981
+ if (totalContext > 0) {
982
+ const unifiedBudget = (0, import_core2.calculateTokenBudget)({
983
+ totalContextTokens: totalContext,
984
+ wastedTokens: {
985
+ duplication: totalWastedDuplication,
986
+ fragmentation: totalWastedFragmentation,
987
+ chattiness: 0
988
+ }
989
+ });
990
+ const targetModel = options.model || "claude-4.6";
991
+ const modelPreset = (0, import_core2.getModelPreset)(targetModel);
992
+ const costEstimate = (0, import_core2.estimateCostFromBudget)(unifiedBudget, modelPreset);
993
+ const barWidth = 20;
994
+ const filled = Math.round(unifiedBudget.efficiencyRatio * barWidth);
995
+ const bar = import_chalk3.default.green("\u2588".repeat(filled)) + import_chalk3.default.dim("\u2591".repeat(barWidth - filled));
996
+ console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Token Budget Analysis (v0.13)"));
997
+ console.log(` Efficiency: [${bar}] ${(unifiedBudget.efficiencyRatio * 100).toFixed(0)}%`);
998
+ console.log(` Total Context: ${import_chalk3.default.bold(unifiedBudget.totalContextTokens.toLocaleString())} tokens`);
999
+ console.log(` Wasted Tokens: ${import_chalk3.default.red(unifiedBudget.wastedTokens.total.toLocaleString())} (${(unifiedBudget.wastedTokens.total / unifiedBudget.totalContextTokens * 100).toFixed(1)}%)`);
1000
+ console.log(` Waste Breakdown:`);
1001
+ console.log(` \u2022 Duplication: ${unifiedBudget.wastedTokens.bySource.duplication.toLocaleString()} tokens`);
1002
+ console.log(` \u2022 Fragmentation: ${unifiedBudget.wastedTokens.bySource.fragmentation.toLocaleString()} tokens`);
1003
+ console.log(` Potential Savings: ${import_chalk3.default.green(unifiedBudget.potentialRetrievableTokens.toLocaleString())} tokens retrievable`);
1004
+ console.log(`
1005
+ Est. Monthly Cost (${modelPreset.name}): ${import_chalk3.default.bold("$" + costEstimate.total)} [range: $${costEstimate.range[0]}-$${costEstimate.range[1]}]`);
1006
+ scoringResult.tokenBudget = unifiedBudget;
1007
+ scoringResult.costEstimate = {
1008
+ model: modelPreset.name,
1009
+ ...costEstimate
1010
+ };
1011
+ }
878
1012
  if (scoringResult.breakdown && scoringResult.breakdown.length > 0) {
879
- console.log(import_chalk2.default.bold("\nTool breakdown:"));
1013
+ console.log(import_chalk3.default.bold("\nTool breakdown:"));
880
1014
  scoringResult.breakdown.forEach((tool) => {
881
- const rating = (0, import_core.getRating)(tool.score);
882
- const rd = (0, import_core.getRatingDisplay)(rating);
1015
+ const rating = (0, import_core2.getRating)(tool.score);
1016
+ const rd = (0, import_core2.getRatingDisplay)(rating);
883
1017
  console.log(
884
1018
  ` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${rd.emoji}`
885
1019
  );
886
1020
  });
887
1021
  console.log();
888
1022
  if (finalOptions.scoring?.showBreakdown) {
889
- console.log(import_chalk2.default.bold("Detailed tool breakdown:"));
1023
+ console.log(import_chalk3.default.bold("Detailed tool breakdown:"));
890
1024
  scoringResult.breakdown.forEach((tool) => {
891
- console.log((0, import_core.formatToolScore)(tool));
1025
+ console.log((0, import_core2.formatToolScore)(tool));
892
1026
  });
893
1027
  console.log();
894
1028
  }
@@ -900,30 +1034,52 @@ async function scanAction(directory, options) {
900
1034
  if (outputFormat === "json") {
901
1035
  const timestamp = getReportTimestamp();
902
1036
  const defaultFilename = `aiready-report-${timestamp}.json`;
903
- const outputPath = (0, import_core.resolveOutputPath)(
1037
+ const outputPath = (0, import_core2.resolveOutputPath)(
904
1038
  userOutputFile,
905
1039
  defaultFilename,
906
1040
  resolvedDir
907
1041
  );
908
- const outputData = { ...results, scoring: scoringResult };
909
- (0, import_core.handleJSONOutput)(
1042
+ const outputData = {
1043
+ ...results,
1044
+ scoring: scoringResult,
1045
+ repository: repoMetadata
1046
+ };
1047
+ (0, import_core2.handleJSONOutput)(
910
1048
  outputData,
911
1049
  outputPath,
912
1050
  `\u2705 Report saved to ${outputPath}`
913
1051
  );
1052
+ if (options.upload) {
1053
+ console.log(import_chalk3.default.blue("\n\u{1F4E4} Automatic upload triggered..."));
1054
+ await uploadAction(outputPath, {
1055
+ apiKey: options.apiKey,
1056
+ server: options.server
1057
+ });
1058
+ }
914
1059
  await warnIfGraphCapExceeded(outputData, resolvedDir);
915
1060
  } else {
916
1061
  const timestamp = getReportTimestamp();
917
1062
  const defaultFilename = `aiready-report-${timestamp}.json`;
918
- const outputPath = (0, import_core.resolveOutputPath)(
1063
+ const outputPath = (0, import_core2.resolveOutputPath)(
919
1064
  userOutputFile,
920
1065
  defaultFilename,
921
1066
  resolvedDir
922
1067
  );
923
- const outputData = { ...results, scoring: scoringResult };
1068
+ const outputData = {
1069
+ ...results,
1070
+ scoring: scoringResult,
1071
+ repository: repoMetadata
1072
+ };
924
1073
  try {
925
- (0, import_fs2.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
926
- console.log(import_chalk2.default.dim(`\u2705 Report auto-persisted to ${outputPath}`));
1074
+ (0, import_fs3.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
1075
+ console.log(import_chalk3.default.dim(`\u2705 Report auto-persisted to ${outputPath}`));
1076
+ if (options.upload) {
1077
+ console.log(import_chalk3.default.blue("\n\u{1F4E4} Automatic upload triggered..."));
1078
+ await uploadAction(outputPath, {
1079
+ apiKey: options.apiKey,
1080
+ server: options.server
1081
+ });
1082
+ }
927
1083
  await warnIfGraphCapExceeded(outputData, resolvedDir);
928
1084
  } catch (err) {
929
1085
  void err;
@@ -1005,37 +1161,37 @@ async function scanAction(directory, options) {
1005
1161
  }
1006
1162
  }
1007
1163
  if (shouldFail) {
1008
- console.log(import_chalk2.default.red("\n\u{1F6AB} PR BLOCKED: AI Readiness Check Failed"));
1009
- console.log(import_chalk2.default.red(` Reason: ${failReason}`));
1010
- console.log(import_chalk2.default.dim("\n Remediation steps:"));
1164
+ console.log(import_chalk3.default.red("\n\u{1F6AB} PR BLOCKED: AI Readiness Check Failed"));
1165
+ console.log(import_chalk3.default.red(` Reason: ${failReason}`));
1166
+ console.log(import_chalk3.default.dim("\n Remediation steps:"));
1011
1167
  console.log(
1012
- import_chalk2.default.dim(" 1. Run `aiready scan` locally to see detailed issues")
1168
+ import_chalk3.default.dim(" 1. Run `aiready scan` locally to see detailed issues")
1013
1169
  );
1014
- console.log(import_chalk2.default.dim(" 2. Fix the critical issues before merging"));
1170
+ console.log(import_chalk3.default.dim(" 2. Fix the critical issues before merging"));
1015
1171
  console.log(
1016
- import_chalk2.default.dim(
1172
+ import_chalk3.default.dim(
1017
1173
  " 3. Consider upgrading to Team plan for historical tracking: https://getaiready.dev/pricing"
1018
1174
  )
1019
1175
  );
1020
1176
  process.exit(1);
1021
1177
  } else {
1022
- console.log(import_chalk2.default.green("\n\u2705 PR PASSED: AI Readiness Check"));
1178
+ console.log(import_chalk3.default.green("\n\u2705 PR PASSED: AI Readiness Check"));
1023
1179
  if (threshold) {
1024
1180
  console.log(
1025
- import_chalk2.default.green(
1181
+ import_chalk3.default.green(
1026
1182
  ` Score: ${scoringResult.overall}/100 (threshold: ${threshold})`
1027
1183
  )
1028
1184
  );
1029
1185
  }
1030
1186
  console.log(
1031
- import_chalk2.default.dim(
1187
+ import_chalk3.default.dim(
1032
1188
  "\n \u{1F4A1} Track historical trends: https://getaiready.dev \u2014 Team plan $99/mo"
1033
1189
  )
1034
1190
  );
1035
1191
  }
1036
1192
  }
1037
1193
  } catch (error) {
1038
- (0, import_core.handleCLIError)(error, "Analysis");
1194
+ (0, import_core2.handleCLIError)(error, "Analysis");
1039
1195
  }
1040
1196
  }
1041
1197
  var scanHelpText = `
@@ -1049,6 +1205,8 @@ EXAMPLES:
1049
1205
  $ aiready scan --ci --threshold 70 # GitHub Actions gatekeeper
1050
1206
  $ aiready scan --ci --fail-on major # Fail on major+ issues
1051
1207
  $ aiready scan --output json --output-file report.json
1208
+ $ aiready scan --upload --api-key ar_... # Automatic platform upload
1209
+ $ aiready scan --upload --server custom-url.com # Upload to custom platform
1052
1210
 
1053
1211
  PROFILES:
1054
1212
  agentic: aiSignalClarity, grounding, testability
@@ -1068,13 +1226,13 @@ CI/CD INTEGRATION (Gatekeeper Mode):
1068
1226
  `;
1069
1227
 
1070
1228
  // src/commands/patterns.ts
1071
- var import_chalk3 = __toESM(require("chalk"));
1072
- var import_path3 = require("path");
1073
- var import_core2 = require("@aiready/core");
1229
+ var import_chalk4 = __toESM(require("chalk"));
1230
+ var import_path4 = require("path");
1231
+ var import_core3 = require("@aiready/core");
1074
1232
  async function patternsAction(directory, options) {
1075
- console.log(import_chalk3.default.blue("\u{1F50D} Analyzing patterns...\n"));
1233
+ console.log(import_chalk4.default.blue("\u{1F50D} Analyzing patterns...\n"));
1076
1234
  const startTime = Date.now();
1077
- const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory || ".");
1235
+ const resolvedDir = (0, import_path4.resolve)(process.cwd(), directory || ".");
1078
1236
  try {
1079
1237
  const useSmartDefaults = !options.fullScan;
1080
1238
  const defaults = {
@@ -1103,14 +1261,14 @@ async function patternsAction(directory, options) {
1103
1261
  if (options.minSharedTokens) {
1104
1262
  cliOptions.minSharedTokens = parseInt(options.minSharedTokens);
1105
1263
  }
1106
- const finalOptions = await (0, import_core2.loadMergedConfig)(
1264
+ const finalOptions = await (0, import_core3.loadMergedConfig)(
1107
1265
  resolvedDir,
1108
1266
  defaults,
1109
1267
  cliOptions
1110
1268
  );
1111
1269
  const { analyzePatterns: analyzePatterns2, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
1112
1270
  const { results, duplicates } = await analyzePatterns2(finalOptions);
1113
- const elapsedTime = (0, import_core2.getElapsedTime)(startTime);
1271
+ const elapsedTime = (0, import_core3.getElapsedTime)(startTime);
1114
1272
  const summary = generateSummary(results);
1115
1273
  let patternScore;
1116
1274
  if (options.score) {
@@ -1124,12 +1282,12 @@ async function patternsAction(directory, options) {
1124
1282
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
1125
1283
  ...patternScore && { scoring: patternScore }
1126
1284
  };
1127
- const outputPath = (0, import_core2.resolveOutputPath)(
1285
+ const outputPath = (0, import_core3.resolveOutputPath)(
1128
1286
  userOutputFile,
1129
1287
  `aiready-report-${getReportTimestamp()}.json`,
1130
1288
  resolvedDir
1131
1289
  );
1132
- (0, import_core2.handleJSONOutput)(
1290
+ (0, import_core3.handleJSONOutput)(
1133
1291
  outputData,
1134
1292
  outputPath,
1135
1293
  `\u2705 Results saved to ${outputPath}`
@@ -1138,38 +1296,38 @@ async function patternsAction(directory, options) {
1138
1296
  const terminalWidth = process.stdout.columns || 80;
1139
1297
  const dividerWidth = Math.min(60, terminalWidth - 2);
1140
1298
  const divider = "\u2501".repeat(dividerWidth);
1141
- console.log(import_chalk3.default.cyan(divider));
1142
- console.log(import_chalk3.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
1143
- console.log(import_chalk3.default.cyan(divider) + "\n");
1299
+ console.log(import_chalk4.default.cyan(divider));
1300
+ console.log(import_chalk4.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
1301
+ console.log(import_chalk4.default.cyan(divider) + "\n");
1144
1302
  console.log(
1145
- import_chalk3.default.white(`\u{1F4C1} Files analyzed: ${import_chalk3.default.bold(results.length)}`)
1303
+ import_chalk4.default.white(`\u{1F4C1} Files analyzed: ${import_chalk4.default.bold(results.length)}`)
1146
1304
  );
1147
1305
  console.log(
1148
- import_chalk3.default.yellow(
1149
- `\u26A0 Duplicate patterns found: ${import_chalk3.default.bold(summary.totalPatterns)}`
1306
+ import_chalk4.default.yellow(
1307
+ `\u26A0 Duplicate patterns found: ${import_chalk4.default.bold(summary.totalPatterns)}`
1150
1308
  )
1151
1309
  );
1152
1310
  console.log(
1153
- import_chalk3.default.red(
1154
- `\u{1F4B0} Token cost (wasted): ${import_chalk3.default.bold(summary.totalTokenCost.toLocaleString())}`
1311
+ import_chalk4.default.red(
1312
+ `\u{1F4B0} Token cost (wasted): ${import_chalk4.default.bold(summary.totalTokenCost.toLocaleString())}`
1155
1313
  )
1156
1314
  );
1157
1315
  console.log(
1158
- import_chalk3.default.gray(`\u23F1 Analysis time: ${import_chalk3.default.bold(elapsedTime + "s")}`)
1316
+ import_chalk4.default.gray(`\u23F1 Analysis time: ${import_chalk4.default.bold(elapsedTime + "s")}`)
1159
1317
  );
1160
1318
  const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
1161
1319
  if (sortedTypes.length > 0) {
1162
- console.log(import_chalk3.default.cyan("\n" + divider));
1163
- console.log(import_chalk3.default.bold.white(" PATTERNS BY TYPE"));
1164
- console.log(import_chalk3.default.cyan(divider) + "\n");
1320
+ console.log(import_chalk4.default.cyan("\n" + divider));
1321
+ console.log(import_chalk4.default.bold.white(" PATTERNS BY TYPE"));
1322
+ console.log(import_chalk4.default.cyan(divider) + "\n");
1165
1323
  sortedTypes.forEach(([type, count]) => {
1166
- console.log(` ${import_chalk3.default.white(type.padEnd(15))} ${import_chalk3.default.bold(count)}`);
1324
+ console.log(` ${import_chalk4.default.white(type.padEnd(15))} ${import_chalk4.default.bold(count)}`);
1167
1325
  });
1168
1326
  }
1169
1327
  if (summary.totalPatterns > 0 && duplicates.length > 0) {
1170
- console.log(import_chalk3.default.cyan("\n" + divider));
1171
- console.log(import_chalk3.default.bold.white(" TOP DUPLICATE PATTERNS"));
1172
- console.log(import_chalk3.default.cyan(divider) + "\n");
1328
+ console.log(import_chalk4.default.cyan("\n" + divider));
1329
+ console.log(import_chalk4.default.bold.white(" TOP DUPLICATE PATTERNS"));
1330
+ console.log(import_chalk4.default.cyan(divider) + "\n");
1173
1331
  const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
1174
1332
  topDuplicates.forEach((dup) => {
1175
1333
  const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
@@ -1177,31 +1335,31 @@ async function patternsAction(directory, options) {
1177
1335
  const file1Name = dup.file1.split("/").pop() || dup.file1;
1178
1336
  const file2Name = dup.file2.split("/").pop() || dup.file2;
1179
1337
  console.log(
1180
- `${severityIcon} ${severity}: ${import_chalk3.default.bold(file1Name)} \u2194 ${import_chalk3.default.bold(file2Name)}`
1338
+ `${severityIcon} ${severity}: ${import_chalk4.default.bold(file1Name)} \u2194 ${import_chalk4.default.bold(file2Name)}`
1181
1339
  );
1182
1340
  console.log(
1183
- ` Similarity: ${import_chalk3.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk3.default.bold(dup.tokenCost.toLocaleString())} tokens each`
1341
+ ` Similarity: ${import_chalk4.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk4.default.bold(dup.tokenCost.toLocaleString())} tokens each`
1184
1342
  );
1185
1343
  console.log(
1186
- ` Lines: ${import_chalk3.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk3.default.cyan(dup.line2 + "-" + dup.endLine2)}
1344
+ ` Lines: ${import_chalk4.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk4.default.cyan(dup.line2 + "-" + dup.endLine2)}
1187
1345
  `
1188
1346
  );
1189
1347
  });
1190
1348
  } else {
1191
1349
  console.log(
1192
- import_chalk3.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
1350
+ import_chalk4.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
1193
1351
  );
1194
1352
  }
1195
1353
  if (patternScore) {
1196
- console.log(import_chalk3.default.cyan(divider));
1197
- console.log(import_chalk3.default.bold.white(" AI READINESS SCORE (Patterns)"));
1198
- console.log(import_chalk3.default.cyan(divider) + "\n");
1199
- console.log((0, import_core2.formatToolScore)(patternScore));
1354
+ console.log(import_chalk4.default.cyan(divider));
1355
+ console.log(import_chalk4.default.bold.white(" AI READINESS SCORE (Patterns)"));
1356
+ console.log(import_chalk4.default.cyan(divider) + "\n");
1357
+ console.log((0, import_core3.formatToolScore)(patternScore));
1200
1358
  console.log();
1201
1359
  }
1202
1360
  }
1203
1361
  } catch (error) {
1204
- (0, import_core2.handleCLIError)(error, "Pattern analysis");
1362
+ (0, import_core3.handleCLIError)(error, "Pattern analysis");
1205
1363
  }
1206
1364
  }
1207
1365
  var patternsHelpText = `
@@ -1212,13 +1370,13 @@ EXAMPLES:
1212
1370
  `;
1213
1371
 
1214
1372
  // src/commands/context.ts
1215
- var import_chalk4 = __toESM(require("chalk"));
1216
- var import_path4 = require("path");
1217
- var import_core3 = require("@aiready/core");
1373
+ var import_chalk5 = __toESM(require("chalk"));
1374
+ var import_path5 = require("path");
1375
+ var import_core4 = require("@aiready/core");
1218
1376
  async function contextAction(directory, options) {
1219
- console.log(import_chalk4.default.blue("\u{1F9E0} Analyzing context costs...\n"));
1377
+ console.log(import_chalk5.default.blue("\u{1F9E0} Analyzing context costs...\n"));
1220
1378
  const startTime = Date.now();
1221
- const resolvedDir = (0, import_path4.resolve)(process.cwd(), directory || ".");
1379
+ const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
1222
1380
  try {
1223
1381
  const defaults = {
1224
1382
  maxDepth: 5,
@@ -1230,7 +1388,7 @@ async function contextAction(directory, options) {
1230
1388
  file: void 0
1231
1389
  }
1232
1390
  };
1233
- const baseOptions = await (0, import_core3.loadMergedConfig)(resolvedDir, defaults, {
1391
+ const baseOptions = await (0, import_core4.loadMergedConfig)(resolvedDir, defaults, {
1234
1392
  maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
1235
1393
  maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
1236
1394
  include: options.include?.split(","),
@@ -1256,7 +1414,7 @@ async function contextAction(directory, options) {
1256
1414
  console.log("");
1257
1415
  const { analyzeContext: analyzeContext2, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
1258
1416
  const results = await analyzeContext2(finalOptions);
1259
- const elapsedTime = (0, import_core3.getElapsedTime)(startTime);
1417
+ const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
1260
1418
  const summary = generateSummary(results);
1261
1419
  let contextScore;
1262
1420
  if (options.score) {
@@ -1270,12 +1428,12 @@ async function contextAction(directory, options) {
1270
1428
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
1271
1429
  ...contextScore && { scoring: contextScore }
1272
1430
  };
1273
- const outputPath = (0, import_core3.resolveOutputPath)(
1431
+ const outputPath = (0, import_core4.resolveOutputPath)(
1274
1432
  userOutputFile,
1275
1433
  `aiready-report-${getReportTimestamp()}.json`,
1276
1434
  resolvedDir
1277
1435
  );
1278
- (0, import_core3.handleJSONOutput)(
1436
+ (0, import_core4.handleJSONOutput)(
1279
1437
  outputData,
1280
1438
  outputPath,
1281
1439
  `\u2705 Results saved to ${outputPath}`
@@ -1284,85 +1442,85 @@ async function contextAction(directory, options) {
1284
1442
  const terminalWidth = process.stdout.columns || 80;
1285
1443
  const dividerWidth = Math.min(60, terminalWidth - 2);
1286
1444
  const divider = "\u2501".repeat(dividerWidth);
1287
- console.log(import_chalk4.default.cyan(divider));
1288
- console.log(import_chalk4.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1289
- console.log(import_chalk4.default.cyan(divider) + "\n");
1445
+ console.log(import_chalk5.default.cyan(divider));
1446
+ console.log(import_chalk5.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1447
+ console.log(import_chalk5.default.cyan(divider) + "\n");
1290
1448
  console.log(
1291
- import_chalk4.default.white(`\u{1F4C1} Files analyzed: ${import_chalk4.default.bold(summary.totalFiles)}`)
1449
+ import_chalk5.default.white(`\u{1F4C1} Files analyzed: ${import_chalk5.default.bold(summary.totalFiles)}`)
1292
1450
  );
1293
1451
  console.log(
1294
- import_chalk4.default.white(
1295
- `\u{1F4CA} Total tokens: ${import_chalk4.default.bold(summary.totalTokens.toLocaleString())}`
1452
+ import_chalk5.default.white(
1453
+ `\u{1F4CA} Total tokens: ${import_chalk5.default.bold(summary.totalTokens.toLocaleString())}`
1296
1454
  )
1297
1455
  );
1298
1456
  console.log(
1299
- import_chalk4.default.yellow(
1300
- `\u{1F4B0} Avg context budget: ${import_chalk4.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1457
+ import_chalk5.default.yellow(
1458
+ `\u{1F4B0} Avg context budget: ${import_chalk5.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1301
1459
  )
1302
1460
  );
1303
1461
  console.log(
1304
- import_chalk4.default.white(`\u23F1 Analysis time: ${import_chalk4.default.bold(elapsedTime + "s")}
1462
+ import_chalk5.default.white(`\u23F1 Analysis time: ${import_chalk5.default.bold(elapsedTime + "s")}
1305
1463
  `)
1306
1464
  );
1307
1465
  const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
1308
1466
  if (totalIssues > 0) {
1309
- console.log(import_chalk4.default.bold("\u26A0\uFE0F Issues Found:\n"));
1467
+ console.log(import_chalk5.default.bold("\u26A0\uFE0F Issues Found:\n"));
1310
1468
  if (summary.criticalIssues > 0) {
1311
1469
  console.log(
1312
- import_chalk4.default.red(` \u{1F534} Critical: ${import_chalk4.default.bold(summary.criticalIssues)}`)
1470
+ import_chalk5.default.red(` \u{1F534} Critical: ${import_chalk5.default.bold(summary.criticalIssues)}`)
1313
1471
  );
1314
1472
  }
1315
1473
  if (summary.majorIssues > 0) {
1316
1474
  console.log(
1317
- import_chalk4.default.yellow(` \u{1F7E1} Major: ${import_chalk4.default.bold(summary.majorIssues)}`)
1475
+ import_chalk5.default.yellow(` \u{1F7E1} Major: ${import_chalk5.default.bold(summary.majorIssues)}`)
1318
1476
  );
1319
1477
  }
1320
1478
  if (summary.minorIssues > 0) {
1321
1479
  console.log(
1322
- import_chalk4.default.blue(` \u{1F535} Minor: ${import_chalk4.default.bold(summary.minorIssues)}`)
1480
+ import_chalk5.default.blue(` \u{1F535} Minor: ${import_chalk5.default.bold(summary.minorIssues)}`)
1323
1481
  );
1324
1482
  }
1325
1483
  console.log(
1326
- import_chalk4.default.green(
1484
+ import_chalk5.default.green(
1327
1485
  `
1328
- \u{1F4A1} Potential savings: ${import_chalk4.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1486
+ \u{1F4A1} Potential savings: ${import_chalk5.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1329
1487
  `
1330
1488
  )
1331
1489
  );
1332
1490
  } else {
1333
- console.log(import_chalk4.default.green("\u2705 No significant issues found!\n"));
1491
+ console.log(import_chalk5.default.green("\u2705 No significant issues found!\n"));
1334
1492
  }
1335
1493
  if (summary.deepFiles.length > 0) {
1336
- console.log(import_chalk4.default.bold("\u{1F4CF} Deep Import Chains:\n"));
1494
+ console.log(import_chalk5.default.bold("\u{1F4CF} Deep Import Chains:\n"));
1337
1495
  console.log(
1338
- import_chalk4.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1496
+ import_chalk5.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1339
1497
  );
1340
1498
  console.log(
1341
- import_chalk4.default.gray(` Maximum depth: ${summary.maxImportDepth}
1499
+ import_chalk5.default.gray(` Maximum depth: ${summary.maxImportDepth}
1342
1500
  `)
1343
1501
  );
1344
1502
  summary.deepFiles.slice(0, 10).forEach((item) => {
1345
1503
  const fileName = item.file.split("/").slice(-2).join("/");
1346
1504
  console.log(
1347
- ` ${import_chalk4.default.cyan("\u2192")} ${import_chalk4.default.white(fileName)} ${import_chalk4.default.dim(`(depth: ${item.depth})`)}`
1505
+ ` ${import_chalk5.default.cyan("\u2192")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(depth: ${item.depth})`)}`
1348
1506
  );
1349
1507
  });
1350
1508
  console.log();
1351
1509
  }
1352
1510
  if (summary.fragmentedModules.length > 0) {
1353
- console.log(import_chalk4.default.bold("\u{1F9E9} Fragmented Modules:\n"));
1511
+ console.log(import_chalk5.default.bold("\u{1F9E9} Fragmented Modules:\n"));
1354
1512
  console.log(
1355
- import_chalk4.default.gray(
1513
+ import_chalk5.default.gray(
1356
1514
  ` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
1357
1515
  `
1358
1516
  )
1359
1517
  );
1360
1518
  summary.fragmentedModules.slice(0, 10).forEach((module2) => {
1361
1519
  console.log(
1362
- ` ${import_chalk4.default.yellow("\u25CF")} ${import_chalk4.default.white(module2.domain)} - ${import_chalk4.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1520
+ ` ${import_chalk5.default.yellow("\u25CF")} ${import_chalk5.default.white(module2.domain)} - ${import_chalk5.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1363
1521
  );
1364
1522
  console.log(
1365
- import_chalk4.default.dim(
1523
+ import_chalk5.default.dim(
1366
1524
  ` Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`
1367
1525
  )
1368
1526
  );
@@ -1370,9 +1528,9 @@ async function contextAction(directory, options) {
1370
1528
  console.log();
1371
1529
  }
1372
1530
  if (summary.lowCohesionFiles.length > 0) {
1373
- console.log(import_chalk4.default.bold("\u{1F500} Low Cohesion Files:\n"));
1531
+ console.log(import_chalk5.default.bold("\u{1F500} Low Cohesion Files:\n"));
1374
1532
  console.log(
1375
- import_chalk4.default.gray(
1533
+ import_chalk5.default.gray(
1376
1534
  ` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
1377
1535
  `
1378
1536
  )
@@ -1380,46 +1538,46 @@ async function contextAction(directory, options) {
1380
1538
  summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
1381
1539
  const fileName = item.file.split("/").slice(-2).join("/");
1382
1540
  const scorePercent = (item.score * 100).toFixed(0);
1383
- const color = item.score < 0.4 ? import_chalk4.default.red : import_chalk4.default.yellow;
1541
+ const color = item.score < 0.4 ? import_chalk5.default.red : import_chalk5.default.yellow;
1384
1542
  console.log(
1385
- ` ${color("\u25CB")} ${import_chalk4.default.white(fileName)} ${import_chalk4.default.dim(`(${scorePercent}% cohesion)`)}`
1543
+ ` ${color("\u25CB")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${scorePercent}% cohesion)`)}`
1386
1544
  );
1387
1545
  });
1388
1546
  console.log();
1389
1547
  }
1390
1548
  if (summary.topExpensiveFiles.length > 0) {
1391
- console.log(import_chalk4.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1549
+ console.log(import_chalk5.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1392
1550
  summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
1393
1551
  const fileName = item.file.split("/").slice(-2).join("/");
1394
- const severityColor = item.severity === "critical" ? import_chalk4.default.red : item.severity === "major" ? import_chalk4.default.yellow : import_chalk4.default.blue;
1552
+ const severityColor = item.severity === "critical" ? import_chalk5.default.red : item.severity === "major" ? import_chalk5.default.yellow : import_chalk5.default.blue;
1395
1553
  console.log(
1396
- ` ${severityColor("\u25CF")} ${import_chalk4.default.white(fileName)} ${import_chalk4.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1554
+ ` ${severityColor("\u25CF")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1397
1555
  );
1398
1556
  });
1399
1557
  console.log();
1400
1558
  }
1401
1559
  if (contextScore) {
1402
- console.log(import_chalk4.default.cyan(divider));
1403
- console.log(import_chalk4.default.bold.white(" AI READINESS SCORE (Context)"));
1404
- console.log(import_chalk4.default.cyan(divider) + "\n");
1405
- console.log((0, import_core3.formatToolScore)(contextScore));
1560
+ console.log(import_chalk5.default.cyan(divider));
1561
+ console.log(import_chalk5.default.bold.white(" AI READINESS SCORE (Context)"));
1562
+ console.log(import_chalk5.default.cyan(divider) + "\n");
1563
+ console.log((0, import_core4.formatToolScore)(contextScore));
1406
1564
  console.log();
1407
1565
  }
1408
1566
  }
1409
1567
  } catch (error) {
1410
- (0, import_core3.handleCLIError)(error, "Context analysis");
1568
+ (0, import_core4.handleCLIError)(error, "Context analysis");
1411
1569
  }
1412
1570
  }
1413
1571
 
1414
1572
  // src/commands/consistency.ts
1415
- var import_chalk5 = __toESM(require("chalk"));
1416
- var import_fs3 = require("fs");
1417
- var import_path5 = require("path");
1418
- var import_core4 = require("@aiready/core");
1573
+ var import_chalk6 = __toESM(require("chalk"));
1574
+ var import_fs4 = require("fs");
1575
+ var import_path6 = require("path");
1576
+ var import_core5 = require("@aiready/core");
1419
1577
  async function consistencyAction(directory, options) {
1420
- console.log(import_chalk5.default.blue("\u{1F50D} Analyzing consistency...\n"));
1578
+ console.log(import_chalk6.default.blue("\u{1F50D} Analyzing consistency...\n"));
1421
1579
  const startTime = Date.now();
1422
- const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
1580
+ const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory || ".");
1423
1581
  try {
1424
1582
  const defaults = {
1425
1583
  checkNaming: true,
@@ -1432,7 +1590,7 @@ async function consistencyAction(directory, options) {
1432
1590
  file: void 0
1433
1591
  }
1434
1592
  };
1435
- const finalOptions = await (0, import_core4.loadMergedConfig)(resolvedDir, defaults, {
1593
+ const finalOptions = await (0, import_core5.loadMergedConfig)(resolvedDir, defaults, {
1436
1594
  checkNaming: options.naming !== false,
1437
1595
  checkPatterns: options.patterns !== false,
1438
1596
  minSeverity: options.minSeverity,
@@ -1441,7 +1599,7 @@ async function consistencyAction(directory, options) {
1441
1599
  });
1442
1600
  const { analyzeConsistency: analyzeConsistency2, calculateConsistencyScore } = await import("@aiready/consistency");
1443
1601
  const report = await analyzeConsistency2(finalOptions);
1444
- const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
1602
+ const elapsedTime = (0, import_core5.getElapsedTime)(startTime);
1445
1603
  let consistencyScore;
1446
1604
  if (options.score) {
1447
1605
  const issues = report.results?.flatMap((r) => r.issues) || [];
@@ -1461,41 +1619,41 @@ async function consistencyAction(directory, options) {
1461
1619
  },
1462
1620
  ...consistencyScore && { scoring: consistencyScore }
1463
1621
  };
1464
- const outputPath = (0, import_core4.resolveOutputPath)(
1622
+ const outputPath = (0, import_core5.resolveOutputPath)(
1465
1623
  userOutputFile,
1466
1624
  `aiready-report-${getReportTimestamp()}.json`,
1467
1625
  resolvedDir
1468
1626
  );
1469
- (0, import_core4.handleJSONOutput)(
1627
+ (0, import_core5.handleJSONOutput)(
1470
1628
  outputData,
1471
1629
  outputPath,
1472
1630
  `\u2705 Results saved to ${outputPath}`
1473
1631
  );
1474
1632
  } else if (outputFormat === "markdown") {
1475
1633
  const markdown = generateMarkdownReport(report, elapsedTime);
1476
- const outputPath = (0, import_core4.resolveOutputPath)(
1634
+ const outputPath = (0, import_core5.resolveOutputPath)(
1477
1635
  userOutputFile,
1478
1636
  `aiready-report-${getReportTimestamp()}.md`,
1479
1637
  resolvedDir
1480
1638
  );
1481
- (0, import_fs3.writeFileSync)(outputPath, markdown);
1482
- console.log(import_chalk5.default.green(`\u2705 Report saved to ${outputPath}`));
1639
+ (0, import_fs4.writeFileSync)(outputPath, markdown);
1640
+ console.log(import_chalk6.default.green(`\u2705 Report saved to ${outputPath}`));
1483
1641
  } else {
1484
- console.log(import_chalk5.default.bold("\n\u{1F4CA} Summary\n"));
1642
+ console.log(import_chalk6.default.bold("\n\u{1F4CA} Summary\n"));
1485
1643
  console.log(
1486
- `Files Analyzed: ${import_chalk5.default.cyan(report.summary.filesAnalyzed)}`
1644
+ `Files Analyzed: ${import_chalk6.default.cyan(report.summary.filesAnalyzed)}`
1487
1645
  );
1488
- console.log(`Total Issues: ${import_chalk5.default.yellow(report.summary.totalIssues)}`);
1489
- console.log(` Naming: ${import_chalk5.default.yellow(report.summary.namingIssues)}`);
1490
- console.log(` Patterns: ${import_chalk5.default.yellow(report.summary.patternIssues)}`);
1646
+ console.log(`Total Issues: ${import_chalk6.default.yellow(report.summary.totalIssues)}`);
1647
+ console.log(` Naming: ${import_chalk6.default.yellow(report.summary.namingIssues)}`);
1648
+ console.log(` Patterns: ${import_chalk6.default.yellow(report.summary.patternIssues)}`);
1491
1649
  console.log(
1492
- ` Architecture: ${import_chalk5.default.yellow(report.summary.architectureIssues || 0)}`
1650
+ ` Architecture: ${import_chalk6.default.yellow(report.summary.architectureIssues || 0)}`
1493
1651
  );
1494
- console.log(`Analysis Time: ${import_chalk5.default.gray(elapsedTime + "s")}
1652
+ console.log(`Analysis Time: ${import_chalk6.default.gray(elapsedTime + "s")}
1495
1653
  `);
1496
1654
  if (report.summary.totalIssues === 0) {
1497
1655
  console.log(
1498
- import_chalk5.default.green(
1656
+ import_chalk6.default.green(
1499
1657
  "\u2728 No consistency issues found! Your codebase is well-maintained.\n"
1500
1658
  )
1501
1659
  );
@@ -1507,20 +1665,20 @@ async function consistencyAction(directory, options) {
1507
1665
  (r) => r.issues.some((i) => i.category === "patterns")
1508
1666
  );
1509
1667
  if (namingResults.length > 0) {
1510
- console.log(import_chalk5.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1668
+ console.log(import_chalk6.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1511
1669
  let shown = 0;
1512
1670
  for (const result of namingResults) {
1513
1671
  if (shown >= 5) break;
1514
1672
  for (const issue of result.issues) {
1515
1673
  if (shown >= 5) break;
1516
- const severityColor = issue.severity === "critical" ? import_chalk5.default.red : issue.severity === "major" ? import_chalk5.default.yellow : issue.severity === "minor" ? import_chalk5.default.blue : import_chalk5.default.gray;
1674
+ const severityColor = issue.severity === "critical" ? import_chalk6.default.red : issue.severity === "major" ? import_chalk6.default.yellow : issue.severity === "minor" ? import_chalk6.default.blue : import_chalk6.default.gray;
1517
1675
  console.log(
1518
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk5.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1676
+ `${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1519
1677
  );
1520
1678
  console.log(` ${issue.message}`);
1521
1679
  if (issue.suggestion) {
1522
1680
  console.log(
1523
- ` ${import_chalk5.default.dim("\u2192")} ${import_chalk5.default.italic(issue.suggestion)}`
1681
+ ` ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
1524
1682
  );
1525
1683
  }
1526
1684
  console.log();
@@ -1529,25 +1687,25 @@ async function consistencyAction(directory, options) {
1529
1687
  }
1530
1688
  const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1531
1689
  if (remaining > 0) {
1532
- console.log(import_chalk5.default.dim(` ... and ${remaining} more issues
1690
+ console.log(import_chalk6.default.dim(` ... and ${remaining} more issues
1533
1691
  `));
1534
1692
  }
1535
1693
  }
1536
1694
  if (patternResults.length > 0) {
1537
- console.log(import_chalk5.default.bold("\u{1F504} Pattern Issues\n"));
1695
+ console.log(import_chalk6.default.bold("\u{1F504} Pattern Issues\n"));
1538
1696
  let shown = 0;
1539
1697
  for (const result of patternResults) {
1540
1698
  if (shown >= 5) break;
1541
1699
  for (const issue of result.issues) {
1542
1700
  if (shown >= 5) break;
1543
- const severityColor = issue.severity === "critical" ? import_chalk5.default.red : issue.severity === "major" ? import_chalk5.default.yellow : issue.severity === "minor" ? import_chalk5.default.blue : import_chalk5.default.gray;
1701
+ const severityColor = issue.severity === "critical" ? import_chalk6.default.red : issue.severity === "major" ? import_chalk6.default.yellow : issue.severity === "minor" ? import_chalk6.default.blue : import_chalk6.default.gray;
1544
1702
  console.log(
1545
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk5.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1703
+ `${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1546
1704
  );
1547
1705
  console.log(` ${issue.message}`);
1548
1706
  if (issue.suggestion) {
1549
1707
  console.log(
1550
- ` ${import_chalk5.default.dim("\u2192")} ${import_chalk5.default.italic(issue.suggestion)}`
1708
+ ` ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
1551
1709
  );
1552
1710
  }
1553
1711
  console.log();
@@ -1556,12 +1714,12 @@ async function consistencyAction(directory, options) {
1556
1714
  }
1557
1715
  const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1558
1716
  if (remaining > 0) {
1559
- console.log(import_chalk5.default.dim(` ... and ${remaining} more issues
1717
+ console.log(import_chalk6.default.dim(` ... and ${remaining} more issues
1560
1718
  `));
1561
1719
  }
1562
1720
  }
1563
1721
  if (report.recommendations.length > 0) {
1564
- console.log(import_chalk5.default.bold("\u{1F4A1} Recommendations\n"));
1722
+ console.log(import_chalk6.default.bold("\u{1F4A1} Recommendations\n"));
1565
1723
  report.recommendations.forEach((rec, i) => {
1566
1724
  console.log(`${i + 1}. ${rec}`);
1567
1725
  });
@@ -1569,38 +1727,38 @@ async function consistencyAction(directory, options) {
1569
1727
  }
1570
1728
  }
1571
1729
  if (consistencyScore) {
1572
- console.log(import_chalk5.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1573
- console.log((0, import_core4.formatToolScore)(consistencyScore));
1730
+ console.log(import_chalk6.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1731
+ console.log((0, import_core5.formatToolScore)(consistencyScore));
1574
1732
  console.log();
1575
1733
  }
1576
1734
  }
1577
1735
  } catch (error) {
1578
- (0, import_core4.handleCLIError)(error, "Consistency analysis");
1736
+ (0, import_core5.handleCLIError)(error, "Consistency analysis");
1579
1737
  }
1580
1738
  }
1581
1739
 
1582
1740
  // src/commands/visualize.ts
1583
- var import_chalk6 = __toESM(require("chalk"));
1584
- var import_fs4 = require("fs");
1585
- var import_path6 = require("path");
1741
+ var import_chalk7 = __toESM(require("chalk"));
1742
+ var import_fs5 = require("fs");
1743
+ var import_path7 = require("path");
1586
1744
  var import_child_process = require("child_process");
1587
- var import_core5 = require("@aiready/core");
1588
1745
  var import_core6 = require("@aiready/core");
1746
+ var import_core7 = require("@aiready/core");
1589
1747
  async function visualizeAction(directory, options) {
1590
1748
  try {
1591
- const dirPath = (0, import_path6.resolve)(process.cwd(), directory || ".");
1592
- let reportPath = options.report ? (0, import_path6.resolve)(dirPath, options.report) : null;
1593
- if (!reportPath || !(0, import_fs4.existsSync)(reportPath)) {
1749
+ const dirPath = (0, import_path7.resolve)(process.cwd(), directory || ".");
1750
+ let reportPath = options.report ? (0, import_path7.resolve)(dirPath, options.report) : null;
1751
+ if (!reportPath || !(0, import_fs5.existsSync)(reportPath)) {
1594
1752
  const latestScan = findLatestScanReport(dirPath);
1595
1753
  if (latestScan) {
1596
1754
  reportPath = latestScan;
1597
1755
  console.log(
1598
- import_chalk6.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1756
+ import_chalk7.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1599
1757
  );
1600
1758
  } else {
1601
- console.error(import_chalk6.default.red("\u274C No AI readiness report found"));
1759
+ console.error(import_chalk7.default.red("\u274C No AI readiness report found"));
1602
1760
  console.log(
1603
- import_chalk6.default.dim(
1761
+ import_chalk7.default.dim(
1604
1762
  `
1605
1763
  Generate a report with:
1606
1764
  aiready scan --output json
@@ -1612,13 +1770,13 @@ Or specify a custom report:
1612
1770
  return;
1613
1771
  }
1614
1772
  }
1615
- const raw = (0, import_fs4.readFileSync)(reportPath, "utf8");
1773
+ const raw = (0, import_fs5.readFileSync)(reportPath, "utf8");
1616
1774
  const report = JSON.parse(raw);
1617
- const configPath = (0, import_path6.resolve)(dirPath, "aiready.json");
1775
+ const configPath = (0, import_path7.resolve)(dirPath, "aiready.json");
1618
1776
  let graphConfig = { maxNodes: 400, maxEdges: 600 };
1619
- if ((0, import_fs4.existsSync)(configPath)) {
1777
+ if ((0, import_fs5.existsSync)(configPath)) {
1620
1778
  try {
1621
- const rawConfig = JSON.parse((0, import_fs4.readFileSync)(configPath, "utf8"));
1779
+ const rawConfig = JSON.parse((0, import_fs5.readFileSync)(configPath, "utf8"));
1622
1780
  if (rawConfig.visualizer?.graph) {
1623
1781
  graphConfig = {
1624
1782
  maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
@@ -1638,16 +1796,16 @@ Or specify a custom report:
1638
1796
  let devServerStarted = false;
1639
1797
  if (useDevMode) {
1640
1798
  try {
1641
- const monorepoWebDir = (0, import_path6.resolve)(dirPath, "packages/visualizer");
1799
+ const monorepoWebDir = (0, import_path7.resolve)(dirPath, "packages/visualizer");
1642
1800
  let webDir = "";
1643
1801
  let visualizerAvailable = false;
1644
- if ((0, import_fs4.existsSync)(monorepoWebDir)) {
1802
+ if ((0, import_fs5.existsSync)(monorepoWebDir)) {
1645
1803
  webDir = monorepoWebDir;
1646
1804
  visualizerAvailable = true;
1647
1805
  } else {
1648
1806
  const nodemodulesLocations = [
1649
- (0, import_path6.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
1650
- (0, import_path6.resolve)(
1807
+ (0, import_path7.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
1808
+ (0, import_path7.resolve)(
1651
1809
  process.cwd(),
1652
1810
  "node_modules",
1653
1811
  "@aiready",
@@ -1657,14 +1815,14 @@ Or specify a custom report:
1657
1815
  let currentDir = dirPath;
1658
1816
  while (currentDir !== "/" && currentDir !== ".") {
1659
1817
  nodemodulesLocations.push(
1660
- (0, import_path6.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
1818
+ (0, import_path7.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
1661
1819
  );
1662
- const parent = (0, import_path6.resolve)(currentDir, "..");
1820
+ const parent = (0, import_path7.resolve)(currentDir, "..");
1663
1821
  if (parent === currentDir) break;
1664
1822
  currentDir = parent;
1665
1823
  }
1666
1824
  for (const location of nodemodulesLocations) {
1667
- if ((0, import_fs4.existsSync)(location) && (0, import_fs4.existsSync)((0, import_path6.resolve)(location, "package.json"))) {
1825
+ if ((0, import_fs5.existsSync)(location) && (0, import_fs5.existsSync)((0, import_path7.resolve)(location, "package.json"))) {
1668
1826
  webDir = location;
1669
1827
  visualizerAvailable = true;
1670
1828
  break;
@@ -1673,21 +1831,21 @@ Or specify a custom report:
1673
1831
  if (!visualizerAvailable) {
1674
1832
  try {
1675
1833
  const vizPkgPath = require.resolve("@aiready/visualizer/package.json");
1676
- webDir = (0, import_path6.resolve)(vizPkgPath, "..");
1834
+ webDir = (0, import_path7.resolve)(vizPkgPath, "..");
1677
1835
  visualizerAvailable = true;
1678
1836
  } catch (err) {
1679
1837
  void err;
1680
1838
  }
1681
1839
  }
1682
1840
  }
1683
- const webViteConfigExists = webDir && (0, import_fs4.existsSync)((0, import_path6.resolve)(webDir, "web", "vite.config.ts"));
1841
+ const webViteConfigExists = webDir && (0, import_fs5.existsSync)((0, import_path7.resolve)(webDir, "web", "vite.config.ts"));
1684
1842
  if (visualizerAvailable && webViteConfigExists) {
1685
1843
  const spawnCwd = webDir;
1686
1844
  const { watch } = await import("fs");
1687
1845
  const copyReportToViz = () => {
1688
1846
  try {
1689
- const destPath = (0, import_path6.resolve)(spawnCwd, "web", "report-data.json");
1690
- (0, import_fs4.copyFileSync)(reportPath, destPath);
1847
+ const destPath = (0, import_path7.resolve)(spawnCwd, "web", "report-data.json");
1848
+ (0, import_fs5.copyFileSync)(reportPath, destPath);
1691
1849
  console.log(`\u{1F4CB} Report synced to ${destPath}`);
1692
1850
  } catch (e) {
1693
1851
  console.error("Failed to sync report:", e);
@@ -1730,29 +1888,29 @@ Or specify a custom report:
1730
1888
  return;
1731
1889
  } else {
1732
1890
  console.log(
1733
- import_chalk6.default.yellow(
1891
+ import_chalk7.default.yellow(
1734
1892
  "\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."
1735
1893
  )
1736
1894
  );
1737
1895
  console.log(
1738
- import_chalk6.default.cyan(" Falling back to static HTML generation...\n")
1896
+ import_chalk7.default.cyan(" Falling back to static HTML generation...\n")
1739
1897
  );
1740
1898
  useDevMode = false;
1741
1899
  }
1742
1900
  } catch (err) {
1743
1901
  console.error("Failed to start dev server:", err);
1744
1902
  console.log(
1745
- import_chalk6.default.cyan(" Falling back to static HTML generation...\n")
1903
+ import_chalk7.default.cyan(" Falling back to static HTML generation...\n")
1746
1904
  );
1747
1905
  useDevMode = false;
1748
1906
  }
1749
1907
  }
1750
1908
  console.log("Generating HTML...");
1751
- const html = (0, import_core6.generateHTML)(graph);
1909
+ const html = (0, import_core7.generateHTML)(graph);
1752
1910
  const defaultOutput = "visualization.html";
1753
- const outPath = (0, import_path6.resolve)(dirPath, options.output || defaultOutput);
1754
- (0, import_fs4.writeFileSync)(outPath, html, "utf8");
1755
- console.log(import_chalk6.default.green(`\u2705 Visualization written to: ${outPath}`));
1911
+ const outPath = (0, import_path7.resolve)(dirPath, options.output || defaultOutput);
1912
+ (0, import_fs5.writeFileSync)(outPath, html, "utf8");
1913
+ console.log(import_chalk7.default.green(`\u2705 Visualization written to: ${outPath}`));
1756
1914
  if (options.open || options.serve) {
1757
1915
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
1758
1916
  if (options.serve) {
@@ -1782,7 +1940,7 @@ Or specify a custom report:
1782
1940
  server.listen(port, () => {
1783
1941
  const addr = `http://localhost:${port}/`;
1784
1942
  console.log(
1785
- import_chalk6.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1943
+ import_chalk7.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1786
1944
  );
1787
1945
  (0, import_child_process.spawn)(opener, [`"${addr}"`], { shell: true });
1788
1946
  });
@@ -1798,7 +1956,7 @@ Or specify a custom report:
1798
1956
  }
1799
1957
  }
1800
1958
  } catch (err) {
1801
- (0, import_core5.handleCLIError)(err, "Visualization");
1959
+ (0, import_core6.handleCLIError)(err, "Visualization");
1802
1960
  }
1803
1961
  }
1804
1962
  var visualizeHelpText = `
@@ -1829,17 +1987,17 @@ NOTES:
1829
1987
  `;
1830
1988
 
1831
1989
  // src/commands/ai-signal-clarity.ts
1832
- var import_chalk7 = __toESM(require("chalk"));
1833
- var import_core7 = require("@aiready/core");
1834
-
1835
- // src/commands/agent-grounding.ts
1836
1990
  var import_chalk8 = __toESM(require("chalk"));
1837
1991
  var import_core8 = require("@aiready/core");
1838
1992
 
1839
- // src/commands/testability.ts
1993
+ // src/commands/agent-grounding.ts
1840
1994
  var import_chalk9 = __toESM(require("chalk"));
1841
1995
  var import_core9 = require("@aiready/core");
1842
1996
 
1997
+ // src/commands/testability.ts
1998
+ var import_chalk10 = __toESM(require("chalk"));
1999
+ var import_core10 = require("@aiready/core");
2000
+
1843
2001
  // src/commands/change-amplification.ts
1844
2002
  var import_cli = require("@aiready/change-amplification/dist/cli.js");
1845
2003
 
@@ -1847,10 +2005,10 @@ var import_cli = require("@aiready/change-amplification/dist/cli.js");
1847
2005
  var import_meta = {};
1848
2006
  var getDirname = () => {
1849
2007
  if (typeof __dirname !== "undefined") return __dirname;
1850
- return (0, import_path7.dirname)((0, import_url.fileURLToPath)(import_meta.url));
2008
+ return (0, import_path8.dirname)((0, import_url.fileURLToPath)(import_meta.url));
1851
2009
  };
1852
2010
  var packageJson = JSON.parse(
1853
- (0, import_fs5.readFileSync)((0, import_path7.join)(getDirname(), "../package.json"), "utf8")
2011
+ (0, import_fs6.readFileSync)((0, import_path8.join)(getDirname(), "../package.json"), "utf8")
1854
2012
  );
1855
2013
  var program = new import_commander.Command();
1856
2014
  program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText(
@@ -1913,7 +2071,7 @@ program.command("scan").description(
1913
2071
  "--fail-on <level>",
1914
2072
  "Fail on issues: critical, major, any",
1915
2073
  "critical"
1916
- ).addHelpText("after", scanHelpText).action(async (directory, options) => {
2074
+ ).option("--api-key <key>", "Platform API key for automatic upload").option("--upload", "Automatically upload results to the platform").option("--server <url>", "Custom platform URL").addHelpText("after", scanHelpText).action(async (directory, options) => {
1917
2075
  await scanAction(directory, options);
1918
2076
  });
1919
2077
  program.command("patterns").description("Detect duplicate code patterns that confuse AI models").argument("[directory]", "Directory to analyze", ".").option("-s, --similarity <number>", "Minimum similarity score (0-1)", "0.40").option("-l, --min-lines <number>", "Minimum lines to consider", "5").option(
@@ -1994,4 +2152,7 @@ program.command("visualize").description("Generate interactive visualization fro
1994
2152
  program.command("change-amplification").description("Analyze graph metrics for change amplification").argument("[directory]", "Directory to analyze", ".").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").action(async (directory, options) => {
1995
2153
  await (0, import_cli.changeAmplificationAction)(directory, options);
1996
2154
  });
2155
+ program.command("upload").description("Upload an AIReady report JSON to the platform").argument("<file>", "Report JSON file to upload").option("--api-key <key>", "Platform API key").option("--repo-id <id>", "Platform repository ID (optional)").option("--server <url>", "Custom platform URL").addHelpText("after", uploadHelpText).action(async (file, options) => {
2156
+ await uploadAction(file, options);
2157
+ });
1997
2158
  program.parse();