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,9 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const { getGitTreeState, isTreeBeyondLimit } = require('./GitTreeState');
4
- const AuditLogger = require('./logging/AuditLogger');
5
- const { recordMetric } = require('../../infrastructure/telemetry/metrics-logger');
6
- const env = require('../../config/env');
7
4
 
8
5
  class RealtimeGuardService {
9
6
  /**
@@ -15,12 +12,6 @@ class RealtimeGuardService {
15
12
  * @param {Object} dependencies.config
16
13
  */
17
14
  constructor(dependencies = {}) {
18
- this._initializeDependencies(dependencies);
19
- this._initializeConfiguration();
20
- this._initializeMonitors();
21
- }
22
-
23
- _initializeDependencies(dependencies = {}) {
24
15
  const {
25
16
  logger,
26
17
  notificationService,
@@ -39,49 +30,39 @@ class RealtimeGuardService {
39
30
  this.monitors = monitors || {};
40
31
  this.orchestration = orchestration;
41
32
  this.config = config || {};
42
- this.auditLogger = dependencies.auditLogger || new AuditLogger({ repoRoot: process.cwd(), logger: this.logger });
43
- }
44
33
 
45
- _initializeConfiguration() {
46
34
  if (!this.config.debugLogPath) {
47
35
  this.config.debugLogPath = path.join(process.cwd(), '.audit-reports', 'guard-debug.log');
48
36
  }
49
37
 
50
- this.evidencePath = this.config.evidencePath || path.join(env.get('REPO_ROOT', process.cwd()), '.AI_EVIDENCE.json');
51
- this.staleThresholdMs = env.getNumber('HOOK_GUARD_EVIDENCE_STALE_THRESHOLD', 60000);
52
- this.reminderIntervalMs = env.getNumber('HOOK_GUARD_EVIDENCE_REMINDER_INTERVAL', 60000);
53
- this.inactivityGraceMs = env.getNumber('HOOK_GUARD_INACTIVITY_GRACE_MS', 120000);
54
- this.pollIntervalMs = env.getNumber('HOOK_GUARD_EVIDENCE_POLL_INTERVAL', 30000);
38
+ this.evidencePath = this.config.evidencePath || path.join(process.cwd(), '.AI_EVIDENCE.json');
39
+ this.staleThresholdMs = Number(process.env.HOOK_GUARD_EVIDENCE_STALE_THRESHOLD || 60000);
40
+ this.reminderIntervalMs = Number(process.env.HOOK_GUARD_EVIDENCE_REMINDER_INTERVAL || 60000);
41
+ this.inactivityGraceMs = Number(process.env.HOOK_GUARD_INACTIVITY_GRACE_MS || 120000);
42
+ this.pollIntervalMs = Number(process.env.HOOK_GUARD_EVIDENCE_POLL_INTERVAL || 30000);
55
43
  this.pollTimer = null;
56
44
  this.lastStaleNotification = 0;
57
45
  this.lastUserActivityAt = 0;
58
46
 
59
- this.gitTreeStagedThreshold = env.getNumber('HOOK_GUARD_DIRTY_TREE_STAGED_LIMIT', 10);
60
- this.gitTreeUnstagedThreshold = env.getNumber('HOOK_GUARD_DIRTY_TREE_UNSTAGED_LIMIT', 15);
61
- this.gitTreeTotalThreshold = env.getNumber('HOOK_GUARD_DIRTY_TREE_TOTAL_LIMIT', 20);
62
- this.gitTreeCheckIntervalMs = env.getNumber('HOOK_GUARD_DIRTY_TREE_INTERVAL', 60000);
63
- this.gitTreeReminderMs = env.getNumber('HOOK_GUARD_DIRTY_TREE_REMINDER', 300000);
47
+ this.gitTreeStagedThreshold = Number(process.env.HOOK_GUARD_DIRTY_TREE_STAGED_LIMIT || 10);
48
+ this.gitTreeUnstagedThreshold = Number(process.env.HOOK_GUARD_DIRTY_TREE_UNSTAGED_LIMIT || 15);
49
+ this.gitTreeTotalThreshold = Number(process.env.HOOK_GUARD_DIRTY_TREE_TOTAL_LIMIT || 20);
50
+ this.gitTreeCheckIntervalMs = Number(process.env.HOOK_GUARD_DIRTY_TREE_INTERVAL || 60000);
51
+ this.gitTreeReminderMs = Number(process.env.HOOK_GUARD_DIRTY_TREE_REMINDER || 300000);
64
52
  this.gitTreeTimer = null;
65
53
  this.lastDirtyTreeNotification = 0;
66
54
  this.dirtyTreeActive = false;
67
55
 
68
- this.autoRefreshCooldownMs = env.getNumber('HOOK_GUARD_EVIDENCE_AUTO_REFRESH_COOLDOWN', 180000);
56
+ this.autoRefreshCooldownMs = Number(process.env.HOOK_GUARD_EVIDENCE_AUTO_REFRESH_COOLDOWN || 180000);
69
57
  this.lastAutoRefresh = 0;
70
58
  this.autoRefreshInFlight = false;
71
59
 
72
60
  this.watchers = [];
73
- this.embedTokenMonitor = env.getBool('HOOK_GUARD_EMBEDDED_TOKEN_MONITOR', false);
74
- }
75
-
76
- _initializeMonitors() {
77
- // Monitors are configured but not started here
78
- // They are started in the start() method to allow for proper initialization order
61
+ this.embedTokenMonitor = process.env.HOOK_GUARD_EMBEDDED_TOKEN_MONITOR === 'true';
79
62
  }
80
63
 
81
64
  start() {
82
65
  this.logger.info('Starting RealtimeGuardService...');
83
- this.auditLogger.record({ action: 'guard.realtime.start', resource: 'realtime_guard', status: 'success' });
84
- recordMetric({ hook: 'realtime_guard', status: 'start' });
85
66
 
86
67
  // Start all monitors
87
68
  this._startEvidenceMonitoring();
@@ -101,8 +82,6 @@ class RealtimeGuardService {
101
82
 
102
83
  stop() {
103
84
  this.logger.info('Stopping RealtimeGuardService...');
104
- this.auditLogger.record({ action: 'guard.realtime.stop', resource: 'realtime_guard', status: 'success' });
105
- recordMetric({ hook: 'realtime_guard', status: 'stop' });
106
85
 
107
86
  this.watchers.forEach(w => w.close());
108
87
  this.watchers = [];
@@ -124,27 +103,14 @@ class RealtimeGuardService {
124
103
  }
125
104
 
126
105
  _startGitTreeMonitoring() {
127
- if (env.getBool('HOOK_GUARD_DIRTY_TREE_DISABLED', false)) return;
106
+ if (process.env.HOOK_GUARD_DIRTY_TREE_DISABLED === 'true') return;
128
107
 
129
108
  this.monitors.gitTree.startMonitoring((state) => {
130
109
  if (state.isBeyondLimit) {
131
110
  const message = `Git tree has too many files: ${state.total} total (${state.staged} staged, ${state.unstaged} unstaged)`;
132
111
  this.notify(message, 'error', { forceDialog: true });
133
- this.auditLogger.record({
134
- action: 'guard.git_tree.dirty',
135
- resource: 'git_tree',
136
- status: 'warning',
137
- meta: { total: state.total, staged: state.staged, unstaged: state.unstaged }
138
- });
139
- recordMetric({ hook: 'git_tree', status: 'dirty', total: state.total, staged: state.staged, unstaged: state.unstaged });
140
112
  } else {
141
113
  this.notify('✅ Git tree is clean', 'success');
142
- this.auditLogger.record({
143
- action: 'guard.git_tree.clean',
144
- resource: 'git_tree',
145
- status: 'success'
146
- });
147
- recordMetric({ hook: 'git_tree', status: 'clean' });
148
114
  }
149
115
  });
150
116
  }
@@ -158,44 +124,22 @@ class RealtimeGuardService {
158
124
  try {
159
125
  this.monitors.token.start();
160
126
  this.notify('🔋 Token monitor started', 'info');
161
- this.auditLogger.record({
162
- action: 'guard.token_monitor.start',
163
- resource: 'token_monitor',
164
- status: 'success'
165
- });
166
- recordMetric({ hook: 'token_monitor', status: 'start' });
167
127
  } catch (error) {
168
128
  this.notify(`Failed to start token monitor: ${error.message}`, 'error');
169
- this.auditLogger.record({
170
- action: 'guard.token_monitor.start',
171
- resource: 'token_monitor',
172
- status: 'fail',
173
- meta: { message: error.message }
174
- });
175
- recordMetric({ hook: 'token_monitor', status: 'fail' });
176
129
  }
177
130
  }
178
131
 
179
132
  _startGitFlowSync() {
180
133
  if (!this.monitors.gitFlow.autoSyncEnabled) return;
181
134
 
182
- this.auditLogger.record({
183
- action: 'guard.gitflow.autosync.enabled',
184
- resource: 'gitflow',
185
- status: 'success',
186
- meta: { intervalMs: env.getNumber('HOOK_GUARD_GITFLOW_AUTOSYNC_INTERVAL', 300000) }
187
- });
188
- recordMetric({ hook: 'gitflow_autosync', status: 'enabled' });
189
-
190
135
  const syncInterval = setInterval(() => {
191
136
  if (this.monitors.gitFlow.isClean()) {
192
137
  const result = this.monitors.gitFlow.syncBranches();
193
138
  if (result.success) {
194
139
  this.notify('🔄 Branches synchronized', 'info');
195
- recordMetric({ hook: 'gitflow_autosync', status: 'sync_success' });
196
140
  }
197
141
  }
198
- }, env.getNumber('HOOK_GUARD_GITFLOW_AUTOSYNC_INTERVAL', 300000));
142
+ }, Number(process.env.HOOK_GUARD_GITFLOW_AUTOSYNC_INTERVAL || 300000));
199
143
 
200
144
  syncInterval.unref();
201
145
  }
@@ -303,18 +247,11 @@ class RealtimeGuardService {
303
247
  this.lastStaleNotification = now;
304
248
  const ageSec = Math.floor(ageMs / 1000);
305
249
  this.notify(`Evidence has been stale for ${ageSec}s (source: ${source}).`, 'warn', { forceDialog: true });
306
- this.auditLogger.record({
307
- action: 'guard.evidence.stale',
308
- resource: 'evidence',
309
- status: 'warning',
310
- meta: { ageSec, source }
311
- });
312
- recordMetric({ hook: 'evidence', status: 'stale', ageSec, source });
313
250
  void this.attemptAutoRefresh('stale');
314
251
  }
315
252
 
316
253
  async attemptAutoRefresh(reason = 'manual') {
317
- if (!env.getBool('HOOK_GUARD_AUTO_REFRESH', false)) {
254
+ if (process.env.HOOK_GUARD_AUTO_REFRESH !== 'true') {
318
255
  return;
319
256
  }
320
257
 
@@ -347,13 +284,6 @@ class RealtimeGuardService {
347
284
  try {
348
285
  await this.runDirectEvidenceRefresh(reason);
349
286
  this.lastAutoRefresh = now;
350
- this.auditLogger.record({
351
- action: 'guard.evidence.auto_refresh',
352
- resource: 'evidence',
353
- status: 'success',
354
- meta: { reason }
355
- });
356
- recordMetric({ hook: 'evidence', status: 'auto_refresh_success', reason });
357
287
  } finally {
358
288
  this.autoRefreshInFlight = false;
359
289
  }
@@ -10,9 +10,6 @@ const GuardConfig = require('./GuardConfig');
10
10
  const GuardNotificationHandler = require('./GuardNotificationHandler');
11
11
  const GuardMonitorLoop = require('./GuardMonitorLoop');
12
12
  const GuardHealthReminder = require('./GuardHealthReminder');
13
- const AuditLogger = require('../logging/AuditLogger');
14
- const envHelper = require('../../../config/env');
15
- const { recordMetric } = require('../../../infrastructure/telemetry/metrics-logger');
16
13
 
17
14
  class GuardAutoManagerService {
18
15
  constructor({
@@ -22,10 +19,9 @@ class GuardAutoManagerService {
22
19
  fsModule = fs,
23
20
  childProcess = { spawnSync },
24
21
  timers = { setInterval, clearInterval },
25
- env = envHelper,
22
+ env = process.env,
26
23
  processRef = process,
27
- heartbeatMonitor = null,
28
- auditLogger = null
24
+ heartbeatMonitor = null
29
25
  } = {}) {
30
26
  this.process = processRef;
31
27
 
@@ -34,7 +30,6 @@ class GuardAutoManagerService {
34
30
  this.eventLogger = new GuardEventLogger({ repoRoot, logger, fsModule });
35
31
  this.lockManager = new GuardLockManager({ repoRoot, logger, fsModule });
36
32
  this.processManager = new GuardProcessManager({ repoRoot, logger, fsModule, childProcess });
37
- this.auditLogger = auditLogger || new AuditLogger({ repoRoot, logger });
38
33
 
39
34
  // Monitors & Handlers
40
35
  this.heartbeatMonitor = heartbeatMonitor || new GuardHeartbeatMonitor({
@@ -64,14 +59,10 @@ class GuardAutoManagerService {
64
59
  start() {
65
60
  if (!this.lockManager.acquireLock()) {
66
61
  this.eventLogger.log('Another guard auto manager instance detected. Exiting.');
67
- this.auditLogger.record({ action: 'guard.lock.acquire', resource: 'guard_auto_manager', status: 'fail', meta: { reason: 'lock_exists' } });
68
- recordMetric({ hook: 'guard_auto_manager', status: 'lock_fail' });
69
62
  return false;
70
63
  }
71
64
  this.lockManager.writePidFile();
72
65
  this.eventLogger.log('Guard auto manager started');
73
- this.auditLogger.record({ action: 'guard.manager.start', resource: 'guard_auto_manager', status: 'success' });
74
- recordMetric({ hook: 'guard_auto_manager', status: 'start' });
75
66
 
76
67
  this.ensureSupervisor('initial-start');
77
68
  this._startReminder();
@@ -103,12 +94,6 @@ class GuardAutoManagerService {
103
94
  handleMissingSupervisor() {
104
95
  this.lastHeartbeatState = { healthy: false, reason: 'missing-supervisor' };
105
96
  this.eventLogger.recordEvent('Guard supervisor no se encuentra en ejecución; reinicio automático.');
106
- this.auditLogger.record({
107
- action: 'guard.supervisor.missing',
108
- resource: 'guard_supervisor',
109
- status: 'fail',
110
- meta: { reason: 'missing-supervisor' }
111
- });
112
97
  this.ensureSupervisor('missing-supervisor');
113
98
  }
114
99
 
@@ -121,21 +106,9 @@ class GuardAutoManagerService {
121
106
  this.eventLogger.log(`Heartbeat degraded (${heartbeat.reason}); attempting supervisor ensure.`);
122
107
  this.lastHeartbeatRestart = now;
123
108
  this.ensureSupervisor(`heartbeat-${heartbeat.reason}`);
124
- this.auditLogger.record({
125
- action: 'guard.supervisor.ensure',
126
- resource: 'guard_supervisor',
127
- status: 'success',
128
- meta: { reason: heartbeat.reason }
129
- });
130
109
  } else {
131
110
  this.eventLogger.log(`Heartbeat degraded (${heartbeat.reason}); restart suppressed (cooldown).`);
132
111
  this.eventLogger.recordEvent(`Heartbeat degradado (${heartbeat.reason}); reinicio omitido por cooldown.`);
133
- this.auditLogger.record({
134
- action: 'guard.supervisor.ensure',
135
- resource: 'guard_supervisor',
136
- status: 'fail',
137
- meta: { reason: heartbeat.reason, suppressed: true }
138
- });
139
112
  }
140
113
  } else {
141
114
  this.eventLogger.recordEvent(`Heartbeat en estado ${heartbeat.reason}; reinicio no requerido.`);
@@ -175,8 +148,6 @@ class GuardAutoManagerService {
175
148
  this.lockManager.removePidFile();
176
149
  this.lockManager.releaseLock();
177
150
  this.healthReminder.stop();
178
- this.auditLogger.record({ action: 'guard.manager.stop', resource: 'guard_auto_manager', status: 'success' });
179
- recordMetric({ hook: 'guard_auto_manager', status: 'stop' });
180
151
  }
181
152
 
182
153
  ensureSupervisor(reason) {
@@ -1,22 +1,14 @@
1
- const envHelper = require('../../../config/env');
2
-
3
1
  class GuardConfig {
4
- constructor(env = envHelper) {
5
- const getNumber = (name, def) =>
6
- typeof env.getNumber === 'function' ? env.getNumber(name, def) : Number(env[name] || def);
7
- const getBool = (name, def) =>
8
- typeof env.getBool === 'function' ? env.getBool(name, def) : (env[name] !== 'false');
9
-
10
- this.healthyReminderIntervalMs = getNumber('GUARD_AUTOSTART_HEALTHY_INTERVAL', 0);
11
- this.heartbeatNotifyCooldownMs = getNumber('GUARD_AUTOSTART_NOTIFY_COOLDOWN', 60000);
12
- this.healthyReminderCooldownMs = getNumber(
13
- 'GUARD_AUTOSTART_HEALTHY_COOLDOWN',
14
- this.healthyReminderIntervalMs > 0 ? this.healthyReminderIntervalMs : 0
2
+ constructor(env = process.env) {
3
+ this.healthyReminderIntervalMs = Number(env.GUARD_AUTOSTART_HEALTHY_INTERVAL || 0);
4
+ this.heartbeatNotifyCooldownMs = Number(env.GUARD_AUTOSTART_NOTIFY_COOLDOWN || 60000);
5
+ this.healthyReminderCooldownMs = Number(
6
+ env.GUARD_AUTOSTART_HEALTHY_COOLDOWN || (this.healthyReminderIntervalMs > 0 ? this.healthyReminderIntervalMs : 0)
15
7
  );
16
- this.heartbeatRestartCooldownMs = getNumber('GUARD_AUTOSTART_HEARTBEAT_COOLDOWN', 60000);
17
- this.monitorIntervalMs = getNumber('GUARD_AUTOSTART_MONITOR_INTERVAL', 5000);
18
- this.restartCooldownMs = getNumber('GUARD_AUTOSTART_RESTART_COOLDOWN', 2000);
19
- this.stopSupervisorOnExit = getBool('GUARD_AUTOSTART_STOP_SUPERVISOR_ON_EXIT', true);
8
+ this.heartbeatRestartCooldownMs = Number(env.GUARD_AUTOSTART_HEARTBEAT_COOLDOWN || 60000);
9
+ this.monitorIntervalMs = Number(env.GUARD_AUTOSTART_MONITOR_INTERVAL || 5000);
10
+ this.restartCooldownMs = Number(env.GUARD_AUTOSTART_RESTART_COOLDOWN || 2000);
11
+ this.stopSupervisorOnExit = env.GUARD_AUTOSTART_STOP_SUPERVISOR_ON_EXIT !== 'false';
20
12
  }
21
13
  }
22
14
 
@@ -1,26 +1,29 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const env = require('../../../config/env');
4
3
 
5
4
  class GuardHeartbeatMonitor {
6
5
  constructor({
7
6
  repoRoot = process.cwd(),
8
7
  logger = console,
9
- fsModule = fs
8
+ fsModule = fs,
9
+ env = process.env
10
10
  } = {}) {
11
11
  this.repoRoot = repoRoot;
12
12
  this.logger = logger;
13
13
  this.fs = fsModule;
14
- const heartbeatRelative = env.get('HOOK_GUARD_HEARTBEAT_PATH', path.join('.audit_tmp', 'guard-heartbeat.json'));
14
+ this.env = env;
15
+
16
+ const heartbeatRelative = env.HOOK_GUARD_HEARTBEAT_PATH || path.join('.audit_tmp', 'guard-heartbeat.json');
15
17
  this.heartbeatPath = path.isAbsolute(heartbeatRelative)
16
18
  ? heartbeatRelative
17
19
  : path.join(this.repoRoot, heartbeatRelative);
18
20
 
19
- this.heartbeatMaxAgeMs = env.getNumber('GUARD_AUTOSTART_HEARTBEAT_MAX_AGE',
20
- env.getNumber('HOOK_GUARD_HEARTBEAT_MAX_AGE', 60000));
21
+ this.heartbeatMaxAgeMs = Number(
22
+ env.GUARD_AUTOSTART_HEARTBEAT_MAX_AGE || env.HOOK_GUARD_HEARTBEAT_MAX_AGE || 60000
23
+ );
21
24
 
22
25
  this.heartbeatRestartReasons = new Set(
23
- (env.get('GUARD_AUTOSTART_HEARTBEAT_RESTART', 'missing,stale,invalid,degraded'))
26
+ (env.GUARD_AUTOSTART_HEARTBEAT_RESTART || 'missing,stale,invalid,degraded')
24
27
  .split(',')
25
28
  .map(entry => entry.trim().toLowerCase())
26
29
  .filter(Boolean)
@@ -1,9 +1,6 @@
1
1
  const path = require('path');
2
2
  const { spawnSync } = require('child_process');
3
3
 
4
- // Import AuditLogger for logging critical operations
5
- const AuditLogger = require('../logging/AuditLogger');
6
-
7
4
  class GuardProcessManager {
8
5
  constructor({
9
6
  repoRoot = process.cwd(),
@@ -18,10 +15,6 @@ class GuardProcessManager {
18
15
 
19
16
  this.supervisorPidFile = path.join(this.repoRoot, '.guard-supervisor.pid');
20
17
  this.startScript = path.join(this.repoRoot, 'bin', 'start-guards.sh');
21
- this.busy = false;
22
-
23
- // Initialize audit logger
24
- this.auditLogger = new AuditLogger({ repoRoot, logger: this.logger });
25
18
  }
26
19
 
27
20
  isSupervisorRunning() {
@@ -65,15 +58,6 @@ class GuardProcessManager {
65
58
  }
66
59
 
67
60
  startSupervisor() {
68
- if (this.busy) {
69
- return {
70
- success: false,
71
- error: new Error('bulkhead_busy'),
72
- stdout: '',
73
- stderr: 'bulkhead_busy'
74
- };
75
- }
76
- this.busy = true;
77
61
  try {
78
62
  const result = this.childProcess.spawnSync(this.startScript, ['start'], {
79
63
  cwd: this.repoRoot,
@@ -96,21 +80,10 @@ class GuardProcessManager {
96
80
  stdout: '',
97
81
  stderr: error.message
98
82
  };
99
- } finally {
100
- this.busy = false;
101
83
  }
102
84
  }
103
85
 
104
86
  stopSupervisor() {
105
- if (this.busy) {
106
- return {
107
- success: false,
108
- error: new Error('bulkhead_busy'),
109
- stdout: '',
110
- stderr: 'bulkhead_busy'
111
- };
112
- }
113
- this.busy = true;
114
87
  try {
115
88
  const result = this.childProcess.spawnSync(this.startScript, ['stop'], {
116
89
  cwd: this.repoRoot,
@@ -133,8 +106,6 @@ class GuardProcessManager {
133
106
  stdout: '',
134
107
  stderr: error.message
135
108
  };
136
- } finally {
137
- this.busy = false;
138
109
  }
139
110
  }
140
111
  }
@@ -2,9 +2,6 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const { execSync, spawnSync } = require('child_process');
4
4
 
5
- // Import recordMetric for prometheus metrics
6
- const { recordMetric } = require('../../../infrastructure/telemetry/metrics-logger');
7
-
8
5
  const COLORS = {
9
6
  reset: '\x1b[0m',
10
7
  blue: '\x1b[34m',
@@ -113,7 +110,7 @@ fi
113
110
 
114
111
  # Try node_modules/.bin first (works with npm install)
115
112
  if [ -f "node_modules/.bin/ast-hooks" ]; then
116
- OUTPUT=$(node_modules/.bin/ast-hooks ast --staged 2>&1)
113
+ OUTPUT=$(node_modules/.bin/ast-hooks ast 2>&1)
117
114
  EXIT_CODE=$?
118
115
  echo "$OUTPUT"
119
116
  if [ $EXIT_CODE -ne 0 ]; then
@@ -3,7 +3,6 @@ const path = require('path');
3
3
  const { execSync } = require('child_process');
4
4
  const crypto = require('crypto');
5
5
  const os = require('os');
6
- const env = require('../../config/env');
7
6
 
8
7
  const COLORS = {
9
8
  reset: '\x1b[0m',
@@ -32,7 +31,7 @@ function computeRepoFingerprint(repoRoot) {
32
31
 
33
32
  function computeServerIdForRepo(repoRoot) {
34
33
  const legacyServerId = 'ast-intelligence-automation';
35
- const forced = (env.get('MCP_SERVER_ID', '') || '').trim();
34
+ const forced = (process.env.MCP_SERVER_ID || '').trim();
36
35
  if (forced.length > 0) return forced;
37
36
 
38
37
  const repoName = path.basename(repoRoot || process.cwd());
@@ -1,6 +1,9 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
+ // Import recordMetric for prometheus metrics
5
+ const { recordMetric } = require('../../../infrastructure/telemetry/metrics-logger');
6
+
4
7
  class AuditLogger {
5
8
  /**
6
9
  * @param {Object} options
@@ -9,6 +12,13 @@ class AuditLogger {
9
12
  * @param {Object} [options.logger=console] - fallback logger for warnings
10
13
  */
11
14
  constructor({ repoRoot = process.cwd(), filename, logger = console } = {}) {
15
+ recordMetric({
16
+ hook: 'audit_logger',
17
+ operation: 'constructor',
18
+ status: 'started',
19
+ repoRoot: repoRoot.substring(0, 100)
20
+ });
21
+
12
22
  this.repoRoot = repoRoot;
13
23
  this.logger = logger;
14
24
  this.logPath = filename
@@ -16,9 +26,22 @@ class AuditLogger {
16
26
  : path.join(repoRoot, '.audit_tmp', 'audit.log');
17
27
 
18
28
  this.ensureDir();
29
+
30
+ recordMetric({
31
+ hook: 'audit_logger',
32
+ operation: 'constructor',
33
+ status: 'success',
34
+ repoRoot: repoRoot.substring(0, 100)
35
+ });
19
36
  }
20
37
 
21
38
  ensureDir() {
39
+ recordMetric({
40
+ hook: 'audit_logger',
41
+ operation: 'ensure_dir',
42
+ status: 'started'
43
+ });
44
+
22
45
  try {
23
46
  const dir = path.dirname(this.logPath);
24
47
  if (!fs.existsSync(dir)) {
@@ -30,14 +53,33 @@ class AuditLogger {
30
53
  } catch (error) {
31
54
  this.warn('AUDIT_LOGGER_INIT_ERROR', error);
32
55
  }
56
+
57
+ recordMetric({
58
+ hook: 'audit_logger',
59
+ operation: 'ensure_dir',
60
+ status: 'success'
61
+ });
33
62
  }
34
63
 
35
64
  warn(message, error) {
65
+ recordMetric({
66
+ hook: 'audit_logger',
67
+ operation: 'warn',
68
+ status: 'started',
69
+ message: message
70
+ });
71
+
36
72
  if (this.logger?.warn) {
37
73
  this.logger.warn(message, { error: error?.message });
38
74
  } else {
39
75
  console.warn(message, error?.message);
40
76
  }
77
+
78
+ recordMetric({
79
+ hook: 'audit_logger',
80
+ operation: 'warn',
81
+ status: 'success'
82
+ });
41
83
  }
42
84
 
43
85
  /**
@@ -50,7 +92,22 @@ class AuditLogger {
50
92
  * @param {string|null} [entry.correlationId=null]
51
93
  */
52
94
  record(entry = {}) {
53
- if (!entry.action) return;
95
+ recordMetric({
96
+ hook: 'audit_logger',
97
+ operation: 'record',
98
+ status: 'started',
99
+ action: entry.action
100
+ });
101
+
102
+ if (!entry.action) {
103
+ recordMetric({
104
+ hook: 'audit_logger',
105
+ operation: 'record',
106
+ status: 'success',
107
+ reason: 'no_action'
108
+ });
109
+ return;
110
+ }
54
111
  const safeMeta = this.sanitizeMeta(entry.meta || {});
55
112
 
56
113
  const payload = {
@@ -65,12 +122,32 @@ class AuditLogger {
65
122
 
66
123
  try {
67
124
  fs.appendFileSync(this.logPath, `${JSON.stringify(payload)}\n`, { encoding: 'utf8' });
125
+ recordMetric({
126
+ hook: 'audit_logger',
127
+ operation: 'record',
128
+ status: 'success',
129
+ action: entry.action
130
+ });
68
131
  } catch (error) {
69
132
  this.warn('AUDIT_LOGGER_WRITE_ERROR', error);
133
+ recordMetric({
134
+ hook: 'audit_logger',
135
+ operation: 'record',
136
+ status: 'failed',
137
+ action: entry.action,
138
+ error: error.message
139
+ });
70
140
  }
71
141
  }
72
142
 
73
143
  sanitizeMeta(meta) {
144
+ recordMetric({
145
+ hook: 'audit_logger',
146
+ operation: 'sanitize_meta',
147
+ status: 'started',
148
+ metaKeys: Object.keys(meta || {}).length
149
+ });
150
+
74
151
  const forbidden = ['token', 'password', 'secret', 'authorization', 'auth', 'apiKey'];
75
152
  const clone = {};
76
153
  Object.entries(meta).forEach(([k, v]) => {
@@ -81,6 +158,14 @@ class AuditLogger {
81
158
  clone[k] = v;
82
159
  }
83
160
  });
161
+
162
+ recordMetric({
163
+ hook: 'audit_logger',
164
+ operation: 'sanitize_meta',
165
+ status: 'success',
166
+ metaKeys: Object.keys(clone).length
167
+ });
168
+
84
169
  return clone;
85
170
  }
86
171
  }
@@ -97,19 +97,10 @@ class UnifiedLogger {
97
97
  this.rotateFileIfNeeded();
98
98
  fs.appendFileSync(this.fileConfig.path, `${JSON.stringify(entry)}\n`, 'utf8');
99
99
  } catch (error) {
100
- try {
101
- const env = require('../../../config/env');
102
- if (env.getBool('DEBUG', false)) {
103
- console.error('[UnifiedLogger] Failed to write log file', {
104
- path: this.fileConfig.path,
105
- error: error.message
106
- });
107
- } else {
108
- console.warn('[UnifiedLogger] File logging skipped due to error');
109
- }
110
- } catch (secondaryError) {
111
- console.error('[UnifiedLogger] Secondary logging failure', {
112
- error: secondaryError.message
100
+ if (process.env.DEBUG) {
101
+ console.error('[UnifiedLogger] Failed to write log file', {
102
+ path: this.fileConfig.path,
103
+ error: error.message
113
104
  });
114
105
  }
115
106
  }
@@ -19,6 +19,7 @@ class EvidenceMonitor {
19
19
  resolveUpdateEvidenceScript() {
20
20
  const candidates = [
21
21
  path.join(this.repoRoot, 'node_modules/@pumuki/ast-intelligence-hooks/bin/update-evidence.sh'),
22
+ path.join(this.repoRoot, 'scripts/hooks-system/bin/update-evidence.sh'),
22
23
  path.join(this.repoRoot, 'bin/update-evidence.sh')
23
24
  ];
24
25
 
@@ -1,10 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const { execSync } = require('child_process');
4
- const env = require('../../config/env');
5
-
6
- // Import recordMetric for prometheus metrics
7
- const { recordMetric } = require('../../../infrastructure/telemetry/metrics-logger');
8
4
 
9
5
  function resolveUpdateEvidenceScript(repoRoot) {
10
6
  const candidates = [
@@ -29,9 +25,9 @@ class EvidenceMonitorService {
29
25
  updateScriptPath = resolveUpdateEvidenceScript(repoRoot) || path.join(process.cwd(), 'scripts', 'hooks-system', 'bin', 'update-evidence.sh'),
30
26
  notifier = () => { },
31
27
  logger = console,
32
- autoRefreshEnabled = env.getBool('HOOK_GUARD_AUTO_REFRESH', true),
33
- autoRefreshCooldownMs = env.getNumber('HOOK_GUARD_AUTO_REFRESH_COOLDOWN', 180000),
34
- staleThresholdMs = env.getNumber('HOOK_GUARD_EVIDENCE_STALE_THRESHOLD', 10 * 60 * 1000),
28
+ autoRefreshEnabled = process.env.HOOK_GUARD_AUTO_REFRESH !== 'false',
29
+ autoRefreshCooldownMs = Number(process.env.HOOK_GUARD_AUTO_REFRESH_COOLDOWN || 180000),
30
+ staleThresholdMs = Number(process.env.HOOK_GUARD_EVIDENCE_STALE_THRESHOLD || 10 * 60 * 1000),
35
31
  fsModule = fs,
36
32
  execFn = execSync
37
33
  } = {}) {