0xray 4.0.34 → 4.0.36
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/.grok-plugin/plugin.json +1 -1
- package/.xray/codex.json +12 -4
- package/.xray/features.json +1 -1
- package/AGENTS-consumer.md +6 -6
- package/AGENTS.md +5 -5
- package/README.md +2 -2
- package/dist/AGENTS.md +5 -5
- package/dist/CHANGELOG.md +26 -0
- package/dist/README.md +2 -2
- package/dist/cli/index.js +2 -5
- package/dist/governance/governance-service.js +1 -1
- package/dist/integrations/base/README.md +1 -9
- package/dist/integrations/base/index.d.ts +0 -1
- package/dist/integrations/base/index.js +0 -2
- package/dist/integrations/governance/index.js +31 -8
- package/dist/integrations/grok/hooks/grok-hook-utils.js +1 -1
- package/dist/integrations/grok/hooks/session-start.js +12 -0
- package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +6 -6
- package/dist/integrations/hooks/goggles-mcp.mjs +10 -3
- package/dist/integrations/hooks/goggles-pipeline.mjs +110 -23
- package/dist/integrations/hooks/host-truth.mjs +74 -0
- package/dist/integrations/hooks/station-hook-runtime.cjs +3 -0
- package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/dist/mcps/knowledge-skills/storyteller.server.js +0 -1
- package/dist/nucleus/delegation-gate.d.ts +2 -2
- package/dist/nucleus/delegation-gate.js +13 -2
- package/dist/nucleus/work-freshness.mjs +189 -0
- package/dist/processors/implementations/agents-md-validation-processor.js +1 -1
- package/docs-site/docs/plates/boot.md +17 -2
- package/docs-site/docs/plates/governance.md +3 -2
- package/docs-site/docs/plates/index.md +3 -1
- package/docs-site/docs/plates/memory-recall.md +26 -35
- package/docs-site/docs/plates/orchestration.md +39 -35
- package/docs-site/docs/plates/processor.md +34 -36
- package/docs-site/docs/plates/reporting.md +3 -8
- package/docs-site/docs/plates/routing.md +22 -11
- package/package.json +3 -2
- package/scripts/foundry/release.mjs +48 -5
- package/scripts/mjs/run-grok-hook.mjs +50 -0
- package/scripts/mjs/test-consumer-readiness.mjs +1 -0
- package/scripts/mjs/test-mcp-functionality.mjs +14 -9
- package/scripts/node/basic-security-audit.cjs +0 -1
- package/scripts/node/bridge-mcp-wiring.cjs +66 -3
- package/scripts/node/install-bridges.cjs +3 -3
- package/scripts/node/postinstall.cjs +1 -1
- package/scripts/node/prepare-consumer.cjs +11 -7
- package/scripts/node/setup-dev.cjs +18 -26
- package/scripts/node/validate-mcp-connectivity.js +2 -1
- package/src/integrations/grok/plugin/0xray/hooks/hooks.json +6 -6
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/src/mcps/knowledge-skills/storyteller.server.ts +0 -1
- package/xray/agents_template.md +5 -5
- package/xray/codex.json +12 -4
- package/xray/features.json +1 -1
- package/dist/agents/known-names.d.ts +0 -26
- package/dist/agents/known-names.js +0 -72
- package/dist/analytics/consent-manager.d.ts +0 -92
- package/dist/analytics/consent-manager.js +0 -257
- package/dist/benchmark/performance-benchmark.d.ts +0 -103
- package/dist/benchmark/performance-benchmark.js +0 -373
- package/dist/cli/commands/analytics-disable.d.ts +0 -9
- package/dist/cli/commands/analytics-disable.js +0 -72
- package/dist/cli/commands/analytics-enable-action.d.ts +0 -8
- package/dist/cli/commands/analytics-enable-action.js +0 -82
- package/dist/cli/commands/analytics-preview.d.ts +0 -9
- package/dist/cli/commands/analytics-preview.js +0 -106
- package/dist/cli/commands/analytics-status.d.ts +0 -9
- package/dist/cli/commands/analytics-status.js +0 -68
- package/dist/cli/commands/enforce.d.ts +0 -12
- package/dist/cli/commands/enforce.js +0 -78
- package/dist/cli/commands/govern.d.ts +0 -29
- package/dist/cli/commands/govern.js +0 -149
- package/dist/cli/commands/security-audit.d.ts +0 -23
- package/dist/cli/commands/security-audit.js +0 -219
- package/dist/cli/server.d.ts +0 -1
- package/dist/cli/server.js +0 -147
- package/dist/config/routing-mappings.d.ts +0 -26
- package/dist/config/routing-mappings.js +0 -151
- package/dist/core/bridge.mjs +0 -922
- package/dist/core/trace-context.d.ts +0 -12
- package/dist/core/trace-context.js +0 -33
- package/dist/enforcement/index.d.ts +0 -22
- package/dist/enforcement/index.js +0 -40
- package/dist/enforcement/loaders/index.d.ts +0 -36
- package/dist/enforcement/loaders/index.js +0 -39
- package/dist/enforcement/test-auto-healing.d.ts +0 -83
- package/dist/enforcement/test-auto-healing.js +0 -325
- package/dist/inference/index.d.ts +0 -10
- package/dist/inference/index.js +0 -5
- package/dist/infrastructure/iac-validator.d.ts +0 -150
- package/dist/infrastructure/iac-validator.js +0 -465
- package/dist/infrastructure/schemas/cloud-schemas.d.ts +0 -482
- package/dist/infrastructure/schemas/cloud-schemas.js +0 -488
- package/dist/integrations/base/ExampleIntegration.d.ts +0 -46
- package/dist/integrations/base/ExampleIntegration.js +0 -180
- package/dist/integrations/enforcement-gate.d.ts +0 -44
- package/dist/integrations/enforcement-gate.js +0 -348
- package/dist/mcps/connection/connection-manager.d.ts +0 -39
- package/dist/mcps/connection/connection-manager.js +0 -79
- package/dist/mcps/index.d.ts +0 -17
- package/dist/mcps/index.js +0 -65
- package/dist/mcps/orchestrator/index.d.ts +0 -6
- package/dist/mcps/orchestrator/index.js +0 -5
- package/dist/metrics/index.d.ts +0 -6
- package/dist/metrics/index.js +0 -6
- package/dist/orchestrator/self-direction-activation.d.ts +0 -108
- package/dist/orchestrator/self-direction-activation.js +0 -244
- package/dist/orchestrator/universal-registry-bridge.d.ts +0 -84
- package/dist/orchestrator/universal-registry-bridge.js +0 -246
- package/dist/performance/performance-budget-enforcer.d.ts +0 -157
- package/dist/performance/performance-budget-enforcer.js +0 -433
- package/dist/performance/performance-regression-tester.d.ts +0 -107
- package/dist/performance/performance-regression-tester.js +0 -341
- package/dist/postprocessor/analysis/CodeChangeAnalyzer.d.ts +0 -11
- package/dist/postprocessor/analysis/CodeChangeAnalyzer.js +0 -50
- package/dist/postprocessor/config/ProcessorConfigLoader.d.ts +0 -44
- package/dist/postprocessor/config/ProcessorConfigLoader.js +0 -16
- package/dist/postprocessor/integration.d.ts +0 -156
- package/dist/postprocessor/integration.js +0 -194
- package/dist/postprocessor/metamorphosis/index.d.ts +0 -2
- package/dist/postprocessor/metamorphosis/index.js +0 -1
- package/dist/postprocessor/redeploy/RetryHandler.d.ts +0 -49
- package/dist/postprocessor/redeploy/RetryHandler.js +0 -118
- package/dist/processors/implementations/session-capture-processor.d.ts +0 -14
- package/dist/processors/implementations/session-capture-processor.js +0 -37
- package/dist/public/XrayService.d.ts +0 -17
- package/dist/public/XrayService.js +0 -40
- package/dist/public/index.d.ts +0 -4
- package/dist/public/index.js +0 -2
- package/dist/security/comprehensive-security-audit.d.ts +0 -157
- package/dist/security/comprehensive-security-audit.js +0 -1004
- package/dist/security/index.d.ts +0 -13
- package/dist/security/index.js +0 -13
- package/dist/security/security-agent-coordinator.d.ts +0 -71
- package/dist/security/security-agent-coordinator.js +0 -203
- package/dist/security/security-hardening-system.d.ts +0 -238
- package/dist/security/security-hardening-system.js +0 -726
- package/dist/security/security-orchestration-layer.d.ts +0 -118
- package/dist/security/security-orchestration-layer.js +0 -495
- package/dist/testing/memory-regression-suite.d.ts +0 -105
- package/dist/testing/memory-regression-suite.js +0 -258
- package/dist/tools/assess-complexity-tool.d.ts +0 -28
- package/dist/tools/assess-complexity-tool.js +0 -44
- package/dist/tools/query-routing-tool.d.ts +0 -17
- package/dist/tools/query-routing-tool.js +0 -59
- package/dist/utils/batch-operations.d.ts +0 -25
- package/dist/utils/batch-operations.js +0 -292
- package/dist/utils/task-graph.d.ts +0 -29
- package/dist/utils/task-graph.js +0 -106
- package/dist/utils/test-template-generator.d.ts +0 -25
- package/dist/utils/test-template-generator.js +0 -178
- package/dist/utils/token-manager.d.ts +0 -48
- package/dist/utils/token-manager.js +0 -163
- package/dist/validation/agent-config-validator.d.ts +0 -110
- package/dist/validation/agent-config-validator.js +0 -280
- package/dist/validation/orchestration-flow-validator.d.ts +0 -87
- package/dist/validation/orchestration-flow-validator.js +0 -606
- package/src/mcps/connection/connection-manager.ts +0 -91
- package/src/mcps/index.ts +0 -80
- package/src/mcps/orchestrator/index.ts +0 -29
|
@@ -1,433 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Performance Budget Enforcement System
|
|
3
|
-
*
|
|
4
|
-
* Comprehensive performance testing and monitoring system that enforces
|
|
5
|
-
* Universal Development Codex performance budget requirements.
|
|
6
|
-
*
|
|
7
|
-
* Performance Budget Requirements:
|
|
8
|
-
* - Bundle size <2MB (gzipped <700KB)
|
|
9
|
-
* - First Contentful Paint <2s
|
|
10
|
-
* - Time to Interactive <5s
|
|
11
|
-
*
|
|
12
|
-
* @since 2026-01-08
|
|
13
|
-
*/
|
|
14
|
-
import { EventEmitter } from "events";
|
|
15
|
-
import * as fs from "fs";
|
|
16
|
-
import * as path from "path";
|
|
17
|
-
import { execSync } from "child_process";
|
|
18
|
-
import { performance } from "perf_hooks";
|
|
19
|
-
import { frameworkLogger } from "../core/framework-logger.js";
|
|
20
|
-
// Performance budget constants from Universal Development Codex
|
|
21
|
-
export const PERFORMANCE_BUDGET = {
|
|
22
|
-
bundleSize: {
|
|
23
|
-
uncompressed: 2 * 1024 * 1024, // 2MB
|
|
24
|
-
gzipped: 700 * 1024, // 700KB
|
|
25
|
-
},
|
|
26
|
-
webVitals: {
|
|
27
|
-
firstContentfulPaint: 2000, // 2s
|
|
28
|
-
timeToInteractive: 5000, // 5s
|
|
29
|
-
largestContentfulPaint: 2500, // 2.5s
|
|
30
|
-
cumulativeLayoutShift: 0.1, // 0.1
|
|
31
|
-
firstInputDelay: 100, // 100ms
|
|
32
|
-
},
|
|
33
|
-
runtime: {
|
|
34
|
-
memoryUsage: 50 * 1024 * 1024, // 50MB heap usage
|
|
35
|
-
startupTime: 100, // 100ms
|
|
36
|
-
testExecutionTime: 5000, // 5s
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* Comprehensive performance budget enforcement system
|
|
41
|
-
*/
|
|
42
|
-
export class PerformanceBudgetEnforcer extends EventEmitter {
|
|
43
|
-
reports = [];
|
|
44
|
-
monitoringActive = false;
|
|
45
|
-
alertThresholds = {
|
|
46
|
-
warning: 0.9,
|
|
47
|
-
error: 1.0,
|
|
48
|
-
critical: 1.1,
|
|
49
|
-
};
|
|
50
|
-
started = false;
|
|
51
|
-
boundViolation;
|
|
52
|
-
boundBudgetExceeded;
|
|
53
|
-
constructor() {
|
|
54
|
-
super();
|
|
55
|
-
}
|
|
56
|
-
start() {
|
|
57
|
-
if (this.started)
|
|
58
|
-
return;
|
|
59
|
-
this.started = true;
|
|
60
|
-
this.setupEventHandlers();
|
|
61
|
-
}
|
|
62
|
-
setupEventHandlers() {
|
|
63
|
-
this.boundViolation = this.handleViolation.bind(this);
|
|
64
|
-
this.boundBudgetExceeded = this.handleBudgetExceeded.bind(this);
|
|
65
|
-
this.on("violation", this.boundViolation);
|
|
66
|
-
this.on("budget-exceeded", this.boundBudgetExceeded);
|
|
67
|
-
}
|
|
68
|
-
destroy() {
|
|
69
|
-
this.off("violation", this.boundViolation);
|
|
70
|
-
this.off("budget-exceeded", this.boundBudgetExceeded);
|
|
71
|
-
this.removeAllListeners();
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Analyze bundle size against performance budget
|
|
75
|
-
*/
|
|
76
|
-
async analyzeBundleSize(distPath = "./dist") {
|
|
77
|
-
const metrics = {
|
|
78
|
-
totalSize: 0,
|
|
79
|
-
gzippedSize: 0,
|
|
80
|
-
fileCount: 0,
|
|
81
|
-
largestFile: { name: "", size: 0, gzippedSize: 0 },
|
|
82
|
-
breakdown: [],
|
|
83
|
-
};
|
|
84
|
-
if (!fs.existsSync(distPath)) {
|
|
85
|
-
throw new Error(`Distribution directory not found: ${distPath}`);
|
|
86
|
-
}
|
|
87
|
-
const files = fs.readdirSync(distPath);
|
|
88
|
-
const jsFiles = files.filter((file) => file.endsWith(".js") || file.endsWith(".mjs"));
|
|
89
|
-
for (const file of jsFiles) {
|
|
90
|
-
const filePath = path.join(distPath, file);
|
|
91
|
-
const stats = fs.statSync(filePath);
|
|
92
|
-
const size = stats.size;
|
|
93
|
-
// Calculate gzipped size
|
|
94
|
-
let gzippedSize = 0;
|
|
95
|
-
try {
|
|
96
|
-
const gzipped = execSync(`gzip -c "${filePath}" | wc -c`, {
|
|
97
|
-
encoding: "utf8",
|
|
98
|
-
});
|
|
99
|
-
gzippedSize = parseInt(gzipped.trim());
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
frameworkLogger.log("performance-budget-enforcer", "gzip-failed", "warning", { file, error });
|
|
103
|
-
gzippedSize = size; // Fallback to uncompressed size
|
|
104
|
-
}
|
|
105
|
-
metrics.totalSize += size;
|
|
106
|
-
metrics.gzippedSize += gzippedSize;
|
|
107
|
-
metrics.fileCount++;
|
|
108
|
-
// Track largest file
|
|
109
|
-
if (size > metrics.largestFile.size) {
|
|
110
|
-
metrics.largestFile = { name: file, size, gzippedSize };
|
|
111
|
-
}
|
|
112
|
-
// Add to breakdown
|
|
113
|
-
metrics.breakdown.push({
|
|
114
|
-
name: file,
|
|
115
|
-
size,
|
|
116
|
-
gzippedSize,
|
|
117
|
-
percentage: 0, // Will be calculated after all files are processed
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
// Calculate percentages
|
|
121
|
-
metrics.breakdown.forEach((file) => {
|
|
122
|
-
file.percentage = (file.size / (metrics.totalSize || 1)) * 100;
|
|
123
|
-
});
|
|
124
|
-
// Sort breakdown by size descending
|
|
125
|
-
metrics.breakdown.sort((a, b) => b.size - a.size);
|
|
126
|
-
return metrics;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Measure web vitals (simulated for server-side framework)
|
|
130
|
-
* In a real web application, this would use the Web Vitals library
|
|
131
|
-
*/
|
|
132
|
-
async measureWebVitals() {
|
|
133
|
-
// For server-side framework, we'll simulate measurements
|
|
134
|
-
// In a real implementation, this would collect from actual page loads
|
|
135
|
-
const metrics = {
|
|
136
|
-
firstContentfulPaint: Math.random() * 1000 + 500, // 500-1500ms
|
|
137
|
-
timeToInteractive: Math.random() * 2000 + 2000, // 2000-4000ms
|
|
138
|
-
largestContentfulPaint: Math.random() * 1000 + 1500, // 1500-2500ms
|
|
139
|
-
cumulativeLayoutShift: Math.random() * 0.1, // 0-0.1
|
|
140
|
-
firstInputDelay: Math.random() * 50 + 25, // 25-75ms
|
|
141
|
-
timestamp: Date.now(),
|
|
142
|
-
};
|
|
143
|
-
return metrics;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Measure runtime performance metrics
|
|
147
|
-
*/
|
|
148
|
-
measureRuntimePerformance() {
|
|
149
|
-
const memUsage = process.memoryUsage();
|
|
150
|
-
const cpuUsage = process.cpuUsage();
|
|
151
|
-
return {
|
|
152
|
-
memoryUsage: {
|
|
153
|
-
rss: memUsage.rss,
|
|
154
|
-
heapUsed: memUsage.heapUsed,
|
|
155
|
-
heapTotal: memUsage.heapTotal,
|
|
156
|
-
external: memUsage.external,
|
|
157
|
-
},
|
|
158
|
-
startupTime: performance.now(), // This would be measured from app start
|
|
159
|
-
cpuUsage: (cpuUsage.user + cpuUsage.system) / 1000, // Convert to milliseconds
|
|
160
|
-
timestamp: Date.now(),
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Check performance budget compliance
|
|
165
|
-
*/
|
|
166
|
-
checkBudgetCompliance(bundleSize, webVitals, runtime) {
|
|
167
|
-
const violations = [];
|
|
168
|
-
// Bundle size checks
|
|
169
|
-
if (bundleSize.totalSize > PERFORMANCE_BUDGET.bundleSize.uncompressed) {
|
|
170
|
-
violations.push({
|
|
171
|
-
metric: "bundle-size-uncompressed",
|
|
172
|
-
actual: bundleSize.totalSize,
|
|
173
|
-
budget: PERFORMANCE_BUDGET.bundleSize.uncompressed,
|
|
174
|
-
percentage: (bundleSize.totalSize / PERFORMANCE_BUDGET.bundleSize.uncompressed) *
|
|
175
|
-
100,
|
|
176
|
-
severity: bundleSize.totalSize >
|
|
177
|
-
PERFORMANCE_BUDGET.bundleSize.uncompressed * 1.1
|
|
178
|
-
? "critical"
|
|
179
|
-
: "error",
|
|
180
|
-
recommendation: "Reduce bundle size by code splitting, tree shaking, or removing unused dependencies",
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
if (bundleSize.gzippedSize > PERFORMANCE_BUDGET.bundleSize.gzipped) {
|
|
184
|
-
violations.push({
|
|
185
|
-
metric: "bundle-size-gzipped",
|
|
186
|
-
actual: bundleSize.gzippedSize,
|
|
187
|
-
budget: PERFORMANCE_BUDGET.bundleSize.gzipped,
|
|
188
|
-
percentage: (bundleSize.gzippedSize / PERFORMANCE_BUDGET.bundleSize.gzipped) *
|
|
189
|
-
100,
|
|
190
|
-
severity: bundleSize.gzippedSize > PERFORMANCE_BUDGET.bundleSize.gzipped * 1.1
|
|
191
|
-
? "critical"
|
|
192
|
-
: "error",
|
|
193
|
-
recommendation: "Optimize gzipped bundle size through minification and compression improvements",
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
// Web vitals checks (if available)
|
|
197
|
-
if (webVitals) {
|
|
198
|
-
if (webVitals.firstContentfulPaint >
|
|
199
|
-
PERFORMANCE_BUDGET.webVitals.firstContentfulPaint) {
|
|
200
|
-
violations.push({
|
|
201
|
-
metric: "first-contentful-paint",
|
|
202
|
-
actual: webVitals.firstContentfulPaint,
|
|
203
|
-
budget: PERFORMANCE_BUDGET.webVitals.firstContentfulPaint,
|
|
204
|
-
percentage: (webVitals.firstContentfulPaint /
|
|
205
|
-
PERFORMANCE_BUDGET.webVitals.firstContentfulPaint) *
|
|
206
|
-
100,
|
|
207
|
-
severity: webVitals.firstContentfulPaint >
|
|
208
|
-
PERFORMANCE_BUDGET.webVitals.firstContentfulPaint * 1.1
|
|
209
|
-
? "critical"
|
|
210
|
-
: "error",
|
|
211
|
-
recommendation: "Optimize critical rendering path, reduce render-blocking resources",
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
if (webVitals.timeToInteractive >
|
|
215
|
-
PERFORMANCE_BUDGET.webVitals.timeToInteractive) {
|
|
216
|
-
violations.push({
|
|
217
|
-
metric: "time-to-interactive",
|
|
218
|
-
actual: webVitals.timeToInteractive,
|
|
219
|
-
budget: PERFORMANCE_BUDGET.webVitals.timeToInteractive,
|
|
220
|
-
percentage: (webVitals.timeToInteractive /
|
|
221
|
-
PERFORMANCE_BUDGET.webVitals.timeToInteractive) *
|
|
222
|
-
100,
|
|
223
|
-
severity: webVitals.timeToInteractive >
|
|
224
|
-
PERFORMANCE_BUDGET.webVitals.timeToInteractive * 1.1
|
|
225
|
-
? "critical"
|
|
226
|
-
: "error",
|
|
227
|
-
recommendation: "Reduce JavaScript execution time, optimize main thread work",
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
// Runtime checks
|
|
232
|
-
if (runtime.memoryUsage.heapUsed > PERFORMANCE_BUDGET.runtime.memoryUsage) {
|
|
233
|
-
violations.push({
|
|
234
|
-
metric: "memory-usage",
|
|
235
|
-
actual: runtime.memoryUsage.heapUsed,
|
|
236
|
-
budget: PERFORMANCE_BUDGET.runtime.memoryUsage,
|
|
237
|
-
percentage: (runtime.memoryUsage.heapUsed /
|
|
238
|
-
PERFORMANCE_BUDGET.runtime.memoryUsage) *
|
|
239
|
-
100,
|
|
240
|
-
severity: runtime.memoryUsage.heapUsed >
|
|
241
|
-
PERFORMANCE_BUDGET.runtime.memoryUsage * 1.1
|
|
242
|
-
? "critical"
|
|
243
|
-
: "warning",
|
|
244
|
-
recommendation: "Optimize memory usage through garbage collection improvements or memory leak fixes",
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
return violations;
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Generate comprehensive performance report
|
|
251
|
-
*/
|
|
252
|
-
async generatePerformanceReport() {
|
|
253
|
-
const bundleSize = await this.analyzeBundleSize();
|
|
254
|
-
const webVitals = await this.measureWebVitals();
|
|
255
|
-
const runtime = this.measureRuntimePerformance();
|
|
256
|
-
const violations = this.checkBudgetCompliance(bundleSize, webVitals, runtime);
|
|
257
|
-
// Generate recommendations based on violations
|
|
258
|
-
const recommendations = this.generateRecommendations(violations, bundleSize, webVitals, runtime);
|
|
259
|
-
// Determine overall status
|
|
260
|
-
const hasCritical = violations.some((v) => v.severity === "critical");
|
|
261
|
-
const hasError = violations.some((v) => v.severity === "error");
|
|
262
|
-
const hasWarning = violations.some((v) => v.severity === "warning");
|
|
263
|
-
let overallStatus = "pass";
|
|
264
|
-
if (hasCritical || hasError) {
|
|
265
|
-
overallStatus = "fail";
|
|
266
|
-
}
|
|
267
|
-
else if (hasWarning) {
|
|
268
|
-
overallStatus = "warning";
|
|
269
|
-
}
|
|
270
|
-
const report = {
|
|
271
|
-
timestamp: Date.now(),
|
|
272
|
-
bundleSize,
|
|
273
|
-
webVitals,
|
|
274
|
-
runtime,
|
|
275
|
-
violations,
|
|
276
|
-
recommendations,
|
|
277
|
-
overallStatus,
|
|
278
|
-
};
|
|
279
|
-
this.reports.push(report);
|
|
280
|
-
// Emit events for violations
|
|
281
|
-
violations.forEach((violation) => {
|
|
282
|
-
this.emit("violation", violation);
|
|
283
|
-
if (violation.percentage > 100) {
|
|
284
|
-
this.emit("budget-exceeded", violation);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
return report;
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Generate performance optimization recommendations
|
|
291
|
-
*/
|
|
292
|
-
generateRecommendations(violations, bundleSize, webVitals, runtime) {
|
|
293
|
-
const recommendations = [];
|
|
294
|
-
// Bundle size recommendations
|
|
295
|
-
if (bundleSize.totalSize >
|
|
296
|
-
PERFORMANCE_BUDGET.bundleSize.uncompressed * 0.8) {
|
|
297
|
-
recommendations.push("Consider implementing code splitting to reduce initial bundle size");
|
|
298
|
-
}
|
|
299
|
-
if (bundleSize.largestFile.size > bundleSize.totalSize * 0.5) {
|
|
300
|
-
recommendations.push(`Largest file (${bundleSize.largestFile.name}) is ${((bundleSize.largestFile.size / bundleSize.totalSize) * 100).toFixed(1)}% of bundle - consider splitting or optimizing`);
|
|
301
|
-
}
|
|
302
|
-
// Web vitals recommendations
|
|
303
|
-
if (webVitals && webVitals.firstContentfulPaint > 1500) {
|
|
304
|
-
recommendations.push("Optimize First Contentful Paint by prioritizing critical CSS and above-the-fold content");
|
|
305
|
-
}
|
|
306
|
-
if (webVitals && webVitals.timeToInteractive > 3000) {
|
|
307
|
-
recommendations.push("Reduce Time to Interactive by minimizing main thread blocking JavaScript");
|
|
308
|
-
}
|
|
309
|
-
// Runtime recommendations
|
|
310
|
-
if (runtime.memoryUsage.heapUsed >
|
|
311
|
-
PERFORMANCE_BUDGET.runtime.memoryUsage * 0.8) {
|
|
312
|
-
recommendations.push("Monitor for memory leaks and consider implementing memory optimization strategies");
|
|
313
|
-
}
|
|
314
|
-
// Add specific recommendations from violations
|
|
315
|
-
violations.forEach((violation) => {
|
|
316
|
-
if (!recommendations.includes(violation.recommendation)) {
|
|
317
|
-
recommendations.push(violation.recommendation);
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
return recommendations;
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Handle performance violations
|
|
324
|
-
*/
|
|
325
|
-
handleViolation(violation) {
|
|
326
|
-
const severity = violation.severity.toUpperCase();
|
|
327
|
-
frameworkLogger.log("performance-budget-enforcer", "budget-violation", "warning", {
|
|
328
|
-
severity,
|
|
329
|
-
metric: violation.metric,
|
|
330
|
-
actual: violation.actual.toLocaleString(),
|
|
331
|
-
budget: violation.budget.toLocaleString(),
|
|
332
|
-
percentage: violation.percentage.toFixed(1) + "%",
|
|
333
|
-
recommendation: violation.recommendation,
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Handle budget exceeded events
|
|
338
|
-
*/
|
|
339
|
-
handleBudgetExceeded(violation) {
|
|
340
|
-
frameworkLogger.log("performance-budget-enforcer", "budget-exceeded", "error", {
|
|
341
|
-
metric: violation.metric,
|
|
342
|
-
percentage: violation.percentage.toFixed(1) + "% of budget",
|
|
343
|
-
});
|
|
344
|
-
if (violation.severity === "critical") {
|
|
345
|
-
frameworkLogger.log("performance-budget-enforcer", "critical-violation", "error", {
|
|
346
|
-
message: "CRITICAL: This violation requires immediate attention before deployment",
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Start continuous performance monitoring
|
|
352
|
-
*/
|
|
353
|
-
startMonitoring(intervalMs = 30000) {
|
|
354
|
-
if (this.monitoringActive) {
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
this.monitoringActive = true;
|
|
358
|
-
const monitor = async () => {
|
|
359
|
-
if (!this.monitoringActive) {
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
try {
|
|
363
|
-
await this.generatePerformanceReport();
|
|
364
|
-
}
|
|
365
|
-
catch (error) {
|
|
366
|
-
frameworkLogger.log("performance-budget-enforcer", "monitoring-error", "error", { error });
|
|
367
|
-
}
|
|
368
|
-
setTimeout(monitor, intervalMs);
|
|
369
|
-
};
|
|
370
|
-
// Initial report
|
|
371
|
-
monitor();
|
|
372
|
-
}
|
|
373
|
-
/**
|
|
374
|
-
* Stop performance monitoring
|
|
375
|
-
*/
|
|
376
|
-
stopMonitoring() {
|
|
377
|
-
this.monitoringActive = false;
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
* Get historical performance reports
|
|
381
|
-
*/
|
|
382
|
-
getReports(limit = 10) {
|
|
383
|
-
return this.reports.slice(-limit);
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Export performance data for analysis
|
|
387
|
-
*/
|
|
388
|
-
exportPerformanceData() {
|
|
389
|
-
const summary = {
|
|
390
|
-
totalReports: this.reports.length,
|
|
391
|
-
averageViolations: this.reports.length > 0
|
|
392
|
-
? this.reports.reduce((sum, r) => sum + r.violations.length, 0) /
|
|
393
|
-
this.reports.length
|
|
394
|
-
: 0,
|
|
395
|
-
mostCommonViolation: "",
|
|
396
|
-
trend: "stable",
|
|
397
|
-
};
|
|
398
|
-
// Calculate most common violation
|
|
399
|
-
const violationCounts = {};
|
|
400
|
-
this.reports.forEach((report) => {
|
|
401
|
-
report.violations.forEach((violation) => {
|
|
402
|
-
violationCounts[violation.metric] =
|
|
403
|
-
(violationCounts[violation.metric] || 0) + 1;
|
|
404
|
-
});
|
|
405
|
-
});
|
|
406
|
-
const mostCommon = Object.entries(violationCounts).sort(([, a], [, b]) => b - a)[0];
|
|
407
|
-
summary.mostCommonViolation = mostCommon ? mostCommon[0] : "none";
|
|
408
|
-
// Calculate trend (simple implementation)
|
|
409
|
-
if (this.reports.length >= 3) {
|
|
410
|
-
const recent = this.reports.slice(-3);
|
|
411
|
-
const violationTrend = recent.map((r) => r.violations.length);
|
|
412
|
-
if (violationTrend.length >= 3 &&
|
|
413
|
-
violationTrend[0] !== undefined &&
|
|
414
|
-
violationTrend[1] !== undefined &&
|
|
415
|
-
violationTrend[2] !== undefined) {
|
|
416
|
-
const avgFirst = (violationTrend[0] + violationTrend[1]) / 2;
|
|
417
|
-
const avgLast = (violationTrend[1] + violationTrend[2]) / 2;
|
|
418
|
-
if (avgLast < avgFirst) {
|
|
419
|
-
summary.trend = "improving";
|
|
420
|
-
}
|
|
421
|
-
else if (avgLast > avgFirst) {
|
|
422
|
-
summary.trend = "degrading";
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
return {
|
|
427
|
-
reports: this.reports,
|
|
428
|
-
summary,
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
// Export singleton instance
|
|
433
|
-
export const performanceBudgetEnforcer = new PerformanceBudgetEnforcer();
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Performance Regression Testing
|
|
3
|
-
*
|
|
4
|
-
* Automated testing system that detects performance regressions and
|
|
5
|
-
* enforces performance budget compliance in CI/CD pipelines.
|
|
6
|
-
*
|
|
7
|
-
* @since 2026-01-08
|
|
8
|
-
*/
|
|
9
|
-
import { PerformanceBudgetEnforcer, PerformanceReport } from "./performance-budget-enforcer.js";
|
|
10
|
-
export interface PerformanceRegressionTest {
|
|
11
|
-
name: string;
|
|
12
|
-
description: string;
|
|
13
|
-
testFunction: () => Promise<void> | void;
|
|
14
|
-
timeout: number;
|
|
15
|
-
expectedDuration?: number;
|
|
16
|
-
tolerance: number;
|
|
17
|
-
}
|
|
18
|
-
export interface RegressionTestResult {
|
|
19
|
-
testName: string;
|
|
20
|
-
duration: number;
|
|
21
|
-
expectedDuration?: number;
|
|
22
|
-
deviation: number;
|
|
23
|
-
status: "pass" | "warning" | "fail";
|
|
24
|
-
error?: string;
|
|
25
|
-
timestamp: number;
|
|
26
|
-
}
|
|
27
|
-
export interface PerformanceBaseline {
|
|
28
|
-
testName: string;
|
|
29
|
-
averageDuration: number;
|
|
30
|
-
standardDeviation: number;
|
|
31
|
-
sampleCount: number;
|
|
32
|
-
lastUpdated: number;
|
|
33
|
-
tolerance: number;
|
|
34
|
-
}
|
|
35
|
-
export interface RegressionTestSuite {
|
|
36
|
-
name: string;
|
|
37
|
-
description: string;
|
|
38
|
-
tests: PerformanceRegressionTest[];
|
|
39
|
-
baselineFile: string;
|
|
40
|
-
failOnRegression: boolean;
|
|
41
|
-
warningThreshold: number;
|
|
42
|
-
failureThreshold: number;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Performance regression testing system
|
|
46
|
-
*/
|
|
47
|
-
export declare class PerformanceRegressionTester {
|
|
48
|
-
private baselines;
|
|
49
|
-
private results;
|
|
50
|
-
private budgetEnforcer;
|
|
51
|
-
constructor(budgetEnforcer?: PerformanceBudgetEnforcer);
|
|
52
|
-
/**
|
|
53
|
-
* Load performance baselines from file
|
|
54
|
-
*/
|
|
55
|
-
loadBaselines(baselineFile: string): void;
|
|
56
|
-
/**
|
|
57
|
-
* Save performance baselines to file
|
|
58
|
-
*/
|
|
59
|
-
saveBaselines(baselineFile: string): void;
|
|
60
|
-
/**
|
|
61
|
-
* Run a single performance regression test
|
|
62
|
-
*/
|
|
63
|
-
runRegressionTest(test: PerformanceRegressionTest): Promise<RegressionTestResult>;
|
|
64
|
-
/**
|
|
65
|
-
* Run a complete regression test suite
|
|
66
|
-
*/
|
|
67
|
-
runTestSuite(suite: RegressionTestSuite): Promise<{
|
|
68
|
-
results: RegressionTestResult[];
|
|
69
|
-
summary: {
|
|
70
|
-
totalTests: number;
|
|
71
|
-
passed: number;
|
|
72
|
-
warnings: number;
|
|
73
|
-
failed: number;
|
|
74
|
-
averageDeviation: number;
|
|
75
|
-
maxDeviation: number;
|
|
76
|
-
duration: number;
|
|
77
|
-
};
|
|
78
|
-
budgetReport?: PerformanceReport;
|
|
79
|
-
success: boolean;
|
|
80
|
-
}>;
|
|
81
|
-
/**
|
|
82
|
-
* Update baselines with new test results
|
|
83
|
-
*/
|
|
84
|
-
private updateBaselines;
|
|
85
|
-
/**
|
|
86
|
-
* Generate test suite summary
|
|
87
|
-
*/
|
|
88
|
-
private generateSummary;
|
|
89
|
-
/**
|
|
90
|
-
* Create default performance regression test suite
|
|
91
|
-
*/
|
|
92
|
-
createDefaultTestSuite(): RegressionTestSuite;
|
|
93
|
-
/**
|
|
94
|
-
* Export test results for analysis
|
|
95
|
-
*/
|
|
96
|
-
exportResults(): {
|
|
97
|
-
results: RegressionTestResult[];
|
|
98
|
-
baselines: Record<string, PerformanceBaseline>;
|
|
99
|
-
summary: {
|
|
100
|
-
totalTests: number;
|
|
101
|
-
passRate: number;
|
|
102
|
-
averageDeviation: number;
|
|
103
|
-
regressionDetected: boolean;
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
export declare const performanceRegressionTester: PerformanceRegressionTester;
|