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
@@ -7,8 +7,6 @@ class iOSArchitectureRules {
7
7
  }
8
8
 
9
9
  runRules(files) {
10
- console.log(`[iOS Architecture] Detected pattern: ${this.pattern}`);
11
-
12
10
  switch (this.pattern) {
13
11
  case 'FEATURE_FIRST_CLEAN_DDD':
14
12
  this.checkFeatureFirstCleanDDDRules(files);
@@ -16,9 +14,6 @@ class iOSArchitectureRules {
16
14
  case 'MVVM':
17
15
  this.checkMVVMRules(files);
18
16
  break;
19
- case 'MVVM-C':
20
- this.checkMVVMCRules(files);
21
- break;
22
17
  case 'MVP':
23
18
  this.checkMVPRules(files);
24
19
  break;
@@ -38,7 +33,7 @@ class iOSArchitectureRules {
38
33
  this.checkMixedArchitectureRules(files);
39
34
  break;
40
35
  default:
41
- console.log(`[iOS Architecture] No specific rules for pattern: ${this.pattern}`);
36
+ break;
42
37
  }
43
38
  }
44
39
 
@@ -68,10 +63,10 @@ class iOSArchitectureRules {
68
63
  });
69
64
 
70
65
  if (file.includes('/domain/') && !file.includes('/entities/') &&
71
- !file.includes('/value-objects/') && !file.includes('/interfaces/')) {
66
+ !file.includes('/value-objects/') && !file.includes('/interfaces/')) {
72
67
  pushFinding(this.findings, {
73
68
  ruleId: 'ios.clean.domain_structure',
74
- severity: 'medium',
69
+ severity: 'critical',
75
70
  message: 'Archivo en domain/ sin estructura correcta. Usar entities/, value-objects/, interfaces/',
76
71
  filePath: file,
77
72
  line: 1
@@ -86,7 +81,7 @@ class iOSArchitectureRules {
86
81
  if (hasProperties > 3 && hasMethods === 0) {
87
82
  pushFinding(this.findings, {
88
83
  ruleId: 'ios.ddd.anemic_entity',
89
- severity: 'high',
84
+ severity: 'critical',
90
85
  message: 'Entity anémica (solo properties, sin comportamiento). Añadir métodos de negocio.',
91
86
  filePath: file,
92
87
  line: 1,
@@ -99,7 +94,7 @@ class iOSArchitectureRules {
99
94
  if (content.includes('var ') && !content.includes('private(set)')) {
100
95
  pushFinding(this.findings, {
101
96
  ruleId: 'ios.ddd.mutable_value_object',
102
- severity: 'high',
97
+ severity: 'critical',
103
98
  message: 'Value Object con properties mutables. VOs deben ser inmutables (usar let).',
104
99
  filePath: file,
105
100
  line: 1,
@@ -110,7 +105,7 @@ class iOSArchitectureRules {
110
105
  if (!content.includes('init(') || !content.includes('throw')) {
111
106
  pushFinding(this.findings, {
112
107
  ruleId: 'ios.ddd.value_object_no_validation',
113
- severity: 'medium',
108
+ severity: 'critical',
114
109
  message: 'Value Object sin validación en init(). VOs deben garantizar invariantes.',
115
110
  filePath: file,
116
111
  line: 1,
@@ -128,7 +123,7 @@ class iOSArchitectureRules {
128
123
  if (!content.includes('func execute(')) {
129
124
  pushFinding(this.findings, {
130
125
  ruleId: 'ios.ddd.usecase_missing_execute',
131
- severity: 'high',
126
+ severity: 'critical',
132
127
  message: 'Use Case sin método execute(). Convención: func execute(input: Input) async throws -> Output',
133
128
  filePath: file,
134
129
  line: 1
@@ -138,7 +133,7 @@ class iOSArchitectureRules {
138
133
  if (content.includes('UIKit') || content.includes('SwiftUI')) {
139
134
  pushFinding(this.findings, {
140
135
  ruleId: 'ios.clean.usecase_ui_dependency',
141
- severity: 'high',
136
+ severity: 'critical',
142
137
  message: 'Use Case depende de UI framework. Application layer debe ser UI-agnostic.',
143
138
  filePath: file,
144
139
  line: 1
@@ -150,7 +145,7 @@ class iOSArchitectureRules {
150
145
  if (!file.includes('/infrastructure/')) {
151
146
  pushFinding(this.findings, {
152
147
  ruleId: 'ios.clean.repository_wrong_layer',
153
- severity: 'high',
148
+ severity: 'critical',
154
149
  message: 'Repository implementation fuera de infrastructure/. Mover a infrastructure/repositories/',
155
150
  filePath: file,
156
151
  line: 1
@@ -162,7 +157,7 @@ class iOSArchitectureRules {
162
157
  if (!file.includes('/domain/')) {
163
158
  pushFinding(this.findings, {
164
159
  ruleId: 'ios.clean.repository_interface_wrong_layer',
165
- severity: 'high',
160
+ severity: 'critical',
166
161
  message: 'Repository protocol fuera de domain/. Mover a domain/interfaces/',
167
162
  filePath: file,
168
163
  line: 1
@@ -174,7 +169,7 @@ class iOSArchitectureRules {
174
169
  if (!file.includes('/application/')) {
175
170
  pushFinding(this.findings, {
176
171
  ruleId: 'ios.clean.dto_wrong_layer',
177
- severity: 'medium',
172
+ severity: 'critical',
178
173
  message: 'DTO fuera de application/. Mover a application/dto/',
179
174
  filePath: file,
180
175
  line: 1
@@ -213,7 +208,7 @@ class iOSArchitectureRules {
213
208
  if (complexMethods.length > 0) {
214
209
  pushFinding(this.findings, {
215
210
  ruleId: 'ios.clean.infrastructure_business_logic',
216
- severity: 'high',
211
+ severity: 'critical',
217
212
  message: 'Infrastructure con lógica de negocio compleja. Mover a domain/ o application/',
218
213
  filePath: file,
219
214
  line: 1,
@@ -226,7 +221,7 @@ class iOSArchitectureRules {
226
221
  if (content.includes('Entity') && !content.includes('DTO') && !content.includes('Dto')) {
227
222
  pushFinding(this.findings, {
228
223
  ruleId: 'ios.clean.presentation_uses_entity',
229
- severity: 'medium',
224
+ severity: 'critical',
230
225
  message: 'Presentation usando Entities de domain directamente. Usar DTOs para desacoplar.',
231
226
  filePath: file,
232
227
  line: 1,
@@ -245,7 +240,7 @@ class iOSArchitectureRules {
245
240
  if (!content.includes('ObservableObject') && !content.includes('@Observable')) {
246
241
  pushFinding(this.findings, {
247
242
  ruleId: 'ios.mvvm.viewmodel_not_observable',
248
- severity: 'high',
243
+ severity: 'critical',
249
244
  message: 'ViewModel debe conformar ObservableObject o usar @Observable macro (iOS 17+)',
250
245
  filePath: file,
251
246
  line: 1
@@ -255,7 +250,7 @@ class iOSArchitectureRules {
255
250
  if (content.match(/import\s+UIKit/) && !content.includes('#if canImport(UIKit)')) {
256
251
  pushFinding(this.findings, {
257
252
  ruleId: 'ios.mvvm.viewmodel_uikit_dependency',
258
- severity: 'high',
253
+ severity: 'critical',
259
254
  message: 'ViewModel NO debe depender de UIKit. Usar tipos agnósticos de plataforma.',
260
255
  filePath: file,
261
256
  line: content.split('\n').findIndex(line => line.includes('import UIKit')) + 1
@@ -266,7 +261,7 @@ class iOSArchitectureRules {
266
261
  if (classMatch && content.includes('var ') && !content.includes('@Published')) {
267
262
  pushFinding(this.findings, {
268
263
  ruleId: 'ios.mvvm.missing_published',
269
- severity: 'medium',
264
+ severity: 'critical',
270
265
  message: 'ViewModel properties que cambian deben usar @Published para notificar a la View',
271
266
  filePath: file,
272
267
  line: 1
@@ -276,7 +271,7 @@ class iOSArchitectureRules {
276
271
 
277
272
  if (file.includes('View.swift') || content.includes('struct ') && content.includes(': View')) {
278
273
  const hasBusinessLogic =
279
- /func\s+\w+\([^)]*\)\s*->\s*\w+\s*{[\s\S]{100,}/.test(content) ||
274
+ /func\s+\w+\([^)]*\)\s*->\s*\w+\s*{[\s\S]{100,}/.test(content) ||
280
275
  content.includes('URLSession') ||
281
276
  content.includes('CoreData') ||
282
277
  /\.save\(|\.fetch\(|\.delete\(/.test(content);
@@ -284,7 +279,7 @@ class iOSArchitectureRules {
284
279
  if (hasBusinessLogic) {
285
280
  pushFinding(this.findings, {
286
281
  ruleId: 'ios.mvvm.view_business_logic',
287
- severity: 'high',
282
+ severity: 'critical',
288
283
  message: 'View contiene lógica de negocio. Mover al ViewModel.',
289
284
  filePath: file,
290
285
  line: 1
@@ -294,63 +289,6 @@ class iOSArchitectureRules {
294
289
  });
295
290
  }
296
291
 
297
- checkMVVMCRules(files) {
298
- this.checkMVVMRules(files);
299
-
300
- files.forEach(file => {
301
- const content = this.readFile(file);
302
-
303
- if (file.includes('Coordinator.swift')) {
304
- if (!content.includes('protocol Coordinator') && !content.includes(': Coordinator')) {
305
- pushFinding(this.findings, {
306
- ruleId: 'ios.mvvmc.coordinator_protocol',
307
- severity: 'medium',
308
- message: 'Coordinator debe conformar protocol Coordinator con start() y navigate(to:)',
309
- filePath: file,
310
- line: 1
311
- });
312
- }
313
-
314
- if (!/func\s+start\(\)/.test(content)) {
315
- pushFinding(this.findings, {
316
- ruleId: 'ios.mvvmc.coordinator_missing_start',
317
- severity: 'high',
318
- message: 'Coordinator debe implementar func start() para iniciar el flujo',
319
- filePath: file,
320
- line: 1
321
- });
322
- }
323
-
324
- const hasBusinessLogic =
325
- content.includes('URLSession') ||
326
- content.includes('CoreData') ||
327
- /\.save\(|\.fetch\(|\.delete\(/.test(content);
328
-
329
- if (hasBusinessLogic) {
330
- pushFinding(this.findings, {
331
- ruleId: 'ios.mvvmc.coordinator_business_logic',
332
- severity: 'high',
333
- message: 'Coordinator NO debe contener lógica de negocio. Solo navegación.',
334
- filePath: file,
335
- line: 1
336
- });
337
- }
338
- }
339
-
340
- if (file.includes('ViewModel.swift')) {
341
- if (content.includes('navigationController') || content.includes('.present(')) {
342
- pushFinding(this.findings, {
343
- ruleId: 'ios.mvvmc.viewmodel_navigation',
344
- severity: 'high',
345
- message: 'ViewModel NO debe manejar navegación. Delegar al Coordinator.',
346
- filePath: file,
347
- line: 1
348
- });
349
- }
350
- }
351
- });
352
- }
353
-
354
292
  checkMVPRules(files) {
355
293
  files.forEach(file => {
356
294
  const content = this.readFile(file);
@@ -359,7 +297,7 @@ class iOSArchitectureRules {
359
297
  if (!content.includes('protocol ') && content.includes('View')) {
360
298
  pushFinding(this.findings, {
361
299
  ruleId: 'ios.mvp.view_not_protocol',
362
- severity: 'high',
300
+ severity: 'critical',
363
301
  message: 'En MVP, View debe ser un protocol implementado por ViewController',
364
302
  filePath: file,
365
303
  line: 1
@@ -371,7 +309,7 @@ class iOSArchitectureRules {
371
309
  if (content.includes('var view:') && !content.includes('weak var view')) {
372
310
  pushFinding(this.findings, {
373
311
  ruleId: 'ios.mvp.presenter_strong_view',
374
- severity: 'high',
312
+ severity: 'critical',
375
313
  message: 'Presenter debe tener referencia weak a View para evitar retain cycles',
376
314
  filePath: file,
377
315
  line: content.split('\n').findIndex(line => line.includes('var view:')) + 1
@@ -385,7 +323,7 @@ class iOSArchitectureRules {
385
323
  if (hasLogic < 3) {
386
324
  pushFinding(this.findings, {
387
325
  ruleId: 'ios.mvp.presenter_thin',
388
- severity: 'medium',
326
+ severity: 'critical',
389
327
  message: 'Presenter parece tener poca lógica. En MVP, Presenter debe contener toda la lógica de presentación.',
390
328
  filePath: file,
391
329
  line: 1
@@ -402,7 +340,7 @@ class iOSArchitectureRules {
402
340
  if (hasBusinessLogic) {
403
341
  pushFinding(this.findings, {
404
342
  ruleId: 'ios.mvp.viewcontroller_business_logic',
405
- severity: 'high',
343
+ severity: 'critical',
406
344
  message: 'ViewController NO debe contener lógica de negocio. Delegar al Presenter.',
407
345
  filePath: file,
408
346
  line: 1
@@ -494,7 +432,7 @@ class iOSArchitectureRules {
494
432
 
495
433
  if (file.includes('Entity.swift')) {
496
434
  const hasMethods = (content.match(/func\s+/g) || []).length;
497
- if (hasMethods > 2) {
435
+ if (hasMethods > 2) {
498
436
  pushFinding(this.findings, {
499
437
  ruleId: 'ios.viper.entity_with_logic',
500
438
  severity: 'medium',
@@ -537,7 +475,7 @@ class iOSArchitectureRules {
537
475
 
538
476
  if (content.includes(': Reducer')) {
539
477
  if ((content.includes('URLSession') || content.includes('async ')) &&
540
- !content.includes('Effect')) {
478
+ !content.includes('Effect')) {
541
479
  pushFinding(this.findings, {
542
480
  ruleId: 'ios.tca.missing_effect',
543
481
  severity: 'high',
@@ -3,9 +3,8 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const { execSync } = require('child_process');
6
- const env = require('../../config/env');
7
6
 
8
- const projectDir = env.get('CLAUDE_PROJECT_DIR', process.cwd());
7
+ const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
9
8
  const rulesPath = path.join(projectDir, '.cursor', 'ai-skills', 'skill-rules.json');
10
9
  const mdcRulesDir = path.join(projectDir, '.cursor', 'rules');
11
10
  const debugLogPath = path.join(projectDir, '.audit_tmp', 'skill-activation-debug.log');
@@ -55,7 +54,7 @@ function sendMacNotification(title, message) {
55
54
  return;
56
55
  }
57
56
 
58
- const enabled = env.getBool('HOOK_GUARD_ENABLE_SKILL_ACTIVATION', true);
57
+ const enabled = process.env.HOOK_GUARD_ENABLE_SKILL_ACTIVATION !== '0';
59
58
  if (!enabled) {
60
59
  appendDebugLog('Notifications disabled via HOOK_GUARD_ENABLE_SKILL_ACTIVATION');
61
60
  return;
@@ -1,26 +1,13 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const env = require('../../config/env');
4
-
5
- // AuditLogger import for logging critical operations
6
- const AuditLogger = require('../services/logging/AuditLogger');
7
-
8
- // Initialize audit logger
9
- const auditLogger = new AuditLogger({
10
- repoRoot: process.cwd(),
11
- filename: path.join('.audit_tmp', 'logger-factory-audit.log')
12
- });
13
-
14
- // Import recordMetric for prometheus metrics
15
- const { recordMetric } = require('../telemetry/metrics-logger');
16
3
 
17
4
  const UnifiedLogger = require('../../application/services/logging/UnifiedLogger');
18
5
 
19
6
  function createUnifiedLogger({
20
7
  repoRoot = process.cwd(),
21
8
  component = 'HookSystem',
22
- consoleLevel = env.get('HOOK_LOG_CONSOLE_LEVEL', 'info'),
23
- fileLevel = env.get('HOOK_LOG_FILE_LEVEL', 'debug'),
9
+ consoleLevel = process.env.HOOK_LOG_CONSOLE_LEVEL || 'info',
10
+ fileLevel = process.env.HOOK_LOG_FILE_LEVEL || 'debug',
24
11
  fileName = null,
25
12
  defaultData = {}
26
13
  } = {}) {
@@ -30,10 +17,10 @@ function createUnifiedLogger({
30
17
  const logFileName = fileName || `${component.replace(/\s+/g, '-').toLowerCase()}.log`;
31
18
  const filePath = path.join(reportsDir, logFileName);
32
19
 
33
- const maxSizeBytes = env.getNumber('HOOK_LOG_MAX_SIZE', 5 * 1024 * 1024);
34
- const maxFiles = env.getNumber('HOOK_LOG_MAX_FILES', 5);
20
+ const maxSizeBytes = Number(process.env.HOOK_LOG_MAX_SIZE || 5 * 1024 * 1024);
21
+ const maxFiles = Number(process.env.HOOK_LOG_MAX_FILES || 5);
35
22
 
36
- const logger = new UnifiedLogger({
23
+ return new UnifiedLogger({
37
24
  component,
38
25
  console: {
39
26
  enabled: true,
@@ -48,23 +35,6 @@ function createUnifiedLogger({
48
35
  },
49
36
  defaultData
50
37
  });
51
-
52
- auditLogger.log({
53
- action: 'logger_created',
54
- category: 'system',
55
- severity: 'info',
56
- message: `UnifiedLogger created for component: ${component}`,
57
- metadata: {
58
- component,
59
- filePath,
60
- consoleLevel,
61
- fileLevel,
62
- maxSizeBytes,
63
- maxFiles
64
- }
65
- });
66
-
67
- return logger;
68
38
  }
69
39
 
70
40
  module.exports = { createUnifiedLogger };
@@ -8,16 +8,9 @@ const { TokenManager } = require('../utils/token-manager');
8
8
  const { toErrorMessage } = require('../utils/error-utils');
9
9
  const fs = require('fs');
10
10
  const path = require('path');
11
- const env = require('../../config/env');
12
-
13
- // AuditLogger import for logging critical operations
14
- const AuditLogger = require('../services/logging/AuditLogger');
15
-
16
- // Import recordMetric for prometheus metrics
17
- const { recordMetric } = require('../telemetry/metrics-logger');
18
11
 
19
12
  function resolveAuditTmpDir() {
20
- const configured = (env.get('AUDIT_TMP', '') || '').trim();
13
+ const configured = (process.env.AUDIT_TMP || '').trim();
21
14
  if (configured.length > 0) {
22
15
  return path.isAbsolute(configured) ? configured : path.join(process.cwd(), configured);
23
16
  }
@@ -29,37 +22,13 @@ function resolveAuditTmpDir() {
29
22
  * Called by audit.sh after AST analysis completes
30
23
  */
31
24
  async function runIntelligentAudit() {
32
- const auditLogger = new AuditLogger({
33
- repoRoot: process.cwd(),
34
- filename: path.join('.audit_tmp', 'audit.log')
35
- });
36
-
37
25
  try {
38
26
  console.log('[Intelligent Audit] Starting severity evaluation...');
39
27
 
40
- auditLogger.log({
41
- action: 'audit_start',
42
- category: 'system',
43
- severity: 'info',
44
- message: 'Intelligent audit orchestration started',
45
- metadata: {
46
- timestamp: new Date().toISOString(),
47
- scope: env.get('AI_GATE_SCOPE', 'staging')
48
- }
49
- });
50
-
51
28
  const rawViolations = loadRawViolations();
52
29
  console.log(`[Intelligent Audit] Loaded ${rawViolations.length} violations from AST`);
53
30
 
54
- auditLogger.log({
55
- action: 'violations_loaded',
56
- category: 'data',
57
- severity: 'info',
58
- message: `Loaded ${rawViolations.length} violations from AST analysis`,
59
- metadata: { violationCount: rawViolations.length }
60
- });
61
-
62
- const gateScope = String(env.get('AI_GATE_SCOPE', 'staging') || 'staging').trim().toLowerCase();
31
+ const gateScope = String(process.env.AI_GATE_SCOPE || 'staging').trim().toLowerCase();
63
32
  const isRepoScope = gateScope === 'repo' || gateScope === 'repository';
64
33
 
65
34
  let violationsForGate = [];
@@ -107,26 +76,6 @@ async function runIntelligentAudit() {
107
76
  console.log(`[Intelligent Audit] Blocked by: ${gateResult.blockedBy} violations`);
108
77
  }
109
78
 
110
- auditLogger.log({
111
- action: 'quality_gate_applied',
112
- category: 'security',
113
- severity: gateResult.passed ? 'info' : 'warn',
114
- message: `Quality gate ${gateResult.passed ? 'PASSED' : 'FAILED'}${gateResult.blockedBy ? ` - blocked by ${gateResult.blockedBy}` : ''}`,
115
- metadata: {
116
- passed: gateResult.passed,
117
- blockedBy: gateResult.blockedBy,
118
- violationCount: enhancedViolations.length
119
- }
120
- });
121
-
122
- // Record prometheus metrics for gate result
123
- recordMetric({
124
- hook: 'quality_gate',
125
- status: gateResult.passed ? 'passed' : 'failed',
126
- violationCount: enhancedViolations.length,
127
- blockedBy: gateResult.blockedBy || 'none'
128
- });
129
-
130
79
  console.log('[Intelligent Audit] Generating reports...');
131
80
  const reportGenerator = new ReportGenerator();
132
81
  const reportPaths = reportGenerator.save(enhancedViolations, gateResult);
@@ -135,25 +84,6 @@ async function runIntelligentAudit() {
135
84
  console.log(` - JSON: ${reportPaths.jsonPath}`);
136
85
  console.log(` - Text: ${reportPaths.textPath}`);
137
86
 
138
- auditLogger.log({
139
- action: 'reports_generated',
140
- category: 'system',
141
- severity: 'info',
142
- message: 'Audit reports generated and saved',
143
- metadata: {
144
- jsonPath: reportPaths.jsonPath,
145
- textPath: reportPaths.textPath,
146
- violationCount: enhancedViolations.length
147
- }
148
- });
149
-
150
- // Record prometheus metrics for report generation
151
- recordMetric({
152
- hook: 'audit_reports',
153
- status: 'generated',
154
- violationCount: enhancedViolations.length
155
- });
156
-
157
87
  const tracker = new SeverityTracker();
158
88
  tracker.record(enhancedViolations, gateResult);
159
89
 
@@ -282,21 +212,21 @@ function updateAIEvidence(violations, gateResult, tokenUsage) {
282
212
  const currentBranch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
283
213
 
284
214
  const resolveBaseBranch = () => {
285
- const configured = env.get('AST_BASE_BRANCH', '');
286
- if (configured && configured.trim().length > 0) {
287
- return configured.trim();
288
- }
289
- try {
290
- execSync('git show-ref --verify --quiet refs/heads/develop', { stdio: 'ignore' });
291
- return 'develop';
292
- } catch {
215
+ const configured = process.env.AST_BASE_BRANCH;
216
+ if (configured && configured.trim().length > 0) {
217
+ return configured.trim();
218
+ }
293
219
  try {
294
- execSync('git show-ref --verify --quiet refs/heads/main', { stdio: 'ignore' });
295
- return 'main';
220
+ execSync('git show-ref --verify --quiet refs/heads/develop', { stdio: 'ignore' });
221
+ return 'develop';
296
222
  } catch {
297
- return 'main';
223
+ try {
224
+ execSync('git show-ref --verify --quiet refs/heads/main', { stdio: 'ignore' });
225
+ return 'main';
226
+ } catch {
227
+ return 'main';
228
+ }
298
229
  }
299
- }
300
230
  };
301
231
  const baseBranch = resolveBaseBranch();
302
232
  const isProtected = ['main', 'master', baseBranch].includes(currentBranch);
@@ -304,12 +234,12 @@ function updateAIEvidence(violations, gateResult, tokenUsage) {
304
234
  const highViolations = violations.filter(v => v.severity === 'HIGH');
305
235
  const blockingViolations = [...criticalViolations, ...highViolations].slice(0, 50);
306
236
 
307
- const gateScope = String(env.get('AI_GATE_SCOPE', 'staging') || 'staging').trim().toLowerCase();
237
+ const gateScope = String(process.env.AI_GATE_SCOPE || 'staging').trim().toLowerCase();
308
238
 
309
239
  const existingGate = evidence.ai_gate && typeof evidence.ai_gate === 'object' ? evidence.ai_gate : null;
310
240
  let preserveExistingRepoGate = false;
311
241
  if (gateScope !== 'repo' && gateScope !== 'repository' && existingGate && existingGate.scope === 'repo' && existingGate.status === 'BLOCKED') {
312
- const preserveMs = env.getNumber('AI_GATE_REPO_PRESERVE_MS', 600000);
242
+ const preserveMs = Number(process.env.AI_GATE_REPO_PRESERVE_MS || 600000);
313
243
  const lastCheckMs = Date.parse(existingGate.last_check || '');
314
244
  if (!Number.isNaN(preserveMs) && preserveMs > 0 && !Number.isNaN(lastCheckMs)) {
315
245
  const ageMs = Date.now() - lastCheckMs;
@@ -3,22 +3,9 @@
3
3
  const http = require('http');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
- const env = require('../../config/env');
7
6
 
8
- // AuditLogger import for logging critical operations
9
- const AuditLogger = require('../services/logging/AuditLogger');
10
-
11
- // Import recordMetric for prometheus metrics
12
- const { recordMetric } = require('./metrics-logger');
13
-
14
- const PORT = env.getNumber('HOOK_METRICS_PORT', 9464);
15
- const METRICS_FILE = path.join(process.cwd(), env.get('HOOK_METRICS_FILE', '.audit_tmp/hook-metrics.jsonl'));
16
-
17
- // Initialize audit logger
18
- const auditLogger = new AuditLogger({
19
- repoRoot: process.cwd(),
20
- filename: path.join('.audit_tmp', 'metrics-server-audit.log')
21
- });
7
+ const PORT = Number(process.env.HOOK_METRICS_PORT || 9464);
8
+ const METRICS_FILE = path.join(process.cwd(), '.audit_tmp', 'hook-metrics.jsonl');
22
9
 
23
10
  function loadMetrics() {
24
11
  if (!fs.existsSync(METRICS_FILE)) return [];
@@ -62,49 +49,13 @@ const server = http.createServer((req, res) => {
62
49
  const body = buildPrometheusMetrics();
63
50
  res.writeHead(200, { 'Content-Type': 'text/plain' });
64
51
  res.end(body);
65
-
66
- auditLogger.log({
67
- action: 'metrics_served',
68
- category: 'observability',
69
- severity: 'info',
70
- message: 'Prometheus metrics served successfully',
71
- metadata: {
72
- port: PORT,
73
- metricsCount: body.split('\n').filter(line => line.trim() && !line.startsWith('#')).length,
74
- endpoint: '/metrics'
75
- }
76
- });
77
52
  return;
78
53
  }
79
54
 
80
55
  res.writeHead(404);
81
56
  res.end();
82
-
83
- auditLogger.log({
84
- action: 'invalid_request',
85
- category: 'observability',
86
- severity: 'warn',
87
- message: 'Invalid request to metrics server',
88
- metadata: {
89
- url: req.url,
90
- method: req.method,
91
- port: PORT
92
- }
93
- });
94
57
  });
95
58
 
96
59
  server.listen(PORT, () => {
97
60
  console.log(`Hook-System metrics server running on http://localhost:${PORT}/metrics`);
98
-
99
- auditLogger.log({
100
- action: 'server_started',
101
- category: 'system',
102
- severity: 'info',
103
- message: 'Metrics server started successfully',
104
- metadata: {
105
- port: PORT,
106
- endpoint: '/metrics',
107
- metricsFile: METRICS_FILE
108
- }
109
- });
110
61
  });
@@ -4,9 +4,8 @@
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
  const { execSync } = require('child_process');
7
- const env = require('../../config/env');
8
7
 
9
- const REPO_ROOT = env.get('HOOK_GUARD_REPO_ROOT', process.cwd());
8
+ const REPO_ROOT = process.env.HOOK_GUARD_REPO_ROOT || process.cwd();
10
9
  const CONFIG_PATH = path.join(REPO_ROOT, 'scripts', 'hooks-system', 'config', 'language-guard.json');
11
10
  const DEFAULT_IGNORED_SEGMENTS = [
12
11
  `${path.sep}node_modules${path.sep}`,
@@ -23,7 +22,7 @@ function decodeUnicode(value) {
23
22
  try {
24
23
  return JSON.parse(`"${value}"`);
25
24
  } catch (error) {
26
- if (env.isDev || env.getBool('DEBUG', false)) {
25
+ if (process.env.NODE_ENV === 'development' || process.env.DEBUG) {
27
26
  console.debug(`[enforce-english-literals] Failed to decode Unicode value "${value}": ${error.message}`);
28
27
  }
29
28
  return value;
@@ -120,10 +119,13 @@ function analyzeFile(relativePath, config) {
120
119
 
121
120
  function collectStagedFiles() {
122
121
  try {
123
- const stagedFilesRaw = execSync('git diff --cached --name-only', { encoding: 'utf8' });
124
- return stagedFilesRaw.split('\n').filter(Boolean).map(file => file.trim());
122
+ const raw = execSync('git diff --cached --name-only --diff-filter=ACMR', {
123
+ cwd: REPO_ROOT,
124
+ encoding: 'utf8'
125
+ });
126
+ return raw.split('\n').map(entry => entry.trim()).filter(Boolean);
125
127
  } catch (error) {
126
- if (env.isDev || env.getBool('DEBUG', false)) {
128
+ if (process.env.NODE_ENV === 'development' || process.env.DEBUG) {
127
129
  console.debug(`[enforce-english-literals] Failed to collect staged files: ${error.message}`);
128
130
  }
129
131
  return [];