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