@sun-asterisk/sunlint 1.2.2 → 1.3.1

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 +107 -1
  2. package/CONTRIBUTING.md +1654 -66
  3. package/README.md +19 -6
  4. package/config/ci-cd.json +54 -0
  5. package/config/development.json +56 -0
  6. package/config/engines/engines-enhanced.json +86 -0
  7. package/config/engines/semantic-config.json +114 -0
  8. package/config/eslint-rule-mapping.json +50 -38
  9. package/config/large-project.json +143 -0
  10. package/config/presets/all.json +0 -1
  11. package/config/release.json +70 -0
  12. package/config/rule-analysis-strategies.js +23 -4
  13. package/config/rules/S027-categories.json +122 -0
  14. package/config/rules/enhanced-rules-registry.json +2564 -0
  15. package/config/rules/rules-registry-generated.json +785 -837
  16. package/config/rules/rules-registry.json +13 -1
  17. package/core/adapters/sunlint-rule-adapter.js +25 -30
  18. package/core/analysis-orchestrator.js +42 -2
  19. package/core/categories.js +52 -0
  20. package/core/category-constants.js +39 -0
  21. package/core/cli-action-handler.js +53 -32
  22. package/core/cli-program.js +11 -3
  23. package/core/config-manager.js +111 -0
  24. package/core/config-merger.js +88 -0
  25. package/core/constants/categories.js +168 -0
  26. package/core/constants/defaults.js +165 -0
  27. package/core/constants/engines.js +185 -0
  28. package/core/constants/index.js +30 -0
  29. package/core/constants/rules.js +215 -0
  30. package/core/enhanced-rules-registry.js +3 -3
  31. package/core/file-targeting-service.js +128 -7
  32. package/core/interfaces/rule-plugin.interface.js +207 -0
  33. package/core/plugin-manager.js +448 -0
  34. package/core/rule-selection-service.js +42 -15
  35. package/core/semantic-engine.js +658 -0
  36. package/core/semantic-rule-base.js +433 -0
  37. package/core/unified-rule-registry.js +484 -0
  38. package/docs/COMMAND-EXAMPLES.md +134 -0
  39. package/docs/CONSTANTS-ARCHITECTURE.md +288 -0
  40. package/docs/LARGE-PROJECT-GUIDE.md +324 -0
  41. package/engines/core/base-engine.js +249 -0
  42. package/engines/engine-factory.js +275 -0
  43. package/engines/eslint-engine.js +171 -19
  44. package/engines/heuristic-engine.js +569 -78
  45. package/integrations/eslint/plugin/index.js +26 -28
  46. package/origin-rules/common-en.md +8 -8
  47. package/package.json +10 -6
  48. package/rules/common/C003_no_vague_abbreviations/analyzer.js +1 -1
  49. package/rules/common/C017_constructor_logic/analyzer.js +254 -17
  50. package/rules/common/C017_constructor_logic/semantic-analyzer.js +340 -0
  51. package/rules/common/C029_catch_block_logging/analyzer.js +17 -5
  52. package/rules/common/C033_separate_service_repository/README.md +78 -0
  53. package/rules/common/C033_separate_service_repository/analyzer.js +160 -0
  54. package/rules/common/C033_separate_service_repository/config.json +50 -0
  55. package/rules/common/C033_separate_service_repository/regex-based-analyzer.js +585 -0
  56. package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +368 -0
  57. package/rules/common/C035_error_logging_context/STRATEGY.md +99 -0
  58. package/rules/common/C035_error_logging_context/analyzer.js +230 -0
  59. package/rules/common/C035_error_logging_context/config.json +54 -0
  60. package/rules/common/C035_error_logging_context/regex-based-analyzer.js +299 -0
  61. package/rules/common/C035_error_logging_context/symbol-based-analyzer.js +454 -0
  62. package/rules/common/C040_centralized_validation/analyzer.js +165 -0
  63. package/rules/common/C040_centralized_validation/config.json +46 -0
  64. package/rules/common/C040_centralized_validation/regex-based-analyzer.js +243 -0
  65. package/rules/common/C040_centralized_validation/symbol-based-analyzer.js +416 -0
  66. package/rules/common/C047_no_duplicate_retry_logic/c047-semantic-rule.js +278 -0
  67. package/rules/common/C047_no_duplicate_retry_logic/symbol-analyzer-enhanced.js +968 -0
  68. package/rules/common/C047_no_duplicate_retry_logic/symbol-config.json +71 -0
  69. package/rules/common/{C076_single_test_behavior → C072_single_test_behavior}/analyzer.js +6 -6
  70. package/rules/common/C076_explicit_function_types/README.md +30 -0
  71. package/rules/common/C076_explicit_function_types/analyzer.js +172 -0
  72. package/rules/common/C076_explicit_function_types/config.json +15 -0
  73. package/rules/common/C076_explicit_function_types/semantic-analyzer.js +341 -0
  74. package/rules/index.js +8 -0
  75. package/rules/parser/rule-parser.js +13 -2
  76. package/rules/security/S005_no_origin_auth/README.md +226 -0
  77. package/rules/security/S005_no_origin_auth/analyzer.js +184 -0
  78. package/rules/security/S005_no_origin_auth/ast-analyzer.js +406 -0
  79. package/rules/security/S005_no_origin_auth/config.json +85 -0
  80. package/rules/security/S006_no_plaintext_recovery_codes/README.md +139 -0
  81. package/rules/security/S006_no_plaintext_recovery_codes/analyzer.js +306 -0
  82. package/rules/security/S006_no_plaintext_recovery_codes/config.json +48 -0
  83. package/rules/security/S007_no_plaintext_otp/README.md +198 -0
  84. package/rules/security/S007_no_plaintext_otp/analyzer.js +406 -0
  85. package/rules/security/S007_no_plaintext_otp/config.json +79 -0
  86. package/rules/security/S007_no_plaintext_otp/semantic-analyzer.js +609 -0
  87. package/rules/security/S007_no_plaintext_otp/semantic-config.json +195 -0
  88. package/rules/security/S007_no_plaintext_otp/semantic-wrapper.js +280 -0
  89. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +180 -366
  90. package/rules/security/S027_no_hardcoded_secrets/categories.json +153 -0
  91. package/rules/security/S027_no_hardcoded_secrets/categorized-analyzer.js +250 -0
  92. package/scripts/category-manager.js +150 -0
  93. package/scripts/generate-rules-registry.js +88 -0
  94. package/scripts/migrate-rule-registry.js +157 -0
  95. package/scripts/prepare-release.sh +1 -1
  96. package/scripts/validate-system.js +48 -0
  97. package/.sunlint.json +0 -35
  98. package/config/README.md +0 -88
  99. package/config/engines/eslint-rule-mapping.json +0 -74
  100. package/config/schemas/sunlint-schema.json +0 -0
  101. package/config/testing/test-s005-working.ts +0 -22
  102. package/core/multi-rule-runner.js +0 -0
  103. package/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
  104. package/docs/FUTURE_PACKAGES.md +0 -83
  105. package/docs/HEURISTIC_VS_AI.md +0 -113
  106. package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +0 -112
  107. package/docs/PRODUCTION_SIZE_IMPACT.md +0 -183
  108. package/docs/RELEASE_GUIDE.md +0 -230
  109. package/docs/STANDARDIZED-CATEGORY-FILTERING.md +0 -156
  110. package/engines/tree-sitter-parser.js +0 -0
  111. package/engines/universal-ast-engine.js +0 -0
  112. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +0 -254
  113. package/rules/common/C029_catch_block_logging/analyzer-backup.js +0 -426
  114. package/rules/common/C029_catch_block_logging/analyzer-fixed.js +0 -130
  115. package/rules/common/C029_catch_block_logging/analyzer-multi-tech.js +0 -487
  116. package/rules/common/C029_catch_block_logging/analyzer-simple.js +0 -110
  117. package/rules/common/C029_catch_block_logging/ast-analyzer-backup.js +0 -441
  118. package/rules/common/C029_catch_block_logging/ast-analyzer-new.js +0 -127
  119. package/rules/common/C029_catch_block_logging/ast-analyzer.js +0 -133
  120. package/rules/common/C029_catch_block_logging/cfg-analyzer.js +0 -408
  121. package/rules/common/C029_catch_block_logging/dataflow-analyzer.js +0 -454
  122. package/rules/common/C029_catch_block_logging/multi-language-ast-engine.js +0 -700
  123. package/rules/common/C029_catch_block_logging/pattern-learning-analyzer.js +0 -568
  124. package/rules/common/C029_catch_block_logging/semantic-analyzer.js +0 -459
package/CONTRIBUTING.md CHANGED
@@ -49,74 +49,917 @@ When contributing to Sun Lint, please follow these coding rules:
49
49
 
50
50
  ## 🔧 **Development Workflow**
51
51
 
52
- ### **Adding a New Quality Rule**
52
+ ### **SunLint Architecture Overview**
53
+
54
+ SunLint uses a **multi-engine architecture** with rule mapping system:
55
+
56
+ - **Heuristic Engine**: Pattern-based analysis using AST (Abstract Syntax Tree)
57
+ - **ESLint Engine**: JavaScript/TypeScript linting using ESLint rules
58
+ - **OpenAI Engine**: AI-powered code analysis
59
+
60
+ **Rule Configuration Files:**
61
+ - `rules/` - Unified rule registry (auto-generated from origin-rules)
62
+ - `config/eslint-rule-mapping.json` - ESLint engine rule mappings
63
+ - `origin-rules/` - Original rule definitions (markdown format)
64
+
65
+ ### **Adding a New Rule (Modern Approach - 2025)**
66
+
67
+ #### **Step 1: Choose Rule Implementation Strategy**
68
+
69
+ **Modern Approach: Hybrid Symbol + Regex Analysis (Recommended)**
70
+ Following the successful C035 pattern, implement rules with both symbol-based and regex-based analyzers for maximum accuracy and fallback coverage.
71
+
72
+ #### **Step 2: Create Rule Directory Structure**
53
73
 
