@aiready/cli 0.9.43 → 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/.turbo/turbo-build.log +8 -8
- package/README.md +22 -1
- package/dist/cli.js +404 -257
- package/dist/cli.mjs +364 -211
- package/package.json +12 -12
- package/src/cli.ts +18 -0
- package/src/commands/index.ts +1 -0
- package/src/commands/scan.ts +113 -7
- package/src/commands/upload.ts +87 -0
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
|
|
29
|
-
var
|
|
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
|
|
34
|
-
var
|
|
35
|
-
var
|
|
36
|
-
var
|
|
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");
|
|
@@ -338,11 +338,79 @@ function truncateArray(arr, cap = 8) {
|
|
|
338
338
|
return shown.join(", ") + (more > 0 ? `, ... (+${more} more)` : "");
|
|
339
339
|
}
|
|
340
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
|
+
|
|
341
408
|
// src/commands/scan.ts
|
|
342
409
|
async function scanAction(directory, options) {
|
|
343
|
-
console.log(
|
|
410
|
+
console.log(import_chalk3.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
|
|
344
411
|
const startTime = Date.now();
|
|
345
|
-
const resolvedDir = (0,
|
|
412
|
+
const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory || ".");
|
|
413
|
+
const repoMetadata = (0, import_core2.getRepoMetadata)(resolvedDir);
|
|
346
414
|
try {
|
|
347
415
|
const defaults = {
|
|
348
416
|
tools: [
|
|
@@ -385,7 +453,7 @@ async function scanAction(directory, options) {
|
|
|
385
453
|
break;
|
|
386
454
|
default:
|
|
387
455
|
console.log(
|
|
388
|
-
|
|
456
|
+
import_chalk3.default.yellow(
|
|
389
457
|
`
|
|
390
458
|
\u26A0\uFE0F Unknown profile '${options.profile}'. Using specified tools or defaults.`
|
|
391
459
|
)
|
|
@@ -399,7 +467,7 @@ async function scanAction(directory, options) {
|
|
|
399
467
|
if (profileTools) {
|
|
400
468
|
cliOverrides.tools = profileTools;
|
|
401
469
|
}
|
|
402
|
-
const baseOptions = await (0,
|
|
470
|
+
const baseOptions = await (0, import_core2.loadMergedConfig)(
|
|
403
471
|
resolvedDir,
|
|
404
472
|
defaults,
|
|
405
473
|
cliOverrides
|
|
@@ -417,22 +485,22 @@ async function scanAction(directory, options) {
|
|
|
417
485
|
...baseOptions
|
|
418
486
|
};
|
|
419
487
|
}
|
|
420
|
-
console.log(
|
|
488
|
+
console.log(import_chalk3.default.cyan("\n=== AIReady Run Preview ==="));
|
|
421
489
|
console.log(
|
|
422
|
-
|
|
490
|
+
import_chalk3.default.white("Tools to run:"),
|
|
423
491
|
(finalOptions.tools || ["patterns", "context", "consistency"]).join(", ")
|
|
424
492
|
);
|
|
425
|
-
console.log(
|
|
426
|
-
console.log(
|
|
493
|
+
console.log(import_chalk3.default.white("Will use settings from config and defaults."));
|
|
494
|
+
console.log(import_chalk3.default.white("\nGeneral settings:"));
|
|
427
495
|
if (finalOptions.rootDir)
|
|
428
|
-
console.log(` rootDir: ${
|
|
496
|
+
console.log(` rootDir: ${import_chalk3.default.bold(String(finalOptions.rootDir))}`);
|
|
429
497
|
if (finalOptions.include)
|
|
430
498
|
console.log(
|
|
431
|
-
` include: ${
|
|
499
|
+
` include: ${import_chalk3.default.bold(truncateArray(finalOptions.include, 6))}`
|
|
432
500
|
);
|
|
433
501
|
if (finalOptions.exclude)
|
|
434
502
|
console.log(
|
|
435
|
-
` exclude: ${
|
|
503
|
+
` exclude: ${import_chalk3.default.bold(truncateArray(finalOptions.exclude, 6))}`
|
|
436
504
|
);
|
|
437
505
|
if (finalOptions["pattern-detect"] || finalOptions.minSimilarity) {
|
|
438
506
|
const patternDetectConfig = finalOptions["pattern-detect"] || {
|
|
@@ -446,40 +514,40 @@ async function scanAction(directory, options) {
|
|
|
446
514
|
severity: finalOptions.severity,
|
|
447
515
|
includeTests: finalOptions.includeTests
|
|
448
516
|
};
|
|
449
|
-
console.log(
|
|
517
|
+
console.log(import_chalk3.default.white("\nPattern-detect settings:"));
|
|
450
518
|
console.log(
|
|
451
|
-
` minSimilarity: ${
|
|
519
|
+
` minSimilarity: ${import_chalk3.default.bold(patternDetectConfig.minSimilarity ?? "default")}`
|
|
452
520
|
);
|
|
453
521
|
console.log(
|
|
454
|
-
` minLines: ${
|
|
522
|
+
` minLines: ${import_chalk3.default.bold(patternDetectConfig.minLines ?? "default")}`
|
|
455
523
|
);
|
|
456
524
|
if (patternDetectConfig.approx !== void 0)
|
|
457
525
|
console.log(
|
|
458
|
-
` approx: ${
|
|
526
|
+
` approx: ${import_chalk3.default.bold(String(patternDetectConfig.approx))}`
|
|
459
527
|
);
|
|
460
528
|
if (patternDetectConfig.minSharedTokens !== void 0)
|
|
461
529
|
console.log(
|
|
462
|
-
` minSharedTokens: ${
|
|
530
|
+
` minSharedTokens: ${import_chalk3.default.bold(String(patternDetectConfig.minSharedTokens))}`
|
|
463
531
|
);
|
|
464
532
|
if (patternDetectConfig.maxCandidatesPerBlock !== void 0)
|
|
465
533
|
console.log(
|
|
466
|
-
` maxCandidatesPerBlock: ${
|
|
534
|
+
` maxCandidatesPerBlock: ${import_chalk3.default.bold(String(patternDetectConfig.maxCandidatesPerBlock))}`
|
|
467
535
|
);
|
|
468
536
|
if (patternDetectConfig.batchSize !== void 0)
|
|
469
537
|
console.log(
|
|
470
|
-
` batchSize: ${
|
|
538
|
+
` batchSize: ${import_chalk3.default.bold(String(patternDetectConfig.batchSize))}`
|
|
471
539
|
);
|
|
472
540
|
if (patternDetectConfig.streamResults !== void 0)
|
|
473
541
|
console.log(
|
|
474
|
-
` streamResults: ${
|
|
542
|
+
` streamResults: ${import_chalk3.default.bold(String(patternDetectConfig.streamResults))}`
|
|
475
543
|
);
|
|
476
544
|
if (patternDetectConfig.severity !== void 0)
|
|
477
545
|
console.log(
|
|
478
|
-
` severity: ${
|
|
546
|
+
` severity: ${import_chalk3.default.bold(String(patternDetectConfig.severity))}`
|
|
479
547
|
);
|
|
480
548
|
if (patternDetectConfig.includeTests !== void 0)
|
|
481
549
|
console.log(
|
|
482
|
-
` includeTests: ${
|
|
550
|
+
` includeTests: ${import_chalk3.default.bold(String(patternDetectConfig.includeTests))}`
|
|
483
551
|
);
|
|
484
552
|
}
|
|
485
553
|
if (finalOptions["context-analyzer"] || finalOptions.maxDepth) {
|
|
@@ -490,57 +558,57 @@ async function scanAction(directory, options) {
|
|
|
490
558
|
maxFragmentation: finalOptions.maxFragmentation,
|
|
491
559
|
includeNodeModules: finalOptions.includeNodeModules
|
|
492
560
|
};
|
|
493
|
-
console.log(
|
|
494
|
-
console.log(` maxDepth: ${
|
|
561
|
+
console.log(import_chalk3.default.white("\nContext-analyzer settings:"));
|
|
562
|
+
console.log(` maxDepth: ${import_chalk3.default.bold(ca.maxDepth ?? "default")}`);
|
|
495
563
|
console.log(
|
|
496
|
-
` maxContextBudget: ${
|
|
564
|
+
` maxContextBudget: ${import_chalk3.default.bold(ca.maxContextBudget ?? "default")}`
|
|
497
565
|
);
|
|
498
566
|
if (ca.minCohesion !== void 0)
|
|
499
|
-
console.log(` minCohesion: ${
|
|
567
|
+
console.log(` minCohesion: ${import_chalk3.default.bold(String(ca.minCohesion))}`);
|
|
500
568
|
if (ca.maxFragmentation !== void 0)
|
|
501
569
|
console.log(
|
|
502
|
-
` maxFragmentation: ${
|
|
570
|
+
` maxFragmentation: ${import_chalk3.default.bold(String(ca.maxFragmentation))}`
|
|
503
571
|
);
|
|
504
572
|
if (ca.includeNodeModules !== void 0)
|
|
505
573
|
console.log(
|
|
506
|
-
` includeNodeModules: ${
|
|
574
|
+
` includeNodeModules: ${import_chalk3.default.bold(String(ca.includeNodeModules))}`
|
|
507
575
|
);
|
|
508
576
|
}
|
|
509
577
|
if (finalOptions.consistency) {
|
|
510
578
|
const c = finalOptions.consistency;
|
|
511
|
-
console.log(
|
|
579
|
+
console.log(import_chalk3.default.white("\nConsistency settings:"));
|
|
512
580
|
console.log(
|
|
513
|
-
` checkNaming: ${
|
|
581
|
+
` checkNaming: ${import_chalk3.default.bold(String(c.checkNaming ?? true))}`
|
|
514
582
|
);
|
|
515
583
|
console.log(
|
|
516
|
-
` checkPatterns: ${
|
|
584
|
+
` checkPatterns: ${import_chalk3.default.bold(String(c.checkPatterns ?? true))}`
|
|
517
585
|
);
|
|
518
586
|
console.log(
|
|
519
|
-
` checkArchitecture: ${
|
|
587
|
+
` checkArchitecture: ${import_chalk3.default.bold(String(c.checkArchitecture ?? false))}`
|
|
520
588
|
);
|
|
521
589
|
if (c.minSeverity)
|
|
522
|
-
console.log(` minSeverity: ${
|
|
590
|
+
console.log(` minSeverity: ${import_chalk3.default.bold(c.minSeverity)}`);
|
|
523
591
|
if (c.acceptedAbbreviations)
|
|
524
592
|
console.log(
|
|
525
|
-
` acceptedAbbreviations: ${
|
|
593
|
+
` acceptedAbbreviations: ${import_chalk3.default.bold(truncateArray(c.acceptedAbbreviations, 8))}`
|
|
526
594
|
);
|
|
527
595
|
if (c.shortWords)
|
|
528
596
|
console.log(
|
|
529
|
-
` shortWords: ${
|
|
597
|
+
` shortWords: ${import_chalk3.default.bold(truncateArray(c.shortWords, 8))}`
|
|
530
598
|
);
|
|
531
599
|
}
|
|
532
|
-
console.log(
|
|
600
|
+
console.log(import_chalk3.default.white("\nStarting analysis..."));
|
|
533
601
|
const progressCallback = (event) => {
|
|
534
|
-
console.log(
|
|
602
|
+
console.log(import_chalk3.default.cyan(`
|
|
535
603
|
--- ${event.tool.toUpperCase()} RESULTS ---`));
|
|
536
604
|
try {
|
|
537
605
|
if (event.tool === "patterns") {
|
|
538
606
|
const pr = event.data;
|
|
539
607
|
console.log(
|
|
540
|
-
` Duplicate patterns: ${
|
|
608
|
+
` Duplicate patterns: ${import_chalk3.default.bold(String(pr.duplicates?.length || 0))}`
|
|
541
609
|
);
|
|
542
610
|
console.log(
|
|
543
|
-
` Files with pattern issues: ${
|
|
611
|
+
` Files with pattern issues: ${import_chalk3.default.bold(String(pr.results?.length || 0))}`
|
|
544
612
|
);
|
|
545
613
|
if (pr.duplicates && pr.duplicates.length > 0) {
|
|
546
614
|
pr.duplicates.slice(0, 5).forEach((d, i) => {
|
|
@@ -562,12 +630,12 @@ async function scanAction(directory, options) {
|
|
|
562
630
|
}
|
|
563
631
|
if (pr.groups && pr.groups.length >= 0) {
|
|
564
632
|
console.log(
|
|
565
|
-
` \u2705 Grouped ${
|
|
633
|
+
` \u2705 Grouped ${import_chalk3.default.bold(String(pr.duplicates?.length || 0))} duplicates into ${import_chalk3.default.bold(String(pr.groups.length))} file pairs`
|
|
566
634
|
);
|
|
567
635
|
}
|
|
568
636
|
if (pr.clusters && pr.clusters.length >= 0) {
|
|
569
637
|
console.log(
|
|
570
|
-
` \u2705 Created ${
|
|
638
|
+
` \u2705 Created ${import_chalk3.default.bold(String(pr.clusters.length))} refactor clusters`
|
|
571
639
|
);
|
|
572
640
|
pr.clusters.slice(0, 3).forEach((cl, idx) => {
|
|
573
641
|
const files = (cl.files || []).map((f) => f.path.split("/").pop()).join(", ");
|
|
@@ -579,7 +647,7 @@ async function scanAction(directory, options) {
|
|
|
579
647
|
} else if (event.tool === "context") {
|
|
580
648
|
const cr = event.data;
|
|
581
649
|
console.log(
|
|
582
|
-
` Context issues found: ${
|
|
650
|
+
` Context issues found: ${import_chalk3.default.bold(String(cr.length || 0))}`
|
|
583
651
|
);
|
|
584
652
|
cr.slice(0, 5).forEach((c, i) => {
|
|
585
653
|
const msg = c.message ? ` - ${c.message}` : "";
|
|
@@ -590,7 +658,7 @@ async function scanAction(directory, options) {
|
|
|
590
658
|
} else if (event.tool === "consistency") {
|
|
591
659
|
const rep = event.data;
|
|
592
660
|
console.log(
|
|
593
|
-
` Consistency totalIssues: ${
|
|
661
|
+
` Consistency totalIssues: ${import_chalk3.default.bold(String(rep.summary?.totalIssues || 0))}`
|
|
594
662
|
);
|
|
595
663
|
if (rep.results && rep.results.length > 0) {
|
|
596
664
|
const fileMap = /* @__PURE__ */ new Map();
|
|
@@ -625,7 +693,7 @@ async function scanAction(directory, options) {
|
|
|
625
693
|
const remaining = files.length - topFiles.length;
|
|
626
694
|
if (remaining > 0) {
|
|
627
695
|
console.log(
|
|
628
|
-
|
|
696
|
+
import_chalk3.default.dim(
|
|
629
697
|
` ... and ${remaining} more files with issues (use --output json for full details)`
|
|
630
698
|
)
|
|
631
699
|
);
|
|
@@ -634,37 +702,37 @@ async function scanAction(directory, options) {
|
|
|
634
702
|
} else if (event.tool === "doc-drift") {
|
|
635
703
|
const dr = event.data;
|
|
636
704
|
console.log(
|
|
637
|
-
` Issues found: ${
|
|
705
|
+
` Issues found: ${import_chalk3.default.bold(String(dr.issues?.length || 0))}`
|
|
638
706
|
);
|
|
639
707
|
if (dr.rawData) {
|
|
640
708
|
console.log(
|
|
641
|
-
` Signature Mismatches: ${
|
|
709
|
+
` Signature Mismatches: ${import_chalk3.default.bold(dr.rawData.outdatedComments || 0)}`
|
|
642
710
|
);
|
|
643
711
|
console.log(
|
|
644
|
-
` Undocumented Complexity: ${
|
|
712
|
+
` Undocumented Complexity: ${import_chalk3.default.bold(dr.rawData.undocumentedComplexity || 0)}`
|
|
645
713
|
);
|
|
646
714
|
}
|
|
647
715
|
} else if (event.tool === "deps-health") {
|
|
648
716
|
const dr = event.data;
|
|
649
717
|
console.log(
|
|
650
|
-
` Packages Analyzed: ${
|
|
718
|
+
` Packages Analyzed: ${import_chalk3.default.bold(String(dr.summary?.packagesAnalyzed || 0))}`
|
|
651
719
|
);
|
|
652
720
|
if (dr.rawData) {
|
|
653
721
|
console.log(
|
|
654
|
-
` Deprecated Packages: ${
|
|
722
|
+
` Deprecated Packages: ${import_chalk3.default.bold(dr.rawData.deprecatedPackages || 0)}`
|
|
655
723
|
);
|
|
656
724
|
console.log(
|
|
657
|
-
` AI Cutoff Skew Score: ${
|
|
725
|
+
` AI Cutoff Skew Score: ${import_chalk3.default.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`
|
|
658
726
|
);
|
|
659
727
|
}
|
|
660
728
|
} else if (event.tool === "change-amplification" || event.tool === "changeAmplification") {
|
|
661
729
|
const dr = event.data;
|
|
662
730
|
console.log(
|
|
663
|
-
` Coupling issues: ${
|
|
731
|
+
` Coupling issues: ${import_chalk3.default.bold(String(dr.issues?.length || 0))}`
|
|
664
732
|
);
|
|
665
733
|
if (dr.summary) {
|
|
666
734
|
console.log(
|
|
667
|
-
` Complexity Score: ${
|
|
735
|
+
` Complexity Score: ${import_chalk3.default.bold(dr.summary.score || 0)}/100`
|
|
668
736
|
);
|
|
669
737
|
}
|
|
670
738
|
}
|
|
@@ -685,36 +753,36 @@ async function scanAction(directory, options) {
|
|
|
685
753
|
},
|
|
686
754
|
suppressToolConfig: true
|
|
687
755
|
});
|
|
688
|
-
console.log(
|
|
756
|
+
console.log(import_chalk3.default.cyan("\n=== AIReady Run Summary ==="));
|
|
689
757
|
console.log(
|
|
690
|
-
|
|
758
|
+
import_chalk3.default.white("Tools run:"),
|
|
691
759
|
(finalOptions.tools || ["patterns", "context", "consistency"]).join(", ")
|
|
692
760
|
);
|
|
693
|
-
console.log(
|
|
761
|
+
console.log(import_chalk3.default.cyan("\nResults summary:"));
|
|
694
762
|
console.log(
|
|
695
|
-
` Total issues (all tools): ${
|
|
763
|
+
` Total issues (all tools): ${import_chalk3.default.bold(String(results.summary.totalIssues || 0))}`
|
|
696
764
|
);
|
|
697
765
|
if (results.duplicates)
|
|
698
766
|
console.log(
|
|
699
|
-
` Duplicate patterns found: ${
|
|
767
|
+
` Duplicate patterns found: ${import_chalk3.default.bold(String(results.duplicates.length || 0))}`
|
|
700
768
|
);
|
|
701
769
|
if (results.patterns)
|
|
702
770
|
console.log(
|
|
703
|
-
` Pattern files with issues: ${
|
|
771
|
+
` Pattern files with issues: ${import_chalk3.default.bold(String(results.patterns.length || 0))}`
|
|
704
772
|
);
|
|
705
773
|
if (results.context)
|
|
706
774
|
console.log(
|
|
707
|
-
` Context issues: ${
|
|
775
|
+
` Context issues: ${import_chalk3.default.bold(String(results.context.length || 0))}`
|
|
708
776
|
);
|
|
709
777
|
console.log(
|
|
710
|
-
` Consistency issues: ${
|
|
778
|
+
` Consistency issues: ${import_chalk3.default.bold(String(results.consistency?.summary?.totalIssues || 0))}`
|
|
711
779
|
);
|
|
712
780
|
if (results.changeAmplification)
|
|
713
781
|
console.log(
|
|
714
|
-
` Change amplification: ${
|
|
782
|
+
` Change amplification: ${import_chalk3.default.bold(String(results.changeAmplification.summary?.score || 0))}/100`
|
|
715
783
|
);
|
|
716
|
-
console.log(
|
|
717
|
-
const elapsedTime = (0,
|
|
784
|
+
console.log(import_chalk3.default.cyan("===========================\n"));
|
|
785
|
+
const elapsedTime = (0, import_core2.getElapsedTime)(startTime);
|
|
718
786
|
void elapsedTime;
|
|
719
787
|
let scoringResult;
|
|
720
788
|
if (options.score || finalOptions.scoring?.showBreakdown) {
|
|
@@ -726,6 +794,16 @@ async function scanAction(directory, options) {
|
|
|
726
794
|
results.duplicates,
|
|
727
795
|
results.patterns?.length || 0
|
|
728
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
|
+
});
|
|
729
807
|
toolScores.set("pattern-detect", patternScore);
|
|
730
808
|
} catch (err) {
|
|
731
809
|
void err;
|
|
@@ -736,6 +814,14 @@ async function scanAction(directory, options) {
|
|
|
736
814
|
try {
|
|
737
815
|
const ctxSummary = genContextSummary(results.context);
|
|
738
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
|
+
});
|
|
739
825
|
toolScores.set("context-analyzer", contextScore);
|
|
740
826
|
} catch (err) {
|
|
741
827
|
void err;
|
|
@@ -827,19 +913,19 @@ async function scanAction(directory, options) {
|
|
|
827
913
|
}))
|
|
828
914
|
});
|
|
829
915
|
}
|
|
830
|
-
const cliWeights = (0,
|
|
916
|
+
const cliWeights = (0, import_core2.parseWeightString)(options.weights);
|
|
831
917
|
if (toolScores.size > 0) {
|
|
832
|
-
scoringResult = (0,
|
|
918
|
+
scoringResult = (0, import_core2.calculateOverallScore)(
|
|
833
919
|
toolScores,
|
|
834
920
|
finalOptions,
|
|
835
921
|
cliWeights.size ? cliWeights : void 0
|
|
836
922
|
);
|
|
837
|
-
console.log(
|
|
838
|
-
console.log(` ${(0,
|
|
923
|
+
console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
|
|
924
|
+
console.log(` ${(0, import_core2.formatScore)(scoringResult)}`);
|
|
839
925
|
if (options.compareTo) {
|
|
840
926
|
try {
|
|
841
|
-
const prevReportStr = (0,
|
|
842
|
-
(0,
|
|
927
|
+
const prevReportStr = (0, import_fs3.readFileSync)(
|
|
928
|
+
(0, import_path3.resolve)(process.cwd(), options.compareTo),
|
|
843
929
|
"utf8"
|
|
844
930
|
);
|
|
845
931
|
const prevReport = JSON.parse(prevReportStr);
|
|
@@ -850,19 +936,19 @@ async function scanAction(directory, options) {
|
|
|
850
936
|
console.log();
|
|
851
937
|
if (diff > 0) {
|
|
852
938
|
console.log(
|
|
853
|
-
|
|
939
|
+
import_chalk3.default.green(
|
|
854
940
|
` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
|
|
855
941
|
)
|
|
856
942
|
);
|
|
857
943
|
} else if (diff < 0) {
|
|
858
944
|
console.log(
|
|
859
|
-
|
|
945
|
+
import_chalk3.default.red(
|
|
860
946
|
` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
|
|
861
947
|
)
|
|
862
948
|
);
|
|
863
949
|
} else {
|
|
864
950
|
console.log(
|
|
865
|
-
|
|
951
|
+
import_chalk3.default.blue(
|
|
866
952
|
` \u2796 Trend: No change compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
|
|
867
953
|
)
|
|
868
954
|
);
|
|
@@ -873,7 +959,7 @@ async function scanAction(directory, options) {
|
|
|
873
959
|
};
|
|
874
960
|
} else {
|
|
875
961
|
console.log(
|
|
876
|
-
|
|
962
|
+
import_chalk3.default.yellow(
|
|
877
963
|
`
|
|
878
964
|
\u26A0\uFE0F Previous report at ${options.compareTo} does not contain an overall score.`
|
|
879
965
|
)
|
|
@@ -882,27 +968,61 @@ async function scanAction(directory, options) {
|
|
|
882
968
|
} catch (e) {
|
|
883
969
|
void e;
|
|
884
970
|
console.log(
|
|
885
|
-
|
|
971
|
+
import_chalk3.default.yellow(
|
|
886
972
|
`
|
|
887
973
|
\u26A0\uFE0F Could not read or parse previous report at ${options.compareTo}.`
|
|
888
974
|
)
|
|
889
975
|
);
|
|
890
976
|
}
|
|
891
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
|
+
}
|
|
892
1012
|
if (scoringResult.breakdown && scoringResult.breakdown.length > 0) {
|
|
893
|
-
console.log(
|
|
1013
|
+
console.log(import_chalk3.default.bold("\nTool breakdown:"));
|
|
894
1014
|
scoringResult.breakdown.forEach((tool) => {
|
|
895
|
-
const rating = (0,
|
|
896
|
-
const rd = (0,
|
|
1015
|
+
const rating = (0, import_core2.getRating)(tool.score);
|
|
1016
|
+
const rd = (0, import_core2.getRatingDisplay)(rating);
|
|
897
1017
|
console.log(
|
|
898
1018
|
` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${rd.emoji}`
|
|
899
1019
|
);
|
|
900
1020
|
});
|
|
901
1021
|
console.log();
|
|
902
1022
|
if (finalOptions.scoring?.showBreakdown) {
|
|
903
|
-
console.log(
|
|
1023
|
+
console.log(import_chalk3.default.bold("Detailed tool breakdown:"));
|
|
904
1024
|
scoringResult.breakdown.forEach((tool) => {
|
|
905
|
-
console.log((0,
|
|
1025
|
+
console.log((0, import_core2.formatToolScore)(tool));
|
|
906
1026
|
});
|
|
907
1027
|
console.log();
|
|
908
1028
|
}
|
|
@@ -914,30 +1034,52 @@ async function scanAction(directory, options) {
|
|
|
914
1034
|
if (outputFormat === "json") {
|
|
915
1035
|
const timestamp = getReportTimestamp();
|
|
916
1036
|
const defaultFilename = `aiready-report-${timestamp}.json`;
|
|
917
|
-
const outputPath = (0,
|
|
1037
|
+
const outputPath = (0, import_core2.resolveOutputPath)(
|
|
918
1038
|
userOutputFile,
|
|
919
1039
|
defaultFilename,
|
|
920
1040
|
resolvedDir
|
|
921
1041
|
);
|
|
922
|
-
const outputData = {
|
|
923
|
-
|
|
1042
|
+
const outputData = {
|
|
1043
|
+
...results,
|
|
1044
|
+
scoring: scoringResult,
|
|
1045
|
+
repository: repoMetadata
|
|
1046
|
+
};
|
|
1047
|
+
(0, import_core2.handleJSONOutput)(
|
|
924
1048
|
outputData,
|
|
925
1049
|
outputPath,
|
|
926
1050
|
`\u2705 Report saved to ${outputPath}`
|
|
927
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
|
+
}
|
|
928
1059
|
await warnIfGraphCapExceeded(outputData, resolvedDir);
|
|
929
1060
|
} else {
|
|
930
1061
|
const timestamp = getReportTimestamp();
|
|
931
1062
|
const defaultFilename = `aiready-report-${timestamp}.json`;
|
|
932
|
-
const outputPath = (0,
|
|
1063
|
+
const outputPath = (0, import_core2.resolveOutputPath)(
|
|
933
1064
|
userOutputFile,
|
|
934
1065
|
defaultFilename,
|
|
935
1066
|
resolvedDir
|
|
936
1067
|
);
|
|
937
|
-
const outputData = {
|
|
1068
|
+
const outputData = {
|
|
1069
|
+
...results,
|
|
1070
|
+
scoring: scoringResult,
|
|
1071
|
+
repository: repoMetadata
|
|
1072
|
+
};
|
|
938
1073
|
try {
|
|
939
|
-
(0,
|
|
940
|
-
console.log(
|
|
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
|
+
}
|
|
941
1083
|
await warnIfGraphCapExceeded(outputData, resolvedDir);
|
|
942
1084
|
} catch (err) {
|
|
943
1085
|
void err;
|
|
@@ -1019,37 +1161,37 @@ async function scanAction(directory, options) {
|
|
|
1019
1161
|
}
|
|
1020
1162
|
}
|
|
1021
1163
|
if (shouldFail) {
|
|
1022
|
-
console.log(
|
|
1023
|
-
console.log(
|
|
1024
|
-
console.log(
|
|
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:"));
|
|
1025
1167
|
console.log(
|
|
1026
|
-
|
|
1168
|
+
import_chalk3.default.dim(" 1. Run `aiready scan` locally to see detailed issues")
|
|
1027
1169
|
);
|
|
1028
|
-
console.log(
|
|
1170
|
+
console.log(import_chalk3.default.dim(" 2. Fix the critical issues before merging"));
|
|
1029
1171
|
console.log(
|
|
1030
|
-
|
|
1172
|
+
import_chalk3.default.dim(
|
|
1031
1173
|
" 3. Consider upgrading to Team plan for historical tracking: https://getaiready.dev/pricing"
|
|
1032
1174
|
)
|
|
1033
1175
|
);
|
|
1034
1176
|
process.exit(1);
|
|
1035
1177
|
} else {
|
|
1036
|
-
console.log(
|
|
1178
|
+
console.log(import_chalk3.default.green("\n\u2705 PR PASSED: AI Readiness Check"));
|
|
1037
1179
|
if (threshold) {
|
|
1038
1180
|
console.log(
|
|
1039
|
-
|
|
1181
|
+
import_chalk3.default.green(
|
|
1040
1182
|
` Score: ${scoringResult.overall}/100 (threshold: ${threshold})`
|
|
1041
1183
|
)
|
|
1042
1184
|
);
|
|
1043
1185
|
}
|
|
1044
1186
|
console.log(
|
|
1045
|
-
|
|
1187
|
+
import_chalk3.default.dim(
|
|
1046
1188
|
"\n \u{1F4A1} Track historical trends: https://getaiready.dev \u2014 Team plan $99/mo"
|
|
1047
1189
|
)
|
|
1048
1190
|
);
|
|
1049
1191
|
}
|
|
1050
1192
|
}
|
|
1051
1193
|
} catch (error) {
|
|
1052
|
-
(0,
|
|
1194
|
+
(0, import_core2.handleCLIError)(error, "Analysis");
|
|
1053
1195
|
}
|
|
1054
1196
|
}
|
|
1055
1197
|
var scanHelpText = `
|
|
@@ -1063,6 +1205,8 @@ EXAMPLES:
|
|
|
1063
1205
|
$ aiready scan --ci --threshold 70 # GitHub Actions gatekeeper
|
|
1064
1206
|
$ aiready scan --ci --fail-on major # Fail on major+ issues
|
|
1065
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
|
|
1066
1210
|
|
|
1067
1211
|
PROFILES:
|
|
1068
1212
|
agentic: aiSignalClarity, grounding, testability
|
|
@@ -1082,13 +1226,13 @@ CI/CD INTEGRATION (Gatekeeper Mode):
|
|
|
1082
1226
|
`;
|
|
1083
1227
|
|
|
1084
1228
|
// src/commands/patterns.ts
|
|
1085
|
-
var
|
|
1086
|
-
var
|
|
1087
|
-
var
|
|
1229
|
+
var import_chalk4 = __toESM(require("chalk"));
|
|
1230
|
+
var import_path4 = require("path");
|
|
1231
|
+
var import_core3 = require("@aiready/core");
|
|
1088
1232
|
async function patternsAction(directory, options) {
|
|
1089
|
-
console.log(
|
|
1233
|
+
console.log(import_chalk4.default.blue("\u{1F50D} Analyzing patterns...\n"));
|
|
1090
1234
|
const startTime = Date.now();
|
|
1091
|
-
const resolvedDir = (0,
|
|
1235
|
+
const resolvedDir = (0, import_path4.resolve)(process.cwd(), directory || ".");
|
|
1092
1236
|
try {
|
|
1093
1237
|
const useSmartDefaults = !options.fullScan;
|
|
1094
1238
|
const defaults = {
|
|
@@ -1117,14 +1261,14 @@ async function patternsAction(directory, options) {
|
|
|
1117
1261
|
if (options.minSharedTokens) {
|
|
1118
1262
|
cliOptions.minSharedTokens = parseInt(options.minSharedTokens);
|
|
1119
1263
|
}
|
|
1120
|
-
const finalOptions = await (0,
|
|
1264
|
+
const finalOptions = await (0, import_core3.loadMergedConfig)(
|
|
1121
1265
|
resolvedDir,
|
|
1122
1266
|
defaults,
|
|
1123
1267
|
cliOptions
|
|
1124
1268
|
);
|
|
1125
1269
|
const { analyzePatterns: analyzePatterns2, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
|
|
1126
1270
|
const { results, duplicates } = await analyzePatterns2(finalOptions);
|
|
1127
|
-
const elapsedTime = (0,
|
|
1271
|
+
const elapsedTime = (0, import_core3.getElapsedTime)(startTime);
|
|
1128
1272
|
const summary = generateSummary(results);
|
|
1129
1273
|
let patternScore;
|
|
1130
1274
|
if (options.score) {
|
|
@@ -1138,12 +1282,12 @@ async function patternsAction(directory, options) {
|
|
|
1138
1282
|
summary: { ...summary, executionTime: parseFloat(elapsedTime) },
|
|
1139
1283
|
...patternScore && { scoring: patternScore }
|
|
1140
1284
|
};
|
|
1141
|
-
const outputPath = (0,
|
|
1285
|
+
const outputPath = (0, import_core3.resolveOutputPath)(
|
|
1142
1286
|
userOutputFile,
|
|
1143
1287
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
1144
1288
|
resolvedDir
|
|
1145
1289
|
);
|
|
1146
|
-
(0,
|
|
1290
|
+
(0, import_core3.handleJSONOutput)(
|
|
1147
1291
|
outputData,
|
|
1148
1292
|
outputPath,
|
|
1149
1293
|
`\u2705 Results saved to ${outputPath}`
|
|
@@ -1152,38 +1296,38 @@ async function patternsAction(directory, options) {
|
|
|
1152
1296
|
const terminalWidth = process.stdout.columns || 80;
|
|
1153
1297
|
const dividerWidth = Math.min(60, terminalWidth - 2);
|
|
1154
1298
|
const divider = "\u2501".repeat(dividerWidth);
|
|
1155
|
-
console.log(
|
|
1156
|
-
console.log(
|
|
1157
|
-
console.log(
|
|
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");
|
|
1158
1302
|
console.log(
|
|
1159
|
-
|
|
1303
|
+
import_chalk4.default.white(`\u{1F4C1} Files analyzed: ${import_chalk4.default.bold(results.length)}`)
|
|
1160
1304
|
);
|
|
1161
1305
|
console.log(
|
|
1162
|
-
|
|
1163
|
-
`\u26A0 Duplicate patterns found: ${
|
|
1306
|
+
import_chalk4.default.yellow(
|
|
1307
|
+
`\u26A0 Duplicate patterns found: ${import_chalk4.default.bold(summary.totalPatterns)}`
|
|
1164
1308
|
)
|
|
1165
1309
|
);
|
|
1166
1310
|
console.log(
|
|
1167
|
-
|
|
1168
|
-
`\u{1F4B0} Token cost (wasted): ${
|
|
1311
|
+
import_chalk4.default.red(
|
|
1312
|
+
`\u{1F4B0} Token cost (wasted): ${import_chalk4.default.bold(summary.totalTokenCost.toLocaleString())}`
|
|
1169
1313
|
)
|
|
1170
1314
|
);
|
|
1171
1315
|
console.log(
|
|
1172
|
-
|
|
1316
|
+
import_chalk4.default.gray(`\u23F1 Analysis time: ${import_chalk4.default.bold(elapsedTime + "s")}`)
|
|
1173
1317
|
);
|
|
1174
1318
|
const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
|
|
1175
1319
|
if (sortedTypes.length > 0) {
|
|
1176
|
-
console.log(
|
|
1177
|
-
console.log(
|
|
1178
|
-
console.log(
|
|
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");
|
|
1179
1323
|
sortedTypes.forEach(([type, count]) => {
|
|
1180
|
-
console.log(` ${
|
|
1324
|
+
console.log(` ${import_chalk4.default.white(type.padEnd(15))} ${import_chalk4.default.bold(count)}`);
|
|
1181
1325
|
});
|
|
1182
1326
|
}
|
|
1183
1327
|
if (summary.totalPatterns > 0 && duplicates.length > 0) {
|
|
1184
|
-
console.log(
|
|
1185
|
-
console.log(
|
|
1186
|
-
console.log(
|
|
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");
|
|
1187
1331
|
const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
|
|
1188
1332
|
topDuplicates.forEach((dup) => {
|
|
1189
1333
|
const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
|
|
@@ -1191,31 +1335,31 @@ async function patternsAction(directory, options) {
|
|
|
1191
1335
|
const file1Name = dup.file1.split("/").pop() || dup.file1;
|
|
1192
1336
|
const file2Name = dup.file2.split("/").pop() || dup.file2;
|
|
1193
1337
|
console.log(
|
|
1194
|
-
`${severityIcon} ${severity}: ${
|
|
1338
|
+
`${severityIcon} ${severity}: ${import_chalk4.default.bold(file1Name)} \u2194 ${import_chalk4.default.bold(file2Name)}`
|
|
1195
1339
|
);
|
|
1196
1340
|
console.log(
|
|
1197
|
-
` Similarity: ${
|
|
1341
|
+
` Similarity: ${import_chalk4.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk4.default.bold(dup.tokenCost.toLocaleString())} tokens each`
|
|
1198
1342
|
);
|
|
1199
1343
|
console.log(
|
|
1200
|
-
` Lines: ${
|
|
1344
|
+
` Lines: ${import_chalk4.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk4.default.cyan(dup.line2 + "-" + dup.endLine2)}
|
|
1201
1345
|
`
|
|
1202
1346
|
);
|
|
1203
1347
|
});
|
|
1204
1348
|
} else {
|
|
1205
1349
|
console.log(
|
|
1206
|
-
|
|
1350
|
+
import_chalk4.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
|
|
1207
1351
|
);
|
|
1208
1352
|
}
|
|
1209
1353
|
if (patternScore) {
|
|
1210
|
-
console.log(
|
|
1211
|
-
console.log(
|
|
1212
|
-
console.log(
|
|
1213
|
-
console.log((0,
|
|
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));
|
|
1214
1358
|
console.log();
|
|
1215
1359
|
}
|
|
1216
1360
|
}
|
|
1217
1361
|
} catch (error) {
|
|
1218
|
-
(0,
|
|
1362
|
+
(0, import_core3.handleCLIError)(error, "Pattern analysis");
|
|
1219
1363
|
}
|
|
1220
1364
|
}
|
|
1221
1365
|
var patternsHelpText = `
|
|
@@ -1226,13 +1370,13 @@ EXAMPLES:
|
|
|
1226
1370
|
`;
|
|
1227
1371
|
|
|
1228
1372
|
// src/commands/context.ts
|
|
1229
|
-
var
|
|
1230
|
-
var
|
|
1231
|
-
var
|
|
1373
|
+
var import_chalk5 = __toESM(require("chalk"));
|
|
1374
|
+
var import_path5 = require("path");
|
|
1375
|
+
var import_core4 = require("@aiready/core");
|
|
1232
1376
|
async function contextAction(directory, options) {
|
|
1233
|
-
console.log(
|
|
1377
|
+
console.log(import_chalk5.default.blue("\u{1F9E0} Analyzing context costs...\n"));
|
|
1234
1378
|
const startTime = Date.now();
|
|
1235
|
-
const resolvedDir = (0,
|
|
1379
|
+
const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
|
|
1236
1380
|
try {
|
|
1237
1381
|
const defaults = {
|
|
1238
1382
|
maxDepth: 5,
|
|
@@ -1244,7 +1388,7 @@ async function contextAction(directory, options) {
|
|
|
1244
1388
|
file: void 0
|
|
1245
1389
|
}
|
|
1246
1390
|
};
|
|
1247
|
-
const baseOptions = await (0,
|
|
1391
|
+
const baseOptions = await (0, import_core4.loadMergedConfig)(resolvedDir, defaults, {
|
|
1248
1392
|
maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
|
|
1249
1393
|
maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
|
|
1250
1394
|
include: options.include?.split(","),
|
|
@@ -1270,7 +1414,7 @@ async function contextAction(directory, options) {
|
|
|
1270
1414
|
console.log("");
|
|
1271
1415
|
const { analyzeContext: analyzeContext2, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
|
|
1272
1416
|
const results = await analyzeContext2(finalOptions);
|
|
1273
|
-
const elapsedTime = (0,
|
|
1417
|
+
const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
|
|
1274
1418
|
const summary = generateSummary(results);
|
|
1275
1419
|
let contextScore;
|
|
1276
1420
|
if (options.score) {
|
|
@@ -1284,12 +1428,12 @@ async function contextAction(directory, options) {
|
|
|
1284
1428
|
summary: { ...summary, executionTime: parseFloat(elapsedTime) },
|
|
1285
1429
|
...contextScore && { scoring: contextScore }
|
|
1286
1430
|
};
|
|
1287
|
-
const outputPath = (0,
|
|
1431
|
+
const outputPath = (0, import_core4.resolveOutputPath)(
|
|
1288
1432
|
userOutputFile,
|
|
1289
1433
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
1290
1434
|
resolvedDir
|
|
1291
1435
|
);
|
|
1292
|
-
(0,
|
|
1436
|
+
(0, import_core4.handleJSONOutput)(
|
|
1293
1437
|
outputData,
|
|
1294
1438
|
outputPath,
|
|
1295
1439
|
`\u2705 Results saved to ${outputPath}`
|
|
@@ -1298,85 +1442,85 @@ async function contextAction(directory, options) {
|
|
|
1298
1442
|
const terminalWidth = process.stdout.columns || 80;
|
|
1299
1443
|
const dividerWidth = Math.min(60, terminalWidth - 2);
|
|
1300
1444
|
const divider = "\u2501".repeat(dividerWidth);
|
|
1301
|
-
console.log(
|
|
1302
|
-
console.log(
|
|
1303
|
-
console.log(
|
|
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");
|
|
1304
1448
|
console.log(
|
|
1305
|
-
|
|
1449
|
+
import_chalk5.default.white(`\u{1F4C1} Files analyzed: ${import_chalk5.default.bold(summary.totalFiles)}`)
|
|
1306
1450
|
);
|
|
1307
1451
|
console.log(
|
|
1308
|
-
|
|
1309
|
-
`\u{1F4CA} Total tokens: ${
|
|
1452
|
+
import_chalk5.default.white(
|
|
1453
|
+
`\u{1F4CA} Total tokens: ${import_chalk5.default.bold(summary.totalTokens.toLocaleString())}`
|
|
1310
1454
|
)
|
|
1311
1455
|
);
|
|
1312
1456
|
console.log(
|
|
1313
|
-
|
|
1314
|
-
`\u{1F4B0} Avg context budget: ${
|
|
1457
|
+
import_chalk5.default.yellow(
|
|
1458
|
+
`\u{1F4B0} Avg context budget: ${import_chalk5.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
|
|
1315
1459
|
)
|
|
1316
1460
|
);
|
|
1317
1461
|
console.log(
|
|
1318
|
-
|
|
1462
|
+
import_chalk5.default.white(`\u23F1 Analysis time: ${import_chalk5.default.bold(elapsedTime + "s")}
|
|
1319
1463
|
`)
|
|
1320
1464
|
);
|
|
1321
1465
|
const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
|
|
1322
1466
|
if (totalIssues > 0) {
|
|
1323
|
-
console.log(
|
|
1467
|
+
console.log(import_chalk5.default.bold("\u26A0\uFE0F Issues Found:\n"));
|
|
1324
1468
|
if (summary.criticalIssues > 0) {
|
|
1325
1469
|
console.log(
|
|
1326
|
-
|
|
1470
|
+
import_chalk5.default.red(` \u{1F534} Critical: ${import_chalk5.default.bold(summary.criticalIssues)}`)
|
|
1327
1471
|
);
|
|
1328
1472
|
}
|
|
1329
1473
|
if (summary.majorIssues > 0) {
|
|
1330
1474
|
console.log(
|
|
1331
|
-
|
|
1475
|
+
import_chalk5.default.yellow(` \u{1F7E1} Major: ${import_chalk5.default.bold(summary.majorIssues)}`)
|
|
1332
1476
|
);
|
|
1333
1477
|
}
|
|
1334
1478
|
if (summary.minorIssues > 0) {
|
|
1335
1479
|
console.log(
|
|
1336
|
-
|
|
1480
|
+
import_chalk5.default.blue(` \u{1F535} Minor: ${import_chalk5.default.bold(summary.minorIssues)}`)
|
|
1337
1481
|
);
|
|
1338
1482
|
}
|
|
1339
1483
|
console.log(
|
|
1340
|
-
|
|
1484
|
+
import_chalk5.default.green(
|
|
1341
1485
|
`
|
|
1342
|
-
\u{1F4A1} Potential savings: ${
|
|
1486
|
+
\u{1F4A1} Potential savings: ${import_chalk5.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
|
|
1343
1487
|
`
|
|
1344
1488
|
)
|
|
1345
1489
|
);
|
|
1346
1490
|
} else {
|
|
1347
|
-
console.log(
|
|
1491
|
+
console.log(import_chalk5.default.green("\u2705 No significant issues found!\n"));
|
|
1348
1492
|
}
|
|
1349
1493
|
if (summary.deepFiles.length > 0) {
|
|
1350
|
-
console.log(
|
|
1494
|
+
console.log(import_chalk5.default.bold("\u{1F4CF} Deep Import Chains:\n"));
|
|
1351
1495
|
console.log(
|
|
1352
|
-
|
|
1496
|
+
import_chalk5.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
|
|
1353
1497
|
);
|
|
1354
1498
|
console.log(
|
|
1355
|
-
|
|
1499
|
+
import_chalk5.default.gray(` Maximum depth: ${summary.maxImportDepth}
|
|
1356
1500
|
`)
|
|
1357
1501
|
);
|
|
1358
1502
|
summary.deepFiles.slice(0, 10).forEach((item) => {
|
|
1359
1503
|
const fileName = item.file.split("/").slice(-2).join("/");
|
|
1360
1504
|
console.log(
|
|
1361
|
-
` ${
|
|
1505
|
+
` ${import_chalk5.default.cyan("\u2192")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(depth: ${item.depth})`)}`
|
|
1362
1506
|
);
|
|
1363
1507
|
});
|
|
1364
1508
|
console.log();
|
|
1365
1509
|
}
|
|
1366
1510
|
if (summary.fragmentedModules.length > 0) {
|
|
1367
|
-
console.log(
|
|
1511
|
+
console.log(import_chalk5.default.bold("\u{1F9E9} Fragmented Modules:\n"));
|
|
1368
1512
|
console.log(
|
|
1369
|
-
|
|
1513
|
+
import_chalk5.default.gray(
|
|
1370
1514
|
` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
|
|
1371
1515
|
`
|
|
1372
1516
|
)
|
|
1373
1517
|
);
|
|
1374
1518
|
summary.fragmentedModules.slice(0, 10).forEach((module2) => {
|
|
1375
1519
|
console.log(
|
|
1376
|
-
` ${
|
|
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`)}`
|
|
1377
1521
|
);
|
|
1378
1522
|
console.log(
|
|
1379
|
-
|
|
1523
|
+
import_chalk5.default.dim(
|
|
1380
1524
|
` Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`
|
|
1381
1525
|
)
|
|
1382
1526
|
);
|
|
@@ -1384,9 +1528,9 @@ async function contextAction(directory, options) {
|
|
|
1384
1528
|
console.log();
|
|
1385
1529
|
}
|
|
1386
1530
|
if (summary.lowCohesionFiles.length > 0) {
|
|
1387
|
-
console.log(
|
|
1531
|
+
console.log(import_chalk5.default.bold("\u{1F500} Low Cohesion Files:\n"));
|
|
1388
1532
|
console.log(
|
|
1389
|
-
|
|
1533
|
+
import_chalk5.default.gray(
|
|
1390
1534
|
` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
|
|
1391
1535
|
`
|
|
1392
1536
|
)
|
|
@@ -1394,46 +1538,46 @@ async function contextAction(directory, options) {
|
|
|
1394
1538
|
summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
|
|
1395
1539
|
const fileName = item.file.split("/").slice(-2).join("/");
|
|
1396
1540
|
const scorePercent = (item.score * 100).toFixed(0);
|
|
1397
|
-
const color = item.score < 0.4 ?
|
|
1541
|
+
const color = item.score < 0.4 ? import_chalk5.default.red : import_chalk5.default.yellow;
|
|
1398
1542
|
console.log(
|
|
1399
|
-
` ${color("\u25CB")} ${
|
|
1543
|
+
` ${color("\u25CB")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${scorePercent}% cohesion)`)}`
|
|
1400
1544
|
);
|
|
1401
1545
|
});
|
|
1402
1546
|
console.log();
|
|
1403
1547
|
}
|
|
1404
1548
|
if (summary.topExpensiveFiles.length > 0) {
|
|
1405
|
-
console.log(
|
|
1549
|
+
console.log(import_chalk5.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
|
|
1406
1550
|
summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
|
|
1407
1551
|
const fileName = item.file.split("/").slice(-2).join("/");
|
|
1408
|
-
const severityColor = item.severity === "critical" ?
|
|
1552
|
+
const severityColor = item.severity === "critical" ? import_chalk5.default.red : item.severity === "major" ? import_chalk5.default.yellow : import_chalk5.default.blue;
|
|
1409
1553
|
console.log(
|
|
1410
|
-
` ${severityColor("\u25CF")} ${
|
|
1554
|
+
` ${severityColor("\u25CF")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
|
|
1411
1555
|
);
|
|
1412
1556
|
});
|
|
1413
1557
|
console.log();
|
|
1414
1558
|
}
|
|
1415
1559
|
if (contextScore) {
|
|
1416
|
-
console.log(
|
|
1417
|
-
console.log(
|
|
1418
|
-
console.log(
|
|
1419
|
-
console.log((0,
|
|
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));
|
|
1420
1564
|
console.log();
|
|
1421
1565
|
}
|
|
1422
1566
|
}
|
|
1423
1567
|
} catch (error) {
|
|
1424
|
-
(0,
|
|
1568
|
+
(0, import_core4.handleCLIError)(error, "Context analysis");
|
|
1425
1569
|
}
|
|
1426
1570
|
}
|
|
1427
1571
|
|
|
1428
1572
|
// src/commands/consistency.ts
|
|
1429
|
-
var
|
|
1430
|
-
var
|
|
1431
|
-
var
|
|
1432
|
-
var
|
|
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");
|
|
1433
1577
|
async function consistencyAction(directory, options) {
|
|
1434
|
-
console.log(
|
|
1578
|
+
console.log(import_chalk6.default.blue("\u{1F50D} Analyzing consistency...\n"));
|
|
1435
1579
|
const startTime = Date.now();
|
|
1436
|
-
const resolvedDir = (0,
|
|
1580
|
+
const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory || ".");
|
|
1437
1581
|
try {
|
|
1438
1582
|
const defaults = {
|
|
1439
1583
|
checkNaming: true,
|
|
@@ -1446,7 +1590,7 @@ async function consistencyAction(directory, options) {
|
|
|
1446
1590
|
file: void 0
|
|
1447
1591
|
}
|
|
1448
1592
|
};
|
|
1449
|
-
const finalOptions = await (0,
|
|
1593
|
+
const finalOptions = await (0, import_core5.loadMergedConfig)(resolvedDir, defaults, {
|
|
1450
1594
|
checkNaming: options.naming !== false,
|
|
1451
1595
|
checkPatterns: options.patterns !== false,
|
|
1452
1596
|
minSeverity: options.minSeverity,
|
|
@@ -1455,7 +1599,7 @@ async function consistencyAction(directory, options) {
|
|
|
1455
1599
|
});
|
|
1456
1600
|
const { analyzeConsistency: analyzeConsistency2, calculateConsistencyScore } = await import("@aiready/consistency");
|
|
1457
1601
|
const report = await analyzeConsistency2(finalOptions);
|
|
1458
|
-
const elapsedTime = (0,
|
|
1602
|
+
const elapsedTime = (0, import_core5.getElapsedTime)(startTime);
|
|
1459
1603
|
let consistencyScore;
|
|
1460
1604
|
if (options.score) {
|
|
1461
1605
|
const issues = report.results?.flatMap((r) => r.issues) || [];
|
|
@@ -1475,41 +1619,41 @@ async function consistencyAction(directory, options) {
|
|
|
1475
1619
|
},
|
|
1476
1620
|
...consistencyScore && { scoring: consistencyScore }
|
|
1477
1621
|
};
|
|
1478
|
-
const outputPath = (0,
|
|
1622
|
+
const outputPath = (0, import_core5.resolveOutputPath)(
|
|
1479
1623
|
userOutputFile,
|
|
1480
1624
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
1481
1625
|
resolvedDir
|
|
1482
1626
|
);
|
|
1483
|
-
(0,
|
|
1627
|
+
(0, import_core5.handleJSONOutput)(
|
|
1484
1628
|
outputData,
|
|
1485
1629
|
outputPath,
|
|
1486
1630
|
`\u2705 Results saved to ${outputPath}`
|
|
1487
1631
|
);
|
|
1488
1632
|
} else if (outputFormat === "markdown") {
|
|
1489
1633
|
const markdown = generateMarkdownReport(report, elapsedTime);
|
|
1490
|
-
const outputPath = (0,
|
|
1634
|
+
const outputPath = (0, import_core5.resolveOutputPath)(
|
|
1491
1635
|
userOutputFile,
|
|
1492
1636
|
`aiready-report-${getReportTimestamp()}.md`,
|
|
1493
1637
|
resolvedDir
|
|
1494
1638
|
);
|
|
1495
|
-
(0,
|
|
1496
|
-
console.log(
|
|
1639
|
+
(0, import_fs4.writeFileSync)(outputPath, markdown);
|
|
1640
|
+
console.log(import_chalk6.default.green(`\u2705 Report saved to ${outputPath}`));
|
|
1497
1641
|
} else {
|
|
1498
|
-
console.log(
|
|
1642
|
+
console.log(import_chalk6.default.bold("\n\u{1F4CA} Summary\n"));
|
|
1499
1643
|
console.log(
|
|
1500
|
-
`Files Analyzed: ${
|
|
1644
|
+
`Files Analyzed: ${import_chalk6.default.cyan(report.summary.filesAnalyzed)}`
|
|
1501
1645
|
);
|
|
1502
|
-
console.log(`Total Issues: ${
|
|
1503
|
-
console.log(` Naming: ${
|
|
1504
|
-
console.log(` Patterns: ${
|
|
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)}`);
|
|
1505
1649
|
console.log(
|
|
1506
|
-
` Architecture: ${
|
|
1650
|
+
` Architecture: ${import_chalk6.default.yellow(report.summary.architectureIssues || 0)}`
|
|
1507
1651
|
);
|
|
1508
|
-
console.log(`Analysis Time: ${
|
|
1652
|
+
console.log(`Analysis Time: ${import_chalk6.default.gray(elapsedTime + "s")}
|
|
1509
1653
|
`);
|
|
1510
1654
|
if (report.summary.totalIssues === 0) {
|
|
1511
1655
|
console.log(
|
|
1512
|
-
|
|
1656
|
+
import_chalk6.default.green(
|
|
1513
1657
|
"\u2728 No consistency issues found! Your codebase is well-maintained.\n"
|
|
1514
1658
|
)
|
|
1515
1659
|
);
|
|
@@ -1521,20 +1665,20 @@ async function consistencyAction(directory, options) {
|
|
|
1521
1665
|
(r) => r.issues.some((i) => i.category === "patterns")
|
|
1522
1666
|
);
|
|
1523
1667
|
if (namingResults.length > 0) {
|
|
1524
|
-
console.log(
|
|
1668
|
+
console.log(import_chalk6.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
|
|
1525
1669
|
let shown = 0;
|
|
1526
1670
|
for (const result of namingResults) {
|
|
1527
1671
|
if (shown >= 5) break;
|
|
1528
1672
|
for (const issue of result.issues) {
|
|
1529
1673
|
if (shown >= 5) break;
|
|
1530
|
-
const severityColor = issue.severity === "critical" ?
|
|
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;
|
|
1531
1675
|
console.log(
|
|
1532
|
-
`${severityColor(issue.severity.toUpperCase())} ${
|
|
1676
|
+
`${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
|
|
1533
1677
|
);
|
|
1534
1678
|
console.log(` ${issue.message}`);
|
|
1535
1679
|
if (issue.suggestion) {
|
|
1536
1680
|
console.log(
|
|
1537
|
-
` ${
|
|
1681
|
+
` ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
|
|
1538
1682
|
);
|
|
1539
1683
|
}
|
|
1540
1684
|
console.log();
|
|
@@ -1543,25 +1687,25 @@ async function consistencyAction(directory, options) {
|
|
|
1543
1687
|
}
|
|
1544
1688
|
const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
|
|
1545
1689
|
if (remaining > 0) {
|
|
1546
|
-
console.log(
|
|
1690
|
+
console.log(import_chalk6.default.dim(` ... and ${remaining} more issues
|
|
1547
1691
|
`));
|
|
1548
1692
|
}
|
|
1549
1693
|
}
|
|
1550
1694
|
if (patternResults.length > 0) {
|
|
1551
|
-
console.log(
|
|
1695
|
+
console.log(import_chalk6.default.bold("\u{1F504} Pattern Issues\n"));
|
|
1552
1696
|
let shown = 0;
|
|
1553
1697
|
for (const result of patternResults) {
|
|
1554
1698
|
if (shown >= 5) break;
|
|
1555
1699
|
for (const issue of result.issues) {
|
|
1556
1700
|
if (shown >= 5) break;
|
|
1557
|
-
const severityColor = issue.severity === "critical" ?
|
|
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;
|
|
1558
1702
|
console.log(
|
|
1559
|
-
`${severityColor(issue.severity.toUpperCase())} ${
|
|
1703
|
+
`${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
|
|
1560
1704
|
);
|
|
1561
1705
|
console.log(` ${issue.message}`);
|
|
1562
1706
|
if (issue.suggestion) {
|
|
1563
1707
|
console.log(
|
|
1564
|
-
` ${
|
|
1708
|
+
` ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
|
|
1565
1709
|
);
|
|
1566
1710
|
}
|
|
1567
1711
|
console.log();
|
|
@@ -1570,12 +1714,12 @@ async function consistencyAction(directory, options) {
|
|
|
1570
1714
|
}
|
|
1571
1715
|
const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
|
|
1572
1716
|
if (remaining > 0) {
|
|
1573
|
-
console.log(
|
|
1717
|
+
console.log(import_chalk6.default.dim(` ... and ${remaining} more issues
|
|
1574
1718
|
`));
|
|
1575
1719
|
}
|
|
1576
1720
|
}
|
|
1577
1721
|
if (report.recommendations.length > 0) {
|
|
1578
|
-
console.log(
|
|
1722
|
+
console.log(import_chalk6.default.bold("\u{1F4A1} Recommendations\n"));
|
|
1579
1723
|
report.recommendations.forEach((rec, i) => {
|
|
1580
1724
|
console.log(`${i + 1}. ${rec}`);
|
|
1581
1725
|
});
|
|
@@ -1583,38 +1727,38 @@ async function consistencyAction(directory, options) {
|
|
|
1583
1727
|
}
|
|
1584
1728
|
}
|
|
1585
1729
|
if (consistencyScore) {
|
|
1586
|
-
console.log(
|
|
1587
|
-
console.log((0,
|
|
1730
|
+
console.log(import_chalk6.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
|
|
1731
|
+
console.log((0, import_core5.formatToolScore)(consistencyScore));
|
|
1588
1732
|
console.log();
|
|
1589
1733
|
}
|
|
1590
1734
|
}
|
|
1591
1735
|
} catch (error) {
|
|
1592
|
-
(0,
|
|
1736
|
+
(0, import_core5.handleCLIError)(error, "Consistency analysis");
|
|
1593
1737
|
}
|
|
1594
1738
|
}
|
|
1595
1739
|
|
|
1596
1740
|
// src/commands/visualize.ts
|
|
1597
|
-
var
|
|
1598
|
-
var
|
|
1599
|
-
var
|
|
1741
|
+
var import_chalk7 = __toESM(require("chalk"));
|
|
1742
|
+
var import_fs5 = require("fs");
|
|
1743
|
+
var import_path7 = require("path");
|
|
1600
1744
|
var import_child_process = require("child_process");
|
|
1601
|
-
var import_core5 = require("@aiready/core");
|
|
1602
1745
|
var import_core6 = require("@aiready/core");
|
|
1746
|
+
var import_core7 = require("@aiready/core");
|
|
1603
1747
|
async function visualizeAction(directory, options) {
|
|
1604
1748
|
try {
|
|
1605
|
-
const dirPath = (0,
|
|
1606
|
-
let reportPath = options.report ? (0,
|
|
1607
|
-
if (!reportPath || !(0,
|
|
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)) {
|
|
1608
1752
|
const latestScan = findLatestScanReport(dirPath);
|
|
1609
1753
|
if (latestScan) {
|
|
1610
1754
|
reportPath = latestScan;
|
|
1611
1755
|
console.log(
|
|
1612
|
-
|
|
1756
|
+
import_chalk7.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
|
|
1613
1757
|
);
|
|
1614
1758
|
} else {
|
|
1615
|
-
console.error(
|
|
1759
|
+
console.error(import_chalk7.default.red("\u274C No AI readiness report found"));
|
|
1616
1760
|
console.log(
|
|
1617
|
-
|
|
1761
|
+
import_chalk7.default.dim(
|
|
1618
1762
|
`
|
|
1619
1763
|
Generate a report with:
|
|
1620
1764
|
aiready scan --output json
|
|
@@ -1626,13 +1770,13 @@ Or specify a custom report:
|
|
|
1626
1770
|
return;
|
|
1627
1771
|
}
|
|
1628
1772
|
}
|
|
1629
|
-
const raw = (0,
|
|
1773
|
+
const raw = (0, import_fs5.readFileSync)(reportPath, "utf8");
|
|
1630
1774
|
const report = JSON.parse(raw);
|
|
1631
|
-
const configPath = (0,
|
|
1775
|
+
const configPath = (0, import_path7.resolve)(dirPath, "aiready.json");
|
|
1632
1776
|
let graphConfig = { maxNodes: 400, maxEdges: 600 };
|
|
1633
|
-
if ((0,
|
|
1777
|
+
if ((0, import_fs5.existsSync)(configPath)) {
|
|
1634
1778
|
try {
|
|
1635
|
-
const rawConfig = JSON.parse((0,
|
|
1779
|
+
const rawConfig = JSON.parse((0, import_fs5.readFileSync)(configPath, "utf8"));
|
|
1636
1780
|
if (rawConfig.visualizer?.graph) {
|
|
1637
1781
|
graphConfig = {
|
|
1638
1782
|
maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
|
|
@@ -1652,16 +1796,16 @@ Or specify a custom report:
|
|
|
1652
1796
|
let devServerStarted = false;
|
|
1653
1797
|
if (useDevMode) {
|
|
1654
1798
|
try {
|
|
1655
|
-
const monorepoWebDir = (0,
|
|
1799
|
+
const monorepoWebDir = (0, import_path7.resolve)(dirPath, "packages/visualizer");
|
|
1656
1800
|
let webDir = "";
|
|
1657
1801
|
let visualizerAvailable = false;
|
|
1658
|
-
if ((0,
|
|
1802
|
+
if ((0, import_fs5.existsSync)(monorepoWebDir)) {
|
|
1659
1803
|
webDir = monorepoWebDir;
|
|
1660
1804
|
visualizerAvailable = true;
|
|
1661
1805
|
} else {
|
|
1662
1806
|
const nodemodulesLocations = [
|
|
1663
|
-
(0,
|
|
1664
|
-
(0,
|
|
1807
|
+
(0, import_path7.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
|
|
1808
|
+
(0, import_path7.resolve)(
|
|
1665
1809
|
process.cwd(),
|
|
1666
1810
|
"node_modules",
|
|
1667
1811
|
"@aiready",
|
|
@@ -1671,14 +1815,14 @@ Or specify a custom report:
|
|
|
1671
1815
|
let currentDir = dirPath;
|
|
1672
1816
|
while (currentDir !== "/" && currentDir !== ".") {
|
|
1673
1817
|
nodemodulesLocations.push(
|
|
1674
|
-
(0,
|
|
1818
|
+
(0, import_path7.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
|
|
1675
1819
|
);
|
|
1676
|
-
const parent = (0,
|
|
1820
|
+
const parent = (0, import_path7.resolve)(currentDir, "..");
|
|
1677
1821
|
if (parent === currentDir) break;
|
|
1678
1822
|
currentDir = parent;
|
|
1679
1823
|
}
|
|
1680
1824
|
for (const location of nodemodulesLocations) {
|
|
1681
|
-
if ((0,
|
|
1825
|
+
if ((0, import_fs5.existsSync)(location) && (0, import_fs5.existsSync)((0, import_path7.resolve)(location, "package.json"))) {
|
|
1682
1826
|
webDir = location;
|
|
1683
1827
|
visualizerAvailable = true;
|
|
1684
1828
|
break;
|
|
@@ -1687,21 +1831,21 @@ Or specify a custom report:
|
|
|
1687
1831
|
if (!visualizerAvailable) {
|
|
1688
1832
|
try {
|
|
1689
1833
|
const vizPkgPath = require.resolve("@aiready/visualizer/package.json");
|
|
1690
|
-
webDir = (0,
|
|
1834
|
+
webDir = (0, import_path7.resolve)(vizPkgPath, "..");
|
|
1691
1835
|
visualizerAvailable = true;
|
|
1692
1836
|
} catch (err) {
|
|
1693
1837
|
void err;
|
|
1694
1838
|
}
|
|
1695
1839
|
}
|
|
1696
1840
|
}
|
|
1697
|
-
const webViteConfigExists = webDir && (0,
|
|
1841
|
+
const webViteConfigExists = webDir && (0, import_fs5.existsSync)((0, import_path7.resolve)(webDir, "web", "vite.config.ts"));
|
|
1698
1842
|
if (visualizerAvailable && webViteConfigExists) {
|
|
1699
1843
|
const spawnCwd = webDir;
|
|
1700
1844
|
const { watch } = await import("fs");
|
|
1701
1845
|
const copyReportToViz = () => {
|
|
1702
1846
|
try {
|
|
1703
|
-
const destPath = (0,
|
|
1704
|
-
(0,
|
|
1847
|
+
const destPath = (0, import_path7.resolve)(spawnCwd, "web", "report-data.json");
|
|
1848
|
+
(0, import_fs5.copyFileSync)(reportPath, destPath);
|
|
1705
1849
|
console.log(`\u{1F4CB} Report synced to ${destPath}`);
|
|
1706
1850
|
} catch (e) {
|
|
1707
1851
|
console.error("Failed to sync report:", e);
|
|
@@ -1744,29 +1888,29 @@ Or specify a custom report:
|
|
|
1744
1888
|
return;
|
|
1745
1889
|
} else {
|
|
1746
1890
|
console.log(
|
|
1747
|
-
|
|
1891
|
+
import_chalk7.default.yellow(
|
|
1748
1892
|
"\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."
|
|
1749
1893
|
)
|
|
1750
1894
|
);
|
|
1751
1895
|
console.log(
|
|
1752
|
-
|
|
1896
|
+
import_chalk7.default.cyan(" Falling back to static HTML generation...\n")
|
|
1753
1897
|
);
|
|
1754
1898
|
useDevMode = false;
|
|
1755
1899
|
}
|
|
1756
1900
|
} catch (err) {
|
|
1757
1901
|
console.error("Failed to start dev server:", err);
|
|
1758
1902
|
console.log(
|
|
1759
|
-
|
|
1903
|
+
import_chalk7.default.cyan(" Falling back to static HTML generation...\n")
|
|
1760
1904
|
);
|
|
1761
1905
|
useDevMode = false;
|
|
1762
1906
|
}
|
|
1763
1907
|
}
|
|
1764
1908
|
console.log("Generating HTML...");
|
|
1765
|
-
const html = (0,
|
|
1909
|
+
const html = (0, import_core7.generateHTML)(graph);
|
|
1766
1910
|
const defaultOutput = "visualization.html";
|
|
1767
|
-
const outPath = (0,
|
|
1768
|
-
(0,
|
|
1769
|
-
console.log(
|
|
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}`));
|
|
1770
1914
|
if (options.open || options.serve) {
|
|
1771
1915
|
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
1772
1916
|
if (options.serve) {
|
|
@@ -1796,7 +1940,7 @@ Or specify a custom report:
|
|
|
1796
1940
|
server.listen(port, () => {
|
|
1797
1941
|
const addr = `http://localhost:${port}/`;
|
|
1798
1942
|
console.log(
|
|
1799
|
-
|
|
1943
|
+
import_chalk7.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
|
|
1800
1944
|
);
|
|
1801
1945
|
(0, import_child_process.spawn)(opener, [`"${addr}"`], { shell: true });
|
|
1802
1946
|
});
|
|
@@ -1812,7 +1956,7 @@ Or specify a custom report:
|
|
|
1812
1956
|
}
|
|
1813
1957
|
}
|
|
1814
1958
|
} catch (err) {
|
|
1815
|
-
(0,
|
|
1959
|
+
(0, import_core6.handleCLIError)(err, "Visualization");
|
|
1816
1960
|
}
|
|
1817
1961
|
}
|
|
1818
1962
|
var visualizeHelpText = `
|
|
@@ -1843,17 +1987,17 @@ NOTES:
|
|
|
1843
1987
|
`;
|
|
1844
1988
|
|
|
1845
1989
|
// src/commands/ai-signal-clarity.ts
|
|
1846
|
-
var import_chalk7 = __toESM(require("chalk"));
|
|
1847
|
-
var import_core7 = require("@aiready/core");
|
|
1848
|
-
|
|
1849
|
-
// src/commands/agent-grounding.ts
|
|
1850
1990
|
var import_chalk8 = __toESM(require("chalk"));
|
|
1851
1991
|
var import_core8 = require("@aiready/core");
|
|
1852
1992
|
|
|
1853
|
-
// src/commands/
|
|
1993
|
+
// src/commands/agent-grounding.ts
|
|
1854
1994
|
var import_chalk9 = __toESM(require("chalk"));
|
|
1855
1995
|
var import_core9 = require("@aiready/core");
|
|
1856
1996
|
|
|
1997
|
+
// src/commands/testability.ts
|
|
1998
|
+
var import_chalk10 = __toESM(require("chalk"));
|
|
1999
|
+
var import_core10 = require("@aiready/core");
|
|
2000
|
+
|
|
1857
2001
|
// src/commands/change-amplification.ts
|
|
1858
2002
|
var import_cli = require("@aiready/change-amplification/dist/cli.js");
|
|
1859
2003
|
|
|
@@ -1861,10 +2005,10 @@ var import_cli = require("@aiready/change-amplification/dist/cli.js");
|
|
|
1861
2005
|
var import_meta = {};
|
|
1862
2006
|
var getDirname = () => {
|
|
1863
2007
|
if (typeof __dirname !== "undefined") return __dirname;
|
|
1864
|
-
return (0,
|
|
2008
|
+
return (0, import_path8.dirname)((0, import_url.fileURLToPath)(import_meta.url));
|
|
1865
2009
|
};
|
|
1866
2010
|
var packageJson = JSON.parse(
|
|
1867
|
-
(0,
|
|
2011
|
+
(0, import_fs6.readFileSync)((0, import_path8.join)(getDirname(), "../package.json"), "utf8")
|
|
1868
2012
|
);
|
|
1869
2013
|
var program = new import_commander.Command();
|
|
1870
2014
|
program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText(
|
|
@@ -1927,7 +2071,7 @@ program.command("scan").description(
|
|
|
1927
2071
|
"--fail-on <level>",
|
|
1928
2072
|
"Fail on issues: critical, major, any",
|
|
1929
2073
|
"critical"
|
|
1930
|
-
).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) => {
|
|
1931
2075
|
await scanAction(directory, options);
|
|
1932
2076
|
});
|
|
1933
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(
|
|
@@ -2008,4 +2152,7 @@ program.command("visualize").description("Generate interactive visualization fro
|
|
|
2008
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) => {
|
|
2009
2153
|
await (0, import_cli.changeAmplificationAction)(directory, options);
|
|
2010
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
|
+
});
|
|
2011
2158
|
program.parse();
|