pumuki-ast-hooks 5.3.18 → 5.3.19

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 (36) hide show
  1. package/docs/VIOLATIONS_RESOLUTION_PLAN.md +23 -25
  2. package/package.json +2 -2
  3. package/scripts/hooks-system/application/CompositionRoot.js +24 -73
  4. package/scripts/hooks-system/application/services/DynamicRulesLoader.js +1 -2
  5. package/scripts/hooks-system/application/services/GitTreeState.js +139 -13
  6. package/scripts/hooks-system/application/services/HookSystemScheduler.js +43 -0
  7. package/scripts/hooks-system/application/services/PlaybookRunner.js +1 -1
  8. package/scripts/hooks-system/application/services/RealtimeGuardService.js +15 -85
  9. package/scripts/hooks-system/application/services/guard/GuardAutoManagerService.js +2 -31
  10. package/scripts/hooks-system/application/services/guard/GuardConfig.js +9 -17
  11. package/scripts/hooks-system/application/services/guard/GuardHeartbeatMonitor.js +9 -6
  12. package/scripts/hooks-system/application/services/guard/GuardProcessManager.js +0 -29
  13. package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +1 -4
  14. package/scripts/hooks-system/application/services/installation/McpConfigurator.js +1 -2
  15. package/scripts/hooks-system/application/services/logging/AuditLogger.js +86 -1
  16. package/scripts/hooks-system/application/services/logging/UnifiedLogger.js +4 -13
  17. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitor.js +1 -0
  18. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +3 -7
  19. package/scripts/hooks-system/application/services/token/TokenMetricsService.js +1 -14
  20. package/scripts/hooks-system/bin/__tests__/evidence-update.spec.js +49 -0
  21. package/scripts/hooks-system/bin/cli.js +1 -15
  22. package/scripts/hooks-system/domain/events/index.js +6 -32
  23. package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidAnalysisOrchestrator.js +2 -3
  24. package/scripts/hooks-system/infrastructure/ast/ast-core.js +20 -12
  25. package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +18 -8
  26. package/scripts/hooks-system/infrastructure/ast/backend/analyzers/BackendPatternDetector.js +1 -2
  27. package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +8 -10
  28. package/scripts/hooks-system/infrastructure/ast/frontend/ast-frontend.js +196 -196
  29. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/__tests__/iOSASTIntelligentAnalyzer.spec.js +66 -0
  30. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +2 -3
  31. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSArchitectureRules.js +24 -86
  32. package/scripts/hooks-system/infrastructure/hooks/skill-activation-prompt.js +2 -3
  33. package/scripts/hooks-system/infrastructure/logging/UnifiedLoggerFactory.js +5 -35
  34. package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +16 -86
  35. package/scripts/hooks-system/infrastructure/telemetry/metrics-server.js +2 -51
  36. package/scripts/hooks-system/infrastructure/validators/enforce-english-literals.js +8 -6
@@ -1,8 +1,5 @@
1
1
  const { execSync } = require('child_process');
2
2
 
