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.
- package/docs/VIOLATIONS_RESOLUTION_PLAN.md +95 -0
- package/docs/alerting-system.md +51 -0
- package/docs/observability.md +36 -0
- package/docs/type-safety.md +8 -0
- package/package.json +1 -1
- package/scripts/hooks-system/.AI_TOKEN_STATUS.txt +1 -1
- package/scripts/hooks-system/.audit-reports/auto-recovery.log +2 -0
- package/scripts/hooks-system/.audit-reports/install-wizard.log +8 -0
- package/scripts/hooks-system/.audit-reports/notifications.log +45 -0
- package/scripts/hooks-system/.audit-reports/token-monitor.log +174 -0
- package/scripts/hooks-system/application/CompositionRoot.js +73 -24
- package/scripts/hooks-system/application/services/DynamicRulesLoader.js +2 -1
- package/scripts/hooks-system/application/services/PlaybookRunner.js +1 -1
- package/scripts/hooks-system/application/services/RealtimeGuardService.js +85 -15
- package/scripts/hooks-system/application/services/guard/GuardAutoManagerService.js +31 -2
- package/scripts/hooks-system/application/services/guard/GuardConfig.js +17 -9
- package/scripts/hooks-system/application/services/guard/GuardHeartbeatMonitor.js +6 -9
- package/scripts/hooks-system/application/services/guard/GuardProcessManager.js +29 -0
- package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +4 -1
- package/scripts/hooks-system/application/services/installation/McpConfigurator.js +2 -1
- package/scripts/hooks-system/application/services/logging/AuditLogger.js +88 -0
- package/scripts/hooks-system/application/services/logging/UnifiedLogger.js +13 -4
- package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +7 -3
- package/scripts/hooks-system/application/services/token/TokenMetricsService.js +14 -1
- package/scripts/hooks-system/bin/cli.js +15 -1
- package/scripts/hooks-system/config/env.js +33 -0
- package/scripts/hooks-system/domain/events/__tests__/EventBus.spec.js +33 -0
- package/scripts/hooks-system/domain/events/index.js +32 -6
- package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidAnalysisOrchestrator.js +3 -2
- package/scripts/hooks-system/infrastructure/ast/ast-core.js +12 -20
- package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +8 -18
- package/scripts/hooks-system/infrastructure/ast/backend/analyzers/BackendPatternDetector.js +2 -1
- package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +10 -8
- package/scripts/hooks-system/infrastructure/ast/frontend/ast-frontend.js +196 -196
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +3 -2
- package/scripts/hooks-system/infrastructure/hooks/skill-activation-prompt.js +3 -2
- package/scripts/hooks-system/infrastructure/logging/UnifiedLoggerFactory.js +35 -5
- package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +86 -16
- package/scripts/hooks-system/infrastructure/telemetry/metrics-server.js +51 -2
- package/scripts/hooks-system/infrastructure/validators/enforce-english-literals.js +6 -8
- 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 = (
|
|
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
|
-
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
221
|
-
|
|
294
|
+
execSync('git show-ref --verify --quiet refs/heads/main', { stdio: 'ignore' });
|
|
295
|
+
return 'main';
|
|
222
296
|
} catch {
|
|
223
|
-
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
8
|
-
const
|
|
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 =
|
|
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 (
|
|
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
|
|
123
|
-
|
|
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 (
|
|
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 [];
|
package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log
CHANGED
|
@@ -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)"}}
|