54
- 1. **Create Rule Implementation**
55
74
  ```bash
56
- # Create the rule directory
57
- mkdir -p rules/quality/c042-new-rule
58
- cd rules/quality/c042-new-rule
75
+ # Create rule directory
76
+ mkdir -p rules/common/C042_no_hardcoded_config
77
+
78
+ # Create required files
79
+ touch rules/common/C042_no_hardcoded_config/analyzer.js
80
+ touch rules/common/C042_no_hardcoded_config/symbol-based-analyzer.js
81
+ touch rules/common/C042_no_hardcoded_config/regex-based-analyzer.js
82
+ touch rules/common/C042_no_hardcoded_config/config.json
83
+ touch rules/common/C042_no_hardcoded_config/STRATEGY.md
84
+ ```
85
+
86
+ #### **Step 3: Implement Main Analyzer (Hybrid Orchestrator)**
87
+
88
+ ```javascript
89
+ // rules/common/C042_no_hardcoded_config/analyzer.js
90
+ const C042SymbolBasedAnalyzer = require('./symbol-based-analyzer.js');
91
+ const C042RegexBasedAnalyzer = require('./regex-based-analyzer.js');
92
+
93
+ class C042Analyzer {
94
+ constructor(semanticEngine = null) {
95
+ this.ruleId = 'C042';
96
+ this.ruleName = 'No Hardcoded Configuration Values';
97
+ this.description = 'Avoid hardcoding configuration values in business logic';
98
+ this.semanticEngine = semanticEngine;
99
+ this.verbose = false;
100
+
101
+ // Configuration
102
+ this.config = {
103
+ useSymbolBased: true, // Primary approach
104
+ fallbackToRegex: true, // Only when symbol fails completely
105
+ symbolBasedOnly: false // Can be set to true for pure mode
106
+ };
107
+
108
+ // Initialize both analyzers
109
+ this.symbolAnalyzer = new C042SymbolBasedAnalyzer(semanticEngine);
110
+ this.regexAnalyzer = new C042RegexBasedAnalyzer(semanticEngine);
111
+ }
112
+
113
+ async initialize(semanticEngine = null) {
114
+ if (semanticEngine) {
115
+ this.semanticEngine = semanticEngine;
116
+ }
117
+ this.verbose = semanticEngine?.verbose || false;
118
+
119
+ // Initialize both analyzers
120
+ await this.symbolAnalyzer.initialize(semanticEngine);
121
+ await this.regexAnalyzer.initialize(semanticEngine);
122
+
123
+ if (this.verbose) {
124
+ console.log(`🔧 [C042 Hybrid] Analyzer initialized`);
125
+ }
126
+ }
127
+
128
+ async analyzeFileBasic(filePath, options = {}) {
129
+ try {
130
+ // Try symbol-based analysis first
131
+ if (this.semanticEngine?.isSymbolEngineReady?.() &&
132
+ this.semanticEngine.project) {
133
+
134
+ if (this.verbose) {
135
+ console.log(`🔍 [C042] Using symbol-based analysis for ${filePath}`);
136
+ }
137
+
138
+ const violations = await this.symbolAnalyzer.analyzeFileBasic(filePath, options);
139
+ return violations;
140
+ }
141
+ } catch (error) {
142
+ if (this.verbose) {
143
+ console.warn(`⚠️ [C042] Symbol analysis failed: ${error.message}`);
144
+ }
145
+ }
146
+
147
+ // Fallback to regex-based analysis
148
+ if (this.verbose) {
149
+ console.log(`🔄 [C042] Using regex-based analysis (fallback) for ${filePath}`);
150
+ }
151
+
152
+ return await this.regexAnalyzer.analyzeFileBasic(filePath, options);
153
+ }
154
+
155
+ async analyze(files, language, options = {}) {
156
+ const violations = [];
157
+
158
+ for (const filePath of files) {
159
+ try {
160
+ const fileViolations = await this.analyzeFileBasic(filePath, options);
161
+ violations.push(...fileViolations);
162
+ } catch (error) {
163
+ if (this.verbose) {
164
+ console.warn(`❌ [C042] Analysis failed for ${filePath}:`, error.message);
165
+ }
166
+ }
167
+ }
168
+
169
+ return violations;
170
+ }
171
+ }
172
+
173
+ module.exports = C042Analyzer;
174
+ ```
175
+
176
+ #### **Step 4: Implement Symbol-Based Analyzer (Primary)**
177
+
178
+ ```javascript
179
+ // rules/common/C042_no_hardcoded_config/symbol-based-analyzer.js
180
+ class C042SymbolBasedAnalyzer {
181
+ constructor(semanticEngine = null) {
182
+ this.ruleId = 'C042';
183
+ this.ruleName = 'No Hardcoded Configuration Values (Symbol-Based)';
184
+ this.semanticEngine = semanticEngine;
185
+ this.verbose = false;
186
+
187
+ // Configuration patterns to detect
188
+ this.configPatterns = [
189
+ /^API_/i, /^DATABASE_/i, /^DB_/i,
190
+ /^MAX_/i, /^MIN_/i, /^LIMIT_/i,
191
+ /^TIMEOUT/i, /^PORT$/i, /^HOST$/i,
192
+ /^SECRET/i, /^KEY$/i, /^TOKEN/i
193
+ ];
194
+ }
195
+
196
+ async initialize(semanticEngine = null) {
197
+ if (semanticEngine) {
198
+ this.semanticEngine = semanticEngine;
199
+ }
200
+ this.verbose = semanticEngine?.verbose || false;
201
+
202
+ if (this.verbose) {
203
+ console.log(`🔧 [C042 Symbol-Based] Analyzer initialized`);
204
+ }
205
+ }
206
+
207
+ async analyzeFileBasic(filePath, options = {}) {
208
+ const violations = [];
209
+
210
+ if (!this.semanticEngine?.project) {
211
+ return violations;
212
+ }
213
+
214
+ try {
215
+ const sourceFile = this.semanticEngine.project.getSourceFileByFilePath(filePath);
216
+ if (!sourceFile) {
217
+ return violations;
218
+ }
219
+
220
+ // Analyze variable declarations
221
+ const variableDeclarations = sourceFile.getVariableDeclarations();
222
+ for (const declaration of variableDeclarations) {
223
+ const violation = this.analyzeVariableDeclaration(declaration, filePath);
224
+ if (violation) {
225
+ violations.push(violation);
226
+ }
227
+ }
228
+
229
+ return violations;
230
+ } catch (error) {
231
+ if (this.verbose) {
232
+ console.warn(`⚠️ [C042 Symbol-Based] Analysis failed for ${filePath}:`, error.message);
233
+ }
234
+ return violations;
235
+ }
236
+ }
237
+
238
+ analyzeVariableDeclaration(declaration, filePath) {
239
+ const name = declaration.getName();
240
+ const initializer = declaration.getInitializer();
241
+
242
+ // Check if variable name suggests configuration
243
+ if (!this.isConfigVariable(name)) {
244
+ return null;
245
+ }
246
+
247
+ // Check if value is hardcoded
248
+ if (this.isHardcodedValue(initializer)) {
249
+ const startLineNumber = declaration.getStartLineNumber();
250
+
251
+ return {
252
+ ruleId: this.ruleId,
253
+ severity: 'warning',
254
+ message: `Configuration variable '${name}' should not be hardcoded`,
255
+ source: this.ruleId,
256
+ file: filePath,
257
+ line: startLineNumber,
258
+ column: declaration.getStart() - declaration.getStartLinePos() + 1,
259
+ description: `Symbol-based analysis detected hardcoded configuration value. Use environment variables or config files.`,
260
+ suggestion: `Use process.env.${name} or load from configuration file`,
261
+ category: 'maintainability'
262
+ };
263
+ }
264
+
265
+ return null;
266
+ }
267
+
268
+ isConfigVariable(name) {
269
+ return this.configPatterns.some(pattern => pattern.test(name));
270
+ }
271
+
272
+ isHardcodedValue(initializer) {
273
+ if (!initializer) return false;
274
+
275
+ // Check for literal values (strings, numbers)
276
+ if (initializer.getKind() === ts.SyntaxKind.StringLiteral ||
277
+ initializer.getKind() === ts.SyntaxKind.NumericLiteral) {
278
+ return true;
279
+ }
280
+
281
+ // Check for property access to process.env
282
+ if (initializer.getText().includes('process.env')) {
283
+ return false;
284
+ }
285
+
286
+ return false;
287
+ }
288
+ }
289
+
290
+ module.exports = C042SymbolBasedAnalyzer;
59
291
  ```
60
292
 
