pumuki-ast-hooks 5.3.20 → 5.3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/docs/RELEASE_NOTES.md +35 -0
  2. package/docs/VIOLATIONS_RESOLUTION_PLAN.md +58 -58
  3. package/package.json +3 -3
  4. package/scripts/hooks-system/.AI_TOKEN_STATUS.txt +1 -1
  5. package/scripts/hooks-system/.audit-reports/notifications.log +935 -0
  6. package/scripts/hooks-system/.audit-reports/token-monitor.log +2809 -0
  7. package/scripts/hooks-system/application/CompositionRoot.js +38 -22
  8. package/scripts/hooks-system/application/services/AutonomousOrchestrator.js +0 -18
  9. package/scripts/hooks-system/application/services/ContextDetectionEngine.js +0 -58
  10. package/scripts/hooks-system/application/services/DynamicRulesLoader.js +2 -12
  11. package/scripts/hooks-system/application/services/GitFlowService.js +0 -80
  12. package/scripts/hooks-system/application/services/GitTreeState.js +2 -5
  13. package/scripts/hooks-system/application/services/HookSystemScheduler.js +0 -4
  14. package/scripts/hooks-system/application/services/IntelligentCommitAnalyzer.js +0 -25
  15. package/scripts/hooks-system/application/services/IntelligentGitTreeMonitor.js +0 -11
  16. package/scripts/hooks-system/application/services/PlatformAnalysisService.js +0 -19
  17. package/scripts/hooks-system/application/services/PlatformDetectionService.js +0 -19
  18. package/scripts/hooks-system/application/services/PlaybookRunner.js +1 -22
  19. package/scripts/hooks-system/application/services/PredictiveHookAdvisor.js +0 -19
  20. package/scripts/hooks-system/application/services/RealtimeGuardPlugin.js +0 -25
  21. package/scripts/hooks-system/application/services/RealtimeGuardService.js +71 -41
  22. package/scripts/hooks-system/application/services/SmartDirtyTreeAnalyzer.js +0 -11
  23. package/scripts/hooks-system/application/services/commit/CommitMessageGenerator.js +0 -11
  24. package/scripts/hooks-system/application/services/commit/FeatureDetector.js +0 -11
  25. package/scripts/hooks-system/application/services/evidence/EvidenceContextManager.js +0 -25
  26. package/scripts/hooks-system/application/services/guard/GuardAutoManagerService.js +31 -21
  27. package/scripts/hooks-system/application/services/guard/GuardConfig.js +15 -18
  28. package/scripts/hooks-system/application/services/guard/GuardEventLogger.js +0 -11
  29. package/scripts/hooks-system/application/services/guard/GuardHealthReminder.js +0 -26
  30. package/scripts/hooks-system/application/services/guard/GuardHeartbeatMonitor.js +6 -20
  31. package/scripts/hooks-system/application/services/guard/GuardLockManager.js +0 -11
  32. package/scripts/hooks-system/application/services/guard/GuardMonitorLoop.js +0 -25
  33. package/scripts/hooks-system/application/services/guard/GuardNotificationHandler.js +0 -11
  34. package/scripts/hooks-system/application/services/guard/GuardProcessManager.js +23 -11
  35. package/scripts/hooks-system/application/services/guard/GuardRecoveryService.js +0 -11
  36. package/scripts/hooks-system/application/services/installation/ConfigurationGeneratorService.js +0 -18
  37. package/scripts/hooks-system/application/services/installation/FileSystemInstallerService.js +0 -18
  38. package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +1 -19
  39. package/scripts/hooks-system/application/services/installation/HookInstaller.js +62 -24
  40. package/scripts/hooks-system/application/services/installation/IdeIntegrationService.js +0 -11
  41. package/scripts/hooks-system/application/services/installation/InstallService.js +1 -25
  42. package/scripts/hooks-system/application/services/installation/McpConfigurator.js +2 -19
  43. package/scripts/hooks-system/application/services/installation/PlatformDetectorService.js +0 -11
  44. package/scripts/hooks-system/application/services/installation/VSCodeTaskConfigurator.js +0 -11
  45. package/scripts/hooks-system/application/services/logging/AuditLogger.js +0 -8
  46. package/scripts/hooks-system/application/services/logging/UnifiedLogger.js +13 -15
  47. package/scripts/hooks-system/application/services/monitoring/ActivityMonitor.js +0 -33
  48. package/scripts/hooks-system/application/services/monitoring/AstMonitor.js +0 -27
  49. package/scripts/hooks-system/application/services/monitoring/DevDocsMonitor.js +0 -26
  50. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitor.js +0 -18
  51. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +4 -28
  52. package/scripts/hooks-system/application/services/monitoring/GitTreeMonitor.js +0 -28
  53. package/scripts/hooks-system/application/services/monitoring/GitTreeMonitorService.js +0 -26
  54. package/scripts/hooks-system/application/services/monitoring/HealthCheckProviders.js +0 -4
  55. package/scripts/hooks-system/application/services/monitoring/HealthCheckService.js +0 -25
  56. package/scripts/hooks-system/application/services/monitoring/HeartbeatMonitorService.js +0 -26
  57. package/scripts/hooks-system/application/services/monitoring/TokenMonitor.js +0 -26
  58. package/scripts/hooks-system/application/services/notification/MacNotificationSender.js +0 -11
  59. package/scripts/hooks-system/application/services/notification/NotificationCenterService.js +0 -18
  60. package/scripts/hooks-system/application/services/notification/NotificationDispatcher.js +0 -11
  61. package/scripts/hooks-system/application/services/notification/components/NotificationCooldownManager.js +0 -18
  62. package/scripts/hooks-system/application/services/notification/components/NotificationDeduplicator.js +0 -18
  63. package/scripts/hooks-system/application/services/notification/components/NotificationQueue.js +0 -11
  64. package/scripts/hooks-system/application/services/notification/components/NotificationRetryExecutor.js +0 -20
  65. package/scripts/hooks-system/application/services/platform/PlatformHeuristics.js +0 -19
  66. package/scripts/hooks-system/application/services/recovery/AutoRecoveryManager.js +0 -19
  67. package/scripts/hooks-system/application/services/smart-commit/CommitMessageSuggester.js +0 -11
  68. package/scripts/hooks-system/application/services/smart-commit/FileContextGrouper.js +0 -19
  69. package/scripts/hooks-system/application/services/smart-commit/SmartCommitSummaryBuilder.js +0 -4
  70. package/scripts/hooks-system/application/services/token/CursorTokenService.js +0 -20
  71. package/scripts/hooks-system/application/services/token/TokenMetricsService.js +2 -12
  72. package/scripts/hooks-system/application/services/token/TokenMonitorService.js +0 -19
  73. package/scripts/hooks-system/application/services/token/TokenStatusReporter.js +0 -12
  74. package/scripts/hooks-system/bin/cli.js +15 -1
  75. package/scripts/hooks-system/bin/guard-env.sh +18 -38
  76. package/scripts/hooks-system/bin/guard-supervisor.js +5 -515
  77. package/scripts/hooks-system/bin/session-loader.sh +3 -262
  78. package/scripts/hooks-system/bin/start-guards.sh +21 -184
  79. package/scripts/hooks-system/bin/update-evidence.sh +10 -1161
  80. package/scripts/hooks-system/config/project.config.json +1 -1
  81. package/scripts/hooks-system/domain/events/index.js +31 -24
  82. package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidAnalysisOrchestrator.js +3 -2
  83. package/scripts/hooks-system/infrastructure/ast/ast-core.js +12 -20
  84. package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +8 -18
  85. package/scripts/hooks-system/infrastructure/ast/backend/analyzers/BackendPatternDetector.js +2 -1
  86. package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +18 -14
  87. package/scripts/hooks-system/infrastructure/ast/frontend/ast-frontend.js +196 -196
  88. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +3 -2
  89. package/scripts/hooks-system/infrastructure/hooks/skill-activation-prompt.js +3 -2
  90. package/scripts/hooks-system/infrastructure/logging/UnifiedLoggerFactory.js +5 -4
  91. package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +88 -0
  92. package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +17 -16
  93. package/scripts/hooks-system/infrastructure/shell/orchestrators/audit-orchestrator.sh +92 -54
  94. package/scripts/hooks-system/infrastructure/telemetry/metrics-server.js +3 -2
  95. package/scripts/hooks-system/infrastructure/validators/enforce-english-literals.js +6 -8
