pumuki-ast-hooks 5.5.12 → 5.5.14
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/bin/install.js +0 -0
- package/package.json +2 -3
- package/scripts/hooks-system/.audit-reports/auto-recovery.log +1 -0
- package/scripts/hooks-system/.audit-reports/install-wizard.log +4 -0
- package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +24 -0
- package/scripts/hooks-system/application/services/PlatformDetectionService.js +5 -1
- package/scripts/hooks-system/application/services/RealtimeGuardService.js +1 -0
- package/scripts/hooks-system/application/services/guard/EvidenceManager.js +33 -8
- package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +1 -3
- package/scripts/hooks-system/bin/cli.js +19 -1
- package/scripts/hooks-system/bin/update-evidence.sh +2 -2
- package/scripts/hooks-system/infrastructure/ast/ast-core.js +1 -1
- package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +20 -6
- package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +1 -3
- package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +21 -5
- package/scripts/hooks-system/infrastructure/shell/orchestrators/audit-orchestrator.sh +0 -25
- package/scripts/hooks-system/infrastructure/utils/timestamp-helper.sh +12 -4
- package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log +3 -0
package/bin/install.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki-ast-hooks",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.14",
|
|
4
4
|
"description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -116,7 +116,6 @@
|
|
|
116
116
|
},
|
|
117
117
|
"exports": {
|
|
118
118
|
".": "./index.js",
|
|
119
|
-
"./package.json": "./package.json",
|
|
120
119
|
"./ast": "./scripts/hooks-system/infrastructure/ast/ast-intelligence.js",
|
|
121
120
|
"./domain": "./scripts/hooks-system/domain/index.js",
|
|
122
121
|
"./application": "./scripts/hooks-system/application/index.js",
|
|
@@ -124,4 +123,4 @@
|
|
|
124
123
|
"./skills": "./skills/skill-rules.json",
|
|
125
124
|
"./hooks": "./hooks/index.js"
|
|
126
125
|
}
|
|
127
|
-
}
|
|
126
|
+
}
|
|
@@ -6,3 +6,4 @@
|
|
|
6
6
|
{"timestamp":"2026-01-03T13:47:40.470Z","level":"info","component":"AutoRecovery","event":"NotificationCenterService shutdown","data":{"totalEnqueued":0,"totalSent":0,"totalDeduplicated":0,"totalCooldownSkipped":0,"totalFailed":0,"totalRetries":0,"queueSize":0,"deduplication":{"size":0},"cooldowns":{"activeCooldowns":0}},"context":{}}
|
|
7
7
|
{"timestamp":"2026-01-03T13:53:08.976Z","level":"info","component":"AutoRecovery","event":"NotificationCenterService shutdown","data":{"totalEnqueued":0,"totalSent":0,"totalDeduplicated":0,"totalCooldownSkipped":0,"totalFailed":0,"totalRetries":0,"queueSize":0,"deduplication":{"size":0},"cooldowns":{"activeCooldowns":0}},"context":{}}
|
|
8
8
|
{"timestamp":"2026-01-03T14:05:35.588Z","level":"info","component":"AutoRecovery","event":"NotificationCenterService shutdown","data":{"totalEnqueued":0,"totalSent":0,"totalDeduplicated":0,"totalCooldownSkipped":0,"totalFailed":0,"totalRetries":0,"queueSize":0,"deduplication":{"size":0},"cooldowns":{"activeCooldowns":0}},"context":{}}
|
|
9
|
+
{"timestamp":"2026-01-04T07:12:12.600Z","level":"info","component":"AutoRecovery","event":"NotificationCenterService shutdown","data":{"totalEnqueued":0,"totalSent":0,"totalDeduplicated":0,"totalCooldownSkipped":0,"totalFailed":0,"totalRetries":0,"queueSize":0,"deduplication":{"size":0},"cooldowns":{"activeCooldowns":0}},"context":{}}
|
|
@@ -30,3 +30,7 @@
|
|
|
30
30
|
{"timestamp":"2026-01-03T14:05:35.955Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_CONFIG_EXISTS","data":{"configPath":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.hook-system/config.json"},"context":{}}
|
|
31
31
|
{"timestamp":"2026-01-03T14:05:35.955Z","level":"error","component":"InstallWizard","event":"INSTALL_WIZARD_SYMLINK_FAILED","data":{"error":"EEXIST: file already exists, symlink '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/scripts/hooks-system/bin/guard-supervisor.js' -> '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.git/hooks/guard-supervisor'"},"context":{}}
|
|
32
32
|
{"timestamp":"2026-01-03T14:05:35.955Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
|
|
33
|
+
{"timestamp":"2026-01-04T07:12:12.823Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
|
|
34
|
+
{"timestamp":"2026-01-04T07:12:12.834Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_CONFIG_EXISTS","data":{"configPath":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.hook-system/config.json"},"context":{}}
|
|
35
|
+
{"timestamp":"2026-01-04T07:12:12.835Z","level":"error","component":"InstallWizard","event":"INSTALL_WIZARD_SYMLINK_FAILED","data":{"error":"EEXIST: file already exists, symlink '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/scripts/hooks-system/bin/guard-supervisor.js' -> '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.git/hooks/guard-supervisor'"},"context":{}}
|
|
36
|
+
{"timestamp":"2026-01-04T07:12:12.835Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
|
|
@@ -94,3 +94,27 @@
|
|
|
94
94
|
{"timestamp":1767449135588,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
95
95
|
{"timestamp":1767449135588,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
96
96
|
{"timestamp":1767449135588,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
97
|
+
{"timestamp":1767510732597,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
98
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
99
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
100
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
101
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
102
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
103
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
104
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
105
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
106
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
107
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
108
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
109
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
110
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
111
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
112
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
113
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
114
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
115
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
116
|
+
{"timestamp":1767510732599,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
117
|
+
{"timestamp":1767510732600,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
118
|
+
{"timestamp":1767510732600,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
119
|
+
{"timestamp":1767510732600,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
120
|
+
{"timestamp":1767510732600,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
@@ -116,7 +116,11 @@ class PlatformDetectionService {
|
|
|
116
116
|
_detectPlatformUncached(filePath) {
|
|
117
117
|
const lowerPath = filePath.toLowerCase();
|
|
118
118
|
|
|
119
|
-
if (lowerPath.includes('
|
|
119
|
+
if (lowerPath.includes('scripts/hooks-system/')) {
|
|
120
|
+
return 'other';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (lowerPath.includes('apps/backend/') || lowerPath.includes('/services/') || lowerPath.includes('services/') || lowerPath.includes('/functions/') || lowerPath.includes('functions/')) {
|
|
120
124
|
return 'backend';
|
|
121
125
|
}
|
|
122
126
|
if (lowerPath.includes('apps/web-app/') || lowerPath.includes('apps/admin')) {
|
|
@@ -2,6 +2,10 @@ const fs = require('fs');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { recordMetric } = require('../../../infrastructure/telemetry/metrics-logger');
|
|
4
4
|
const env = require('../../../config/env.js');
|
|
5
|
+
const { execFile } = require('child_process');
|
|
6
|
+
const { promisify } = require('util');
|
|
7
|
+
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
5
9
|
|
|
6
10
|
class EvidenceManager {
|
|
7
11
|
constructor(evidencePath, notifier, auditLogger, delegate = null) {
|
|
@@ -9,7 +13,7 @@ class EvidenceManager {
|
|
|
9
13
|
this.notifier = notifier;
|
|
10
14
|
this.auditLogger = auditLogger;
|
|
11
15
|
this.delegate = delegate;
|
|
12
|
-
this.staleThresholdMs = env.getNumber('HOOK_GUARD_EVIDENCE_STALE_THRESHOLD',
|
|
16
|
+
this.staleThresholdMs = env.getNumber('HOOK_GUARD_EVIDENCE_STALE_THRESHOLD', 180000);
|
|
13
17
|
this.reminderIntervalMs = env.getNumber('HOOK_GUARD_EVIDENCE_REMINDER_INTERVAL', 60000);
|
|
14
18
|
this.inactivityGraceMs = env.getNumber('HOOK_GUARD_INACTIVITY_GRACE_MS', 120000);
|
|
15
19
|
this.pollIntervalMs = env.getNumber('HOOK_GUARD_EVIDENCE_POLL_INTERVAL', 30000);
|
|
@@ -54,10 +58,10 @@ class EvidenceManager {
|
|
|
54
58
|
}
|
|
55
59
|
const raw = fs.readFileSync(this.evidencePath, 'utf8');
|
|
56
60
|
const json = JSON.parse(raw);
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
const ms =
|
|
60
|
-
if (
|
|
61
|
+
const ts = json?.timestamp;
|
|
62
|
+
if (!ts) return null;
|
|
63
|
+
const ms = new Date(ts).getTime();
|
|
64
|
+
if (Number.isNaN(ms)) return null;
|
|
61
65
|
return ms;
|
|
62
66
|
} catch (error) {
|
|
63
67
|
const msg = error && error.message ? error.message : String(error);
|
|
@@ -127,7 +131,7 @@ class EvidenceManager {
|
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
async attemptAutoRefresh(reason = 'manual') {
|
|
130
|
-
if (!env.getBool('HOOK_GUARD_AUTO_REFRESH',
|
|
134
|
+
if (!env.getBool('HOOK_GUARD_AUTO_REFRESH', true)) return;
|
|
131
135
|
|
|
132
136
|
const updateScriptCandidates = [
|
|
133
137
|
path.join(process.cwd(), 'scripts/hooks-system/bin/update-evidence.sh'),
|
|
@@ -165,8 +169,29 @@ class EvidenceManager {
|
|
|
165
169
|
}
|
|
166
170
|
|
|
167
171
|
async runDirectEvidenceRefresh(_reason) {
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
const updateScriptCandidates = [
|
|
173
|
+
path.join(process.cwd(), 'scripts/hooks-system/bin/update-evidence.sh'),
|
|
174
|
+
path.join(process.cwd(), 'node_modules/@pumuki/ast-intelligence-hooks/scripts/hooks-system/bin/update-evidence.sh'),
|
|
175
|
+
path.join(process.cwd(), 'node_modules/pumuki-ast-hooks/scripts/hooks-system/bin/update-evidence.sh')
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
const updateScript = updateScriptCandidates.find(p => fs.existsSync(p));
|
|
179
|
+
if (!updateScript) return;
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
await execFileAsync('bash', [updateScript, '--auto'], {
|
|
183
|
+
cwd: process.cwd(),
|
|
184
|
+
env: {
|
|
185
|
+
...process.env,
|
|
186
|
+
AUTO_EVIDENCE_TRIGGER: 'auto',
|
|
187
|
+
AUTO_EVIDENCE_REASON: 'guard.auto_refresh',
|
|
188
|
+
AUTO_EVIDENCE_SUMMARY: 'auto-refresh'
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
} catch (error) {
|
|
192
|
+
const msg = error && error.message ? error.message : String(error);
|
|
193
|
+
this.notifier.appendDebugLog(`EVIDENCE_AUTO_REFRESH_ERROR|${msg}`);
|
|
194
|
+
}
|
|
170
195
|
}
|
|
171
196
|
|
|
172
197
|
updateUserActivity() {
|
|
@@ -89,9 +89,7 @@ class EvidenceMonitorService {
|
|
|
89
89
|
try {
|
|
90
90
|
const raw = this.fs.readFileSync(this.evidencePath, 'utf8');
|
|
91
91
|
const data = JSON.parse(raw);
|
|
92
|
-
const
|
|
93
|
-
const severityTimestamp = new Date(data?.severity_metrics?.last_updated).getTime();
|
|
94
|
-
const timestamp = [rootTimestamp, severityTimestamp].filter(Number.isFinite).reduce((max, v) => Math.max(max, v), NaN);
|
|
92
|
+
const timestamp = new Date(data.timestamp).getTime();
|
|
95
93
|
if (!Number.isFinite(timestamp)) {
|
|
96
94
|
this.notify({
|
|
97
95
|
message: 'Evidence timestamp is invalid.',
|
|
@@ -16,6 +16,24 @@ const args = process.argv.slice(3);
|
|
|
16
16
|
|
|
17
17
|
const HOOKS_ROOT = path.join(__dirname, '..');
|
|
18
18
|
|
|
19
|
+
function formatLocalTimestamp(date = new Date()) {
|
|
20
|
+
const year = date.getFullYear();
|
|
21
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
22
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
23
|
+
const hours = String(date.getHours()).padStart(2, '0');
|
|
24
|
+
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
25
|
+
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
26
|
+
const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
|
|
27
|
+
|
|
28
|
+
const offsetMinutes = date.getTimezoneOffset();
|
|
29
|
+
const sign = offsetMinutes <= 0 ? '+' : '-';
|
|
30
|
+
const absolute = Math.abs(offsetMinutes);
|
|
31
|
+
const offsetHours = String(Math.floor(absolute / 60)).padStart(2, '0');
|
|
32
|
+
const offsetMins = String(absolute % 60).padStart(2, '0');
|
|
33
|
+
|
|
34
|
+
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds}${sign}${offsetHours}:${offsetMins}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
19
37
|
function resolveRepoRoot() {
|
|
20
38
|
try {
|
|
21
39
|
const output = execSync('git rev-parse --show-toplevel', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
@@ -140,7 +158,7 @@ const commands = {
|
|
|
140
158
|
|
|
141
159
|
const next = {
|
|
142
160
|
...existing,
|
|
143
|
-
timestamp:
|
|
161
|
+
timestamp: formatLocalTimestamp(),
|
|
144
162
|
trigger: process.env.AUTO_EVIDENCE_TRIGGER ?? existing.trigger,
|
|
145
163
|
reason: process.env.AUTO_EVIDENCE_REASON ?? existing.reason,
|
|
146
164
|
summary: process.env.AUTO_EVIDENCE_SUMMARY ?? existing.summary,
|
|
@@ -14,9 +14,9 @@ for arg in "$@"; do
|
|
|
14
14
|
fi
|
|
15
15
|
done
|
|
16
16
|
|
|
17
|
-
CLI="$REPO_ROOT/
|
|
17
|
+
CLI="$REPO_ROOT/scripts/hooks-system/bin/cli.js"
|
|
18
18
|
if [[ ! -f "$CLI" ]]; then
|
|
19
|
-
CLI="$REPO_ROOT/scripts/hooks-system/bin/cli.js"
|
|
19
|
+
CLI="$REPO_ROOT/node_modules/pumuki-ast-hooks/scripts/hooks-system/bin/cli.js"
|
|
20
20
|
fi
|
|
21
21
|
|
|
22
22
|
if [[ ! -f "$CLI" ]]; then
|
|
@@ -339,7 +339,7 @@ function platformOf(filePath) {
|
|
|
339
339
|
if (p.includes("/apps/mobile-android/") || p.includes("/apps/android/")) return "android";
|
|
340
340
|
|
|
341
341
|
if (p.includes("/landing-page/") || p.includes("landing-page/")) return "frontend";
|
|
342
|
-
if (p.includes("/scripts/hooks-system/") || p.includes("scripts/hooks-system/")) return
|
|
342
|
+
if (p.includes("/scripts/hooks-system/") || p.includes("scripts/hooks-system/")) return null;
|
|
343
343
|
if (p.includes("/packages/ast-hooks/") || p.includes("packages/ast-hooks/")) return "backend";
|
|
344
344
|
|
|
345
345
|
if (p.endsWith(".swift")) return "ios";
|
|
@@ -3,6 +3,24 @@ const path = require("path");
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const env = require("../../config/env.js");
|
|
5
5
|
|
|
6
|
+
function formatLocalTimestamp(date = new Date()) {
|
|
7
|
+
const year = date.getFullYear();
|
|
8
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
9
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
10
|
+
const hours = String(date.getHours()).padStart(2, '0');
|
|
11
|
+
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
12
|
+
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
13
|
+
const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
|
|
14
|
+
|
|
15
|
+
const offsetMinutes = date.getTimezoneOffset();
|
|
16
|
+
const sign = offsetMinutes <= 0 ? '+' : '-';
|
|
17
|
+
const absolute = Math.abs(offsetMinutes);
|
|
18
|
+
const offsetHours = String(Math.floor(absolute / 60)).padStart(2, '0');
|
|
19
|
+
const offsetMins = String(absolute % 60).padStart(2, '0');
|
|
20
|
+
|
|
21
|
+
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds}${sign}${offsetHours}:${offsetMins}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
6
24
|
const astModulesPath = __dirname;
|
|
7
25
|
const { createProject, platformOf, mapToLevel } = require(path.join(astModulesPath, "ast-core"));
|
|
8
26
|
const { MacOSNotificationAdapter } = require(path.join(__dirname, '../adapters/MacOSNotificationAdapter'));
|
|
@@ -474,7 +492,7 @@ function saveDetailedReport(findings, levelTotals, platformTotals, project, root
|
|
|
474
492
|
findings,
|
|
475
493
|
metadata: {
|
|
476
494
|
totalFiles: project.getSourceFiles().length,
|
|
477
|
-
timestamp:
|
|
495
|
+
timestamp: formatLocalTimestamp(),
|
|
478
496
|
root,
|
|
479
497
|
stagingOnlyMode: !!(context && context.stagingOnlyMode),
|
|
480
498
|
stagedFiles: Array.isArray(context && context.stagedFiles) ? context.stagedFiles : [],
|
|
@@ -503,12 +521,8 @@ function updateAIEvidenceMetrics(findings, levelTotals, root) {
|
|
|
503
521
|
try {
|
|
504
522
|
const evidence = JSON.parse(fs.readFileSync(evidencePath, 'utf8'));
|
|
505
523
|
|
|
506
|
-
const now = new Date().toISOString();
|
|
507
|
-
|
|
508
|
-
evidence.timestamp = now;
|
|
509
|
-
|
|
510
524
|
evidence.severity_metrics = {
|
|
511
|
-
last_updated:
|
|
525
|
+
last_updated: formatLocalTimestamp(),
|
|
512
526
|
total_violations: findings.length,
|
|
513
527
|
by_severity: {
|
|
514
528
|
CRITICAL: levelTotals.CRITICAL || 0,
|
|
@@ -761,8 +761,6 @@ async function validateAndFix(params) {
|
|
|
761
761
|
const McpProtocolHandler = require('./services/McpProtocolHandler');
|
|
762
762
|
const protocolHandler = new McpProtocolHandler(process.stdin, process.stdout);
|
|
763
763
|
|
|
764
|
-
const SERVER_NAME = (process.env.MCP_SERVER_NAME || '').trim() || 'ast-intelligence-automation';
|
|
765
|
-
|
|
766
764
|
async function handleMcpMessage(message) {
|
|
767
765
|
try {
|
|
768
766
|
const request = JSON.parse(message);
|
|
@@ -790,7 +788,7 @@ async function handleMcpMessage(message) {
|
|
|
790
788
|
}
|
|
791
789
|
},
|
|
792
790
|
serverInfo: {
|
|
793
|
-
name:
|
|
791
|
+
name: 'ast-intelligence-automation',
|
|
794
792
|
version: '3.0.0',
|
|
795
793
|
description: 'Autonomous AST Intelligence + Git Flow Automation'
|
|
796
794
|
}
|
|
@@ -10,6 +10,24 @@ const { toErrorMessage } = require('../utils/error-utils');
|
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
12
|
|
|
13
|
+
function formatLocalTimestamp(date = new Date()) {
|
|
14
|
+
const year = date.getFullYear();
|
|
15
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
16
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
17
|
+
const hours = String(date.getHours()).padStart(2, '0');
|
|
18
|
+
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
19
|
+
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
20
|
+
const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
|
|
21
|
+
|
|
22
|
+
const offsetMinutes = date.getTimezoneOffset();
|
|
23
|
+
const sign = offsetMinutes <= 0 ? '+' : '-';
|
|
24
|
+
const absolute = Math.abs(offsetMinutes);
|
|
25
|
+
const offsetHours = String(Math.floor(absolute / 60)).padStart(2, '0');
|
|
26
|
+
const offsetMins = String(absolute % 60).padStart(2, '0');
|
|
27
|
+
|
|
28
|
+
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds}${sign}${offsetHours}:${offsetMins}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
13
31
|
function resolveAuditTmpDir() {
|
|
14
32
|
const configured = (env.get('AUDIT_TMP', '') || '').trim();
|
|
15
33
|
if (configured.length > 0) {
|
|
@@ -147,7 +165,7 @@ function saveEnhancedViolations(violations) {
|
|
|
147
165
|
const outputPath = path.join(resolveAuditTmpDir(), 'ast-summary-enhanced.json');
|
|
148
166
|
|
|
149
167
|
const enhanced = {
|
|
150
|
-
timestamp:
|
|
168
|
+
timestamp: formatLocalTimestamp(),
|
|
151
169
|
generator: 'AST Intelligence v2.0 with Severity Evaluation',
|
|
152
170
|
intelligentEvaluation: true,
|
|
153
171
|
totalViolations: violations.length,
|
|
@@ -180,10 +198,8 @@ function updateAIEvidence(violations, gateResult, tokenUsage) {
|
|
|
180
198
|
try {
|
|
181
199
|
const evidence = JSON.parse(fs.readFileSync(evidencePath, 'utf8'));
|
|
182
200
|
|
|
183
|
-
evidence.timestamp = new Date().toISOString();
|
|
184
|
-
|
|
185
201
|
evidence.severity_metrics = {
|
|
186
|
-
last_updated:
|
|
202
|
+
last_updated: formatLocalTimestamp(),
|
|
187
203
|
total_violations: violations.length,
|
|
188
204
|
by_severity: {
|
|
189
205
|
CRITICAL: violations.filter(v => v.severity === 'CRITICAL').length,
|
|
@@ -255,7 +271,7 @@ function updateAIEvidence(violations, gateResult, tokenUsage) {
|
|
|
255
271
|
const nextGate = {
|
|
256
272
|
status: gateResult.passed ? 'ALLOWED' : 'BLOCKED',
|
|
257
273
|
scope: gateScope === 'repo' || gateScope === 'repository' ? 'repo' : 'staging',
|
|
258
|
-
last_check:
|
|
274
|
+
last_check: formatLocalTimestamp(),
|
|
259
275
|
violations: blockingViolations.map(v => ({
|
|
260
276
|
file: v.filePath || v.file || 'unknown',
|
|
261
277
|
line: v.line || null,
|
|
@@ -771,13 +771,6 @@ summarize_all() {
|
|
|
771
771
|
print_final_signature
|
|
772
772
|
exit 0
|
|
773
773
|
fi
|
|
774
|
-
|
|
775
|
-
local is_revert_in_progress=0
|
|
776
|
-
if [[ "${AST_ALLOW_REVERT:-1}" == "1" ]] && command -v git >/dev/null 2>&1; then
|
|
777
|
-
if git rev-parse -q --verify REVERT_HEAD >/dev/null 2>&1; then
|
|
778
|
-
is_revert_in_progress=1
|
|
779
|
-
fi
|
|
780
|
-
fi
|
|
781
774
|
local gate_crit gate_high gate_med gate_low gate_es
|
|
782
775
|
|
|
783
776
|
# Decide gate values based on mode
|
|
@@ -802,15 +795,6 @@ summarize_all() {
|
|
|
802
795
|
# Block on ANY violation (CRITICAL + HIGH + MEDIUM + LOW)
|
|
803
796
|
if (( gate_crit > 0 || gate_high > 0 || gate_med > 0 || gate_low > 0 || gate_es > 0 )); then
|
|
804
797
|
printf "\n"
|
|
805
|
-
if (( is_revert_in_progress == 1 )); then
|
|
806
|
-
printf "%b[REVERT MODE - COMMIT ALLOWED]%b\n" "$YELLOW" "$NC"
|
|
807
|
-
printf " Detected git revert in progress (REVERT_HEAD).\n"
|
|
808
|
-
printf " Skipping quality gate blocking for pre-existing violations.\n"
|
|
809
|
-
printf " Tip: set AST_ALLOW_REVERT=0 to enforce gates during revert.\n"
|
|
810
|
-
printf "\n"
|
|
811
|
-
print_final_signature
|
|
812
|
-
exit 0
|
|
813
|
-
fi
|
|
814
798
|
if [[ "${BLOCK_ON_REPO_VIOLATIONS:-0}" == "1" ]]; then
|
|
815
799
|
printf "%b[COMMIT BLOCKED - STRICT REPO+STAGING]%b\n" "$RED" "$NC"
|
|
816
800
|
printf " CRITICAL violations (repository): %s\n" "$gate_crit"
|
|
@@ -835,15 +819,6 @@ summarize_all() {
|
|
|
835
819
|
# Standard mode: Block only on CRITICAL/HIGH IN STAGING
|
|
836
820
|
if (( gate_crit > 0 || gate_high > 0 )); then
|
|
837
821
|
printf "\n"
|
|
838
|
-
if (( is_revert_in_progress == 1 )); then
|
|
839
|
-
printf "%b[REVERT MODE - COMMIT ALLOWED]%b\n" "$YELLOW" "$NC"
|
|
840
|
-
printf " Detected git revert in progress (REVERT_HEAD).\n"
|
|
841
|
-
printf " Skipping quality gate blocking for pre-existing violations.\n"
|
|
842
|
-
printf " Tip: set AST_ALLOW_REVERT=0 to enforce gates during revert.\n"
|
|
843
|
-
printf "\n"
|
|
844
|
-
print_final_signature
|
|
845
|
-
exit 0
|
|
846
|
-
fi
|
|
847
822
|
printf "%b[COMMIT BLOCKED - CRITICAL/HIGH]%b\n" "$RED" "$NC"
|
|
848
823
|
printf " CRITICAL violations in staging: %s\n" "$gate_crit"
|
|
849
824
|
printf " HIGH violations in staging: %s\n" "$gate_high"
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
# Get current timestamp in ISO 8601 with milliseconds
|
|
12
12
|
# Returns: 2025-11-06T10:45:23.123Z
|
|
13
13
|
get_current_timestamp() {
|
|
14
|
-
|
|
14
|
+
local raw
|
|
15
|
+
raw=$(date +"%Y-%m-%dT%H:%M:%S.000%z")
|
|
16
|
+
echo "$raw" | sed -E 's/([+-][0-9]{2})([0-9]{2})$/\1:\2/'
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
# Get current timestamp in epoch seconds
|
|
@@ -26,10 +28,16 @@ iso_to_epoch() {
|
|
|
26
28
|
local timestamp="$1"
|
|
27
29
|
|
|
28
30
|
# Strip milliseconds if present (2025-11-06T10:45:23.123Z → 2025-11-06T10:45:23Z)
|
|
29
|
-
local clean_ts
|
|
31
|
+
local clean_ts
|
|
32
|
+
clean_ts=$(echo "$timestamp" | sed -E 's/\.[0-9]+Z$/Z/')
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
if echo "$clean_ts" | grep -qE 'Z$'; then
|
|
35
|
+
TZ=UTC date -j -f "%Y-%m-%dT%H:%M:%SZ" "$clean_ts" +%s 2>/dev/null || echo "0"
|
|
36
|
+
return 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
clean_ts=$(echo "$timestamp" | sed -E 's/\.[0-9]+([+-][0-9]{2}):([0-9]{2})$/\1\2/' | sed -E 's/([+-][0-9]{2}):([0-9]{2})$/\1\2/')
|
|
40
|
+
date -j -f "%Y-%m-%dT%H:%M:%S%z" "$clean_ts" +%s 2>/dev/null || echo "0"
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
# Get age of timestamp in seconds
|
package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log
CHANGED
|
@@ -37,3 +37,6 @@
|
|
|
37
37
|
{"timestamp":"2026-01-03T14:05:38.098Z","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"}}
|
|
38
38
|
{"timestamp":"2026-01-03T14:05:38.102Z","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"}}
|
|
39
39
|
{"timestamp":"2026-01-03T14:05:38.103Z","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)"}}
|
|
40
|
+
{"timestamp":"2026-01-04T07:12:14.852Z","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"}}
|
|
41
|
+
{"timestamp":"2026-01-04T07:12:14.855Z","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"}}
|
|
42
|
+
{"timestamp":"2026-01-04T07:12:14.856Z","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)"}}
|