61
- 2. **Implement the Rule**
293
+ #### **Step 5: Implement Regex-Based Analyzer (Fallback)**
294
+
62
295
  ```javascript
63
- // rules/quality/c042-new-rule/analyzer.js
64
- class C042NewRuleAnalyzer {
65
- analyze(code, filePath) {
66
- // Implementation following Rule C005 (single responsibility)
67
- return this.findViolations(code, filePath);
296
+ // rules/common/C042_no_hardcoded_config/regex-based-analyzer.js
297
+ class C042RegexBasedAnalyzer {
298
+ constructor(semanticEngine = null) {
299
+ this.ruleId = 'C042';
300
+ this.ruleName = 'No Hardcoded Configuration Values (Regex-Based)';
301
+ this.semanticEngine = semanticEngine;
302
+ this.verbose = false;
303
+
304
+ // Patterns for hardcoded config detection
305
+ this.hardcodedPatterns = [
306
+ /const\s+(API_\w+|DATABASE_\w+|DB_\w+)\s*=\s*["'][^"']+["']/gi,
307
+ /const\s+(MAX_\w+|MIN_\w+|LIMIT_\w+)\s*=\s*\d+/gi,
308
+ /const\s+(TIMEOUT|PORT|HOST)\s*=\s*["']\w+["']|\d+/gi
309
+ ];
310
+ }
311
+
312
+ async initialize(semanticEngine = null) {
313
+ if (semanticEngine) {
314
+ this.semanticEngine = semanticEngine;
315
+ }
316
+ this.verbose = semanticEngine?.verbose || false;
317
+
318
+ if (this.verbose) {
319
+ console.log(`🔧 [C042 Regex-Based] Analyzer initialized`);
320
+ }
68
321
  }
69
322
 
70
- findViolations(code, filePath) {
71
- // Rule C031: Keep validation logic separate
323
+ async analyzeFileBasic(filePath, options = {}) {
324
+ const fs = require('fs');
72
325
  const violations = [];
73
- // Analysis logic here
326
+
327
+ if (!fs.existsSync(filePath)) {
328
+ return violations;
329
+ }
330
+
331
+ const content = fs.readFileSync(filePath, 'utf8');
332
+ const lines = content.split('\n');
333
+
334
+ for (let i = 0; i < lines.length; i++) {
335
+ const line = lines[i];
336
+
337
+ for (const pattern of this.hardcodedPatterns) {
338
+ pattern.lastIndex = 0; // Reset regex
339
+ let match;
340
+
341
+ while ((match = pattern.exec(line)) !== null) {
342
+ // Skip if using process.env
343
+ if (line.includes('process.env')) {
344
+ continue;
345
+ }
346
+
347
+ violations.push({
348
+ ruleId: this.ruleId,
349
+ severity: 'warning',
350
+ message: `Configuration variable '${match[1]}' should not be hardcoded`,
351
+ source: this.ruleId,
352
+ file: filePath,
353
+ line: i + 1,
354
+ column: match.index + 1,
355
+ description: `[REGEX-FALLBACK] Hardcoded configuration detected. Use environment variables or config files.`,
356
+ suggestion: `Use process.env.${match[1]} or load from configuration file`,
357
+ category: 'maintainability'
358
+ });
359
+ }
360
+ }
361
+ }
362
+
363
+ return violations;
364
+ }
365
+
366
+ async analyze(files, language, options = {}) {
367
+ const violations = [];
368
+
369
+ for (const filePath of files) {
370
+ try {
371
+ const fileViolations = await this.analyzeFileBasic(filePath, options);
372
+ violations.push(...fileViolations);
373
+ } catch (error) {
374
+ if (this.verbose) {
375
+ console.warn(`❌ [C042 Regex] Analysis failed for ${filePath}:`, error.message);
376
+ }
377
+ }
378
+ }
379
+
74
380
  return violations;
75
381
  }
76
382
  }
77
383
 
78
- module.exports = C042NewRuleAnalyzer;
384
+ module.exports = C042RegexBasedAnalyzer;
79
385
  ```
80
386
 
81
- 3. **Add Configuration**
387
+ #### **Step 6: Create Rule Configuration**
388
+
82
389
  ```json
83
- // rules/quality/c042-new-rule/config.json
390
+ // rules/common/C042_no_hardcoded_config/config.json
84
391
  {
85
- "id": "C042",
86
- "name": "New Rule Name",
87
- "category": "quality",
88
- "severity": "error",
89
- "description": "Description following Rule C015 (domain language)",
90
- "languages": ["typescript", "dart", "kotlin"],
91
- "tags": ["maintainability", "readability"]
392
+ "ruleId": "C042",
393
+ "name": "No Hardcoded Configuration Values",
394
+ "description": "Avoid hardcoding configuration values in business logic",
395
+ "category": "maintainability",
396
+ "severity": "warning",
397
+ "languages": ["typescript", "javascript"],
398
+ "version": "1.0.0",
399
+ "tags": ["configuration", "maintainability", "environment"],
400
+ "patterns": {
401
+ "configVariables": [
402
+ "API_", "DATABASE_", "DB_", "MAX_", "MIN_", "LIMIT_",
403
+ "TIMEOUT", "PORT", "HOST", "SECRET", "KEY", "TOKEN"
404
+ ],
405
+ "excludePatterns": [
406
+ "process.env", "config.", "getConfig(", "loadConfig("
407
+ ]
408
+ },
409
+ "examples": {
410
+ "bad": [
411
+ "const API_URL = 'https://api.example.com';",
412
+ "const MAX_RETRIES = 5;",
413
+ "const DATABASE_PASSWORD = 'secret123';"
414
+ ],
415
+ "good": [
416
+ "const API_URL = process.env.API_URL;",
417
+ "const MAX_RETRIES = parseInt(process.env.MAX_RETRIES || '3');",
418
+ "const config = loadConfigFromFile();"
419
+ ]
420
+ }
92
421
  }
93
422
  ```
94
423
 
95
- 4. **Update Registry**
424
+ #### **Step 7: Document Analysis Strategy**
425
+
426
+ ```markdown
427
+ <!-- rules/common/C042_no_hardcoded_config/STRATEGY.md -->
428
+ # C042 Analysis Strategy: No Hardcoded Configuration Values
429
+
430
+ ## Overview
431
+ Hybrid approach using symbol-based analysis as primary with regex fallback.
432
+
433
+ ## Symbol-Based Analysis (Primary)
434
+ - Uses ts-morph AST to analyze variable declarations
435
+ - Detects configuration variable patterns by name
436
+ - Checks initializer values for hardcoded literals
437
+ - Excludes process.env and config function calls
438
+
439
+ ## Regex-Based Analysis (Fallback)
440
+ - Pattern matching for common hardcoded config scenarios
441
+ - Simpler but broader detection
442
+ - Used when symbol analysis unavailable
443
+
444
+ ## Strategy Selection
445
+ 1. **Symbol-based**: When ts-morph project available (95% accuracy)
446
+ 2. **Regex-fallback**: When symbol analysis fails (80% accuracy)
447
+
448
+ ## Testing Approach
449
+ Test both analyzers independently and verify hybrid orchestration.
450
+ ```
451
+
452
+ ---
453
+
454
+ ## 🆕 **Modern Rule Implementation Guide (2025)**
455
+
456
+ Based on the successful C035 implementation, here's the **current recommended approach** for adding new rules:
457
+
458
+ ### **Critical Success Patterns**
459
+
460
+ #### **✅ 1. Constructor Pattern (REQUIRED)**
96
461
  ```javascript
97
- // Add to config/rules/rules-registry.json
462
+ // CORRECT - Works with semantic engine injection
463
+ class C042Analyzer {
464
+ constructor(options = {}) {
465
+ this.semanticEngine = options.semanticEngine || null;
466
+ this.verbose = options.verbose || false;
467
+ // ...
468
+ }
469
+ }
470
+
471
+ // ❌ WRONG - Causes semantic engine injection failure
472
+ class C042Analyzer {
473
+ constructor(semanticEngine = null) {
474
+ this.semanticEngine = semanticEngine;
475
+ // ...
476
+ }
477
+ }
478
+ ```
479
+
480
+ #### **✅ 2. Registry Configuration (REQUIRED)**
481
+
482
+ **Enhanced Rules Registry** (`config/rules/enhanced-rules-registry.json`):
483
+ ```json
98
484
  {
99
485
  "C042": {
100
- "id": "C042",
101
- "name": "New Rule Name",
102
- "category": "quality",
103
- "path": "./rules/quality/c042-new-rule",
104
- "analyzer": "analyzer.js",
105
- "config": "config.json"
486
+ "name": "No Hardcoded Configuration Values",
487
+ "description": "Avoid hardcoding configuration values in business logic",
488
+ "category": "maintainability",
489
+ "severity": "warning",
490
+ "languages": ["typescript", "javascript", "dart", "kotlin"],
491
+ "analyzer": "./rules/common/C042_no_hardcoded_config/analyzer.js",
492
+ "config": "./rules/common/C042_no_hardcoded_config/config.json",
493
+ "version": "1.0.0",
494
+ "status": "stable",
495
+ "tags": ["configuration", "hardcoding", "maintainability"],
496
+ "engineMappings": {
497
+ "eslint": ["no-magic-numbers", "@typescript-eslint/no-magic-numbers"]
498
+ }
499
+ }
500
+ }
501
+ ```
502
+
503
+ **Rule Analysis Strategies** (`config/rule-analysis-strategies.js`):
504
+ ```javascript
505
+ module.exports = {
506
+ hybridOptimal: {
507
+ 'C042': {
508
+ reason: 'Configuration detection requires symbol resolution + pattern matching',
509
+ methods: ['semantic', 'regex'],
510
+ strategy: 'semantic-primary-regex-fallback',
511
+ accuracy: { semantic: 90, regex: 75, combined: 95 }
512
+ }
106
513
  }
107
514
  }
108
515
  ```
109
516
 
