pumuki-ast-hooks 5.3.18 → 5.3.20

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 (91) hide show
  1. package/docs/VIOLATIONS_RESOLUTION_PLAN.md +39 -37
  2. package/package.json +8 -2
  3. package/scripts/hooks-system/application/CompositionRoot.js +24 -73
  4. package/scripts/hooks-system/application/services/AutonomousOrchestrator.js +18 -0
  5. package/scripts/hooks-system/application/services/ContextDetectionEngine.js +58 -0
  6. package/scripts/hooks-system/application/services/DynamicRulesLoader.js +12 -2
  7. package/scripts/hooks-system/application/services/GitFlowService.js +80 -0
  8. package/scripts/hooks-system/application/services/GitTreeState.js +143 -13
  9. package/scripts/hooks-system/application/services/HookSystemScheduler.js +47 -0
  10. package/scripts/hooks-system/application/services/IntelligentCommitAnalyzer.js +25 -0
  11. package/scripts/hooks-system/application/services/IntelligentGitTreeMonitor.js +11 -0
  12. package/scripts/hooks-system/application/services/PlatformAnalysisService.js +19 -0
  13. package/scripts/hooks-system/application/services/PlatformDetectionService.js +19 -0
  14. package/scripts/hooks-system/application/services/PlaybookRunner.js +22 -1
  15. package/scripts/hooks-system/application/services/PredictiveHookAdvisor.js +19 -0
  16. package/scripts/hooks-system/application/services/RealtimeGuardPlugin.js +25 -0
  17. package/scripts/hooks-system/application/services/RealtimeGuardService.js +41 -84
  18. package/scripts/hooks-system/application/services/SmartDirtyTreeAnalyzer.js +11 -0
  19. package/scripts/hooks-system/application/services/commit/CommitMessageGenerator.js +11 -0
  20. package/scripts/hooks-system/application/services/commit/FeatureDetector.js +11 -0
  21. package/scripts/hooks-system/application/services/evidence/EvidenceContextManager.js +25 -0
  22. package/scripts/hooks-system/application/services/guard/GuardAutoManagerService.js +21 -31
  23. package/scripts/hooks-system/application/services/guard/GuardConfig.js +18 -15
  24. package/scripts/hooks-system/application/services/guard/GuardEventLogger.js +11 -0
  25. package/scripts/hooks-system/application/services/guard/GuardHealthReminder.js +26 -0
  26. package/scripts/hooks-system/application/services/guard/GuardHeartbeatMonitor.js +20 -6
  27. package/scripts/hooks-system/application/services/guard/GuardLockManager.js +11 -0
  28. package/scripts/hooks-system/application/services/guard/GuardMonitorLoop.js +25 -0
  29. package/scripts/hooks-system/application/services/guard/GuardNotificationHandler.js +11 -0
  30. package/scripts/hooks-system/application/services/guard/GuardProcessManager.js +10 -28
  31. package/scripts/hooks-system/application/services/guard/GuardRecoveryService.js +11 -0
  32. package/scripts/hooks-system/application/services/installation/ConfigurationGeneratorService.js +18 -0
  33. package/scripts/hooks-system/application/services/installation/FileSystemInstallerService.js +18 -0
  34. package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +18 -3
  35. package/scripts/hooks-system/application/services/installation/HookInstaller.js +19 -0
  36. package/scripts/hooks-system/application/services/installation/IdeIntegrationService.js +11 -0
  37. package/scripts/hooks-system/application/services/installation/InstallService.js +25 -1
  38. package/scripts/hooks-system/application/services/installation/McpConfigurator.js +19 -2
  39. package/scripts/hooks-system/application/services/installation/PlatformDetectorService.js +11 -0
  40. package/scripts/hooks-system/application/services/installation/VSCodeTaskConfigurator.js +11 -0
  41. package/scripts/hooks-system/application/services/logging/AuditLogger.js +90 -1
  42. package/scripts/hooks-system/application/services/logging/UnifiedLogger.js +15 -13
  43. package/scripts/hooks-system/application/services/monitoring/ActivityMonitor.js +33 -0
  44. package/scripts/hooks-system/application/services/monitoring/AstMonitor.js +27 -0
  45. package/scripts/hooks-system/application/services/monitoring/DevDocsMonitor.js +26 -0
  46. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitor.js +19 -0
  47. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +27 -6
  48. package/scripts/hooks-system/application/services/monitoring/GitTreeMonitor.js +28 -0
  49. package/scripts/hooks-system/application/services/monitoring/GitTreeMonitorService.js +26 -0
  50. package/scripts/hooks-system/application/services/monitoring/HealthCheckProviders.js +4 -0
  51. package/scripts/hooks-system/application/services/monitoring/HealthCheckService.js +25 -0
  52. package/scripts/hooks-system/application/services/monitoring/HeartbeatMonitorService.js +26 -0
  53. package/scripts/hooks-system/application/services/monitoring/TokenMonitor.js +26 -0
  54. package/scripts/hooks-system/application/services/notification/MacNotificationSender.js +11 -0
  55. package/scripts/hooks-system/application/services/notification/NotificationCenterService.js +18 -0
  56. package/scripts/hooks-system/application/services/notification/NotificationDispatcher.js +11 -0
  57. package/scripts/hooks-system/application/services/notification/components/NotificationCooldownManager.js +18 -0
  58. package/scripts/hooks-system/application/services/notification/components/NotificationDeduplicator.js +18 -0
  59. package/scripts/hooks-system/application/services/notification/components/NotificationQueue.js +11 -0
  60. package/scripts/hooks-system/application/services/notification/components/NotificationRetryExecutor.js +20 -0
  61. package/scripts/hooks-system/application/services/platform/PlatformHeuristics.js +19 -0
  62. package/scripts/hooks-system/application/services/recovery/AutoRecoveryManager.js +19 -0
  63. package/scripts/hooks-system/application/services/smart-commit/CommitMessageSuggester.js +11 -0
  64. package/scripts/hooks-system/application/services/smart-commit/FileContextGrouper.js +19 -0
  65. package/scripts/hooks-system/application/services/smart-commit/SmartCommitSummaryBuilder.js +4 -0
  66. package/scripts/hooks-system/application/services/token/CursorTokenService.js +20 -0
  67. package/scripts/hooks-system/application/services/token/TokenMetricsService.js +11 -13
  68. package/scripts/hooks-system/application/services/token/TokenMonitorService.js +19 -0
  69. package/scripts/hooks-system/application/services/token/TokenStatusReporter.js +12 -0
  70. package/scripts/hooks-system/bin/__tests__/evidence-update.spec.js +49 -0
  71. package/scripts/hooks-system/bin/cli.js +1 -15
  72. package/scripts/hooks-system/config/project.config.json +1 -1
  73. package/scripts/hooks-system/domain/events/index.js +24 -31
  74. package/scripts/hooks-system/domain/exceptions/index.js +87 -0
  75. package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidAnalysisOrchestrator.js +2 -3
  76. package/scripts/hooks-system/infrastructure/ast/ast-core.js +20 -12
  77. package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +18 -8
  78. package/scripts/hooks-system/infrastructure/ast/backend/analyzers/BackendPatternDetector.js +1 -2
  79. package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +14 -18
  80. package/scripts/hooks-system/infrastructure/ast/frontend/ast-frontend.js +196 -196
  81. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/__tests__/iOSASTIntelligentAnalyzer.spec.js +66 -0
  82. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +2 -3
  83. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSArchitectureRules.js +24 -86
  84. package/scripts/hooks-system/infrastructure/config/config.js +5 -0
  85. package/scripts/hooks-system/infrastructure/hooks/skill-activation-prompt.js +2 -3
  86. package/scripts/hooks-system/infrastructure/logging/UnifiedLoggerFactory.js +5 -35
  87. package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +16 -86
  88. package/scripts/hooks-system/infrastructure/shell/orchestrators/audit-orchestrator.sh +54 -92
  89. package/scripts/hooks-system/infrastructure/telemetry/metric-scope.js +98 -0
  90. package/scripts/hooks-system/infrastructure/telemetry/metrics-server.js +2 -51
  91. package/scripts/hooks-system/infrastructure/validators/enforce-english-literals.js +8 -6
