@aiready/cli 0.14.9 → 0.14.11
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/.aiready/aiready-report-20260319-201106.json +5566 -0
- package/.aiready/aiready-report-20260319-201511.json +5566 -0
- package/.aiready/aiready-report-20260319-202017.json +5708 -0
- package/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-test.log +19 -19
- package/dist/chunk-HBPSESJV.mjs +289 -0
- package/dist/chunk-JRRBBFYB.mjs +307 -0
- package/dist/chunk-YP2EVXQN.mjs +303 -0
- package/dist/chunk-ZQOTGPK4.mjs +289 -0
- package/dist/cli.js +219 -102
- package/dist/cli.mjs +196 -83
- package/dist/index.js +25 -21
- package/dist/index.mjs +1 -1
- package/package.json +12 -12
- package/src/commands/__tests__/init.test.ts +6 -11
- package/src/commands/bug.ts +1 -1
- package/src/commands/consistency.ts +5 -5
- package/src/commands/context.ts +4 -4
- package/src/commands/init.ts +76 -42
- package/src/commands/patterns.ts +3 -3
- package/src/commands/report-formatter.ts +138 -12
- package/src/commands/scan.ts +18 -18
- package/src/commands/upload.ts +6 -6
- package/src/commands/visualize.ts +4 -4
- package/src/index.ts +35 -25
package/dist/cli.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
__require,
|
|
4
4
|
analyzeUnified,
|
|
5
5
|
scoreUnified
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JRRBBFYB.mjs";
|
|
7
7
|
|
|
8
8
|
// src/cli.ts
|
|
9
9
|
import { Command } from "commander";
|
|
@@ -131,13 +131,91 @@ import {
|
|
|
131
131
|
getRating,
|
|
132
132
|
getRatingDisplay
|
|
133
133
|
} from "@aiready/core";
|
|
134
|
+
function generateProgressBar(score, width = 20) {
|
|
135
|
+
const filled = Math.round(score / 100 * width);
|
|
136
|
+
const empty = width - filled;
|
|
137
|
+
let color = chalk2.red;
|
|
138
|
+
if (score >= 90) color = chalk2.green;
|
|
139
|
+
else if (score >= 75) color = chalk2.cyan;
|
|
140
|
+
else if (score >= 60) color = chalk2.yellow;
|
|
141
|
+
const bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
142
|
+
return color(bar);
|
|
143
|
+
}
|
|
144
|
+
function countIssuesBySeverity(results) {
|
|
145
|
+
let critical = 0;
|
|
146
|
+
let major = 0;
|
|
147
|
+
let minor = 0;
|
|
148
|
+
if (results.summary?.toolsRun) {
|
|
149
|
+
for (const toolId of results.summary.toolsRun) {
|
|
150
|
+
const toolRes = results[toolId];
|
|
151
|
+
if (toolRes?.results) {
|
|
152
|
+
for (const fileRes of toolRes.results) {
|
|
153
|
+
if (fileRes.issues) {
|
|
154
|
+
for (const issue of fileRes.issues) {
|
|
155
|
+
const sev = issue.severity?.toLowerCase();
|
|
156
|
+
if (sev === "critical") critical++;
|
|
157
|
+
else if (sev === "major") major++;
|
|
158
|
+
else minor++;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return { critical, major, minor };
|
|
166
|
+
}
|
|
167
|
+
function getTopFilesWithIssues(results, limit = 5) {
|
|
168
|
+
const fileCounts = /* @__PURE__ */ new Map();
|
|
169
|
+
if (results.summary?.toolsRun) {
|
|
170
|
+
for (const toolId of results.summary.toolsRun) {
|
|
171
|
+
const toolRes = results[toolId];
|
|
172
|
+
if (toolRes?.results) {
|
|
173
|
+
for (const fileRes of toolRes.results) {
|
|
174
|
+
if (fileRes.issues?.length > 0) {
|
|
175
|
+
const current = fileCounts.get(fileRes.fileName) || 0;
|
|
176
|
+
fileCounts.set(fileRes.fileName, current + fileRes.issues.length);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return Array.from(fileCounts.entries()).map(([file, count]) => ({ file, count })).sort((a, b) => b.count - a.count).slice(0, limit);
|
|
183
|
+
}
|
|
134
184
|
function printScanSummary(results, startTime) {
|
|
185
|
+
const severity = countIssuesBySeverity(results);
|
|
186
|
+
const totalIssues = severity.critical + severity.major + severity.minor;
|
|
187
|
+
const topFiles = getTopFilesWithIssues(results);
|
|
135
188
|
console.log(chalk2.cyan("\n=== AIReady Run Summary ==="));
|
|
189
|
+
console.log(` Total issues: ${chalk2.bold(String(totalIssues))}`);
|
|
190
|
+
if (totalIssues > 0) {
|
|
191
|
+
console.log(chalk2.dim(" Severity breakdown:"));
|
|
192
|
+
if (severity.critical > 0) {
|
|
193
|
+
console.log(
|
|
194
|
+
` ${chalk2.red("\u25CF")} Critical: ${chalk2.bold(severity.critical)}`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
if (severity.major > 0) {
|
|
198
|
+
console.log(
|
|
199
|
+
` ${chalk2.yellow("\u25CF")} Major: ${chalk2.bold(severity.major)}`
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
if (severity.minor > 0) {
|
|
203
|
+
console.log(
|
|
204
|
+
` ${chalk2.blue("\u25CF")} Minor: ${chalk2.bold(severity.minor)}`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (topFiles.length > 0) {
|
|
209
|
+
console.log(chalk2.dim("\n Top files with issues:"));
|
|
210
|
+
topFiles.forEach((item) => {
|
|
211
|
+
console.log(
|
|
212
|
+
` ${chalk2.yellow("\u2192")} ${item.file}: ${chalk2.bold(item.count)} issues`
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
136
216
|
console.log(
|
|
137
|
-
`
|
|
138
|
-
)
|
|
139
|
-
console.log(
|
|
140
|
-
` Execution time: ${chalk2.bold(((Date.now() - startTime) / 1e3).toFixed(2) + "s")}`
|
|
217
|
+
`
|
|
218
|
+
Execution time: ${chalk2.bold(((Date.now() - startTime) / 1e3).toFixed(2) + "s")}`
|
|
141
219
|
);
|
|
142
220
|
}
|
|
143
221
|
function printBusinessImpact(roi, unifiedBudget) {
|
|
@@ -164,13 +242,14 @@ function printScoring(scoringResult, scoringProfile) {
|
|
|
164
242
|
scoringResult.breakdown.forEach((tool) => {
|
|
165
243
|
const rating = getRating(tool.score);
|
|
166
244
|
const emoji = getRatingDisplay(rating).emoji;
|
|
245
|
+
const progressBar = generateProgressBar(tool.score, 15);
|
|
167
246
|
console.log(
|
|
168
|
-
`
|
|
247
|
+
` ${progressBar} ${tool.score}/100 (${rating}) ${emoji} ${tool.toolName}`
|
|
169
248
|
);
|
|
170
249
|
});
|
|
171
250
|
const allRecs = scoringResult.breakdown.flatMap(
|
|
172
|
-
(t) => (t.recommendations
|
|
173
|
-
).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0,
|
|
251
|
+
(t) => (t.recommendations ?? []).map((r) => ({ ...r, tool: t.toolName }))
|
|
252
|
+
).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 5);
|
|
174
253
|
if (allRecs.length > 0) {
|
|
175
254
|
console.log(chalk2.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
|
|
176
255
|
allRecs.forEach((rec, i) => {
|
|
@@ -223,8 +302,8 @@ import { handleCLIError } from "@aiready/core";
|
|
|
223
302
|
async function uploadAction(file, options) {
|
|
224
303
|
const startTime = Date.now();
|
|
225
304
|
const filePath = resolvePath2(process.cwd(), file);
|
|
226
|
-
const serverUrl = options.server
|
|
227
|
-
const apiKey = options.apiKey
|
|
305
|
+
const serverUrl = options.server ?? process.env.AIREADY_SERVER ?? "https://dev.platform.getaiready.dev";
|
|
306
|
+
const apiKey = options.apiKey ?? process.env.AIREADY_API_KEY;
|
|
228
307
|
if (!apiKey) {
|
|
229
308
|
console.error(chalk3.red("\u274C API Key is required for upload."));
|
|
230
309
|
console.log(
|
|
@@ -249,7 +328,7 @@ async function uploadAction(file, options) {
|
|
|
249
328
|
const reportContent = fs.readFileSync(filePath, "utf-8");
|
|
250
329
|
const reportData = JSON.parse(reportContent);
|
|
251
330
|
console.log(chalk3.dim(` Successfully parsed report JSON.`));
|
|
252
|
-
const repoId = options.repoId
|
|
331
|
+
const repoId = options.repoId ?? reportData.repository?.repoId;
|
|
253
332
|
const response = await fetch(`${serverUrl}/api/analysis/upload`, {
|
|
254
333
|
method: "POST",
|
|
255
334
|
headers: {
|
|
@@ -268,12 +347,12 @@ async function uploadAction(file, options) {
|
|
|
268
347
|
uploadResult = await response.json();
|
|
269
348
|
} else {
|
|
270
349
|
const text = await response.text();
|
|
271
|
-
uploadResult = { error: text
|
|
350
|
+
uploadResult = { error: text ?? response.statusText };
|
|
272
351
|
}
|
|
273
352
|
if (!response.ok) {
|
|
274
353
|
console.error(
|
|
275
354
|
chalk3.red(
|
|
276
|
-
`\u274C Upload failed: ${uploadResult.error
|
|
355
|
+
`\u274C Upload failed: ${uploadResult.error ?? response.statusText}`
|
|
277
356
|
)
|
|
278
357
|
);
|
|
279
358
|
if (contentType?.includes("text/html")) {
|
|
@@ -324,7 +403,7 @@ ENVIRONMENT VARIABLES:
|
|
|
324
403
|
async function scanAction(directory, options) {
|
|
325
404
|
console.log(chalk4.blue("\u{1F680} Starting AIReady unified analysis...\n"));
|
|
326
405
|
const startTime = Date.now();
|
|
327
|
-
const resolvedDir = resolvePath3(process.cwd(), directory
|
|
406
|
+
const resolvedDir = resolvePath3(process.cwd(), directory ?? ".");
|
|
328
407
|
const repoMetadata = getRepoMetadata(resolvedDir);
|
|
329
408
|
try {
|
|
330
409
|
const defaults = {
|
|
@@ -414,7 +493,7 @@ async function scanAction(directory, options) {
|
|
|
414
493
|
const { getSmartDefaults } = await import("@aiready/pattern-detect");
|
|
415
494
|
const patternSmartDefaults = await getSmartDefaults(
|
|
416
495
|
resolvedDir,
|
|
417
|
-
finalOptions.toolConfigs?.[ToolName.PatternDetect]
|
|
496
|
+
finalOptions.toolConfigs?.[ToolName.PatternDetect] ?? {}
|
|
418
497
|
);
|
|
419
498
|
if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
|
|
420
499
|
finalOptions.toolConfigs[ToolName.PatternDetect] = {
|
|
@@ -425,7 +504,7 @@ async function scanAction(directory, options) {
|
|
|
425
504
|
console.log(chalk4.cyan("\n=== AIReady Run Preview ==="));
|
|
426
505
|
console.log(
|
|
427
506
|
chalk4.white("Tools to run:"),
|
|
428
|
-
(finalOptions.tools
|
|
507
|
+
(finalOptions.tools ?? []).join(", ")
|
|
429
508
|
);
|
|
430
509
|
const progressCallback = (event) => {
|
|
431
510
|
if (event.message) {
|
|
@@ -446,7 +525,7 @@ async function scanAction(directory, options) {
|
|
|
446
525
|
);
|
|
447
526
|
}
|
|
448
527
|
};
|
|
449
|
-
const scoringProfile = options.profile
|
|
528
|
+
const scoringProfile = options.profile ?? baseOptions.scoring?.profile ?? "default";
|
|
450
529
|
const results = await analyzeUnified({
|
|
451
530
|
...finalOptions,
|
|
452
531
|
progressCallback,
|
|
@@ -470,7 +549,7 @@ async function scanAction(directory, options) {
|
|
|
470
549
|
const prevReport = JSON.parse(
|
|
471
550
|
readFileSync2(resolvePath3(process.cwd(), options.compareTo), "utf8")
|
|
472
551
|
);
|
|
473
|
-
const prevScore = prevReport.scoring?.overall
|
|
552
|
+
const prevScore = prevReport.scoring?.overall ?? prevReport.scoring?.score;
|
|
474
553
|
if (typeof prevScore === "number") {
|
|
475
554
|
const diff = scoringResult.overall - prevScore;
|
|
476
555
|
const diffStr = diff > 0 ? `+${diff}` : String(diff);
|
|
@@ -497,17 +576,17 @@ async function scanAction(directory, options) {
|
|
|
497
576
|
void e;
|
|
498
577
|
}
|
|
499
578
|
}
|
|
500
|
-
const totalWastedDuplication = (scoringResult.breakdown
|
|
501
|
-
(sum, s) => sum + (s.tokenBudget?.wastedTokens
|
|
579
|
+
const totalWastedDuplication = (scoringResult.breakdown ?? []).reduce(
|
|
580
|
+
(sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.duplication ?? 0),
|
|
502
581
|
0
|
|
503
582
|
);
|
|
504
|
-
const totalWastedFragmentation = (scoringResult.breakdown
|
|
505
|
-
(sum, s) => sum + (s.tokenBudget?.wastedTokens
|
|
583
|
+
const totalWastedFragmentation = (scoringResult.breakdown ?? []).reduce(
|
|
584
|
+
(sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.fragmentation ?? 0),
|
|
506
585
|
0
|
|
507
586
|
);
|
|
508
587
|
const totalContext = Math.max(
|
|
509
|
-
...(scoringResult.breakdown
|
|
510
|
-
(s) => s.tokenBudget?.totalContextTokens
|
|
588
|
+
...(scoringResult.breakdown ?? []).map(
|
|
589
|
+
(s) => s.tokenBudget?.totalContextTokens ?? 0
|
|
511
590
|
),
|
|
512
591
|
0
|
|
513
592
|
);
|
|
@@ -531,7 +610,7 @@ async function scanAction(directory, options) {
|
|
|
531
610
|
});
|
|
532
611
|
}
|
|
533
612
|
}
|
|
534
|
-
const modelId = options.model
|
|
613
|
+
const modelId = options.model ?? "gpt-5.4-mini";
|
|
535
614
|
const roi = (await import("@aiready/core")).calculateBusinessROI({
|
|
536
615
|
tokenWaste: unifiedBudget.wastedTokens.total,
|
|
537
616
|
issues: allIssues,
|
|
@@ -568,9 +647,9 @@ async function scanAction(directory, options) {
|
|
|
568
647
|
...mapToUnifiedReport(results, scoringResult),
|
|
569
648
|
repository: repoMetadata
|
|
570
649
|
};
|
|
571
|
-
const outputFormat = options.output
|
|
650
|
+
const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
|
|
572
651
|
const outputPath = resolveOutputPath(
|
|
573
|
-
options.outputFile
|
|
652
|
+
options.outputFile ?? finalOptions.output?.file,
|
|
574
653
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
575
654
|
resolvedDir
|
|
576
655
|
);
|
|
@@ -597,8 +676,8 @@ async function scanAction(directory, options) {
|
|
|
597
676
|
await warnIfGraphCapExceeded(outputData, resolvedDir);
|
|
598
677
|
if (scoringResult) {
|
|
599
678
|
const threshold = options.threshold ? parseInt(options.threshold) : void 0;
|
|
600
|
-
const failOnLevel = options.failOn
|
|
601
|
-
const isCI = options.ci
|
|
679
|
+
const failOnLevel = options.failOn ?? "critical";
|
|
680
|
+
const isCI = options.ci ?? process.env.CI === "true";
|
|
602
681
|
let shouldFail = false;
|
|
603
682
|
let failReason = "";
|
|
604
683
|
const report = mapToUnifiedReport(results, scoringResult);
|
|
@@ -654,6 +733,9 @@ async function initAction(options) {
|
|
|
654
733
|
process.exit(1);
|
|
655
734
|
}
|
|
656
735
|
const baseConfig = {
|
|
736
|
+
// Target quality score threshold (0-100)
|
|
737
|
+
threshold: 75,
|
|
738
|
+
// Global scan settings
|
|
657
739
|
scan: {
|
|
658
740
|
include: [
|
|
659
741
|
"src/**/*.ts",
|
|
@@ -680,6 +762,17 @@ async function initAction(options) {
|
|
|
680
762
|
ToolName2.ChangeAmplification
|
|
681
763
|
]
|
|
682
764
|
},
|
|
765
|
+
// Output preferences
|
|
766
|
+
output: {
|
|
767
|
+
format: "console",
|
|
768
|
+
showBreakdown: true,
|
|
769
|
+
saveTo: "aiready-report.json"
|
|
770
|
+
},
|
|
771
|
+
// Scoring profile and weights
|
|
772
|
+
scoring: {
|
|
773
|
+
profile: "balanced"
|
|
774
|
+
},
|
|
775
|
+
// Tool-specific configurations
|
|
683
776
|
tools: {
|
|
684
777
|
[ToolName2.PatternDetect]: {
|
|
685
778
|
minSimilarity: 0.8,
|
|
@@ -703,7 +796,33 @@ async function initAction(options) {
|
|
|
703
796
|
},
|
|
704
797
|
[ToolName2.NamingConsistency]: {
|
|
705
798
|
shortWords: ["id", "db", "ui", "ai"],
|
|
706
|
-
|
|
799
|
+
acceptedAbbreviations: [
|
|
800
|
+
"API",
|
|
801
|
+
"JSON",
|
|
802
|
+
"CSV",
|
|
803
|
+
"HTML",
|
|
804
|
+
"CSS",
|
|
805
|
+
"HTTP",
|
|
806
|
+
"URL",
|
|
807
|
+
"SDK",
|
|
808
|
+
"CLI",
|
|
809
|
+
"AI",
|
|
810
|
+
"ML",
|
|
811
|
+
"ID",
|
|
812
|
+
"DB",
|
|
813
|
+
"UI",
|
|
814
|
+
"UX",
|
|
815
|
+
"DOM",
|
|
816
|
+
"UUID",
|
|
817
|
+
"GUID",
|
|
818
|
+
"DEFAULT",
|
|
819
|
+
"MAX",
|
|
820
|
+
"MIN",
|
|
821
|
+
"config",
|
|
822
|
+
"INIT",
|
|
823
|
+
"SKILL"
|
|
824
|
+
],
|
|
825
|
+
...options.full ? { disableChecks: [] } : {}
|
|
707
826
|
},
|
|
708
827
|
[ToolName2.AiSignalClarity]: {
|
|
709
828
|
checkMagicLiterals: true,
|
|
@@ -712,48 +831,42 @@ async function initAction(options) {
|
|
|
712
831
|
checkUndocumentedExports: true,
|
|
713
832
|
...options.full ? { checkImplicitSideEffects: false, checkDeepCallbacks: false } : {}
|
|
714
833
|
},
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
scoring: {
|
|
734
|
-
threshold: 70,
|
|
735
|
-
showBreakdown: true,
|
|
736
|
-
...options.full ? { profile: "default" } : {}
|
|
834
|
+
[ToolName2.AgentGrounding]: {
|
|
835
|
+
maxRecommendedDepth: 5,
|
|
836
|
+
readmeStaleDays: 30
|
|
837
|
+
},
|
|
838
|
+
[ToolName2.TestabilityIndex]: {
|
|
839
|
+
minCoverageRatio: 0.7,
|
|
840
|
+
testPatterns: ["**/*.test.ts", "**/__tests__/**"]
|
|
841
|
+
},
|
|
842
|
+
[ToolName2.DocDrift]: {
|
|
843
|
+
maxCommits: 50,
|
|
844
|
+
staleMonths: 3
|
|
845
|
+
},
|
|
846
|
+
[ToolName2.DependencyHealth]: {
|
|
847
|
+
trainingCutoffYear: 2023
|
|
848
|
+
},
|
|
849
|
+
[ToolName2.ChangeAmplification]: {
|
|
850
|
+
// No specific options yet, uses global scan settings
|
|
851
|
+
}
|
|
737
852
|
},
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
}
|
|
853
|
+
// Visualizer settings (interactive graph)
|
|
854
|
+
visualizer: {
|
|
855
|
+
groupingDirs: ["packages", "src", "lib"],
|
|
856
|
+
graph: {
|
|
857
|
+
maxNodes: 5e3,
|
|
858
|
+
maxEdges: 1e4
|
|
745
859
|
}
|
|
746
|
-
}
|
|
860
|
+
}
|
|
747
861
|
};
|
|
748
862
|
const defaultConfig = baseConfig;
|
|
749
863
|
let content;
|
|
750
864
|
if (fileExt === "js") {
|
|
751
|
-
content = `/**
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
)};
|
|
865
|
+
content = `/**
|
|
866
|
+
* AIReady Configuration
|
|
867
|
+
* @type {import('@aiready/core').AIReadyConfig}
|
|
868
|
+
*/
|
|
869
|
+
module.exports = ${JSON.stringify(defaultConfig, null, 2)};
|
|
757
870
|
`;
|
|
758
871
|
} else {
|
|
759
872
|
content = JSON.stringify(defaultConfig, null, 2);
|
|
@@ -789,7 +902,7 @@ import {
|
|
|
789
902
|
async function patternsAction(directory, options) {
|
|
790
903
|
console.log(chalk6.blue("\u{1F50D} Analyzing patterns...\n"));
|
|
791
904
|
const startTime = Date.now();
|
|
792
|
-
const resolvedDir = resolvePath4(process.cwd(), directory
|
|
905
|
+
const resolvedDir = resolvePath4(process.cwd(), directory ?? ".");
|
|
793
906
|
try {
|
|
794
907
|
const useSmartDefaults = !options.fullScan;
|
|
795
908
|
const defaults = {
|
|
@@ -833,8 +946,8 @@ async function patternsAction(directory, options) {
|
|
|
833
946
|
if (options.score) {
|
|
834
947
|
patternScore = calculatePatternScore(duplicates, results.length);
|
|
835
948
|
}
|
|
836
|
-
const outputFormat = options.output
|
|
837
|
-
const userOutputFile = options.outputFile
|
|
949
|
+
const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
|
|
950
|
+
const userOutputFile = options.outputFile ?? finalOptions.output?.file;
|
|
838
951
|
if (outputFormat === "json") {
|
|
839
952
|
const outputData = {
|
|
840
953
|
results,
|
|
@@ -942,7 +1055,7 @@ import {
|
|
|
942
1055
|
async function contextAction(directory, options) {
|
|
943
1056
|
console.log(chalk7.blue("\u{1F9E0} Analyzing context costs...\n"));
|
|
944
1057
|
const startTime = Date.now();
|
|
945
|
-
const resolvedDir = resolvePath5(process.cwd(), directory
|
|
1058
|
+
const resolvedDir = resolvePath5(process.cwd(), directory ?? ".");
|
|
946
1059
|
try {
|
|
947
1060
|
const defaults = {
|
|
948
1061
|
maxDepth: 5,
|
|
@@ -986,8 +1099,8 @@ async function contextAction(directory, options) {
|
|
|
986
1099
|
if (options.score) {
|
|
987
1100
|
contextScore = calculateContextScore(summary);
|
|
988
1101
|
}
|
|
989
|
-
const outputFormat = options.output
|
|
990
|
-
const userOutputFile = options.outputFile
|
|
1102
|
+
const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
|
|
1103
|
+
const userOutputFile = options.outputFile ?? finalOptions.output?.file;
|
|
991
1104
|
if (outputFormat === "json") {
|
|
992
1105
|
const outputData = {
|
|
993
1106
|
results,
|
|
@@ -1005,7 +1118,7 @@ async function contextAction(directory, options) {
|
|
|
1005
1118
|
`\u2705 Results saved to ${outputPath}`
|
|
1006
1119
|
);
|
|
1007
1120
|
} else {
|
|
1008
|
-
const terminalWidth = process.stdout.columns
|
|
1121
|
+
const terminalWidth = process.stdout.columns ?? 80;
|
|
1009
1122
|
const dividerWidth = Math.min(60, terminalWidth - 2);
|
|
1010
1123
|
const divider = "\u2501".repeat(dividerWidth);
|
|
1011
1124
|
console.log(chalk7.cyan(divider));
|
|
@@ -1150,7 +1263,7 @@ import {
|
|
|
1150
1263
|
async function consistencyAction(directory, options) {
|
|
1151
1264
|
console.log(chalk8.blue("\u{1F50D} Analyzing consistency...\n"));
|
|
1152
1265
|
const startTime = Date.now();
|
|
1153
|
-
const resolvedDir = resolvePath6(process.cwd(), directory
|
|
1266
|
+
const resolvedDir = resolvePath6(process.cwd(), directory ?? ".");
|
|
1154
1267
|
try {
|
|
1155
1268
|
const defaults = {
|
|
1156
1269
|
checkNaming: true,
|
|
@@ -1175,14 +1288,14 @@ async function consistencyAction(directory, options) {
|
|
|
1175
1288
|
const elapsedTime = getElapsedTime3(startTime);
|
|
1176
1289
|
let consistencyScore;
|
|
1177
1290
|
if (options.score) {
|
|
1178
|
-
const issues = report.results?.flatMap((r) => r.issues)
|
|
1291
|
+
const issues = report.results?.flatMap((r) => r.issues) ?? [];
|
|
1179
1292
|
consistencyScore = calculateConsistencyScore(
|
|
1180
1293
|
issues,
|
|
1181
1294
|
report.summary.filesAnalyzed
|
|
1182
1295
|
);
|
|
1183
1296
|
}
|
|
1184
|
-
const outputFormat = options.output
|
|
1185
|
-
const userOutputFile = options.outputFile
|
|
1297
|
+
const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
|
|
1298
|
+
const userOutputFile = options.outputFile ?? finalOptions.output?.file;
|
|
1186
1299
|
if (outputFormat === "json") {
|
|
1187
1300
|
const outputData = {
|
|
1188
1301
|
...report,
|
|
@@ -1220,7 +1333,7 @@ async function consistencyAction(directory, options) {
|
|
|
1220
1333
|
console.log(` Naming: ${chalk8.yellow(report.summary.namingIssues)}`);
|
|
1221
1334
|
console.log(` Patterns: ${chalk8.yellow(report.summary.patternIssues)}`);
|
|
1222
1335
|
console.log(
|
|
1223
|
-
` Architecture: ${chalk8.yellow(report.summary.architectureIssues
|
|
1336
|
+
` Architecture: ${chalk8.yellow(report.summary.architectureIssues ?? 0)}`
|
|
1224
1337
|
);
|
|
1225
1338
|
console.log(`Analysis Time: ${chalk8.gray(elapsedTime + "s")}
|
|
1226
1339
|
`);
|
|
@@ -1319,7 +1432,7 @@ import { handleCLIError as handleCLIError6 } from "@aiready/core";
|
|
|
1319
1432
|
import { generateHTML, findLatestReport as findLatestReport2 } from "@aiready/core";
|
|
1320
1433
|
async function visualizeAction(directory, options) {
|
|
1321
1434
|
try {
|
|
1322
|
-
const dirPath = resolvePath7(process.cwd(), directory
|
|
1435
|
+
const dirPath = resolvePath7(process.cwd(), directory ?? ".");
|
|
1323
1436
|
let reportPath = options.report ? resolvePath7(dirPath, options.report) : null;
|
|
1324
1437
|
if (!reportPath || !existsSync3(reportPath)) {
|
|
1325
1438
|
const latestScan = findLatestReport2(dirPath);
|
|
@@ -1365,7 +1478,7 @@ Or specify a custom report:
|
|
|
1365
1478
|
console.log("Building graph from report...");
|
|
1366
1479
|
const { GraphBuilder } = await import("@aiready/visualizer/graph");
|
|
1367
1480
|
const graph = GraphBuilder.buildFromReport(report, dirPath);
|
|
1368
|
-
let useDevMode = options.dev
|
|
1481
|
+
let useDevMode = options.dev ?? false;
|
|
1369
1482
|
let devServerStarted = false;
|
|
1370
1483
|
if (useDevMode) {
|
|
1371
1484
|
try {
|
|
@@ -1481,7 +1594,7 @@ Or specify a custom report:
|
|
|
1481
1594
|
console.log("Generating HTML...");
|
|
1482
1595
|
const html = generateHTML(graph);
|
|
1483
1596
|
const defaultOutput = "visualization.html";
|
|
1484
|
-
const outPath = resolvePath7(dirPath, options.output
|
|
1597
|
+
const outPath = resolvePath7(dirPath, options.output ?? defaultOutput);
|
|
1485
1598
|
writeFileSync4(outPath, html, "utf8");
|
|
1486
1599
|
console.log(chalk9.green(`\u2705 Visualization written to: ${outPath}`));
|
|
1487
1600
|
if (options.open || options.serve) {
|
|
@@ -1493,7 +1606,7 @@ Or specify a custom report:
|
|
|
1493
1606
|
const fsp = await import("fs/promises");
|
|
1494
1607
|
const server = http.createServer(async (req, res) => {
|
|
1495
1608
|
try {
|
|
1496
|
-
const urlPath = req.url
|
|
1609
|
+
const urlPath = req.url ?? "/";
|
|
1497
1610
|
if (urlPath === "/" || urlPath === "/index.html") {
|
|
1498
1611
|
const content = await fsp.readFile(outPath, "utf8");
|
|
1499
1612
|
res.writeHead(200, {
|
|
@@ -1631,7 +1744,7 @@ async function bugAction(message, options) {
|
|
|
1631
1744
|
const repoUrl = "https://github.com/caopengau/aiready-cli";
|
|
1632
1745
|
const repoSlug = "caopengau/aiready-cli";
|
|
1633
1746
|
if (message) {
|
|
1634
|
-
const type = options.type
|
|
1747
|
+
const type = options.type ?? "bug";
|
|
1635
1748
|
const title = `[${type.toUpperCase()}] ${message}`;
|
|
1636
1749
|
const label = type === "bug" ? "bug" : type === "feature" ? "enhancement" : "metric";
|
|
1637
1750
|
const body = `
|
package/dist/index.js
CHANGED
|
@@ -84,7 +84,7 @@ function sanitizeToolConfig(config) {
|
|
|
84
84
|
async function analyzeUnified(options) {
|
|
85
85
|
await (0, import_core.initializeParsers)();
|
|
86
86
|
const startTime = Date.now();
|
|
87
|
-
const requestedTools = options.tools
|
|
87
|
+
const requestedTools = options.tools ?? [
|
|
88
88
|
"patterns",
|
|
89
89
|
"context",
|
|
90
90
|
"consistency"
|
|
@@ -106,7 +106,7 @@ async function analyzeUnified(options) {
|
|
|
106
106
|
for (const toolName of requestedTools) {
|
|
107
107
|
let provider = import_core.ToolRegistry.find(toolName);
|
|
108
108
|
if (!provider) {
|
|
109
|
-
const packageName = TOOL_PACKAGE_MAP[toolName]
|
|
109
|
+
const packageName = TOOL_PACKAGE_MAP[toolName] ?? (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
|
|
110
110
|
try {
|
|
111
111
|
await import(packageName);
|
|
112
112
|
provider = import_core.ToolRegistry.find(toolName);
|
|
@@ -184,29 +184,15 @@ async function analyzeUnified(options) {
|
|
|
184
184
|
} else {
|
|
185
185
|
result.summary.toolConfigs[provider.id] = sanitizeToolConfig(toolOptions);
|
|
186
186
|
}
|
|
187
|
-
const toolFiles = output.summary?.totalFiles
|
|
187
|
+
const toolFiles = output.summary?.totalFiles ?? output.summary?.filesAnalyzed ?? 0;
|
|
188
188
|
if (toolFiles > result.summary.totalFiles) {
|
|
189
189
|
result.summary.totalFiles = toolFiles;
|
|
190
190
|
}
|
|
191
191
|
const issueCount = output.results.reduce(
|
|
192
|
-
(sum, file) => sum + (file.issues?.length
|
|
192
|
+
(sum, file) => sum + (file.issues?.length ?? 0),
|
|
193
193
|
0
|
|
194
194
|
);
|
|
195
195
|
result.summary.totalIssues += issueCount;
|
|
196
|
-
if (provider.alias && Array.isArray(provider.alias)) {
|
|
197
|
-
for (const alias of provider.alias) {
|
|
198
|
-
if (!result[alias]) {
|
|
199
|
-
result[alias] = output;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
const camelCaseId = provider.id.replace(
|
|
204
|
-
/-([a-z])/g,
|
|
205
|
-
(g) => g[1].toUpperCase()
|
|
206
|
-
);
|
|
207
|
-
if (camelCaseId !== provider.id && !result[camelCaseId]) {
|
|
208
|
-
result[camelCaseId] = output;
|
|
209
|
-
}
|
|
210
196
|
} catch (err) {
|
|
211
197
|
console.error(`\u274C Error running tool '${provider.id}':`, err);
|
|
212
198
|
}
|
|
@@ -221,6 +207,24 @@ async function analyzeUnified(options) {
|
|
|
221
207
|
tools: result.summary.toolConfigs
|
|
222
208
|
});
|
|
223
209
|
result.summary.executionTime = Date.now() - startTime;
|
|
210
|
+
const keyMappings = {
|
|
211
|
+
"pattern-detect": ["patternDetect", "patterns"],
|
|
212
|
+
"context-analyzer": ["contextAnalyzer", "context"],
|
|
213
|
+
"naming-consistency": ["namingConsistency", "consistency"],
|
|
214
|
+
"ai-signal-clarity": ["aiSignalClarity"],
|
|
215
|
+
"agent-grounding": ["agentGrounding"],
|
|
216
|
+
"testability-index": ["testabilityIndex", "testability"],
|
|
217
|
+
"doc-drift": ["docDrift"],
|
|
218
|
+
"dependency-health": ["dependencyHealth", "deps"],
|
|
219
|
+
"change-amplification": ["changeAmplification"]
|
|
220
|
+
};
|
|
221
|
+
for (const [kebabKey, aliases] of Object.entries(keyMappings)) {
|
|
222
|
+
if (result[kebabKey]) {
|
|
223
|
+
for (const alias of aliases) {
|
|
224
|
+
result[alias] = result[kebabKey];
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
224
228
|
return result;
|
|
225
229
|
}
|
|
226
230
|
async function scoreUnified(results, options) {
|
|
@@ -235,7 +239,7 @@ async function scoreUnified(results, options) {
|
|
|
235
239
|
if (!toolScore.tokenBudget) {
|
|
236
240
|
if (toolId === import_core.ToolName.PatternDetect && output.duplicates) {
|
|
237
241
|
const wastedTokens = output.duplicates.reduce(
|
|
238
|
-
(sum, d) => sum + (d.tokenCost
|
|
242
|
+
(sum, d) => sum + (d.tokenCost ?? 0),
|
|
239
243
|
0
|
|
240
244
|
);
|
|
241
245
|
toolScore.tokenBudget = (0, import_core.calculateTokenBudget)({
|
|
@@ -251,7 +255,7 @@ async function scoreUnified(results, options) {
|
|
|
251
255
|
totalContextTokens: output.summary.totalTokens,
|
|
252
256
|
wastedTokens: {
|
|
253
257
|
duplication: 0,
|
|
254
|
-
fragmentation: output.summary.totalPotentialSavings
|
|
258
|
+
fragmentation: output.summary.totalPotentialSavings ?? 0,
|
|
255
259
|
chattiness: 0
|
|
256
260
|
}
|
|
257
261
|
});
|
|
@@ -296,7 +300,7 @@ function generateUnifiedSummary(result) {
|
|
|
296
300
|
const toolResult = result[provider.id];
|
|
297
301
|
if (toolResult) {
|
|
298
302
|
const issueCount = toolResult.results.reduce(
|
|
299
|
-
(sum, r) => sum + (r.issues?.length
|
|
303
|
+
(sum, r) => sum + (r.issues?.length ?? 0),
|
|
300
304
|
0
|
|
301
305
|
);
|
|
302
306
|
output += `\u2022 ${provider.id}: ${issueCount} issues
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/cli",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.11",
|
|
4
4
|
"description": "Unified CLI for AIReady analysis tools",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"chalk": "^5.3.0",
|
|
13
13
|
"commander": "^14.0.0",
|
|
14
|
-
"@aiready/
|
|
15
|
-
"@aiready/consistency": "0.20.
|
|
16
|
-
"@aiready/
|
|
17
|
-
"@aiready/
|
|
18
|
-
"@aiready/
|
|
19
|
-
"@aiready/
|
|
20
|
-
"@aiready/visualizer": "0.6.
|
|
21
|
-
"@aiready/
|
|
22
|
-
"@aiready/
|
|
23
|
-
"@aiready/testability": "0.6.
|
|
24
|
-
"@aiready/
|
|
14
|
+
"@aiready/context-analyzer": "0.21.12",
|
|
15
|
+
"@aiready/consistency": "0.20.8",
|
|
16
|
+
"@aiready/core": "0.23.9",
|
|
17
|
+
"@aiready/agent-grounding": "0.13.8",
|
|
18
|
+
"@aiready/pattern-detect": "0.16.8",
|
|
19
|
+
"@aiready/deps": "0.13.9",
|
|
20
|
+
"@aiready/visualizer": "0.6.8",
|
|
21
|
+
"@aiready/change-amplification": "0.13.8",
|
|
22
|
+
"@aiready/doc-drift": "0.13.8",
|
|
23
|
+
"@aiready/testability": "0.6.8",
|
|
24
|
+
"@aiready/ai-signal-clarity": "0.13.9"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^24.0.0",
|