110
- 5. **Add Tests**
517
+ #### **✅ 3. Hybrid Architecture Template**
518
+
519
+ **Main Analyzer** (`analyzer.js`):
111
520
  ```javascript
112
- // test/fixtures/c042/valid.ts
113
- // test/fixtures/c042/invalid.ts
114
- // test/unit/rules/c042.test.js
521
+ const C042SymbolBasedAnalyzer = require('./symbol-based-analyzer.js');
522
+ const C042RegexBasedAnalyzer = require('./regex-based-analyzer.js');
523
+
524
+ class C042Analyzer {
525
+ constructor(options = {}) {
526
+ if (process.env.SUNLINT_DEBUG) {
527
+ console.log(`🔧 [C042] Constructor called with options:`, !!options);
528
+ }
529
+
530
+ this.ruleId = 'C042';
531
+ this.semanticEngine = options.semanticEngine || null;
532
+ this.verbose = options.verbose || false;
533
+
534
+ // Initialize analyzers with THIS.semanticEngine
535
+ this.symbolAnalyzer = new C042SymbolBasedAnalyzer(this.semanticEngine);
536
+ this.regexAnalyzer = new C042RegexBasedAnalyzer(this.semanticEngine);
537
+
538
+ this.config = {
539
+ useSymbolBased: true,
540
+ fallbackToRegex: true,
541
+ symbolBasedOnly: false
542
+ };
543
+ }
544
+
545
+ async analyze(files, language = 'javascript', options = {}) {
546
+ const allViolations = [];
547
+
548
+ for (const filePath of files) {
549
+ const violations = await this.analyzeFile(filePath, options);
550
+ allViolations.push(...violations);
551
+ }
552
+
553
+ return allViolations;
554
+ }
555
+
556
+ async analyzeFile(filePath, options = {}) {
557
+ // 1. Try Symbol-based analysis first (primary)
558
+ if (this.config.useSymbolBased &&
559
+ this.semanticEngine?.project &&
560
+ this.semanticEngine?.initialized) {
561
+ try {
562
+ const sourceFile = this.semanticEngine.project.getSourceFile(filePath);
563
+ if (sourceFile) {
564
+ const violations = await this.symbolAnalyzer.analyzeFileWithSymbols(filePath, options);
565
+ violations.forEach(v => v.analysisStrategy = 'symbol-based');
566
+ return violations;
567
+ }
568
+ } catch (error) {
569
+ console.warn(`⚠️ [C042] Symbol analysis failed: ${error.message}`);
570
+ }
571
+ }
572
+
573
+ // 2. Fallback to regex-based analysis
574
+ if (this.config.fallbackToRegex) {
575
+ const violations = await this.regexAnalyzer.analyzeFileBasic(filePath, options);
576
+ violations.forEach(v => v.analysisStrategy = 'regex-based');
577
+ return violations;
578
+ }
579
+
580
+ return [];
581
+ }
582
+ }
583
+
584
+ module.exports = C042Analyzer;
585
+ ```
586
+
587
+ #### **✅ 4. Testing & Validation**
588
+
589
+ **Debug Output Verification**:
590
+ ```bash
591
+ SUNLINT_DEBUG=true node cli.js --input test-files/c042-test.js --rules C042 --engine=heuristic --debug
592
+ ```
593
+
594
+ **Expected Output**:
595
+ ```
596
+ 🔧 [HeuristicEngine] Rule C042: semantic (approach: hybrid-combined)
597
+ 🔧 [C042] Constructor called with options: true
598
+ 🔧 [C042] Options type: object [ 'verbose', 'semanticEngine' ]
599
+ 🔧 [C042] Trying symbol-based analysis...
600
+ ✅ [C042] Symbol-based analysis: X violations
601
+ ```
602
+
603
+ #### **✅ 5. Common Pitfalls & Solutions**
604
+
605
+ | ❌ Problem | ✅ Solution |
606
+ |------------|-------------|
607
+ | `constructor(semanticEngine)` | `constructor(options = {})` |
608
+ | Missing from `rule-analysis-strategies.js` | Add to `hybridOptimal` section |
609
+ | `ast (approach: ast-primary)` output | Ensure rule in strategies config |
610
+ | `this.semanticEngine?.project: false` | Check engine injection & initialization |
611
+ | No debug output from constructor | Verify constructor signature |
612
+
613
+ #### **✅ 6. Validation Checklist**
614
+
615
+ Before submitting a new rule:
616
+
617
+ - [ ] Constructor uses `options = {}` pattern
618
+ - [ ] Rule registered in `enhanced-rules-registry.json`
619
+ - [ ] Strategy defined in `rule-analysis-strategies.js` `hybridOptimal`
620
+ - [ ] Symbol-based analyzer implemented with ts-morph
621
+ - [ ] Regex-based analyzer implemented with pattern matching
622
+ - [ ] Debug output shows `semantic (approach: hybrid-combined)`
623
+ - [ ] Test cases detect expected violations accurately
624
+ - [ ] No modifications to engine core files (registry-driven only)
625
+ - [ ] Performance acceptable for large codebases
626
+
627
+ ---
628
+
629
+ ## 📚 **Legacy Implementation Examples**
630
+
631
+ The following examples show older patterns for reference, but **use the Modern Guide above** for new rules:
632
+
633
+ #### **Step 7: Document Analysis Strategy**
634
+
635
+ ```markdown
636
+ <!-- rules/common/C042_no_hardcoded_config/STRATEGY.md -->
637
+ # C042 Analysis Strategy: No Hardcoded Configuration Values
638
+
639
+ ## Overview
640
+ Hybrid approach using symbol-based analysis as primary with regex fallback.
641
+
642
+ ## Symbol-Based Analysis (Primary)
643
+ - Uses ts-morph AST to analyze variable declarations
644
+ - Detects configuration variable patterns by name
645
+ - Checks initializer values for hardcoded literals
646
+ - Excludes process.env and config function calls
647
+
648
+ ## Regex-Based Analysis (Fallback)
649
+ - Pattern matching for common hardcoded config scenarios
650
+ - Simpler but broader detection
651
+ - Used when symbol analysis unavailable
652
+
653
+ ## Strategy Selection
654
+ 1. **Symbol-based**: When ts-morph project available (95% accuracy)
655
+ 2. **Regex-fallback**: When symbol analysis fails (80% accuracy)
656
+
657
+ ## Testing Approach
658
+ Test both analyzers independently and verify hybrid orchestration.
659
+ ```
660
+
661
+ #### **Step 8: Register Rule in Rules Registry**
662
+
663
+ ```json
664
+ // config/rules/rules-registry.json
665
+ {
666
+ "rules": {
667
+ "C042": {
668
+ "name": "No Hardcoded Configuration Values",
669
+ "description": "Avoid hardcoding configuration values in business logic",
670
+ "category": "maintainability",
671
+ "severity": "warning",
672
+ "languages": ["typescript", "javascript"],
673
+ "analyzer": "./rules/common/C042_no_hardcoded_config/analyzer.js",
674
+ "config": "./rules/common/C042_no_hardcoded_config/config.json",
675
+ "version": "1.0.0",
676
+ "status": "experimental",
677
+ "tags": ["configuration", "maintainability", "environment"]
678
+ }
679
+ }
680
+ }
681
+ ```
682
+
683
+ #### **Step 9: Add to Enhanced Rules Registry**
684
+
685
+ ```javascript
686
+ // core/enhanced-rules-registry.js
687
+ loadEnginePreferences(options = {}) {
688
+ const preferences = {
689
+ // ... existing rules ...
690
+ 'C042': ['heuristic', 'openai'], // Symbol + regex hybrid
691
+ // ... rest of rules ...
692
+ };
693
+ }
694
+ ```
695
+
696
+ #### **Step 10: Add to Analysis Strategies**
697
+
698
+ ```javascript
699
+ // config/rule-analysis-strategies.js
700
+ module.exports = {
701
+ astPreferred: {
702
+ // ... existing rules ...
703
+ 'C042': {
704
+ reason: 'Configuration detection requires precise symbol analysis for variable declarations',
705
+ methods: ['ast', 'regex'],
706
+ accuracy: { ast: 95, regex: 80 }
707
+ }
708
+ }
709
+ };
710
+ ```
711
+
712
+ **Description**: Avoid hardcoding configuration values in business logic
713
+
714
+ **Examples**:
715
+ ❌ Bad:
716
+ ```javascript
717
+ const API_URL = "https://api.example.com";
718
+ const MAX_RETRIES = 5;
719
+ ```
720
+
721
+ ✅ Good:
722
+ ```javascript
723
+ const API_URL = process.env.API_URL;
724
+ const MAX_RETRIES = parseInt(process.env.MAX_RETRIES || '3');
725
+ ```
726
+
727
+ #### **Step 4: Add Tests**
728
+
729
+ ```javascript
730
+ // test/rules/c042.test.js
731
+ const { testRule } = require('../test-utils');
732
+
733
+ describe('Rule C042: No Hardcoded Configuration Values', () => {
734
+ testRule('C042', {
735
+ valid: [
736
+ 'const apiUrl = process.env.API_URL;',
737
+ 'const config = loadConfig();'
738
+ ],
739
+ invalid: [
740
+ 'const API_URL = "https://api.example.com";',
741
+ 'const MAX_RETRIES = 5;'
742
+ ]
743
+ });
744
+ });
745
+ ```
746
+
747
+ #### **Step 5: Test Your Rule**
748
+
749
+ ```bash
750
+ # Test with specific engine
751
+ node cli.js --rule=C042 --engine=eslint --input=test/fixtures
752
+ node cli.js --rule=C042 --engine=heuristic --input=test/fixtures
753
+
754
+ # Test rule behavior
755
+ node cli.js --rule=C042 --input=test/fixtures --verbose
756
+ ```
757
+
758
+ ### **Engine-Specific Development**
759
+
760
+ #### **Heuristic Engine Rules**
761
+
762
+ For custom pattern-based analysis:
763
+
764
+ 1. **Create Rule Class**:
765
+ ```javascript
766
+ // rules/custom/your-rule.js
767
+ const HeuristicRuleBase = require('../../core/heuristic-rule-base');
768
+
769
+ class YourCustomRule extends HeuristicRuleBase {
770
+ constructor() {
771
+ super('CXXX', 'Your Rule Name');
772
+ }
773
+
774
+ analyze(node, context) {
775
+ // Your analysis logic
776
+ // Return violation or null
777
+ }
778
+ }
779
+ ```
780
+
781
+ 2. **Add to Registry**:
782
+ ```json
783
+ {
784
+ "CXXX": {
785
+ "engineMappings": {
786
+ "heuristic": {
787
+ "implementation": "custom/your-rule",
788
+ "supportedLanguages": ["typescript", "javascript"]
789
+ }
790
+ }
791
+ }
792
+ }
793
+ ```
794
+
795
+ #### **ESLint Engine Rules**
796
+
797
+ For JavaScript/TypeScript linting:
798
+
799
+ 1. **Use Existing ESLint Rules**:
800
+ ```json
801
+ {
802
+ "CXXX": {
803
+ "engineMappings": {
804
+ "eslint": {
805
+ "rules": ["no-console", "prefer-const"],
806
+ "config": {
807
+ "no-console": ["error"],
808
+ "prefer-const": ["warn"]
809
+ }
810
+ }
811
+ }
812
+ }
813
+ }
814
+ ```
815
+
816
+ 2. **Create Custom ESLint Rule** (advanced):
817
+ ```javascript
818
+ // eslint-custom-rules/your-rule.js
819
+ module.exports = {
820
+ meta: {
821
+ type: 'problem',
822
+ docs: { description: 'Your rule description' }
823
+ },
824
+ create(context) {
825
+ return {
826
+ FunctionDeclaration(node) {
827
+ // Your ESLint rule logic
828
+ }
829
+ };
830
+ }
831
+ };
832
+ ```
833
+
834
+ #### **OpenAI Engine Rules**
835
+
836
+ For AI-powered analysis:
837
+
838
+ ```json
839
+ {
840
+ "CXXX": {
841
+ "engineMappings": {
842
+ "openai": {
843
+ "prompt": "Analyze code for specific pattern or anti-pattern",
844
+ "examples": [
845
+ "// Bad example",
846
+ "// Good example"
847
+ ],
848
+ "temperature": 0.1,
849
+ "maxTokens": 500
850
+ }
851
+ }
852
+ }
853
+ }
115
854
  ```
