pumuki-ast-hooks 5.3.19 → 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.
- package/docs/VIOLATIONS_RESOLUTION_PLAN.md +38 -34
- package/package.json +7 -1
- package/scripts/hooks-system/application/services/AutonomousOrchestrator.js +18 -0
- package/scripts/hooks-system/application/services/ContextDetectionEngine.js +58 -0
- package/scripts/hooks-system/application/services/DynamicRulesLoader.js +11 -0
- package/scripts/hooks-system/application/services/GitFlowService.js +80 -0
- package/scripts/hooks-system/application/services/GitTreeState.js +4 -0
- package/scripts/hooks-system/application/services/HookSystemScheduler.js +4 -0
- package/scripts/hooks-system/application/services/IntelligentCommitAnalyzer.js +25 -0
- package/scripts/hooks-system/application/services/IntelligentGitTreeMonitor.js +11 -0
- package/scripts/hooks-system/application/services/PlatformAnalysisService.js +19 -0
- package/scripts/hooks-system/application/services/PlatformDetectionService.js +19 -0
- package/scripts/hooks-system/application/services/PlaybookRunner.js +22 -1
- package/scripts/hooks-system/application/services/PredictiveHookAdvisor.js +19 -0
- package/scripts/hooks-system/application/services/RealtimeGuardPlugin.js +25 -0
- package/scripts/hooks-system/application/services/RealtimeGuardService.js +27 -0
- package/scripts/hooks-system/application/services/SmartDirtyTreeAnalyzer.js +11 -0
- package/scripts/hooks-system/application/services/commit/CommitMessageGenerator.js +11 -0
- package/scripts/hooks-system/application/services/commit/FeatureDetector.js +11 -0
- package/scripts/hooks-system/application/services/evidence/EvidenceContextManager.js +25 -0
- package/scripts/hooks-system/application/services/guard/GuardAutoManagerService.js +19 -0
- package/scripts/hooks-system/application/services/guard/GuardConfig.js +11 -0
- package/scripts/hooks-system/application/services/guard/GuardEventLogger.js +11 -0
- package/scripts/hooks-system/application/services/guard/GuardHealthReminder.js +26 -0
- package/scripts/hooks-system/application/services/guard/GuardHeartbeatMonitor.js +11 -0
- package/scripts/hooks-system/application/services/guard/GuardLockManager.js +11 -0
- package/scripts/hooks-system/application/services/guard/GuardMonitorLoop.js +25 -0
- package/scripts/hooks-system/application/services/guard/GuardNotificationHandler.js +11 -0
- package/scripts/hooks-system/application/services/guard/GuardProcessManager.js +11 -0
- package/scripts/hooks-system/application/services/guard/GuardRecoveryService.js +11 -0
- package/scripts/hooks-system/application/services/installation/ConfigurationGeneratorService.js +18 -0
- package/scripts/hooks-system/application/services/installation/FileSystemInstallerService.js +18 -0
- package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +18 -0
- package/scripts/hooks-system/application/services/installation/HookInstaller.js +19 -0
- package/scripts/hooks-system/application/services/installation/IdeIntegrationService.js +11 -0
- package/scripts/hooks-system/application/services/installation/InstallService.js +25 -1
- package/scripts/hooks-system/application/services/installation/McpConfigurator.js +18 -0
- package/scripts/hooks-system/application/services/installation/PlatformDetectorService.js +11 -0
- package/scripts/hooks-system/application/services/installation/VSCodeTaskConfigurator.js +11 -0
- package/scripts/hooks-system/application/services/logging/AuditLogger.js +4 -0
- package/scripts/hooks-system/application/services/logging/UnifiedLogger.js +11 -0
- package/scripts/hooks-system/application/services/monitoring/ActivityMonitor.js +33 -0
- package/scripts/hooks-system/application/services/monitoring/AstMonitor.js +27 -0
- package/scripts/hooks-system/application/services/monitoring/DevDocsMonitor.js +26 -0
- package/scripts/hooks-system/application/services/monitoring/EvidenceMonitor.js +18 -0
- package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +25 -0
- package/scripts/hooks-system/application/services/monitoring/GitTreeMonitor.js +28 -0
- package/scripts/hooks-system/application/services/monitoring/GitTreeMonitorService.js +26 -0
- package/scripts/hooks-system/application/services/monitoring/HealthCheckProviders.js +4 -0
- package/scripts/hooks-system/application/services/monitoring/HealthCheckService.js +25 -0
- package/scripts/hooks-system/application/services/monitoring/HeartbeatMonitorService.js +26 -0
- package/scripts/hooks-system/application/services/monitoring/TokenMonitor.js +26 -0
- package/scripts/hooks-system/application/services/notification/MacNotificationSender.js +11 -0
- package/scripts/hooks-system/application/services/notification/NotificationCenterService.js +18 -0
- package/scripts/hooks-system/application/services/notification/NotificationDispatcher.js +11 -0
- package/scripts/hooks-system/application/services/notification/components/NotificationCooldownManager.js +18 -0
- package/scripts/hooks-system/application/services/notification/components/NotificationDeduplicator.js +18 -0
- package/scripts/hooks-system/application/services/notification/components/NotificationQueue.js +11 -0
- package/scripts/hooks-system/application/services/notification/components/NotificationRetryExecutor.js +20 -0
- package/scripts/hooks-system/application/services/platform/PlatformHeuristics.js +19 -0
- package/scripts/hooks-system/application/services/recovery/AutoRecoveryManager.js +19 -0
- package/scripts/hooks-system/application/services/smart-commit/CommitMessageSuggester.js +11 -0
- package/scripts/hooks-system/application/services/smart-commit/FileContextGrouper.js +19 -0
- package/scripts/hooks-system/application/services/smart-commit/SmartCommitSummaryBuilder.js +4 -0
- package/scripts/hooks-system/application/services/token/CursorTokenService.js +20 -0
- package/scripts/hooks-system/application/services/token/TokenMetricsService.js +11 -0
- package/scripts/hooks-system/application/services/token/TokenMonitorService.js +19 -0
- package/scripts/hooks-system/application/services/token/TokenStatusReporter.js +12 -0
- package/scripts/hooks-system/config/project.config.json +1 -1
- package/scripts/hooks-system/domain/events/index.js +25 -6
- package/scripts/hooks-system/domain/exceptions/index.js +87 -0
- package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +7 -9
- package/scripts/hooks-system/infrastructure/config/config.js +5 -0
- package/scripts/hooks-system/infrastructure/shell/orchestrators/audit-orchestrator.sh +54 -92
- package/scripts/hooks-system/infrastructure/telemetry/metric-scope.js +98 -0
|
@@ -1,12 +1,29 @@
|
|
|
1
|
+
const {
|
|
2
|
+
createMetricScope: createMetricScope
|
|
3
|
+
} = require('../../../infrastructure/telemetry/metric-scope');
|
|
4
|
+
|
|
1
5
|
class NotificationRetryExecutor {
|
|
2
6
|
constructor(sender, config = {}, logger = null) {
|
|
7
|
+
const m_constructor = createMetricScope({
|
|
8
|
+
hook: 'notification_retry_executor',
|
|
9
|
+
operation: 'constructor'
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
m_constructor.started();
|
|
3
13
|
this.sender = sender;
|
|
4
14
|
this.maxRetries = config.maxRetries || 2;
|
|
5
15
|
this.retryDelayMs = config.retryDelayMs || 1000;
|
|
6
16
|
this.logger = logger;
|
|
17
|
+
m_constructor.success();
|
|
7
18
|
}
|
|
8
19
|
|
|
9
20
|
async execute(notification, options = {}) {
|
|
21
|
+
const m_execute = createMetricScope({
|
|
22
|
+
hook: 'notification_retry_executor',
|
|
23
|
+
operation: 'execute'
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
m_execute.started();
|
|
10
27
|
const currentRetries = notification.retries || 0;
|
|
11
28
|
const remainingRetries = currentRetries < this.maxRetries ? this.maxRetries - currentRetries : 0;
|
|
12
29
|
|
|
@@ -21,6 +38,7 @@ class NotificationRetryExecutor {
|
|
|
21
38
|
if (attempt > 0) {
|
|
22
39
|
this.logRetrySuccess(notification, attempt);
|
|
23
40
|
}
|
|
41
|
+
m_execute.success();
|
|
24
42
|
return { success: true, attempts: attempt + 1 };
|
|
25
43
|
}
|
|
26
44
|
} catch (error) {
|
|
@@ -28,6 +46,8 @@ class NotificationRetryExecutor {
|
|
|
28
46
|
}
|
|
29
47
|
}
|
|
30
48
|
|
|
49
|
+
m_execute.success();
|
|
50
|
+
|
|
31
51
|
return { success: false, attempts: remainingRetries + 1 };
|
|
32
52
|
}
|
|
33
53
|
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
|
|
4
|
+
const {
|
|
5
|
+
createMetricScope: createMetricScope
|
|
6
|
+
} = require('../../../infrastructure/telemetry/metric-scope');
|
|
7
|
+
|
|
4
8
|
class PlatformHeuristics {
|
|
5
9
|
constructor(platformDetector) {
|
|
10
|
+
const m_constructor = createMetricScope({
|
|
11
|
+
hook: 'platform_heuristics',
|
|
12
|
+
operation: 'constructor'
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
m_constructor.started();
|
|
6
16
|
this.platformDetector = platformDetector;
|
|
17
|
+
m_constructor.success();
|
|
7
18
|
}
|
|
8
19
|
|
|
9
20
|
detectFromASTSystemFiles(files) {
|
|
@@ -129,6 +140,12 @@ class PlatformHeuristics {
|
|
|
129
140
|
}
|
|
130
141
|
|
|
131
142
|
getPlatformFrequencyInHistory(platform, commits) {
|
|
143
|
+
const m_get_platform_frequency_in_history = createMetricScope({
|
|
144
|
+
hook: 'platform_heuristics',
|
|
145
|
+
operation: 'get_platform_frequency_in_history'
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
m_get_platform_frequency_in_history.started();
|
|
132
149
|
if (!commits || commits.length === 0) return 0;
|
|
133
150
|
|
|
134
151
|
const platformCommits = commits.filter(commit =>
|
|
@@ -137,6 +154,8 @@ class PlatformHeuristics {
|
|
|
137
154
|
)
|
|
138
155
|
);
|
|
139
156
|
|
|
157
|
+
m_get_platform_frequency_in_history.success();
|
|
158
|
+
|
|
140
159
|
return platformCommits.length / commits.length;
|
|
141
160
|
}
|
|
142
161
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
|
|
3
|
+
const {
|
|
4
|
+
createMetricScope: createMetricScope
|
|
5
|
+
} = require('../../../infrastructure/telemetry/metric-scope');
|
|
6
|
+
|
|
3
7
|
class AutoRecoveryManager {
|
|
4
8
|
constructor({
|
|
5
9
|
repoRoot = process.cwd(),
|
|
@@ -11,6 +15,12 @@ class AutoRecoveryManager {
|
|
|
11
15
|
baseBackoffMs = 2000,
|
|
12
16
|
jitter = 0.25
|
|
13
17
|
} = {}) {
|
|
18
|
+
const m_constructor = createMetricScope({
|
|
19
|
+
hook: 'auto_recovery_manager',
|
|
20
|
+
operation: 'constructor'
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
m_constructor.started();
|
|
14
24
|
this.repoRoot = repoRoot;
|
|
15
25
|
this.logger = logger || console;
|
|
16
26
|
this.notificationCenter = notificationCenter;
|
|
@@ -23,14 +33,23 @@ class AutoRecoveryManager {
|
|
|
23
33
|
: [AutoRecoveryManager.createSupervisorRestartStrategy()];
|
|
24
34
|
this.attempts = new Map();
|
|
25
35
|
this.timeouts = new Map();
|
|
36
|
+
m_constructor.success();
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
static createSupervisorRestartStrategy() {
|
|
40
|
+
const m_create_supervisor_restart_strategy = createMetricScope({
|
|
41
|
+
hook: 'auto_recovery_manager',
|
|
42
|
+
operation: 'create_supervisor_restart_strategy'
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
m_create_supervisor_restart_strategy.started();
|
|
46
|
+
m_create_supervisor_restart_strategy.success();
|
|
29
47
|
return {
|
|
30
48
|
id: 'guard-supervisor-restart',
|
|
31
49
|
condition: ({ reason }) => reason && reason.startsWith('heartbeat-'),
|
|
32
50
|
action: async ({ logger }) => {
|
|
33
51
|
logger.info('Attempting guard-supervisor restart via start-guards.sh');
|
|
52
|
+
m_create_supervisor_restart_strategy.success();
|
|
34
53
|
return AutoRecoveryManager.runScript('start-guards.sh', ['restart']);
|
|
35
54
|
}
|
|
36
55
|
};
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
|
|
3
|
+
const {
|
|
4
|
+
createMetricScope: createMetricScope
|
|
5
|
+
} = require('../../../infrastructure/telemetry/metric-scope');
|
|
6
|
+
|
|
3
7
|
class CommitMessageSuggester {
|
|
4
8
|
constructor(featureDetector) {
|
|
9
|
+
const m_constructor = createMetricScope({
|
|
10
|
+
hook: 'commit_message_suggester',
|
|
11
|
+
operation: 'constructor'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
m_constructor.started();
|
|
5
15
|
this.featureDetector = featureDetector;
|
|
6
16
|
this.commitTypePatterns = {
|
|
7
17
|
feat: ['feature/', 'feat/', 'add', 'new', 'create', 'implement'],
|
|
@@ -12,6 +22,7 @@ class CommitMessageSuggester {
|
|
|
12
22
|
chore: ['chore/', 'config/', 'build/', 'ci/'],
|
|
13
23
|
style: ['style/', 'css/', 'scss/', 'styling']
|
|
14
24
|
};
|
|
25
|
+
m_constructor.success();
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
suggest(group) {
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
|
|
3
|
+
const {
|
|
4
|
+
createMetricScope: createMetricScope
|
|
5
|
+
} = require('../../../infrastructure/telemetry/metric-scope');
|
|
6
|
+
|
|
3
7
|
class FileContextGrouper {
|
|
4
8
|
constructor(featureDetector, platformDetector = null) {
|
|
9
|
+
const m_constructor = createMetricScope({
|
|
10
|
+
hook: 'file_context_grouper',
|
|
11
|
+
operation: 'constructor'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
m_constructor.started();
|
|
5
15
|
this.featureDetector = featureDetector;
|
|
6
16
|
this.platformDetector = platformDetector;
|
|
17
|
+
m_constructor.success();
|
|
7
18
|
}
|
|
8
19
|
|
|
9
20
|
group(files) {
|
|
@@ -89,10 +100,18 @@ class FileContextGrouper {
|
|
|
89
100
|
}
|
|
90
101
|
|
|
91
102
|
getContextDirectory(file) {
|
|
103
|
+
const m_get_context_directory = createMetricScope({
|
|
104
|
+
hook: 'file_context_grouper',
|
|
105
|
+
operation: 'get_context_directory'
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
m_get_context_directory.started();
|
|
92
109
|
const parts = file.split(path.sep);
|
|
93
110
|
if (parts.length <= 2) {
|
|
111
|
+
m_get_context_directory.success();
|
|
94
112
|
return parts[0] || 'root';
|
|
95
113
|
}
|
|
114
|
+
m_get_context_directory.success();
|
|
96
115
|
return parts.slice(0, 2).join(path.sep);
|
|
97
116
|
}
|
|
98
117
|
|
|
@@ -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,11 +1,22 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
2
|
|
|
3
|
+
const {
|
|
4
|
+
createMetricScope: createMetricScope
|
|
5
|
+
} = require('../../../infrastructure/telemetry/metric-scope');
|
|
6
|
+
|
|
3
7
|
class TokenMetricsService {
|
|
4
8
|
constructor(cursorTokenService, thresholds, logger) {
|
|
9
|
+
const m_constructor = createMetricScope({
|
|
10
|
+
hook: 'token_metrics_service',
|
|
11
|
+
operation: 'constructor'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
m_constructor.started();
|
|
5
15
|
this.cursorTokenService = cursorTokenService;
|
|
6
16
|
this.thresholds = thresholds;
|
|
7
17
|
this.logger = logger;
|
|
8
18
|
this.repoRoot = process.cwd();
|
|
19
|
+
m_constructor.success();
|
|
9
20
|
}
|
|
10
21
|
|
|
11
22
|
async collectMetrics(fallbackEstimator) {
|
|
@@ -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) {
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
const {
|
|
2
|
+
ValidationException,
|
|
3
|
+
BadRequestException,
|
|
4
|
+
InternalServerException
|
|
5
|
+
} = require('../exceptions');
|
|
6
|
+
|
|
1
7
|
class DomainEvent {
|
|
2
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' });
|
|
3
11
|
this.type = type;
|
|
4
12
|
this.payload = payload;
|
|
5
13
|
this.timestamp = new Date().toISOString();
|
|
@@ -7,8 +15,8 @@ class DomainEvent {
|
|
|
7
15
|
}
|
|
8
16
|
|
|
9
17
|
validate() {
|
|
10
|
-
if (!this.type) throw new
|
|
11
|
-
if (!this.payload) throw new
|
|
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
20
|
return true;
|
|
13
21
|
}
|
|
14
22
|
|
|
@@ -29,7 +37,7 @@ class EvidenceStaleEvent extends DomainEvent {
|
|
|
29
37
|
|
|
30
38
|
validate() {
|
|
31
39
|
super.validate();
|
|
32
|
-
if (!this.payload.evidencePath) throw new
|
|
40
|
+
if (!this.payload.evidencePath) throw new ValidationException('Evidence path is required', { field: 'evidencePath' });
|
|
33
41
|
}
|
|
34
42
|
}
|
|
35
43
|
|
|
@@ -41,8 +49,8 @@ class GitFlowViolationEvent extends DomainEvent {
|
|
|
41
49
|
|
|
42
50
|
validate() {
|
|
43
51
|
super.validate();
|
|
44
|
-
if (!this.payload.branch) throw new
|
|
45
|
-
if (!this.payload.violation) throw new
|
|
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' });
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
56
|
|
|
@@ -54,7 +62,7 @@ class AstCriticalFoundEvent extends DomainEvent {
|
|
|
54
62
|
|
|
55
63
|
validate() {
|
|
56
64
|
super.validate();
|
|
57
|
-
if (!Array.isArray(this.payload.findings)) throw new
|
|
65
|
+
if (!Array.isArray(this.payload.findings)) throw new ValidationException('Findings must be an array', { field: 'findings' });
|
|
58
66
|
}
|
|
59
67
|
}
|
|
60
68
|
|
|
@@ -63,6 +71,12 @@ class PreCommitBlockedEvent extends DomainEvent {
|
|
|
63
71
|
super('PRE_COMMIT_BLOCKED', { reason, violations });
|
|
64
72
|
this.validate();
|
|
65
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
|
+
}
|
|
66
80
|
}
|
|
67
81
|
|
|
68
82
|
class AnalysisCompletedEvent extends DomainEvent {
|
|
@@ -70,6 +84,11 @@ class AnalysisCompletedEvent extends DomainEvent {
|
|
|
70
84
|
super('ANALYSIS_COMPLETED', summary);
|
|
71
85
|
this.validate();
|
|
72
86
|
}
|
|
87
|
+
|
|
88
|
+
validate() {
|
|
89
|
+
super.validate();
|
|
90
|
+
if (!this.payload) throw new ValidationException('Summary is required', { field: 'summary' });
|
|
91
|
+
}
|
|
73
92
|
}
|
|
74
93
|
|
|
75
94
|
class EventBus {
|
|
@@ -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
|
+
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
const path = require('path');
|
|
3
2
|
const {
|
|
4
3
|
pushFinding,
|
|
@@ -367,11 +366,12 @@ function runBackendIntelligence(project, findings, platform) {
|
|
|
367
366
|
}
|
|
368
367
|
});
|
|
369
368
|
|
|
370
|
-
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
+
// }
|
|
375
375
|
|
|
376
376
|
sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((call) => {
|
|
377
377
|
const expr = call.getExpression();
|
|
@@ -423,9 +423,7 @@ function runBackendIntelligence(project, findings, platform) {
|
|
|
423
423
|
|
|
424
424
|
if (isTestFile(filePath)) {
|
|
425
425
|
sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((call) => {
|
|
426
|
-
const
|
|
427
|
-
if (!expr) return;
|
|
428
|
-
const exprText = expr.getText();
|
|
426
|
+
const exprText = call.getExpression().getText();
|
|
429
427
|
if (/Thread\.sleep|await|delay/.test(exprText)) {
|
|
430
428
|
pushFinding("backend.testing.slow_tests", "medium", sf, call, "Test with sleep/delay detected - slow tests impact CI/CD performance", findings);
|
|
431
429
|
}
|