pumuki-ast-hooks 5.3.19 → 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 (46) hide show
  1. package/docs/RELEASE_NOTES.md +35 -0
  2. package/docs/VIOLATIONS_RESOLUTION_PLAN.md +64 -60
  3. package/package.json +9 -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/DynamicRulesLoader.js +2 -1
  9. package/scripts/hooks-system/application/services/GitTreeState.js +2 -1
  10. package/scripts/hooks-system/application/services/PlaybookRunner.js +1 -1
  11. package/scripts/hooks-system/application/services/RealtimeGuardService.js +71 -14
  12. package/scripts/hooks-system/application/services/guard/GuardAutoManagerService.js +31 -2
  13. package/scripts/hooks-system/application/services/guard/GuardConfig.js +17 -9
  14. package/scripts/hooks-system/application/services/guard/GuardHeartbeatMonitor.js +6 -9
  15. package/scripts/hooks-system/application/services/guard/GuardProcessManager.js +23 -0
  16. package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +1 -1
  17. package/scripts/hooks-system/application/services/installation/HookInstaller.js +62 -5
  18. package/scripts/hooks-system/application/services/installation/McpConfigurator.js +2 -1
  19. package/scripts/hooks-system/application/services/logging/AuditLogger.js +0 -4
  20. package/scripts/hooks-system/application/services/logging/UnifiedLogger.js +13 -4
  21. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +4 -3
  22. package/scripts/hooks-system/application/services/token/TokenMetricsService.js +2 -1
  23. package/scripts/hooks-system/bin/cli.js +15 -1
  24. package/scripts/hooks-system/bin/guard-env.sh +18 -38
  25. package/scripts/hooks-system/bin/guard-supervisor.js +5 -515
  26. package/scripts/hooks-system/bin/session-loader.sh +3 -262
  27. package/scripts/hooks-system/bin/start-guards.sh +21 -184
  28. package/scripts/hooks-system/bin/update-evidence.sh +10 -1161
  29. package/scripts/hooks-system/config/project.config.json +1 -1
  30. package/scripts/hooks-system/domain/events/index.js +32 -6
  31. package/scripts/hooks-system/domain/exceptions/index.js +87 -0
  32. package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidAnalysisOrchestrator.js +3 -2
  33. package/scripts/hooks-system/infrastructure/ast/ast-core.js +12 -20
  34. package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +8 -18
  35. package/scripts/hooks-system/infrastructure/ast/backend/analyzers/BackendPatternDetector.js +2 -1
  36. package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +10 -8
  37. package/scripts/hooks-system/infrastructure/ast/frontend/ast-frontend.js +196 -196
  38. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +3 -2
  39. package/scripts/hooks-system/infrastructure/config/config.js +5 -0
  40. package/scripts/hooks-system/infrastructure/hooks/skill-activation-prompt.js +3 -2
  41. package/scripts/hooks-system/infrastructure/logging/UnifiedLoggerFactory.js +5 -4
  42. package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +88 -0
  43. package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +17 -16
  44. package/scripts/hooks-system/infrastructure/telemetry/metric-scope.js +98 -0
  45. package/scripts/hooks-system/infrastructure/telemetry/metrics-server.js +3 -2
  46. 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-25T22:02:53.249Z"
8
+ "created": "2025-12-31T11:37:15.219Z"
9
9
  },
