pumuki-ast-hooks 5.3.16 → 5.3.18

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 (41) hide show
  1. package/docs/VIOLATIONS_RESOLUTION_PLAN.md +95 -0
  2. package/docs/alerting-system.md +51 -0
  3. package/docs/observability.md +36 -0
  4. package/docs/type-safety.md +8 -0
  5. package/package.json +1 -1
  6. package/scripts/hooks-system/.AI_TOKEN_STATUS.txt +1 -1
  7. package/scripts/hooks-system/.audit-reports/auto-recovery.log +2 -0
  8. package/scripts/hooks-system/.audit-reports/install-wizard.log +8 -0
  9. package/scripts/hooks-system/.audit-reports/notifications.log +45 -0
  10. package/scripts/hooks-system/.audit-reports/token-monitor.log +174 -0
  11. package/scripts/hooks-system/application/CompositionRoot.js +73 -24
  12. package/scripts/hooks-system/application/services/DynamicRulesLoader.js +2 -1
  13. package/scripts/hooks-system/application/services/PlaybookRunner.js +1 -1
  14. package/scripts/hooks-system/application/services/RealtimeGuardService.js +85 -15
  15. package/scripts/hooks-system/application/services/guard/GuardAutoManagerService.js +31 -2
  16. package/scripts/hooks-system/application/services/guard/GuardConfig.js +17 -9
  17. package/scripts/hooks-system/application/services/guard/GuardHeartbeatMonitor.js +6 -9
  18. package/scripts/hooks-system/application/services/guard/GuardProcessManager.js +29 -0
  19. package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +4 -1
  20. package/scripts/hooks-system/application/services/installation/McpConfigurator.js +2 -1
  21. package/scripts/hooks-system/application/services/logging/AuditLogger.js +88 -0
  22. package/scripts/hooks-system/application/services/logging/UnifiedLogger.js +13 -4
  23. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +7 -3
  24. package/scripts/hooks-system/application/services/token/TokenMetricsService.js +14 -1
  25. package/scripts/hooks-system/bin/cli.js +15 -1
  26. package/scripts/hooks-system/config/env.js +33 -0
  27. package/scripts/hooks-system/domain/events/__tests__/EventBus.spec.js +33 -0
  28. package/scripts/hooks-system/domain/events/index.js +32 -6
  29. package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidAnalysisOrchestrator.js +3 -2
  30. package/scripts/hooks-system/infrastructure/ast/ast-core.js +12 -20
  31. package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +8 -18
  32. package/scripts/hooks-system/infrastructure/ast/backend/analyzers/BackendPatternDetector.js +2 -1
  33. package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +10 -8
  34. package/scripts/hooks-system/infrastructure/ast/frontend/ast-frontend.js +196 -196
  35. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +3 -2
  36. package/scripts/hooks-system/infrastructure/hooks/skill-activation-prompt.js +3 -2
  37. package/scripts/hooks-system/infrastructure/logging/UnifiedLoggerFactory.js +35 -5
  38. package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +86 -16
  39. package/scripts/hooks-system/infrastructure/telemetry/metrics-server.js +51 -2
  40. package/scripts/hooks-system/infrastructure/validators/enforce-english-literals.js +6 -8
  41. package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log +3 -0
@@ -8,9 +8,16 @@ 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');
11
18
 