@@ -5,7 +5,7 @@
5
5
  "platforms": [
6
6
  "backend"
7
7
  ],
8
- "created": "2025-12-31T07:05:44.501Z"
8
+ "created": "2025-12-31T11:37:15.219Z"
9
9
  },
10
10
  "architecture": {
11
11
  "pattern": "FEATURE_FIRST_CLEAN_DDD",
@@ -1,13 +1,7 @@
1
- const {
2
- ValidationException,
3
- BadRequestException,
4
- InternalServerException
5
- } = require('../exceptions');
1
+ const { ValidationError } = require('../errors');
6
2
 
7
3
  class DomainEvent {
8
4
  constructor(type, payload) {
9
- if (!type) throw new ValidationException('Event type is required', { field: 'type' });
10
- if (!payload) throw new ValidationException('Event payload is required', { field: 'payload' });
11
5
  this.type = type;
12
6
  this.payload = payload;
13
7
  this.timestamp = new Date().toISOString();
@@ -15,8 +9,8 @@ class DomainEvent {
15
9
  }
16
10
 
17
11
  validate() {
18
- if (!this.type) throw new ValidationException('Event type is required', { field: 'type' });
19
- if (!this.payload) throw new ValidationException('Event payload is required', { field: 'payload' });
12
+ if (!this.type) throw new ValidationError('Event type is required', 'type', this.type);
13
+ if (!this.payload) throw new ValidationError('Event payload is required', 'payload', this.payload);
20
14
  return true;
21
15
  }
22
16
 
@@ -37,7 +31,9 @@ class EvidenceStaleEvent extends DomainEvent {
37
31
 
38
32
  validate() {
39
33
  super.validate();
40
- if (!this.payload.evidencePath) throw new ValidationException('Evidence path is required', { field: 'evidencePath' });
34
+ if (!this.payload.evidencePath) {
35
+ throw new ValidationError('Evidence path is required', 'payload.evidencePath', this.payload.evidencePath);
36
+ }
41
37
  }
42
38
  }
43
39
 
@@ -49,8 +45,12 @@ class GitFlowViolationEvent extends DomainEvent {
49
45
 
50
46
  validate() {
51
47
  super.validate();
52
- if (!this.payload.branch) throw new ValidationException('Branch name is required', { field: 'branch' });
53
- if (!this.payload.violation) throw new ValidationException('Violation details are required', { field: 'violation' });
48
+ if (!this.payload.branch) {
49
+ throw new ValidationError('Branch name is required', 'payload.branch', this.payload.branch);
50
+ }
51
+ if (!this.payload.violation) {
52
+ throw new ValidationError('Violation details are required', 'payload.violation', this.payload.violation);
53
+ }
54
54
  }
55
55
  }
56
56
 
@@ -62,7 +62,9 @@ class AstCriticalFoundEvent extends DomainEvent {
62
62
 
63
63
  validate() {
64
64
  super.validate();
65
- if (!Array.isArray(this.payload.findings)) throw new ValidationException('Findings must be an array', { field: 'findings' });
65
+ if (!Array.isArray(this.payload.findings)) {
66
+ throw new ValidationError('Findings must be an array', 'payload.findings', this.payload.findings);
67
+ }
66
68
  }
67
69
  }
68
70
 
@@ -71,12 +73,6 @@ class PreCommitBlockedEvent extends DomainEvent {
71
73
  super('PRE_COMMIT_BLOCKED', { reason, violations });
72
74
  this.validate();
73
75
  }
74
-
75
- validate() {
76
- super.validate();
77
- if (!this.payload.reason) throw new ValidationException('Reason is required', { field: 'reason' });
78
- if (!this.payload.violations) throw new ValidationException('Violations are required', { field: 'violations' });
79
- }
80
76
  }
81
77
 
82
78
  class AnalysisCompletedEvent extends DomainEvent {
@@ -84,16 +80,13 @@ class AnalysisCompletedEvent extends DomainEvent {
84
80
  super('ANALYSIS_COMPLETED', summary);
85
81
  this.validate();
86
82
  }
87
-
88
- validate() {
89
- super.validate();
90
- if (!this.payload) throw new ValidationException('Summary is required', { field: 'summary' });
91
- }
92
83
  }
93
84
 
94
85
  class EventBus {
95
86
  constructor() {
96
87
  this.subscribers = new Map();
88
+ this.processedIds = new Set();
89
+ this.maxProcessed = 500;
97
90
  }
98
91
 
99
92
  subscribe(eventType, handler) {
@@ -113,11 +106,25 @@ class EventBus {
113
106
  }
114
107
 
115
108
  async publish(event) {
109
+ if (event?.id && this.processedIds.has(event.id)) {
110
+ return event;
111
+ }
116
112
  const handlers = this.subscribers.get(event.type) || [];
117
113
  const wildcardHandlers = this.subscribers.get('*') || [];
118
114
  const allHandlers = [...handlers, ...wildcardHandlers];
119
115
 
120
116
  await Promise.all(allHandlers.map(handler => handler(event)));
117
+
118
+ if (event?.id) {
119
+ this.processedIds.add(event.id);
120
+ if (this.processedIds.size > this.maxProcessed) {
121
+ const iter = this.processedIds.values();
122
+ for (let i = 0; i < 50 && this.processedIds.size > this.maxProcessed; i++) {
123
+ const next = iter.next();
124
+ if (!next.done) this.processedIds.delete(next.value);
125
+ }
126
+ }
127
+ }
121
128
  return event;
122
129
  }
123
130
 
@@ -40,8 +40,9 @@ class AndroidAnalysisOrchestrator {
40
40
  return 0.6745 * (x - med) / madValue;
41
41
  };
42
42
 
43
- const pOutlier = Number(process.env.AST_GODCLASS_P_OUTLIER || 90);
44
- const pExtreme = Number(process.env.AST_GODCLASS_P_EXTREME || 97);
43
+ const env = require('../../../../config/env');
44
+ const pOutlier = env.getNumber('AST_GODCLASS_P_OUTLIER', 90);
45
+ const pExtreme = env.getNumber('AST_GODCLASS_P_EXTREME', 97);
45
46
 
46
47
  const methods = this.godClassCandidates.map(c => c.methodsCount);
47
48
  const props = this.godClassCandidates.map(c => c.propertiesCount);
@@ -2,6 +2,7 @@
2
2
  const { Project, Node, SyntaxKind, ScriptTarget, ModuleKind } = require("ts-morph");
3
3
  const path = require("path");
4
4
  const fs = require("fs");
5
+ const env = require("../../config/env");
5
6
 
6
7
  let SeverityEvaluator = null;
7
8
  let severityEvaluatorInstance = null;
@@ -19,7 +20,7 @@ function getSeverityEvaluator() {
19
20
  return severityEvaluatorInstance;
20
21
  }
21
22
 
22
- let INTELLIGENT_SEVERITY_ENABLED = process.env.INTELLIGENT_SEVERITY === 'true';
23
+ let INTELLIGENT_SEVERITY_ENABLED = env.getBool('INTELLIGENT_SEVERITY', false);
23
24
 
24
25
  /**
25
26
  * Get repository root directory (portable - dynamic detection)
@@ -179,18 +180,18 @@ function pushFinding(ruleId, severity, sf, node, message, findings, metrics = {}
179
180
  let mappedSeverity = mapToLevel(severity);
180
181
  const isCleanLayerMarkerRule = ruleId === 'backend.clean.domain' || ruleId === 'backend.clean.application' || ruleId === 'backend.clean.infrastructure' || ruleId === 'backend.clean.presentation';
181
182
  let isStrictCriticalRule = false;
182
- if (process.env.AUDIT_STRICT === '1' && !isCleanLayerMarkerRule) {
183
+ if (env.get('AUDIT_STRICT', '0') === '1' && !isCleanLayerMarkerRule) {
183
184
  const defaultStrictCriticalRegex = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|performance\\.|metrics\\.|observability\\.|validation\\.|i18n\\.|accessibility\\.|naming\\.)';
184
185
  const defaultStrictCriticalRegexLibrary = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|validation\\.|naming\\.)';
185
- const strictRegexSource = process.env.AST_STRICT_CRITICAL_RULES_REGEX ||
186
- (process.env.AUDIT_LIBRARY === 'true'
187
- ? (process.env.AST_STRICT_CRITICAL_RULES_REGEX_LIBRARY || defaultStrictCriticalRegexLibrary)
186
+ const strictRegexSource = env.get('AST_STRICT_CRITICAL_RULES_REGEX',
187
+ env.getBool('AUDIT_LIBRARY', false)
188
+ ? env.get('AST_STRICT_CRITICAL_RULES_REGEX_LIBRARY', defaultStrictCriticalRegexLibrary)
188
189
  : defaultStrictCriticalRegex);
189
190
  let strictRegex;
190
191
  try {
191
192
  strictRegex = new RegExp(strictRegexSource, 'i');
192
193
  } catch {
193
- strictRegex = new RegExp(process.env.AUDIT_LIBRARY === 'true' ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
194
+ strictRegex = new RegExp(env.getBool('AUDIT_LIBRARY', false) ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
194
195
  }
195
196
  isStrictCriticalRule = strictRegex.test(ruleId);
196
197
  if (isStrictCriticalRule) {
@@ -241,18 +242,18 @@ function pushFileFinding(ruleId, severity, filePath, line, column, message, find
241
242
  let mappedSeverity = mapToLevel(severity);
242
243
  const isCleanLayerMarkerRule = ruleId === 'backend.clean.domain' || ruleId === 'backend.clean.application' || ruleId === 'backend.clean.infrastructure' || ruleId === 'backend.clean.presentation';
243
244
  let isStrictCriticalRule = false;
244
- if (process.env.AUDIT_STRICT === '1' && !isCleanLayerMarkerRule) {
245
+ if (env.get('AUDIT_STRICT', '0') === '1' && !isCleanLayerMarkerRule) {
245
246
  const defaultStrictCriticalRegex = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|performance\\.|metrics\\.|observability\\.|validation\\.|i18n\\.|accessibility\\.|naming\\.)';
246
247
  const defaultStrictCriticalRegexLibrary = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|validation\\.|naming\\.)';
247
- const strictRegexSource = process.env.AST_STRICT_CRITICAL_RULES_REGEX ||
248
- (process.env.AUDIT_LIBRARY === 'true'
249
- ? (process.env.AST_STRICT_CRITICAL_RULES_REGEX_LIBRARY || defaultStrictCriticalRegexLibrary)
248
+ const strictRegexSource = env.get('AST_STRICT_CRITICAL_RULES_REGEX',
249
+ env.getBool('AUDIT_LIBRARY', false)
250
+ ? env.get('AST_STRICT_CRITICAL_RULES_REGEX_LIBRARY', defaultStrictCriticalRegexLibrary)
250
251
  : defaultStrictCriticalRegex);
251
252
  let strictRegex;
252
253
  try {
253
254
  strictRegex = new RegExp(strictRegexSource, 'i');
254
255
  } catch {
255
- strictRegex = new RegExp(process.env.AUDIT_LIBRARY === 'true' ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
256
+ strictRegex = new RegExp(env.getBool('AUDIT_LIBRARY', false) ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
256
257
  }
257
258
  isStrictCriticalRule = strictRegex.test(ruleId);
258
259
  if (isStrictCriticalRule) {
@@ -332,15 +333,6 @@ function mapToLevel(severity) {
332
333
  function platformOf(filePath) {
333
334
  const p = filePath.replace(/\\/g, "/");
334
335
 
335
- if (p.includes("/infrastructure/ast/") && process.env.AUDIT_LIBRARY !== 'true') return null;
336
-
337
- if (process.env.AUDIT_LIBRARY === 'true') {
338
- if (p.includes("/infrastructure/ast/backend/") || p.includes("/scripts/hooks-system/infrastructure/ast/backend/")) return "backend";
339
- if (p.includes("/infrastructure/ast/frontend/") || p.includes("/scripts/hooks-system/infrastructure/ast/frontend/")) return "frontend";
340
- if (p.includes("/infrastructure/ast/android/") || p.includes("/scripts/hooks-system/infrastructure/ast/android/")) return "android";
341
- if (p.includes("/infrastructure/ast/ios/") || p.includes("/scripts/hooks-system/infrastructure/ast/ios/")) return "ios";
342
- }
343
-
344
336
  if (p.includes("/apps/backend/") || p.includes("apps/backend/")) return "backend";
345
337
  if (p.includes("/apps/admin/") || p.includes("/admin-dashboard/")) return "frontend";
346
338
  if (p.includes("/apps/mobile-ios/") || p.includes("/apps/ios/")) return "ios";
@@ -1,6 +1,7 @@
1
1
 
2
2
  const path = require("path");
3
3
  const fs = require("fs");
4
+ const env = require("../../config/env");
4
5
 
5
6
  const astModulesPath = __dirname;
6
7
  const { createProject, platformOf, mapToLevel } = require(path.join(astModulesPath, "ast-core"));
@@ -27,13 +28,7 @@ async function runASTIntelligence() {
27
28
  const { getRepoRoot } = require('./ast-core');
28
29
  const root = getRepoRoot();
29
30
 
30
- const isLibraryAudit = process.env.AUDIT_LIBRARY === 'true';
31
-
32
- const allFiles = listSourceFiles(root).filter(f => {
33
- const p = String(f || '').replace(/\\/g, '/');
34
- if (!isLibraryAudit && p.includes('/infrastructure/ast/')) return false;
35
- return true;
36
- });
31
+ const allFiles = listSourceFiles(root);
37
32
 
38
33
  const project = createProject(allFiles);
39
34
  const findings = [];
@@ -75,9 +70,9 @@ async function runASTIntelligence() {
75
70
  }
76
71
 
77
72
  function runProjectHardcodedThresholdAudit(root, allFiles, findings) {
78
- if (process.env.AST_INSIGHTS !== '1') return;
73
+ if (env.get('AST_INSIGHTS', '0') !== '1') return;
79
74
 
80
- const maxFindings = Number(process.env.AST_INSIGHTS_PROJECT_MAX || 200);
75
+ const maxFindings = env.getNumber('AST_INSIGHTS_PROJECT_MAX', 200);
81
76
  if (!Number.isFinite(maxFindings) || maxFindings <= 0) return;
82
77
 
83
78
  const isExcludedPath = (filePath) => {
@@ -160,7 +155,7 @@ function runProjectHardcodedThresholdAudit(root, allFiles, findings) {
160
155
  }
161
156
 
162
157
  function runHardcodedThresholdAudit(root, findings) {
163
- if (process.env.AST_INSIGHTS !== '1') return;
158
+ if (env.get('AST_INSIGHTS', '0') !== '1') return;
164
159
 
165
160
  const ruleDirs = [
166
161
  path.join(root, 'infrastructure', 'ast'),
@@ -317,7 +312,7 @@ async function runPlatformAnalysis(project, findings, context) {
317
312
  }
318
313
  } catch (error) {
319
314
  console.error(`[ERROR] Error processing platform ${platform}:`, error.message);
320
- if (process.env.DEBUG_AST) {
315
+ if (env.getBool('DEBUG_AST', false)) {
321
316
  console.error(error.stack);
322
317
  }
323
318
  }
@@ -376,7 +371,7 @@ function generateOutput(findings, context, project, root) {
376
371
  * Save detailed JSON report
377
372
  */
378
373
  function saveDetailedReport(findings, levelTotals, platformTotals, project, root) {
379
- const outDir = process.env.AUDIT_TMP || path.join(root, ".audit_tmp");
374
+ const outDir = env.get('AUDIT_TMP', path.join(root, ".audit_tmp"));
380
375
  try {
381
376
  fs.mkdirSync(outDir, { recursive: true });
382
377
 
@@ -532,7 +527,7 @@ function checkForMigrations(root) {
532
527
  * List source files recursively
533
528
  */
534
529
  function listSourceFiles(root) {
535
- if (process.env.STAGING_ONLY_MODE === "1") {
530
+ if (env.get('STAGING_ONLY_MODE', '0') === "1") {
536
531
  const { execSync } = require("child_process");
537
532
  try {
538
533
  const allStaged = execSync("git diff --cached --name-only --diff-filter=ACM", {
@@ -600,11 +595,6 @@ function listSourceFiles(root) {
600
595
  function shouldIgnore(file) {
601
596
  const p = file.replace(/\\/g, "/");
602
597
  if (p.includes("node_modules/")) return true;
603
-
604
- const isLibraryAudit = process.env.AUDIT_LIBRARY === 'true';
605
-
606
- if (!isLibraryAudit && p.includes("scripts/hooks-system/")) return true;
607
- if (!isLibraryAudit && p.includes("/infrastructure/ast/")) return true;
608
598
  if (p.includes("/.cursor/")) return true;
609
599
  if (/\.bak/i.test(p)) return true;
610
600
  if (p.includes("/.next/")) return true;
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
+ const env = require('../../../../config/env');
3
4
 
4
5
  class BackendPatternDetector {
5
6
  constructor(projectRoot) {
@@ -11,7 +12,7 @@ class BackendPatternDetector {
11
12
  const fullPath = path.join(this.projectRoot, relativePath);
12
13
  return fs.readFileSync(fullPath, 'utf-8');
13
14
  } catch (error) {
14
- if (process.env.DEBUG) {
15
+ if (env.getBool('DEBUG', false)) {
15
16
  console.debug(`[BackendPatternDetector] Failed to read file ${relativePath}: ${error.message}`);
16
17
  }
17
18
  return '';
@@ -1,10 +1,13 @@
1
1
  const path = require('path');
2
+ const env = require('../../../config/env');
2
3
  const {
4
+ platformOf,
3
5
  pushFinding,
6
+ pushFileFinding,
4
7
  mapToLevel,
5
- SyntaxKind,
8
+ positionOf,
6
9
  isTestFile,
7
- platformOf,
10
+ SyntaxKind,
8
11
  hasImport,
9
12
  hasDecorator,
10
13
  findStringLiterals,
@@ -118,7 +121,7 @@ function runBackendIntelligence(project, findings, platform) {
118
121
  const filePath = sf.getFilePath();
119
122
  if (platformOf(filePath) !== 'backend') return;
120
123
  if (/\/ast-[^/]+\.js$/.test(filePath)) return;
121
- if (process.env.AUDIT_LIBRARY !== 'true') {
124
+ if (!env.getBool('AUDIT_LIBRARY', false)) {
122
125
  if (/scripts\/hooks-system\/infrastructure\/ast\//i.test(filePath) || /\/infrastructure\/ast\//i.test(filePath)) return;
123
126
  }
124
127
  if (isTestFile(filePath)) return;
@@ -143,8 +146,8 @@ function runBackendIntelligence(project, findings, platform) {
143
146
 
144
147
  if (metrics.length === 0) return null;
145
148
 
146
- const pOutlier = Number(process.env.AST_GODCLASS_P_OUTLIER || 90);
147
- const pExtreme = Number(process.env.AST_GODCLASS_P_EXTREME || 97);
149
+ const pOutlier = env.getNumber('AST_GODCLASS_P_OUTLIER', 90);
150
+ const pExtreme = env.getNumber('AST_GODCLASS_P_EXTREME', 97);
148
151
 
149
152
  const methods = metrics.map(m => m.methodsCount);
150
153
  const props = metrics.map(m => m.propertiesCount);
@@ -201,12 +204,12 @@ function runBackendIntelligence(project, findings, platform) {
201
204
  if (platformOf(filePath) !== "backend") return;
202
205
 
203
206
  if (/\/ast-[^/]+\.js$/.test(filePath)) return;
204
- if (process.env.AUDIT_LIBRARY !== 'true') {
207
+ if (!env.getBool('AUDIT_LIBRARY', false)) {
205
208
  if (/scripts\/hooks-system\/infrastructure\/ast\//i.test(filePath) || /\/infrastructure\/ast\//i.test(filePath)) return;
206
209
  }
207
210
 
208
211
  const fullText = sf.getFullText();
209
- const insightsEnabled = process.env.AST_INSIGHTS === '1';
212
+ const insightsEnabled = env.get('AST_INSIGHTS', '0') === '1';
210
213
  const isSpecFile = /\.(spec|test)\.(ts|tsx|js|jsx)$/.test(filePath);
211
214
  const secretPattern = /(password|secret|key|token)\s*[:=]\s*['"`]([^'"]{8,})['"`]/gi;
212
215
  const matches = Array.from(fullText.matchAll(secretPattern));
@@ -366,12 +369,11 @@ function runBackendIntelligence(project, findings, platform) {
366
369
  }
367
370
  });
368
371
 
369
- // Removed controller-level CORS check because global CORS is enabled
370
- // const hasCors = sf.getFullText().includes("cors") || sf.getFullText().includes("CORS") || sf.getFullText().includes("@CrossOrigin");
371
- // const missingCorsSeverity = hasGlobalCors ? "low" : "high";
372
- // if (!hasCors && (sf.getFullText().includes("controller") || sf.getFullText().includes("Controller"))) {
373
- // pushFinding("backend.auth.missing_cors", missingCorsSeverity, sf, sf, "Missing CORS configuration in controller - consider @CrossOrigin or global CORS config", findings);
374
- // }
372
+ const hasCors = sf.getFullText().includes("cors") || sf.getFullText().includes("CORS") || sf.getFullText().includes("@CrossOrigin");
373
+ const missingCorsSeverity = hasGlobalCors ? "low" : "high";
374
+ if (!hasCors && (sf.getFullText().includes("controller") || sf.getFullText().includes("Controller"))) {
375
+ pushFinding("backend.auth.missing_cors", missingCorsSeverity, sf, sf, "Missing CORS configuration in controller - consider @CrossOrigin or global CORS config", findings);
376
+ }
375
377
 
376
378
  sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((call) => {
377
379
  const expr = call.getExpression();
@@ -423,7 +425,9 @@ function runBackendIntelligence(project, findings, platform) {
423
425
 
424
426
  if (isTestFile(filePath)) {
425
427
  sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((call) => {
426
- const exprText = call.getExpression().getText();
428
+ const expr = call.getExpression();
429
+ if (!expr) return;
430
+ const exprText = expr.getText();
427
431
  if (/Thread\.sleep|await|delay/.test(exprText)) {
428
432
  pushFinding("backend.testing.slow_tests", "medium", sf, call, "Test with sleep/delay detected - slow tests impact CI/CD performance", findings);
429
433
  }