pumuki-ast-hooks 5.3.30 → 5.4.0
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 +10 -10
- package/package.json +2 -2
- package/scripts/hooks-system/application/CompositionRoot.js +57 -282
- package/scripts/hooks-system/application/factories/AdapterFactory.js +58 -0
- package/scripts/hooks-system/application/factories/MonitorFactory.js +104 -0
- package/scripts/hooks-system/application/factories/ServiceFactory.js +153 -0
- package/scripts/hooks-system/application/services/RealtimeGuardService.js +49 -246
- package/scripts/hooks-system/application/services/guard/EvidenceManager.js +153 -0
- package/scripts/hooks-system/application/services/guard/GitTreeManager.js +129 -0
- package/scripts/hooks-system/application/services/guard/GuardNotifier.js +54 -0
- package/scripts/hooks-system/application/services/installation/McpConfigurator.js +3 -2
- package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +33 -29
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +80 -10
- package/scripts/hooks-system/infrastructure/ast/ios/ast-ios.js +45 -11
- package/scripts/hooks-system/infrastructure/ast/ios/native-bridge.js +39 -2
- package/scripts/hooks-system/.hook-system/config.json +0 -8
|
@@ -45,22 +45,22 @@ gantt
|
|
|
45
45
|
## 🔴 Phase 1: BLOCKER Violations (CRITICAL + HIGH)
|
|
46
46
|
| Status | Severity | Count | Owner | DOD (Definition of Done) | Source |
|
|
47
47
|
|--------|-----------|-------|-------------|--------------------------|--------|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
48
|
+
| ✅ | CRITICAL | 0 | BE | Resolve CRITICAL violations in repository (0 CRITICAL to unblock) | `.audit_tmp/ast-summary.json` / `.violations-by-priority.md` |
|
|
49
|
+
| ✅ | HIGH | 0 | BE | Resolve HIGH violations in repository (0 HIGH to unblock) | `.audit_tmp/ast-summary.json` / `.violations-by-priority.md` |
|
|
50
50
|
|
|
51
51
|
---
|
|
52
52
|
|
|
53
|
-
## 🟠 Phase 2: MEDIUM Violations (
|
|
53
|
+
## 🟠 Phase 2: MEDIUM Violations (277)
|
|
54
54
|
| Status | Violation | Count | Owner | DOD | Doc |
|
|
55
55
|
|--------|-----------|-------|-------------|-----|-----|
|
|
56
|
-
| 🚧 | MEDIUM |
|
|
56
|
+
| 🚧 | MEDIUM | 277 | BE | Resolve remaining medium-complexity violations | [Medium violations](../docs/medium-violations.md) |
|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
|
60
|
-
## 🔵 Phase 3: LOW Violations (
|
|
60
|
+
## 🔵 Phase 3: LOW Violations (218)
|
|
61
61
|
| Status | Violation | Count | Owner | DOD | Doc |
|
|
62
62
|
|--------|-----------|-------|-------------|-----|-----|
|
|
63
|
-
| 🚧 | LOW |
|
|
63
|
+
| 🚧 | LOW | 218 | BE/FE | Resolve remaining low-priority violations | [Low violations](../docs/low-violations.md) |
|
|
64
64
|
|
|
65
65
|
---
|
|
66
66
|
|
|
@@ -83,10 +83,10 @@ gantt
|
|
|
83
83
|
## 📈 Progress Metrics
|
|
84
84
|
| Phase | Total | Completed | % |
|
|
85
85
|
|------|-------|------------|---|
|
|
86
|
-
| BLOCKERS (CRITICAL + HIGH) |
|
|
87
|
-
| MEDIUM |
|
|
88
|
-
| LOW |
|
|
89
|
-
| **TOTAL** | **
|
|
86
|
+
| BLOCKERS (CRITICAL + HIGH) | 9 | 9 | 100% |
|
|
87
|
+
| MEDIUM | 272 | 0 | 0% |
|
|
88
|
+
| LOW | 213 | 0 | 0% |
|
|
89
|
+
| **TOTAL** | **494** | **9** | **1.8%** |
|
|
90
90
|
|
|
91
91
|
**Updated risks:**
|
|
92
92
|
1) Prometheus implementation may require infra changes; 2) Security review depends on team availability; 3) Refactors may impact timelines.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki-ast-hooks",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -123,4 +123,4 @@
|
|
|
123
123
|
"./skills": "./skills/skill-rules.json",
|
|
124
124
|
"./hooks": "./hooks/index.js"
|
|
125
125
|
}
|
|
126
|
-
}
|
|
126
|
+
}
|
|
@@ -1,31 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const GitCommandAdapter = require('../infrastructure/adapters/GitCommandAdapter');
|
|
5
|
-
const GitHubCliAdapter = require('../infrastructure/adapters/GitHubCliAdapter');
|
|
6
|
-
const AstAnalyzerAdapter = require('../infrastructure/adapters/AstAnalyzerAdapter');
|
|
7
|
-
|
|
8
|
-
const AutonomousOrchestrator = require('./services/AutonomousOrchestrator');
|
|
9
|
-
const ContextDetectionEngine = require('./services/ContextDetectionEngine');
|
|
10
|
-
const PlatformDetectionService = require('./services/PlatformDetectionService');
|
|
11
|
-
const AutoExecuteAIStartUseCase = require('./use-cases/AutoExecuteAIStartUseCase');
|
|
12
|
-
|
|
13
|
-
// Services & Monitors
|
|
14
|
-
const RealtimeGuardService = require('./services/RealtimeGuardService');
|
|
15
|
-
const UnifiedLogger = require('./services/logging/UnifiedLogger');
|
|
16
|
-
const NotificationCenterService = require('./services/notification/NotificationCenterService');
|
|
17
|
-
const GitFlowService = require('./services/GitFlowService');
|
|
18
|
-
const EvidenceMonitor = require('./services/monitoring/EvidenceMonitor');
|
|
19
|
-
const GitTreeMonitor = require('./services/monitoring/GitTreeMonitor');
|
|
20
|
-
const TokenMonitor = require('./services/monitoring/TokenMonitor');
|
|
21
|
-
const ActivityMonitor = require('./services/monitoring/ActivityMonitor');
|
|
22
|
-
const DevDocsMonitor = require('./services/monitoring/DevDocsMonitor');
|
|
23
|
-
const AstMonitor = require('./services/monitoring/AstMonitor');
|
|
24
|
-
const AuditLogger = require('./services/logging/AuditLogger');
|
|
25
|
-
|
|
1
|
+
const AdapterFactory = require('./factories/AdapterFactory');
|
|
2
|
+
const ServiceFactory = require('./factories/ServiceFactory');
|
|
3
|
+
const MonitorFactory = require('./factories/MonitorFactory');
|
|
26
4
|
const path = require('path');
|
|
27
5
|
const fs = require('fs');
|
|
28
|
-
const env = require('../config/env');
|
|
29
6
|
|
|
30
7
|
class CompositionRoot {
|
|
31
8
|
constructor(repoRoot) {
|
|
@@ -36,6 +13,39 @@ class CompositionRoot {
|
|
|
36
13
|
this.auditDir = path.join(repoRoot, '.audit-reports');
|
|
37
14
|
this.tempDir = path.join(repoRoot, '.audit_tmp');
|
|
38
15
|
this._ensureDirectories([this.auditDir, this.tempDir]);
|
|
16
|
+
|
|
17
|
+
// Initialize factories lazily
|
|
18
|
+
this._adapterFactory = null;
|
|
19
|
+
this._serviceFactory = null;
|
|
20
|
+
this._monitorFactory = null;
|
|
21
|
+
|
|
22
|
+
// Create dynamic proxy for automatic delegation
|
|
23
|
+
return new Proxy(this, {
|
|
24
|
+
get(target, prop) {
|
|
25
|
+
// If method exists in CompositionRoot, use it
|
|
26
|
+
if (typeof target[prop] === 'function' && target.hasOwnProperty(prop)) {
|
|
27
|
+
return target[prop].bind(target);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Delegate to specialized factories
|
|
31
|
+
if (target._serviceFactory && typeof target._serviceFactory[prop] === 'function') {
|
|
32
|
+
return target._serviceFactory[prop].bind(target._serviceFactory);
|
|
33
|
+
}
|
|
34
|
+
if (target._adapterFactory && typeof target._adapterFactory[prop] === 'function') {
|
|
35
|
+
return target._adapterFactory[prop].bind(target._adapterFactory);
|
|
36
|
+
}
|
|
37
|
+
if (target._monitorFactory && typeof target._monitorFactory[prop] === 'function') {
|
|
38
|
+
return target._monitorFactory[prop].bind(target._monitorFactory);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Para acceso a propiedades de factories
|
|
42
|
+
if (prop === '_serviceFactory') return target._serviceFactory;
|
|
43
|
+
if (prop === '_adapterFactory') return target._adapterFactory;
|
|
44
|
+
if (prop === '_monitorFactory') return target._monitorFactory;
|
|
45
|
+
|
|
46
|
+
return target[prop];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
39
49
|
}
|
|
40
50
|
|
|
41
51
|
_ensureDirectories(dirs) {
|
|
@@ -46,283 +56,48 @@ class CompositionRoot {
|
|
|
46
56
|
});
|
|
47
57
|
}
|
|
48
58
|
|
|
49
|
-
|
|
50
|
-
if (!this.
|
|
51
|
-
this.
|
|
52
|
-
component: 'HookSystem',
|
|
53
|
-
file: {
|
|
54
|
-
enabled: true,
|
|
55
|
-
path: path.join(this.auditDir, 'guard-audit.jsonl'),
|
|
56
|
-
level: env.get('HOOK_LOG_LEVEL', env.isProd ? 'warn' : 'info')
|
|
57
|
-
},
|
|
58
|
-
console: {
|
|
59
|
-
enabled: false,
|
|
60
|
-
level: 'info'
|
|
61
|
-
}
|
|
62
|
-
}));
|
|
63
|
-
}
|
|
64
|
-
return this.instances.get('logger');
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
getNotificationService() {
|
|
68
|
-
if (!this.instances.has('notificationService')) {
|
|
69
|
-
const logger = this.getLogger();
|
|
70
|
-
this.instances.set('notificationService', new NotificationCenterService({
|
|
71
|
-
repoRoot: this.repoRoot,
|
|
72
|
-
logger
|
|
73
|
-
}));
|
|
74
|
-
}
|
|
75
|
-
return this.instances.get('notificationService');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
getAuditLogger() {
|
|
79
|
-
if (!this.instances.has('auditLogger')) {
|
|
80
|
-
const logger = this.getLogger();
|
|
81
|
-
this.instances.set('auditLogger', new AuditLogger({
|
|
82
|
-
repoRoot: this.repoRoot,
|
|
83
|
-
filename: path.join('.audit_tmp', 'audit.log'),
|
|
84
|
-
logger
|
|
85
|
-
}));
|
|
86
|
-
}
|
|
87
|
-
return this.instances.get('auditLogger');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// --- Infrastructure Adapters ---
|
|
91
|
-
|
|
92
|
-
getNotificationAdapter() {
|
|
93
|
-
if (!this.instances.has('notificationAdapter')) {
|
|
94
|
-
this.instances.set('notificationAdapter', new MacOSNotificationAdapter());
|
|
95
|
-
}
|
|
96
|
-
return this.instances.get('notificationAdapter');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
getEvidenceAdapter() {
|
|
100
|
-
if (!this.instances.has('evidenceAdapter')) {
|
|
101
|
-
this.instances.set('evidenceAdapter', new FileEvidenceAdapter(this.repoRoot));
|
|
102
|
-
}
|
|
103
|
-
return this.instances.get('evidenceAdapter');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
getGitQueryAdapter() {
|
|
107
|
-
if (!this.instances.has('gitQuery')) {
|
|
108
|
-
const logger = this.getLogger();
|
|
109
|
-
this.instances.set('gitQuery', new GitQueryAdapter({ repoRoot: this.repoRoot, logger }));
|
|
110
|
-
}
|
|
111
|
-
return this.instances.get('gitQuery');
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
getGitCommandAdapter() {
|
|
115
|
-
if (!this.instances.has('gitCommand')) {
|
|
116
|
-
const logger = this.getLogger();
|
|
117
|
-
this.instances.set('gitCommand', new GitCommandAdapter({ repoRoot: this.repoRoot, logger }));
|
|
118
|
-
}
|
|
119
|
-
return this.instances.get('gitCommand');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
getGitHubAdapter() {
|
|
123
|
-
if (!this.instances.has('github')) {
|
|
124
|
-
const logger = this.getLogger();
|
|
125
|
-
this.instances.set('github', new GitHubCliAdapter(this.repoRoot, logger));
|
|
59
|
+
_getAdapterFactory() {
|
|
60
|
+
if (!this._adapterFactory) {
|
|
61
|
+
this._adapterFactory = new AdapterFactory(this.repoRoot, this.instances, this.getLogger());
|
|
126
62
|
}
|
|
127
|
-
return this.
|
|
63
|
+
return this._adapterFactory;
|
|
128
64
|
}
|
|
129
65
|
|
|
130
|
-
|
|
131
|
-
if (!this.
|
|
132
|
-
this.
|
|
66
|
+
_getServiceFactory() {
|
|
67
|
+
if (!this._serviceFactory) {
|
|
68
|
+
this._serviceFactory = new ServiceFactory(this.repoRoot, this.instances, this._getAdapterFactory());
|
|
133
69
|
}
|
|
134
|
-
return this.
|
|
70
|
+
return this._serviceFactory;
|
|
135
71
|
}
|
|
136
72
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (!this.instances.has('contextEngine')) {
|
|
141
|
-
const gitQuery = this.getGitQueryAdapter();
|
|
142
|
-
const logger = this.getLogger();
|
|
143
|
-
this.instances.set('contextEngine', new ContextDetectionEngine(gitQuery, logger));
|
|
73
|
+
_getMonitorFactory() {
|
|
74
|
+
if (!this._monitorFactory) {
|
|
75
|
+
this._monitorFactory = new MonitorFactory(this.repoRoot, this.instances, this._getServiceFactory());
|
|
144
76
|
}
|
|
145
|
-
return this.
|
|
77
|
+
return this._monitorFactory;
|
|
146
78
|
}
|
|
147
79
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
return this.instances.get('platformDetector');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
getOrchestrator() {
|
|
156
|
-
if (!this.instances.has('orchestrator')) {
|
|
157
|
-
const contextEngine = this.getContextDetectionEngine();
|
|
158
|
-
const platformDetector = this.getPlatformDetectionService();
|
|
159
|
-
const logger = this.getLogger();
|
|
160
|
-
// Note: RulesLoader is currently null in Factory, maintaining that behavior or adding if needed
|
|
161
|
-
|
|
162
|
-
this.instances.set('orchestrator', new AutonomousOrchestrator(
|
|
163
|
-
contextEngine,
|
|
164
|
-
platformDetector,
|
|
165
|
-
null,
|
|
166
|
-
logger
|
|
167
|
-
));
|
|
168
|
-
}
|
|
169
|
-
return this.instances.get('orchestrator');
|
|
80
|
+
// Essential methods that are not delegated
|
|
81
|
+
getLogger() {
|
|
82
|
+
return this._getServiceFactory().getLogger();
|
|
170
83
|
}
|
|
171
84
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const orchestrator = this.getOrchestrator();
|
|
175
|
-
const logger = this.getLogger();
|
|
176
|
-
this.instances.set('autoExecuteAIStart', new AutoExecuteAIStartUseCase(orchestrator, this.repoRoot, logger));
|
|
177
|
-
}
|
|
178
|
-
return this.instances.get('autoExecuteAIStart');
|
|
85
|
+
getMonitors() {
|
|
86
|
+
return this._getMonitorFactory().getMonitors();
|
|
179
87
|
}
|
|
180
88
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
this.instances.set('blockCommit', new BlockCommitUseCase());
|
|
185
|
-
}
|
|
186
|
-
return this.instances.get('blockCommit');
|
|
89
|
+
getRealtimeGuardService() {
|
|
90
|
+
const monitors = this.getMonitors();
|
|
91
|
+
return this._getServiceFactory().getRealtimeGuardService(monitors);
|
|
187
92
|
}
|
|
188
93
|
|
|
94
|
+
// MCP Protocol Handler (kept here as it's specific to MCP infrastructure)
|
|
189
95
|
getMcpProtocolHandler(inputStream, outputStream) {
|
|
190
96
|
const McpProtocolHandler = require('../infrastructure/mcp/services/McpProtocolHandler');
|
|
191
97
|
const logger = this.getLogger();
|
|
192
98
|
return new McpProtocolHandler(inputStream, outputStream, logger);
|
|
193
99
|
}
|
|
194
100
|
|
|
195
|
-
// --- Monitors ---
|
|
196
|
-
|
|
197
|
-
getEvidenceMonitor() {
|
|
198
|
-
if (!this.instances.has('evidenceMonitor')) {
|
|
199
|
-
this.instances.set('evidenceMonitor', new EvidenceMonitor(this.repoRoot, {
|
|
200
|
-
staleThresholdMs: env.getNumber('HOOK_GUARD_EVIDENCE_STALE_THRESHOLD', 180000),
|
|
201
|
-
pollIntervalMs: env.getNumber('HOOK_GUARD_EVIDENCE_POLL_INTERVAL', 30000),
|
|
202
|
-
reminderIntervalMs: env.getNumber('HOOK_GUARD_EVIDENCE_REMINDER_INTERVAL', 60000)
|
|
203
|
-
}));
|
|
204
|
-
}
|
|
205
|
-
return this.instances.get('evidenceMonitor');
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
getGitTreeMonitor() {
|
|
209
|
-
if (!this.instances.has('gitTreeMonitor')) {
|
|
210
|
-
this.instances.set('gitTreeMonitor', new GitTreeMonitor(this.repoRoot, {
|
|
211
|
-
stagedThreshold: env.getNumber('HOOK_GUARD_DIRTY_TREE_STAGED_LIMIT', 10),
|
|
212
|
-
unstagedThreshold: env.getNumber('HOOK_GUARD_DIRTY_TREE_UNSTAGED_LIMIT', 15),
|
|
213
|
-
totalThreshold: env.getNumber('HOOK_GUARD_DIRTY_TREE_TOTAL_LIMIT', 20),
|
|
214
|
-
checkIntervalMs: env.getNumber('HOOK_GUARD_DIRTY_TREE_INTERVAL', 60000),
|
|
215
|
-
reminderMs: env.getNumber('HOOK_GUARD_DIRTY_TREE_REMINDER', 300000)
|
|
216
|
-
}));
|
|
217
|
-
}
|
|
218
|
-
return this.instances.get('gitTreeMonitor');
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
getTokenMonitor() {
|
|
222
|
-
if (!this.instances.has('tokenMonitor')) {
|
|
223
|
-
this.instances.set('tokenMonitor', new TokenMonitor(this.repoRoot));
|
|
224
|
-
}
|
|
225
|
-
return this.instances.get('tokenMonitor');
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
getGitFlowService() {
|
|
229
|
-
if (!this.instances.has('gitFlowService')) {
|
|
230
|
-
const logger = this.getLogger();
|
|
231
|
-
const gitQuery = this.getGitQueryAdapter();
|
|
232
|
-
const gitCommand = this.getGitCommandAdapter();
|
|
233
|
-
const github = this.getGitHubAdapter();
|
|
234
|
-
|
|
235
|
-
this.instances.set('gitFlowService', new GitFlowService(this.repoRoot, {
|
|
236
|
-
developBranch: env.get('HOOK_GUARD_GITFLOW_DEVELOP_BRANCH', 'develop'),
|
|
237
|
-
mainBranch: env.get('HOOK_GUARD_GITFLOW_MAIN_BRANCH', 'main'),
|
|
238
|
-
autoSyncEnabled: env.getBool('HOOK_GUARD_GITFLOW_AUTOSYNC', true),
|
|
239
|
-
autoCleanEnabled: env.getBool('HOOK_GUARD_GITFLOW_AUTOCLEAN', true),
|
|
240
|
-
requireClean: env.getBool('HOOK_GUARD_GITFLOW_REQUIRE_CLEAN', true)
|
|
241
|
-
}, logger, gitQuery, gitCommand, github));
|
|
242
|
-
}
|
|
243
|
-
return this.instances.get('gitFlowService');
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
getActivityMonitor() {
|
|
247
|
-
if (!this.instances.has('activityMonitor')) {
|
|
248
|
-
const logger = this.getLogger();
|
|
249
|
-
this.instances.set('activityMonitor', new ActivityMonitor({
|
|
250
|
-
repoRoot: this.repoRoot,
|
|
251
|
-
inactivityGraceMs: env.getNumber('HOOK_GUARD_INACTIVITY_GRACE_MS', 420000),
|
|
252
|
-
logger
|
|
253
|
-
}));
|
|
254
|
-
}
|
|
255
|
-
return this.instances.get('activityMonitor');
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
getDevDocsMonitor() {
|
|
259
|
-
if (!this.instances.has('devDocsMonitor')) {
|
|
260
|
-
const logger = this.getLogger();
|
|
261
|
-
const notificationService = this.getNotificationService();
|
|
262
|
-
this.instances.set('devDocsMonitor', new DevDocsMonitor({
|
|
263
|
-
repoRoot: this.repoRoot,
|
|
264
|
-
checkIntervalMs: env.getNumber('HOOK_GUARD_DEV_DOCS_CHECK_INTERVAL', 300000),
|
|
265
|
-
staleThresholdMs: env.getNumber('HOOK_GUARD_DEV_DOCS_STALE_THRESHOLD', 86400000),
|
|
266
|
-
autoRefreshEnabled: env.getBool('HOOK_GUARD_DEV_DOCS_AUTO_REFRESH', true),
|
|
267
|
-
logger,
|
|
268
|
-
notificationService
|
|
269
|
-
}));
|
|
270
|
-
}
|
|
271
|
-
return this.instances.get('devDocsMonitor');
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
getAstMonitor() {
|
|
275
|
-
if (!this.instances.has('astMonitor')) {
|
|
276
|
-
const logger = this.getLogger();
|
|
277
|
-
const notificationService = this.getNotificationService();
|
|
278
|
-
this.instances.set('astMonitor', new AstMonitor({
|
|
279
|
-
repoRoot: this.repoRoot,
|
|
280
|
-
debounceMs: env.getNumber('HOOK_AST_WATCH_DEBOUNCE', 8000),
|
|
281
|
-
cooldownMs: env.getNumber('HOOK_AST_WATCH_COOLDOWN', 30000),
|
|
282
|
-
enabled: env.getBool('HOOK_AST_WATCH', true),
|
|
283
|
-
logger,
|
|
284
|
-
notificationService
|
|
285
|
-
}));
|
|
286
|
-
}
|
|
287
|
-
return this.instances.get('astMonitor');
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
getMonitors() {
|
|
291
|
-
return {
|
|
292
|
-
evidence: this.getEvidenceMonitor(),
|
|
293
|
-
gitTree: this.getGitTreeMonitor(),
|
|
294
|
-
token: this.getTokenMonitor(),
|
|
295
|
-
gitFlow: this.getGitFlowService(),
|
|
296
|
-
activity: this.getActivityMonitor(),
|
|
297
|
-
devDocs: this.getDevDocsMonitor(),
|
|
298
|
-
ast: this.getAstMonitor()
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
getRealtimeGuardService() {
|
|
303
|
-
if (!this.instances.has('guardService')) {
|
|
304
|
-
const logger = this.getLogger();
|
|
305
|
-
const notificationService = this.getNotificationService();
|
|
306
|
-
const monitors = this.getMonitors();
|
|
307
|
-
const orchestrator = this.getOrchestrator();
|
|
308
|
-
const auditLogger = this.getAuditLogger();
|
|
309
|
-
const config = {
|
|
310
|
-
debugLogPath: path.join(this.auditDir, 'guard-debug.log'),
|
|
311
|
-
repoRoot: this.repoRoot
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
this.instances.set('guardService', new RealtimeGuardService({
|
|
315
|
-
logger,
|
|
316
|
-
notificationService,
|
|
317
|
-
monitors,
|
|
318
|
-
orchestration: orchestrator,
|
|
319
|
-
config,
|
|
320
|
-
auditLogger
|
|
321
|
-
}));
|
|
322
|
-
}
|
|
323
|
-
return this.instances.get('guardService');
|
|
324
|
-
}
|
|
325
|
-
|
|
326
101
|
static createForProduction(repoRoot) {
|
|
327
102
|
return new CompositionRoot(repoRoot);
|
|
328
103
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const MacOSNotificationAdapter = require('../../adapters/MacOSNotificationAdapter');
|
|
2
|
+
const FileEvidenceAdapter = require('../../adapters/FileEvidenceAdapter');
|
|
3
|
+
const GitQueryAdapter = require('../../adapters/GitQueryAdapter');
|
|
4
|
+
const GitCommandAdapter = require('../../adapters/GitCommandAdapter');
|
|
5
|
+
const GitHubCliAdapter = require('../../adapters/GitHubCliAdapter');
|
|
6
|
+
const AstAnalyzerAdapter = require('../../adapters/AstAnalyzerAdapter');
|
|
7
|
+
|
|
8
|
+
class AdapterFactory {
|
|
9
|
+
constructor(repoRoot, instances, logger) {
|
|
10
|
+
this.repoRoot = repoRoot;
|
|
11
|
+
this.instances = instances;
|
|
12
|
+
this.logger = logger;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getNotificationAdapter() {
|
|
16
|
+
if (!this.instances.has('notificationAdapter')) {
|
|
17
|
+
this.instances.set('notificationAdapter', new MacOSNotificationAdapter());
|
|
18
|
+
}
|
|
19
|
+
return this.instances.get('notificationAdapter');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getEvidenceAdapter() {
|
|
23
|
+
if (!this.instances.has('evidenceAdapter')) {
|
|
24
|
+
this.instances.set('evidenceAdapter', new FileEvidenceAdapter(this.repoRoot));
|
|
25
|
+
}
|
|
26
|
+
return this.instances.get('evidenceAdapter');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getGitQueryAdapter() {
|
|
30
|
+
if (!this.instances.has('gitQuery')) {
|
|
31
|
+
this.instances.set('gitQuery', new GitQueryAdapter({ repoRoot: this.repoRoot, logger: this.logger }));
|
|
32
|
+
}
|
|
33
|
+
return this.instances.get('gitQuery');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getGitCommandAdapter() {
|
|
37
|
+
if (!this.instances.has('gitCommand')) {
|
|
38
|
+
this.instances.set('gitCommand', new GitCommandAdapter({ repoRoot: this.repoRoot, logger: this.logger }));
|
|
39
|
+
}
|
|
40
|
+
return this.instances.get('gitCommand');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getGitHubAdapter() {
|
|
44
|
+
if (!this.instances.has('github')) {
|
|
45
|
+
this.instances.set('github', new GitHubCliAdapter(this.repoRoot, this.logger));
|
|
46
|
+
}
|
|
47
|
+
return this.instances.get('github');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
getAstAdapter() {
|
|
51
|
+
if (!this.instances.has('ast')) {
|
|
52
|
+
this.instances.set('ast', new AstAnalyzerAdapter(this.repoRoot));
|
|
53
|
+
}
|
|
54
|
+
return this.instances.get('ast');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = AdapterFactory;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const EvidenceMonitor = require('../services/monitoring/EvidenceMonitor');
|
|
2
|
+
const GitTreeMonitor = require('../services/monitoring/GitTreeMonitor');
|
|
3
|
+
const TokenMonitor = require('../services/monitoring/TokenMonitor');
|
|
4
|
+
const ActivityMonitor = require('../services/monitoring/ActivityMonitor');
|
|
5
|
+
const DevDocsMonitor = require('../services/monitoring/DevDocsMonitor');
|
|
6
|
+
const AstMonitor = require('../services/monitoring/AstMonitor');
|
|
7
|
+
const env = require('../../config/env');
|
|
8
|
+
|
|
9
|
+
class MonitorFactory {
|
|
10
|
+
constructor(repoRoot, instances, serviceFactory) {
|
|
11
|
+
this.repoRoot = repoRoot;
|
|
12
|
+
this.instances = instances;
|
|
13
|
+
this.serviceFactory = serviceFactory;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getEvidenceMonitor() {
|
|
17
|
+
if (!this.instances.has('evidenceMonitor')) {
|
|
18
|
+
this.instances.set('evidenceMonitor', new EvidenceMonitor(this.repoRoot, {
|
|
19
|
+
staleThresholdMs: env.getNumber('HOOK_GUARD_EVIDENCE_STALE_THRESHOLD', 180000),
|
|
20
|
+
pollIntervalMs: env.getNumber('HOOK_GUARD_EVIDENCE_POLL_INTERVAL', 30000),
|
|
21
|
+
reminderIntervalMs: env.getNumber('HOOK_GUARD_EVIDENCE_REMINDER_INTERVAL', 60000)
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
return this.instances.get('evidenceMonitor');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
getGitTreeMonitor() {
|
|
28
|
+
if (!this.instances.has('gitTreeMonitor')) {
|
|
29
|
+
this.instances.set('gitTreeMonitor', new GitTreeMonitor(this.repoRoot, {
|
|
30
|
+
stagedThreshold: env.getNumber('HOOK_GUARD_DIRTY_TREE_STAGED_LIMIT', 10),
|
|
31
|
+
unstagedThreshold: env.getNumber('HOOK_GUARD_DIRTY_TREE_UNSTAGED_LIMIT', 15),
|
|
32
|
+
totalThreshold: env.getNumber('HOOK_GUARD_DIRTY_TREE_TOTAL_LIMIT', 20),
|
|
33
|
+
checkIntervalMs: env.getNumber('HOOK_GUARD_DIRTY_TREE_INTERVAL', 60000),
|
|
34
|
+
reminderMs: env.getNumber('HOOK_GUARD_DIRTY_TREE_REMINDER', 300000)
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
return this.instances.get('gitTreeMonitor');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getTokenMonitor() {
|
|
41
|
+
if (!this.instances.has('tokenMonitor')) {
|
|
42
|
+
this.instances.set('tokenMonitor', new TokenMonitor(this.repoRoot));
|
|
43
|
+
}
|
|
44
|
+
return this.instances.get('tokenMonitor');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getActivityMonitor() {
|
|
48
|
+
if (!this.instances.has('activityMonitor')) {
|
|
49
|
+
const logger = this.serviceFactory.getLogger();
|
|
50
|
+
this.instances.set('activityMonitor', new ActivityMonitor({
|
|
51
|
+
repoRoot: this.repoRoot,
|
|
52
|
+
inactivityGraceMs: env.getNumber('HOOK_GUARD_INACTIVITY_GRACE_MS', 420000),
|
|
53
|
+
logger
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
return this.instances.get('activityMonitor');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getDevDocsMonitor() {
|
|
60
|
+
if (!this.instances.has('devDocsMonitor')) {
|
|
61
|
+
const logger = this.serviceFactory.getLogger();
|
|
62
|
+
const notificationService = this.serviceFactory.getNotificationService();
|
|
63
|
+
this.instances.set('devDocsMonitor', new DevDocsMonitor({
|
|
64
|
+
repoRoot: this.repoRoot,
|
|
65
|
+
checkIntervalMs: env.getNumber('HOOK_GUARD_DEV_DOCS_CHECK_INTERVAL', 300000),
|
|
66
|
+
staleThresholdMs: env.getNumber('HOOK_GUARD_DEV_DOCS_STALE_THRESHOLD', 86400000),
|
|
67
|
+
autoRefreshEnabled: env.getBool('HOOK_GUARD_DEV_DOCS_AUTO_REFRESH', true),
|
|
68
|
+
logger,
|
|
69
|
+
notificationService
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
return this.instances.get('devDocsMonitor');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getAstMonitor() {
|
|
76
|
+
if (!this.instances.has('astMonitor')) {
|
|
77
|
+
const logger = this.serviceFactory.getLogger();
|
|
78
|
+
const notificationService = this.serviceFactory.getNotificationService();
|
|
79
|
+
this.instances.set('astMonitor', new AstMonitor({
|
|
80
|
+
repoRoot: this.repoRoot,
|
|
81
|
+
debounceMs: env.getNumber('HOOK_AST_WATCH_DEBOUNCE', 8000),
|
|
82
|
+
cooldownMs: env.getNumber('HOOK_AST_WATCH_COOLDOWN', 30000),
|
|
83
|
+
enabled: env.getBool('HOOK_AST_WATCH', true),
|
|
84
|
+
logger,
|
|
85
|
+
notificationService
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
return this.instances.get('astMonitor');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
getMonitors() {
|
|
92
|
+
return {
|
|
93
|
+
evidence: this.getEvidenceMonitor(),
|
|
94
|
+
gitTree: this.getGitTreeMonitor(),
|
|
95
|
+
token: this.getTokenMonitor(),
|
|
96
|
+
gitFlow: this.serviceFactory.getGitFlowService(),
|
|
97
|
+
activity: this.getActivityMonitor(),
|
|
98
|
+
devDocs: this.getDevDocsMonitor(),
|
|
99
|
+
ast: this.getAstMonitor()
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = MonitorFactory;
|