@aiready/consistency 0.20.2 → 0.20.4
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 +9 -9
- package/.turbo/turbo-lint.log +24 -17
- package/.turbo/turbo-test.log +12 -12
- package/dist/chunk-3ZB6FFRL.mjs +661 -0
- package/dist/chunk-6BM5MV3S.mjs +719 -0
- package/dist/chunk-BYY6MD5T.mjs +729 -0
- package/dist/chunk-DSI3TEO2.mjs +662 -0
- package/dist/chunk-H6S7WKSQ.mjs +729 -0
- package/dist/chunk-LMOXGPCM.mjs +722 -0
- package/dist/chunk-MAPVFXBP.mjs +708 -0
- package/dist/chunk-NPWCJZUG.mjs +708 -0
- package/dist/chunk-S6BZVTWN.mjs +731 -0
- package/dist/chunk-ZB6UK276.mjs +662 -0
- package/dist/cli.js +102 -158
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +102 -158
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/src/analyzer.ts +131 -183
- package/src/analyzers/naming-ast.ts +8 -3
- package/src/analyzers/naming-generalized.ts +3 -4
- package/src/analyzers/naming.ts +2 -0
- package/src/analyzers/patterns.ts +2 -5
- package/src/types.ts +6 -1
package/dist/index.js
CHANGED
|
@@ -361,7 +361,7 @@ function checkNamingConvention(name, convention, node, file, issues, context) {
|
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
363
|
function checkVariableNaming(varInfo, file, issues, context) {
|
|
364
|
-
const { name,
|
|
364
|
+
const { name, line, options } = varInfo;
|
|
365
365
|
if (isAcceptableInContext(name, context, options)) {
|
|
366
366
|
return;
|
|
367
367
|
}
|
|
@@ -483,7 +483,6 @@ async function analyzeNamingGeneralized(files) {
|
|
|
483
483
|
const conventions = parser.getNamingConventions();
|
|
484
484
|
for (const exp of result.exports) {
|
|
485
485
|
let pattern;
|
|
486
|
-
const typeName = exp.type;
|
|
487
486
|
if (exp.type === "class") {
|
|
488
487
|
pattern = conventions.classPattern;
|
|
489
488
|
} else if (exp.type === "interface" && conventions.interfacePattern) {
|
|
@@ -499,7 +498,7 @@ async function analyzeNamingGeneralized(files) {
|
|
|
499
498
|
}
|
|
500
499
|
if (pattern && !pattern.test(exp.name)) {
|
|
501
500
|
issues.push({
|
|
502
|
-
type: "
|
|
501
|
+
type: "naming-inconsistency",
|
|
503
502
|
identifier: exp.name,
|
|
504
503
|
file,
|
|
505
504
|
line: exp.loc?.start.line || 1,
|
|
@@ -515,7 +514,7 @@ async function analyzeNamingGeneralized(files) {
|
|
|
515
514
|
if (spec === "*" || spec === "default") continue;
|
|
516
515
|
if (!conventions.variablePattern.test(spec) && !conventions.classPattern.test(spec)) {
|
|
517
516
|
issues.push({
|
|
518
|
-
type: "
|
|
517
|
+
type: "naming-inconsistency",
|
|
519
518
|
identifier: spec,
|
|
520
519
|
file,
|
|
521
520
|
line: imp.loc?.start.line || 1,
|
|
@@ -541,7 +540,6 @@ async function analyzePatterns(filePaths) {
|
|
|
541
540
|
const issues = [];
|
|
542
541
|
const contents = /* @__PURE__ */ new Map();
|
|
543
542
|
const tryCatchPattern = /try\s*\{/g;
|
|
544
|
-
const catchPattern = /catch\s*\(\s*(\w+)\s*\)/g;
|
|
545
543
|
const styleStats = {
|
|
546
544
|
tryCatch: 0,
|
|
547
545
|
thenCatch: 0,
|
|
@@ -562,7 +560,6 @@ async function analyzePatterns(filePaths) {
|
|
|
562
560
|
void err;
|
|
563
561
|
}
|
|
564
562
|
}
|
|
565
|
-
const totalFiles = filePaths.length;
|
|
566
563
|
if (styleStats.tryCatch > 0 && styleStats.thenCatch > 0) {
|
|
567
564
|
const dominant = styleStats.tryCatch >= styleStats.thenCatch ? "try-catch" : ".catch()";
|
|
568
565
|
const minority = dominant === "try-catch" ? ".catch()" : "try-catch";
|
|
@@ -571,7 +568,7 @@ async function analyzePatterns(filePaths) {
|
|
|
571
568
|
const c = contents.get(f) || "";
|
|
572
569
|
return minority === "try-catch" ? c.match(tryCatchPattern) : c.match(/\.catch\s*\(/);
|
|
573
570
|
}),
|
|
574
|
-
type: "
|
|
571
|
+
type: "pattern-inconsistency",
|
|
575
572
|
description: `Mixed error handling styles: codebase primarily uses ${dominant}, but found ${minority} in some files.`,
|
|
576
573
|
examples: [dominant, minority],
|
|
577
574
|
severity: import_core4.Severity.Minor
|
|
@@ -584,7 +581,7 @@ async function analyzePatterns(filePaths) {
|
|
|
584
581
|
const c = contents.get(f) || "";
|
|
585
582
|
return minority === "CommonJS (require)" ? c.match(/\brequire\s*\(/) : c.match(/\bimport\b/);
|
|
586
583
|
}),
|
|
587
|
-
type: "
|
|
584
|
+
type: "pattern-inconsistency",
|
|
588
585
|
description: `Mixed module systems: found both ESM and CommonJS.`,
|
|
589
586
|
examples: ['import X from "y"', 'const X = require("y")'],
|
|
590
587
|
severity: import_core4.Severity.Major
|
|
@@ -618,130 +615,126 @@ async function analyzeConsistency(options) {
|
|
|
618
615
|
const results = [];
|
|
619
616
|
const fileIssuesMap = /* @__PURE__ */ new Map();
|
|
620
617
|
for (const issue of namingIssues) {
|
|
621
|
-
if (!shouldIncludeSeverity(issue.severity, minSeverity))
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
type: issue.type === "convention-mix" ? import_core5.IssueType.NamingInconsistency : import_core5.IssueType.NamingQuality,
|
|
626
|
-
category: "naming",
|
|
627
|
-
severity: getSeverityEnum(issue.severity),
|
|
628
|
-
message: `${issue.type}: ${issue.identifier}`,
|
|
629
|
-
location: {
|
|
630
|
-
file: issue.file,
|
|
631
|
-
line: issue.line,
|
|
632
|
-
column: issue.column
|
|
633
|
-
},
|
|
634
|
-
suggestion: issue.suggestion
|
|
635
|
-
};
|
|
636
|
-
if (!fileIssuesMap.has(issue.file)) {
|
|
637
|
-
fileIssuesMap.set(issue.file, []);
|
|
638
|
-
}
|
|
639
|
-
fileIssuesMap.get(issue.file).push(consistencyIssue);
|
|
618
|
+
if (!shouldIncludeSeverity(issue.severity, minSeverity)) continue;
|
|
619
|
+
const fileName = issue.fileName || issue.file || issue.filePath || "unknown";
|
|
620
|
+
if (!fileIssuesMap.has(fileName)) fileIssuesMap.set(fileName, []);
|
|
621
|
+
fileIssuesMap.get(fileName).push(issue);
|
|
640
622
|
}
|
|
641
623
|
for (const issue of patternIssues) {
|
|
642
|
-
if (!shouldIncludeSeverity(issue.severity, minSeverity))
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
type: import_core5.IssueType.PatternInconsistency,
|
|
647
|
-
category: "patterns",
|
|
648
|
-
severity: getSeverityEnum(issue.severity),
|
|
649
|
-
message: issue.description,
|
|
650
|
-
location: {
|
|
651
|
-
file: issue.files[0] || "multiple files",
|
|
652
|
-
line: 1
|
|
653
|
-
},
|
|
654
|
-
examples: issue.examples,
|
|
655
|
-
suggestion: `Standardize ${issue.type} patterns across ${issue.files.length} files`
|
|
656
|
-
};
|
|
657
|
-
const firstFile = issue.files[0];
|
|
658
|
-
if (firstFile && !fileIssuesMap.has(firstFile)) {
|
|
659
|
-
fileIssuesMap.set(firstFile, []);
|
|
660
|
-
}
|
|
661
|
-
if (firstFile) {
|
|
662
|
-
fileIssuesMap.get(firstFile).push(consistencyIssue);
|
|
663
|
-
}
|
|
624
|
+
if (!shouldIncludeSeverity(issue.severity, minSeverity)) continue;
|
|
625
|
+
const fileName = issue.fileName || issue.file || issue.filePath || (Array.isArray(issue.files) ? issue.files[0] : "unknown");
|
|
626
|
+
if (!fileIssuesMap.has(fileName)) fileIssuesMap.set(fileName, []);
|
|
627
|
+
fileIssuesMap.get(fileName).push(issue);
|
|
664
628
|
}
|
|
665
|
-
for (const [fileName, issues] of fileIssuesMap) {
|
|
629
|
+
for (const [fileName, issues] of fileIssuesMap.entries()) {
|
|
666
630
|
results.push({
|
|
667
631
|
fileName,
|
|
668
|
-
issues,
|
|
632
|
+
issues: issues.map((i) => transformToIssue(i)),
|
|
669
633
|
metrics: {
|
|
670
634
|
consistencyScore: calculateConsistencyScore(issues)
|
|
671
635
|
}
|
|
672
636
|
});
|
|
673
637
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
return val === 4 ? 0 : val === 3 ? 1 : val === 2 ? 2 : 3;
|
|
685
|
-
})
|
|
638
|
+
const recommendations = [];
|
|
639
|
+
if (namingIssues.length > 0) {
|
|
640
|
+
recommendations.push("Standardize naming conventions across the codebase");
|
|
641
|
+
}
|
|
642
|
+
if (patternIssues.length > 0) {
|
|
643
|
+
recommendations.push("Consolidate repetitive implementation patterns");
|
|
644
|
+
}
|
|
645
|
+
if (results.some((r) => (r.metrics?.consistencyScore ?? 1) < 0.8)) {
|
|
646
|
+
recommendations.push(
|
|
647
|
+
"Improve cross-module consistency to reduce AI confusion"
|
|
686
648
|
);
|
|
687
|
-
|
|
688
|
-
return maxSeverityA - maxSeverityB;
|
|
689
|
-
}
|
|
690
|
-
return fileResultB.issues.length - fileResultA.issues.length;
|
|
691
|
-
});
|
|
692
|
-
const recommendations = generateRecommendations(namingIssues, patternIssues);
|
|
693
|
-
const namingCountFiltered = namingIssues.filter(
|
|
694
|
-
(i) => shouldIncludeSeverity(i.severity, minSeverity)
|
|
695
|
-
).length;
|
|
696
|
-
const patternCountFiltered = patternIssues.filter(
|
|
697
|
-
(i) => shouldIncludeSeverity(i.severity, minSeverity)
|
|
698
|
-
).length;
|
|
649
|
+
}
|
|
699
650
|
return {
|
|
651
|
+
results,
|
|
700
652
|
summary: {
|
|
701
|
-
totalIssues: namingCountFiltered + patternCountFiltered,
|
|
702
|
-
namingIssues: namingCountFiltered,
|
|
703
|
-
patternIssues: patternCountFiltered,
|
|
704
|
-
architectureIssues: 0,
|
|
705
653
|
filesAnalyzed: filePaths.length,
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
)
|
|
654
|
+
totalIssues: results.reduce((acc, r) => acc + r.issues.length, 0),
|
|
655
|
+
namingIssues: namingIssues.length,
|
|
656
|
+
patternIssues: patternIssues.length,
|
|
657
|
+
architectureIssues: 0
|
|
711
658
|
},
|
|
712
|
-
|
|
713
|
-
|
|
659
|
+
recommendations,
|
|
660
|
+
metadata: {
|
|
661
|
+
toolName: "naming-consistency",
|
|
662
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
663
|
+
}
|
|
714
664
|
};
|
|
715
665
|
}
|
|
716
|
-
function
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
if (
|
|
721
|
-
|
|
666
|
+
function shouldIncludeSeverity(severity, minSeverity) {
|
|
667
|
+
return (0, import_core5.getSeverityLevel)(severity) >= (0, import_core5.getSeverityLevel)(minSeverity);
|
|
668
|
+
}
|
|
669
|
+
function getIssueType(type) {
|
|
670
|
+
if (!type) return import_core5.IssueType.NamingInconsistency;
|
|
671
|
+
const typeMap = {
|
|
672
|
+
"naming-inconsistency": import_core5.IssueType.NamingInconsistency,
|
|
673
|
+
"naming-quality": import_core5.IssueType.NamingQuality,
|
|
674
|
+
"pattern-inconsistency": import_core5.IssueType.PatternInconsistency,
|
|
675
|
+
"architecture-inconsistency": import_core5.IssueType.ArchitectureInconsistency,
|
|
676
|
+
"error-handling": import_core5.IssueType.PatternInconsistency,
|
|
677
|
+
"async-style": import_core5.IssueType.PatternInconsistency,
|
|
678
|
+
"import-style": import_core5.IssueType.PatternInconsistency,
|
|
679
|
+
"api-design": import_core5.IssueType.PatternInconsistency
|
|
680
|
+
};
|
|
681
|
+
return typeMap[type] || import_core5.IssueType.NamingInconsistency;
|
|
722
682
|
}
|
|
723
|
-
function
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
case 1:
|
|
733
|
-
return import_core5.Severity.Info;
|
|
734
|
-
default:
|
|
735
|
-
return import_core5.Severity.Info;
|
|
683
|
+
function transformToIssue(i) {
|
|
684
|
+
if (i.message && i.location) {
|
|
685
|
+
return {
|
|
686
|
+
type: getIssueType(i.type),
|
|
687
|
+
severity: i.severity,
|
|
688
|
+
message: i.message,
|
|
689
|
+
location: i.location,
|
|
690
|
+
suggestion: i.suggestion
|
|
691
|
+
};
|
|
736
692
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
693
|
+
if (i.identifier || i.type) {
|
|
694
|
+
const line = i.line || 1;
|
|
695
|
+
const column = i.column || 1;
|
|
696
|
+
return {
|
|
697
|
+
type: getIssueType(i.type),
|
|
698
|
+
severity: i.severity,
|
|
699
|
+
message: i.suggestion ? `Naming issue: ${i.suggestion}` : `Naming issue for '${i.identifier || "unknown"}'`,
|
|
700
|
+
location: {
|
|
701
|
+
file: i.file || i.fileName || "",
|
|
702
|
+
line,
|
|
703
|
+
column,
|
|
704
|
+
endLine: line,
|
|
705
|
+
endColumn: column + (i.identifier?.length || 10)
|
|
706
|
+
},
|
|
707
|
+
suggestion: i.suggestion
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
if (i.description || i.files) {
|
|
711
|
+
const fileName = Array.isArray(i.files) ? i.files[0] : i.file || "";
|
|
712
|
+
return {
|
|
713
|
+
type: getIssueType(i.type),
|
|
714
|
+
severity: i.severity,
|
|
715
|
+
message: i.description || "Pattern inconsistency found",
|
|
716
|
+
location: {
|
|
717
|
+
file: fileName,
|
|
718
|
+
line: 1,
|
|
719
|
+
column: 1,
|
|
720
|
+
endLine: 1,
|
|
721
|
+
endColumn: 10
|
|
722
|
+
},
|
|
723
|
+
suggestion: i.examples?.[0]
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
return {
|
|
727
|
+
type: getIssueType(i.type),
|
|
728
|
+
severity: i.severity,
|
|
729
|
+
message: i.message || "Unknown issue",
|
|
730
|
+
location: i.location || { file: "", line: 1, column: 1 },
|
|
731
|
+
suggestion: i.suggestion
|
|
732
|
+
};
|
|
740
733
|
}
|
|
741
734
|
function calculateConsistencyScore(issues) {
|
|
742
735
|
let totalWeight = 0;
|
|
743
736
|
for (const issue of issues) {
|
|
744
|
-
const val = getSeverityLevel(issue.severity);
|
|
737
|
+
const val = (0, import_core5.getSeverityLevel)(issue.severity);
|
|
745
738
|
switch (val) {
|
|
746
739
|
case 4:
|
|
747
740
|
totalWeight += 10;
|
|
@@ -761,55 +754,6 @@ function calculateConsistencyScore(issues) {
|
|
|
761
754
|
}
|
|
762
755
|
return Math.max(0, 1 - totalWeight / 100);
|
|
763
756
|
}
|
|
764
|
-
function generateRecommendations(namingIssues, patternIssues) {
|
|
765
|
-
const recommendations = [];
|
|
766
|
-
if (namingIssues.length > 0) {
|
|
767
|
-
const conventionMixCount = namingIssues.filter(
|
|
768
|
-
(i) => i.type === "convention-mix"
|
|
769
|
-
).length;
|
|
770
|
-
if (conventionMixCount > 0) {
|
|
771
|
-
recommendations.push(
|
|
772
|
-
`Standardize naming conventions: Found ${conventionMixCount} snake_case variables in TypeScript/JavaScript (use camelCase)`
|
|
773
|
-
);
|
|
774
|
-
}
|
|
775
|
-
const poorNamingCount = namingIssues.filter(
|
|
776
|
-
(i) => i.type === "poor-naming"
|
|
777
|
-
).length;
|
|
778
|
-
if (poorNamingCount > 0) {
|
|
779
|
-
recommendations.push(
|
|
780
|
-
`Improve variable naming: Found ${poorNamingCount} single-letter or unclear variable names`
|
|
781
|
-
);
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
if (patternIssues.length > 0) {
|
|
785
|
-
const errorHandlingIssues = patternIssues.filter(
|
|
786
|
-
(i) => i.type === "error-handling"
|
|
787
|
-
);
|
|
788
|
-
if (errorHandlingIssues.length > 0) {
|
|
789
|
-
recommendations.push(
|
|
790
|
-
"Standardize error handling strategy across the codebase (prefer try-catch with typed errors)"
|
|
791
|
-
);
|
|
792
|
-
}
|
|
793
|
-
const asyncIssues = patternIssues.filter((i) => i.type === "async-style");
|
|
794
|
-
if (asyncIssues.length > 0) {
|
|
795
|
-
recommendations.push(
|
|
796
|
-
"Use async/await consistently instead of mixing with promise chains or callbacks"
|
|
797
|
-
);
|
|
798
|
-
}
|
|
799
|
-
const importIssues = patternIssues.filter((i) => i.type === "import-style");
|
|
800
|
-
if (importIssues.length > 0) {
|
|
801
|
-
recommendations.push(
|
|
802
|
-
"Use ES modules consistently across the project (avoid mixing with CommonJS)"
|
|
803
|
-
);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
if (recommendations.length === 0) {
|
|
807
|
-
recommendations.push(
|
|
808
|
-
"No major consistency issues found! Your codebase follows good practices."
|
|
809
|
-
);
|
|
810
|
-
}
|
|
811
|
-
return recommendations;
|
|
812
|
-
}
|
|
813
757
|
|
|
814
758
|
// src/scoring.ts
|
|
815
759
|
var import_core6 = require("@aiready/core");
|
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.4",
|
|
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.4"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/node": "^24.0.0",
|