@aiready/consistency 0.20.5 → 0.20.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +23 -24
- package/.turbo/turbo-test.log +25 -27
- package/dist/chunk-DNGW3WQK.mjs +810 -0
- package/dist/chunk-Q3KTWDSL.mjs +808 -0
- package/dist/chunk-TE6JYZD3.mjs +810 -0
- package/dist/cli.js +85 -6
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +12 -10
- package/dist/index.d.ts +12 -10
- package/dist/index.js +85 -6
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/src/analyzer.ts +21 -4
- package/src/analyzers/naming-ast.ts +29 -0
- package/src/analyzers/naming-generalized.ts +67 -5
- package/src/scoring.ts +6 -8
package/dist/cli.js
CHANGED
|
@@ -413,7 +413,36 @@ function isCommonAbbreviation(name) {
|
|
|
413
413
|
"ux",
|
|
414
414
|
"api",
|
|
415
415
|
"env",
|
|
416
|
-
"url"
|
|
416
|
+
"url",
|
|
417
|
+
"req",
|
|
418
|
+
"res",
|
|
419
|
+
"err",
|
|
420
|
+
"ctx",
|
|
421
|
+
"cb",
|
|
422
|
+
"idx",
|
|
423
|
+
"src",
|
|
424
|
+
"dir",
|
|
425
|
+
"app",
|
|
426
|
+
"dev",
|
|
427
|
+
"qa",
|
|
428
|
+
"dto",
|
|
429
|
+
"dao",
|
|
430
|
+
"ref",
|
|
431
|
+
"ast",
|
|
432
|
+
"dom",
|
|
433
|
+
"log",
|
|
434
|
+
"msg",
|
|
435
|
+
"pkg",
|
|
436
|
+
"req",
|
|
437
|
+
"err",
|
|
438
|
+
"res",
|
|
439
|
+
"css",
|
|
440
|
+
"html",
|
|
441
|
+
"xml",
|
|
442
|
+
"jsx",
|
|
443
|
+
"tsx",
|
|
444
|
+
"ts",
|
|
445
|
+
"js"
|
|
417
446
|
];
|
|
418
447
|
return common.includes(name.toLowerCase());
|
|
419
448
|
}
|
|
@@ -463,6 +492,44 @@ function extractDestructuredIdentifiers(node, isParameter, scopeTracker) {
|
|
|
463
492
|
// src/analyzers/naming-generalized.ts
|
|
464
493
|
var import_core3 = require("@aiready/core");
|
|
465
494
|
var import_fs2 = require("fs");
|
|
495
|
+
var COMMON_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
496
|
+
"id",
|
|
497
|
+
"db",
|
|
498
|
+
"fs",
|
|
499
|
+
"os",
|
|
500
|
+
"ip",
|
|
501
|
+
"ui",
|
|
502
|
+
"ux",
|
|
503
|
+
"api",
|
|
504
|
+
"env",
|
|
505
|
+
"url",
|
|
506
|
+
"req",
|
|
507
|
+
"res",
|
|
508
|
+
"err",
|
|
509
|
+
"ctx",
|
|
510
|
+
"cb",
|
|
511
|
+
"idx",
|
|
512
|
+
"src",
|
|
513
|
+
"dir",
|
|
514
|
+
"app",
|
|
515
|
+
"dev",
|
|
516
|
+
"qa",
|
|
517
|
+
"dto",
|
|
518
|
+
"dao",
|
|
519
|
+
"ref",
|
|
520
|
+
"ast",
|
|
521
|
+
"dom",
|
|
522
|
+
"log",
|
|
523
|
+
"msg",
|
|
524
|
+
"pkg",
|
|
525
|
+
"css",
|
|
526
|
+
"html",
|
|
527
|
+
"xml",
|
|
528
|
+
"jsx",
|
|
529
|
+
"tsx",
|
|
530
|
+
"ts",
|
|
531
|
+
"js"
|
|
532
|
+
]);
|
|
466
533
|
async function analyzeNamingGeneralized(files) {
|
|
467
534
|
const issues = [];
|
|
468
535
|
for (const file of files) {
|
|
@@ -470,10 +537,15 @@ async function analyzeNamingGeneralized(files) {
|
|
|
470
537
|
if (!parser) continue;
|
|
471
538
|
try {
|
|
472
539
|
const code = (0, import_fs2.readFileSync)(file, "utf-8");
|
|
540
|
+
if (!code.trim()) continue;
|
|
473
541
|
await parser.initialize();
|
|
474
542
|
const result = parser.parse(code, file);
|
|
475
543
|
const conventions = parser.getNamingConventions();
|
|
544
|
+
const exceptions = new Set(conventions.exceptions || []);
|
|
476
545
|
for (const exp of result.exports) {
|
|
546
|
+
if (!exp.name || exp.name === "default") continue;
|
|
547
|
+
if (exceptions.has(exp.name)) continue;
|
|
548
|
+
if (COMMON_ABBREVIATIONS.has(exp.name.toLowerCase())) continue;
|
|
477
549
|
let pattern;
|
|
478
550
|
if (exp.type === "class") {
|
|
479
551
|
pattern = conventions.classPattern;
|
|
@@ -484,7 +556,7 @@ async function analyzeNamingGeneralized(files) {
|
|
|
484
556
|
} else if (exp.type === "function") {
|
|
485
557
|
pattern = conventions.functionPattern;
|
|
486
558
|
} else if (exp.type === "const") {
|
|
487
|
-
pattern = conventions.constantPattern;
|
|
559
|
+
pattern = exp.isPrimitive ? conventions.constantPattern : conventions.variablePattern;
|
|
488
560
|
} else {
|
|
489
561
|
pattern = conventions.variablePattern;
|
|
490
562
|
}
|
|
@@ -495,7 +567,8 @@ async function analyzeNamingGeneralized(files) {
|
|
|
495
567
|
file,
|
|
496
568
|
line: exp.loc?.start.line || 1,
|
|
497
569
|
column: exp.loc?.start.column || 0,
|
|
498
|
-
|
|
570
|
+
// Recalibrate naming issues to Minor to differentiate from structural/architectural issues
|
|
571
|
+
severity: import_core3.Severity.Minor,
|
|
499
572
|
category: "naming",
|
|
500
573
|
suggestion: `Follow ${parser.language} ${exp.type} naming convention: ${pattern.toString()}`
|
|
501
574
|
});
|
|
@@ -503,7 +576,9 @@ async function analyzeNamingGeneralized(files) {
|
|
|
503
576
|
}
|
|
504
577
|
for (const imp of result.imports) {
|
|
505
578
|
for (const spec of imp.specifiers) {
|
|
506
|
-
if (spec === "*" || spec === "default") continue;
|
|
579
|
+
if (!spec || spec === "*" || spec === "default") continue;
|
|
580
|
+
if (exceptions.has(spec)) continue;
|
|
581
|
+
if (COMMON_ABBREVIATIONS.has(spec.toLowerCase())) continue;
|
|
507
582
|
if (!conventions.variablePattern.test(spec) && !conventions.classPattern.test(spec)) {
|
|
508
583
|
issues.push({
|
|
509
584
|
type: "naming-inconsistency",
|
|
@@ -511,7 +586,8 @@ async function analyzeNamingGeneralized(files) {
|
|
|
511
586
|
file,
|
|
512
587
|
line: imp.loc?.start.line || 1,
|
|
513
588
|
column: imp.loc?.start.column || 0,
|
|
514
|
-
severity: import_core3.Severity.
|
|
589
|
+
severity: import_core3.Severity.Info,
|
|
590
|
+
// Reduced from Minor to Info for imports
|
|
515
591
|
category: "naming",
|
|
516
592
|
suggestion: `Imported identifier '${spec}' may not follow standard conventions for this language.`
|
|
517
593
|
});
|
|
@@ -519,7 +595,10 @@ async function analyzeNamingGeneralized(files) {
|
|
|
519
595
|
}
|
|
520
596
|
}
|
|
521
597
|
} catch (error) {
|
|
522
|
-
|
|
598
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
599
|
+
console.debug(
|
|
600
|
+
`Consistency: Skipping unparseable file ${file}: ${errorMessage.split("\\n")[0]}`
|
|
601
|
+
);
|
|
523
602
|
}
|
|
524
603
|
}
|
|
525
604
|
return issues;
|
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -61,8 +61,12 @@ interface ConsistencyReport {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* Main consistency analyzer that orchestrates all analysis types
|
|
65
|
-
* Supports: TypeScript, JavaScript, Python, Java, C#, Go
|
|
64
|
+
* Main consistency analyzer that orchestrates all analysis types.
|
|
65
|
+
* Supports: TypeScript, JavaScript, Python, Java, C#, Go.
|
|
66
|
+
*
|
|
67
|
+
* @param options - Configuration for consistency analysis and file scanning.
|
|
68
|
+
* @returns Promise resolving to the comprehensive consistency report.
|
|
69
|
+
* @lastUpdated 2026-03-18
|
|
66
70
|
*/
|
|
67
71
|
declare function analyzeConsistency(options: ConsistencyOptions): Promise<ConsistencyReport>;
|
|
68
72
|
|
|
@@ -96,15 +100,13 @@ declare function detectNamingConventions(files: string[], allIssues: Array<{
|
|
|
96
100
|
declare function analyzePatterns(filePaths: string[]): Promise<PatternIssue[]>;
|
|
97
101
|
|
|
98
102
|
/**
|
|
99
|
-
* Calculate AI Readiness Score for code consistency (0-100)
|
|
100
|
-
*
|
|
101
|
-
* Based on:
|
|
102
|
-
* - Issue density (issues per file)
|
|
103
|
-
* - Weighted severity (critical: 10pts, major: 3pts, minor: 0.5pts)
|
|
104
|
-
* - Pattern consistency across codebase
|
|
103
|
+
* Calculate AI Readiness Score for code consistency (0-100).
|
|
105
104
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
105
|
+
* @param issues - Array of detected consistency issues.
|
|
106
|
+
* @param totalFilesAnalyzed - Total number of files scanned.
|
|
107
|
+
* @param costConfig - Optional configuration for productivity cost calculation.
|
|
108
|
+
* @returns Standardized scoring output for the consistency tool.
|
|
109
|
+
* @lastUpdated 2026-03-18
|
|
108
110
|
*/
|
|
109
111
|
declare function calculateConsistencyScore(issues: ConsistencyIssue[], totalFilesAnalyzed: number, costConfig?: Partial<CostConfig>): ToolScoringOutput;
|
|
110
112
|
|
package/dist/index.d.ts
CHANGED
|
@@ -61,8 +61,12 @@ interface ConsistencyReport {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* Main consistency analyzer that orchestrates all analysis types
|
|
65
|
-
* Supports: TypeScript, JavaScript, Python, Java, C#, Go
|
|
64
|
+
* Main consistency analyzer that orchestrates all analysis types.
|
|
65
|
+
* Supports: TypeScript, JavaScript, Python, Java, C#, Go.
|
|
66
|
+
*
|
|
67
|
+
* @param options - Configuration for consistency analysis and file scanning.
|
|
68
|
+
* @returns Promise resolving to the comprehensive consistency report.
|
|
69
|
+
* @lastUpdated 2026-03-18
|
|
66
70
|
*/
|
|
67
71
|
declare function analyzeConsistency(options: ConsistencyOptions): Promise<ConsistencyReport>;
|
|
68
72
|
|
|
@@ -96,15 +100,13 @@ declare function detectNamingConventions(files: string[], allIssues: Array<{
|
|
|
96
100
|
declare function analyzePatterns(filePaths: string[]): Promise<PatternIssue[]>;
|
|
97
101
|
|
|
98
102
|
/**
|
|
99
|
-
* Calculate AI Readiness Score for code consistency (0-100)
|
|
100
|
-
*
|
|
101
|
-
* Based on:
|
|
102
|
-
* - Issue density (issues per file)
|
|
103
|
-
* - Weighted severity (critical: 10pts, major: 3pts, minor: 0.5pts)
|
|
104
|
-
* - Pattern consistency across codebase
|
|
103
|
+
* Calculate AI Readiness Score for code consistency (0-100).
|
|
105
104
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
105
|
+
* @param issues - Array of detected consistency issues.
|
|
106
|
+
* @param totalFilesAnalyzed - Total number of files scanned.
|
|
107
|
+
* @param costConfig - Optional configuration for productivity cost calculation.
|
|
108
|
+
* @returns Standardized scoring output for the consistency tool.
|
|
109
|
+
* @lastUpdated 2026-03-18
|
|
108
110
|
*/
|
|
109
111
|
declare function calculateConsistencyScore(issues: ConsistencyIssue[], totalFilesAnalyzed: number, costConfig?: Partial<CostConfig>): ToolScoringOutput;
|
|
110
112
|
|
package/dist/index.js
CHANGED
|
@@ -421,7 +421,36 @@ function isCommonAbbreviation(name) {
|
|
|
421
421
|
"ux",
|
|
422
422
|
"api",
|
|
423
423
|
"env",
|
|
424
|
-
"url"
|
|
424
|
+
"url",
|
|
425
|
+
"req",
|
|
426
|
+
"res",
|
|
427
|
+
"err",
|
|
428
|
+
"ctx",
|
|
429
|
+
"cb",
|
|
430
|
+
"idx",
|
|
431
|
+
"src",
|
|
432
|
+
"dir",
|
|
433
|
+
"app",
|
|
434
|
+
"dev",
|
|
435
|
+
"qa",
|
|
436
|
+
"dto",
|
|
437
|
+
"dao",
|
|
438
|
+
"ref",
|
|
439
|
+
"ast",
|
|
440
|
+
"dom",
|
|
441
|
+
"log",
|
|
442
|
+
"msg",
|
|
443
|
+
"pkg",
|
|
444
|
+
"req",
|
|
445
|
+
"err",
|
|
446
|
+
"res",
|
|
447
|
+
"css",
|
|
448
|
+
"html",
|
|
449
|
+
"xml",
|
|
450
|
+
"jsx",
|
|
451
|
+
"tsx",
|
|
452
|
+
"ts",
|
|
453
|
+
"js"
|
|
425
454
|
];
|
|
426
455
|
return common.includes(name.toLowerCase());
|
|
427
456
|
}
|
|
@@ -471,6 +500,44 @@ function extractDestructuredIdentifiers(node, isParameter, scopeTracker) {
|
|
|
471
500
|
// src/analyzers/naming-generalized.ts
|
|
472
501
|
var import_core3 = require("@aiready/core");
|
|
473
502
|
var import_fs2 = require("fs");
|
|
503
|
+
var COMMON_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
504
|
+
"id",
|
|
505
|
+
"db",
|
|
506
|
+
"fs",
|
|
507
|
+
"os",
|
|
508
|
+
"ip",
|
|
509
|
+
"ui",
|
|
510
|
+
"ux",
|
|
511
|
+
"api",
|
|
512
|
+
"env",
|
|
513
|
+
"url",
|
|
514
|
+
"req",
|
|
515
|
+
"res",
|
|
516
|
+
"err",
|
|
517
|
+
"ctx",
|
|
518
|
+
"cb",
|
|
519
|
+
"idx",
|
|
520
|
+
"src",
|
|
521
|
+
"dir",
|
|
522
|
+
"app",
|
|
523
|
+
"dev",
|
|
524
|
+
"qa",
|
|
525
|
+
"dto",
|
|
526
|
+
"dao",
|
|
527
|
+
"ref",
|
|
528
|
+
"ast",
|
|
529
|
+
"dom",
|
|
530
|
+
"log",
|
|
531
|
+
"msg",
|
|
532
|
+
"pkg",
|
|
533
|
+
"css",
|
|
534
|
+
"html",
|
|
535
|
+
"xml",
|
|
536
|
+
"jsx",
|
|
537
|
+
"tsx",
|
|
538
|
+
"ts",
|
|
539
|
+
"js"
|
|
540
|
+
]);
|
|
474
541
|
async function analyzeNamingGeneralized(files) {
|
|
475
542
|
const issues = [];
|
|
476
543
|
for (const file of files) {
|
|
@@ -478,10 +545,15 @@ async function analyzeNamingGeneralized(files) {
|
|
|
478
545
|
if (!parser) continue;
|
|
479
546
|
try {
|
|
480
547
|
const code = (0, import_fs2.readFileSync)(file, "utf-8");
|
|
548
|
+
if (!code.trim()) continue;
|
|
481
549
|
await parser.initialize();
|
|
482
550
|
const result = parser.parse(code, file);
|
|
483
551
|
const conventions = parser.getNamingConventions();
|
|
552
|
+
const exceptions = new Set(conventions.exceptions || []);
|
|
484
553
|
for (const exp of result.exports) {
|
|
554
|
+
if (!exp.name || exp.name === "default") continue;
|
|
555
|
+
if (exceptions.has(exp.name)) continue;
|
|
556
|
+
if (COMMON_ABBREVIATIONS.has(exp.name.toLowerCase())) continue;
|
|
485
557
|
let pattern;
|
|
486
558
|
if (exp.type === "class") {
|
|
487
559
|
pattern = conventions.classPattern;
|
|
@@ -492,7 +564,7 @@ async function analyzeNamingGeneralized(files) {
|
|
|
492
564
|
} else if (exp.type === "function") {
|
|
493
565
|
pattern = conventions.functionPattern;
|
|
494
566
|
} else if (exp.type === "const") {
|
|
495
|
-
pattern = conventions.constantPattern;
|
|
567
|
+
pattern = exp.isPrimitive ? conventions.constantPattern : conventions.variablePattern;
|
|
496
568
|
} else {
|
|
497
569
|
pattern = conventions.variablePattern;
|
|
498
570
|
}
|
|
@@ -503,7 +575,8 @@ async function analyzeNamingGeneralized(files) {
|
|
|
503
575
|
file,
|
|
504
576
|
line: exp.loc?.start.line || 1,
|
|
505
577
|
column: exp.loc?.start.column || 0,
|
|
506
|
-
|
|
578
|
+
// Recalibrate naming issues to Minor to differentiate from structural/architectural issues
|
|
579
|
+
severity: import_core3.Severity.Minor,
|
|
507
580
|
category: "naming",
|
|
508
581
|
suggestion: `Follow ${parser.language} ${exp.type} naming convention: ${pattern.toString()}`
|
|
509
582
|
});
|
|
@@ -511,7 +584,9 @@ async function analyzeNamingGeneralized(files) {
|
|
|
511
584
|
}
|
|
512
585
|
for (const imp of result.imports) {
|
|
513
586
|
for (const spec of imp.specifiers) {
|
|
514
|
-
if (spec === "*" || spec === "default") continue;
|
|
587
|
+
if (!spec || spec === "*" || spec === "default") continue;
|
|
588
|
+
if (exceptions.has(spec)) continue;
|
|
589
|
+
if (COMMON_ABBREVIATIONS.has(spec.toLowerCase())) continue;
|
|
515
590
|
if (!conventions.variablePattern.test(spec) && !conventions.classPattern.test(spec)) {
|
|
516
591
|
issues.push({
|
|
517
592
|
type: "naming-inconsistency",
|
|
@@ -519,7 +594,8 @@ async function analyzeNamingGeneralized(files) {
|
|
|
519
594
|
file,
|
|
520
595
|
line: imp.loc?.start.line || 1,
|
|
521
596
|
column: imp.loc?.start.column || 0,
|
|
522
|
-
severity: import_core3.Severity.
|
|
597
|
+
severity: import_core3.Severity.Info,
|
|
598
|
+
// Reduced from Minor to Info for imports
|
|
523
599
|
category: "naming",
|
|
524
600
|
suggestion: `Imported identifier '${spec}' may not follow standard conventions for this language.`
|
|
525
601
|
});
|
|
@@ -527,7 +603,10 @@ async function analyzeNamingGeneralized(files) {
|
|
|
527
603
|
}
|
|
528
604
|
}
|
|
529
605
|
} catch (error) {
|
|
530
|
-
|
|
606
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
607
|
+
console.debug(
|
|
608
|
+
`Consistency: Skipping unparseable file ${file}: ${errorMessage.split("\\n")[0]}`
|
|
609
|
+
);
|
|
531
610
|
}
|
|
532
611
|
}
|
|
533
612
|
return issues;
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/consistency",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.7",
|
|
4
4
|
"description": "Detects consistency issues in naming, patterns, and architecture that confuse AI models",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@typescript-eslint/typescript-estree": "^8.53.0",
|
|
44
44
|
"chalk": "^5.3.0",
|
|
45
45
|
"commander": "^14.0.0",
|
|
46
|
-
"@aiready/core": "0.23.
|
|
46
|
+
"@aiready/core": "0.23.8"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/node": "^24.0.0",
|
package/src/analyzer.ts
CHANGED
|
@@ -15,8 +15,12 @@ import { analyzeNamingGeneralized } from './analyzers/naming-generalized';
|
|
|
15
15
|
import { analyzePatterns } from './analyzers/patterns';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Main consistency analyzer that orchestrates all analysis types
|
|
19
|
-
* Supports: TypeScript, JavaScript, Python, Java, C#, Go
|
|
18
|
+
* Main consistency analyzer that orchestrates all analysis types.
|
|
19
|
+
* Supports: TypeScript, JavaScript, Python, Java, C#, Go.
|
|
20
|
+
*
|
|
21
|
+
* @param options - Configuration for consistency analysis and file scanning.
|
|
22
|
+
* @returns Promise resolving to the comprehensive consistency report.
|
|
23
|
+
* @lastUpdated 2026-03-18
|
|
20
24
|
*/
|
|
21
25
|
export async function analyzeConsistency(
|
|
22
26
|
options: ConsistencyOptions
|
|
@@ -126,6 +130,13 @@ export async function analyzeConsistency(
|
|
|
126
130
|
} as unknown as ConsistencyReport;
|
|
127
131
|
}
|
|
128
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Check if an issue severity meets the minimum threshold.
|
|
135
|
+
*
|
|
136
|
+
* @param severity - The severity of the issue.
|
|
137
|
+
* @param minSeverity - The minimum severity threshold.
|
|
138
|
+
* @returns True if severity is greater than or equal to minSeverity.
|
|
139
|
+
*/
|
|
129
140
|
function shouldIncludeSeverity(
|
|
130
141
|
severity: Severity | string,
|
|
131
142
|
minSeverity: Severity | string
|
|
@@ -134,7 +145,10 @@ function shouldIncludeSeverity(
|
|
|
134
145
|
}
|
|
135
146
|
|
|
136
147
|
/**
|
|
137
|
-
* Map string type to IssueType enum value
|
|
148
|
+
* Map string type to IssueType enum value.
|
|
149
|
+
*
|
|
150
|
+
* @param type - The raw issue type string.
|
|
151
|
+
* @returns Normalized IssueType enum.
|
|
138
152
|
*/
|
|
139
153
|
function getIssueType(type: string | undefined): IssueType {
|
|
140
154
|
if (!type) return IssueType.NamingInconsistency;
|
|
@@ -155,7 +169,10 @@ function getIssueType(type: string | undefined): IssueType {
|
|
|
155
169
|
}
|
|
156
170
|
|
|
157
171
|
/**
|
|
158
|
-
* Transform NamingIssue or PatternIssue to the required Issue format
|
|
172
|
+
* Transform NamingIssue or PatternIssue to the required Issue format.
|
|
173
|
+
*
|
|
174
|
+
* @param i - The raw issue object to transform.
|
|
175
|
+
* @returns Standardized Issue object.
|
|
159
176
|
*/
|
|
160
177
|
function transformToIssue(i: any): Issue {
|
|
161
178
|
// If already has message and location, return as is
|
|
@@ -227,6 +227,35 @@ function isCommonAbbreviation(name: string): boolean {
|
|
|
227
227
|
'api',
|
|
228
228
|
'env',
|
|
229
229
|
'url',
|
|
230
|
+
'req',
|
|
231
|
+
'res',
|
|
232
|
+
'err',
|
|
233
|
+
'ctx',
|
|
234
|
+
'cb',
|
|
235
|
+
'idx',
|
|
236
|
+
'src',
|
|
237
|
+
'dir',
|
|
238
|
+
'app',
|
|
239
|
+
'dev',
|
|
240
|
+
'qa',
|
|
241
|
+
'dto',
|
|
242
|
+
'dao',
|
|
243
|
+
'ref',
|
|
244
|
+
'ast',
|
|
245
|
+
'dom',
|
|
246
|
+
'log',
|
|
247
|
+
'msg',
|
|
248
|
+
'pkg',
|
|
249
|
+
'req',
|
|
250
|
+
'err',
|
|
251
|
+
'res',
|
|
252
|
+
'css',
|
|
253
|
+
'html',
|
|
254
|
+
'xml',
|
|
255
|
+
'jsx',
|
|
256
|
+
'tsx',
|
|
257
|
+
'ts',
|
|
258
|
+
'js',
|
|
230
259
|
];
|
|
231
260
|
return common.includes(name.toLowerCase());
|
|
232
261
|
}
|
|
@@ -9,6 +9,46 @@ import { getParser, Severity } from '@aiready/core';
|
|
|
9
9
|
import type { NamingIssue } from '../types';
|
|
10
10
|
import { readFileSync } from 'fs';
|
|
11
11
|
|
|
12
|
+
// Common abbreviations to whitelist
|
|
13
|
+
const COMMON_ABBREVIATIONS = new Set([
|
|
14
|
+
'id',
|
|
15
|
+
'db',
|
|
16
|
+
'fs',
|
|
17
|
+
'os',
|
|
18
|
+
'ip',
|
|
19
|
+
'ui',
|
|
20
|
+
'ux',
|
|
21
|
+
'api',
|
|
22
|
+
'env',
|
|
23
|
+
'url',
|
|
24
|
+
'req',
|
|
25
|
+
'res',
|
|
26
|
+
'err',
|
|
27
|
+
'ctx',
|
|
28
|
+
'cb',
|
|
29
|
+
'idx',
|
|
30
|
+
'src',
|
|
31
|
+
'dir',
|
|
32
|
+
'app',
|
|
33
|
+
'dev',
|
|
34
|
+
'qa',
|
|
35
|
+
'dto',
|
|
36
|
+
'dao',
|
|
37
|
+
'ref',
|
|
38
|
+
'ast',
|
|
39
|
+
'dom',
|
|
40
|
+
'log',
|
|
41
|
+
'msg',
|
|
42
|
+
'pkg',
|
|
43
|
+
'css',
|
|
44
|
+
'html',
|
|
45
|
+
'xml',
|
|
46
|
+
'jsx',
|
|
47
|
+
'tsx',
|
|
48
|
+
'ts',
|
|
49
|
+
'js',
|
|
50
|
+
]);
|
|
51
|
+
|
|
12
52
|
/**
|
|
13
53
|
* Analyzes naming conventions using generalized LanguageParser metadata
|
|
14
54
|
*/
|
|
@@ -23,13 +63,22 @@ export async function analyzeNamingGeneralized(
|
|
|
23
63
|
|
|
24
64
|
try {
|
|
25
65
|
const code = readFileSync(file, 'utf-8');
|
|
66
|
+
if (!code.trim()) continue; // Skip empty files
|
|
67
|
+
|
|
26
68
|
// Ensure parser is initialized (e.g. WASM loaded)
|
|
27
69
|
await parser.initialize();
|
|
28
70
|
const result = parser.parse(code, file);
|
|
29
71
|
const conventions = parser.getNamingConventions();
|
|
72
|
+
const exceptions = new Set(conventions.exceptions || []);
|
|
30
73
|
|
|
31
74
|
// 1. Check Exports
|
|
32
75
|
for (const exp of result.exports) {
|
|
76
|
+
if (!exp.name || exp.name === 'default') continue;
|
|
77
|
+
if (exceptions.has(exp.name)) continue;
|
|
78
|
+
|
|
79
|
+
// Skip common abbreviations
|
|
80
|
+
if (COMMON_ABBREVIATIONS.has(exp.name.toLowerCase())) continue;
|
|
81
|
+
|
|
33
82
|
let pattern: RegExp | undefined;
|
|
34
83
|
|
|
35
84
|
if (exp.type === 'class') {
|
|
@@ -41,7 +90,12 @@ export async function analyzeNamingGeneralized(
|
|
|
41
90
|
} else if (exp.type === 'function') {
|
|
42
91
|
pattern = conventions.functionPattern;
|
|
43
92
|
} else if (exp.type === 'const') {
|
|
44
|
-
|
|
93
|
+
// Only enforce SCREAMING_SNAKE_CASE for primitive constants (strings, numbers,
|
|
94
|
+
// booleans). Object literals, class instances, and tool definitions are
|
|
95
|
+
// camelCase by convention (e.g. `logger`, `githubTools`, `RemediationSwarm`).
|
|
96
|
+
pattern = exp.isPrimitive
|
|
97
|
+
? conventions.constantPattern
|
|
98
|
+
: conventions.variablePattern;
|
|
45
99
|
} else {
|
|
46
100
|
pattern = conventions.variablePattern;
|
|
47
101
|
}
|
|
@@ -53,7 +107,8 @@ export async function analyzeNamingGeneralized(
|
|
|
53
107
|
file,
|
|
54
108
|
line: exp.loc?.start.line || 1,
|
|
55
109
|
column: exp.loc?.start.column || 0,
|
|
56
|
-
|
|
110
|
+
// Recalibrate naming issues to Minor to differentiate from structural/architectural issues
|
|
111
|
+
severity: Severity.Minor,
|
|
57
112
|
category: 'naming',
|
|
58
113
|
suggestion: `Follow ${parser.language} ${exp.type} naming convention: ${pattern.toString()}`,
|
|
59
114
|
});
|
|
@@ -63,7 +118,9 @@ export async function analyzeNamingGeneralized(
|
|
|
63
118
|
// 2. Check Imports (basic check for specifier consistency)
|
|
64
119
|
for (const imp of result.imports) {
|
|
65
120
|
for (const spec of imp.specifiers) {
|
|
66
|
-
if (spec === '*' || spec === 'default') continue;
|
|
121
|
+
if (!spec || spec === '*' || spec === 'default') continue;
|
|
122
|
+
if (exceptions.has(spec)) continue;
|
|
123
|
+
if (COMMON_ABBREVIATIONS.has(spec.toLowerCase())) continue;
|
|
67
124
|
|
|
68
125
|
if (
|
|
69
126
|
!conventions.variablePattern.test(spec) &&
|
|
@@ -76,7 +133,7 @@ export async function analyzeNamingGeneralized(
|
|
|
76
133
|
file,
|
|
77
134
|
line: imp.loc?.start.line || 1,
|
|
78
135
|
column: imp.loc?.start.column || 0,
|
|
79
|
-
severity: Severity.Minor
|
|
136
|
+
severity: Severity.Info, // Reduced from Minor to Info for imports
|
|
80
137
|
category: 'naming',
|
|
81
138
|
suggestion: `Imported identifier '${spec}' may not follow standard conventions for this language.`,
|
|
82
139
|
});
|
|
@@ -84,7 +141,12 @@ export async function analyzeNamingGeneralized(
|
|
|
84
141
|
}
|
|
85
142
|
}
|
|
86
143
|
} catch (error) {
|
|
87
|
-
|
|
144
|
+
// Improved error handling
|
|
145
|
+
const errorMessage =
|
|
146
|
+
error instanceof Error ? error.message : String(error);
|
|
147
|
+
console.debug(
|
|
148
|
+
`Consistency: Skipping unparseable file ${file}: ${errorMessage.split('\\n')[0]}`
|
|
149
|
+
);
|
|
88
150
|
}
|
|
89
151
|
}
|
|
90
152
|
|
package/src/scoring.ts
CHANGED
|
@@ -3,15 +3,13 @@ import type { ToolScoringOutput, CostConfig } from '@aiready/core';
|
|
|
3
3
|
import type { ConsistencyIssue } from './types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Calculate AI Readiness Score for code consistency (0-100)
|
|
6
|
+
* Calculate AI Readiness Score for code consistency (0-100).
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Includes business value metrics:
|
|
14
|
-
* - Estimated developer hours to fix consistency issues
|
|
8
|
+
* @param issues - Array of detected consistency issues.
|
|
9
|
+
* @param totalFilesAnalyzed - Total number of files scanned.
|
|
10
|
+
* @param costConfig - Optional configuration for productivity cost calculation.
|
|
11
|
+
* @returns Standardized scoring output for the consistency tool.
|
|
12
|
+
* @lastUpdated 2026-03-18
|
|
15
13
|
*/
|
|
16
14
|
export function calculateConsistencyScore(
|
|
17
15
|
issues: ConsistencyIssue[],
|