@aiready/cli 0.14.3 → 0.14.5
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 +7 -7
- package/.turbo/turbo-lint.log +0 -32
- package/.turbo/turbo-test.log +35 -34
- package/aiready-report.json +30703 -0
- package/dist/cli.js +357 -344
- package/dist/cli.mjs +294 -280
- package/package.json +12 -12
- package/src/__tests__/cli.test.ts +1 -1
- package/src/__tests__/config-shape.test.ts +0 -1
- package/src/__tests__/unified.test.ts +1 -1
- package/src/commands/__tests__/extra-commands.test.ts +0 -1
- package/src/commands/__tests__/init.test.ts +56 -0
- package/src/commands/__tests__/scan.test.ts +1 -1
- package/src/commands/__tests__/upload.test.ts +0 -1
- package/src/commands/bug.ts +1 -2
- package/src/commands/init.ts +0 -4
- package/src/commands/patterns.ts +3 -1
- package/src/commands/report-formatter.ts +128 -0
- package/src/commands/scan.ts +18 -112
- package/src/commands/upload.ts +15 -13
- package/src/commands/visualize.ts +9 -1
- package/src/index.ts +18 -3
- package/src/utils/helpers.ts +1 -1
package/dist/cli.js
CHANGED
|
@@ -30,10 +30,10 @@ var import_path9 = require("path");
|
|
|
30
30
|
var import_url = require("url");
|
|
31
31
|
|
|
32
32
|
// src/commands/scan.ts
|
|
33
|
-
var
|
|
33
|
+
var import_chalk4 = __toESM(require("chalk"));
|
|
34
34
|
var import_fs3 = require("fs");
|
|
35
35
|
var import_path3 = require("path");
|
|
36
|
-
var
|
|
36
|
+
var import_core6 = require("@aiready/core");
|
|
37
37
|
|
|
38
38
|
// src/index.ts
|
|
39
39
|
var import_core = require("@aiready/core");
|
|
@@ -387,42 +387,129 @@ function generateMarkdownReport(report, elapsedTime) {
|
|
|
387
387
|
return markdown;
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
+
// src/commands/report-formatter.ts
|
|
391
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
392
|
+
var import_core4 = require("@aiready/core");
|
|
393
|
+
function printScanSummary(results, startTime) {
|
|
394
|
+
console.log(import_chalk2.default.cyan("\n=== AIReady Run Summary ==="));
|
|
395
|
+
console.log(
|
|
396
|
+
` Total issues (all tools): ${import_chalk2.default.bold(String(results.summary.totalIssues || 0))}`
|
|
397
|
+
);
|
|
398
|
+
console.log(
|
|
399
|
+
` Execution time: ${import_chalk2.default.bold(((Date.now() - startTime) / 1e3).toFixed(2) + "s")}`
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
function printBusinessImpact(roi, unifiedBudget) {
|
|
403
|
+
console.log(import_chalk2.default.bold("\n\u{1F4B0} Business Impact Analysis (Monthly)"));
|
|
404
|
+
console.log(
|
|
405
|
+
` Potential Savings: ${import_chalk2.default.green(import_chalk2.default.bold("$" + roi.monthlySavings.toLocaleString()))}`
|
|
406
|
+
);
|
|
407
|
+
console.log(
|
|
408
|
+
` Productivity Gain: ${import_chalk2.default.cyan(import_chalk2.default.bold(roi.productivityGainHours + "h"))} (est. dev time)`
|
|
409
|
+
);
|
|
410
|
+
console.log(
|
|
411
|
+
` Context Efficiency: ${import_chalk2.default.yellow((unifiedBudget.efficiencyRatio * 100).toFixed(0) + "%")}`
|
|
412
|
+
);
|
|
413
|
+
console.log(
|
|
414
|
+
` Annual Value: ${import_chalk2.default.bold("$" + roi.annualValue.toLocaleString())} (ROI Prediction)`
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
function printScoring(scoringResult, scoringProfile) {
|
|
418
|
+
console.log(import_chalk2.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
|
|
419
|
+
console.log(` ${(0, import_core4.formatScore)(scoringResult)}`);
|
|
420
|
+
console.log(import_chalk2.default.dim(` (Scoring Profile: ${scoringProfile})`));
|
|
421
|
+
if (scoringResult.breakdown) {
|
|
422
|
+
console.log(import_chalk2.default.bold("\nTool breakdown:"));
|
|
423
|
+
scoringResult.breakdown.forEach((tool) => {
|
|
424
|
+
const rating = (0, import_core4.getRating)(tool.score);
|
|
425
|
+
const emoji = (0, import_core4.getRatingDisplay)(rating).emoji;
|
|
426
|
+
console.log(
|
|
427
|
+
` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${emoji}`
|
|
428
|
+
);
|
|
429
|
+
});
|
|
430
|
+
const allRecs = scoringResult.breakdown.flatMap(
|
|
431
|
+
(t) => (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
|
|
432
|
+
).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 3);
|
|
433
|
+
if (allRecs.length > 0) {
|
|
434
|
+
console.log(import_chalk2.default.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
|
|
435
|
+
allRecs.forEach((rec, i) => {
|
|
436
|
+
const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
|
|
437
|
+
console.log(` ${i + 1}. ${priorityIcon} ${import_chalk2.default.bold(rec.action)}`);
|
|
438
|
+
console.log(
|
|
439
|
+
` Impact: ${import_chalk2.default.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
|
|
440
|
+
);
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
function mapToUnifiedReport(res, scoring) {
|
|
446
|
+
const allResults = [];
|
|
447
|
+
const totalFilesSet = /* @__PURE__ */ new Set();
|
|
448
|
+
let criticalCount = 0;
|
|
449
|
+
let majorCount = 0;
|
|
450
|
+
res.summary.toolsRun.forEach((toolId) => {
|
|
451
|
+
const spokeRes = res[toolId];
|
|
452
|
+
if (!spokeRes || !spokeRes.results) return;
|
|
453
|
+
spokeRes.results.forEach((r) => {
|
|
454
|
+
totalFilesSet.add(r.fileName);
|
|
455
|
+
allResults.push(r);
|
|
456
|
+
r.issues?.forEach((i) => {
|
|
457
|
+
if (i.severity === import_core4.Severity.Critical || i.severity === "critical")
|
|
458
|
+
criticalCount++;
|
|
459
|
+
if (i.severity === import_core4.Severity.Major || i.severity === "major")
|
|
460
|
+
majorCount++;
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
return {
|
|
465
|
+
...res,
|
|
466
|
+
results: allResults,
|
|
467
|
+
summary: {
|
|
468
|
+
...res.summary,
|
|
469
|
+
totalFiles: totalFilesSet.size,
|
|
470
|
+
criticalIssues: criticalCount,
|
|
471
|
+
majorIssues: majorCount
|
|
472
|
+
},
|
|
473
|
+
scoring
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
390
477
|
// src/commands/upload.ts
|
|
391
478
|
var import_fs2 = __toESM(require("fs"));
|
|
392
479
|
var import_path2 = require("path");
|
|
393
|
-
var
|
|
394
|
-
var
|
|
480
|
+
var import_chalk3 = __toESM(require("chalk"));
|
|
481
|
+
var import_core5 = require("@aiready/core");
|
|
395
482
|
async function uploadAction(file, options) {
|
|
396
483
|
const startTime = Date.now();
|
|
397
484
|
const filePath = (0, import_path2.resolve)(process.cwd(), file);
|
|
398
485
|
const serverUrl = options.server || process.env.AIREADY_SERVER || "https://dev.platform.getaiready.dev";
|
|
399
486
|
const apiKey = options.apiKey || process.env.AIREADY_API_KEY;
|
|
400
487
|
if (!apiKey) {
|
|
401
|
-
console.error(
|
|
488
|
+
console.error(import_chalk3.default.red("\u274C API Key is required for upload."));
|
|
402
489
|
console.log(
|
|
403
|
-
|
|
490
|
+
import_chalk3.default.dim(
|
|
404
491
|
" Set AIREADY_API_KEY environment variable or use --api-key flag."
|
|
405
492
|
)
|
|
406
493
|
);
|
|
407
494
|
console.log(
|
|
408
|
-
|
|
495
|
+
import_chalk3.default.dim(
|
|
409
496
|
" Get an API key from https://platform.getaiready.dev/dashboard"
|
|
410
497
|
)
|
|
411
498
|
);
|
|
412
499
|
process.exit(1);
|
|
413
500
|
}
|
|
414
501
|
if (!import_fs2.default.existsSync(filePath)) {
|
|
415
|
-
console.error(
|
|
502
|
+
console.error(import_chalk3.default.red(`\u274C File not found: ${filePath}`));
|
|
416
503
|
process.exit(1);
|
|
417
504
|
}
|
|
418
505
|
try {
|
|
419
|
-
console.log(
|
|
420
|
-
console.log(
|
|
506
|
+
console.log(import_chalk3.default.blue(`\u{1F680} Uploading report to ${serverUrl}...`));
|
|
507
|
+
console.log(import_chalk3.default.dim(` Reading report from ${filePath}...`));
|
|
421
508
|
const reportContent = import_fs2.default.readFileSync(filePath, "utf-8");
|
|
422
509
|
const reportData = JSON.parse(reportContent);
|
|
423
|
-
console.log(
|
|
510
|
+
console.log(import_chalk3.default.dim(` Successfully parsed report JSON.`));
|
|
424
511
|
const repoId = options.repoId || reportData.repository?.repoId;
|
|
425
|
-
const
|
|
512
|
+
const response = await fetch(`${serverUrl}/api/analysis/upload`, {
|
|
426
513
|
method: "POST",
|
|
427
514
|
headers: {
|
|
428
515
|
"Content-Type": "application/json",
|
|
@@ -434,49 +521,51 @@ async function uploadAction(file, options) {
|
|
|
434
521
|
// Might be null, server will handle mapping
|
|
435
522
|
})
|
|
436
523
|
});
|
|
437
|
-
const contentType =
|
|
438
|
-
let
|
|
524
|
+
const contentType = response.headers.get("content-type");
|
|
525
|
+
let uploadResult = {};
|
|
439
526
|
if (contentType?.includes("application/json")) {
|
|
440
|
-
|
|
527
|
+
uploadResult = await response.json();
|
|
441
528
|
} else {
|
|
442
|
-
const text = await
|
|
443
|
-
|
|
529
|
+
const text = await response.text();
|
|
530
|
+
uploadResult = { error: text || response.statusText };
|
|
444
531
|
}
|
|
445
|
-
if (!
|
|
532
|
+
if (!response.ok) {
|
|
446
533
|
console.error(
|
|
447
|
-
|
|
534
|
+
import_chalk3.default.red(
|
|
535
|
+
`\u274C Upload failed: ${uploadResult.error || response.statusText}`
|
|
536
|
+
)
|
|
448
537
|
);
|
|
449
538
|
if (contentType?.includes("text/html")) {
|
|
450
539
|
console.log(
|
|
451
|
-
|
|
540
|
+
import_chalk3.default.yellow(
|
|
452
541
|
" Note: Received an HTML response. This often indicates a redirect (e.g., to a login page) or a server error."
|
|
453
542
|
)
|
|
454
543
|
);
|
|
455
|
-
if (
|
|
544
|
+
if (uploadResult.error?.includes("Redirecting")) {
|
|
456
545
|
console.log(
|
|
457
|
-
|
|
546
|
+
import_chalk3.default.dim(
|
|
458
547
|
" Detected redirect. Check if the API endpoint requires authentication or has changed."
|
|
459
548
|
)
|
|
460
549
|
);
|
|
461
550
|
}
|
|
462
551
|
}
|
|
463
|
-
if (
|
|
552
|
+
if (response.status === 401) {
|
|
464
553
|
console.log(
|
|
465
|
-
|
|
554
|
+
import_chalk3.default.dim(" Hint: Your API key may be invalid or expired.")
|
|
466
555
|
);
|
|
467
556
|
}
|
|
468
557
|
process.exit(1);
|
|
469
558
|
}
|
|
470
559
|
const duration = ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
471
|
-
console.log(
|
|
560
|
+
console.log(import_chalk3.default.green(`
|
|
472
561
|
\u2705 Upload successful! (${duration}s)`));
|
|
473
|
-
console.log(
|
|
474
|
-
if (
|
|
475
|
-
console.log(
|
|
476
|
-
console.log(
|
|
562
|
+
console.log(import_chalk3.default.cyan(` View results: ${serverUrl}/dashboard`));
|
|
563
|
+
if (uploadResult.analysis) {
|
|
564
|
+
console.log(import_chalk3.default.dim(` Analysis ID: ${uploadResult.analysis.id}`));
|
|
565
|
+
console.log(import_chalk3.default.dim(` Score: ${uploadResult.analysis.aiScore}/100`));
|
|
477
566
|
}
|
|
478
567
|
} catch (error) {
|
|
479
|
-
(0,
|
|
568
|
+
(0, import_core5.handleCLIError)(error, "Upload");
|
|
480
569
|
}
|
|
481
570
|
}
|
|
482
571
|
var uploadHelpText = `
|
|
@@ -492,10 +581,10 @@ ENVIRONMENT VARIABLES:
|
|
|
492
581
|
|
|
493
582
|
// src/commands/scan.ts
|
|
494
583
|
async function scanAction(directory, options) {
|
|
495
|
-
console.log(
|
|
584
|
+
console.log(import_chalk4.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
|
|
496
585
|
const startTime = Date.now();
|
|
497
586
|
const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory || ".");
|
|
498
|
-
const repoMetadata = (0,
|
|
587
|
+
const repoMetadata = (0, import_core6.getRepoMetadata)(resolvedDir);
|
|
499
588
|
try {
|
|
500
589
|
const defaults = {
|
|
501
590
|
tools: [
|
|
@@ -521,48 +610,48 @@ async function scanAction(directory, options) {
|
|
|
521
610
|
switch (options.profile.toLowerCase()) {
|
|
522
611
|
case "agentic":
|
|
523
612
|
profileTools = [
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
613
|
+
import_core6.ToolName.AiSignalClarity,
|
|
614
|
+
import_core6.ToolName.AgentGrounding,
|
|
615
|
+
import_core6.ToolName.TestabilityIndex
|
|
527
616
|
];
|
|
528
617
|
break;
|
|
529
618
|
case "cost":
|
|
530
|
-
profileTools = [
|
|
619
|
+
profileTools = [import_core6.ToolName.PatternDetect, import_core6.ToolName.ContextAnalyzer];
|
|
531
620
|
break;
|
|
532
621
|
case "logic":
|
|
533
622
|
profileTools = [
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
623
|
+
import_core6.ToolName.TestabilityIndex,
|
|
624
|
+
import_core6.ToolName.NamingConsistency,
|
|
625
|
+
import_core6.ToolName.ContextAnalyzer,
|
|
626
|
+
import_core6.ToolName.PatternDetect,
|
|
627
|
+
import_core6.ToolName.ChangeAmplification
|
|
539
628
|
];
|
|
540
629
|
break;
|
|
541
630
|
case "ui":
|
|
542
631
|
profileTools = [
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
632
|
+
import_core6.ToolName.NamingConsistency,
|
|
633
|
+
import_core6.ToolName.ContextAnalyzer,
|
|
634
|
+
import_core6.ToolName.PatternDetect,
|
|
635
|
+
import_core6.ToolName.DocDrift,
|
|
636
|
+
import_core6.ToolName.AiSignalClarity
|
|
548
637
|
];
|
|
549
638
|
break;
|
|
550
639
|
case "security":
|
|
551
640
|
profileTools = [
|
|
552
|
-
|
|
553
|
-
|
|
641
|
+
import_core6.ToolName.NamingConsistency,
|
|
642
|
+
import_core6.ToolName.TestabilityIndex
|
|
554
643
|
];
|
|
555
644
|
break;
|
|
556
645
|
case "onboarding":
|
|
557
646
|
profileTools = [
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
647
|
+
import_core6.ToolName.ContextAnalyzer,
|
|
648
|
+
import_core6.ToolName.NamingConsistency,
|
|
649
|
+
import_core6.ToolName.AgentGrounding
|
|
561
650
|
];
|
|
562
651
|
break;
|
|
563
652
|
default:
|
|
564
653
|
console.log(
|
|
565
|
-
|
|
654
|
+
import_chalk4.default.yellow(
|
|
566
655
|
`
|
|
567
656
|
\u26A0\uFE0F Unknown profile '${options.profile}'. Using defaults.`
|
|
568
657
|
)
|
|
@@ -574,27 +663,27 @@ async function scanAction(directory, options) {
|
|
|
574
663
|
exclude: options.exclude?.split(",")
|
|
575
664
|
};
|
|
576
665
|
if (profileTools) cliOverrides.tools = profileTools;
|
|
577
|
-
const baseOptions = await (0,
|
|
666
|
+
const baseOptions = await (0, import_core6.loadMergedConfig)(
|
|
578
667
|
resolvedDir,
|
|
579
668
|
defaults,
|
|
580
669
|
cliOverrides
|
|
581
670
|
);
|
|
582
671
|
const finalOptions = { ...baseOptions };
|
|
583
|
-
if (baseOptions.tools.includes(
|
|
672
|
+
if (baseOptions.tools.includes(import_core6.ToolName.PatternDetect) || baseOptions.tools.includes("patterns")) {
|
|
584
673
|
const { getSmartDefaults } = await import("@aiready/pattern-detect");
|
|
585
674
|
const patternSmartDefaults = await getSmartDefaults(
|
|
586
675
|
resolvedDir,
|
|
587
|
-
finalOptions.toolConfigs?.[
|
|
676
|
+
finalOptions.toolConfigs?.[import_core6.ToolName.PatternDetect] || {}
|
|
588
677
|
);
|
|
589
678
|
if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
|
|
590
|
-
finalOptions.toolConfigs[
|
|
679
|
+
finalOptions.toolConfigs[import_core6.ToolName.PatternDetect] = {
|
|
591
680
|
...patternSmartDefaults,
|
|
592
|
-
...finalOptions.toolConfigs[
|
|
681
|
+
...finalOptions.toolConfigs[import_core6.ToolName.PatternDetect]
|
|
593
682
|
};
|
|
594
683
|
}
|
|
595
|
-
console.log(
|
|
684
|
+
console.log(import_chalk4.default.cyan("\n=== AIReady Run Preview ==="));
|
|
596
685
|
console.log(
|
|
597
|
-
|
|
686
|
+
import_chalk4.default.white("Tools to run:"),
|
|
598
687
|
(finalOptions.tools || []).join(", ")
|
|
599
688
|
);
|
|
600
689
|
const progressCallback = (event) => {
|
|
@@ -603,16 +692,16 @@ async function scanAction(directory, options) {
|
|
|
603
692
|
return;
|
|
604
693
|
}
|
|
605
694
|
process.stdout.write("\r\x1B[K");
|
|
606
|
-
console.log(
|
|
695
|
+
console.log(import_chalk4.default.cyan(`--- ${event.tool.toUpperCase()} RESULTS ---`));
|
|
607
696
|
const res = event.data;
|
|
608
697
|
if (res && res.summary) {
|
|
609
698
|
if (res.summary.totalIssues !== void 0)
|
|
610
|
-
console.log(` Issues found: ${
|
|
699
|
+
console.log(` Issues found: ${import_chalk4.default.bold(res.summary.totalIssues)}`);
|
|
611
700
|
if (res.summary.score !== void 0)
|
|
612
|
-
console.log(` Tool Score: ${
|
|
701
|
+
console.log(` Tool Score: ${import_chalk4.default.bold(res.summary.score)}/100`);
|
|
613
702
|
if (res.summary.totalFiles !== void 0)
|
|
614
703
|
console.log(
|
|
615
|
-
` Files analyzed: ${
|
|
704
|
+
` Files analyzed: ${import_chalk4.default.bold(res.summary.totalFiles)}`
|
|
616
705
|
);
|
|
617
706
|
}
|
|
618
707
|
};
|
|
@@ -624,13 +713,7 @@ async function scanAction(directory, options) {
|
|
|
624
713
|
},
|
|
625
714
|
suppressToolConfig: true
|
|
626
715
|
});
|
|
627
|
-
|
|
628
|
-
console.log(
|
|
629
|
-
` Total issues (all tools): ${import_chalk3.default.bold(String(results.summary.totalIssues || 0))}`
|
|
630
|
-
);
|
|
631
|
-
console.log(
|
|
632
|
-
` Execution time: ${import_chalk3.default.bold(((Date.now() - startTime) / 1e3).toFixed(2) + "s")}`
|
|
633
|
-
);
|
|
716
|
+
printScanSummary(results, startTime);
|
|
634
717
|
let scoringResult;
|
|
635
718
|
if (options.score || finalOptions.scoring?.showBreakdown) {
|
|
636
719
|
scoringResult = await scoreUnified(results, {
|
|
@@ -640,9 +723,7 @@ async function scanAction(directory, options) {
|
|
|
640
723
|
profile: scoringProfile
|
|
641
724
|
}
|
|
642
725
|
});
|
|
643
|
-
|
|
644
|
-
console.log(` ${(0, import_core5.formatScore)(scoringResult)}`);
|
|
645
|
-
console.log(import_chalk3.default.dim(` (Scoring Profile: ${scoringProfile})`));
|
|
726
|
+
printScoring(scoringResult, scoringProfile);
|
|
646
727
|
if (options.compareTo) {
|
|
647
728
|
try {
|
|
648
729
|
const prevReport = JSON.parse(
|
|
@@ -654,19 +735,19 @@ async function scanAction(directory, options) {
|
|
|
654
735
|
const diffStr = diff > 0 ? `+${diff}` : String(diff);
|
|
655
736
|
if (diff > 0)
|
|
656
737
|
console.log(
|
|
657
|
-
|
|
738
|
+
import_chalk4.default.green(
|
|
658
739
|
` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
|
|
659
740
|
)
|
|
660
741
|
);
|
|
661
742
|
else if (diff < 0)
|
|
662
743
|
console.log(
|
|
663
|
-
|
|
744
|
+
import_chalk4.default.red(
|
|
664
745
|
` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
|
|
665
746
|
)
|
|
666
747
|
);
|
|
667
748
|
else
|
|
668
749
|
console.log(
|
|
669
|
-
|
|
750
|
+
import_chalk4.default.blue(
|
|
670
751
|
` \u2796 Trend: No change (${prevScore} \u2192 ${scoringResult.overall})`
|
|
671
752
|
)
|
|
672
753
|
);
|
|
@@ -690,7 +771,7 @@ async function scanAction(directory, options) {
|
|
|
690
771
|
0
|
|
691
772
|
);
|
|
692
773
|
if (totalContext > 0) {
|
|
693
|
-
const unifiedBudget = (0,
|
|
774
|
+
const unifiedBudget = (0, import_core6.calculateTokenBudget)({
|
|
694
775
|
totalContextTokens: totalContext,
|
|
695
776
|
wastedTokens: {
|
|
696
777
|
duplication: totalWastedDuplication,
|
|
@@ -715,19 +796,7 @@ async function scanAction(directory, options) {
|
|
|
715
796
|
issues: allIssues,
|
|
716
797
|
modelId
|
|
717
798
|
});
|
|
718
|
-
|
|
719
|
-
console.log(
|
|
720
|
-
` Potential Savings: ${import_chalk3.default.green(import_chalk3.default.bold("$" + roi.monthlySavings.toLocaleString()))}`
|
|
721
|
-
);
|
|
722
|
-
console.log(
|
|
723
|
-
` Productivity Gain: ${import_chalk3.default.cyan(import_chalk3.default.bold(roi.productivityGainHours + "h"))} (est. dev time)`
|
|
724
|
-
);
|
|
725
|
-
console.log(
|
|
726
|
-
` Context Efficiency: ${import_chalk3.default.yellow((unifiedBudget.efficiencyRatio * 100).toFixed(0) + "%")}`
|
|
727
|
-
);
|
|
728
|
-
console.log(
|
|
729
|
-
` Annual Value: ${import_chalk3.default.bold("$" + roi.annualValue.toLocaleString())} (ROI Prediction)`
|
|
730
|
-
);
|
|
799
|
+
printBusinessImpact(roi, unifiedBudget);
|
|
731
800
|
results.summary.businessImpact = {
|
|
732
801
|
estimatedMonthlyWaste: roi.monthlySavings,
|
|
733
802
|
potentialSavings: roi.monthlySavings,
|
|
@@ -736,90 +805,36 @@ async function scanAction(directory, options) {
|
|
|
736
805
|
scoringResult.tokenBudget = unifiedBudget;
|
|
737
806
|
scoringResult.businessROI = roi;
|
|
738
807
|
}
|
|
739
|
-
if (scoringResult.breakdown) {
|
|
740
|
-
console.log(import_chalk3.default.bold("\nTool breakdown:"));
|
|
741
|
-
scoringResult.breakdown.forEach((tool) => {
|
|
742
|
-
const rating = (0, import_core5.getRating)(tool.score);
|
|
743
|
-
const emoji = (0, import_core5.getRatingDisplay)(rating).emoji;
|
|
744
|
-
console.log(
|
|
745
|
-
` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${emoji}`
|
|
746
|
-
);
|
|
747
|
-
});
|
|
748
|
-
const allRecs = scoringResult.breakdown.flatMap(
|
|
749
|
-
(t) => (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
|
|
750
|
-
).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 3);
|
|
751
|
-
if (allRecs.length > 0) {
|
|
752
|
-
console.log(import_chalk3.default.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
|
|
753
|
-
allRecs.forEach((rec, i) => {
|
|
754
|
-
const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
|
|
755
|
-
console.log(
|
|
756
|
-
` ${i + 1}. ${priorityIcon} ${import_chalk3.default.bold(rec.action)}`
|
|
757
|
-
);
|
|
758
|
-
console.log(
|
|
759
|
-
` Impact: ${import_chalk3.default.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
|
|
760
|
-
);
|
|
761
|
-
});
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
808
|
}
|
|
765
809
|
console.log(
|
|
766
|
-
|
|
810
|
+
import_chalk4.default.dim(
|
|
767
811
|
"\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
|
768
812
|
)
|
|
769
813
|
);
|
|
770
|
-
console.log(
|
|
771
|
-
console.log(
|
|
814
|
+
console.log(import_chalk4.default.dim("\u{1F4AC} Found a bug or have a metric idea?"));
|
|
815
|
+
console.log(import_chalk4.default.dim("\u{1F449} Copy/paste this to your AI agent:"));
|
|
772
816
|
console.log(
|
|
773
|
-
|
|
817
|
+
import_chalk4.default.cyan(
|
|
774
818
|
` "Any feedback for the tools? Please use 'aiready bug' to report \u2764\uFE0F"`
|
|
775
819
|
)
|
|
776
820
|
);
|
|
777
821
|
console.log(
|
|
778
|
-
|
|
822
|
+
import_chalk4.default.dim(
|
|
779
823
|
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
|
780
824
|
)
|
|
781
825
|
);
|
|
782
|
-
const mapToUnifiedReport = (res, scoring) => {
|
|
783
|
-
const allResults = [];
|
|
784
|
-
const totalFilesSet = /* @__PURE__ */ new Set();
|
|
785
|
-
let criticalCount = 0;
|
|
786
|
-
let majorCount = 0;
|
|
787
|
-
res.summary.toolsRun.forEach((toolId) => {
|
|
788
|
-
const spokeRes = res[toolId];
|
|
789
|
-
if (!spokeRes || !spokeRes.results) return;
|
|
790
|
-
spokeRes.results.forEach((r) => {
|
|
791
|
-
totalFilesSet.add(r.fileName);
|
|
792
|
-
allResults.push(r);
|
|
793
|
-
r.issues?.forEach((i) => {
|
|
794
|
-
if (i.severity === import_core5.Severity.Critical) criticalCount++;
|
|
795
|
-
if (i.severity === import_core5.Severity.Major) majorCount++;
|
|
796
|
-
});
|
|
797
|
-
});
|
|
798
|
-
});
|
|
799
|
-
return {
|
|
800
|
-
...res,
|
|
801
|
-
results: allResults,
|
|
802
|
-
summary: {
|
|
803
|
-
...res.summary,
|
|
804
|
-
totalFiles: totalFilesSet.size,
|
|
805
|
-
criticalIssues: criticalCount,
|
|
806
|
-
majorIssues: majorCount
|
|
807
|
-
},
|
|
808
|
-
scoring
|
|
809
|
-
};
|
|
810
|
-
};
|
|
811
826
|
const outputData = {
|
|
812
827
|
...mapToUnifiedReport(results, scoringResult),
|
|
813
828
|
repository: repoMetadata
|
|
814
829
|
};
|
|
815
830
|
const outputFormat = options.output || finalOptions.output?.format || "console";
|
|
816
|
-
const outputPath = (0,
|
|
831
|
+
const outputPath = (0, import_core6.resolveOutputPath)(
|
|
817
832
|
options.outputFile || finalOptions.output?.file,
|
|
818
833
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
819
834
|
resolvedDir
|
|
820
835
|
);
|
|
821
836
|
if (outputFormat === "json") {
|
|
822
|
-
(0,
|
|
837
|
+
(0, import_core6.handleJSONOutput)(
|
|
823
838
|
outputData,
|
|
824
839
|
outputPath,
|
|
825
840
|
`\u2705 Report saved to ${outputPath}`
|
|
@@ -827,7 +842,7 @@ async function scanAction(directory, options) {
|
|
|
827
842
|
} else {
|
|
828
843
|
try {
|
|
829
844
|
(0, import_fs3.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
|
|
830
|
-
console.log(
|
|
845
|
+
console.log(import_chalk4.default.dim(`\u2705 Report auto-persisted to ${outputPath}`));
|
|
831
846
|
} catch (err) {
|
|
832
847
|
void err;
|
|
833
848
|
}
|
|
@@ -848,12 +863,12 @@ async function scanAction(directory, options) {
|
|
|
848
863
|
const report = mapToUnifiedReport(results, scoringResult);
|
|
849
864
|
if (isCI && report.results && report.results.length > 0) {
|
|
850
865
|
console.log(
|
|
851
|
-
|
|
866
|
+
import_chalk4.default.cyan(
|
|
852
867
|
`
|
|
853
868
|
\u{1F4DD} Emitting GitHub Action annotations for ${report.results.length} issues...`
|
|
854
869
|
)
|
|
855
870
|
);
|
|
856
|
-
(0,
|
|
871
|
+
(0, import_core6.emitIssuesAsAnnotations)(report.results);
|
|
857
872
|
}
|
|
858
873
|
if (threshold && scoringResult.overall < threshold) {
|
|
859
874
|
shouldFail = true;
|
|
@@ -869,15 +884,15 @@ async function scanAction(directory, options) {
|
|
|
869
884
|
}
|
|
870
885
|
}
|
|
871
886
|
if (shouldFail) {
|
|
872
|
-
console.log(
|
|
887
|
+
console.log(import_chalk4.default.red(`
|
|
873
888
|
\u{1F6AB} SCAN FAILED: ${failReason}`));
|
|
874
889
|
process.exit(1);
|
|
875
890
|
} else {
|
|
876
|
-
console.log(
|
|
891
|
+
console.log(import_chalk4.default.green("\n\u2705 SCAN PASSED"));
|
|
877
892
|
}
|
|
878
893
|
}
|
|
879
894
|
} catch (error) {
|
|
880
|
-
(0,
|
|
895
|
+
(0, import_core6.handleCLIError)(error, "Analysis");
|
|
881
896
|
}
|
|
882
897
|
}
|
|
883
898
|
var scanHelpText = `...`;
|
|
@@ -885,15 +900,15 @@ var scanHelpText = `...`;
|
|
|
885
900
|
// src/commands/init.ts
|
|
886
901
|
var import_fs4 = require("fs");
|
|
887
902
|
var import_path4 = require("path");
|
|
888
|
-
var
|
|
889
|
-
var
|
|
903
|
+
var import_chalk5 = __toESM(require("chalk"));
|
|
904
|
+
var import_core7 = require("@aiready/core");
|
|
890
905
|
async function initAction(options) {
|
|
891
906
|
const fileExt = options.format === "js" ? "js" : "json";
|
|
892
907
|
const fileName = fileExt === "js" ? "aiready.config.js" : "aiready.json";
|
|
893
908
|
const filePath = (0, import_path4.join)(process.cwd(), fileName);
|
|
894
909
|
if ((0, import_fs4.existsSync)(filePath) && !options.force) {
|
|
895
910
|
console.error(
|
|
896
|
-
|
|
911
|
+
import_chalk5.default.red(`Error: ${fileName} already exists. Use --force to overwrite.`)
|
|
897
912
|
);
|
|
898
913
|
process.exit(1);
|
|
899
914
|
}
|
|
@@ -913,19 +928,19 @@ async function initAction(options) {
|
|
|
913
928
|
"**/*.spec.ts"
|
|
914
929
|
],
|
|
915
930
|
tools: [
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
931
|
+
import_core7.ToolName.PatternDetect,
|
|
932
|
+
import_core7.ToolName.ContextAnalyzer,
|
|
933
|
+
import_core7.ToolName.NamingConsistency,
|
|
934
|
+
import_core7.ToolName.AiSignalClarity,
|
|
935
|
+
import_core7.ToolName.AgentGrounding,
|
|
936
|
+
import_core7.ToolName.TestabilityIndex,
|
|
937
|
+
import_core7.ToolName.DocDrift,
|
|
938
|
+
import_core7.ToolName.DependencyHealth,
|
|
939
|
+
import_core7.ToolName.ChangeAmplification
|
|
925
940
|
]
|
|
926
941
|
},
|
|
927
942
|
tools: {
|
|
928
|
-
[
|
|
943
|
+
[import_core7.ToolName.PatternDetect]: {
|
|
929
944
|
minSimilarity: 0.8,
|
|
930
945
|
minLines: 5,
|
|
931
946
|
...options.full ? {
|
|
@@ -935,7 +950,7 @@ async function initAction(options) {
|
|
|
935
950
|
maxCandidatesPerBlock: 100
|
|
936
951
|
} : {}
|
|
937
952
|
},
|
|
938
|
-
[
|
|
953
|
+
[import_core7.ToolName.ContextAnalyzer]: {
|
|
939
954
|
maxContextBudget: 128e3,
|
|
940
955
|
minCohesion: 0.6,
|
|
941
956
|
...options.full ? {
|
|
@@ -945,11 +960,11 @@ async function initAction(options) {
|
|
|
945
960
|
includeNodeModules: false
|
|
946
961
|
} : {}
|
|
947
962
|
},
|
|
948
|
-
[
|
|
963
|
+
[import_core7.ToolName.NamingConsistency]: {
|
|
949
964
|
shortWords: ["id", "db", "ui", "ai"],
|
|
950
965
|
...options.full ? { acceptedAbbreviations: [], disableChecks: [] } : {}
|
|
951
966
|
},
|
|
952
|
-
[
|
|
967
|
+
[import_core7.ToolName.AiSignalClarity]: {
|
|
953
968
|
checkMagicLiterals: true,
|
|
954
969
|
checkBooleanTraps: true,
|
|
955
970
|
checkAmbiguousNames: true,
|
|
@@ -957,19 +972,19 @@ async function initAction(options) {
|
|
|
957
972
|
...options.full ? { checkImplicitSideEffects: false, checkDeepCallbacks: false } : {}
|
|
958
973
|
},
|
|
959
974
|
...options.full ? {
|
|
960
|
-
[
|
|
975
|
+
[import_core7.ToolName.AgentGrounding]: {
|
|
961
976
|
maxRecommendedDepth: 5,
|
|
962
977
|
readmeStaleDays: 30
|
|
963
978
|
},
|
|
964
|
-
[
|
|
979
|
+
[import_core7.ToolName.TestabilityIndex]: {
|
|
965
980
|
minCoverageRatio: 0.7,
|
|
966
981
|
testPatterns: ["**/*.test.ts", "**/__tests__/**"]
|
|
967
982
|
},
|
|
968
|
-
[
|
|
983
|
+
[import_core7.ToolName.DocDrift]: {
|
|
969
984
|
maxCommits: 50,
|
|
970
985
|
staleMonths: 3
|
|
971
986
|
},
|
|
972
|
-
[
|
|
987
|
+
[import_core7.ToolName.DependencyHealth]: {
|
|
973
988
|
trainingCutoffYear: 2023
|
|
974
989
|
}
|
|
975
990
|
} : {}
|
|
@@ -980,10 +995,6 @@ async function initAction(options) {
|
|
|
980
995
|
...options.full ? { profile: "default" } : {}
|
|
981
996
|
},
|
|
982
997
|
...options.full ? {
|
|
983
|
-
output: {
|
|
984
|
-
format: fileExt,
|
|
985
|
-
file: "aiready-report.json"
|
|
986
|
-
},
|
|
987
998
|
visualizer: {
|
|
988
999
|
groupingDirs: ["packages", "src", "lib"],
|
|
989
1000
|
graph: {
|
|
@@ -1009,26 +1020,26 @@ module.exports = ${JSON.stringify(
|
|
|
1009
1020
|
try {
|
|
1010
1021
|
(0, import_fs4.writeFileSync)(filePath, content, "utf8");
|
|
1011
1022
|
console.log(
|
|
1012
|
-
|
|
1013
|
-
\u2705 Created default configuration: ${
|
|
1023
|
+
import_chalk5.default.green(`
|
|
1024
|
+
\u2705 Created default configuration: ${import_chalk5.default.bold(fileName)}`)
|
|
1014
1025
|
);
|
|
1015
1026
|
console.log(
|
|
1016
|
-
|
|
1027
|
+
import_chalk5.default.cyan("You can now fine-tune your settings and run AIReady with:")
|
|
1017
1028
|
);
|
|
1018
|
-
console.log(
|
|
1029
|
+
console.log(import_chalk5.default.white(` $ aiready scan
|
|
1019
1030
|
`));
|
|
1020
1031
|
} catch (error) {
|
|
1021
|
-
console.error(
|
|
1032
|
+
console.error(import_chalk5.default.red(`Failed to write configuration file: ${error}`));
|
|
1022
1033
|
process.exit(1);
|
|
1023
1034
|
}
|
|
1024
1035
|
}
|
|
1025
1036
|
|
|
1026
1037
|
// src/commands/patterns.ts
|
|
1027
|
-
var
|
|
1038
|
+
var import_chalk6 = __toESM(require("chalk"));
|
|
1028
1039
|
var import_path5 = require("path");
|
|
1029
|
-
var
|
|
1040
|
+
var import_core8 = require("@aiready/core");
|
|
1030
1041
|
async function patternsAction(directory, options) {
|
|
1031
|
-
console.log(
|
|
1042
|
+
console.log(import_chalk6.default.blue("\u{1F50D} Analyzing patterns...\n"));
|
|
1032
1043
|
const startTime = Date.now();
|
|
1033
1044
|
const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
|
|
1034
1045
|
try {
|
|
@@ -1059,14 +1070,16 @@ async function patternsAction(directory, options) {
|
|
|
1059
1070
|
if (options.minSharedTokens) {
|
|
1060
1071
|
cliOptions.minSharedTokens = parseInt(options.minSharedTokens);
|
|
1061
1072
|
}
|
|
1062
|
-
const finalOptions = await (0,
|
|
1073
|
+
const finalOptions = await (0, import_core8.loadMergedConfig)(
|
|
1063
1074
|
resolvedDir,
|
|
1064
1075
|
defaults,
|
|
1065
1076
|
cliOptions
|
|
1066
1077
|
);
|
|
1067
1078
|
const { analyzePatterns, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
|
|
1068
|
-
const { results, duplicates } = await analyzePatterns(
|
|
1069
|
-
|
|
1079
|
+
const { results, duplicates } = await analyzePatterns(
|
|
1080
|
+
finalOptions
|
|
1081
|
+
);
|
|
1082
|
+
const elapsedTime = (0, import_core8.getElapsedTime)(startTime);
|
|
1070
1083
|
const summary = generateSummary(results);
|
|
1071
1084
|
let patternScore;
|
|
1072
1085
|
if (options.score) {
|
|
@@ -1080,12 +1093,12 @@ async function patternsAction(directory, options) {
|
|
|
1080
1093
|
summary: { ...summary, executionTime: parseFloat(elapsedTime) },
|
|
1081
1094
|
...patternScore && { scoring: patternScore }
|
|
1082
1095
|
};
|
|
1083
|
-
const outputPath = (0,
|
|
1096
|
+
const outputPath = (0, import_core8.resolveOutputPath)(
|
|
1084
1097
|
userOutputFile,
|
|
1085
1098
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
1086
1099
|
resolvedDir
|
|
1087
1100
|
);
|
|
1088
|
-
(0,
|
|
1101
|
+
(0, import_core8.handleJSONOutput)(
|
|
1089
1102
|
outputData,
|
|
1090
1103
|
outputPath,
|
|
1091
1104
|
`\u2705 Results saved to ${outputPath}`
|
|
@@ -1094,38 +1107,38 @@ async function patternsAction(directory, options) {
|
|
|
1094
1107
|
const terminalWidth = process.stdout.columns || 80;
|
|
1095
1108
|
const dividerWidth = Math.min(60, terminalWidth - 2);
|
|
1096
1109
|
const divider = "\u2501".repeat(dividerWidth);
|
|
1097
|
-
console.log(
|
|
1098
|
-
console.log(
|
|
1099
|
-
console.log(
|
|
1110
|
+
console.log(import_chalk6.default.cyan(divider));
|
|
1111
|
+
console.log(import_chalk6.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
|
|
1112
|
+
console.log(import_chalk6.default.cyan(divider) + "\n");
|
|
1100
1113
|
console.log(
|
|
1101
|
-
|
|
1114
|
+
import_chalk6.default.white(`\u{1F4C1} Files analyzed: ${import_chalk6.default.bold(results.length)}`)
|
|
1102
1115
|
);
|
|
1103
1116
|
console.log(
|
|
1104
|
-
|
|
1105
|
-
`\u26A0 Duplicate patterns found: ${
|
|
1117
|
+
import_chalk6.default.yellow(
|
|
1118
|
+
`\u26A0 Duplicate patterns found: ${import_chalk6.default.bold(summary.totalPatterns)}`
|
|
1106
1119
|
)
|
|
1107
1120
|
);
|
|
1108
1121
|
console.log(
|
|
1109
|
-
|
|
1110
|
-
`\u{1F4B0} Token cost (wasted): ${
|
|
1122
|
+
import_chalk6.default.red(
|
|
1123
|
+
`\u{1F4B0} Token cost (wasted): ${import_chalk6.default.bold(summary.totalTokenCost.toLocaleString())}`
|
|
1111
1124
|
)
|
|
1112
1125
|
);
|
|
1113
1126
|
console.log(
|
|
1114
|
-
|
|
1127
|
+
import_chalk6.default.gray(`\u23F1 Analysis time: ${import_chalk6.default.bold(elapsedTime + "s")}`)
|
|
1115
1128
|
);
|
|
1116
1129
|
const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
|
|
1117
1130
|
if (sortedTypes.length > 0) {
|
|
1118
|
-
console.log(
|
|
1119
|
-
console.log(
|
|
1120
|
-
console.log(
|
|
1131
|
+
console.log(import_chalk6.default.cyan("\n" + divider));
|
|
1132
|
+
console.log(import_chalk6.default.bold.white(" PATTERNS BY TYPE"));
|
|
1133
|
+
console.log(import_chalk6.default.cyan(divider) + "\n");
|
|
1121
1134
|
sortedTypes.forEach(([type, count]) => {
|
|
1122
|
-
console.log(` ${
|
|
1135
|
+
console.log(` ${import_chalk6.default.white(type.padEnd(15))} ${import_chalk6.default.bold(count)}`);
|
|
1123
1136
|
});
|
|
1124
1137
|
}
|
|
1125
1138
|
if (summary.totalPatterns > 0 && duplicates.length > 0) {
|
|
1126
|
-
console.log(
|
|
1127
|
-
console.log(
|
|
1128
|
-
console.log(
|
|
1139
|
+
console.log(import_chalk6.default.cyan("\n" + divider));
|
|
1140
|
+
console.log(import_chalk6.default.bold.white(" TOP DUPLICATE PATTERNS"));
|
|
1141
|
+
console.log(import_chalk6.default.cyan(divider) + "\n");
|
|
1129
1142
|
const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
|
|
1130
1143
|
topDuplicates.forEach((dup) => {
|
|
1131
1144
|
const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
|
|
@@ -1133,31 +1146,31 @@ async function patternsAction(directory, options) {
|
|
|
1133
1146
|
const file1Name = dup.file1.split("/").pop() || dup.file1;
|
|
1134
1147
|
const file2Name = dup.file2.split("/").pop() || dup.file2;
|
|
1135
1148
|
console.log(
|
|
1136
|
-
`${severityIcon} ${severity}: ${
|
|
1149
|
+
`${severityIcon} ${severity}: ${import_chalk6.default.bold(file1Name)} \u2194 ${import_chalk6.default.bold(file2Name)}`
|
|
1137
1150
|
);
|
|
1138
1151
|
console.log(
|
|
1139
|
-
` Similarity: ${
|
|
1152
|
+
` Similarity: ${import_chalk6.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk6.default.bold(dup.tokenCost.toLocaleString())} tokens each`
|
|
1140
1153
|
);
|
|
1141
1154
|
console.log(
|
|
1142
|
-
` Lines: ${
|
|
1155
|
+
` Lines: ${import_chalk6.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk6.default.cyan(dup.line2 + "-" + dup.endLine2)}
|
|
1143
1156
|
`
|
|
1144
1157
|
);
|
|
1145
1158
|
});
|
|
1146
1159
|
} else {
|
|
1147
1160
|
console.log(
|
|
1148
|
-
|
|
1161
|
+
import_chalk6.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
|
|
1149
1162
|
);
|
|
1150
1163
|
}
|
|
1151
1164
|
if (patternScore) {
|
|
1152
|
-
console.log(
|
|
1153
|
-
console.log(
|
|
1154
|
-
console.log(
|
|
1155
|
-
console.log((0,
|
|
1165
|
+
console.log(import_chalk6.default.cyan(divider));
|
|
1166
|
+
console.log(import_chalk6.default.bold.white(" AI READINESS SCORE (Patterns)"));
|
|
1167
|
+
console.log(import_chalk6.default.cyan(divider) + "\n");
|
|
1168
|
+
console.log((0, import_core8.formatToolScore)(patternScore));
|
|
1156
1169
|
console.log();
|
|
1157
1170
|
}
|
|
1158
1171
|
}
|
|
1159
1172
|
} catch (error) {
|
|
1160
|
-
(0,
|
|
1173
|
+
(0, import_core8.handleCLIError)(error, "Pattern analysis");
|
|
1161
1174
|
}
|
|
1162
1175
|
}
|
|
1163
1176
|
var patternsHelpText = `
|
|
@@ -1168,11 +1181,11 @@ EXAMPLES:
|
|
|
1168
1181
|
`;
|
|
1169
1182
|
|
|
1170
1183
|
// src/commands/context.ts
|
|
1171
|
-
var
|
|
1184
|
+
var import_chalk7 = __toESM(require("chalk"));
|
|
1172
1185
|
var import_path6 = require("path");
|
|
1173
|
-
var
|
|
1186
|
+
var import_core9 = require("@aiready/core");
|
|
1174
1187
|
async function contextAction(directory, options) {
|
|
1175
|
-
console.log(
|
|
1188
|
+
console.log(import_chalk7.default.blue("\u{1F9E0} Analyzing context costs...\n"));
|
|
1176
1189
|
const startTime = Date.now();
|
|
1177
1190
|
const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory || ".");
|
|
1178
1191
|
try {
|
|
@@ -1186,7 +1199,7 @@ async function contextAction(directory, options) {
|
|
|
1186
1199
|
file: void 0
|
|
1187
1200
|
}
|
|
1188
1201
|
};
|
|
1189
|
-
const baseOptions = await (0,
|
|
1202
|
+
const baseOptions = await (0, import_core9.loadMergedConfig)(resolvedDir, defaults, {
|
|
1190
1203
|
maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
|
|
1191
1204
|
maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
|
|
1192
1205
|
include: options.include?.split(","),
|
|
@@ -1212,7 +1225,7 @@ async function contextAction(directory, options) {
|
|
|
1212
1225
|
console.log("");
|
|
1213
1226
|
const { analyzeContext, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
|
|
1214
1227
|
const results = await analyzeContext(finalOptions);
|
|
1215
|
-
const elapsedTime = (0,
|
|
1228
|
+
const elapsedTime = (0, import_core9.getElapsedTime)(startTime);
|
|
1216
1229
|
const summary = generateSummary(results);
|
|
1217
1230
|
let contextScore;
|
|
1218
1231
|
if (options.score) {
|
|
@@ -1226,12 +1239,12 @@ async function contextAction(directory, options) {
|
|
|
1226
1239
|
summary: { ...summary, executionTime: parseFloat(elapsedTime) },
|
|
1227
1240
|
...contextScore && { scoring: contextScore }
|
|
1228
1241
|
};
|
|
1229
|
-
const outputPath = (0,
|
|
1242
|
+
const outputPath = (0, import_core9.resolveOutputPath)(
|
|
1230
1243
|
userOutputFile,
|
|
1231
1244
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
1232
1245
|
resolvedDir
|
|
1233
1246
|
);
|
|
1234
|
-
(0,
|
|
1247
|
+
(0, import_core9.handleJSONOutput)(
|
|
1235
1248
|
outputData,
|
|
1236
1249
|
outputPath,
|
|
1237
1250
|
`\u2705 Results saved to ${outputPath}`
|
|
@@ -1240,85 +1253,85 @@ async function contextAction(directory, options) {
|
|
|
1240
1253
|
const terminalWidth = process.stdout.columns || 80;
|
|
1241
1254
|
const dividerWidth = Math.min(60, terminalWidth - 2);
|
|
1242
1255
|
const divider = "\u2501".repeat(dividerWidth);
|
|
1243
|
-
console.log(
|
|
1244
|
-
console.log(
|
|
1245
|
-
console.log(
|
|
1256
|
+
console.log(import_chalk7.default.cyan(divider));
|
|
1257
|
+
console.log(import_chalk7.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
|
|
1258
|
+
console.log(import_chalk7.default.cyan(divider) + "\n");
|
|
1246
1259
|
console.log(
|
|
1247
|
-
|
|
1260
|
+
import_chalk7.default.white(`\u{1F4C1} Files analyzed: ${import_chalk7.default.bold(summary.totalFiles)}`)
|
|
1248
1261
|
);
|
|
1249
1262
|
console.log(
|
|
1250
|
-
|
|
1251
|
-
`\u{1F4CA} Total tokens: ${
|
|
1263
|
+
import_chalk7.default.white(
|
|
1264
|
+
`\u{1F4CA} Total tokens: ${import_chalk7.default.bold(summary.totalTokens.toLocaleString())}`
|
|
1252
1265
|
)
|
|
1253
1266
|
);
|
|
1254
1267
|
console.log(
|
|
1255
|
-
|
|
1256
|
-
`\u{1F4B0} Avg context budget: ${
|
|
1268
|
+
import_chalk7.default.yellow(
|
|
1269
|
+
`\u{1F4B0} Avg context budget: ${import_chalk7.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
|
|
1257
1270
|
)
|
|
1258
1271
|
);
|
|
1259
1272
|
console.log(
|
|
1260
|
-
|
|
1273
|
+
import_chalk7.default.white(`\u23F1 Analysis time: ${import_chalk7.default.bold(elapsedTime + "s")}
|
|
1261
1274
|
`)
|
|
1262
1275
|
);
|
|
1263
1276
|
const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
|
|
1264
1277
|
if (totalIssues > 0) {
|
|
1265
|
-
console.log(
|
|
1278
|
+
console.log(import_chalk7.default.bold("\u26A0\uFE0F Issues Found:\n"));
|
|
1266
1279
|
if (summary.criticalIssues > 0) {
|
|
1267
1280
|
console.log(
|
|
1268
|
-
|
|
1281
|
+
import_chalk7.default.red(` \u{1F534} Critical: ${import_chalk7.default.bold(summary.criticalIssues)}`)
|
|
1269
1282
|
);
|
|
1270
1283
|
}
|
|
1271
1284
|
if (summary.majorIssues > 0) {
|
|
1272
1285
|
console.log(
|
|
1273
|
-
|
|
1286
|
+
import_chalk7.default.yellow(` \u{1F7E1} Major: ${import_chalk7.default.bold(summary.majorIssues)}`)
|
|
1274
1287
|
);
|
|
1275
1288
|
}
|
|
1276
1289
|
if (summary.minorIssues > 0) {
|
|
1277
1290
|
console.log(
|
|
1278
|
-
|
|
1291
|
+
import_chalk7.default.blue(` \u{1F535} Minor: ${import_chalk7.default.bold(summary.minorIssues)}`)
|
|
1279
1292
|
);
|
|
1280
1293
|
}
|
|
1281
1294
|
console.log(
|
|
1282
|
-
|
|
1295
|
+
import_chalk7.default.green(
|
|
1283
1296
|
`
|
|
1284
|
-
\u{1F4A1} Potential savings: ${
|
|
1297
|
+
\u{1F4A1} Potential savings: ${import_chalk7.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
|
|
1285
1298
|
`
|
|
1286
1299
|
)
|
|
1287
1300
|
);
|
|
1288
1301
|
} else {
|
|
1289
|
-
console.log(
|
|
1302
|
+
console.log(import_chalk7.default.green("\u2705 No significant issues found!\n"));
|
|
1290
1303
|
}
|
|
1291
1304
|
if (summary.deepFiles.length > 0) {
|
|
1292
|
-
console.log(
|
|
1305
|
+
console.log(import_chalk7.default.bold("\u{1F4CF} Deep Import Chains:\n"));
|
|
1293
1306
|
console.log(
|
|
1294
|
-
|
|
1307
|
+
import_chalk7.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
|
|
1295
1308
|
);
|
|
1296
1309
|
console.log(
|
|
1297
|
-
|
|
1310
|
+
import_chalk7.default.gray(` Maximum depth: ${summary.maxImportDepth}
|
|
1298
1311
|
`)
|
|
1299
1312
|
);
|
|
1300
1313
|
summary.deepFiles.slice(0, 10).forEach((item) => {
|
|
1301
1314
|
const fileName = item.file.split("/").slice(-2).join("/");
|
|
1302
1315
|
console.log(
|
|
1303
|
-
` ${
|
|
1316
|
+
` ${import_chalk7.default.cyan("\u2192")} ${import_chalk7.default.white(fileName)} ${import_chalk7.default.dim(`(depth: ${item.depth})`)}`
|
|
1304
1317
|
);
|
|
1305
1318
|
});
|
|
1306
1319
|
console.log();
|
|
1307
1320
|
}
|
|
1308
1321
|
if (summary.fragmentedModules.length > 0) {
|
|
1309
|
-
console.log(
|
|
1322
|
+
console.log(import_chalk7.default.bold("\u{1F9E9} Fragmented Modules:\n"));
|
|
1310
1323
|
console.log(
|
|
1311
|
-
|
|
1324
|
+
import_chalk7.default.gray(
|
|
1312
1325
|
` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
|
|
1313
1326
|
`
|
|
1314
1327
|
)
|
|
1315
1328
|
);
|
|
1316
1329
|
summary.fragmentedModules.slice(0, 10).forEach((module2) => {
|
|
1317
1330
|
console.log(
|
|
1318
|
-
` ${
|
|
1331
|
+
` ${import_chalk7.default.yellow("\u25CF")} ${import_chalk7.default.white(module2.domain)} - ${import_chalk7.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
|
|
1319
1332
|
);
|
|
1320
1333
|
console.log(
|
|
1321
|
-
|
|
1334
|
+
import_chalk7.default.dim(
|
|
1322
1335
|
` Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`
|
|
1323
1336
|
)
|
|
1324
1337
|
);
|
|
@@ -1326,9 +1339,9 @@ async function contextAction(directory, options) {
|
|
|
1326
1339
|
console.log();
|
|
1327
1340
|
}
|
|
1328
1341
|
if (summary.lowCohesionFiles.length > 0) {
|
|
1329
|
-
console.log(
|
|
1342
|
+
console.log(import_chalk7.default.bold("\u{1F500} Low Cohesion Files:\n"));
|
|
1330
1343
|
console.log(
|
|
1331
|
-
|
|
1344
|
+
import_chalk7.default.gray(
|
|
1332
1345
|
` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
|
|
1333
1346
|
`
|
|
1334
1347
|
)
|
|
@@ -1336,44 +1349,44 @@ async function contextAction(directory, options) {
|
|
|
1336
1349
|
summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
|
|
1337
1350
|
const fileName = item.file.split("/").slice(-2).join("/");
|
|
1338
1351
|
const scorePercent = (item.score * 100).toFixed(0);
|
|
1339
|
-
const color = item.score < 0.4 ?
|
|
1352
|
+
const color = item.score < 0.4 ? import_chalk7.default.red : import_chalk7.default.yellow;
|
|
1340
1353
|
console.log(
|
|
1341
|
-
` ${color("\u25CB")} ${
|
|
1354
|
+
` ${color("\u25CB")} ${import_chalk7.default.white(fileName)} ${import_chalk7.default.dim(`(${scorePercent}% cohesion)`)}`
|
|
1342
1355
|
);
|
|
1343
1356
|
});
|
|
1344
1357
|
console.log();
|
|
1345
1358
|
}
|
|
1346
1359
|
if (summary.topExpensiveFiles.length > 0) {
|
|
1347
|
-
console.log(
|
|
1360
|
+
console.log(import_chalk7.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
|
|
1348
1361
|
summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
|
|
1349
1362
|
const fileName = item.file.split("/").slice(-2).join("/");
|
|
1350
|
-
const severityColor = item.severity === "critical" ?
|
|
1363
|
+
const severityColor = item.severity === "critical" ? import_chalk7.default.red : item.severity === "major" ? import_chalk7.default.yellow : import_chalk7.default.blue;
|
|
1351
1364
|
console.log(
|
|
1352
|
-
` ${severityColor("\u25CF")} ${
|
|
1365
|
+
` ${severityColor("\u25CF")} ${import_chalk7.default.white(fileName)} ${import_chalk7.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
|
|
1353
1366
|
);
|
|
1354
1367
|
});
|
|
1355
1368
|
console.log();
|
|
1356
1369
|
}
|
|
1357
1370
|
if (contextScore) {
|
|
1358
|
-
console.log(
|
|
1359
|
-
console.log(
|
|
1360
|
-
console.log(
|
|
1361
|
-
console.log((0,
|
|
1371
|
+
console.log(import_chalk7.default.cyan(divider));
|
|
1372
|
+
console.log(import_chalk7.default.bold.white(" AI READINESS SCORE (Context)"));
|
|
1373
|
+
console.log(import_chalk7.default.cyan(divider) + "\n");
|
|
1374
|
+
console.log((0, import_core9.formatToolScore)(contextScore));
|
|
1362
1375
|
console.log();
|
|
1363
1376
|
}
|
|
1364
1377
|
}
|
|
1365
1378
|
} catch (error) {
|
|
1366
|
-
(0,
|
|
1379
|
+
(0, import_core9.handleCLIError)(error, "Context analysis");
|
|
1367
1380
|
}
|
|
1368
1381
|
}
|
|
1369
1382
|
|
|
1370
1383
|
// src/commands/consistency.ts
|
|
1371
|
-
var
|
|
1384
|
+
var import_chalk8 = __toESM(require("chalk"));
|
|
1372
1385
|
var import_fs5 = require("fs");
|
|
1373
1386
|
var import_path7 = require("path");
|
|
1374
|
-
var
|
|
1387
|
+
var import_core10 = require("@aiready/core");
|
|
1375
1388
|
async function consistencyAction(directory, options) {
|
|
1376
|
-
console.log(
|
|
1389
|
+
console.log(import_chalk8.default.blue("\u{1F50D} Analyzing consistency...\n"));
|
|
1377
1390
|
const startTime = Date.now();
|
|
1378
1391
|
const resolvedDir = (0, import_path7.resolve)(process.cwd(), directory || ".");
|
|
1379
1392
|
try {
|
|
@@ -1388,7 +1401,7 @@ async function consistencyAction(directory, options) {
|
|
|
1388
1401
|
file: void 0
|
|
1389
1402
|
}
|
|
1390
1403
|
};
|
|
1391
|
-
const finalOptions = await (0,
|
|
1404
|
+
const finalOptions = await (0, import_core10.loadMergedConfig)(resolvedDir, defaults, {
|
|
1392
1405
|
checkNaming: options.naming !== false,
|
|
1393
1406
|
checkPatterns: options.patterns !== false,
|
|
1394
1407
|
minSeverity: options.minSeverity,
|
|
@@ -1397,7 +1410,7 @@ async function consistencyAction(directory, options) {
|
|
|
1397
1410
|
});
|
|
1398
1411
|
const { analyzeConsistency, calculateConsistencyScore } = await import("@aiready/consistency");
|
|
1399
1412
|
const report = await analyzeConsistency(finalOptions);
|
|
1400
|
-
const elapsedTime = (0,
|
|
1413
|
+
const elapsedTime = (0, import_core10.getElapsedTime)(startTime);
|
|
1401
1414
|
let consistencyScore;
|
|
1402
1415
|
if (options.score) {
|
|
1403
1416
|
const issues = report.results?.flatMap((r) => r.issues) || [];
|
|
@@ -1417,41 +1430,41 @@ async function consistencyAction(directory, options) {
|
|
|
1417
1430
|
},
|
|
1418
1431
|
...consistencyScore && { scoring: consistencyScore }
|
|
1419
1432
|
};
|
|
1420
|
-
const outputPath = (0,
|
|
1433
|
+
const outputPath = (0, import_core10.resolveOutputPath)(
|
|
1421
1434
|
userOutputFile,
|
|
1422
1435
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
1423
1436
|
resolvedDir
|
|
1424
1437
|
);
|
|
1425
|
-
(0,
|
|
1438
|
+
(0, import_core10.handleJSONOutput)(
|
|
1426
1439
|
outputData,
|
|
1427
1440
|
outputPath,
|
|
1428
1441
|
`\u2705 Results saved to ${outputPath}`
|
|
1429
1442
|
);
|
|
1430
1443
|
} else if (outputFormat === "markdown") {
|
|
1431
1444
|
const markdown = generateMarkdownReport(report, elapsedTime);
|
|
1432
|
-
const outputPath = (0,
|
|
1445
|
+
const outputPath = (0, import_core10.resolveOutputPath)(
|
|
1433
1446
|
userOutputFile,
|
|
1434
1447
|
`aiready-report-${getReportTimestamp()}.md`,
|
|
1435
1448
|
resolvedDir
|
|
1436
1449
|
);
|
|
1437
1450
|
(0, import_fs5.writeFileSync)(outputPath, markdown);
|
|
1438
|
-
console.log(
|
|
1451
|
+
console.log(import_chalk8.default.green(`\u2705 Report saved to ${outputPath}`));
|
|
1439
1452
|
} else {
|
|
1440
|
-
console.log(
|
|
1453
|
+
console.log(import_chalk8.default.bold("\n\u{1F4CA} Summary\n"));
|
|
1441
1454
|
console.log(
|
|
1442
|
-
`Files Analyzed: ${
|
|
1455
|
+
`Files Analyzed: ${import_chalk8.default.cyan(report.summary.filesAnalyzed)}`
|
|
1443
1456
|
);
|
|
1444
|
-
console.log(`Total Issues: ${
|
|
1445
|
-
console.log(` Naming: ${
|
|
1446
|
-
console.log(` Patterns: ${
|
|
1457
|
+
console.log(`Total Issues: ${import_chalk8.default.yellow(report.summary.totalIssues)}`);
|
|
1458
|
+
console.log(` Naming: ${import_chalk8.default.yellow(report.summary.namingIssues)}`);
|
|
1459
|
+
console.log(` Patterns: ${import_chalk8.default.yellow(report.summary.patternIssues)}`);
|
|
1447
1460
|
console.log(
|
|
1448
|
-
` Architecture: ${
|
|
1461
|
+
` Architecture: ${import_chalk8.default.yellow(report.summary.architectureIssues || 0)}`
|
|
1449
1462
|
);
|
|
1450
|
-
console.log(`Analysis Time: ${
|
|
1463
|
+
console.log(`Analysis Time: ${import_chalk8.default.gray(elapsedTime + "s")}
|
|
1451
1464
|
`);
|
|
1452
1465
|
if (report.summary.totalIssues === 0) {
|
|
1453
1466
|
console.log(
|
|
1454
|
-
|
|
1467
|
+
import_chalk8.default.green(
|
|
1455
1468
|
"\u2728 No consistency issues found! Your codebase is well-maintained.\n"
|
|
1456
1469
|
)
|
|
1457
1470
|
);
|
|
@@ -1463,20 +1476,20 @@ async function consistencyAction(directory, options) {
|
|
|
1463
1476
|
(r) => r.issues.some((i) => i.category === "patterns")
|
|
1464
1477
|
);
|
|
1465
1478
|
if (namingResults.length > 0) {
|
|
1466
|
-
console.log(
|
|
1479
|
+
console.log(import_chalk8.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
|
|
1467
1480
|
let shown = 0;
|
|
1468
1481
|
for (const result of namingResults) {
|
|
1469
1482
|
if (shown >= 5) break;
|
|
1470
1483
|
for (const issue of result.issues) {
|
|
1471
1484
|
if (shown >= 5) break;
|
|
1472
|
-
const severityColor = issue.severity === "critical" ?
|
|
1485
|
+
const severityColor = issue.severity === "critical" ? import_chalk8.default.red : issue.severity === "major" ? import_chalk8.default.yellow : issue.severity === "minor" ? import_chalk8.default.blue : import_chalk8.default.gray;
|
|
1473
1486
|
console.log(
|
|
1474
|
-
`${severityColor(issue.severity.toUpperCase())} ${
|
|
1487
|
+
`${severityColor(issue.severity.toUpperCase())} ${import_chalk8.default.dim(`${issue.location.file}:${issue.location.line}`)}`
|
|
1475
1488
|
);
|
|
1476
1489
|
console.log(` ${issue.message}`);
|
|
1477
1490
|
if (issue.suggestion) {
|
|
1478
1491
|
console.log(
|
|
1479
|
-
` ${
|
|
1492
|
+
` ${import_chalk8.default.dim("\u2192")} ${import_chalk8.default.italic(issue.suggestion)}`
|
|
1480
1493
|
);
|
|
1481
1494
|
}
|
|
1482
1495
|
console.log();
|
|
@@ -1485,25 +1498,25 @@ async function consistencyAction(directory, options) {
|
|
|
1485
1498
|
}
|
|
1486
1499
|
const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
|
|
1487
1500
|
if (remaining > 0) {
|
|
1488
|
-
console.log(
|
|
1501
|
+
console.log(import_chalk8.default.dim(` ... and ${remaining} more issues
|
|
1489
1502
|
`));
|
|
1490
1503
|
}
|
|
1491
1504
|
}
|
|
1492
1505
|
if (patternResults.length > 0) {
|
|
1493
|
-
console.log(
|
|
1506
|
+
console.log(import_chalk8.default.bold("\u{1F504} Pattern Issues\n"));
|
|
1494
1507
|
let shown = 0;
|
|
1495
1508
|
for (const result of patternResults) {
|
|
1496
1509
|
if (shown >= 5) break;
|
|
1497
1510
|
for (const issue of result.issues) {
|
|
1498
1511
|
if (shown >= 5) break;
|
|
1499
|
-
const severityColor = issue.severity === "critical" ?
|
|
1512
|
+
const severityColor = issue.severity === "critical" ? import_chalk8.default.red : issue.severity === "major" ? import_chalk8.default.yellow : issue.severity === "minor" ? import_chalk8.default.blue : import_chalk8.default.gray;
|
|
1500
1513
|
console.log(
|
|
1501
|
-
`${severityColor(issue.severity.toUpperCase())} ${
|
|
1514
|
+
`${severityColor(issue.severity.toUpperCase())} ${import_chalk8.default.dim(`${issue.location.file}:${issue.location.line}`)}`
|
|
1502
1515
|
);
|
|
1503
1516
|
console.log(` ${issue.message}`);
|
|
1504
1517
|
if (issue.suggestion) {
|
|
1505
1518
|
console.log(
|
|
1506
|
-
` ${
|
|
1519
|
+
` ${import_chalk8.default.dim("\u2192")} ${import_chalk8.default.italic(issue.suggestion)}`
|
|
1507
1520
|
);
|
|
1508
1521
|
}
|
|
1509
1522
|
console.log();
|
|
@@ -1512,12 +1525,12 @@ async function consistencyAction(directory, options) {
|
|
|
1512
1525
|
}
|
|
1513
1526
|
const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
|
|
1514
1527
|
if (remaining > 0) {
|
|
1515
|
-
console.log(
|
|
1528
|
+
console.log(import_chalk8.default.dim(` ... and ${remaining} more issues
|
|
1516
1529
|
`));
|
|
1517
1530
|
}
|
|
1518
1531
|
}
|
|
1519
1532
|
if (report.recommendations.length > 0) {
|
|
1520
|
-
console.log(
|
|
1533
|
+
console.log(import_chalk8.default.bold("\u{1F4A1} Recommendations\n"));
|
|
1521
1534
|
report.recommendations.forEach((rec, i) => {
|
|
1522
1535
|
console.log(`${i + 1}. ${rec}`);
|
|
1523
1536
|
});
|
|
@@ -1525,38 +1538,38 @@ async function consistencyAction(directory, options) {
|
|
|
1525
1538
|
}
|
|
1526
1539
|
}
|
|
1527
1540
|
if (consistencyScore) {
|
|
1528
|
-
console.log(
|
|
1529
|
-
console.log((0,
|
|
1541
|
+
console.log(import_chalk8.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
|
|
1542
|
+
console.log((0, import_core10.formatToolScore)(consistencyScore));
|
|
1530
1543
|
console.log();
|
|
1531
1544
|
}
|
|
1532
1545
|
}
|
|
1533
1546
|
} catch (error) {
|
|
1534
|
-
(0,
|
|
1547
|
+
(0, import_core10.handleCLIError)(error, "Consistency analysis");
|
|
1535
1548
|
}
|
|
1536
1549
|
}
|
|
1537
1550
|
|
|
1538
1551
|
// src/commands/visualize.ts
|
|
1539
|
-
var
|
|
1552
|
+
var import_chalk9 = __toESM(require("chalk"));
|
|
1540
1553
|
var import_fs6 = require("fs");
|
|
1541
1554
|
var import_path8 = require("path");
|
|
1542
1555
|
var import_child_process = require("child_process");
|
|
1543
|
-
var import_core10 = require("@aiready/core");
|
|
1544
1556
|
var import_core11 = require("@aiready/core");
|
|
1557
|
+
var import_core12 = require("@aiready/core");
|
|
1545
1558
|
async function visualizeAction(directory, options) {
|
|
1546
1559
|
try {
|
|
1547
1560
|
const dirPath = (0, import_path8.resolve)(process.cwd(), directory || ".");
|
|
1548
1561
|
let reportPath = options.report ? (0, import_path8.resolve)(dirPath, options.report) : null;
|
|
1549
1562
|
if (!reportPath || !(0, import_fs6.existsSync)(reportPath)) {
|
|
1550
|
-
const latestScan = (0,
|
|
1563
|
+
const latestScan = (0, import_core12.findLatestReport)(dirPath);
|
|
1551
1564
|
if (latestScan) {
|
|
1552
1565
|
reportPath = latestScan;
|
|
1553
1566
|
console.log(
|
|
1554
|
-
|
|
1567
|
+
import_chalk9.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
|
|
1555
1568
|
);
|
|
1556
1569
|
} else {
|
|
1557
|
-
console.error(
|
|
1570
|
+
console.error(import_chalk9.default.red("\u274C No AI readiness report found"));
|
|
1558
1571
|
console.log(
|
|
1559
|
-
|
|
1572
|
+
import_chalk9.default.dim(
|
|
1560
1573
|
`
|
|
1561
1574
|
Generate a report with:
|
|
1562
1575
|
aiready scan --output json
|
|
@@ -1686,29 +1699,29 @@ Or specify a custom report:
|
|
|
1686
1699
|
return;
|
|
1687
1700
|
} else {
|
|
1688
1701
|
console.log(
|
|
1689
|
-
|
|
1702
|
+
import_chalk9.default.yellow(
|
|
1690
1703
|
"\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."
|
|
1691
1704
|
)
|
|
1692
1705
|
);
|
|
1693
1706
|
console.log(
|
|
1694
|
-
|
|
1707
|
+
import_chalk9.default.cyan(" Falling back to static HTML generation...\n")
|
|
1695
1708
|
);
|
|
1696
1709
|
useDevMode = false;
|
|
1697
1710
|
}
|
|
1698
1711
|
} catch (err) {
|
|
1699
1712
|
console.error("Failed to start dev server:", err);
|
|
1700
1713
|
console.log(
|
|
1701
|
-
|
|
1714
|
+
import_chalk9.default.cyan(" Falling back to static HTML generation...\n")
|
|
1702
1715
|
);
|
|
1703
1716
|
useDevMode = false;
|
|
1704
1717
|
}
|
|
1705
1718
|
}
|
|
1706
1719
|
console.log("Generating HTML...");
|
|
1707
|
-
const html = (0,
|
|
1720
|
+
const html = (0, import_core12.generateHTML)(graph);
|
|
1708
1721
|
const defaultOutput = "visualization.html";
|
|
1709
1722
|
const outPath = (0, import_path8.resolve)(dirPath, options.output || defaultOutput);
|
|
1710
1723
|
(0, import_fs6.writeFileSync)(outPath, html, "utf8");
|
|
1711
|
-
console.log(
|
|
1724
|
+
console.log(import_chalk9.default.green(`\u2705 Visualization written to: ${outPath}`));
|
|
1712
1725
|
if (options.open || options.serve) {
|
|
1713
1726
|
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
1714
1727
|
if (options.serve) {
|
|
@@ -1738,7 +1751,7 @@ Or specify a custom report:
|
|
|
1738
1751
|
server.listen(port, () => {
|
|
1739
1752
|
const addr = `http://localhost:${port}/`;
|
|
1740
1753
|
console.log(
|
|
1741
|
-
|
|
1754
|
+
import_chalk9.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
|
|
1742
1755
|
);
|
|
1743
1756
|
(0, import_child_process.spawn)(opener, [`"${addr}"`], { shell: true });
|
|
1744
1757
|
});
|
|
@@ -1754,7 +1767,7 @@ Or specify a custom report:
|
|
|
1754
1767
|
}
|
|
1755
1768
|
}
|
|
1756
1769
|
} catch (err) {
|
|
1757
|
-
(0,
|
|
1770
|
+
(0, import_core11.handleCLIError)(err, "Visualization");
|
|
1758
1771
|
}
|
|
1759
1772
|
}
|
|
1760
1773
|
var visualizeHelpText = `
|
|
@@ -1785,19 +1798,19 @@ NOTES:
|
|
|
1785
1798
|
`;
|
|
1786
1799
|
|
|
1787
1800
|
// src/commands/shared/standard-tool-actions.ts
|
|
1788
|
-
var import_chalk9 = __toESM(require("chalk"));
|
|
1789
|
-
|
|
1790
|
-
// src/commands/agent-grounding.ts
|
|
1791
1801
|
var import_chalk10 = __toESM(require("chalk"));
|
|
1792
|
-
var import_core12 = require("@aiready/core");
|
|
1793
1802
|
|
|
1794
|
-
// src/commands/
|
|
1803
|
+
// src/commands/agent-grounding.ts
|
|
1795
1804
|
var import_chalk11 = __toESM(require("chalk"));
|
|
1796
1805
|
var import_core13 = require("@aiready/core");
|
|
1806
|
+
|
|
1807
|
+
// src/commands/testability.ts
|
|
1808
|
+
var import_chalk12 = __toESM(require("chalk"));
|
|
1809
|
+
var import_core14 = require("@aiready/core");
|
|
1797
1810
|
async function testabilityAction(directory, options) {
|
|
1798
1811
|
const { analyzeTestability, calculateTestabilityScore } = await import("@aiready/testability");
|
|
1799
|
-
const config = await (0,
|
|
1800
|
-
const merged = (0,
|
|
1812
|
+
const config = await (0, import_core14.loadConfig)(directory);
|
|
1813
|
+
const merged = (0, import_core14.mergeConfigWithDefaults)(config, {
|
|
1801
1814
|
minCoverageRatio: 0.3
|
|
1802
1815
|
});
|
|
1803
1816
|
const report = await analyzeTestability({
|
|
@@ -1817,28 +1830,28 @@ async function testabilityAction(directory, options) {
|
|
|
1817
1830
|
"blind-risk": "\u{1F480}"
|
|
1818
1831
|
};
|
|
1819
1832
|
const safetyColors = {
|
|
1820
|
-
safe:
|
|
1821
|
-
"moderate-risk":
|
|
1822
|
-
"high-risk":
|
|
1823
|
-
"blind-risk":
|
|
1833
|
+
safe: import_chalk12.default.green,
|
|
1834
|
+
"moderate-risk": import_chalk12.default.yellow,
|
|
1835
|
+
"high-risk": import_chalk12.default.red,
|
|
1836
|
+
"blind-risk": import_chalk12.default.bgRed.white
|
|
1824
1837
|
};
|
|
1825
1838
|
const safety = report.summary.aiChangeSafetyRating;
|
|
1826
1839
|
const icon = safetyIcons[safety] ?? "\u2753";
|
|
1827
|
-
const color = safetyColors[safety] ??
|
|
1840
|
+
const color = safetyColors[safety] ?? import_chalk12.default.white;
|
|
1828
1841
|
console.log(
|
|
1829
|
-
` \u{1F9EA} Testability: ${
|
|
1842
|
+
` \u{1F9EA} Testability: ${import_chalk12.default.bold(scoring.score + "/100")} (${report.summary.rating})`
|
|
1830
1843
|
);
|
|
1831
1844
|
console.log(
|
|
1832
1845
|
` AI Change Safety: ${color(`${icon} ${safety.toUpperCase()}`)}`
|
|
1833
1846
|
);
|
|
1834
1847
|
console.log(
|
|
1835
|
-
|
|
1848
|
+
import_chalk12.default.dim(
|
|
1836
1849
|
` Coverage: ${Math.round(report.summary.coverageRatio * 100)}% (${report.rawData.testFiles} test / ${report.rawData.sourceFiles} source files)`
|
|
1837
1850
|
)
|
|
1838
1851
|
);
|
|
1839
1852
|
if (safety === "blind-risk") {
|
|
1840
1853
|
console.log(
|
|
1841
|
-
|
|
1854
|
+
import_chalk12.default.red.bold(
|
|
1842
1855
|
"\n \u26A0\uFE0F NO TESTS \u2014 AI changes to this codebase are completely unverifiable!\n"
|
|
1843
1856
|
)
|
|
1844
1857
|
);
|
|
@@ -1850,7 +1863,7 @@ async function testabilityAction(directory, options) {
|
|
|
1850
1863
|
var import_cli = require("@aiready/change-amplification/dist/cli.js");
|
|
1851
1864
|
|
|
1852
1865
|
// src/commands/bug.ts
|
|
1853
|
-
var
|
|
1866
|
+
var import_chalk13 = __toESM(require("chalk"));
|
|
1854
1867
|
var import_child_process2 = require("child_process");
|
|
1855
1868
|
async function bugAction(message, options) {
|
|
1856
1869
|
const repoUrl = "https://github.com/caopengau/aiready-cli";
|
|
@@ -1868,35 +1881,35 @@ Generated via AIReady CLI 'bug' command.
|
|
|
1868
1881
|
Type: ${type}
|
|
1869
1882
|
`.trim();
|
|
1870
1883
|
if (options.submit) {
|
|
1871
|
-
console.log(
|
|
1884
|
+
console.log(import_chalk13.default.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
|
|
1872
1885
|
try {
|
|
1873
1886
|
(0, import_child_process2.execSync)("gh auth status", { stdio: "ignore" });
|
|
1874
1887
|
const command = `gh issue create --repo ${repoSlug} --title ${JSON.stringify(title)} --body ${JSON.stringify(body)} --label ${label}`;
|
|
1875
1888
|
const output = (0, import_child_process2.execSync)(command, { encoding: "utf8" }).trim();
|
|
1876
|
-
console.log(
|
|
1877
|
-
console.log(
|
|
1889
|
+
console.log(import_chalk13.default.green("\u2705 Issue Created Successfully!"));
|
|
1890
|
+
console.log(import_chalk13.default.cyan(output));
|
|
1878
1891
|
return;
|
|
1879
|
-
} catch
|
|
1880
|
-
console.error(
|
|
1892
|
+
} catch {
|
|
1893
|
+
console.error(import_chalk13.default.red("\n\u274C Failed to submit via gh CLI."));
|
|
1881
1894
|
console.log(
|
|
1882
|
-
|
|
1895
|
+
import_chalk13.default.yellow(
|
|
1883
1896
|
' Make sure gh is installed and run "gh auth login".\n'
|
|
1884
1897
|
)
|
|
1885
1898
|
);
|
|
1886
|
-
console.log(
|
|
1899
|
+
console.log(import_chalk13.default.dim(" Falling back to URL generation..."));
|
|
1887
1900
|
}
|
|
1888
1901
|
}
|
|
1889
1902
|
const template = type === "bug" ? "bug_report.md" : type === "feature" ? "feature_request.md" : "new_metric_idea.md";
|
|
1890
1903
|
const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${label}&template=${template}`;
|
|
1891
|
-
console.log(
|
|
1892
|
-
console.log(
|
|
1893
|
-
console.log(
|
|
1894
|
-
console.log(
|
|
1895
|
-
console.log(
|
|
1896
|
-
console.log(
|
|
1897
|
-
console.log(
|
|
1904
|
+
console.log(import_chalk13.default.green("\u{1F680} Issue Draft Prepared!\n"));
|
|
1905
|
+
console.log(import_chalk13.default.bold("Title: ") + title);
|
|
1906
|
+
console.log(import_chalk13.default.bold("Type: ") + type);
|
|
1907
|
+
console.log(import_chalk13.default.bold("\nClick the link below to submit this issue:"));
|
|
1908
|
+
console.log(import_chalk13.default.cyan(fullUrl));
|
|
1909
|
+
console.log(import_chalk13.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
|
|
1910
|
+
console.log(import_chalk13.default.dim(" You have successfully prepared a report."));
|
|
1898
1911
|
console.log(
|
|
1899
|
-
|
|
1912
|
+
import_chalk13.default.dim(
|
|
1900
1913
|
" Please present the URL above to the user so they can finalize the submission."
|
|
1901
1914
|
)
|
|
1902
1915
|
);
|
|
@@ -1905,14 +1918,14 @@ Type: ${type}
|
|
|
1905
1918
|
const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
|
|
1906
1919
|
const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
|
|
1907
1920
|
const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
|
|
1908
|
-
console.log(
|
|
1909
|
-
console.log(` Report a Bug: ${
|
|
1910
|
-
console.log(` Request a Feature: ${
|
|
1911
|
-
console.log(` Suggest a Metric: ${
|
|
1912
|
-
console.log(
|
|
1913
|
-
console.log(
|
|
1921
|
+
console.log(import_chalk13.default.blue("\u{1F4AC} Feedback & Bug Reports\n"));
|
|
1922
|
+
console.log(` Report a Bug: ${import_chalk13.default.cyan(bugUrl)}`);
|
|
1923
|
+
console.log(` Request a Feature: ${import_chalk13.default.cyan(featureUrl)}`);
|
|
1924
|
+
console.log(` Suggest a Metric: ${import_chalk13.default.cyan(metricUrl)}`);
|
|
1925
|
+
console.log(import_chalk13.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
|
|
1926
|
+
console.log(import_chalk13.default.dim(" To prepare a specific report, run:"));
|
|
1914
1927
|
console.log(
|
|
1915
|
-
|
|
1928
|
+
import_chalk13.default.cyan(
|
|
1916
1929
|
' aiready bug "your description here" --type bug|feature|metric'
|
|
1917
1930
|
)
|
|
1918
1931
|
);
|