@sun-asterisk/sunlint 1.3.0 → 1.3.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.
Files changed (124) hide show
  1. package/CHANGELOG.md +115 -1
  2. package/CONTRIBUTING.md +249 -605
  3. package/README.md +3 -4
  4. package/config/ci-cd.json +54 -0
  5. package/config/development.json +56 -0
  6. package/config/large-project.json +143 -0
  7. package/config/presets/all.json +0 -1
  8. package/config/release.json +70 -0
  9. package/config/rule-analysis-strategies.js +38 -3
  10. package/config/rules/enhanced-rules-registry.json +474 -1179
  11. package/config/rules/rules-registry-generated.json +3 -3
  12. package/core/cli-action-handler.js +24 -30
  13. package/core/cli-program.js +11 -3
  14. package/core/config-merger.js +29 -2
  15. package/core/enhanced-rules-registry.js +3 -2
  16. package/core/semantic-engine.js +129 -19
  17. package/core/semantic-rule-base.js +4 -2
  18. package/core/unified-rule-registry.js +1 -1
  19. package/docs/COMMAND-EXAMPLES.md +134 -0
  20. package/docs/LARGE-PROJECT-GUIDE.md +324 -0
  21. package/engines/heuristic-engine.js +135 -16
  22. package/integrations/eslint/plugin/index.js +0 -2
  23. package/integrations/eslint/plugin/rules/common/c003-no-vague-abbreviations.js +59 -1
  24. package/integrations/eslint/plugin/rules/common/c006-function-name-verb-noun.js +26 -1
  25. package/integrations/eslint/plugin/rules/common/c030-use-custom-error-classes.js +54 -19
  26. package/origin-rules/common-en.md +19 -15
  27. package/package.json +1 -1
  28. package/rules/common/C002_no_duplicate_code/analyzer.js +334 -36
  29. package/rules/common/C003_no_vague_abbreviations/analyzer.js +220 -35
  30. package/rules/common/C006_function_naming/analyzer.js +29 -3
  31. package/rules/common/C010_limit_block_nesting/analyzer.js +181 -337
  32. package/rules/common/C010_limit_block_nesting/config.json +64 -0
  33. package/rules/common/C010_limit_block_nesting/regex-based-analyzer.js +379 -0
  34. package/rules/common/C010_limit_block_nesting/symbol-based-analyzer.js +231 -0
  35. package/rules/common/C013_no_dead_code/analyzer.js +75 -177
  36. package/rules/common/C013_no_dead_code/config.json +61 -0
  37. package/rules/common/C013_no_dead_code/regex-based-analyzer.js +345 -0
  38. package/rules/common/C013_no_dead_code/symbol-based-analyzer.js +640 -0
  39. package/rules/common/C014_dependency_injection/analyzer.js +48 -313
  40. package/rules/common/C014_dependency_injection/config.json +26 -0
  41. package/rules/common/C014_dependency_injection/symbol-based-analyzer.js +751 -0
  42. package/rules/common/C017_constructor_logic/analyzer.js +254 -17
  43. package/rules/common/C017_constructor_logic/semantic-analyzer.js +340 -0
  44. package/rules/common/C018_no_throw_generic_error/analyzer.js +232 -0
  45. package/rules/common/C018_no_throw_generic_error/config.json +50 -0
  46. package/rules/common/C018_no_throw_generic_error/regex-based-analyzer.js +387 -0
  47. package/rules/common/C018_no_throw_generic_error/symbol-based-analyzer.js +314 -0
  48. package/rules/common/C019_log_level_usage/analyzer.js +110 -317
  49. package/rules/common/C019_log_level_usage/pattern-analyzer.js +88 -0
  50. package/rules/common/C019_log_level_usage/system-log-analyzer.js +1267 -0
  51. package/rules/common/C023_no_duplicate_variable/analyzer.js +180 -0
  52. package/rules/common/C023_no_duplicate_variable/config.json +50 -0
  53. package/rules/common/C023_no_duplicate_variable/symbol-based-analyzer.js +158 -0
  54. package/rules/common/C024_no_scatter_hardcoded_constants/analyzer.js +180 -0
  55. package/rules/common/C024_no_scatter_hardcoded_constants/config.json +50 -0
  56. package/rules/common/C024_no_scatter_hardcoded_constants/symbol-based-analyzer.js +181 -0
  57. package/rules/common/C030_use_custom_error_classes/analyzer.js +200 -0
  58. package/rules/common/C033_separate_service_repository/README.md +78 -0
  59. package/rules/common/C033_separate_service_repository/analyzer.js +160 -0
  60. package/rules/common/C033_separate_service_repository/config.json +50 -0
  61. package/rules/common/C033_separate_service_repository/regex-based-analyzer.js +585 -0
  62. package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +368 -0
  63. package/rules/common/C035_error_logging_context/STRATEGY.md +99 -0
  64. package/rules/common/C035_error_logging_context/analyzer.js +232 -0
  65. package/rules/common/C035_error_logging_context/config.json +54 -0
  66. package/rules/common/C035_error_logging_context/regex-based-analyzer.js +299 -0
  67. package/rules/common/C035_error_logging_context/symbol-based-analyzer.js +454 -0
  68. package/rules/common/C040_centralized_validation/analyzer.js +165 -0
  69. package/rules/common/C040_centralized_validation/config.json +46 -0
  70. package/rules/common/C040_centralized_validation/regex-based-analyzer.js +243 -0
  71. package/rules/common/C040_centralized_validation/symbol-based-analyzer.js +416 -0
  72. package/rules/common/{C076_single_test_behavior → C072_single_test_behavior}/analyzer.js +6 -6
  73. package/rules/common/C076_explicit_function_types/README.md +30 -0
  74. package/rules/common/C076_explicit_function_types/analyzer.js +172 -0
  75. package/rules/common/C076_explicit_function_types/config.json +15 -0
  76. package/rules/common/C076_explicit_function_types/semantic-analyzer.js +341 -0
  77. package/rules/index.js +6 -1
  78. package/rules/parser/rule-parser.js +13 -2
  79. package/rules/security/S005_no_origin_auth/README.md +226 -0
  80. package/rules/security/S005_no_origin_auth/analyzer.js +184 -0
  81. package/rules/security/S005_no_origin_auth/ast-analyzer.js +406 -0
  82. package/rules/security/S005_no_origin_auth/config.json +85 -0
  83. package/rules/security/S006_no_plaintext_recovery_codes/README.md +139 -0
  84. package/rules/security/S006_no_plaintext_recovery_codes/analyzer.js +306 -0
  85. package/rules/security/S006_no_plaintext_recovery_codes/config.json +48 -0
  86. package/rules/security/S007_no_plaintext_otp/README.md +198 -0
  87. package/rules/security/S007_no_plaintext_otp/analyzer.js +406 -0
  88. package/rules/security/S007_no_plaintext_otp/config.json +79 -0
  89. package/rules/security/S007_no_plaintext_otp/semantic-analyzer.js +609 -0
  90. package/rules/security/S007_no_plaintext_otp/semantic-config.json +195 -0
  91. package/rules/security/S007_no_plaintext_otp/semantic-wrapper.js +280 -0
  92. package/rules/security/S009_no_insecure_encryption/README.md +158 -0
  93. package/rules/security/S009_no_insecure_encryption/analyzer.js +319 -0
  94. package/rules/security/S009_no_insecure_encryption/config.json +55 -0
  95. package/rules/security/S010_no_insecure_encryption/README.md +224 -0
  96. package/rules/security/S010_no_insecure_encryption/analyzer.js +493 -0
  97. package/rules/security/S010_no_insecure_encryption/config.json +48 -0
  98. package/rules/security/S016_no_sensitive_querystring/STRATEGY.md +149 -0
  99. package/rules/security/S016_no_sensitive_querystring/analyzer.js +276 -0
  100. package/rules/security/S016_no_sensitive_querystring/config.json +127 -0
  101. package/rules/security/S016_no_sensitive_querystring/regex-based-analyzer.js +258 -0
  102. package/rules/security/S016_no_sensitive_querystring/symbol-based-analyzer.js +495 -0
  103. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +180 -366
  104. package/rules/security/S027_no_hardcoded_secrets/categories.json +153 -0
  105. package/rules/security/S027_no_hardcoded_secrets/categorized-analyzer.js +250 -0
  106. package/rules/security/S048_no_current_password_in_reset/README.md +222 -0
  107. package/rules/security/S048_no_current_password_in_reset/analyzer.js +366 -0
  108. package/rules/security/S048_no_current_password_in_reset/config.json +48 -0
  109. package/rules/security/S055_content_type_validation/README.md +176 -0
  110. package/rules/security/S055_content_type_validation/analyzer.js +312 -0
  111. package/rules/security/S055_content_type_validation/config.json +48 -0
  112. package/rules/utils/rule-helpers.js +140 -1
  113. package/scripts/consolidate-config.js +116 -0
  114. package/scripts/prepare-release.sh +1 -1
  115. package/config/rules/rules-registry.json +0 -765
  116. package/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
  117. package/docs/FUTURE_PACKAGES.md +0 -83
  118. package/docs/HEURISTIC_VS_AI.md +0 -113
  119. package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +0 -112
  120. package/docs/PRODUCTION_SIZE_IMPACT.md +0 -183
  121. package/docs/RELEASE_GUIDE.md +0 -230
  122. package/docs/STANDARDIZED-CATEGORY-FILTERING.md +0 -156
  123. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +0 -254
  124. package/rules/common/C006_function_naming/smart-analyzer.js +0 -503