3
- // Import recordMetric for prometheus metrics
4
- const { recordMetric } = require('../../../infrastructure/telemetry/metrics-logger');
5
-
6
3
  class TokenMetricsService {
7
4
  constructor(cursorTokenService, thresholds, logger) {
8
5
  this.cursorTokenService = cursorTokenService;
@@ -57,8 +54,7 @@ class TokenMetricsService {
57
54
  if (untrusted) {
58
55
  level = 'ok';
59
56
  }
60
- const env = require('../../config/env');
61
- const forceLevel = (env.get('TOKEN_MONITOR_FORCE_LEVEL', '') || '').toLowerCase();
57
+ const forceLevel = (process.env.TOKEN_MONITOR_FORCE_LEVEL || '').toLowerCase();
62
58
  if (forceLevel === 'warning' || forceLevel === 'critical' || forceLevel === 'ok') {
63
59
  level = forceLevel;
64
60
  }
@@ -79,15 +75,6 @@ class TokenMetricsService {
79
75
  this.logger.debug('TOKEN_MONITOR_METRICS', metrics);
80
76
  }
81
77
 
82
- // Record prometheus metrics
83
- recordMetric({
84
- hook: 'token_monitor',
85
- status: 'collect',
86
- tokensUsed,
87
- percentUsed: Number(percentUsed.toFixed(0)),
88
- level
89
- });
90
-
91
78
  return metrics;
92
79
  }
93
80
 
@@ -0,0 +1,49 @@
1
+ const fs = require('fs');
2
+ const os = require('os');
3
+ const path = require('path');
4
+ const { execSync } = require('child_process');
5
+
6
+ describe('ast-hooks evidence:update', () => {
7
+ let repoRoot;
8
+ let subdir;
9
+
10
+ beforeEach(() => {
11
+ repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'ast-hooks-evidence-cli-'));
12
+ subdir = path.join(repoRoot, 'packages', 'app');
13
+ fs.mkdirSync(subdir, { recursive: true });
14
+
15
+ execSync('git init', { cwd: repoRoot, stdio: 'ignore' });
16
+ execSync('git config user.email "test@example.com"', { cwd: repoRoot, stdio: 'ignore' });
17
+ execSync('git config user.name "Test"', { cwd: repoRoot, stdio: 'ignore' });
18
+
19
+ fs.writeFileSync(path.join(repoRoot, 'README.md'), 'test', 'utf8');
20
+ execSync('git add README.md', { cwd: repoRoot, stdio: 'ignore' });
21
+ execSync('git commit -m "chore: init"', { cwd: repoRoot, stdio: 'ignore' });
22
+ });
23
+
24
+ afterEach(() => {
25
+ fs.rmSync(repoRoot, { recursive: true, force: true });
26
+ });
27
+
28
+ it('updates .AI_EVIDENCE.json in repo root even when executed from subdirectory', () => {
29
+ const cliPath = path.resolve(__dirname, '..', 'cli.js');
30
+ const output = execSync(`node ${cliPath} evidence:update`, {
31
+ cwd: subdir,
32
+ encoding: 'utf8',
33
+ env: {
34
+ ...process.env,
35
+ AUTO_EVIDENCE_TRIGGER: 'test',
36
+ AUTO_EVIDENCE_REASON: 'test',
37
+ AUTO_EVIDENCE_SUMMARY: 'test'
38
+ }
39
+ }).trim();
40
+
41
+ const evidencePath = path.join(repoRoot, '.AI_EVIDENCE.json');
42
+ expect(fs.realpathSync(output)).toBe(fs.realpathSync(evidencePath));
43
+ expect(fs.existsSync(evidencePath)).toBe(true);
44
+
45
+ const json = JSON.parse(fs.readFileSync(evidencePath, 'utf8'));
46
+ expect(typeof json.timestamp).toBe('string');
47
+ expect(json.timestamp.length).toBeGreaterThan(10);
48
+ });
49
+ });
@@ -121,21 +121,7 @@ const commands = {
121
121
  },
122
122
 
123
123
  ast: () => {
124
- const env = { ...process.env };
125
- const filteredArgs = [];
126
-
127
- for (const arg of args) {
128
- if (arg === '--staged') {
129
- env.STAGING_ONLY_MODE = '1';
130
- } else {
131
- filteredArgs.push(arg);
132
- }
133
- }
134
-
135
- execSync(
136
- `node ${path.join(HOOKS_ROOT, 'infrastructure/ast/ast-intelligence.js')} ${filteredArgs.join(' ')}`,
137
- { stdio: 'inherit', env }
138
- );
124
+ execSync(`node ${path.join(HOOKS_ROOT, 'infrastructure/ast/ast-intelligence.js')}`, { stdio: 'inherit' });
139
125
  },
140
126
 
