@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/dist/index.mjs CHANGED
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  analyzeConsistency,
3
3
  analyzeNamingAST,
4
- analyzePatterns
5
- } from "./chunk-6H3JHDP7.mjs";
4
+ analyzePatterns,
5
+ calculateConsistencyScore
6
+ } from "./chunk-CLWNLHDB.mjs";
6
7
 
7
8
  // src/index.ts
8
9
  import { ToolRegistry } from "@aiready/core";
@@ -10,108 +11,10 @@ import { ToolRegistry } from "@aiready/core";
10
11
  // src/provider.ts
11
12
  import {
12
13
  createProvider,
13
- ToolName as ToolName2
14
+ ToolName
14
15
  } from "@aiready/core";
15
-
16
- // src/scoring.ts
17
- import { calculateProductivityImpact, ToolName } from "@aiready/core";
18
- function calculateConsistencyScore(issues, totalFilesAnalyzed, costConfig) {
19
- void costConfig;
20
- const criticalIssues = issues.filter((i) => i.severity === "critical").length;
21
- const majorIssues = issues.filter((i) => i.severity === "major").length;
22
- const minorIssues = issues.filter((i) => i.severity === "minor").length;
23
- const totalIssues = issues.length;
24
- const issuesPerFile = totalFilesAnalyzed > 0 ? totalIssues / totalFilesAnalyzed : 0;
25
- const densityPenalty = Math.min(50, issuesPerFile * 15);
26
- const weightedCount = criticalIssues * 10 + majorIssues * 3 + minorIssues * 0.5;
27
- const avgWeightedIssuesPerFile = totalFilesAnalyzed > 0 ? weightedCount / totalFilesAnalyzed : 0;
28
- const severityPenalty = Math.min(50, avgWeightedIssuesPerFile * 2);
29
- const rawScore = 100 - densityPenalty - severityPenalty;
30
- const score = Math.max(0, Math.min(100, Math.round(rawScore)));
31
- const factors = [
32
- {
33
- name: "Issue Density",
34
- impact: -Math.round(densityPenalty),
35
- description: `${issuesPerFile.toFixed(2)} issues per file ${issuesPerFile < 1 ? "(excellent)" : issuesPerFile < 3 ? "(acceptable)" : "(high)"}`
36
- }
37
- ];
38
- if (criticalIssues > 0) {
39
- const criticalImpact = Math.min(30, criticalIssues * 10);
40
- factors.push({
41
- name: "Critical Issues",
42
- impact: -criticalImpact,
43
- description: `${criticalIssues} critical consistency issue${criticalIssues > 1 ? "s" : ""} (high AI confusion risk)`
44
- });
45
- }
46
- if (majorIssues > 0) {
47
- const majorImpact = Math.min(20, Math.round(majorIssues * 3));
48
- factors.push({
49
- name: "Major Issues",
50
- impact: -majorImpact,
51
- description: `${majorIssues} major issue${majorIssues > 1 ? "s" : ""} (moderate AI confusion risk)`
52
- });
53
- }
54
- if (minorIssues > 0 && minorIssues >= totalFilesAnalyzed) {
55
- const minorImpact = -Math.round(minorIssues * 0.5);
56
- factors.push({
57
- name: "Minor Issues",
58
- impact: minorImpact,
59
- description: `${minorIssues} minor issue${minorIssues > 1 ? "s" : ""} (slight AI confusion risk)`
60
- });
61
- }
62
- const recommendations = [];
63
- if (criticalIssues > 0) {
64
- const estimatedImpact = Math.min(30, criticalIssues * 10);
65
- recommendations.push({
66
- action: "Fix critical naming/pattern inconsistencies (highest AI confusion risk)",
67
- estimatedImpact,
68
- priority: "high"
69
- });
70
- }
71
- if (majorIssues > 5) {
72
- const estimatedImpact = Math.min(15, Math.round(majorIssues / 2));
73
- recommendations.push({
74
- action: "Standardize naming conventions across codebase",
75
- estimatedImpact,
76
- priority: "medium"
77
- });
78
- }
79
- if (issuesPerFile > 3) {
80
- recommendations.push({
81
- action: "Establish and enforce coding style guide to reduce inconsistencies",
82
- estimatedImpact: 12,
83
- priority: "medium"
84
- });
85
- }
86
- if (totalIssues > 20 && minorIssues / totalIssues > 0.7) {
87
- recommendations.push({
88
- action: "Enable linter/formatter to automatically fix minor style issues",
89
- estimatedImpact: 8,
90
- priority: "low"
91
- });
92
- }
93
- const productivityImpact = calculateProductivityImpact(issues);
94
- return {
95
- toolName: ToolName.NamingConsistency,
96
- score,
97
- rawMetrics: {
98
- totalIssues,
99
- criticalIssues,
100
- majorIssues,
101
- minorIssues,
102
- issuesPerFile: Math.round(issuesPerFile * 100) / 100,
103
- avgWeightedIssuesPerFile: Math.round(avgWeightedIssuesPerFile * 100) / 100,
104
- // Business value metrics
105
- estimatedDeveloperHours: productivityImpact.totalHours
106
- },
107
- factors,
108
- recommendations
109
- };
110
- }
111
-
112
- // src/provider.ts
113
16
  var ConsistencyProvider = createProvider({
114
- id: ToolName2.NamingConsistency,
17
+ id: ToolName.NamingConsistency,
115
18
  alias: ["consistency", "naming", "standards"],
116
19
  version: "0.16.5",
117
20
  defaultWeight: 14,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/consistency",
3
- "version": "0.20.19",
3
+ "version": "0.20.21",
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.20"
46
+ "@aiready/core": "0.23.22"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^24.0.0",
@@ -52,12 +52,12 @@ describe('Consistency Scoring', () => {
52
52
  // score = 100 - 3 - 4 = 93
53
53
  expect(result.score).toBe(93);
54
54
  expect(result.rawMetrics.criticalIssues).toBe(2);
55
- expect(result.factors.some((f) => f.name === 'Critical Issues')).toBe(
56
- true
57
- );
58
- expect(result.recommendations.some((r) => r.priority === 'high')).toBe(
59
- true
60
- );
55
+ expect(
56
+ result.factors.some((f: any) => f.name === 'Critical Issues')
57
+ ).toBe(true);
58
+ expect(
59
+ result.recommendations.some((r: any) => r.priority === 'high')
60
+ ).toBe(true);
61
61
  });
62
62
 
63
63
  it('should apply weighted severity penalties', () => {
@@ -109,10 +109,10 @@ describe('Consistency Scoring', () => {
109
109
 
110
110
  expect(result.recommendations.length).toBeGreaterThan(0);
111
111
  expect(
112
- result.recommendations.some((r) => r.action.includes('critical'))
112
+ result.recommendations.some((r: any) => r.action.includes('critical'))
113
113
  ).toBe(true);
114
114
  expect(
115
- result.recommendations.some((r) => r.action.includes('naming'))
115
+ result.recommendations.some((r: any) => r.action.includes('naming'))
116
116
  ).toBe(true);
117
117
  });
118
118
 
@@ -136,7 +136,7 @@ describe('Consistency Scoring', () => {
136
136
  const result = calculateConsistencyScore(issues, 10);
137
137
 
138
138
  expect(
139
- result.recommendations.some((r) => r.action.includes('linter'))
139
+ result.recommendations.some((r: any) => r.action.includes('linter'))
140
140
  ).toBe(true);
141
141
  });
142
142
 
package/src/analyzer.ts CHANGED
@@ -13,6 +13,7 @@ import type {
13
13
  import { analyzeNamingAST } from './analyzers/naming-ast';
14
14
  import { analyzeNamingGeneralized } from './analyzers/naming-generalized';
15
15
  import { analyzePatterns } from './analyzers/patterns';
16
+ import { calculateConsistencyScore as calculateConsistencyScoreFromScoring } from './scoring';
16
17
 
17
18
  /**
18
19
  * Main consistency analyzer that orchestrates all analysis types.
@@ -90,11 +91,15 @@ export async function analyzeConsistency(
90
91
 
91
92
  // Build final results
92
93
  for (const [fileName, issues] of fileIssuesMap.entries()) {
94
+ const scoreResult = calculateConsistencyScoreFromScoring(
95
+ issues,
96
+ filePaths.length
97
+ );
93
98
  results.push({
94
99
  fileName,
95
100
  issues: issues.map((i) => transformToIssue(i)),
96
101
  metrics: {
97
- consistencyScore: calculateConsistencyScore(issues),
102
+ consistencyScore: scoreResult.score / 100,
98
103
  },
99
104
  });
100
105
  }
@@ -234,28 +239,3 @@ function transformToIssue(i: any): Issue {
234
239
  suggestion: i.suggestion,
235
240
  };
236
241
  }
237
-
238
- function calculateConsistencyScore(issues: ConsistencyIssue[]): number {
239
- let totalWeight = 0;
240
- for (const issue of issues) {
241
- const val = getSeverityLevel(issue.severity);
242
- switch (val) {
243
- case 4:
244
- totalWeight += 10;
245
- break;
246
- case 3:
247
- totalWeight += 5;
248
- break;
249
- case 2:
250
- totalWeight += 2;
251
- break;
252
- case 1:
253
- totalWeight += 1;
254
- break;
255
- default:
256
- totalWeight += 1;
257
- }
258
- }
259
- // Score from 0-1, where 1 is perfect
260
- return Math.max(0, 1 - totalWeight / 100);
261
- }
@@ -79,12 +79,10 @@ function analyzeIdentifiers(
79
79
  );
80
80
  } else if (param.type === 'ObjectPattern') {
81
81
  // Handle destructured parameters: { id, name }
82
- extractDestructuredIdentifiers(
83
- param,
84
- true,
85
- scopeTracker,
86
- isArrowParameter
87
- );
82
+ extractDestructuredIdentifiers(param, scopeTracker, {
83
+ isParameter: true,
84
+ isArrowParameter,
85
+ });
88
86
  }
89
87
  });
90
88
  }
@@ -299,10 +297,14 @@ class ScopeTracker {
299
297
  */
300
298
  function extractDestructuredIdentifiers(
301
299
  node: TSESTree.ObjectPattern | TSESTree.ArrayPattern,
302
- isParameter: boolean,
303
300
  scopeTracker: ScopeTracker,
304
- isArrowParameter: boolean = false
301
+ options: {
302
+ isParameter?: boolean;
303
+ isArrowParameter?: boolean;
304
+ } = {}
305
305
  ) {
306
+ const { isParameter = false, isArrowParameter = false } = options;
307
+
306
308
  if (node.type === 'ObjectPattern') {
307
309
  node.properties.forEach((prop) => {
308
310
  if (prop.type === 'Property' && prop.value.type === 'Identifier') {
@@ -58,7 +58,7 @@ export async function analyzeNamingGeneralized(
58
58
  const issues: NamingIssue[] = [];
59
59
 
60
60
  for (const file of files) {
61
- const parser = getParser(file);
61
+ const parser = await getParser(file);
62
62
  if (!parser) continue;
63
63
 
64
64
  try {