@aiready/consistency 0.20.19 → 0.20.21
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-lint.log +4 -5
- package/.turbo/turbo-test.log +28 -31
- package/dist/chunk-CLWNLHDB.mjs +909 -0
- package/dist/chunk-KWQVBF7K.mjs +831 -0
- package/dist/chunk-P6NVKUBB.mjs +831 -0
- package/dist/cli.js +126 -50
- package/dist/cli.mjs +1 -1
- package/dist/index.js +123 -143
- package/dist/index.mjs +5 -102
- package/package.json +2 -2
- package/src/__tests__/scoring.test.ts +9 -9
- package/src/analyzer.ts +6 -26
- package/src/analyzers/naming-ast.ts +10 -8
- package/src/analyzers/naming-generalized.ts +1 -1
package/dist/cli.js
CHANGED
|
@@ -27,7 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
var import_commander = require("commander");
|
|
28
28
|
|
|
29
29
|
// src/analyzer.ts
|
|
30
|
-
var
|
|
30
|
+
var import_core6 = require("@aiready/core");
|
|
31
31
|
|
|
32
32
|
// src/analyzers/naming-ast.ts
|
|
33
33
|
var import_core2 = require("@aiready/core");
|
|
@@ -311,12 +311,10 @@ function analyzeIdentifiers(ast, filePath, context) {
|
|
|
311
311
|
{ isParameter: true, isArrowParameter }
|
|
312
312
|
);
|
|
313
313
|
} else if (param.type === "ObjectPattern") {
|
|
314
|
-
extractDestructuredIdentifiers(
|
|
315
|
-
|
|
316
|
-
true,
|
|
317
|
-
scopeTracker,
|
|
314
|
+
extractDestructuredIdentifiers(param, scopeTracker, {
|
|
315
|
+
isParameter: true,
|
|
318
316
|
isArrowParameter
|
|
319
|
-
);
|
|
317
|
+
});
|
|
320
318
|
}
|
|
321
319
|
});
|
|
322
320
|
}
|
|
@@ -463,7 +461,8 @@ var ScopeTracker = class {
|
|
|
463
461
|
return this.variables;
|
|
464
462
|
}
|
|
465
463
|
};
|
|
466
|
-
function extractDestructuredIdentifiers(node,
|
|
464
|
+
function extractDestructuredIdentifiers(node, scopeTracker, options = {}) {
|
|
465
|
+
const { isParameter = false, isArrowParameter = false } = options;
|
|
467
466
|
if (node.type === "ObjectPattern") {
|
|
468
467
|
node.properties.forEach((prop) => {
|
|
469
468
|
if (prop.type === "Property" && prop.value.type === "Identifier") {
|
|
@@ -541,7 +540,7 @@ var COMMON_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
|
541
540
|
async function analyzeNamingGeneralized(files) {
|
|
542
541
|
const issues = [];
|
|
543
542
|
for (const file of files) {
|
|
544
|
-
const parser = (0, import_core3.getParser)(file);
|
|
543
|
+
const parser = await (0, import_core3.getParser)(file);
|
|
545
544
|
if (!parser) continue;
|
|
546
545
|
try {
|
|
547
546
|
const code = (0, import_fs2.readFileSync)(file, "utf-8");
|
|
@@ -683,6 +682,102 @@ async function analyzePatterns(filePaths) {
|
|
|
683
682
|
return issues;
|
|
684
683
|
}
|
|
685
684
|
|
|
685
|
+
// src/scoring.ts
|
|
686
|
+
var import_core5 = require("@aiready/core");
|
|
687
|
+
function calculateConsistencyScore(issues, totalFilesAnalyzed, costConfig) {
|
|
688
|
+
void costConfig;
|
|
689
|
+
const criticalIssues = issues.filter((i) => i.severity === "critical").length;
|
|
690
|
+
const majorIssues = issues.filter((i) => i.severity === "major").length;
|
|
691
|
+
const minorIssues = issues.filter((i) => i.severity === "minor").length;
|
|
692
|
+
const totalIssues = issues.length;
|
|
693
|
+
const issuesPerFile = totalFilesAnalyzed > 0 ? totalIssues / totalFilesAnalyzed : 0;
|
|
694
|
+
const densityPenalty = Math.min(50, issuesPerFile * 15);
|
|
695
|
+
const weightedCount = criticalIssues * 10 + majorIssues * 3 + minorIssues * 0.5;
|
|
696
|
+
const avgWeightedIssuesPerFile = totalFilesAnalyzed > 0 ? weightedCount / totalFilesAnalyzed : 0;
|
|
697
|
+
const severityPenalty = Math.min(50, avgWeightedIssuesPerFile * 2);
|
|
698
|
+
const rawScore = 100 - densityPenalty - severityPenalty;
|
|
699
|
+
const score = Math.max(0, Math.min(100, Math.round(rawScore)));
|
|
700
|
+
const factors = [
|
|
701
|
+
{
|
|
702
|
+
name: "Issue Density",
|
|
703
|
+
impact: -Math.round(densityPenalty),
|
|
704
|
+
description: `${issuesPerFile.toFixed(2)} issues per file ${issuesPerFile < 1 ? "(excellent)" : issuesPerFile < 3 ? "(acceptable)" : "(high)"}`
|
|
705
|
+
}
|
|
706
|
+
];
|
|
707
|
+
if (criticalIssues > 0) {
|
|
708
|
+
const criticalImpact = Math.min(30, criticalIssues * 10);
|
|
709
|
+
factors.push({
|
|
710
|
+
name: "Critical Issues",
|
|
711
|
+
impact: -criticalImpact,
|
|
712
|
+
description: `${criticalIssues} critical consistency issue${criticalIssues > 1 ? "s" : ""} (high AI confusion risk)`
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
if (majorIssues > 0) {
|
|
716
|
+
const majorImpact = Math.min(20, Math.round(majorIssues * 3));
|
|
717
|
+
factors.push({
|
|
718
|
+
name: "Major Issues",
|
|
719
|
+
impact: -majorImpact,
|
|
720
|
+
description: `${majorIssues} major issue${majorIssues > 1 ? "s" : ""} (moderate AI confusion risk)`
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
if (minorIssues > 0 && minorIssues >= totalFilesAnalyzed) {
|
|
724
|
+
const minorImpact = -Math.round(minorIssues * 0.5);
|
|
725
|
+
factors.push({
|
|
726
|
+
name: "Minor Issues",
|
|
727
|
+
impact: minorImpact,
|
|
728
|
+
description: `${minorIssues} minor issue${minorIssues > 1 ? "s" : ""} (slight AI confusion risk)`
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
const recommendations = [];
|
|
732
|
+
if (criticalIssues > 0) {
|
|
733
|
+
const estimatedImpact = Math.min(30, criticalIssues * 10);
|
|
734
|
+
recommendations.push({
|
|
735
|
+
action: "Fix critical naming/pattern inconsistencies (highest AI confusion risk)",
|
|
736
|
+
estimatedImpact,
|
|
737
|
+
priority: "high"
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
if (majorIssues > 5) {
|
|
741
|
+
const estimatedImpact = Math.min(15, Math.round(majorIssues / 2));
|
|
742
|
+
recommendations.push({
|
|
743
|
+
action: "Standardize naming conventions across codebase",
|
|
744
|
+
estimatedImpact,
|
|
745
|
+
priority: "medium"
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
if (issuesPerFile > 3) {
|
|
749
|
+
recommendations.push({
|
|
750
|
+
action: "Establish and enforce coding style guide to reduce inconsistencies",
|
|
751
|
+
estimatedImpact: 12,
|
|
752
|
+
priority: "medium"
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
if (totalIssues > 20 && minorIssues / totalIssues > 0.7) {
|
|
756
|
+
recommendations.push({
|
|
757
|
+
action: "Enable linter/formatter to automatically fix minor style issues",
|
|
758
|
+
estimatedImpact: 8,
|
|
759
|
+
priority: "low"
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
const productivityImpact = (0, import_core5.calculateProductivityImpact)(issues);
|
|
763
|
+
return {
|
|
764
|
+
toolName: import_core5.ToolName.NamingConsistency,
|
|
765
|
+
score,
|
|
766
|
+
rawMetrics: {
|
|
767
|
+
totalIssues,
|
|
768
|
+
criticalIssues,
|
|
769
|
+
majorIssues,
|
|
770
|
+
minorIssues,
|
|
771
|
+
issuesPerFile: Math.round(issuesPerFile * 100) / 100,
|
|
772
|
+
avgWeightedIssuesPerFile: Math.round(avgWeightedIssuesPerFile * 100) / 100,
|
|
773
|
+
// Business value metrics
|
|
774
|
+
estimatedDeveloperHours: productivityImpact.totalHours
|
|
775
|
+
},
|
|
776
|
+
factors,
|
|
777
|
+
recommendations
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
|
|
686
781
|
// src/analyzer.ts
|
|
687
782
|
async function analyzeConsistency(options) {
|
|
688
783
|
const {
|
|
@@ -690,11 +785,11 @@ async function analyzeConsistency(options) {
|
|
|
690
785
|
checkPatterns = true,
|
|
691
786
|
checkArchitecture = false,
|
|
692
787
|
// Not implemented yet
|
|
693
|
-
minSeverity =
|
|
788
|
+
minSeverity = import_core6.Severity.Info,
|
|
694
789
|
...scanOptions
|
|
695
790
|
} = options;
|
|
696
791
|
void checkArchitecture;
|
|
697
|
-
const filePaths = await (0,
|
|
792
|
+
const filePaths = await (0, import_core6.scanFiles)(scanOptions);
|
|
698
793
|
let namingIssues = [];
|
|
699
794
|
if (checkNaming) {
|
|
700
795
|
namingIssues = await analyzeNamingGeneralized(filePaths);
|
|
@@ -720,11 +815,15 @@ async function analyzeConsistency(options) {
|
|
|
720
815
|
fileIssuesMap.get(fileName).push(issue);
|
|
721
816
|
}
|
|
722
817
|
for (const [fileName, issues] of fileIssuesMap.entries()) {
|
|
818
|
+
const scoreResult = calculateConsistencyScore(
|
|
819
|
+
issues,
|
|
820
|
+
filePaths.length
|
|
821
|
+
);
|
|
723
822
|
results.push({
|
|
724
823
|
fileName,
|
|
725
824
|
issues: issues.map((i) => transformToIssue(i)),
|
|
726
825
|
metrics: {
|
|
727
|
-
consistencyScore:
|
|
826
|
+
consistencyScore: scoreResult.score / 100
|
|
728
827
|
}
|
|
729
828
|
});
|
|
730
829
|
}
|
|
@@ -757,21 +856,21 @@ async function analyzeConsistency(options) {
|
|
|
757
856
|
};
|
|
758
857
|
}
|
|
759
858
|
function shouldIncludeSeverity(severity, minSeverity) {
|
|
760
|
-
return (0,
|
|
859
|
+
return (0, import_core6.getSeverityLevel)(severity) >= (0, import_core6.getSeverityLevel)(minSeverity);
|
|
761
860
|
}
|
|
762
861
|
function getIssueType(type) {
|
|
763
|
-
if (!type) return
|
|
862
|
+
if (!type) return import_core6.IssueType.NamingInconsistency;
|
|
764
863
|
const typeMap = {
|
|
765
|
-
"naming-inconsistency":
|
|
766
|
-
"naming-quality":
|
|
767
|
-
"pattern-inconsistency":
|
|
768
|
-
"architecture-inconsistency":
|
|
769
|
-
"error-handling":
|
|
770
|
-
"async-style":
|
|
771
|
-
"import-style":
|
|
772
|
-
"api-design":
|
|
864
|
+
"naming-inconsistency": import_core6.IssueType.NamingInconsistency,
|
|
865
|
+
"naming-quality": import_core6.IssueType.NamingQuality,
|
|
866
|
+
"pattern-inconsistency": import_core6.IssueType.PatternInconsistency,
|
|
867
|
+
"architecture-inconsistency": import_core6.IssueType.ArchitectureInconsistency,
|
|
868
|
+
"error-handling": import_core6.IssueType.PatternInconsistency,
|
|
869
|
+
"async-style": import_core6.IssueType.PatternInconsistency,
|
|
870
|
+
"import-style": import_core6.IssueType.PatternInconsistency,
|
|
871
|
+
"api-design": import_core6.IssueType.PatternInconsistency
|
|
773
872
|
};
|
|
774
|
-
return typeMap[type] ||
|
|
873
|
+
return typeMap[type] || import_core6.IssueType.NamingInconsistency;
|
|
775
874
|
}
|
|
776
875
|
function transformToIssue(i) {
|
|
777
876
|
if (i.message && i.location) {
|
|
@@ -824,35 +923,12 @@ function transformToIssue(i) {
|
|
|
824
923
|
suggestion: i.suggestion
|
|
825
924
|
};
|
|
826
925
|
}
|
|
827
|
-
function calculateConsistencyScore(issues) {
|
|
828
|
-
let totalWeight = 0;
|
|
829
|
-
for (const issue of issues) {
|
|
830
|
-
const val = (0, import_core5.getSeverityLevel)(issue.severity);
|
|
831
|
-
switch (val) {
|
|
832
|
-
case 4:
|
|
833
|
-
totalWeight += 10;
|
|
834
|
-
break;
|
|
835
|
-
case 3:
|
|
836
|
-
totalWeight += 5;
|
|
837
|
-
break;
|
|
838
|
-
case 2:
|
|
839
|
-
totalWeight += 2;
|
|
840
|
-
break;
|
|
841
|
-
case 1:
|
|
842
|
-
totalWeight += 1;
|
|
843
|
-
break;
|
|
844
|
-
default:
|
|
845
|
-
totalWeight += 1;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
return Math.max(0, 1 - totalWeight / 100);
|
|
849
|
-
}
|
|
850
926
|
|
|
851
927
|
// src/cli.ts
|
|
852
928
|
var import_chalk = __toESM(require("chalk"));
|
|
853
929
|
var import_fs4 = require("fs");
|
|
854
930
|
var import_path = require("path");
|
|
855
|
-
var
|
|
931
|
+
var import_core7 = require("@aiready/core");
|
|
856
932
|
var program = new import_commander.Command();
|
|
857
933
|
program.name("aiready-consistency").description(
|
|
858
934
|
"Detect consistency patterns in naming, code structure, and architecture"
|
|
@@ -891,7 +967,7 @@ EXAMPLES:
|
|
|
891
967
|
).option("--output-file <path>", "Output file path (for json/markdown)").action(async (directory, options) => {
|
|
892
968
|
console.log(import_chalk.default.blue("\u{1F50D} Analyzing consistency...\n"));
|
|
893
969
|
const startTime = Date.now();
|
|
894
|
-
const config = await (0,
|
|
970
|
+
const config = await (0, import_core7.loadConfig)(directory);
|
|
895
971
|
const defaults = {
|
|
896
972
|
checkNaming: true,
|
|
897
973
|
checkPatterns: true,
|
|
@@ -900,7 +976,7 @@ EXAMPLES:
|
|
|
900
976
|
include: void 0,
|
|
901
977
|
exclude: void 0
|
|
902
978
|
};
|
|
903
|
-
const mergedConfig = (0,
|
|
979
|
+
const mergedConfig = (0, import_core7.mergeConfigWithDefaults)(config, defaults);
|
|
904
980
|
const finalOptions = {
|
|
905
981
|
rootDir: directory,
|
|
906
982
|
checkNaming: options.naming !== false && mergedConfig.checkNaming,
|
|
@@ -914,7 +990,7 @@ EXAMPLES:
|
|
|
914
990
|
const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
915
991
|
if (options.output === "json") {
|
|
916
992
|
const output = JSON.stringify(report, null, 2);
|
|
917
|
-
const outputPath = (0,
|
|
993
|
+
const outputPath = (0, import_core7.resolveOutputPath)(
|
|
918
994
|
options.outputFile,
|
|
919
995
|
`consistency-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.json`,
|
|
920
996
|
directory
|
|
@@ -927,7 +1003,7 @@ EXAMPLES:
|
|
|
927
1003
|
console.log(import_chalk.default.green(`\u2713 Report saved to ${outputPath}`));
|
|
928
1004
|
} else if (options.output === "markdown") {
|
|
929
1005
|
const markdown = generateMarkdownReport(report, elapsedTime);
|
|
930
|
-
const outputPath = (0,
|
|
1006
|
+
const outputPath = (0, import_core7.resolveOutputPath)(
|
|
931
1007
|
options.outputFile,
|
|
932
1008
|
`consistency-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.md`,
|
|
933
1009
|
directory
|
package/dist/cli.mjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ __export(index_exports, {
|
|
|
25
25
|
analyzeNaming: () => analyzeNaming,
|
|
26
26
|
analyzeNamingAST: () => analyzeNamingAST,
|
|
27
27
|
analyzePatterns: () => analyzePatterns,
|
|
28
|
-
calculateConsistencyScore: () =>
|
|
28
|
+
calculateConsistencyScore: () => calculateConsistencyScore,
|
|
29
29
|
detectNamingConventions: () => detectNamingConventions
|
|
30
30
|
});
|
|
31
31
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -35,7 +35,7 @@ var import_core9 = require("@aiready/core");
|
|
|
35
35
|
var import_core7 = require("@aiready/core");
|
|
36
36
|
|
|
37
37
|
// src/analyzer.ts
|
|
38
|
-
var
|
|
38
|
+
var import_core6 = require("@aiready/core");
|
|
39
39
|
|
|
40
40
|
// src/analyzers/naming-ast.ts
|
|
41
41
|
var import_core2 = require("@aiready/core");
|
|
@@ -319,12 +319,10 @@ function analyzeIdentifiers(ast, filePath, context) {
|
|
|
319
319
|
{ isParameter: true, isArrowParameter }
|
|
320
320
|
);
|
|
321
321
|
} else if (param.type === "ObjectPattern") {
|
|
322
|
-
extractDestructuredIdentifiers(
|
|
323
|
-
|
|
324
|
-
true,
|
|
325
|
-
scopeTracker,
|
|
322
|
+
extractDestructuredIdentifiers(param, scopeTracker, {
|
|
323
|
+
isParameter: true,
|
|
326
324
|
isArrowParameter
|
|
327
|
-
);
|
|
325
|
+
});
|
|
328
326
|
}
|
|
329
327
|
});
|
|
330
328
|
}
|
|
@@ -471,7 +469,8 @@ var ScopeTracker = class {
|
|
|
471
469
|
return this.variables;
|
|
472
470
|
}
|
|
473
471
|
};
|
|
474
|
-
function extractDestructuredIdentifiers(node,
|
|
472
|
+
function extractDestructuredIdentifiers(node, scopeTracker, options = {}) {
|
|
473
|
+
const { isParameter = false, isArrowParameter = false } = options;
|
|
475
474
|
if (node.type === "ObjectPattern") {
|
|
476
475
|
node.properties.forEach((prop) => {
|
|
477
476
|
if (prop.type === "Property" && prop.value.type === "Identifier") {
|
|
@@ -549,7 +548,7 @@ var COMMON_ABBREVIATIONS = /* @__PURE__ */ new Set([
|
|
|
549
548
|
async function analyzeNamingGeneralized(files) {
|
|
550
549
|
const issues = [];
|
|
551
550
|
for (const file of files) {
|
|
552
|
-
const parser = (0, import_core3.getParser)(file);
|
|
551
|
+
const parser = await (0, import_core3.getParser)(file);
|
|
553
552
|
if (!parser) continue;
|
|
554
553
|
try {
|
|
555
554
|
const code = (0, import_fs2.readFileSync)(file, "utf-8");
|
|
@@ -691,6 +690,102 @@ async function analyzePatterns(filePaths) {
|
|
|
691
690
|
return issues;
|
|
692
691
|
}
|
|
693
692
|
|
|
693
|
+
// src/scoring.ts
|
|
694
|
+
var import_core5 = require("@aiready/core");
|
|
695
|
+
function calculateConsistencyScore(issues, totalFilesAnalyzed, costConfig) {
|
|
696
|
+
void costConfig;
|
|
697
|
+
const criticalIssues = issues.filter((i) => i.severity === "critical").length;
|
|
698
|
+
const majorIssues = issues.filter((i) => i.severity === "major").length;
|
|
699
|
+
const minorIssues = issues.filter((i) => i.severity === "minor").length;
|
|
700
|
+
const totalIssues = issues.length;
|
|
701
|
+
const issuesPerFile = totalFilesAnalyzed > 0 ? totalIssues / totalFilesAnalyzed : 0;
|
|
702
|
+
const densityPenalty = Math.min(50, issuesPerFile * 15);
|
|
703
|
+
const weightedCount = criticalIssues * 10 + majorIssues * 3 + minorIssues * 0.5;
|
|
704
|
+
const avgWeightedIssuesPerFile = totalFilesAnalyzed > 0 ? weightedCount / totalFilesAnalyzed : 0;
|
|
705
|
+
const severityPenalty = Math.min(50, avgWeightedIssuesPerFile * 2);
|
|
706
|
+
const rawScore = 100 - densityPenalty - severityPenalty;
|
|
707
|
+
const score = Math.max(0, Math.min(100, Math.round(rawScore)));
|
|
708
|
+
const factors = [
|
|
709
|
+
{
|
|
710
|
+
name: "Issue Density",
|
|
711
|
+
impact: -Math.round(densityPenalty),
|
|
712
|
+
description: `${issuesPerFile.toFixed(2)} issues per file ${issuesPerFile < 1 ? "(excellent)" : issuesPerFile < 3 ? "(acceptable)" : "(high)"}`
|
|
713
|
+
}
|
|
714
|
+
];
|
|
715
|
+
if (criticalIssues > 0) {
|
|
716
|
+
const criticalImpact = Math.min(30, criticalIssues * 10);
|
|
717
|
+
factors.push({
|
|
718
|
+
name: "Critical Issues",
|
|
719
|
+
impact: -criticalImpact,
|
|
720
|
+
description: `${criticalIssues} critical consistency issue${criticalIssues > 1 ? "s" : ""} (high AI confusion risk)`
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
if (majorIssues > 0) {
|
|
724
|
+
const majorImpact = Math.min(20, Math.round(majorIssues * 3));
|
|
725
|
+
factors.push({
|
|
726
|
+
name: "Major Issues",
|
|
727
|
+
impact: -majorImpact,
|
|
728
|
+
description: `${majorIssues} major issue${majorIssues > 1 ? "s" : ""} (moderate AI confusion risk)`
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
if (minorIssues > 0 && minorIssues >= totalFilesAnalyzed) {
|
|
732
|
+
const minorImpact = -Math.round(minorIssues * 0.5);
|
|
733
|
+
factors.push({
|
|
734
|
+
name: "Minor Issues",
|
|
735
|
+
impact: minorImpact,
|
|
736
|
+
description: `${minorIssues} minor issue${minorIssues > 1 ? "s" : ""} (slight AI confusion risk)`
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
const recommendations = [];
|
|
740
|
+
if (criticalIssues > 0) {
|
|
741
|
+
const estimatedImpact = Math.min(30, criticalIssues * 10);
|
|
742
|
+
recommendations.push({
|
|
743
|
+
action: "Fix critical naming/pattern inconsistencies (highest AI confusion risk)",
|
|
744
|
+
estimatedImpact,
|
|
745
|
+
priority: "high"
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
if (majorIssues > 5) {
|
|
749
|
+
const estimatedImpact = Math.min(15, Math.round(majorIssues / 2));
|
|
750
|
+
recommendations.push({
|
|
751
|
+
action: "Standardize naming conventions across codebase",
|
|
752
|
+
estimatedImpact,
|
|
753
|
+
priority: "medium"
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
if (issuesPerFile > 3) {
|
|
757
|
+
recommendations.push({
|
|
758
|
+
action: "Establish and enforce coding style guide to reduce inconsistencies",
|
|
759
|
+
estimatedImpact: 12,
|
|
760
|
+
priority: "medium"
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
if (totalIssues > 20 && minorIssues / totalIssues > 0.7) {
|
|
764
|
+
recommendations.push({
|
|
765
|
+
action: "Enable linter/formatter to automatically fix minor style issues",
|
|
766
|
+
estimatedImpact: 8,
|
|
767
|
+
priority: "low"
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
const productivityImpact = (0, import_core5.calculateProductivityImpact)(issues);
|
|
771
|
+
return {
|
|
772
|
+
toolName: import_core5.ToolName.NamingConsistency,
|
|
773
|
+
score,
|
|
774
|
+
rawMetrics: {
|
|
775
|
+
totalIssues,
|
|
776
|
+
criticalIssues,
|
|
777
|
+
majorIssues,
|
|
778
|
+
minorIssues,
|
|
779
|
+
issuesPerFile: Math.round(issuesPerFile * 100) / 100,
|
|
780
|
+
avgWeightedIssuesPerFile: Math.round(avgWeightedIssuesPerFile * 100) / 100,
|
|
781
|
+
// Business value metrics
|
|
782
|
+
estimatedDeveloperHours: productivityImpact.totalHours
|
|
783
|
+
},
|
|
784
|
+
factors,
|
|
785
|
+
recommendations
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
|
|
694
789
|
// src/analyzer.ts
|
|
695
790
|
async function analyzeConsistency(options) {
|
|
696
791
|
const {
|
|
@@ -698,11 +793,11 @@ async function analyzeConsistency(options) {
|
|
|
698
793
|
checkPatterns = true,
|
|
699
794
|
checkArchitecture = false,
|
|
700
795
|
// Not implemented yet
|
|
701
|
-
minSeverity =
|
|
796
|
+
minSeverity = import_core6.Severity.Info,
|
|
702
797
|
...scanOptions
|
|
703
798
|
} = options;
|
|
704
799
|
void checkArchitecture;
|
|
705
|
-
const filePaths = await (0,
|
|
800
|
+
const filePaths = await (0, import_core6.scanFiles)(scanOptions);
|
|
706
801
|
let namingIssues = [];
|
|
707
802
|
if (checkNaming) {
|
|
708
803
|
namingIssues = await analyzeNamingGeneralized(filePaths);
|
|
@@ -728,11 +823,15 @@ async function analyzeConsistency(options) {
|
|
|
728
823
|
fileIssuesMap.get(fileName).push(issue);
|
|
729
824
|
}
|
|
730
825
|
for (const [fileName, issues] of fileIssuesMap.entries()) {
|
|
826
|
+
const scoreResult = calculateConsistencyScore(
|
|
827
|
+
issues,
|
|
828
|
+
filePaths.length
|
|
829
|
+
);
|
|
731
830
|
results.push({
|
|
732
831
|
fileName,
|
|
733
832
|
issues: issues.map((i) => transformToIssue(i)),
|
|
734
833
|
metrics: {
|
|
735
|
-
consistencyScore:
|
|
834
|
+
consistencyScore: scoreResult.score / 100
|
|
736
835
|
}
|
|
737
836
|
});
|
|
738
837
|
}
|
|
@@ -765,21 +864,21 @@ async function analyzeConsistency(options) {
|
|
|
765
864
|
};
|
|
766
865
|
}
|
|
767
866
|
function shouldIncludeSeverity(severity, minSeverity) {
|
|
768
|
-
return (0,
|
|
867
|
+
return (0, import_core6.getSeverityLevel)(severity) >= (0, import_core6.getSeverityLevel)(minSeverity);
|
|
769
868
|
}
|
|
770
869
|
function getIssueType(type) {
|
|
771
|
-
if (!type) return
|
|
870
|
+
if (!type) return import_core6.IssueType.NamingInconsistency;
|
|
772
871
|
const typeMap = {
|
|
773
|
-
"naming-inconsistency":
|
|
774
|
-
"naming-quality":
|
|
775
|
-
"pattern-inconsistency":
|
|
776
|
-
"architecture-inconsistency":
|
|
777
|
-
"error-handling":
|
|
778
|
-
"async-style":
|
|
779
|
-
"import-style":
|
|
780
|
-
"api-design":
|
|
872
|
+
"naming-inconsistency": import_core6.IssueType.NamingInconsistency,
|
|
873
|
+
"naming-quality": import_core6.IssueType.NamingQuality,
|
|
874
|
+
"pattern-inconsistency": import_core6.IssueType.PatternInconsistency,
|
|
875
|
+
"architecture-inconsistency": import_core6.IssueType.ArchitectureInconsistency,
|
|
876
|
+
"error-handling": import_core6.IssueType.PatternInconsistency,
|
|
877
|
+
"async-style": import_core6.IssueType.PatternInconsistency,
|
|
878
|
+
"import-style": import_core6.IssueType.PatternInconsistency,
|
|
879
|
+
"api-design": import_core6.IssueType.PatternInconsistency
|
|
781
880
|
};
|
|
782
|
-
return typeMap[type] ||
|
|
881
|
+
return typeMap[type] || import_core6.IssueType.NamingInconsistency;
|
|
783
882
|
}
|
|
784
883
|
function transformToIssue(i) {
|
|
785
884
|
if (i.message && i.location) {
|
|
@@ -832,125 +931,6 @@ function transformToIssue(i) {
|
|
|
832
931
|
suggestion: i.suggestion
|
|
833
932
|
};
|
|
834
933
|
}
|
|
835
|
-
function calculateConsistencyScore(issues) {
|
|
836
|
-
let totalWeight = 0;
|
|
837
|
-
for (const issue of issues) {
|
|
838
|
-
const val = (0, import_core5.getSeverityLevel)(issue.severity);
|
|
839
|
-
switch (val) {
|
|
840
|
-
case 4:
|
|
841
|
-
totalWeight += 10;
|
|
842
|
-
break;
|
|
843
|
-
case 3:
|
|
844
|
-
totalWeight += 5;
|
|
845
|
-
break;
|
|
846
|
-
case 2:
|
|
847
|
-
totalWeight += 2;
|
|
848
|
-
break;
|
|
849
|
-
case 1:
|
|
850
|
-
totalWeight += 1;
|
|
851
|
-
break;
|
|
852
|
-
default:
|
|
853
|
-
totalWeight += 1;
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
return Math.max(0, 1 - totalWeight / 100);
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
// src/scoring.ts
|
|
860
|
-
var import_core6 = require("@aiready/core");
|
|
861
|
-
function calculateConsistencyScore2(issues, totalFilesAnalyzed, costConfig) {
|
|
862
|
-
void costConfig;
|
|
863
|
-
const criticalIssues = issues.filter((i) => i.severity === "critical").length;
|
|
864
|
-
const majorIssues = issues.filter((i) => i.severity === "major").length;
|
|
865
|
-
const minorIssues = issues.filter((i) => i.severity === "minor").length;
|
|
866
|
-
const totalIssues = issues.length;
|
|
867
|
-
const issuesPerFile = totalFilesAnalyzed > 0 ? totalIssues / totalFilesAnalyzed : 0;
|
|
868
|
-
const densityPenalty = Math.min(50, issuesPerFile * 15);
|
|
869
|
-
const weightedCount = criticalIssues * 10 + majorIssues * 3 + minorIssues * 0.5;
|
|
870
|
-
const avgWeightedIssuesPerFile = totalFilesAnalyzed > 0 ? weightedCount / totalFilesAnalyzed : 0;
|
|
871
|
-
const severityPenalty = Math.min(50, avgWeightedIssuesPerFile * 2);
|
|
872
|
-
const rawScore = 100 - densityPenalty - severityPenalty;
|
|
873
|
-
const score = Math.max(0, Math.min(100, Math.round(rawScore)));
|
|
874
|
-
const factors = [
|
|
875
|
-
{
|
|
876
|
-
name: "Issue Density",
|
|
877
|
-
impact: -Math.round(densityPenalty),
|
|
878
|
-
description: `${issuesPerFile.toFixed(2)} issues per file ${issuesPerFile < 1 ? "(excellent)" : issuesPerFile < 3 ? "(acceptable)" : "(high)"}`
|
|
879
|
-
}
|
|
880
|
-
];
|
|
881
|
-
if (criticalIssues > 0) {
|
|
882
|
-
const criticalImpact = Math.min(30, criticalIssues * 10);
|
|
883
|
-
factors.push({
|
|
884
|
-
name: "Critical Issues",
|
|
885
|
-
impact: -criticalImpact,
|
|
886
|
-
description: `${criticalIssues} critical consistency issue${criticalIssues > 1 ? "s" : ""} (high AI confusion risk)`
|
|
887
|
-
});
|
|
888
|
-
}
|
|
889
|
-
if (majorIssues > 0) {
|
|
890
|
-
const majorImpact = Math.min(20, Math.round(majorIssues * 3));
|
|
891
|
-
factors.push({
|
|
892
|
-
name: "Major Issues",
|
|
893
|
-
impact: -majorImpact,
|
|
894
|
-
description: `${majorIssues} major issue${majorIssues > 1 ? "s" : ""} (moderate AI confusion risk)`
|
|
895
|
-
});
|
|
896
|
-
}
|
|
897
|
-
if (minorIssues > 0 && minorIssues >= totalFilesAnalyzed) {
|
|
898
|
-
const minorImpact = -Math.round(minorIssues * 0.5);
|
|
899
|
-
factors.push({
|
|
900
|
-
name: "Minor Issues",
|
|
901
|
-
impact: minorImpact,
|
|
902
|
-
description: `${minorIssues} minor issue${minorIssues > 1 ? "s" : ""} (slight AI confusion risk)`
|
|
903
|
-
});
|
|
904
|
-
}
|
|
905
|
-
const recommendations = [];
|
|
906
|
-
if (criticalIssues > 0) {
|
|
907
|
-
const estimatedImpact = Math.min(30, criticalIssues * 10);
|
|
908
|
-
recommendations.push({
|
|
909
|
-
action: "Fix critical naming/pattern inconsistencies (highest AI confusion risk)",
|
|
910
|
-
estimatedImpact,
|
|
911
|
-
priority: "high"
|
|
912
|
-
});
|
|
913
|
-
}
|
|
914
|
-
if (majorIssues > 5) {
|
|
915
|
-
const estimatedImpact = Math.min(15, Math.round(majorIssues / 2));
|
|
916
|
-
recommendations.push({
|
|
917
|
-
action: "Standardize naming conventions across codebase",
|
|
918
|
-
estimatedImpact,
|
|
919
|
-
priority: "medium"
|
|
920
|
-
});
|
|
921
|
-
}
|
|
922
|
-
if (issuesPerFile > 3) {
|
|
923
|
-
recommendations.push({
|
|
924
|
-
action: "Establish and enforce coding style guide to reduce inconsistencies",
|
|
925
|
-
estimatedImpact: 12,
|
|
926
|
-
priority: "medium"
|
|
927
|
-
});
|
|
928
|
-
}
|
|
929
|
-
if (totalIssues > 20 && minorIssues / totalIssues > 0.7) {
|
|
930
|
-
recommendations.push({
|
|
931
|
-
action: "Enable linter/formatter to automatically fix minor style issues",
|
|
932
|
-
estimatedImpact: 8,
|
|
933
|
-
priority: "low"
|
|
934
|
-
});
|
|
935
|
-
}
|
|
936
|
-
const productivityImpact = (0, import_core6.calculateProductivityImpact)(issues);
|
|
937
|
-
return {
|
|
938
|
-
toolName: import_core6.ToolName.NamingConsistency,
|
|
939
|
-
score,
|
|
940
|
-
rawMetrics: {
|
|
941
|
-
totalIssues,
|
|
942
|
-
criticalIssues,
|
|
943
|
-
majorIssues,
|
|
944
|
-
minorIssues,
|
|
945
|
-
issuesPerFile: Math.round(issuesPerFile * 100) / 100,
|
|
946
|
-
avgWeightedIssuesPerFile: Math.round(avgWeightedIssuesPerFile * 100) / 100,
|
|
947
|
-
// Business value metrics
|
|
948
|
-
estimatedDeveloperHours: productivityImpact.totalHours
|
|
949
|
-
},
|
|
950
|
-
factors,
|
|
951
|
-
recommendations
|
|
952
|
-
};
|
|
953
|
-
}
|
|
954
934
|
|
|
955
935
|
// src/provider.ts
|
|
956
936
|
var ConsistencyProvider = (0, import_core7.createProvider)({
|
|
@@ -971,7 +951,7 @@ var ConsistencyProvider = (0, import_core7.createProvider)({
|
|
|
971
951
|
const results = output.results;
|
|
972
952
|
const allIssues = results.flatMap((r) => r.issues);
|
|
973
953
|
const totalFiles = output.summary.filesAnalyzed || results.length;
|
|
974
|
-
return
|
|
954
|
+
return calculateConsistencyScore(
|
|
975
955
|
allIssues,
|
|
976
956
|
totalFiles,
|
|
977
957
|
options.costConfig
|