141
127
  install: () => {
@@ -1,5 +1,3 @@
1
- const { ValidationError } = require('../errors');
2
-
3
1
  class DomainEvent {
4
2
  constructor(type, payload) {
5
3
  this.type = type;
@@ -9,8 +7,8 @@ class DomainEvent {
9
7
  }
10
8
 
11
9
  validate() {
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);
10
+ if (!this.type) throw new Error('Event type is required');
11
+ if (!this.payload) throw new Error('Event payload is required');
14
12
  return true;
15
13
  }
16
14
 
@@ -31,9 +29,7 @@ class EvidenceStaleEvent extends DomainEvent {
31
29
 
32
30
  validate() {
33
31
  super.validate();
34
- if (!this.payload.evidencePath) {
35
- throw new ValidationError('Evidence path is required', 'payload.evidencePath', this.payload.evidencePath);
36
- }
32
+ if (!this.payload.evidencePath) throw new Error('Evidence path is required');
37
33
  }
38
34
  }
39
35
 
@@ -45,12 +41,8 @@ class GitFlowViolationEvent extends DomainEvent {
45
41
 
46
42
  validate() {
47
43
  super.validate();
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
- }
44
+ if (!this.payload.branch) throw new Error('Branch name is required');
45
+ if (!this.payload.violation) throw new Error('Violation details are required');
54
46
  }
55
47
  }
56
48
 
@@ -62,9 +54,7 @@ class AstCriticalFoundEvent extends DomainEvent {
62
54
 
63
55
  validate() {
64
56
  super.validate();
65
- if (!Array.isArray(this.payload.findings)) {
66
- throw new ValidationError('Findings must be an array', 'payload.findings', this.payload.findings);
67
- }
57
+ if (!Array.isArray(this.payload.findings)) throw new Error('Findings must be an array');
68
58
  }
69
59
  }
70
60
 
@@ -85,8 +75,6 @@ class AnalysisCompletedEvent extends DomainEvent {
85
75
  class EventBus {
86
76
  constructor() {
87
77
  this.subscribers = new Map();
88
- this.processedIds = new Set();
89
- this.maxProcessed = 500;
90
78
  }
91
79
 
92
80
  subscribe(eventType, handler) {
@@ -106,25 +94,11 @@ class EventBus {
106
94
  }
107
95
 
108
96
  async publish(event) {
109
- if (event?.id && this.processedIds.has(event.id)) {
110
- return event;
111
- }
112
97
  const handlers = this.subscribers.get(event.type) || [];
113
98
  const wildcardHandlers = this.subscribers.get('*') || [];
114
99
  const allHandlers = [...handlers, ...wildcardHandlers];
115
100
 
116
101
  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
- }
128
102
  return event;
129
103
  }
130
104
 
@@ -40,9 +40,8 @@ class AndroidAnalysisOrchestrator {
40
40
  return 0.6745 * (x - med) / madValue;
41
41
  };
42
42
 
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);
43
+ const pOutlier = Number(process.env.AST_GODCLASS_P_OUTLIER || 90);
44
+ const pExtreme = Number(process.env.AST_GODCLASS_P_EXTREME || 97);
46
45
 
47
46
  const methods = this.godClassCandidates.map(c => c.methodsCount);
48
47
  const props = this.godClassCandidates.map(c => c.propertiesCount);
@@ -2,7 +2,6 @@
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");
6
5
 
7
6
  let SeverityEvaluator = null;
8
7
  let severityEvaluatorInstance = null;
@@ -20,7 +19,7 @@ function getSeverityEvaluator() {
20
19
  return severityEvaluatorInstance;
21
20
  }
22
21
 
23
- let INTELLIGENT_SEVERITY_ENABLED = env.getBool('INTELLIGENT_SEVERITY', false);
22
+ let INTELLIGENT_SEVERITY_ENABLED = process.env.INTELLIGENT_SEVERITY === 'true';
24
23
 
25
24
  /**
26
25
  * Get repository root directory (portable - dynamic detection)
@@ -180,18 +179,18 @@ function pushFinding(ruleId, severity, sf, node, message, findings, metrics = {}
180
179
  let mappedSeverity = mapToLevel(severity);
181
180
  const isCleanLayerMarkerRule = ruleId === 'backend.clean.domain' || ruleId === 'backend.clean.application' || ruleId === 'backend.clean.infrastructure' || ruleId === 'backend.clean.presentation';
182
181
  let isStrictCriticalRule = false;
183
- if (env.get('AUDIT_STRICT', '0') === '1' && !isCleanLayerMarkerRule) {
182
+ if (process.env.AUDIT_STRICT === '1' && !isCleanLayerMarkerRule) {
184
183
  const defaultStrictCriticalRegex = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|performance\\.|metrics\\.|observability\\.|validation\\.|i18n\\.|accessibility\\.|naming\\.)';
185
184
  const defaultStrictCriticalRegexLibrary = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|validation\\.|naming\\.)';
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)
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)
189
188
  : defaultStrictCriticalRegex);
190
189
  let strictRegex;
191
190
  try {
192
191
  strictRegex = new RegExp(strictRegexSource, 'i');
193
192
  } catch {
194
- strictRegex = new RegExp(env.getBool('AUDIT_LIBRARY', false) ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
193
+ strictRegex = new RegExp(process.env.AUDIT_LIBRARY === 'true' ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
195
194
  }
196
195
  isStrictCriticalRule = strictRegex.test(ruleId);
197
196
  if (isStrictCriticalRule) {
@@ -242,18 +241,18 @@ function pushFileFinding(ruleId, severity, filePath, line, column, message, find
242
241
  let mappedSeverity = mapToLevel(severity);
243
242
  const isCleanLayerMarkerRule = ruleId === 'backend.clean.domain' || ruleId === 'backend.clean.application' || ruleId === 'backend.clean.infrastructure' || ruleId === 'backend.clean.presentation';
244
243
  let isStrictCriticalRule = false;
245
- if (env.get('AUDIT_STRICT', '0') === '1' && !isCleanLayerMarkerRule) {
244
+ if (process.env.AUDIT_STRICT === '1' && !isCleanLayerMarkerRule) {
246
245
  const defaultStrictCriticalRegex = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|performance\\.|metrics\\.|observability\\.|validation\\.|i18n\\.|accessibility\\.|naming\\.)';
247
246
  const defaultStrictCriticalRegexLibrary = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|validation\\.|naming\\.)';
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)
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)
251
250
  : defaultStrictCriticalRegex);
252
251
  let strictRegex;
253
252
  try {
254
253
  strictRegex = new RegExp(strictRegexSource, 'i');
255
254
  } catch {
256
- strictRegex = new RegExp(env.getBool('AUDIT_LIBRARY', false) ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
255
+ strictRegex = new RegExp(process.env.AUDIT_LIBRARY === 'true' ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
257
256
  }
258
257
  isStrictCriticalRule = strictRegex.test(ruleId);
259
258
  if (isStrictCriticalRule) {
@@ -333,6 +332,15 @@ function mapToLevel(severity) {
333
332
  function platformOf(filePath) {
334
333
  const p = filePath.replace(/\\/g, "/");
335
334
 
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
+
336
344
  if (p.includes("/apps/backend/") || p.includes("apps/backend/")) return "backend";
337
345
  if (p.includes("/apps/admin/") || p.includes("/admin-dashboard/")) return "frontend";
338
346
  if (p.includes("/apps/mobile-ios/") || p.includes("/apps/ios/")) return "ios";
@@ -1,7 +1,6 @@
1
1
 
2
2
  const path = require("path");
3
3
  const fs = require("fs");
4
- const env = require("../../config/env");
5
4
 
6
5
  const astModulesPath = __dirname;
7
6
  const { createProject, platformOf, mapToLevel } = require(path.join(astModulesPath, "ast-core"));
@@ -28,7 +27,13 @@ async function runASTIntelligence() {
28
27
  const { getRepoRoot } = require('./ast-core');
29
28
  const root = getRepoRoot();
30
29
 
31
- const allFiles = listSourceFiles(root);
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
+ });
32
37
 
33
38
  const project = createProject(allFiles);
34
39
  const findings = [];
@@ -70,9 +75,9 @@ async function runASTIntelligence() {
70
75
  }
71
76
 
72
77
  function runProjectHardcodedThresholdAudit(root, allFiles, findings) {
73
- if (env.get('AST_INSIGHTS', '0') !== '1') return;
78
+ if (process.env.AST_INSIGHTS !== '1') return;
74
79
 
75
- const maxFindings = env.getNumber('AST_INSIGHTS_PROJECT_MAX', 200);
80
+ const maxFindings = Number(process.env.AST_INSIGHTS_PROJECT_MAX || 200);
76
81
  if (!Number.isFinite(maxFindings) || maxFindings <= 0) return;
77
82
 
78
83
  const isExcludedPath = (filePath) => {
@@ -155,7 +160,7 @@ function runProjectHardcodedThresholdAudit(root, allFiles, findings) {
155
160
  }
156
161
 
157
162
  function runHardcodedThresholdAudit(root, findings) {
158
- if (env.get('AST_INSIGHTS', '0') !== '1') return;
163
+ if (process.env.AST_INSIGHTS !== '1') return;
159
164
 
160
165
  const ruleDirs = [
161
166
  path.join(root, 'infrastructure', 'ast'),
@@ -312,7 +317,7 @@ async function runPlatformAnalysis(project, findings, context) {
312
317
  }
313
318
  } catch (error) {
314
319
  console.error(`[ERROR] Error processing platform ${platform}:`, error.message);
315
- if (env.getBool('DEBUG_AST', false)) {
320
+ if (process.env.DEBUG_AST) {
316
321
  console.error(error.stack);
317
322
  }
318
323
  }
@@ -371,7 +376,7 @@ function generateOutput(findings, context, project, root) {
371
376
  * Save detailed JSON report
372
377
  */
373
378
  function saveDetailedReport(findings, levelTotals, platformTotals, project, root) {
374
- const outDir = env.get('AUDIT_TMP', path.join(root, ".audit_tmp"));
379
+ const outDir = process.env.AUDIT_TMP || path.join(root, ".audit_tmp");
375
380
  try {
376
381
  fs.mkdirSync(outDir, { recursive: true });
377
382
 
@@ -527,7 +532,7 @@ function checkForMigrations(root) {
527
532
  * List source files recursively
528
533
  */
529
534
  function listSourceFiles(root) {
530
- if (env.get('STAGING_ONLY_MODE', '0') === "1") {
535
+ if (process.env.STAGING_ONLY_MODE === "1") {
531
536
  const { execSync } = require("child_process");
532
537
  try {
533
538
  const allStaged = execSync("git diff --cached --name-only --diff-filter=ACM", {
@@ -595,6 +600,11 @@ function listSourceFiles(root) {
595
600
  function shouldIgnore(file) {
596
601
  const p = file.replace(/\\/g, "/");
597
602
  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;
598
608
  if (p.includes("/.cursor/")) return true;
599
609
  if (/\.bak/i.test(p)) return true;
600
610
  if (p.includes("/.next/")) return true;
@@ -1,6 +1,5 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const env = require('../../../../config/env');
4
3
 
5
4
  class BackendPatternDetector {
6
5
  constructor(projectRoot) {
@@ -12,7 +11,7 @@ class BackendPatternDetector {
12
11
  const fullPath = path.join(this.projectRoot, relativePath);
13
12
  return fs.readFileSync(fullPath, 'utf-8');
14
13
  } catch (error) {
15
- if (env.getBool('DEBUG', false)) {
14
+ if (process.env.DEBUG) {
16
15
  console.debug(`[BackendPatternDetector] Failed to read file ${relativePath}: ${error.message}`);
17
16
  }
18
17
  return '';
@@ -1,13 +1,11 @@
1
+
1
2
  const path = require('path');
2
- const env = require('../../../config/env');
3
3
  const {
4
- platformOf,
5
4
  pushFinding,
6
- pushFileFinding,
7
5
  mapToLevel,
8
- positionOf,
9
- isTestFile,
10
6
  SyntaxKind,
7
+ isTestFile,
8
+ platformOf,
11
9
  hasImport,
12
10
  hasDecorator,
13
11
  findStringLiterals,
@@ -121,7 +119,7 @@ function runBackendIntelligence(project, findings, platform) {
121
119
  const filePath = sf.getFilePath();
122
120
  if (platformOf(filePath) !== 'backend') return;
123
121
  if (/\/ast-[^/]+\.js$/.test(filePath)) return;
124
- if (!env.getBool('AUDIT_LIBRARY', false)) {
122
+ if (process.env.AUDIT_LIBRARY !== 'true') {
125
123
  if (/scripts\/hooks-system\/infrastructure\/ast\//i.test(filePath) || /\/infrastructure\/ast\//i.test(filePath)) return;
126
124
  }
127
125
  if (isTestFile(filePath)) return;
@@ -146,8 +144,8 @@ function runBackendIntelligence(project, findings, platform) {
146
144
 
147
145
  if (metrics.length === 0) return null;
148
146
 
149
- const pOutlier = env.getNumber('AST_GODCLASS_P_OUTLIER', 90);
150
- const pExtreme = env.getNumber('AST_GODCLASS_P_EXTREME', 97);
147
+ const pOutlier = Number(process.env.AST_GODCLASS_P_OUTLIER || 90);
148
+ const pExtreme = Number(process.env.AST_GODCLASS_P_EXTREME || 97);
151
149
 
152
150
  const methods = metrics.map(m => m.methodsCount);
153
151
  const props = metrics.map(m => m.propertiesCount);
@@ -204,12 +202,12 @@ function runBackendIntelligence(project, findings, platform) {
204
202
  if (platformOf(filePath) !== "backend") return;
205
203
 
206
204
  if (/\/ast-[^/]+\.js$/.test(filePath)) return;
207
- if (!env.getBool('AUDIT_LIBRARY', false)) {
205
+ if (process.env.AUDIT_LIBRARY !== 'true') {
208
206
  if (/scripts\/hooks-system\/infrastructure\/ast\//i.test(filePath) || /\/infrastructure\/ast\//i.test(filePath)) return;
209
207
  }
210
208
 
211
209
  const fullText = sf.getFullText();
212
- const insightsEnabled = env.get('AST_INSIGHTS', '0') === '1';
210
+ const insightsEnabled = process.env.AST_INSIGHTS === '1';
213
211
  const isSpecFile = /\.(spec|test)\.(ts|tsx|js|jsx)$/.test(filePath);
214
212
  const secretPattern = /(password|secret|key|token)\s*[:=]\s*['"`]([^'"]{8,})['"`]/gi;
215
213
  const matches = Array.from(fullText.matchAll(secretPattern));