116
855
 
117
856
  ### **Adding a New Security Rule**
118
857
 
119
- Same process but in `rules/security/` directory with `security` category.
858
+ Same process as above, just use `"category": "security"` in the rule definition.
859
+
860
+ ### **Testing Your New Rule**
861
+
862
+ ```bash
863
+ # Test all engines with your new rule
864
+ node cli.js --rule=C042 --input=test/fixtures --format=json
865
+
866
+ # Test specific engine
867
+ node cli.js --rule=C042 --engine=heuristic --input=test/fixtures
868
+ node cli.js --rule=C042 --engine=eslint --input=test/fixtures
869
+ node cli.js --rule=C042 --engine=openai --input=test/fixtures
870
+
871
+ # Validate rule registry
872
+ node validate-system.js
873
+ ```
874
+
875
+ ### **Rule Definition Schema**
876
+
877
+ Complete schema for rule definitions:
878
+
879
+ ```json
880
+ {
881
+ "CXXX": {
882
+ "id": "CXXX", // Required: Rule ID
883
+ "title": "Rule Title", // Required: Human-readable title
884
+ "description": "Detailed description", // Required: Rule description
885
+ "severity": "error|warning|info", // Required: Severity level
886
+ "category": "quality|security|performance|maintainability", // Required
887
+ "tags": ["tag1", "tag2"], // Optional: Tags for filtering
888
+ "languages": ["typescript", "javascript"], // Optional: Supported languages
889
+ "engineMappings": { // Required: Engine configurations
890
+ "heuristic": {
891
+ "implementation": "custom/rule-name",
892
+ "supportedLanguages": ["typescript"],
893
+ "astTargets": ["FunctionDeclaration"]
894
+ },
895
+ "eslint": {
896
+ "rules": ["eslint-rule-name"],
897
+ "config": { "rule-option": true }
898
+ },
899
+ "openai": {
900
+ "prompt": "AI analysis prompt",
901
+ "examples": ["code example"],
902
+ "temperature": 0.1
903
+ }
904
+ },
905
+ "analysisStrategy": { // Optional: Analysis metadata
906
+ "type": "ast|regex|semantic",
907
+ "patterns": ["pattern1"],
908
+ "astTargets": ["NodeType"],
909
+ "heuristics": ["detection-method"]
910
+ },
911
+ "metadata": { // Optional: Additional metadata
912
+ "author": "Developer Name",
913
+ "created": "2025-08-07",
914
+ "updated": "2025-08-07",
915
+ "version": "1.0.0"
916
+ }
917
+ }
918
+ }
919
+ ```
920
+
921
+ ### **Architecture Deep Dive**
922
+
923
+ #### **Unified Rule Registry**
924
+ - **Location**: `rules/` (auto-generated from origin-rules)
925
+ - **Source**: `origin-rules/` (markdown files)
926
+ - **ESLint Mappings**: `config/eslint-rule-mapping.json`
927
+ - **Loader**: `core/unified-rule-registry.js`
928
+
929
+ #### **Engine Architecture**
930
+ ```
931
+ ┌─────────────────────────────────────────┐
932
+ │ SunLint CLI │
933
+ ├─────────────────────────────────────────┤
934
+ │ Analysis Orchestrator │
935
+ │ (Strict Engine Mode Support) │
936
+ ├─────────────────────────────────────────┤
937
+ │ ┌─────────────┬─────────────┬─────────┐ │
938
+ │ │ Heuristic │ ESLint │ OpenAI │ │
939
+ │ │ Engine │ Engine │ Engine │ │
940
+ │ │ (244 rules) │ (57 rules) │(256 all)│ │
941
+ │ └─────────────┴─────────────┴─────────┘ │
942
+ ├─────────────────────────────────────────┤
943
+ │ Rule Configuration │
944
+ │ ┌─────────────┬─────────────────────────┐ │
945
+ │ │ ESLint │ Unified Registry │ │
946
+ │ │ Mappings │ (Generated Rules) │ │
947
+ │ │ (.json) │ (origin-rules) │ │
948
+ │ └─────────────┴─────────────────────────┘ │
949
+ └─────────────────────────────────────────┘
950
+ ```
951
+
952
+ #### **How Engines Load Rules**
953
+ 1. **Initialization**: Each engine calls `getInstance()` from unified registry
954
+ 2. **Rule Loading**: Registry loads rules from auto-generated `rules/` directory
955
+ 3. **ESLint Mapping**: ESLint engine loads rule mappings from `config/eslint-rule-mapping.json`
956
+ 4. **Engine Filtering**: Each engine filters rules based on their capabilities
957
+ 5. **Analysis**: Engines analyze code using their specific rule implementations
958
+
959
+ **Key Features:**
960
+ - ✅ **Strict Engine Mode**: `--engine=eslint` only runs ESLint, skips unsupported rules
961
+ - ✅ **Fallback Mode**: Auto-engine selection with fallback (ESLint → Heuristic → OpenAI)
962
+ - ✅ **Rule Skipping**: Graceful handling of unsupported rules by specific engines
120
963
 
121
964
  ## 🧪 **Testing**
122
965
 
@@ -125,25 +968,50 @@ Same process but in `rules/security/` directory with `security` category.
125
968
  npm test
126
969
  ```
127
970
 
128
- ### **Run Specific Tests**
971
+ ### **Test Rule Registry System**
129
972
  ```bash
130
- # Test specific rule
131
- npm run test:c019
973
+ # Validate unified rule registry
974
+ node validate-system.js
975
+
976
+ # Check rule loading for each engine
977
+ npm run test:engines
978
+ ```
132
979
 
133
- # Test multiple rules
134
- npm run test:multi
980
+ ### **Test Specific Rules**
981
+ ```bash
982
+ # Test specific rule with all engines
983
+ node cli.js --rule=C042 --input=test/fixtures
135
984
 
136
- # Test all quality rules
137
- npm run test:quality
985
+ # Test with specific engine
986
+ node cli.js --rule=C042 --engine=heuristic --input=test/fixtures
987
+ node cli.js --rule=C042 --engine=eslint --input=test/fixtures
988
+ node cli.js --rule=C042 --engine=openai --input=test/fixtures
138
989
 
139
- # Test all security rules
140
- npm run test:security
990
+ # Test multiple rules
991
+ node cli.js --rule=C006,C019,C042 --input=test/fixtures
141
992
  ```
142
993
 
143
- ### **Test Your Changes**
994
+ ### **Test Rule Development**
144
995
  ```bash
145
- # Test your new rule
146
- node cli.js --rule=C042 --input=test/fixtures --format=eslint
996
+ # Create test fixtures
997
+ mkdir -p test/fixtures/c042
998
+ echo 'const API_URL = "https://api.example.com";' > test/fixtures/c042/invalid.ts
999
+ echo 'const apiUrl = process.env.API_URL;' > test/fixtures/c042/valid.ts
1000
+
1001
+ # Test your rule
1002
+ node cli.js --rule=C042 --input=test/fixtures/c042 --format=json
1003
+ ```
1004
+
1005
+ ### **Integration Testing**
1006
+ ```bash
1007
+ # Test all engines work together
1008
+ npm run test:integration
1009
+
1010
+ # Test rule registry loading
1011
+ npm run test:registry
1012
+
1013
+ # Performance testing
1014
+ npm run test:performance
147
1015
  ```
148
1016
 
149
1017
  ## 📊 **Code Review Process**
@@ -158,13 +1026,16 @@ node cli.js --rule=C042 --input=test/fixtures --format=eslint
158
1026
 
159
1027
  2. **Submit Pull Request**
160
1028
  - Clear title and description
161
- - Reference related issues
1029
+ - Reference related issues
162
1030
  - Include test results
163
1031
  - Follow template
1032
+ - **NEW**: Validate rule registry with `node validate-system.js`
164
1033
 
165
1034
  3. **Review Criteria**
166
1035
  - Code quality (follows our own rules!)
167
- - Test coverage
1036
+ - Rule properly defined in `enhanced-rules-registry.json`
1037
+ - All engines can load the rule correctly
1038
+ - Test coverage for all supported engines
168
1039
  - Documentation completeness
169
1040
  - Performance impact
170
1041
  - Backward compatibility
@@ -174,32 +1045,88 @@ node cli.js --rule=C042 --input=test/fixtures --format=eslint
174
1045
  ### **Update Documentation**
175
1046
  When adding features:
176
1047
  - Update `README.md`
177
- - Add rule documentation
1048
+ - Add rule to `enhanced-rules-registry.json` (this is your main documentation!)
178
1049
  - Update configuration examples
179
1050
  - Add usage examples
1051
+ - Update `RULE_MIGRATION_SUMMARY.md` if changing rule system
180
1052
 
181
1053
  ### **Rule Documentation Template**
182
- ```markdown
183
- ## Rule C042: New Rule Name
184
1054
 
185
- **Category**: Quality
186
- **Severity**: Error
187
- **Languages**: TypeScript, Dart, Kotlin
1055
+ All rule documentation is now centralized in `enhanced-rules-registry.json`:
188
1056
 
189
- ### Description
190
- Following Rule C015 (domain language), use clear business terms...
1057
+ ```json
1058
+ {
1059
+ "C042": {
1060
+ "title": "Clear, descriptive rule title",
1061
+ "description": "Detailed explanation of what the rule checks, why it matters, and how to fix violations. Follow Rule C015 (domain language) - use clear business terms.",
1062
+ "examples": {
1063
+ "invalid": [
1064
+ "// Bad example that violates the rule",
1065
+ "const API_URL = 'https://hardcoded-url.com';"
1066
+ ],
1067
+ "valid": [
1068
+ "// Good example that follows the rule",
1069
+ "const apiUrl = process.env.API_URL;"
1070
+ ]
1071
+ },
1072
+ "fixSuggestions": [
1073
+ "Move configuration to environment variables",
1074
+ "Use a configuration management system",
1075
+ "Extract constants to a separate config file"
1076
+ ],
1077
+ "relatedRules": ["C031", "C034"]
1078
+ }
1079
+ }
1080
+ ```
191
1081
 
192
- ### Examples
1082
+ ### **Engine-Specific Documentation**
193
1083
 