@@ -1,8 +1,15 @@
1
1
  /**
2
- * C003 Heuristic Analyzer: No vague abbreviations
3
- * Detects unclear variable names and abbreviations
2
+ * C003_no_vague_abbreviations - Enhanced Regex-based Rule Analyzer
3
+ * Category: coding
4
+ *
5
+ * Detects vague variable names and unclear abbreviations
6
+ * Uses enhanced regex patterns with proper comment filtering
4
7
  */
5
8
 
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const { CommentDetector } = require('../../utils/rule-helpers');
12
+
6
13
  class C003NoVagueAbbreviations {
7
14
  constructor(options = {}) {
8
15
  this.options = {
@@ -84,19 +91,43 @@ class C003NoVagueAbbreviations {
84
91
  }
85
92
 
86
93
  /**
87
- * Check if variable is in math/algorithm context
94
+ * Check if variable is a generic type parameter
88
95
  */
89
- isMathContext(content, variableName, line) {
96
+ isGenericTypeParameter(content, variableName, line) {
97
+ // Single uppercase letters T, U, V, K, etc. are common generic type names
98
+ if (!/^[T-Z]$/i.test(variableName)) {
99
+ return false;
100
+ }
101
+
90
102
  const lines = content.split('\n');
91
103
  const currentLine = lines[line - 1] || '';
104
+ const prevLine = lines[line - 2] || '';
105
+ const nextLine = lines[line] || '';
92
106
 
93
- // Math constants like a, b, c in equations
94
- if (/const\s+[a-z]\s*=\s*\d+.*[a-z]\s*=\s*\d+/.test(currentLine)) {
95
- return true;
96
- }
107
+ const contextLines = [prevLine, currentLine, nextLine].join(' ');
97
108
 
98
- // Math operations
99
- if (/[+\-*/=]\s*\w+|\w+\s*[+\-*/=]/.test(currentLine)) {
109
+ // Check for generic type context
110
+ const genericPatterns = [
111
+ /function\s*<[^>]*>/i, // function<T, U>
112
+ /class\s+\w+\s*<[^>]*>/i, // class Foo<T>
113
+ /interface\s+\w+\s*<[^>]*>/i, // interface Bar<T>
114
+ /type\s+\w+\s*<[^>]*>/i, // type Baz<T>
115
+ /<[^>]*>.*=>/i, // <T>(param: T) =>
116
+ /:\s*[T-Z]\s*[,)]/i // parameter: T,
117
+ ];
118
+
119
+ return genericPatterns.some(pattern => pattern.test(contextLines));
120
+ }
121
+
122
+ /**
123
+ * Check if variable is a TypeScript type annotation context
124
+ */
125
+ isTypeAnnotationContext(content, variableName, line) {
126
+ const lines = content.split('\n');
127
+ const currentLine = lines[line - 1] || '';
128
+
129
+ // Check if variable is in type position: param: Type, variable: Type
130
+ if (/:\s*\w+\s*[,)=]/.test(currentLine)) {
100
131
  return true;
101
132
  }
102
133
 
@@ -104,20 +135,44 @@ class C003NoVagueAbbreviations {
104
135
  }
105
136
 
106
137
  /**
107
- * Check if variable is in function parameter context
138
+ * Check if variable is function parameter context
108
139
  */
109
140
  isFunctionParameter(content, variableName, line) {
110
141
  const lines = content.split('\n');
111
142
  const currentLine = lines[line - 1] || '';
112
143
 
113
144
  // Check if we're in a function parameter list
114
- return /function.*\(.*\w+.*\)/.test(currentLine) ||
115
- /\(.*\w+.*\)\s*=>/.test(currentLine) ||
116
- /\w+\s*=>\s*/.test(currentLine);
145
+ const functionPatterns = [
146
+ /function.*\(.*\w+.*\)/, // function foo(param)
147
+ /\(.*\w+.*\)\s*=>/, // (param) =>
148
+ /\w+\s*=>\s*/, // param =>
149
+ /\w+\s*:\s*\w+\s*[,)]/, // param: Type,
150
+ /\w+\?\s*:\s*\w+\s*[,)]/ // param?: Type,
151
+ ];
152
+
153
+ return functionPatterns.some(pattern => pattern.test(currentLine));
154
+ }
155
+
156
+ /**
157
+ * Check if variable has clear type information
158
+ */
159
+ hasTypeInformation(content, variableName, line) {
160
+ const lines = content.split('\n');
161
+ const currentLine = lines[line - 1] || '';
162
+
163
+ // TypeScript type annotations make variables clearer
164
+ // Example: function process(u: User) - 'u' is clear from User type
165
+ const typePatterns = [
166
+ new RegExp(`${variableName}\\s*:\\s*[A-Z]\\w+`), // param: TypeName
167
+ new RegExp(`${variableName}\\s*:\\s*\\w+\\[\\]`), // param: Type[]
168
+ new RegExp(`${variableName}\\s*:\\s*string|number|boolean`) // primitive types
169
+ ];
170
+
171
+ return typePatterns.some(pattern => pattern.test(currentLine));
117
172
  }
118
173
 
119
174
  /**
120
- * Check if variable is coordinate-like
175
+ * Check if variable is coordinate-like or math notation
121
176
  */
122
177
  isCoordinate(variableName) {
123
178
  return /^[xyz](\d+)?$/i.test(variableName) ||
@@ -126,36 +181,62 @@ class C003NoVagueAbbreviations {
126
181
  }
127
182
 
128
183
  /**
129
- * Check if variable is in math/algorithm context
184
+ * Check if variable is math/algorithm context
130
185
  */
131
186
  isMathContext(content, variableName, line) {
132
187
  const lines = content.split('\n');
133
188
  const currentLine = lines[line - 1] || '';
189
+ const prevLine = lines[line - 2] || '';
190
+ const nextLine = lines[line] || '';
134
191
 
135
- // Math constants like a, b, c in equations
136
- if (/const\s+[a-z]\s*=\s*\d+.*[a-z]\s*=\s*\d+/.test(currentLine)) {
192
+ // Check for math variable patterns
193
+ const mathPatterns = [
194
+ // Coordinate pairs: x1, y1, x2, y2
195
+ /^[xyz][12]$/i,
196
+ // Delta notation: dx, dy, dt, dr
197
+ /^d[xyztr]$/i,
198
+ // Math constants: a, b, c in equations
199
+ /^[abc]$/i,
200
+ // Vector components: vx, vy, vz
201
+ /^v[xyz]$/i,
202
+ // Position/point notation: p1, p2
203
+ /^p\d+$/i
204
+ ];
205
+
206
+ if (mathPatterns.some(pattern => pattern.test(variableName))) {
137
207
  return true;
138
208
  }
139
209
 
140
- // Math operations
210
+ // Context-based detection
211
+ const contextLines = [prevLine, currentLine, nextLine].join(' ');
212
+
213
+ // Check for math function names in the context
214
+ if (/function\s+(distance|calculate|compute|solve|formula|algorithm|equation|math)/i.test(contextLines)) {
215
+ return true;
216
+ }
217
+
218
+ // Math operations context
141
219
  if (/[+\-*/=]\s*\w+|\w+\s*[+\-*/=]/.test(currentLine)) {
142
220
  return true;
143
221
  }
144
222
 
145
- return false;
146
- }
147
-
148
- /**
149
- * Check if variable is in function parameter context
150
- */
151
- isFunctionParameter(content, variableName, line) {
152
- const lines = content.split('\n');
153
- const currentLine = lines[line - 1] || '';
223
+ // Math functions context
224
+ if (/Math\.|sqrt|pow|abs|sin|cos|tan|distance|calculate/i.test(contextLines)) {
225
+ return true;
226
+ }
154
227
 
155
- // Check if we're in a function parameter list
156
- return /function.*\(.*\w+.*\)/.test(currentLine) ||
157
- /\(.*\w+.*\)\s*=>/.test(currentLine) ||
158
- /\w+\s*=>\s*/.test(currentLine);
228
+ // Multiple single-char variables (typical in math)
229
+ if (/const\s+[a-z]\s*=.*[a-z]\s*=/.test(currentLine)) {
230
+ return true;
231
+ }
232
+
233
+ // Check for function parameters that are clearly coordinates/math
234
+ // Example: function distance(x1: number, y1: number, x2: number, y2: number)
235
+ if (/function.*\([^)]*\b(x1|y1|x2|y2|dx|dy|dz|dt)\b.*\)/.test(contextLines)) {
236
+ return true;
237
+ }
238
+
239
+ return false;
159
240
  }
160
241
 
161
242
  /**
@@ -244,6 +325,91 @@ class C003NoVagueAbbreviations {
244
325
  return violations;
245
326
  }
246
327
 
328
+ /**
329
+ * Clean line by removing comments but preserving structure for regex matching
330
+ * @param {string} line - Original line
331
+ * @returns {object} { cleanLine, commentRanges }
332
+ */
333
+ cleanLineForMatching(line) {
334
+ return CommentDetector.cleanLineForMatching(line);
335
+ }
336
+
337
+ /**
338
+ * Check if a variable at a specific position is inside a comment
339
+ * @param {string} line - Line content
340
+ * @param {number} position - Position in line where variable was found
341
+ * @returns {boolean} True if position is inside a comment
342
+ */
343
+ isPositionInComment(line, position) {
344
+ return CommentDetector.isPositionInComment(line, position);
345
+ }
346
+
347
+ /**
348
+ * Check if a line is a comment or inside a comment block
349
+ * @param {string} line - Line to check
350
+ * @param {number} lineIndex - Current line index
351
+ * @param {string[]} allLines - All lines in content
352
+ * @returns {boolean} True if line is commented
353
+ */
354
+ isCommentedLine(line, lineIndex, allLines) {
355
+ const trimmedLine = line.trim();
356
+
357
+ // Check single-line comments
358
+ if (trimmedLine.startsWith('//') || trimmedLine.startsWith('#')) {
359
+ return true;
360
+ }
361
+
362
+ // Check if we're inside a multi-line comment
363
+ let inComment = false;
364
+ for (let i = 0; i <= lineIndex; i++) {
365
+ const currentLine = allLines[i];
366
+
367
+ // Find /* and */ on the same line or across lines
368
+ let startPos = 0;
369
+ while (startPos < currentLine.length) {
370
+ const commentStart = currentLine.indexOf('/*', startPos);
371
+ const commentEnd = currentLine.indexOf('*/', startPos);
372
+
373
+ if (commentStart !== -1 && (commentEnd === -1 || commentStart < commentEnd)) {
374
+ inComment = true;
375
+ startPos = commentStart + 2;
376
+ } else if (commentEnd !== -1 && inComment) {
377
+ inComment = false;
378
+ startPos = commentEnd + 2;
379
+ } else {
380
+ break;
381
+ }
382
+ }
383
+
384
+ // If we're at the target line and inside a comment
385
+ if (i === lineIndex && inComment) {
386
+ return true;
387
+ }
388
+ }
389
+
390
+ return false;
391
+ }
392
+
393
+ /**
394
+ * Remove comments from content
395
+ * @param {string} content - File content
396
+ * @returns {string} Content with comments removed
397
+ */
398
+ removeComments(content) {
399
+ let result = content;
400
+
401
+ // Remove single line comments (// comments)
402
+ result = result.replace(/\/\/.*$/gm, '');
403
+
404
+ // Remove multi-line comments (/* comments */)
405
+ result = result.replace(/\/\*[\s\S]*?\*\//g, '');
406
+
407
+ // Remove # comments (for other languages like Python, Shell)
408
+ result = result.replace(/#.*$/gm, '');
409
+
410
+ return result;
411
+ }
412
+
247
413
  /**
248
414
  * Analyze variable names in content
249
415
  */
@@ -255,12 +421,25 @@ class C003NoVagueAbbreviations {
255
421
  }
256
422
 
257
423
  const violations = [];
258
- const lines = content.split('\n');
424
+ const lines = content.split('\n'); // Use original content to preserve line numbers
259
425
 
260
426
  lines.forEach((line, index) => {
261
427
  const lineNumber = index + 1;
262
428
 
263
- // Match variable declarations
429
+ // Skip commented lines
430
+ if (this.isCommentedLine(line, index, lines)) {
431
+ return;
432
+ }
433
+
434
+ // Skip empty lines
435
+ if (!line.trim()) {
436
+ return;
437
+ }
438
+
439
+ // Clean line for better pattern matching
440
+ const { cleanLine } = this.cleanLineForMatching(line);
441
+
442
+ // Match variable declarations on cleaned line
264
443
  const patterns = [
265
444
  // const/let/var declarations
266
445
  /(?:const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*[=:]/g,
@@ -274,7 +453,7 @@ class C003NoVagueAbbreviations {
274
453
 
275
454
  patterns.forEach(pattern => {
276
455
  let match;
277
- while ((match = pattern.exec(line)) !== null) {
456
+ while ((match = pattern.exec(cleanLine)) !== null) {
278
457
  let variableNames = [];
279
458
 
280
459
  if (match[1]) {
@@ -292,6 +471,7 @@ class C003NoVagueAbbreviations {
292
471
  }
293
472
 
294
473
  variableNames.forEach(variableName => {
474
+ // No need to check position since we're using cleaned line
295
475
  const violation = this.checkVariableName(variableName, content, lineNumber, match.index);
296
476
  if (violation) {
297
477
  violations.push({
@@ -395,6 +575,11 @@ class C003NoVagueAbbreviations {
395
575
  };
396
576
  }
397
577
 
578
+ // Check for math context BEFORE suspicious patterns
579
+ if (this.isMathContext(content, variableName, line)) {
580
+ return null;
581
+ }
582
+
398
583
  // Check for suspicious patterns
399
584
  for (const pattern of this.suspiciousPatterns) {
400
585
  if (pattern.test(lowerName)) {
@@ -1,6 +1,7 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const ts = require('typescript');
4
+ const { CommentDetector } = require('../../utils/rule-helpers');
4
5
 
5
6
  /**
6
7
  * SMART C006 ANALYZER - INTELLIGENT FUNCTION NAMING ANALYSIS
@@ -254,6 +255,20 @@ class SmartC006Analyzer {
254
255
  * Uses multiple strategies to detect verbs
255
256
  */
256
257
  isVerbLikeName(functionName) {
258
+ // Strategy 0: REJECT generic/vague verbs that should be flagged
259
+ const genericVerbs = [
260
+ 'do', 'handle', 'process', 'manage', 'execute',
261
+ 'something', 'stuff', 'thing', 'work', 'data'
262
+ ];
263
+
264
+ const isGenericVerb = genericVerbs.some(verb => {
265
+ const verbPattern = new RegExp(`^${verb}([A-Z].*|$)`, 'i');
266
+ return verbPattern.test(functionName);
267
+ });
268
+
269
+ // Reject names starting with generic verbs
270
+ if (isGenericVerb) return false;
271
+
257
272
  // Strategy 1: Known verb prefixes (expanded beyond static list)
258
273
  const verbPrefixes = [
259
274
  'get', 'set', 'is', 'has', 'can', 'should', 'will', 'does',
@@ -262,9 +277,9 @@ class SmartC006Analyzer {
262
277
  'delete', 'remove', 'destroy', 'clean', 'clear', 'reset',
263
278
  'load', 'save', 'fetch', 'retrieve', 'find', 'search', 'query',
264
279
  'validate', 'verify', 'check', 'confirm', 'ensure', 'test',
265
- 'calculate', 'compute', 'process', 'handle', 'manage', 'execute',
280
+ 'calculate', 'compute', 'parse', 'format', 'convert',
266
281
  'send', 'receive', 'transmit', 'broadcast', 'emit', 'publish',
267
- 'parse', 'format', 'convert', 'map', 'filter', 'sort', 'group',
282
+ 'map', 'filter', 'sort', 'group', 'merge', 'split',
268
283
  'connect', 'disconnect', 'open', 'close', 'start', 'stop', 'run',
269
284
  'show', 'hide', 'display', 'render', 'draw', 'paint', 'animate',
270
285
  'add', 'append', 'insert', 'push', 'pop', 'shift', 'splice',
@@ -272,7 +287,7 @@ class SmartC006Analyzer {
272
287
  'refresh', 'restore', 'reload', 'retry', 'resume', 'redirect',
273
288
  'select', 'toggle', 'switch', 'enable', 'disable', 'activate',
274
289
  'expand', 'collapse', 'scroll', 'navigate', 'submit', 'cancel',
275
- 'on', 'handle', 'trigger', 'fire', 'dispatch', 'invoke', 'call'
290
+ 'on', 'trigger', 'fire', 'dispatch', 'invoke', 'call'
276
291
  ];
277
292
 
278
293
  // Strategy 2: Check if starts with known verb
@@ -365,6 +380,17 @@ class SmartC006Analyzer {
365
380
  // 🧮 CONFIDENCE CALCULATION
366
381
  let confidence = 0.5; // Base confidence
367
382
 
383
+ // Boost confidence for clearly generic/vague patterns
384
+ const vagueFunctionNames = [
385
+ 'doSomething', 'handleStuff', 'processData', 'processInfo',
386
+ 'executeWork', 'manageItems', 'doWork', 'handleData',
387
+ 'something', 'stuff', 'thing', 'data', 'info', 'item'
388
+ ];
389
+
390
+ if (vagueFunctionNames.some(vague => functionName.toLowerCase().includes(vague.toLowerCase()))) {
391
+ confidence += 0.4; // Strongly boost confidence for obviously vague names
392
+ }
393
+
368
394
  // Boost confidence for clear noun-only patterns
369
395
  if (/^[a-z]+$/.test(functionName)) {
370
396
  confidence += 0.3; // Simple lowercase nouns: user, data