@aiready/consistency 0.6.0 → 0.6.2

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/cli.js CHANGED
@@ -818,7 +818,7 @@ var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
818
818
  async function analyzeNamingAST(files) {
819
819
  const issues = [];
820
820
  const rootDir = files.length > 0 ? (0, import_path.dirname)(files[0]) : process.cwd();
821
- const config = (0, import_core.loadConfig)(rootDir);
821
+ const config = await (0, import_core.loadConfig)(rootDir);
822
822
  const consistencyConfig = config?.tools?.["consistency"];
823
823
  const customAbbreviations = new Set(consistencyConfig?.acceptedAbbreviations || []);
824
824
  const customShortWords = new Set(consistencyConfig?.shortWords || []);
@@ -972,17 +972,19 @@ function analyzeFileNamingAST(file, ast, allAbbreviations, allShortWords, disabl
972
972
  if (!name) return;
973
973
  const line = getLineNumber(node);
974
974
  if (["main", "init", "setup", "bootstrap"].includes(name)) return;
975
- const hasActionVerb = name.match(/^(get|set|is|has|can|should|create|update|delete|fetch|load|save|process|handle|validate|check|find|search|filter|map|reduce|make|do|run|start|stop|build|parse|format|render|calculate|compute|generate|transform|convert|normalize|sanitize|encode|decode|compress|extract|merge|split|join|sort|compare|test|verify|ensure|apply|execute|invoke|call|emit|dispatch|trigger|listen|subscribe|unsubscribe|add|remove|clear|reset|toggle|enable|disable|open|close|connect|disconnect|send|receive|read|write|import|export|register|unregister|mount|unmount|track|store|persist|upsert|derive|classify|combine|discover|activate|require|assert|expect|mask|escape|sign|put|list|complete|page|safe|mock|pick|pluralize|text)/);
975
+ const hasActionVerb = name.match(/^(get|set|is|has|can|should|create|update|delete|fetch|load|save|process|handle|validate|check|find|search|filter|map|reduce|make|do|run|start|stop|build|parse|format|render|calculate|compute|generate|transform|convert|normalize|sanitize|encode|decode|compress|extract|merge|split|join|sort|compare|test|verify|ensure|apply|execute|invoke|call|emit|dispatch|trigger|listen|subscribe|unsubscribe|add|remove|clear|reset|toggle|enable|disable|open|close|connect|disconnect|send|receive|read|write|import|export|register|unregister|mount|unmount|track|store|persist|upsert|derive|classify|combine|discover|activate|require|assert|expect|mask|escape|sign|put|list|complete|page|safe|mock|pick|pluralize|text|count|detect|select)/);
976
976
  const isFactoryPattern = name.match(/(Factory|Builder|Creator|Generator|Provider|Adapter|Mock)$/);
977
977
  const isEventHandler = name.match(/^on[A-Z]/);
978
978
  const isDescriptiveLong = name.length > 15;
979
979
  const isReactHook = name.match(/^use[A-Z]/);
980
- const isHelperPattern = name.match(/^(to|from|with|without|for|as|into)\w+/);
980
+ const isHelperPattern = name.match(/^(to|from|with|without|for|as|into)\w+/) || name.match(/^\w+(To|From|With|Without|For|As|Into)\w*$/);
981
981
  const isUtilityName = ["cn", "proxy", "sitemap", "robots", "gtag"].includes(name);
982
+ const isLanguageKeyword = ["constructor", "toString", "valueOf", "toJSON"].includes(name);
983
+ const isFrameworkPattern = name.match(/^(goto|fill|click|select|submit|wait|expect)\w*/);
982
984
  const isDescriptivePattern = name.match(/^(default|total|count|sum|avg|max|min|initial|current|previous|next)\w+/) || name.match(/\w+(Count|Total|Sum|Average|List|Map|Set|Config|Settings|Options|Props|Data|Info|Details|State|Status|Response|Result)$/);
983
985
  const capitalCount = (name.match(/[A-Z]/g) || []).length;
984
986
  const isCompoundWord = capitalCount >= 3;
985
- if (!hasActionVerb && !isFactoryPattern && !isEventHandler && !isDescriptiveLong && !isReactHook && !isHelperPattern && !isUtilityName && !isDescriptivePattern && !isCompoundWord) {
987
+ if (!hasActionVerb && !isFactoryPattern && !isEventHandler && !isDescriptiveLong && !isReactHook && !isHelperPattern && !isUtilityName && !isDescriptivePattern && !isCompoundWord && !isLanguageKeyword && !isFrameworkPattern) {
986
988
  issues.push({
987
989
  file,
988
990
  line,
@@ -1254,6 +1256,19 @@ async function analyzeConsistency(options) {
1254
1256
  }
1255
1257
  });
1256
1258
  }
1259
+ results.sort((fileResultA, fileResultB) => {
1260
+ const severityOrder = { critical: 0, major: 1, minor: 2, info: 3 };
1261
+ const maxSeverityA = Math.min(
1262
+ ...fileResultA.issues.map((i) => severityOrder[i.severity])
1263
+ );
1264
+ const maxSeverityB = Math.min(
1265
+ ...fileResultB.issues.map((i) => severityOrder[i.severity])
1266
+ );
1267
+ if (maxSeverityA !== maxSeverityB) {
1268
+ return maxSeverityA - maxSeverityB;
1269
+ }
1270
+ return fileResultB.issues.length - fileResultA.issues.length;
1271
+ });
1257
1272
  const recommendations = generateRecommendations(namingIssues, patternIssues);
1258
1273
  return {
1259
1274
  summary: {
@@ -1342,7 +1357,7 @@ EXAMPLES:
1342
1357
  `).argument("<directory>", "Directory to analyze").option("--naming", "Check naming conventions and quality (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code pattern consistency (default: true)").option("--no-patterns", "Skip pattern analysis").option("--architecture", "Check architectural consistency (not yet implemented)").option("--min-severity <level>", "Minimum severity: info|minor|major|critical. Default: info").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|markdown", "console").option("--output-file <path>", "Output file path (for json/markdown)").action(async (directory, options) => {
1343
1358
  console.log(import_chalk.default.blue("\u{1F50D} Analyzing consistency...\n"));
1344
1359
  const startTime = Date.now();
1345
- const config = (0, import_core4.loadConfig)(directory);
1360
+ const config = await (0, import_core4.loadConfig)(directory);
1346
1361
  const defaults = {
1347
1362
  checkNaming: true,
1348
1363
  checkPatterns: true,
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  analyzeConsistency
4
- } from "./chunk-IVRBV7SE.mjs";
4
+ } from "./chunk-ON73WHHU.mjs";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
@@ -28,7 +28,7 @@ EXAMPLES:
28
28
  `).argument("<directory>", "Directory to analyze").option("--naming", "Check naming conventions and quality (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code pattern consistency (default: true)").option("--no-patterns", "Skip pattern analysis").option("--architecture", "Check architectural consistency (not yet implemented)").option("--min-severity <level>", "Minimum severity: info|minor|major|critical. Default: info").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|markdown", "console").option("--output-file <path>", "Output file path (for json/markdown)").action(async (directory, options) => {
29
29
  console.log(chalk.blue("\u{1F50D} Analyzing consistency...\n"));
30
30
  const startTime = Date.now();
31
- const config = loadConfig(directory);
31
+ const config = await loadConfig(directory);
32
32
  const defaults = {
33
33
  checkNaming: true,
34
34
  checkPatterns: true,
package/dist/index.js CHANGED
@@ -820,7 +820,7 @@ var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
820
820
  async function analyzeNamingAST(files) {
821
821
  const issues = [];
822
822
  const rootDir = files.length > 0 ? (0, import_path.dirname)(files[0]) : process.cwd();
823
- const config = (0, import_core.loadConfig)(rootDir);
823
+ const config = await (0, import_core.loadConfig)(rootDir);
824
824
  const consistencyConfig = config?.tools?.["consistency"];
825
825
  const customAbbreviations = new Set(consistencyConfig?.acceptedAbbreviations || []);
826
826
  const customShortWords = new Set(consistencyConfig?.shortWords || []);
@@ -974,17 +974,19 @@ function analyzeFileNamingAST(file, ast, allAbbreviations, allShortWords, disabl
974
974
  if (!name) return;
975
975
  const line = getLineNumber(node);
976
976
  if (["main", "init", "setup", "bootstrap"].includes(name)) return;
977
- const hasActionVerb = name.match(/^(get|set|is|has|can|should|create|update|delete|fetch|load|save|process|handle|validate|check|find|search|filter|map|reduce|make|do|run|start|stop|build|parse|format|render|calculate|compute|generate|transform|convert|normalize|sanitize|encode|decode|compress|extract|merge|split|join|sort|compare|test|verify|ensure|apply|execute|invoke|call|emit|dispatch|trigger|listen|subscribe|unsubscribe|add|remove|clear|reset|toggle|enable|disable|open|close|connect|disconnect|send|receive|read|write|import|export|register|unregister|mount|unmount|track|store|persist|upsert|derive|classify|combine|discover|activate|require|assert|expect|mask|escape|sign|put|list|complete|page|safe|mock|pick|pluralize|text)/);
977
+ const hasActionVerb = name.match(/^(get|set|is|has|can|should|create|update|delete|fetch|load|save|process|handle|validate|check|find|search|filter|map|reduce|make|do|run|start|stop|build|parse|format|render|calculate|compute|generate|transform|convert|normalize|sanitize|encode|decode|compress|extract|merge|split|join|sort|compare|test|verify|ensure|apply|execute|invoke|call|emit|dispatch|trigger|listen|subscribe|unsubscribe|add|remove|clear|reset|toggle|enable|disable|open|close|connect|disconnect|send|receive|read|write|import|export|register|unregister|mount|unmount|track|store|persist|upsert|derive|classify|combine|discover|activate|require|assert|expect|mask|escape|sign|put|list|complete|page|safe|mock|pick|pluralize|text|count|detect|select)/);
978
978
  const isFactoryPattern = name.match(/(Factory|Builder|Creator|Generator|Provider|Adapter|Mock)$/);
979
979
  const isEventHandler = name.match(/^on[A-Z]/);
980
980
  const isDescriptiveLong = name.length > 15;
981
981
  const isReactHook = name.match(/^use[A-Z]/);
982
- const isHelperPattern = name.match(/^(to|from|with|without|for|as|into)\w+/);
982
+ const isHelperPattern = name.match(/^(to|from|with|without|for|as|into)\w+/) || name.match(/^\w+(To|From|With|Without|For|As|Into)\w*$/);
983
983
  const isUtilityName = ["cn", "proxy", "sitemap", "robots", "gtag"].includes(name);
984
+ const isLanguageKeyword = ["constructor", "toString", "valueOf", "toJSON"].includes(name);
985
+ const isFrameworkPattern = name.match(/^(goto|fill|click|select|submit|wait|expect)\w*/);
984
986
  const isDescriptivePattern = name.match(/^(default|total|count|sum|avg|max|min|initial|current|previous|next)\w+/) || name.match(/\w+(Count|Total|Sum|Average|List|Map|Set|Config|Settings|Options|Props|Data|Info|Details|State|Status|Response|Result)$/);
985
987
  const capitalCount = (name.match(/[A-Z]/g) || []).length;
986
988
  const isCompoundWord = capitalCount >= 3;
987
- if (!hasActionVerb && !isFactoryPattern && !isEventHandler && !isDescriptiveLong && !isReactHook && !isHelperPattern && !isUtilityName && !isDescriptivePattern && !isCompoundWord) {
989
+ if (!hasActionVerb && !isFactoryPattern && !isEventHandler && !isDescriptiveLong && !isReactHook && !isHelperPattern && !isUtilityName && !isDescriptivePattern && !isCompoundWord && !isLanguageKeyword && !isFrameworkPattern) {
988
990
  issues.push({
989
991
  file,
990
992
  line,
@@ -1256,6 +1258,19 @@ async function analyzeConsistency(options) {
1256
1258
  }
1257
1259
  });
1258
1260
  }
1261
+ results.sort((fileResultA, fileResultB) => {
1262
+ const severityOrder = { critical: 0, major: 1, minor: 2, info: 3 };
1263
+ const maxSeverityA = Math.min(
1264
+ ...fileResultA.issues.map((i) => severityOrder[i.severity])
1265
+ );
1266
+ const maxSeverityB = Math.min(
1267
+ ...fileResultB.issues.map((i) => severityOrder[i.severity])
1268
+ );
1269
+ if (maxSeverityA !== maxSeverityB) {
1270
+ return maxSeverityA - maxSeverityB;
1271
+ }
1272
+ return fileResultB.issues.length - fileResultA.issues.length;
1273
+ });
1259
1274
  const recommendations = generateRecommendations(namingIssues, patternIssues);
1260
1275
  return {
1261
1276
  summary: {
@@ -1708,7 +1723,7 @@ var ACCEPTABLE_ABBREVIATIONS2 = /* @__PURE__ */ new Set([
1708
1723
  async function analyzeNaming(files) {
1709
1724
  const issues = [];
1710
1725
  const rootDir = files.length > 0 ? (0, import_path2.dirname)(files[0]) : process.cwd();
1711
- const config = (0, import_core4.loadConfig)(rootDir);
1726
+ const config = await (0, import_core4.loadConfig)(rootDir);
1712
1727
  const consistencyConfig = config?.tools?.["consistency"];
1713
1728
  const customAbbreviations = new Set(consistencyConfig?.acceptedAbbreviations || []);
1714
1729
  const customShortWords = new Set(consistencyConfig?.shortWords || []);
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  analyzeConsistency,
3
3
  analyzeNamingAST,
4
4
  analyzePatterns
5
- } from "./chunk-IVRBV7SE.mjs";
5
+ } from "./chunk-ON73WHHU.mjs";
6
6
 
7
7
  // src/analyzers/naming.ts
8
8
  import { readFileContent, loadConfig } from "@aiready/core";
@@ -392,7 +392,7 @@ var ACCEPTABLE_ABBREVIATIONS = /* @__PURE__ */ new Set([
392
392
  async function analyzeNaming(files) {
393
393
  const issues = [];
394
394
  const rootDir = files.length > 0 ? dirname(files[0]) : process.cwd();
395
- const config = loadConfig(rootDir);
395
+ const config = await loadConfig(rootDir);
396
396
  const consistencyConfig = config?.tools?.["consistency"];
397
397
  const customAbbreviations = new Set(consistencyConfig?.acceptedAbbreviations || []);
398
398
  const customShortWords = new Set(consistencyConfig?.shortWords || []);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/consistency",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
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": "^12.1.0",
46
- "@aiready/core": "0.7.1"
46
+ "@aiready/core": "0.7.2"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^22.10.5",
package/src/analyzer.ts CHANGED
@@ -94,6 +94,27 @@ export async function analyzeConsistency(
94
94
  });
95
95
  }
96
96
 
97
+ // Sort results by severity first, then by issue count per file
98
+ results.sort((fileResultA, fileResultB) => {
99
+ const severityOrder = { critical: 0, major: 1, minor: 2, info: 3 };
100
+
101
+ // Get highest severity in each file
102
+ const maxSeverityA = Math.min(
103
+ ...fileResultA.issues.map(i => severityOrder[(i as ConsistencyIssue).severity])
104
+ );
105
+ const maxSeverityB = Math.min(
106
+ ...fileResultB.issues.map(i => severityOrder[(i as ConsistencyIssue).severity])
107
+ );
108
+
109
+ // Sort by severity first
110
+ if (maxSeverityA !== maxSeverityB) {
111
+ return maxSeverityA - maxSeverityB;
112
+ }
113
+
114
+ // Then by issue count (descending)
115
+ return fileResultB.issues.length - fileResultA.issues.length;
116
+ });
117
+
97
118
  // Generate recommendations
98
119
  const recommendations = generateRecommendations(namingIssues, patternIssues);
99
120
 
@@ -74,7 +74,7 @@ export async function analyzeNamingAST(files: string[]): Promise<NamingIssue[]>
74
74
 
75
75
  // Load config
76
76
  const rootDir = files.length > 0 ? dirname(files[0]) : process.cwd();
77
- const config = loadConfig(rootDir);
77
+ const config = await loadConfig(rootDir);
78
78
  const consistencyConfig = config?.tools?.['consistency'];
79
79
 
80
80
  // Merge custom configuration
@@ -289,14 +289,17 @@ function analyzeFileNamingAST(
289
289
  if (['main', 'init', 'setup', 'bootstrap'].includes(name)) return;
290
290
 
291
291
  // Check for action verbs and patterns
292
- const hasActionVerb = name.match(/^(get|set|is|has|can|should|create|update|delete|fetch|load|save|process|handle|validate|check|find|search|filter|map|reduce|make|do|run|start|stop|build|parse|format|render|calculate|compute|generate|transform|convert|normalize|sanitize|encode|decode|compress|extract|merge|split|join|sort|compare|test|verify|ensure|apply|execute|invoke|call|emit|dispatch|trigger|listen|subscribe|unsubscribe|add|remove|clear|reset|toggle|enable|disable|open|close|connect|disconnect|send|receive|read|write|import|export|register|unregister|mount|unmount|track|store|persist|upsert|derive|classify|combine|discover|activate|require|assert|expect|mask|escape|sign|put|list|complete|page|safe|mock|pick|pluralize|text)/);
292
+ const hasActionVerb = name.match(/^(get|set|is|has|can|should|create|update|delete|fetch|load|save|process|handle|validate|check|find|search|filter|map|reduce|make|do|run|start|stop|build|parse|format|render|calculate|compute|generate|transform|convert|normalize|sanitize|encode|decode|compress|extract|merge|split|join|sort|compare|test|verify|ensure|apply|execute|invoke|call|emit|dispatch|trigger|listen|subscribe|unsubscribe|add|remove|clear|reset|toggle|enable|disable|open|close|connect|disconnect|send|receive|read|write|import|export|register|unregister|mount|unmount|track|store|persist|upsert|derive|classify|combine|discover|activate|require|assert|expect|mask|escape|sign|put|list|complete|page|safe|mock|pick|pluralize|text|count|detect|select)/);
293
293
 
294
294
  const isFactoryPattern = name.match(/(Factory|Builder|Creator|Generator|Provider|Adapter|Mock)$/);
295
295
  const isEventHandler = name.match(/^on[A-Z]/);
296
296
  const isDescriptiveLong = name.length > 15;
297
297
  const isReactHook = name.match(/^use[A-Z]/);
298
- const isHelperPattern = name.match(/^(to|from|with|without|for|as|into)\w+/);
298
+ const isHelperPattern = name.match(/^(to|from|with|without|for|as|into)\w+/) ||
299
+ name.match(/^\w+(To|From|With|Without|For|As|Into)\w*$/); // xForY, xToY patterns
299
300
  const isUtilityName = ['cn', 'proxy', 'sitemap', 'robots', 'gtag'].includes(name);
301
+ const isLanguageKeyword = ['constructor', 'toString', 'valueOf', 'toJSON'].includes(name);
302
+ const isFrameworkPattern = name.match(/^(goto|fill|click|select|submit|wait|expect)\w*/); // Page Object Model, test framework patterns
300
303
 
301
304
  // Descriptive patterns: countX, totalX, etc.
302
305
  const isDescriptivePattern = name.match(/^(default|total|count|sum|avg|max|min|initial|current|previous|next)\w+/) ||
@@ -306,7 +309,7 @@ function analyzeFileNamingAST(
306
309
  const capitalCount = (name.match(/[A-Z]/g) || []).length;
307
310
  const isCompoundWord = capitalCount >= 3; // daysSinceLastCommit has 4 capitals
308
311
 
309
- if (!hasActionVerb && !isFactoryPattern && !isEventHandler && !isDescriptiveLong && !isReactHook && !isHelperPattern && !isUtilityName && !isDescriptivePattern && !isCompoundWord) {
312
+ if (!hasActionVerb && !isFactoryPattern && !isEventHandler && !isDescriptiveLong && !isReactHook && !isHelperPattern && !isUtilityName && !isDescriptivePattern && !isCompoundWord && !isLanguageKeyword && !isFrameworkPattern) {
310
313
  issues.push({
311
314
  file,
312
315
  line,
@@ -82,7 +82,7 @@ export async function analyzeNaming(files: string[]): Promise<NamingIssue[]> {
82
82
 
83
83
  // Load config from the first file's directory (or project root)
84
84
  const rootDir = files.length > 0 ? dirname(files[0]) : process.cwd();
85
- const config = loadConfig(rootDir);
85
+ const config = await loadConfig(rootDir);
86
86
  const consistencyConfig = config?.tools?.['consistency'];
87
87
 
88
88
  // Merge custom abbreviations and short words with defaults
package/src/cli.ts CHANGED
@@ -47,7 +47,7 @@ EXAMPLES:
47
47
  const startTime = Date.now();
48
48
 
49
49
  // Load config file if it exists
50
- const config = loadConfig(directory);
50
+ const config = await loadConfig(directory);
51
51
 
52
52
  // Define defaults
53
53
  const defaults = {