194
- **❌ Bad:**
195
- ```typescript
196
- // Code that violates the rule
1084
+ #### **Heuristic Engine Rules**
1085
+ Document custom analysis patterns:
1086
+ ```json
1087
+ {
1088
+ "analysisStrategy": {
1089
+ "type": "ast",
1090
+ "description": "Analyzes AST nodes for hardcoded configuration patterns",
1091
+ "astTargets": ["VariableDeclaration", "PropertyAssignment"],
1092
+ "patterns": ["literal-values-in-config-context"],
1093
+ "complexity": "O(n) where n is number of variable declarations"
1094
+ }
1095
+ }
197
1096
  ```
198
1097
 
199
- **✅ Good:**
200
- ```typescript
201
- // Code that follows the rule
1098
+ #### **ESLint Engine Rules**
1099
+ Document ESLint rule mappings:
1100
+ ```json
1101
+ {
1102
+ "engineMappings": {
1103
+ "eslint": {
1104
+ "rules": ["no-magic-numbers"],
1105
+ "rationale": "ESLint's no-magic-numbers rule catches hardcoded values",
1106
+ "limitations": "May have false positives for legitimate constants",
1107
+ "customConfig": {
1108
+ "no-magic-numbers": ["error", { "ignore": [0, 1, -1] }]
1109
+ }
1110
+ }
1111
+ }
1112
+ }
202
1113
  ```
1114
+
1115
+ #### **OpenAI Engine Rules**
1116
+ Document AI prompts and examples:
1117
+ ```json
1118
+ {
1119
+ "engineMappings": {
1120
+ "openai": {
1121
+ "prompt": "Identify hardcoded configuration values that should be externalized to environment variables or config files",
1122
+ "context": "Look for URLs, timeouts, limits, and other configuration that might change between environments",
1123
+ "examples": [
1124
+ "❌ const API_URL = 'https://api.example.com';",
1125
+ "✅ const API_URL = process.env.API_URL || 'https://default-api.com';"
1126
+ ]
1127
+ }
1128
+ }
1129
+ }
203
1130
  ```
204
1131
 
205
1132
  ## 🐛 **Bug Reports**
@@ -210,6 +1137,49 @@ When reporting bugs:
210
1137
  3. Provide sample code
211
1138
  4. Include environment details
212
1139
  5. Include sunlint output
1140
+ 6. **NEW**: Run `node validate-system.js` and include output
1141
+
1142
+ ## 🔧 **Troubleshooting**
1143
+
1144
+ ### **Common Issues**
1145
+
1146
+ #### **Rule Not Loading**
1147
+ ```bash
1148
+ # Check if rule exists in registry
1149
+ node -e "const registry = require('./core/unified-rule-registry'); registry.getInstance().initialize().then(() => console.log('Rule C042:', registry.getInstance().rules.has('C042')))"
1150
+
1151
+ # Validate registry syntax
1152
+ node validate-system.js
1153
+ ```
1154
+
1155
+ #### **Engine Not Finding Rule**
1156
+ ```bash
1157
+ # Check engine-specific mapping
1158
+ node -e "const registry = require('./core/unified-rule-registry'); registry.getInstance().initialize().then(r => { const rule = r.rules.get('C042'); console.log('ESLint mapping:', rule?.engineMappings?.eslint); })"
1159
+ ```
1160
+
1161
+ #### **Rule Registry Errors**
1162
+ ```bash
1163
+ # Common issues:
1164
+ # 1. JSON syntax errors in enhanced-rules-registry.json
1165
+ # 2. Missing required fields (id, title, description, severity, category)
1166
+ # 3. Invalid engine mapping structure
1167
+
1168
+ # Validate JSON syntax
1169
+ node -c config/enhanced-rules-registry.json
1170
+
1171
+ # Check required fields
1172
+ node validate-system.js
1173
+ ```
1174
+
1175
+ ### **Performance Issues**
1176
+ ```bash
1177
+ # Profile rule loading
1178
+ node --prof cli.js --rule=C042 --input=large-project/
1179
+
1180
+ # Check memory usage
1181
+ node --inspect cli.js --rule=C042 --input=test/fixtures/
1182
+ ```
213
1183
 
214
1184
  ## 💡 **Feature Requests**
215
1185
 
@@ -220,6 +1190,624 @@ For new features:
220
1190
  4. Consider implementation complexity
221
1191
  5. Think about backward compatibility
222
1192
 
