@aiready/consistency 0.6.16 → 0.7.0

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
@@ -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 import_core3 = require("@aiready/core");
30
+ var import_core4 = require("@aiready/core");
31
31
 
32
32
  // src/utils/ast-parser.ts
33
33
  var import_typescript_estree = require("@typescript-eslint/typescript-estree");
@@ -1083,8 +1083,120 @@ function extractIdentifiersFromPattern(pattern, scopeTracker, isParameter, ances
1083
1083
  }
1084
1084
  }
1085
1085
 
1086
- // src/analyzers/patterns.ts
1086
+ // src/analyzers/naming-python.ts
1087
1087
  var import_core2 = require("@aiready/core");
1088
+ async function analyzePythonNaming(files) {
1089
+ const issues = [];
1090
+ const parser = (0, import_core2.getParser)("dummy.py");
1091
+ if (!parser) {
1092
+ console.warn("Python parser not available");
1093
+ return issues;
1094
+ }
1095
+ const pythonFiles = files.filter((f) => f.toLowerCase().endsWith(".py"));
1096
+ for (const file of pythonFiles) {
1097
+ try {
1098
+ const fs = await import("fs");
1099
+ const code = await fs.promises.readFile(file, "utf-8");
1100
+ const result = parser.parse(code, file);
1101
+ for (const exp of result.exports) {
1102
+ const nameIssue = checkPythonNaming(exp.name, exp.type, file, exp.loc?.start.line || 0);
1103
+ if (nameIssue) {
1104
+ issues.push(nameIssue);
1105
+ }
1106
+ }
1107
+ for (const imp of result.imports) {
1108
+ for (const spec of imp.specifiers) {
1109
+ if (spec !== "*" && spec !== "default") {
1110
+ const nameIssue = checkPythonNaming(spec, "variable", file, imp.loc?.start.line || 0);
1111
+ if (nameIssue) {
1112
+ issues.push(nameIssue);
1113
+ }
1114
+ }
1115
+ }
1116
+ }
1117
+ } catch (error) {
1118
+ console.warn(`Skipping ${file} due to error:`, error);
1119
+ }
1120
+ }
1121
+ return issues;
1122
+ }
1123
+ function checkPythonNaming(identifier, type, file, line) {
1124
+ const parser = (0, import_core2.getParser)("dummy.py");
1125
+ const conventions = parser?.getNamingConventions();
1126
+ if (!conventions) return null;
1127
+ if (conventions.exceptions?.includes(identifier)) {
1128
+ return null;
1129
+ }
1130
+ if (type === "class") {
1131
+ if (!conventions.classPattern.test(identifier)) {
1132
+ return {
1133
+ type: "poor-naming",
1134
+ identifier,
1135
+ file,
1136
+ line,
1137
+ column: 0,
1138
+ severity: "major",
1139
+ category: "naming",
1140
+ suggestion: `Class names should use PascalCase (e.g., ${toPascalCase(identifier)})`
1141
+ };
1142
+ }
1143
+ } else if (type === "function") {
1144
+ if (!conventions.functionPattern.test(identifier)) {
1145
+ if (/^[a-z][a-zA-Z0-9]*$/.test(identifier) && /[A-Z]/.test(identifier)) {
1146
+ return {
1147
+ type: "convention-mix",
1148
+ identifier,
1149
+ file,
1150
+ line,
1151
+ column: 0,
1152
+ severity: "major",
1153
+ category: "naming",
1154
+ suggestion: `Function names should use snake_case, not camelCase (e.g., ${toSnakeCase(identifier)})`
1155
+ };
1156
+ }
1157
+ }
1158
+ } else if (type === "const" || type === "variable") {
1159
+ if (identifier === identifier.toUpperCase() && identifier.length > 1) {
1160
+ if (!conventions.constantPattern.test(identifier)) {
1161
+ return {
1162
+ type: "poor-naming",
1163
+ identifier,
1164
+ file,
1165
+ line,
1166
+ column: 0,
1167
+ severity: "minor",
1168
+ category: "naming",
1169
+ suggestion: "Constants should use UPPER_CASE_WITH_UNDERSCORES"
1170
+ };
1171
+ }
1172
+ } else {
1173
+ if (!conventions.variablePattern.test(identifier)) {
1174
+ if (/^[a-z][a-zA-Z0-9]*$/.test(identifier) && /[A-Z]/.test(identifier)) {
1175
+ return {
1176
+ type: "convention-mix",
1177
+ identifier,
1178
+ file,
1179
+ line,
1180
+ column: 0,
1181
+ severity: "major",
1182
+ category: "naming",
1183
+ suggestion: `Variable names should use snake_case, not camelCase (e.g., ${toSnakeCase(identifier)})`
1184
+ };
1185
+ }
1186
+ }
1187
+ }
1188
+ }
1189
+ return null;
1190
+ }
1191
+ function toSnakeCase(str) {
1192
+ return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
1193
+ }
1194
+ function toPascalCase(str) {
1195
+ return str.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
1196
+ }
1197
+
1198
+ // src/analyzers/patterns.ts
1199
+ var import_core3 = require("@aiready/core");
1088
1200
  async function analyzePatterns(files) {
1089
1201
  const issues = [];
1090
1202
  const errorHandlingIssues = await analyzeErrorHandling(files);
@@ -1103,7 +1215,7 @@ async function analyzeErrorHandling(files) {
1103
1215
  returnsError: []
1104
1216
  };
1105
1217
  for (const file of files) {
1106
- const content = await (0, import_core2.readFileContent)(file);
1218
+ const content = await (0, import_core3.readFileContent)(file);
1107
1219
  if (content.includes("try {") || content.includes("} catch")) {
1108
1220
  patterns.tryCatch.push(file);
1109
1221
  }
@@ -1147,7 +1259,7 @@ async function analyzeAsyncPatterns(files) {
1147
1259
  callbacks: []
1148
1260
  };
1149
1261
  for (const file of files) {
1150
- const content = await (0, import_core2.readFileContent)(file);
1262
+ const content = await (0, import_core3.readFileContent)(file);
1151
1263
  if (content.match(/async\s+(function|\(|[a-zA-Z])/)) {
1152
1264
  patterns.asyncAwait.push(file);
1153
1265
  }
@@ -1189,7 +1301,7 @@ async function analyzeImportStyles(files) {
1189
1301
  mixed: []
1190
1302
  };
1191
1303
  for (const file of files) {
1192
- const content = await (0, import_core2.readFileContent)(file);
1304
+ const content = await (0, import_core3.readFileContent)(file);
1193
1305
  const hasESM = content.match(/^import\s+/m);
1194
1306
  const hasCJS = hasActualRequireCalls(content);
1195
1307
  if (hasESM && hasCJS) {
@@ -1247,8 +1359,15 @@ async function analyzeConsistency(options) {
1247
1359
  minSeverity = "info",
1248
1360
  ...scanOptions
1249
1361
  } = options;
1250
- const filePaths = await (0, import_core3.scanFiles)(scanOptions);
1251
- const namingIssues = checkNaming ? await analyzeNamingAST(filePaths) : [];
1362
+ const filePaths = await (0, import_core4.scanFiles)(scanOptions);
1363
+ const tsJsFiles = filePaths.filter((f) => /\.(ts|tsx|js|jsx)$/i.test(f));
1364
+ const pythonFiles = filePaths.filter((f) => /\.py$/i.test(f));
1365
+ let namingIssues = [];
1366
+ if (checkNaming) {
1367
+ const tsJsNamingIssues = tsJsFiles.length > 0 ? await analyzeNamingAST(tsJsFiles) : [];
1368
+ const pythonNamingIssues = pythonFiles.length > 0 ? await analyzePythonNaming(pythonFiles) : [];
1369
+ namingIssues = [...tsJsNamingIssues, ...pythonNamingIssues];
1370
+ }
1252
1371
  const patternIssues = checkPatterns ? await analyzePatterns(filePaths) : [];
1253
1372
  const results = [];
1254
1373
  const fileIssuesMap = /* @__PURE__ */ new Map();
@@ -1389,7 +1508,7 @@ function generateRecommendations(namingIssues, patternIssues) {
1389
1508
  var import_chalk = __toESM(require("chalk"));
1390
1509
  var import_fs2 = require("fs");
1391
1510
  var import_path2 = require("path");
1392
- var import_core4 = require("@aiready/core");
1511
+ var import_core5 = require("@aiready/core");
1393
1512
  var program = new import_commander.Command();
1394
1513
  program.name("aiready-consistency").description("Detect consistency patterns in naming, code structure, and architecture").version("0.1.0").addHelpText("after", `
1395
1514
  LANGUAGE SUPPORT:
@@ -1413,7 +1532,7 @@ EXAMPLES:
1413
1532
  `).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) => {
1414
1533
  console.log(import_chalk.default.blue("\u{1F50D} Analyzing consistency...\n"));
1415
1534
  const startTime = Date.now();
1416
- const config = await (0, import_core4.loadConfig)(directory);
1535
+ const config = await (0, import_core5.loadConfig)(directory);
1417
1536
  const defaults = {
1418
1537
  checkNaming: true,
1419
1538
  checkPatterns: true,
@@ -1422,7 +1541,7 @@ EXAMPLES:
1422
1541
  include: void 0,
1423
1542
  exclude: void 0
1424
1543
  };
1425
- const mergedConfig = (0, import_core4.mergeConfigWithDefaults)(config, defaults);
1544
+ const mergedConfig = (0, import_core5.mergeConfigWithDefaults)(config, defaults);
1426
1545
  const finalOptions = {
1427
1546
  rootDir: directory,
1428
1547
  checkNaming: options.naming !== false && mergedConfig.checkNaming,
@@ -1436,7 +1555,7 @@ EXAMPLES:
1436
1555
  const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
1437
1556
  if (options.output === "json") {
1438
1557
  const output = JSON.stringify(report, null, 2);
1439
- const outputPath = (0, import_core4.resolveOutputPath)(
1558
+ const outputPath = (0, import_core5.resolveOutputPath)(
1440
1559
  options.outputFile,
1441
1560
  `consistency-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.json`,
1442
1561
  directory
@@ -1449,7 +1568,7 @@ EXAMPLES:
1449
1568
  console.log(import_chalk.default.green(`\u2713 Report saved to ${outputPath}`));
1450
1569
  } else if (options.output === "markdown") {
1451
1570
  const markdown = generateMarkdownReport(report, elapsedTime);
1452
- const outputPath = (0, import_core4.resolveOutputPath)(
1571
+ const outputPath = (0, import_core5.resolveOutputPath)(
1453
1572
  options.outputFile,
1454
1573
  `consistency-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.md`,
1455
1574
  directory
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  analyzeConsistency
4
- } from "./chunk-MM2PLUCH.mjs";
4
+ } from "./chunk-YEHXYHGY.mjs";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
package/dist/index.d.mts CHANGED
@@ -54,8 +54,7 @@ interface ConsistencyReport {
54
54
 
55
55
  /**
56
56
  * Main consistency analyzer that orchestrates all analysis types
57
- * Note: Currently only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
58
- * Python and other language files will be ignored during naming analysis.
57
+ * Supports: TypeScript, JavaScript, Python
59
58
  */
60
59
  declare function analyzeConsistency(options: ConsistencyOptions): Promise<ConsistencyReport>;
61
60
 
package/dist/index.d.ts CHANGED
@@ -54,8 +54,7 @@ interface ConsistencyReport {
54
54
 
55
55
  /**
56
56
  * Main consistency analyzer that orchestrates all analysis types
57
- * Note: Currently only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
58
- * Python and other language files will be ignored during naming analysis.
57
+ * Supports: TypeScript, JavaScript, Python
59
58
  */
60
59
  declare function analyzeConsistency(options: ConsistencyOptions): Promise<ConsistencyReport>;
61
60
 
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -30,7 +40,7 @@ __export(index_exports, {
30
40
  module.exports = __toCommonJS(index_exports);
31
41
 
32
42
  // src/analyzer.ts
33
- var import_core3 = require("@aiready/core");
43
+ var import_core4 = require("@aiready/core");
34
44
 
35
45
  // src/utils/ast-parser.ts
36
46
  var import_typescript_estree = require("@typescript-eslint/typescript-estree");
@@ -1097,8 +1107,120 @@ function extractIdentifiersFromPattern(pattern, scopeTracker, isParameter, ances
1097
1107
  }
1098
1108
  }
1099
1109
 
1100
- // src/analyzers/patterns.ts
1110
+ // src/analyzers/naming-python.ts
1101
1111
  var import_core2 = require("@aiready/core");
1112
+ async function analyzePythonNaming(files) {
1113
+ const issues = [];
1114
+ const parser = (0, import_core2.getParser)("dummy.py");
1115
+ if (!parser) {
1116
+ console.warn("Python parser not available");
1117
+ return issues;
1118
+ }
1119
+ const pythonFiles = files.filter((f) => f.toLowerCase().endsWith(".py"));
1120
+ for (const file of pythonFiles) {
1121
+ try {
1122
+ const fs = await import("fs");
1123
+ const code = await fs.promises.readFile(file, "utf-8");
1124
+ const result = parser.parse(code, file);
1125
+ for (const exp of result.exports) {
1126
+ const nameIssue = checkPythonNaming(exp.name, exp.type, file, exp.loc?.start.line || 0);
1127
+ if (nameIssue) {
1128
+ issues.push(nameIssue);
1129
+ }
1130
+ }
1131
+ for (const imp of result.imports) {
1132
+ for (const spec of imp.specifiers) {
1133
+ if (spec !== "*" && spec !== "default") {
1134
+ const nameIssue = checkPythonNaming(spec, "variable", file, imp.loc?.start.line || 0);
1135
+ if (nameIssue) {
1136
+ issues.push(nameIssue);
1137
+ }
1138
+ }
1139
+ }
1140
+ }
1141
+ } catch (error) {
1142
+ console.warn(`Skipping ${file} due to error:`, error);
1143
+ }
1144
+ }
1145
+ return issues;
1146
+ }
1147
+ function checkPythonNaming(identifier, type, file, line) {
1148
+ const parser = (0, import_core2.getParser)("dummy.py");
1149
+ const conventions = parser?.getNamingConventions();
1150
+ if (!conventions) return null;
1151
+ if (conventions.exceptions?.includes(identifier)) {
1152
+ return null;
1153
+ }
1154
+ if (type === "class") {
1155
+ if (!conventions.classPattern.test(identifier)) {
1156
+ return {
1157
+ type: "poor-naming",
1158
+ identifier,
1159
+ file,
1160
+ line,
1161
+ column: 0,
1162
+ severity: "major",
1163
+ category: "naming",
1164
+ suggestion: `Class names should use PascalCase (e.g., ${toPascalCase(identifier)})`
1165
+ };
1166
+ }
1167
+ } else if (type === "function") {
1168
+ if (!conventions.functionPattern.test(identifier)) {
1169
+ if (/^[a-z][a-zA-Z0-9]*$/.test(identifier) && /[A-Z]/.test(identifier)) {
1170
+ return {
1171
+ type: "convention-mix",
1172
+ identifier,
1173
+ file,
1174
+ line,
1175
+ column: 0,
1176
+ severity: "major",
1177
+ category: "naming",
1178
+ suggestion: `Function names should use snake_case, not camelCase (e.g., ${toSnakeCase(identifier)})`
1179
+ };
1180
+ }
1181
+ }
1182
+ } else if (type === "const" || type === "variable") {
1183
+ if (identifier === identifier.toUpperCase() && identifier.length > 1) {
1184
+ if (!conventions.constantPattern.test(identifier)) {
1185
+ return {
1186
+ type: "poor-naming",
1187
+ identifier,
1188
+ file,
1189
+ line,
1190
+ column: 0,
1191
+ severity: "minor",
1192
+ category: "naming",
1193
+ suggestion: "Constants should use UPPER_CASE_WITH_UNDERSCORES"
1194
+ };
1195
+ }
1196
+ } else {
1197
+ if (!conventions.variablePattern.test(identifier)) {
1198
+ if (/^[a-z][a-zA-Z0-9]*$/.test(identifier) && /[A-Z]/.test(identifier)) {
1199
+ return {
1200
+ type: "convention-mix",
1201
+ identifier,
1202
+ file,
1203
+ line,
1204
+ column: 0,
1205
+ severity: "major",
1206
+ category: "naming",
1207
+ suggestion: `Variable names should use snake_case, not camelCase (e.g., ${toSnakeCase(identifier)})`
1208
+ };
1209
+ }
1210
+ }
1211
+ }
1212
+ }
1213
+ return null;
1214
+ }
1215
+ function toSnakeCase(str) {
1216
+ return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
1217
+ }
1218
+ function toPascalCase(str) {
1219
+ return str.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
1220
+ }
1221
+
1222
+ // src/analyzers/patterns.ts
1223
+ var import_core3 = require("@aiready/core");
1102
1224
  async function analyzePatterns(files) {
1103
1225
  const issues = [];
1104
1226
  const errorHandlingIssues = await analyzeErrorHandling(files);
@@ -1117,7 +1239,7 @@ async function analyzeErrorHandling(files) {
1117
1239
  returnsError: []
1118
1240
  };
1119
1241
  for (const file of files) {
1120
- const content = await (0, import_core2.readFileContent)(file);
1242
+ const content = await (0, import_core3.readFileContent)(file);
1121
1243
  if (content.includes("try {") || content.includes("} catch")) {
1122
1244
  patterns.tryCatch.push(file);
1123
1245
  }
@@ -1161,7 +1283,7 @@ async function analyzeAsyncPatterns(files) {
1161
1283
  callbacks: []
1162
1284
  };
1163
1285
  for (const file of files) {
1164
- const content = await (0, import_core2.readFileContent)(file);
1286
+ const content = await (0, import_core3.readFileContent)(file);
1165
1287
  if (content.match(/async\s+(function|\(|[a-zA-Z])/)) {
1166
1288
  patterns.asyncAwait.push(file);
1167
1289
  }
@@ -1203,7 +1325,7 @@ async function analyzeImportStyles(files) {
1203
1325
  mixed: []
1204
1326
  };
1205
1327
  for (const file of files) {
1206
- const content = await (0, import_core2.readFileContent)(file);
1328
+ const content = await (0, import_core3.readFileContent)(file);
1207
1329
  const hasESM = content.match(/^import\s+/m);
1208
1330
  const hasCJS = hasActualRequireCalls(content);
1209
1331
  if (hasESM && hasCJS) {
@@ -1261,8 +1383,15 @@ async function analyzeConsistency(options) {
1261
1383
  minSeverity = "info",
1262
1384
  ...scanOptions
1263
1385
  } = options;
1264
- const filePaths = await (0, import_core3.scanFiles)(scanOptions);
1265
- const namingIssues = checkNaming ? await analyzeNamingAST(filePaths) : [];
1386
+ const filePaths = await (0, import_core4.scanFiles)(scanOptions);
1387
+ const tsJsFiles = filePaths.filter((f) => /\.(ts|tsx|js|jsx)$/i.test(f));
1388
+ const pythonFiles = filePaths.filter((f) => /\.py$/i.test(f));
1389
+ let namingIssues = [];
1390
+ if (checkNaming) {
1391
+ const tsJsNamingIssues = tsJsFiles.length > 0 ? await analyzeNamingAST(tsJsFiles) : [];
1392
+ const pythonNamingIssues = pythonFiles.length > 0 ? await analyzePythonNaming(pythonFiles) : [];
1393
+ namingIssues = [...tsJsNamingIssues, ...pythonNamingIssues];
1394
+ }
1266
1395
  const patternIssues = checkPatterns ? await analyzePatterns(filePaths) : [];
1267
1396
  const results = [];
1268
1397
  const fileIssuesMap = /* @__PURE__ */ new Map();
@@ -1400,12 +1529,12 @@ function generateRecommendations(namingIssues, patternIssues) {
1400
1529
  }
1401
1530
 
1402
1531
  // src/analyzers/naming.ts
1403
- var import_core4 = require("@aiready/core");
1532
+ var import_core5 = require("@aiready/core");
1404
1533
  async function analyzeNaming(files) {
1405
1534
  const issues = [];
1406
1535
  const { customAbbreviations, customShortWords, disabledChecks } = await loadNamingConfig(files);
1407
1536
  for (const file of files) {
1408
- const content = await (0, import_core4.readFileContent)(file);
1537
+ const content = await (0, import_core5.readFileContent)(file);
1409
1538
  const fileIssues = analyzeFileNaming(file, content, customAbbreviations, customShortWords, disabledChecks);
1410
1539
  issues.push(...fileIssues);
1411
1540
  }
package/dist/index.mjs CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  detectNamingConventions,
8
8
  loadNamingConfig,
9
9
  snakeCaseToCamelCase
10
- } from "./chunk-MM2PLUCH.mjs";
10
+ } from "./chunk-YEHXYHGY.mjs";
11
11
 
12
12
  // src/analyzers/naming.ts
13
13
  import { readFileContent } from "@aiready/core";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/consistency",
3
- "version": "0.6.16",
3
+ "version": "0.7.0",
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.7.13"
46
+ "@aiready/core": "0.8.0"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^24.0.0",
package/src/analyzer.ts CHANGED
@@ -2,12 +2,12 @@ import { scanFiles } from '@aiready/core';
2
2
  import type { AnalysisResult, Issue } from '@aiready/core';
3
3
  import type { ConsistencyOptions, ConsistencyReport, ConsistencyIssue } from './types';
4
4
  import { analyzeNamingAST } from './analyzers/naming-ast';
5
+ import { analyzePythonNaming } from './analyzers/naming-python';
5
6
  import { analyzePatterns } from './analyzers/patterns';
6
7
 
7
8
  /**
8
9
  * Main consistency analyzer that orchestrates all analysis types
9
- * Note: Currently only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
10
- * Python and other language files will be ignored during naming analysis.
10
+ * Supports: TypeScript, JavaScript, Python
11
11
  */
12
12
  export async function analyzeConsistency(
13
13
  options: ConsistencyOptions
@@ -23,8 +23,18 @@ export async function analyzeConsistency(
23
23
  // Scan files
24
24
  const filePaths = await scanFiles(scanOptions);
25
25
 
26
- // Collect issues by category
27
- const namingIssues = checkNaming ? await analyzeNamingAST(filePaths) : [];
26
+ // Separate files by language
27
+ const tsJsFiles = filePaths.filter(f => /\.(ts|tsx|js|jsx)$/i.test(f));
28
+ const pythonFiles = filePaths.filter(f => /\.py$/i.test(f));
29
+
30
+ // Collect issues by category - now handles multiple languages
31
+ let namingIssues: any[] = [];
32
+ if (checkNaming) {
33
+ const tsJsNamingIssues = tsJsFiles.length > 0 ? await analyzeNamingAST(tsJsFiles) : [];
34
+ const pythonNamingIssues = pythonFiles.length > 0 ? await analyzePythonNaming(pythonFiles) : [];
35
+ namingIssues = [...tsJsNamingIssues, ...pythonNamingIssues];
36
+ }
37
+
28
38
  const patternIssues = checkPatterns ? await analyzePatterns(filePaths) : [];
29
39
 
30
40
  // Convert to AnalysisResult format