10
10
  "architecture": {
11
11
  "pattern": "FEATURE_FIRST_CLEAN_DDD",
@@ -1,3 +1,5 @@
1
+ const { ValidationError } = require('../errors');
2
+
1
3
  class DomainEvent {
2
4
  constructor(type, payload) {
3
5
  this.type = type;
@@ -7,8 +9,8 @@ class DomainEvent {
7
9
  }
8
10
 
9
11
  validate() {
10
- if (!this.type) throw new Error('Event type is required');
11
- if (!this.payload) throw new Error('Event payload is required');
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);
12
14
  return true;
13
15
  }
14
16
 
@@ -29,7 +31,9 @@ class EvidenceStaleEvent extends DomainEvent {
29
31
 
30
32
  validate() {
31
33
  super.validate();
32
- if (!this.payload.evidencePath) throw new Error('Evidence path is required');
34
+ if (!this.payload.evidencePath) {
35
+ throw new ValidationError('Evidence path is required', 'payload.evidencePath', this.payload.evidencePath);
36
+ }
33
37
  }
34
38
  }
35
39
 
@@ -41,8 +45,12 @@ class GitFlowViolationEvent extends DomainEvent {
41
45
 
42
46
  validate() {
43
47
  super.validate();
44
- if (!this.payload.branch) throw new Error('Branch name is required');
45
- if (!this.payload.violation) throw new Error('Violation details are required');
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
+ }
46
54
  }
47
55
  }
48
56
 
@@ -54,7 +62,9 @@ class AstCriticalFoundEvent extends DomainEvent {
54
62
 
55
63
  validate() {
56
64
  super.validate();
57
- if (!Array.isArray(this.payload.findings)) throw new Error('Findings must be an array');
65
+ if (!Array.isArray(this.payload.findings)) {
66
+ throw new ValidationError('Findings must be an array', 'payload.findings', this.payload.findings);
67
+ }
58
68
  }
59
69
  }
60
70
 
@@ -75,6 +85,8 @@ class AnalysisCompletedEvent extends DomainEvent {
75
85
  class EventBus {
76
86
  constructor() {
77
87
  this.subscribers = new Map();
88
+ this.processedIds = new Set();
89
+ this.maxProcessed = 500;
78
90
  }
79
91
 
80
92
  subscribe(eventType, handler) {
@@ -94,11 +106,25 @@ class EventBus {
94
106
  }
95
107
 
96
108
  async publish(event) {
109
+ if (event?.id && this.processedIds.has(event.id)) {
110
+ return event;
111
+ }
97
112
  const handlers = this.subscribers.get(event.type) || [];
98
113
  const wildcardHandlers = this.subscribers.get('*') || [];
99
114
  const allHandlers = [...handlers, ...wildcardHandlers];
100
115
 
101
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
+ }
102
128
  return event;
103
129
  }
104
130
 
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Custom Exception Classes for AST Intelligence System
3
+ * Provides structured error handling with specific exception types
4
+ */
5
+
6
+ class BaseException extends Error {
7
+ constructor(message, code = 'INTERNAL_ERROR', statusCode = 500, context = {}) {
8
+ super(message);
9
+ this.name = this.constructor.name;
10
+ this.code = code;
11
+ this.statusCode = statusCode;
12
+ this.timestamp = new Date().toISOString();
13
+ this.context = context;
14
+
15
+ if (Error.captureStackTrace) {
16
+ Error.captureStackTrace(this, this.constructor);
17
+ } else {
18
+ this.stack = (new Error()).stack;
19
+ }
20
+ }
21
+
22
+ toJSON() {
23
+ return {
24
+ name: this.name,
25
+ message: this.message,
26
+ code: this.code,
27
+ statusCode: this.statusCode,
28
+ timestamp: this.timestamp,
29
+ context: this.context,
30
+ stack: this.stack
31
+ };
32
+ }
33
+ }
34
+
35
+ class ValidationException extends BaseException {
36
+ constructor(message, field = null, context = {}) {
37
+ super(message, 'VALIDATION_ERROR', 400, context);
38
+ this.field = field;
39
+ }
40
+ }
41
+
42
+ class BadRequestException extends BaseException {
43
+ constructor(message, context = {}) {
44
+ super(message, 'BAD_REQUEST', 400, context);
45
+ }
46
+ }
47
+
48
+ class NotFoundException extends BaseException {
49
+ constructor(resource = 'Resource', context = {}) {
50
+ super(`${resource} not found`, 'NOT_FOUND', 404, context);
51
+ }
52
+ }
53
+
54
+ class UnauthorizedException extends BaseException {
55
+ constructor(message = 'Unauthorized access', context = {}) {
56
+ super(message, 'UNAUTHORIZED', 401, context);
57
+ }
58
+ }
59
+
60
+ class ForbiddenException extends BaseException {
61
+ constructor(message = 'Forbidden access', context = {}) {
62
+ super(message, 'FORBIDDEN', 403, context);
63
+ }
64
+ }
65
+
66
+ class ConflictException extends BaseException {
67
+ constructor(message, context = {}) {
68
+ super(message, 'CONFLICT', 409, context);
69
+ }
70
+ }
71
+
72
+ class InternalServerException extends BaseException {
73
+ constructor(message = 'Internal server error', context = {}) {
74
+ super(message, 'INTERNAL_SERVER_ERROR', 500, context);
75
+ }
76
+ }
77
+
78
+ module.exports = {
79
+ BaseException,
80
+ ValidationException,
81
+ BadRequestException,
82
+ NotFoundException,
83
+ UnauthorizedException,
84
+ ForbiddenException,
85
+ ConflictException,
86
+ InternalServerException
87
+ };
@@ -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,11 +1,13 @@
1
-
2
1
  const path = require('path');
2
+ const env = require('../../../config/env');
3
3
  const {
4
+ platformOf,
4
5
  pushFinding,
6
+ pushFileFinding,
5
7
  mapToLevel,
6
- SyntaxKind,
8
+ positionOf,
7
9
  isTestFile,
8
- platformOf,
10
+ SyntaxKind,
9
11
  hasImport,
10
12
  hasDecorator,
11
13
  findStringLiterals,
@@ -119,7 +121,7 @@ function runBackendIntelligence(project, findings, platform) {
119
121
  const filePath = sf.getFilePath();
120
122
  if (platformOf(filePath) !== 'backend') return;
121
123
  if (/\/ast-[^/]+\.js$/.test(filePath)) return;
122
- if (process.env.AUDIT_LIBRARY !== 'true') {
124
+ if (!env.getBool('AUDIT_LIBRARY', false)) {
123
125
  if (/scripts\/hooks-system\/infrastructure\/ast\//i.test(filePath) || /\/infrastructure\/ast\//i.test(filePath)) return;
124
126
  }
125
127
  if (isTestFile(filePath)) return;
@@ -144,8 +146,8 @@ function runBackendIntelligence(project, findings, platform) {
144
146
 
145
147
  if (metrics.length === 0) return null;
146
148
 
147
- const pOutlier = Number(process.env.AST_GODCLASS_P_OUTLIER || 90);
148
- 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);
149
151
 
150
152
  const methods = metrics.map(m => m.methodsCount);
151
153
  const props = metrics.map(m => m.propertiesCount);
@@ -202,12 +204,12 @@ function runBackendIntelligence(project, findings, platform) {
202
204
  if (platformOf(filePath) !== "backend") return;
203
205
 
204
206
  if (/\/ast-[^/]+\.js$/.test(filePath)) return;
205
- if (process.env.AUDIT_LIBRARY !== 'true') {
207
+ if (!env.getBool('AUDIT_LIBRARY', false)) {
206
208
  if (/scripts\/hooks-system\/infrastructure\/ast\//i.test(filePath) || /\/infrastructure\/ast\//i.test(filePath)) return;
207
209
  }
208
210
 
209
211
  const fullText = sf.getFullText();
210
- const insightsEnabled = process.env.AST_INSIGHTS === '1';
212
+ const insightsEnabled = env.get('AST_INSIGHTS', '0') === '1';
211
213
  const isSpecFile = /\.(spec|test)\.(ts|tsx|js|jsx)$/.test(filePath);
212
214
  const secretPattern = /(password|secret|key|token)\s*[:=]\s*['"`]([^'"]{8,})['"`]/gi;
213
215
  const matches = Array.from(fullText.matchAll(secretPattern));