12
19
  function resolveAuditTmpDir() {
13
- const configured = (process.env.AUDIT_TMP || '').trim();
20
+ const configured = (env.get('AUDIT_TMP', '') || '').trim();
14
21
  if (configured.length > 0) {
15
22
  return path.isAbsolute(configured) ? configured : path.join(process.cwd(), configured);
16
23
  }
@@ -22,13 +29,37 @@ function resolveAuditTmpDir() {
22
29
  * Called by audit.sh after AST analysis completes
23
30
  */
24
31
  async function runIntelligentAudit() {
32
+ const auditLogger = new AuditLogger({
33
+ repoRoot: process.cwd(),
34
+ filename: path.join('.audit_tmp', 'audit.log')
35
+ });
36
+
25
37
  try {
26
38
  console.log('[Intelligent Audit] Starting severity evaluation...');
27
39
 
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
+
28
51
  const rawViolations = loadRawViolations();
29
52
  console.log(`[Intelligent Audit] Loaded ${rawViolations.length} violations from AST`);
30
53
 
31
- const gateScope = String(process.env.AI_GATE_SCOPE || 'staging').trim().toLowerCase();
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();
32
63
  const isRepoScope = gateScope === 'repo' || gateScope === 'repository';
33
64
 
34
65
  let violationsForGate = [];
@@ -76,6 +107,26 @@ async function runIntelligentAudit() {
76
107
  console.log(`[Intelligent Audit] Blocked by: ${gateResult.blockedBy} violations`);
77
108
  }
78
109
 
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
+
79
130
  console.log('[Intelligent Audit] Generating reports...');
80
131
  const reportGenerator = new ReportGenerator();
81
132
  const reportPaths = reportGenerator.save(enhancedViolations, gateResult);
@@ -84,6 +135,25 @@ async function runIntelligentAudit() {
84
135
  console.log(` - JSON: ${reportPaths.jsonPath}`);
85
136
  console.log(` - Text: ${reportPaths.textPath}`);
86
137
 
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
+
87
157
  const tracker = new SeverityTracker();
88
158
  tracker.record(enhancedViolations, gateResult);
89
159
 
@@ -212,21 +282,21 @@ function updateAIEvidence(violations, gateResult, tokenUsage) {
212
282
  const currentBranch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
213
283
 
214
284
  const resolveBaseBranch = () => {
215
- const configured = process.env.AST_BASE_BRANCH;
216
- if (configured && configured.trim().length > 0) {
217
- return configured.trim();
218
- }
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 {
219
293
  try {
220
- execSync('git show-ref --verify --quiet refs/heads/develop', { stdio: 'ignore' });
221
- return 'develop';
294
+ execSync('git show-ref --verify --quiet refs/heads/main', { stdio: 'ignore' });
295
+ return 'main';
222
296
  } catch {
223
- try {
224
- execSync('git show-ref --verify --quiet refs/heads/main', { stdio: 'ignore' });
225
- return 'main';
226
- } catch {
227
- return 'main';
228
- }
297
+ return 'main';
229
298
  }
299
+ }
230
300
  };
231
301
  const baseBranch = resolveBaseBranch();
232
302
  const isProtected = ['main', 'master', baseBranch].includes(currentBranch);
@@ -234,12 +304,12 @@ function updateAIEvidence(violations, gateResult, tokenUsage) {
234
304
  const highViolations = violations.filter(v => v.severity === 'HIGH');
235
305
  const blockingViolations = [...criticalViolations, ...highViolations].slice(0, 50);
236
306
 
237
- const gateScope = String(process.env.AI_GATE_SCOPE || 'staging').trim().toLowerCase();
307
+ const gateScope = String(env.get('AI_GATE_SCOPE', 'staging') || 'staging').trim().toLowerCase();
238
308
 
239
309
  const existingGate = evidence.ai_gate && typeof evidence.ai_gate === 'object' ? evidence.ai_gate : null;
240
310
  let preserveExistingRepoGate = false;
241
311
  if (gateScope !== 'repo' && gateScope !== 'repository' && existingGate && existingGate.scope === 'repo' && existingGate.status === 'BLOCKED') {
242
- const preserveMs = Number(process.env.AI_GATE_REPO_PRESERVE_MS || 600000);
312
+ const preserveMs = env.getNumber('AI_GATE_REPO_PRESERVE_MS', 600000);
243
313
  const lastCheckMs = Date.parse(existingGate.last_check || '');
244
314
  if (!Number.isNaN(preserveMs) && preserveMs > 0 && !Number.isNaN(lastCheckMs)) {
245
315
  const ageMs = Date.now() - lastCheckMs;
@@ -3,9 +3,22 @@
3
3
  const http = require('http');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
+ const env = require('../../config/env');
6
7
 
7
- const PORT = Number(process.env.HOOK_METRICS_PORT || 9464);
8
- const METRICS_FILE = path.join(process.cwd(), '.audit_tmp', 'hook-metrics.jsonl');
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
+ });
9
22
 
10
23
  function loadMetrics() {
11
24
  if (!fs.existsSync(METRICS_FILE)) return [];
@@ -49,13 +62,49 @@ const server = http.createServer((req, res) => {
49
62
  const body = buildPrometheusMetrics();
50
63
  res.writeHead(200, { 'Content-Type': 'text/plain' });
51
64
  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
+ });
52
77
  return;
53
78
  }
54
79
 
55
80
  res.writeHead(404);
56
81
  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
+ });
57
94
  });
58
95
 
59
96
  server.listen(PORT, () => {
60
97
  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
+ });
61
110
  });
@@ -4,8 +4,9 @@
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');
7
8
 
8
- const REPO_ROOT = process.env.HOOK_GUARD_REPO_ROOT || process.cwd();
9
+ const REPO_ROOT = env.get('HOOK_GUARD_REPO_ROOT', process.cwd());
9
10
  const CONFIG_PATH = path.join(REPO_ROOT, 'scripts', 'hooks-system', 'config', 'language-guard.json');
10
11
  const DEFAULT_IGNORED_SEGMENTS = [
11
12
  `${path.sep}node_modules${path.sep}`,
@@ -22,7 +23,7 @@ function decodeUnicode(value) {
22
23
  try {
23
24
  return JSON.parse(`"${value}"`);
24
25
  } catch (error) {
25
- if (process.env.NODE_ENV === 'development' || process.env.DEBUG) {
26
+ if (env.isDev || env.getBool('DEBUG', false)) {
26
27
  console.debug(`[enforce-english-literals] Failed to decode Unicode value "${value}": ${error.message}`);
27
28
  }
28
29
  return value;
@@ -119,13 +120,10 @@ function analyzeFile(relativePath, config) {
119
120
 
120
121
  function collectStagedFiles() {
121
122
  try {
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);
123
+ const stagedFilesRaw = execSync('git diff --cached --name-only', { encoding: 'utf8' });
124
+ return stagedFilesRaw.split('\n').filter(Boolean).map(file => file.trim());
127
125
  } catch (error) {
128
- if (process.env.NODE_ENV === 'development' || process.env.DEBUG) {
126
+ if (env.isDev || env.getBool('DEBUG', false)) {
129
127
  console.debug(`[enforce-english-literals] Failed to collect staged files: ${error.message}`);
130
128
  }
131
129
  return [];
@@ -19,3 +19,6 @@
19
19
  {"timestamp":"2025-12-29T14:01:17.350Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":10,"tokensUsed":100000,"maxTokens":1000000,"source":"realtime","stale":false},"context":{"message":"Result level=ok percent=10% used=100000/1000000 source=realtime"}}
20
20
  {"timestamp":"2025-12-29T14:01:17.352Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"warning","percentUsed":91,"tokensUsed":910000,"maxTokens":1000000,"source":"fallback","stale":false},"context":{"message":"Result level=warning percent=91% used=910000/1000000 source=fallback"}}
21
21
  {"timestamp":"2025-12-29T14:01:17.352Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"critical","percentUsed":98,"tokensUsed":980000,"maxTokens":1000000,"source":"realtime","stale":true},"context":{"message":"Result level=critical percent=98% used=980000/1000000 source=realtime (stale)"}}
22
+ {"timestamp":"2025-12-30T08:18:15.791Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":10,"tokensUsed":100000,"maxTokens":1000000,"source":"realtime","stale":false},"context":{"message":"Result level=ok percent=10% used=100000/1000000 source=realtime"}}
23
+ {"timestamp":"2025-12-30T08:18:15.794Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"warning","percentUsed":91,"tokensUsed":910000,"maxTokens":1000000,"source":"fallback","stale":false},"context":{"message":"Result level=warning percent=91% used=910000/1000000 source=fallback"}}
24
+ {"timestamp":"2025-12-30T08:18:15.794Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"critical","percentUsed":98,"tokensUsed":980000,"maxTokens":1000000,"source":"realtime","stale":true},"context":{"message":"Result level=critical percent=98% used=980000/1000000 source=realtime (stale)"}}