@@ -1,5 +1,9 @@
1
1
  const CursorTokenRepository = require('../../../infrastructure/repositories/CursorTokenRepository');
2
2
 
3
+ const {
4
+ createMetricScope: createMetricScope
5
+ } = require('../../../infrastructure/telemetry/metric-scope');
6
+
3
7
  class CursorTokenService {
4
8
  constructor({
5
9
  cursorTokenRepository = null,
@@ -10,6 +14,12 @@ class CursorTokenService {
10
14
  fetchImpl,
11
15
  logger = console
12
16
  } = {}) {
17
+ const m_constructor = createMetricScope({
18
+ hook: 'cursor_token_service',
19
+ operation: 'constructor'
20
+ });
21
+
22
+ m_constructor.started();
13
23
  this.logger = logger;
14
24
  this.repository = cursorTokenRepository || new CursorTokenRepository({
15
25
  repoRoot,
@@ -19,24 +29,34 @@ class CursorTokenService {
19
29
  fetchImpl,
20
30
  logger
21
31
  });
32
+ m_constructor.success();
22
33
  }
23
34
 
24
35
  async getCurrentUsage() {
36
+ const m_get_current_usage = createMetricScope({
37
+ hook: 'cursor_token_service',
38
+ operation: 'get_current_usage'
39
+ });
40
+
41
+ m_get_current_usage.started();
25
42
  // Strategy: First try API (most accurate), then File (fallback/offline)
26
43
 
27
44
  const apiUsage = await this.repository.getUsageFromApi();
28
45
  if (apiUsage) {
29
46
  this.logger.debug?.('CURSOR_SERVICE_USING_API', { usage: apiUsage });
47
+ m_get_current_usage.success();
30
48
  return apiUsage;
31
49
  }
32
50
 
33
51
  const fileUsage = await this.repository.getUsageFromFile();
34
52
  if (fileUsage) {
35
53
  this.logger.debug?.('CURSOR_SERVICE_USING_FILE', { usage: fileUsage });
54
+ m_get_current_usage.success();
36
55
  return fileUsage;
37
56
  }
38
57
 
39
58
  this.logger.warn?.('CURSOR_SERVICE_NO_DATA_AVAILABLE');
59
+ m_get_current_usage.success();
40
60
  return null;
41
61
  }
42
62
  }
@@ -1,14 +1,22 @@
1
1
  const { execSync } = require('child_process');
2
2
 
3
- // Import recordMetric for prometheus metrics
4
- const { recordMetric } = require('../../../infrastructure/telemetry/metrics-logger');
3
+ const {
4
+ createMetricScope: createMetricScope
5
+ } = require('../../../infrastructure/telemetry/metric-scope');
5
6
 
6
7
  class TokenMetricsService {
7
8
  constructor(cursorTokenService, thresholds, logger) {
9
+ const m_constructor = createMetricScope({
10
+ hook: 'token_metrics_service',
11
+ operation: 'constructor'
12
+ });
13
+
14
+ m_constructor.started();
8
15
  this.cursorTokenService = cursorTokenService;
9
16
  this.thresholds = thresholds;
10
17
  this.logger = logger;
11
18
  this.repoRoot = process.cwd();
19
+ m_constructor.success();
12
20
  }
13
21
 
14
22
  async collectMetrics(fallbackEstimator) {
@@ -57,8 +65,7 @@ class TokenMetricsService {
57
65
  if (untrusted) {
58
66
  level = 'ok';
59
67
  }
60
- const env = require('../../config/env');
61
- const forceLevel = (env.get('TOKEN_MONITOR_FORCE_LEVEL', '') || '').toLowerCase();
68
+ const forceLevel = (process.env.TOKEN_MONITOR_FORCE_LEVEL || '').toLowerCase();
62
69
  if (forceLevel === 'warning' || forceLevel === 'critical' || forceLevel === 'ok') {
63
70
  level = forceLevel;
64
71
  }
@@ -79,15 +86,6 @@ class TokenMetricsService {
79
86
  this.logger.debug('TOKEN_MONITOR_METRICS', metrics);
80
87
  }
81
88
 
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
89
  return metrics;
92
90
  }
93
91
 
@@ -2,6 +2,10 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const { execSync } = require('child_process');
4
4
 
5
+ const {
6
+ createMetricScope: createMetricScope
7
+ } = require('../../../infrastructure/telemetry/metric-scope');
8
+
5
9
  const fsPromises = fs.promises;
6
10
  const CursorTokenService = require('./CursorTokenService');
7
11
  const NotificationCenterService = require('../notification/NotificationCenterService');
@@ -21,6 +25,12 @@ class TokenMonitorService {
21
25
  fallbackEstimator = null,
22
26
  cursorTokenService = null
23
27
  } = {}) {
28
+ const m_constructor = createMetricScope({
29
+ hook: 'token_monitor_service',
30
+ operation: 'constructor'
31
+ });
32
+
33
+ m_constructor.started();
24
34
  this.repoRoot = repoRoot;
25
35
  this.dataFile = dataFile || path.join(this.repoRoot, '.audit_tmp', 'token-usage.jsonl');
26
36
  this.stateFile = stateFile || path.join(this.repoRoot, '.AI_TOKEN_STATUS.txt');
@@ -47,9 +57,16 @@ class TokenMonitorService {
47
57
 
48
58
  this.metricsService = new TokenMetricsService(this.cursorTokenService, this.thresholds, this.logger);
49
59
  this.statusReporter = new TokenStatusReporter(this.stateFile);
60
+ m_constructor.success();
50
61
  }
51
62
 
52
63
  async run() {
64
+ const m_run = createMetricScope({
65
+ hook: 'token_monitor_service',
66
+ operation: 'run'
67
+ });
68
+
69
+ m_run.started();
53
70
  // Collect metrics
54
71
  const metrics = await this.metricsService.collectMetrics(this.fallbackEstimator);
55
72
 
@@ -59,6 +76,8 @@ class TokenMonitorService {
59
76
  // Notify
60
77
  await this.emitNotification(metrics);
61
78
 
79
+ m_run.success();
80
+
62
81
  return metrics;
63
82
  }
64
83
 
@@ -1,9 +1,21 @@
1
1
  const fs = require('fs');
2
+
3
+ const {
4
+ createMetricScope: createMetricScope
5
+ } = require('../../../infrastructure/telemetry/metric-scope');
6
+
2
7
  const fsPromises = fs.promises;
3
8
 
4
9
  class TokenStatusReporter {
5
10
  constructor(stateFile) {
11
+ const m_constructor = createMetricScope({
12
+ hook: 'token_status_reporter',
13
+ operation: 'constructor'
14
+ });
15
+
16
+ m_constructor.started();
6
17
  this.stateFile = stateFile;
18
+ m_constructor.success();
7
19
  }
8
20
 
9
21
  async writeStatusFile(metrics) {
@@ -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: () => {
@@ -5,7 +5,7 @@
5
5
  "platforms": [
6
6
  "backend"
7
7
  ],
8
- "created": "2025-12-25T22:02:53.249Z"
8
+ "created": "2025-12-31T07:05:44.501Z"
9
9
  },
10
10
  "architecture": {
11
11
  "pattern": "FEATURE_FIRST_CLEAN_DDD",
@@ -1,7 +1,13 @@
1
- const { ValidationError } = require('../errors');
1
+ const {
2
+ ValidationException,
3
+ BadRequestException,
4
+ InternalServerException
5
+ } = require('../exceptions');
2
6
 
3
7
  class DomainEvent {
4
8
  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' });
5
11
  this.type = type;
6
12
  this.payload = payload;
7
13
  this.timestamp = new Date().toISOString();
@@ -9,8 +15,8 @@ class DomainEvent {
9
15
  }
10
16
 
11
17
  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);
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' });
14
20
  return true;
15
21
  }
16
22
 
@@ -31,9 +37,7 @@ class EvidenceStaleEvent extends DomainEvent {
31
37
 
32
38
  validate() {
33
39
  super.validate();
34
- if (!this.payload.evidencePath) {
35
- throw new ValidationError('Evidence path is required', 'payload.evidencePath', this.payload.evidencePath);
36
- }
40
+ if (!this.payload.evidencePath) throw new ValidationException('Evidence path is required', { field: 'evidencePath' });
37
41
  }
38
42
  }
39
43
 
@@ -45,12 +49,8 @@ class GitFlowViolationEvent extends DomainEvent {
45
49
 
46
50
  validate() {
47
51
  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
- }
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' });
54
54
  }
55
55
  }
56
56
 
@@ -62,9 +62,7 @@ class AstCriticalFoundEvent extends DomainEvent {
62
62
 
63
63
  validate() {
64
64
  super.validate();
65
- if (!Array.isArray(this.payload.findings)) {
66
- throw new ValidationError('Findings must be an array', 'payload.findings', this.payload.findings);
67
- }
65
+ if (!Array.isArray(this.payload.findings)) throw new ValidationException('Findings must be an array', { field: 'findings' });
68
66
  }
69
67
  }
70
68
 
@@ -73,6 +71,12 @@ class PreCommitBlockedEvent extends DomainEvent {
73
71
  super('PRE_COMMIT_BLOCKED', { reason, violations });
74
72
  this.validate();
75
73
  }
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
+ }
76
80
  }
77
81
 
78
82
  class AnalysisCompletedEvent extends DomainEvent {
@@ -80,13 +84,16 @@ class AnalysisCompletedEvent extends DomainEvent {
80
84
  super('ANALYSIS_COMPLETED', summary);
81
85
  this.validate();
82
86
  }
87
+
88
+ validate() {
89
+ super.validate();
90
+ if (!this.payload) throw new ValidationException('Summary is required', { field: 'summary' });
91
+ }
83
92
  }
84
93
 
85
94
  class EventBus {
86
95
  constructor() {
87
96
  this.subscribers = new Map();
88
- this.processedIds = new Set();
89
- this.maxProcessed = 500;
90
97
  }
91
98
 
92
99
  subscribe(eventType, handler) {
@@ -106,25 +113,11 @@ class EventBus {
106
113
  }
107
114
 
108
115
  async publish(event) {
109
- if (event?.id && this.processedIds.has(event.id)) {
110
- return event;
111
- }
112
116
  const handlers = this.subscribers.get(event.type) || [];
113
117
  const wildcardHandlers = this.subscribers.get('*') || [];
114
118
  const allHandlers = [...handlers, ...wildcardHandlers];
115
119
 
116
120
  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
121
  return event;
129
122
  }
130
123
 
@@ -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,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 '';