1193
+ ## 📋 **Quick Reference**
1194
+
1195
+ ### **Essential Commands**
1196
+ ```bash
1197
+ # Add ESLint engine rule mapping
1198
+ vim config/eslint-rule-mapping.json
1199
+
1200
+ # Create custom heuristic rule
1201
+ vim custom-rules/c042-rule-name.js
1202
+
1203
+ # Add rule documentation
1204
+ vim origin-rules/common-en.md
1205
+
1206
+ # Test new rule with specific engine
1207
+ node cli.js --rule=CXXX --engine=eslint --input=test/fixtures
1208
+ node cli.js --rule=CXXX --engine=heuristic --input=test/fixtures
1209
+
1210
+ # Test strict engine mode (no fallback)
1211
+ node cli.js --rule=CXXX --engine=eslint --input=test/fixtures
1212
+
1213
+ # Test fallback mode (auto engine selection)
1214
+ node cli.js --rule=CXXX --input=test/fixtures
1215
+ ```
1216
+
1217
+ ### **Key Files**
1218
+ - `config/eslint-rule-mapping.json` - **ESLint engine rule mappings**
1219
+ - `origin-rules/` - **Original rule definitions** (markdown format)
1220
+ - `rules/` - **Generated rule registry** (auto-generated)
1221
+ - `core/unified-rule-registry.js` - Rule registry loader
1222
+ - `engines/heuristic-engine.js` - Custom pattern analysis
1223
+ - `engines/eslint-engine.js` - JavaScript/TypeScript linting
1224
+ - `engines/openai-engine.js` - AI-powered analysis
1225
+ - `integrations/eslint/plugin/` - Custom ESLint rules
1226
+ - `custom-rules/` - Heuristic engine custom rules
1227
+
1228
+ ### **Rule Development Checklist**
1229
+ - [ ] Choose appropriate engine (ESLint for JS/TS, Heuristic for universal)
1230
+ - [ ] Add ESLint mapping to `config/eslint-rule-mapping.json` (if using ESLint engine)
1231
+ - [ ] Create custom rule implementation (if needed)
1232
+ - [ ] Add rule definition to `origin-rules/` (markdown format)
1233
+ - [ ] Add test cases and examples
1234
+ - [ ] Test with `node cli.js --rule=CXXX --input=test/fixtures`
1235
+ - [ ] Test engine-specific behavior (`--engine=eslint`, `--engine=heuristic`)
1236
+ - [ ] Update documentation if needed
1237
+
1238
+ ---
1239
+
1240
+ **🚀 Ready to contribute? Start by choosing your engine and editing the appropriate mapping file!**
1241
+
1242
+ **For ESLint rules**: Edit `config/eslint-rule-mapping.json`
1243
+ **For Heuristic rules**: Create files in `custom-rules/`
1244
+ **For documentation**: Add to `origin-rules/` markdown files
1245
+
1246
+ ---
1247
+
1248
+ ## 🔬 **Modern Rule Development Guide (2024)**
1249
+
1250
+ *This section provides a comprehensive, step-by-step guide for implementing new rules using the modern hybrid architecture pattern (symbol-based + regex fallback), based on the successful C035 implementation.*
1251
+
1252
+ ### **Quick Start: Creating a New Rule**
1253
+
1254
+ #### **Step 1: Create Rule Directory Structure**
1255
+
1256
+ ```bash
1257
+ # Example: Creating C042 (No Hardcoded Configuration Values)
1258
+ mkdir -p rules/common/C042_no_hardcoded_config
1259
+ cd rules/common/C042_no_hardcoded_config
1260
+ ```
1261
+
1262
+ #### **Step 2: Implement Main Analyzer (Hybrid Orchestrator)**
1263
+
1264
+ ```javascript
1265
+ // analyzer.js - Main hybrid orchestrator
1266
+ const SymbolBasedAnalyzer = require('./symbol-based-analyzer');
1267
+ const RegexBasedAnalyzer = require('./regex-based-analyzer');
1268
+
1269
+ class C042NoHardcodedConfigAnalyzer {
1270
+ constructor(verbose = false) {
1271
+ this.verbose = verbose;
1272
+ this.symbolAnalyzer = new SymbolBasedAnalyzer(verbose);
1273
+ this.regexAnalyzer = new RegexBasedAnalyzer(verbose);
1274
+ }
1275
+
1276
+ async analyzeFileBasic(filePath, options = {}) {
1277
+ if (this.verbose) {
1278
+ console.log(`🔍 [C042] Analyzing file: ${filePath}`);
1279
+ }
1280
+
1281
+ try {
1282
+ // Primary: Symbol-based analysis
1283
+ const violations = await this.symbolAnalyzer.analyzeFileBasic(filePath, options);
1284
+
1285
+ if (this.verbose) {
1286
+ console.log(`✅ [C042] Symbol-based analysis completed. Found ${violations.length} violations.`);
1287
+ }
1288
+
1289
+ return violations;
1290
+ } catch (error) {
1291
+ if (this.verbose) {
1292
+ console.warn(`⚠️ [C042] Symbol analysis failed: ${error.message}`);
1293
+ console.log(`🔄 [C042] Falling back to regex analysis...`);
1294
+ }
1295
+
1296
+ // Fallback: Regex-based analysis
1297
+ try {
1298
+ const violations = await this.regexAnalyzer.analyzeFileBasic(filePath, options);
1299
+
1300
+ if (this.verbose) {
1301
+ console.log(`✅ [C042] Regex-fallback analysis completed. Found ${violations.length} violations.`);
1302
+ }
1303
+
1304
+ return violations;
1305
+ } catch (fallbackError) {
1306
+ if (this.verbose) {
1307
+ console.error(`❌ [C042] Both symbol and regex analysis failed: ${fallbackError.message}`);
1308
+ }
1309
+ return [];
1310
+ }
1311
+ }
1312
+ }
1313
+ }
1314
+
1315
+ module.exports = C042NoHardcodedConfigAnalyzer;
1316
+ ```
1317
+
1318
+ #### **Step 3: Implement Symbol-Based Analyzer (Primary)**
1319
+
1320
+ ```javascript
1321
+ // symbol-based-analyzer.js - High-accuracy AST analysis
1322
+ const { Project } = require('ts-morph');
1323
+
1324
+ class C042SymbolBasedAnalyzer {
1325
+ constructor(verbose = false) {
1326
+ this.verbose = verbose;
1327
+ this.project = new Project({
1328
+ useInMemoryFileSystem: true,
1329
+ compilerOptions: {
1330
+ allowJs: true,
1331
+ checkJs: false,
1332
+ },
1333
+ });
1334
+ }
1335
+
1336
+ async analyzeFileBasic(filePath, options = {}) {
1337
+ const violations = [];
1338
+
1339
+ try {
1340
+ const sourceFile = this.project.addSourceFileAtPath(filePath);
1341
+
1342
+ // Analyze variable declarations
1343
+ sourceFile.getVariableDeclarations().forEach(declaration => {
1344
+ const initializer = declaration.getInitializer();
1345
+ if (initializer && this.isHardcodedConfig(initializer, declaration.getName())) {
1346
+ violations.push({
1347
+ line: declaration.getStartLineNumber(),
1348
+ column: declaration.getStart() - declaration.getStartLinePos() + 1,
1349
+ message: `Hardcoded configuration value detected in variable '${declaration.getName()}'`,
1350
+ severity: 'warning',
1351
+ rule: 'C042'
1352
+ });
1353
+ }
1354
+ });
1355
+
1356
+ // Analyze property assignments
1357
+ sourceFile.getDescendantsOfKind(ts.SyntaxKind.PropertyAssignment).forEach(prop => {
1358
+ const value = prop.getInitializer();
1359
+ if (value && this.isHardcodedConfig(value, prop.getName())) {
1360
+ violations.push({
1361
+ line: prop.getStartLineNumber(),
1362
+ column: prop.getStart() - prop.getStartLinePos() + 1,
1363
+ message: `Hardcoded configuration value in property '${prop.getName()}'`,
1364
+ severity: 'warning',
1365
+ rule: 'C042'
1366
+ });
1367
+ }
1368
+ });
1369
+
1370
+ this.project.removeSourceFile(sourceFile);
1371
+ return violations;
1372
+ } catch (error) {
1373
+ throw new Error(`Symbol analysis failed: ${error.message}`);
1374
+ }
1375
+ }
1376
+
1377
+ isHardcodedConfig(node, name) {
1378
+ // Check if the value looks like configuration
1379
+ const configPatterns = [
1380
+ /url/i, /host/i, /port/i, /timeout/i, /secret/i,
1381
+ /api[_-]?key/i, /password/i, /connection/i, /endpoint/i
1382
+ ];
1383
+
1384
+ const nameMatches = configPatterns.some(pattern => pattern.test(name));
1385
+
1386
+ if (!nameMatches) return false;
1387
+
1388
+ // Check if value is hardcoded (string/number literal)
1389
+ return node.getKind() === ts.SyntaxKind.StringLiteral ||
1390
+ node.getKind() === ts.SyntaxKind.NumericLiteral;
1391
+ }
1392
+ }
1393
+
1394
+ module.exports = C042SymbolBasedAnalyzer;
1395
+ ```
1396
+
1397
+ #### **Step 4: Implement Regex-Based Analyzer (Fallback)**
1398
+
1399
+ ```javascript
1400
+ // regex-based-analyzer.js - Broad coverage pattern matching
1401
+ const fs = require('fs');
1402
+
1403
+ class C042RegexBasedAnalyzer {
1404
+ constructor(verbose = false) {
1405
+ this.verbose = verbose;
1406
+
1407
+ // Configuration-related patterns
1408
+ this.configPatterns = [
1409
+ /(?:const|let|var)\s+(\w*(?:url|host|port|timeout|secret|key|password|connection|endpoint)\w*)\s*=\s*['"`]([^'"`]+)['"`]/gi,
1410
+ /(\w*(?:url|host|port|timeout|secret|key|password|connection|endpoint)\w*)\s*:\s*['"`]([^'"`]+)['"`]/gi,
1411
+ /(\w*(?:url|host|port|timeout|secret|key|password|connection|endpoint)\w*)\s*=\s*(\d+)/gi
1412
+ ];
1413
+ }
1414
+
1415
+ async analyzeFileBasic(filePath, options = {}) {
1416
+ const violations = [];
1417
+
1418
+ try {
1419
+ const content = fs.readFileSync(filePath, 'utf8');
1420
+ const lines = content.split('\n');
1421
+
1422
+ this.configPatterns.forEach(pattern => {
1423
+ lines.forEach((line, index) => {
1424
+ let match;
1425
+ while ((match = pattern.exec(line)) !== null) {
1426
+ const variableName = match[1];
1427
+ const value = match[2];
1428
+
1429
+ if (this.isLikelyHardcodedConfig(variableName, value)) {
1430
+ violations.push({
1431
+ line: index + 1,
1432
+ column: match.index + 1,
1433
+ message: `Potential hardcoded configuration: '${variableName}' = '${value}'`,
1434
+ severity: 'warning',
1435
+ rule: 'C042'
1436
+ });
1437
+ }
1438
+ }
1439
+ pattern.lastIndex = 0; // Reset regex
1440
+ });
1441
+ });
1442
+
1443
+ return violations;
1444
+ } catch (error) {
1445
+ throw new Error(`Regex analysis failed: ${error.message}`);
1446
+ }
1447
+ }
1448
+
1449
+ isLikelyHardcodedConfig(name, value) {
1450
+ // Skip obvious non-config values
1451
+ const skipPatterns = [
1452
+ /^(true|false|null|undefined)$/i,
1453
+ /^process\.env\./i,
1454
+ /^require\(/i,
1455
+ /^\w+\(/i // Function calls
1456
+ ];
1457
+
1458
+ return !skipPatterns.some(pattern => pattern.test(value));
1459
+ }
1460
+ }
1461
+
1462
+ module.exports = C042RegexBasedAnalyzer;
1463
+ ```
1464
+
1465
+ #### **Step 5: Create Rule Configuration**
1466
+
1467
+ ```json
1468
+ // config.json - Rule metadata and examples
1469
+ {
1470
+ "id": "C042",
1471
+ "name": "No Hardcoded Configuration Values",
1472
+ "category": "Maintainability",
1473
+ "severity": "warning",
1474
+ "description": "Detects hardcoded configuration values that should use environment variables or config files",
1475
+ "rationale": "Hardcoded configuration makes applications less flexible and harder to deploy across different environments",
1476
+ "examples": {
1477
+ "bad": [
1478
+ "const API_URL = 'https://api.example.com';",
1479
+ "const DB_HOST = 'localhost';",
1480
+ "const MAX_CONNECTIONS = 100;",
1481
+ "config: { port: 3000, host: 'localhost' }"
1482
+ ],
1483
+ "good": [
1484
+ "const API_URL = process.env.API_URL;",
1485
+ "const DB_HOST = process.env.DB_HOST || 'localhost';",
1486
+ "const config = loadConfigFromFile();",
1487
+ "const PORT = parseInt(process.env.PORT || '3000');"
1488
+ ]
1489
+ },
1490
+ "tags": ["configuration", "deployment", "security", "maintainability"],
1491
+ "accuracy": {
1492
+ "symbol_based": "high",
1493
+ "regex_based": "medium"
1494
+ },
1495
+ "performance": {
1496
+ "symbol_based": "medium",
1497
+ "regex_based": "fast"
1498
+ }
1499
+ }
1500
+ ```
1501
+
1502
+ #### **Step 6: Document Analysis Strategy**
1503
+
1504
+ ```markdown
1505
+ <!-- STRATEGY.md - Analysis approach documentation -->
1506
+ # C042: No Hardcoded Configuration Values - Analysis Strategy
1507
+
1508
+ ## Overview
1509
+ This rule detects hardcoded configuration values using a hybrid approach combining symbol-based AST analysis with regex-based pattern matching.
1510
+
1511
+ ## Analysis Approaches
1512
+
1513
+ ### Symbol-Based Analysis (Primary)
1514
+ - **Tool**: ts-morph AST parser
1515
+ - **Accuracy**: High (95%+)
1516
+ - **Coverage**: Variable declarations, property assignments
1517
+ - **Strengths**:
1518
+ - Understands code context
1519
+ - Low false positives
1520
+ - Handles complex expressions
1521
+ - **Limitations**:
1522
+ - Requires valid syntax
1523
+ - Slower performance
1524
+
1525
+ ### Regex-Based Analysis (Fallback)
1526
+ - **Tool**: Regular expressions
1527
+ - **Accuracy**: Medium (80%+)
1528
+ - **Coverage**: String/number patterns in config-like names
1529
+ - **Strengths**:
1530
+ - Fast execution
1531
+ - Works with any file
1532
+ - Broad pattern coverage
1533
+ - **Limitations**:
1534
+ - Higher false positives
1535
+ - Limited context understanding
1536
+
1537
+ ## Detection Patterns
1538
+
1539
+ ### Configuration Indicators
1540
+ - Variable/property names containing: url, host, port, timeout, secret, key, password, connection, endpoint
1541
+ - Literal string/number values
1542
+ - Assignment patterns
1543
+
1544
+ ### Exclusions
1545
+ - Environment variable references (process.env.*)
1546
+ - Function calls
1547
+ - Boolean/null literals
1548
+ - Computed values
1549
+
1550
+ ## Testing Strategy
1551
+ - Unit tests for each analyzer
1552
+ - Integration tests for hybrid orchestration
1553
+ - Real-world project validation
1554
+ - Performance benchmarking
1555
+ ```
1556
+
1557
+ #### **Step 7: Add to Rules Registry**
1558
+
1559
+ ```json
1560
+ // config/rules/rules-registry.json - Add rule definition
1561
+ {
1562
+ "C042": {
1563
+ "id": "C042",
1564
+ "name": "No Hardcoded Configuration Values",
1565
+ "category": "Maintainability",
1566
+ "severity": "warning",
1567
+ "description": "Detects hardcoded configuration values that should use environment variables or config files",
1568
+ "engine": "heuristic",
1569
+ "analyzerPath": "rules/common/C042_no_hardcoded_config/analyzer.js",
1570
+ "configPath": "rules/common/C042_no_hardcoded_config/config.json",
1571
+ "enabled": true,
1572
+ "languages": ["javascript", "typescript"],
1573
+ "tags": ["configuration", "deployment", "security"]
1574
+ }
1575
+ }
1576
+ ```
1577
+
1578
+ #### **Step 8: Register with Enhanced Rules Registry**
1579
+
1580
+ ```javascript
1581
+ // core/enhanced-rules-registry.js - Add engine preferences
1582
+ const enginePreferences = {
1583
+ // ... existing rules
1584
+ 'C042': ['heuristic'], // Add your rule here
1585
+ };
1586
+ ```
1587
+
1588
+ #### **Step 9: Add to Analysis Strategies**
1589
+
1590
+ ```javascript
1591
+ // config/rule-analysis-strategies.js - Add to AST preferred rules
1592
+ const strategies = {
1593
+ astPreferred: [
1594
+ // ... existing rules
1595
+ 'C042', // Add your rule here
1596
+ ],
1597
+ regexOnly: [
1598
+ // Rules that only use regex
1599
+ ],
1600
+ hybridOnly: [
1601
+ // Rules requiring both approaches
1602
+ ]
1603
+ };
1604
+ ```
1605
+
1606
+ #### **Step 10: Create Test Script for Direct Testing**
1607
+
1608
+ ```javascript
1609
+ // test-c042-direct.js - Direct analyzer testing
1610
+ const C042Analyzer = require('./rules/common/C042_no_hardcoded_config/analyzer');
1611
+
1612
+ async function testC042() {
1613
+ const analyzer = new C042Analyzer(true); // Enable verbose mode
1614
+
1615
+ try {
1616
+ const violations = await analyzer.analyzeFileBasic('test-files/c042-test.js');
1617
+ console.log(`\n📊 C042 Analysis Results:`);
1618
+ console.log(` Found ${violations.length} violations`);
1619
+
1620
+ violations.forEach((violation, index) => {
1621
+ console.log(` ${index + 1}. Line ${violation.line}: ${violation.message}`);
1622
+ });
1623
+ } catch (error) {
1624
+ console.error('❌ C042 test failed:', error.message);
1625
+ }
1626
+ }
1627
+
1628
+ testC042();
1629
+ ```
1630
+
1631
+ #### **Step 11: Create Test File**
1632
+
1633
+ ```javascript
1634
+ // test-files/c042-test.js
1635
+ /**
1636
+ * Test file for C042 No Hardcoded Configuration Values rule
1637
+ * Contains various configuration patterns to validate analyzer
1638
+ */
1639
+
1640
+ // Good Examples: Using environment variables
1641
+ const API_URL = process.env.API_URL;
1642
+ const MAX_RETRIES = parseInt(process.env.MAX_RETRIES || '3');
1643
+ const config = loadConfigFromFile();
1644
+
1645
+ // Bad Examples: Hardcoded values (should trigger violations)
1646
+ const DATABASE_URL = 'mongodb://localhost:27017/myapp';
1647
+ const API_SECRET = 'sk-1234567890abcdef';
1648
+ const MAX_CONNECTIONS = 100;
1649
+ const TIMEOUT_MS = 5000;
1650
+
1651
+ // Edge Cases
1652
+ const DEBUG_MODE = true; // Should not trigger (not config pattern)
1653
+ const DEFAULT_CONFIG = { // Should trigger for nested hardcoded values
1654
+ port: 3000,
1655
+ host: 'localhost'
1656
+ };
1657
+
1658
+ module.exports = {
1659
+ goodConfig,
1660
+ badConfig
1661
+ };
1662
+ ```
1663
+
1664
+ #### **Step 12: Test Your Rule**
1665
+
1666
+ ```bash
1667
+ # Test the new rule
1668
+ node cli.js --rule=C042 --input=test-files/c042-test.js --verbose --engine=heuristic
1669
+
1670
+ # Expected output: Should detect 4-5 violations for hardcoded config values
1671
+
1672
+ # Test rule in real projects
1673
+ node cli.js --rule=C042 --input=src --engine=heuristic
1674
+
1675
+ # Test with different engines
1676
+ node cli.js --rule=C042 --input=test-files/c042-test.js --engine=openai
1677
+ ```
1678
+
1679
+ #### **Step 13: Validate Integration**
1680
+
1681
+ ```bash
1682
+ # Check rule is loaded
1683
+ node cli.js --rule=C042 --input=test-files/c042-test.js --verbose | grep "Loaded.*rule: C042"
1684
+
1685
+ # Verify both analyzers work
1686
+ node cli.js --rule=C042 --input=test-files/c042-test.js --verbose | grep -E "(Symbol-based|Regex-fallback)"
1687
+
1688
+ # Check for violations
1689
+ node cli.js --rule=C042 --input=test-files/c042-test.js --format=json | jq '.results[].violations | length'
1690
+ ```
1691
+
1692
+ ### **Modern Rule Development Best Practices**
1693
+
1694
+ #### **Architecture Patterns**
1695
+
1696
+ 1. **Hybrid Symbol + Regex Approach** (Recommended)
1697
+ - Primary: Symbol-based analysis (high accuracy)
1698
+ - Fallback: Regex-based analysis (broad coverage)
1699
+ - Example: C035, C033
1700
+
1701
+ 2. **Symbol-Only Approach**
1702
+ - For complex AST analysis requiring deep context
1703
+ - Higher accuracy but limited fallback
1704
+ - Example: Advanced OOP rules
1705
+
1706
+ 3. **Regex-Only Approach**
1707
+ - For simple pattern matching
1708
+ - Fast but lower accuracy
1709
+ - Example: Basic naming conventions
1710
+
1711
+ #### **Code Quality Standards for Rules**
1712
+
1713
+ - **Rule C005**: Each analyzer should have single responsibility
1714
+ - **Rule C006**: Method names should be verb-noun (e.g., `analyzeVariableDeclaration`)
1715
+ - **Rule C031**: Keep validation logic separate from detection logic
1716
+ - **Rule C035**: Log detailed information for debugging (verbose mode)
1717
+
1718
+ #### **File Structure Standards**
1719
+
1720
+ ```
1721
+ rules/common/C042_rule_name/
1722
+ ├── analyzer.js # Main hybrid orchestrator
1723
+ ├── symbol-based-analyzer.js # Primary AST analysis
1724
+ ├── regex-based-analyzer.js # Fallback pattern matching
1725
+ ├── config.json # Rule configuration
1726
+ ├── STRATEGY.md # Analysis approach documentation
1727
+ └── README.md # Rule documentation (optional)
1728
+ ```
1729
+
1730
+ #### **Error Handling Standards**
1731
+
1732
+ ```javascript
1733
+ // Always include proper error handling
1734
+ try {
1735
+ const violations = await this.symbolAnalyzer.analyzeFileBasic(filePath, options);
1736
+ return violations;
1737
+ } catch (error) {
1738
+ if (this.verbose) {
1739
+ console.warn(`⚠️ [C042] Symbol analysis failed: ${error.message}`);
1740
+ }
1741
+ // Graceful fallback to regex analysis
1742
+ }
1743
+ ```
1744
+
1745
+ #### **Testing Standards**
1746
+
1747
+ 1. **Unit Tests**: Test each analyzer independently
1748
+ 2. **Integration Tests**: Test hybrid orchestration
1749
+ 3. **Real Project Tests**: Validate on actual codebases
1750
+ 4. **Performance Tests**: Ensure reasonable execution time
1751
+
1752
+ #### **Documentation Standards**
1753
+
1754
+ - **STRATEGY.md**: Document analysis approach and accuracy
1755
+ - **config.json**: Include examples of good/bad patterns
1756
+ - **CONTRIBUTING.md**: Update with new patterns learned
1757
+ - **Inline comments**: Explain complex detection logic
1758
+
1759
+ ### **Rule Development Checklist**
1760
+
1761
+ - [ ] Created rule directory structure
1762
+ - [ ] Implemented main analyzer (hybrid orchestrator)
1763
+ - [ ] Implemented symbol-based analyzer (primary)
1764
+ - [ ] Implemented regex-based analyzer (fallback)
1765
+ - [ ] Created rule configuration (config.json)
1766
+ - [ ] Documented analysis strategy (STRATEGY.md)
1767
+ - [ ] Added to rules registry
1768
+ - [ ] Added to enhanced rules registry
1769
+ - [ ] Added to analysis strategies
1770
+ - [ ] Created test file
1771
+ - [ ] Tested rule individually
1772
+ - [ ] Tested rule integration
1773
+ - [ ] Validated on real projects
1774
+ - [ ] Updated documentation
1775
+
1776
+ ### **Common Issues and Solutions**
1777
+
1778
+ #### **Issue: Rule not loaded**
1779
+ ```bash
1780
+ # Check if rule exists in registry
1781
+ node cli.js --rule=C042 --input=test-files --verbose | grep "No compatible analyzer found for C042"
1782
+
1783
+ # Solution: Add rule to config/rules/rules-registry.json
1784
+ ```
1785
+
1786
+ #### **Issue: Symbol analysis fails**
1787
+ ```bash
1788
+ # Check semantic engine availability
1789
+ node cli.js --rule=C042 --input=test-files --verbose | grep "Symbol analysis failed"
1790
+
1791
+ # Solution: Ensure proper error handling and regex fallback
1792
+ ```
1793
+
1794
+ #### **Issue: No violations detected**
1795
+ ```bash
1796
+ # Test analyzers independently
1797
+ node test-c042-direct.js
1798
+
1799
+ # Check file patterns match expectations
1800
+ ```
1801
+
1802
+ #### **Issue: Too many false positives**
1803
+ ```bash
1804
+ # Refine detection patterns
1805
+ # Add exclusion rules
1806
+ # Test on diverse codebases
1807
+ ```
1808
+
1809
+ ---
1810
+
223
1811
  ## 🤝 **Community**
224
1812
 
225
1813
  - **Discord**: [Sun Engineering Discord](https://discord.gg/sun-engineering)