claude-flow-novice 2.2.4 → 2.2.5

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 (288) hide show
  1. package/package.json +9 -8
  2. package/scripts/.claude-flow/metrics/agent-metrics.json +1 -0
  3. package/scripts/.claude-flow/metrics/performance.json +9 -0
  4. package/scripts/.claude-flow/metrics/task-metrics.json +10 -0
  5. package/scripts/CLEANUP_OPTIMIZATION_REPORT.json +312 -0
  6. package/scripts/CLEANUP_PERFORMANCE_OPTIMIZATION.md +387 -0
  7. package/scripts/CLEANUP_QUICK_START.md +268 -0
  8. package/scripts/CLEANUP_TEST_RESULTS.md +205 -0
  9. package/scripts/README.md +339 -0
  10. package/scripts/ace-query.sh +384 -0
  11. package/scripts/agent-token-analysis.js +430 -0
  12. package/scripts/auto-setup.js +332 -0
  13. package/scripts/build/README.md +167 -0
  14. package/scripts/build/build-config.js +27 -0
  15. package/scripts/build/build-prompt-copier.sh +30 -0
  16. package/scripts/build/performance-monitor.js +869 -0
  17. package/scripts/build/prepare-publish.js +150 -0
  18. package/scripts/build/typescript-fixer.js +621 -0
  19. package/scripts/build/unified-builder.sh +428 -0
  20. package/scripts/build/update-bin-version.js +32 -0
  21. package/scripts/build/validate-agents.js +238 -0
  22. package/scripts/build-index.js +43 -0
  23. package/scripts/build-orchestrator.js +320 -0
  24. package/scripts/check-routing-stats.cjs +122 -0
  25. package/scripts/ci-validation.js +375 -0
  26. package/scripts/cleanup-blocking-coordination.sh +420 -0
  27. package/scripts/cleanup-idle-sessions.sh +59 -0
  28. package/scripts/collect-build-metrics.js +65 -0
  29. package/scripts/demo/README.md +79 -0
  30. package/scripts/demo/autoscaling-demo-simplified.js +963 -0
  31. package/scripts/demo/comprehensive-dashboard-test.js +693 -0
  32. package/scripts/demo/confidence-log.js +87 -0
  33. package/scripts/demo/confidence-report.js +82 -0
  34. package/scripts/demo/demo-multi-swarm-coordination.js +325 -0
  35. package/scripts/demo/demo-production-deployment.js +399 -0
  36. package/scripts/demo/demo-visualization-system.js +149 -0
  37. package/scripts/demo/performance-analysis.cjs +71 -0
  38. package/scripts/demo/performance-analysis.js +71 -0
  39. package/scripts/demo/test-autoscaling-demo.js +314 -0
  40. package/scripts/dependency-optimizer.js +349 -0
  41. package/scripts/dependency-security-assessment.js +331 -0
  42. package/scripts/deploy-sdk.sh +176 -0
  43. package/scripts/deployment-readiness-report.json +179 -0
  44. package/scripts/dev/README.md +264 -0
  45. package/scripts/dev/claude-flow-wrapper.sh +35 -0
  46. package/scripts/dev/claude-monitor.py +419 -0
  47. package/scripts/dev/claude-sparc.sh +562 -0
  48. package/scripts/dev/claude-wrapper.sh +17 -0
  49. package/scripts/dev/demo-phase3-compliance.js +172 -0
  50. package/scripts/dev/demo-task-system.ts +224 -0
  51. package/scripts/dev/deployment-validator.js +315 -0
  52. package/scripts/dev/spawn-claude-terminal.sh +32 -0
  53. package/scripts/dev/start-portal.sh +506 -0
  54. package/scripts/dev/start-web-ui.js +15 -0
  55. package/scripts/dev/stop-portal.sh +311 -0
  56. package/scripts/dev/validate-examples.ts +288 -0
  57. package/scripts/dev/validate-phase2.cjs +451 -0
  58. package/scripts/dev/validate-phase2.js +785 -0
  59. package/scripts/dev/validate-phase3.cjs +208 -0
  60. package/scripts/dev/validate-security-remediation.js +1 -0
  61. package/scripts/ecosystem.config.cjs +90 -0
  62. package/scripts/fix-js-extensions.js +167 -0
  63. package/scripts/generate-basic-types.js +73 -0
  64. package/scripts/generate-changelog.js +318 -0
  65. package/scripts/git-hooks/pre-commit.sh +143 -0
  66. package/scripts/health-checks.js +634 -0
  67. package/scripts/hook-wrapper.sh +54 -0
  68. package/scripts/install/README.md +375 -0
  69. package/scripts/install/REDIS_SETUP_VALIDATION.json +245 -0
  70. package/scripts/install/check-prerequisites.js +303 -0
  71. package/scripts/install/config-wizard.js +606 -0
  72. package/scripts/install/dependency-checker.js +385 -0
  73. package/scripts/install/health-check.js +765 -0
  74. package/scripts/install/install.js +256 -0
  75. package/scripts/install/installation-benchmark.js +461 -0
  76. package/scripts/install/quick-install.js +720 -0
  77. package/scripts/install/quick-start-wizard.js +295 -0
  78. package/scripts/install/redis-cli.js +289 -0
  79. package/scripts/install/redis-install-guides.md +407 -0
  80. package/scripts/install/redis-setup.js +559 -0
  81. package/scripts/install/redis-test.js +278 -0
  82. package/scripts/install/service-manager.js +672 -0
  83. package/scripts/install/setup.js +832 -0
  84. package/scripts/install/uninstall.js +526 -0
  85. package/scripts/install/update.js +461 -0
  86. package/scripts/install-pre-commit-hook.sh +127 -0
  87. package/scripts/legacy/README.md +272 -0
  88. package/scripts/legacy/batch-fix-ts.sh +54 -0
  89. package/scripts/legacy/build-migration.sh +105 -0
  90. package/scripts/legacy/build-monitor.js +209 -0
  91. package/scripts/legacy/build-with-filter.sh +84 -0
  92. package/scripts/legacy/build-workaround.sh +71 -0
  93. package/scripts/legacy/fix-ts-advanced.js +358 -0
  94. package/scripts/legacy/fix-ts-final.sh +50 -0
  95. package/scripts/legacy/fix-ts-targeted.sh +49 -0
  96. package/scripts/legacy/fix-typescript-errors.js +305 -0
  97. package/scripts/legacy/force-build.sh +63 -0
  98. package/scripts/legacy/optimize-performance.js +400 -0
  99. package/scripts/legacy/performance-monitor.js +263 -0
  100. package/scripts/legacy/performance-monitoring.js +532 -0
  101. package/scripts/legacy/performance-test-runner.js +645 -0
  102. package/scripts/legacy/quick-fix-ts.js +281 -0
  103. package/scripts/legacy/safe-build.sh +63 -0
  104. package/scripts/memory-monitor-coordinator.js +322 -0
  105. package/scripts/migrate-to-sdk.sh +520 -0
  106. package/scripts/migration/QUICK-START.md +189 -0
  107. package/scripts/migration/QUICK-START.md.backup-1760135091363 +189 -0
  108. package/scripts/migration/README.md +464 -0
  109. package/scripts/migration/TASK-1.3.2-COMPLETION-REPORT.md +500 -0
  110. package/scripts/migration/TASK-1.3.2-COMPLETION-REPORT.md.backup-1760135091348 +500 -0
  111. package/scripts/migration/UPDATE-PATHS-README.md +464 -0
  112. package/scripts/migration/UPDATE-PATHS-README.md.backup-1760135091337 +464 -0
  113. package/scripts/migration/example-patterns.json +19 -0
  114. package/scripts/migration/install-arm64.js +78 -0
  115. package/scripts/migration/install.js +83 -0
  116. package/scripts/migration/migrate-hooks.js +173 -0
  117. package/scripts/migration/migration-examples.ts +318 -0
  118. package/scripts/migration/reorganize-workspace.js +504 -0
  119. package/scripts/migration/test-update-paths.js +359 -0
  120. package/scripts/migration/update-paths.js +664 -0
  121. package/scripts/migration/validate-migration.js +647 -0
  122. package/scripts/monitor-loop.sh +65 -0
  123. package/scripts/monitor-memory.sh +47 -0
  124. package/scripts/monitor-migration.js +339 -0
  125. package/scripts/monitor.py +43 -0
  126. package/scripts/monitoring/README.md +178 -0
  127. package/scripts/monitoring/alert-monitor.sh +220 -0
  128. package/scripts/monitoring/analyze-resources.sh +199 -0
  129. package/scripts/monitoring/dashboards/rate-limiting-dashboard.json +211 -0
  130. package/scripts/monitoring/dynamic-monitor.sh +85 -0
  131. package/scripts/monitoring/launch-stability-test.sh +184 -0
  132. package/scripts/monitoring/monitor-test.sh +93 -0
  133. package/scripts/monitoring/pre-test-validation.sh +208 -0
  134. package/scripts/monitoring/quick-test-alerting.sh +118 -0
  135. package/scripts/monitoring/quick-test-rate-limiting.sh +206 -0
  136. package/scripts/monitoring/rate-limiting-monitor.sh +380 -0
  137. package/scripts/monitoring/resource-monitor.sh +126 -0
  138. package/scripts/monitoring/stability-monitor.js +429 -0
  139. package/scripts/monitoring/test-monitor-quick.sh +54 -0
  140. package/scripts/monitoring/view-alerts.sh +307 -0
  141. package/scripts/npm-metrics-collector.js +482 -0
  142. package/scripts/npm-package-validation.cjs +299 -0
  143. package/scripts/optimization/build-optimizer.js +438 -0
  144. package/scripts/optimization/config-validator.js +761 -0
  145. package/scripts/optimization/test-optimization.js +432 -0
  146. package/scripts/optimization/unified-activation.js +839 -0
  147. package/scripts/optimize-package-swarm.js +54 -0
  148. package/scripts/performance/ACTIVATION_COMMANDS.md +292 -0
  149. package/scripts/performance/sqlite-enhanced-activation.sh +583 -0
  150. package/scripts/performance/test-enhanced-backend.sh +504 -0
  151. package/scripts/performance-monitor.js +644 -0
  152. package/scripts/performance-test-runner.js +698 -0
  153. package/scripts/post-deployment-monitoring.js +350 -0
  154. package/scripts/post-edit-pipeline.js +2091 -0
  155. package/scripts/post-install-claude-md.js +78 -0
  156. package/scripts/postinstall.js +79 -0
  157. package/scripts/pre-publish-validation.cjs +212 -0
  158. package/scripts/pre-publish-validation.js +429 -0
  159. package/scripts/redis-lua/cleanup-blocking-coordination.lua +198 -0
  160. package/scripts/release-announcement.js +425 -0
  161. package/scripts/release-notification.js +248 -0
  162. package/scripts/release-rollback.js +376 -0
  163. package/scripts/release-validation.js +460 -0
  164. package/scripts/rollback-sdk.sh +66 -0
  165. package/scripts/run-production-validation.ts +590 -0
  166. package/scripts/run-stability-validation.sh +687 -0
  167. package/scripts/security/README.md +339 -0
  168. package/scripts/security/deployment-validation.cjs +279 -0
  169. package/scripts/security/envelope-encryption-confidence-report.cjs +422 -0
  170. package/scripts/security/install-git-hooks.sh +132 -0
  171. package/scripts/security/install-git-secrets.sh +295 -0
  172. package/scripts/security/rotate-api-keys.js +469 -0
  173. package/scripts/security/ruv-swarm-safe.js +74 -0
  174. package/scripts/security/security-audit.cjs +538 -0
  175. package/scripts/security/setup-redis-auth.sh +397 -0
  176. package/scripts/security/validate-envelope-encryption.cjs +340 -0
  177. package/scripts/security-scan.js +492 -0
  178. package/scripts/src/web/frontend/.claude-flow/metrics/agent-metrics.json +1 -0
  179. package/scripts/src/web/frontend/.claude-flow/metrics/performance.json +9 -0
  180. package/scripts/src/web/frontend/.claude-flow/metrics/task-metrics.json +10 -0
  181. package/scripts/switch-api.sh +158 -0
  182. package/scripts/sync-agents.js +290 -0
  183. package/scripts/test/50-agent-test.js +625 -0
  184. package/scripts/test/NEW_STABILITY_TEST_GUIDE.md +407 -0
  185. package/scripts/test/README.md +236 -0
  186. package/scripts/test/STABILITY_TEST_EXAMPLE.md +347 -0
  187. package/scripts/test/STABILITY_TEST_README.md +480 -0
  188. package/scripts/test/agent-worker.js +309 -0
  189. package/scripts/test/ai-coordination-test.js +650 -0
  190. package/scripts/test/ai-mesh-coordination-test.js +416 -0
  191. package/scripts/test/check-links.ts +274 -0
  192. package/scripts/test/check-performance-regression.ts +168 -0
  193. package/scripts/test/cli-agent-coordination-test.js +313 -0
  194. package/scripts/test/coordinator-multilingual-test.js +396 -0
  195. package/scripts/test/coordinator-transparency-demo.js +585 -0
  196. package/scripts/test/coverage-report.ts +692 -0
  197. package/scripts/test/generate-swarm-tests.js +633 -0
  198. package/scripts/test/integration-test-validation.cjs +253 -0
  199. package/scripts/test/load-test-swarm.js +576 -0
  200. package/scripts/test/mesh-coordination-zero-overlap-test.js +740 -0
  201. package/scripts/test/multilingual-hello-world-test.js +390 -0
  202. package/scripts/test/quick-multilingual-demo.js +464 -0
  203. package/scripts/test/real-agent-test.js +312 -0
  204. package/scripts/test/run-phase3-compliance-tests.js +427 -0
  205. package/scripts/test/run-stability-test-examples.sh +292 -0
  206. package/scripts/test/stability-results/stability-metrics.jsonl +83 -0
  207. package/scripts/test/stability-results/stability-test-report.json +128 -0
  208. package/scripts/test/stability-results/stability-test.log +1827 -0
  209. package/scripts/test/stability-test-50-agents.js +734 -0
  210. package/scripts/test/test-batch-tasks.ts +29 -0
  211. package/scripts/test/test-byzantine-resolution.js +246 -0
  212. package/scripts/test/test-claude-spawn-options.sh +63 -0
  213. package/scripts/test/test-cli-wizard.js +331 -0
  214. package/scripts/test/test-comprehensive.js +401 -0
  215. package/scripts/test/test-coordination-features.ts +238 -0
  216. package/scripts/test/test-fallback-systems.js +276 -0
  217. package/scripts/test/test-init-command.ts +302 -0
  218. package/scripts/test/test-mcp.ts +251 -0
  219. package/scripts/test/test-runner.ts +568 -0
  220. package/scripts/test/test-swarm-integration.sh +92 -0
  221. package/scripts/test/test-swarm.ts +142 -0
  222. package/scripts/test/validation-summary.ts +408 -0
  223. package/scripts/test-cleanup-performance.sh +416 -0
  224. package/scripts/test-dashboard-auth.cjs +203 -0
  225. package/scripts/test-docker-deployment.sh +207 -0
  226. package/scripts/test-npm-package.cjs +167 -0
  227. package/scripts/test-provider-routing.cjs +226 -0
  228. package/scripts/test-routing-telemetry.cjs +147 -0
  229. package/scripts/test-runner.cjs +154 -0
  230. package/scripts/test-zai-10k.cjs +81 -0
  231. package/scripts/test-zai-api.cjs +191 -0
  232. package/scripts/test-zai-diagnostic.cjs +151 -0
  233. package/scripts/test-zai-final.cjs +128 -0
  234. package/scripts/test-zai-with-env.cjs +85 -0
  235. package/scripts/utils/README.md +261 -0
  236. package/scripts/utils/clean-build-artifacts.sh +94 -0
  237. package/scripts/utils/cleanup-root.sh +69 -0
  238. package/scripts/utils/fix-cliffy-imports.js +307 -0
  239. package/scripts/utils/fix-duplicate-imports.js +114 -0
  240. package/scripts/utils/fix-error-handling.cjs +70 -0
  241. package/scripts/utils/fix-import-paths.js +104 -0
  242. package/scripts/utils/fix-imports.js +116 -0
  243. package/scripts/utils/fix-shebang.js +78 -0
  244. package/scripts/utils/fix-test-modules.js +27 -0
  245. package/scripts/utils/fix-timezone-issue-246.js +200 -0
  246. package/scripts/utils/fix-ts-comprehensive.py +182 -0
  247. package/scripts/utils/fix-ts-targeted-batch.js +250 -0
  248. package/scripts/utils/remove-benchmark-conflicts.sh +140 -0
  249. package/scripts/utils/simple-test-fixer.js +190 -0
  250. package/scripts/utils/validate-metrics-structure.cjs +144 -0
  251. package/scripts/validate-agent-hooks.js +506 -0
  252. package/scripts/validate-changelog.js +241 -0
  253. package/scripts/validate-coordination-cli.js +69 -0
  254. package/scripts/validate-coordination-toggle-integration.cjs +501 -0
  255. package/scripts/validate-docker-infrastructure.sh +502 -0
  256. package/scripts/validate-entry-points.js +300 -0
  257. package/scripts/validate-stage3-performance.ts +377 -0
  258. package/scripts/validate-template-bundling.js +180 -0
  259. package/scripts/validation/README.md +33 -0
  260. package/scripts/validation/acl-security-validation.cjs +214 -0
  261. package/scripts/validation/acl-security-validation.js +402 -0
  262. package/scripts/validation/byzantine-verification.js +407 -0
  263. package/scripts/validation/final-phase-2-consensus.cjs +219 -0
  264. package/scripts/validation/final-security-validation.js +791 -0
  265. package/scripts/validation/final-wasm-validation.cjs +840 -0
  266. package/scripts/validation/integration-test-analysis.js +105 -0
  267. package/scripts/validation/phase-0-comprehensive-validation.js +474 -0
  268. package/scripts/validation/phase-0-consensus-report.js +139 -0
  269. package/scripts/validation/phase-0-final-report.js +112 -0
  270. package/scripts/validation/phase-0-redis-consensus-report.js +129 -0
  271. package/scripts/validation/phase-0-validation-improved.js +490 -0
  272. package/scripts/validation/phase-0-validation-test.js +65 -0
  273. package/scripts/validation/phase-1-consensus-report.cjs +342 -0
  274. package/scripts/validation/phase-1-consensus-validation.cjs +551 -0
  275. package/scripts/validation/phase-1-consensus-validation.js +551 -0
  276. package/scripts/validation/phase-2-consensus-report.cjs +186 -0
  277. package/scripts/validation/phase-2-validation.cjs +171 -0
  278. package/scripts/validation/phase-2-validation.js +171 -0
  279. package/scripts/validation/phase-4-consensus-report.js +181 -0
  280. package/scripts/validation/phase-4-final-validation.js +351 -0
  281. package/scripts/validation/phase-5-consensus-report.cjs +113 -0
  282. package/scripts/validation/phase-5-consensus-report.js +113 -0
  283. package/scripts/validation/security-analysis.js +49 -0
  284. package/scripts/validation/security-validation.js +492 -0
  285. package/scripts/validation/simple-security-validation.js +464 -0
  286. package/scripts/verify-installation.js +112 -0
  287. package/scripts/verify-mcp-server.js +86 -0
  288. package/scripts/verify-sdk-phase1.cjs +293 -0
@@ -0,0 +1,734 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * 8-Hour Stability Test for 50-Agent Swarm
5
+ *
6
+ * Tests:
7
+ * - 50 agents coordinating every 5 minutes for 8 hours (96 cycles)
8
+ * - Memory stability (RSS/VSZ) with <10% growth target
9
+ * - File descriptor stability
10
+ * - tmpfs usage monitoring
11
+ * - Coordination time variance <20%
12
+ * - Zero crash tolerance
13
+ *
14
+ * Usage:
15
+ * node scripts/test/stability-test-50-agents.js
16
+ * node scripts/test/stability-test-50-agents.js --dry-run
17
+ * node scripts/test/stability-test-50-agents.js --cycles 10 --interval 30000
18
+ */
19
+
20
+ import { spawn, exec } from 'child_process';
21
+ import { promisify } from 'util';
22
+ import * as fs from 'fs/promises';
23
+ import * as path from 'path';
24
+ import * as os from 'os';
25
+
26
+ const execAsync = promisify(exec);
27
+
28
+ // Configuration
29
+ const CONFIG = {
30
+ AGENT_COUNT: 50,
31
+ COORDINATION_INTERVAL: 5 * 60 * 1000, // 5 minutes
32
+ TOTAL_DURATION: 8 * 60 * 60 * 1000, // 8 hours
33
+ TOTAL_CYCLES: 96,
34
+ LOG_FILE: 'stability-test-results.jsonl',
35
+ MEMORY_GROWTH_THRESHOLD: 0.10, // 10%
36
+ FD_VARIANCE_THRESHOLD: 0.10, // 10%
37
+ COORDINATION_VARIANCE_THRESHOLD: 0.20, // 20%
38
+ TMPFS_PATH: '/tmp',
39
+ HEALTH_CHECK_INTERVAL: 30000, // 30 seconds
40
+ };
41
+
42
+ // Parse CLI args
43
+ const args = process.argv.slice(2);
44
+ const isDryRun = args.includes('--dry-run');
45
+ const cyclesOverride = args.findIndex(a => a === '--cycles');
46
+ const intervalOverride = args.findIndex(a => a === '--interval');
47
+
48
+ if (cyclesOverride !== -1 && args[cyclesOverride + 1]) {
49
+ CONFIG.TOTAL_CYCLES = parseInt(args[cyclesOverride + 1], 10);
50
+ CONFIG.TOTAL_DURATION = CONFIG.TOTAL_CYCLES * CONFIG.COORDINATION_INTERVAL;
51
+ }
52
+ if (intervalOverride !== -1 && args[intervalOverride + 1]) {
53
+ CONFIG.COORDINATION_INTERVAL = parseInt(args[intervalOverride + 1], 10);
54
+ }
55
+
56
+ class StabilityTestRunner {
57
+ constructor() {
58
+ this.agents = [];
59
+ this.swarmId = null;
60
+ this.startTime = null;
61
+ this.baselineMetrics = null;
62
+ this.cycleMetrics = [];
63
+ this.isRunning = false;
64
+ this.logStream = null;
65
+ this.healthCheckInterval = null;
66
+
67
+ // Bind cleanup handlers
68
+ this.cleanup = this.cleanup.bind(this);
69
+ process.on('SIGINT', this.cleanup);
70
+ process.on('SIGTERM', this.cleanup);
71
+ process.on('uncaughtException', (err) => {
72
+ this.log(`Uncaught exception: ${err.message}`, 'error');
73
+ this.cleanup();
74
+ });
75
+ }
76
+
77
+ log(message, level = 'info') {
78
+ const timestamp = new Date().toISOString();
79
+ const prefix = `[${timestamp}]`;
80
+
81
+ const colors = {
82
+ info: '\x1b[36m',
83
+ success: '\x1b[32m',
84
+ warning: '\x1b[33m',
85
+ error: '\x1b[31m',
86
+ reset: '\x1b[0m',
87
+ };
88
+
89
+ const color = colors[level] || colors.reset;
90
+ console.log(`${color}${prefix} ${message}${colors.reset}`);
91
+ }
92
+
93
+ async captureSystemMetrics() {
94
+ const metrics = {
95
+ timestamp: new Date().toISOString(),
96
+ memory: await this.getMemoryMetrics(),
97
+ fileDescriptors: await this.getFileDescriptorMetrics(),
98
+ tmpfs: await this.getTmpfsMetrics(),
99
+ processes: await this.getProcessMetrics(),
100
+ };
101
+
102
+ return metrics;
103
+ }
104
+
105
+ async getMemoryMetrics() {
106
+ try {
107
+ // Get current process and all child processes
108
+ const { stdout } = await execAsync(`ps -o pid,rss,vsz,comm -p ${process.pid} --ppid ${process.pid} --no-headers`);
109
+ const lines = stdout.trim().split('\n').filter(l => l.trim());
110
+
111
+ let totalRss = 0;
112
+ let totalVsz = 0;
113
+ const processes = [];
114
+
115
+ lines.forEach(line => {
116
+ const parts = line.trim().split(/\s+/);
117
+ if (parts.length >= 4) {
118
+ const pid = parseInt(parts[0], 10);
119
+ const rss = parseInt(parts[1], 10); // KB
120
+ const vsz = parseInt(parts[2], 10); // KB
121
+ const comm = parts.slice(3).join(' ');
122
+
123
+ totalRss += rss;
124
+ totalVsz += vsz;
125
+ processes.push({ pid, rss, vsz, comm });
126
+ }
127
+ });
128
+
129
+ return {
130
+ totalRss: totalRss * 1024, // Convert to bytes
131
+ totalVsz: totalVsz * 1024,
132
+ processCount: processes.length,
133
+ processes: processes.slice(0, 5), // Top 5 for logging
134
+ };
135
+ } catch (error) {
136
+ this.log(`Failed to get memory metrics: ${error.message}`, 'warning');
137
+ return { totalRss: 0, totalVsz: 0, processCount: 0, processes: [] };
138
+ }
139
+ }
140
+
141
+ async getFileDescriptorMetrics() {
142
+ try {
143
+ // Count file descriptors for current process
144
+ const fdPath = `/proc/${process.pid}/fd`;
145
+ const files = await fs.readdir(fdPath);
146
+ const openFds = files.length;
147
+
148
+ // Get system FD limit
149
+ const { stdout: limitsOut } = await execAsync(`cat /proc/${process.pid}/limits | grep 'open files'`);
150
+ const limitMatch = limitsOut.match(/(\d+)\s+(\d+)/);
151
+ const softLimit = limitMatch ? parseInt(limitMatch[1], 10) : 1024;
152
+ const hardLimit = limitMatch ? parseInt(limitMatch[2], 10) : 4096;
153
+
154
+ return {
155
+ open: openFds,
156
+ softLimit,
157
+ hardLimit,
158
+ utilization: (openFds / softLimit) * 100,
159
+ };
160
+ } catch (error) {
161
+ this.log(`Failed to get FD metrics: ${error.message}`, 'warning');
162
+ return { open: 0, softLimit: 1024, hardLimit: 4096, utilization: 0 };
163
+ }
164
+ }
165
+
166
+ async getTmpfsMetrics() {
167
+ try {
168
+ const { stdout } = await execAsync(`df -B1 ${CONFIG.TMPFS_PATH} | tail -1`);
169
+ const parts = stdout.trim().split(/\s+/);
170
+
171
+ if (parts.length >= 6) {
172
+ const total = parseInt(parts[1], 10);
173
+ const used = parseInt(parts[2], 10);
174
+ const available = parseInt(parts[3], 10);
175
+ const utilizationPct = parseFloat(parts[4]);
176
+
177
+ return { total, used, available, utilizationPct };
178
+ }
179
+
180
+ return { total: 0, used: 0, available: 0, utilizationPct: 0 };
181
+ } catch (error) {
182
+ this.log(`Failed to get tmpfs metrics: ${error.message}`, 'warning');
183
+ return { total: 0, used: 0, available: 0, utilizationPct: 0 };
184
+ }
185
+ }
186
+
187
+ async getProcessMetrics() {
188
+ try {
189
+ // Count agent processes (looking for node processes spawned by this script)
190
+ const { stdout } = await execAsync(`pgrep -P ${process.pid} | wc -l`);
191
+ const childProcessCount = parseInt(stdout.trim(), 10);
192
+
193
+ return {
194
+ parentPid: process.pid,
195
+ childProcessCount,
196
+ expectedAgents: this.agents.length,
197
+ agentsCrashed: Math.max(0, this.agents.length - childProcessCount),
198
+ };
199
+ } catch (error) {
200
+ this.log(`Failed to get process metrics: ${error.message}`, 'warning');
201
+ return { parentPid: process.pid, childProcessCount: 0, expectedAgents: 0, agentsCrashed: 0 };
202
+ }
203
+ }
204
+
205
+ async spawnAgent(index) {
206
+ return new Promise((resolve, reject) => {
207
+ // Simple agent process that stays alive and responds to coordination
208
+ const agentScript = `
209
+ const agentId = 'agent-${index}';
210
+ let coordinations = 0;
211
+
212
+ process.on('message', (msg) => {
213
+ if (msg.type === 'coordinate') {
214
+ coordinations++;
215
+ process.send({
216
+ type: 'coordination_response',
217
+ agentId,
218
+ coordinations,
219
+ timestamp: Date.now()
220
+ });
221
+ } else if (msg.type === 'status') {
222
+ process.send({
223
+ type: 'status_response',
224
+ agentId,
225
+ coordinations,
226
+ uptime: process.uptime(),
227
+ memory: process.memoryUsage()
228
+ });
229
+ }
230
+ });
231
+
232
+ // Keep alive
233
+ setInterval(() => {}, 60000);
234
+
235
+ process.send({ type: 'ready', agentId });
236
+ `;
237
+
238
+ const agent = spawn('node', ['-e', agentScript], {
239
+ stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
240
+ detached: false,
241
+ });
242
+
243
+ agent.stdout.on('data', (data) => {
244
+ // Suppress normal output
245
+ });
246
+
247
+ agent.stderr.on('data', (data) => {
248
+ this.log(`Agent ${index} error: ${data.toString().trim()}`, 'warning');
249
+ });
250
+
251
+ agent.on('message', (msg) => {
252
+ if (msg.type === 'ready') {
253
+ resolve({
254
+ id: msg.agentId,
255
+ process: agent,
256
+ pid: agent.pid,
257
+ spawnTime: Date.now(),
258
+ });
259
+ }
260
+ });
261
+
262
+ agent.on('exit', (code, signal) => {
263
+ this.log(`Agent ${index} exited with code ${code}, signal ${signal}`, 'error');
264
+ const agentIndex = this.agents.findIndex(a => a.id === `agent-${index}`);
265
+ if (agentIndex !== -1) {
266
+ this.agents[agentIndex].crashed = true;
267
+ this.agents[agentIndex].exitCode = code;
268
+ this.agents[agentIndex].exitSignal = signal;
269
+ }
270
+ });
271
+
272
+ agent.on('error', (error) => {
273
+ reject(error);
274
+ });
275
+
276
+ // Timeout after 10 seconds
277
+ setTimeout(() => reject(new Error(`Agent ${index} spawn timeout`)), 10000);
278
+ });
279
+ }
280
+
281
+ async spawnAllAgents() {
282
+ this.log(`Spawning ${CONFIG.AGENT_COUNT} agents...`, 'info');
283
+ const startTime = Date.now();
284
+
285
+ const agentPromises = Array.from({ length: CONFIG.AGENT_COUNT }, (_, i) =>
286
+ this.spawnAgent(i).catch(err => {
287
+ this.log(`Failed to spawn agent ${i}: ${err.message}`, 'error');
288
+ return null;
289
+ })
290
+ );
291
+
292
+ const agents = await Promise.all(agentPromises);
293
+ this.agents = agents.filter(a => a !== null);
294
+
295
+ const duration = Date.now() - startTime;
296
+ this.log(`Spawned ${this.agents.length}/${CONFIG.AGENT_COUNT} agents in ${duration}ms`, 'success');
297
+
298
+ if (this.agents.length < CONFIG.AGENT_COUNT) {
299
+ throw new Error(`Failed to spawn all agents: ${this.agents.length}/${CONFIG.AGENT_COUNT}`);
300
+ }
301
+ }
302
+
303
+ async coordinateAgents(cycle) {
304
+ const startTime = Date.now();
305
+ const responses = [];
306
+
307
+ const coordinationPromises = this.agents.map(agent => {
308
+ return new Promise((resolve) => {
309
+ if (agent.crashed) {
310
+ resolve({ agentId: agent.id, error: 'Agent crashed', responded: false });
311
+ return;
312
+ }
313
+
314
+ const timeout = setTimeout(() => {
315
+ resolve({ agentId: agent.id, error: 'Timeout', responded: false });
316
+ }, 5000);
317
+
318
+ const messageHandler = (msg) => {
319
+ if (msg.type === 'coordination_response') {
320
+ clearTimeout(timeout);
321
+ agent.process.off('message', messageHandler);
322
+ resolve({ ...msg, responded: true });
323
+ }
324
+ };
325
+
326
+ agent.process.on('message', messageHandler);
327
+ agent.process.send({ type: 'coordinate', cycle });
328
+ });
329
+ });
330
+
331
+ const results = await Promise.all(coordinationPromises);
332
+ const responded = results.filter(r => r.responded).length;
333
+ const failed = results.filter(r => !r.responded).length;
334
+
335
+ const duration = Date.now() - startTime;
336
+
337
+ return {
338
+ cycle,
339
+ startTime: new Date(startTime).toISOString(),
340
+ durationMs: duration,
341
+ agentsTotal: this.agents.length,
342
+ agentsResponded: responded,
343
+ agentsFailed: failed,
344
+ responses: results,
345
+ };
346
+ }
347
+
348
+ async runCoordinationCycle(cycle) {
349
+ this.log(`Running coordination cycle ${cycle}/${CONFIG.TOTAL_CYCLES}`, 'info');
350
+
351
+ // Capture pre-coordination metrics
352
+ const preMetrics = await this.captureSystemMetrics();
353
+
354
+ // Coordinate agents
355
+ const coordination = await this.coordinateAgents(cycle);
356
+
357
+ // Capture post-coordination metrics
358
+ const postMetrics = await this.captureSystemMetrics();
359
+
360
+ // Calculate deltas
361
+ const memoryDelta = postMetrics.memory.totalRss - preMetrics.memory.totalRss;
362
+ const fdDelta = postMetrics.fileDescriptors.open - preMetrics.fileDescriptors.open;
363
+
364
+ const cycleData = {
365
+ cycle,
366
+ timestamp: new Date().toISOString(),
367
+ preMetrics,
368
+ coordination,
369
+ postMetrics,
370
+ deltas: {
371
+ memory: memoryDelta,
372
+ fileDescriptors: fdDelta,
373
+ },
374
+ };
375
+
376
+ this.cycleMetrics.push(cycleData);
377
+
378
+ // Write to JSONL log
379
+ await this.writeLogEntry(cycleData);
380
+
381
+ // Log summary
382
+ this.log(
383
+ `Cycle ${cycle}: ${coordination.agentsResponded}/${coordination.agentsTotal} agents responded in ${coordination.durationMs}ms ` +
384
+ `(mem: ${memoryDelta > 0 ? '+' : ''}${(memoryDelta / 1024 / 1024).toFixed(2)}MB, fds: ${fdDelta > 0 ? '+' : ''}${fdDelta})`,
385
+ coordination.agentsFailed > 0 ? 'warning' : 'success'
386
+ );
387
+
388
+ return cycleData;
389
+ }
390
+
391
+ async writeLogEntry(data) {
392
+ try {
393
+ const logLine = JSON.stringify(data) + '\n';
394
+ await fs.appendFile(CONFIG.LOG_FILE, logLine, 'utf8');
395
+ } catch (error) {
396
+ this.log(`Failed to write log entry: ${error.message}`, 'warning');
397
+ }
398
+ }
399
+
400
+ async runStabilityTest() {
401
+ this.log('Starting 8-hour stability test for 50-agent swarm', 'info');
402
+ this.log(`Configuration: ${CONFIG.TOTAL_CYCLES} cycles, ${CONFIG.COORDINATION_INTERVAL / 60000} min interval`, 'info');
403
+
404
+ if (isDryRun) {
405
+ this.log('DRY RUN MODE - Test will complete after 3 cycles', 'warning');
406
+ CONFIG.TOTAL_CYCLES = 3;
407
+ CONFIG.COORDINATION_INTERVAL = 10000; // 10 seconds
408
+ }
409
+
410
+ try {
411
+ // Phase 1: Spawn agents
412
+ await this.spawnAllAgents();
413
+
414
+ // Capture baseline metrics
415
+ this.startTime = Date.now();
416
+ this.baselineMetrics = await this.captureSystemMetrics();
417
+ this.log(`Baseline metrics captured: ${(this.baselineMetrics.memory.totalRss / 1024 / 1024).toFixed(2)}MB RSS, ${this.baselineMetrics.fileDescriptors.open} FDs`, 'info');
418
+
419
+ await this.writeLogEntry({
420
+ type: 'baseline',
421
+ timestamp: new Date().toISOString(),
422
+ metrics: this.baselineMetrics,
423
+ config: CONFIG,
424
+ });
425
+
426
+ // Phase 2: Run coordination cycles
427
+ this.isRunning = true;
428
+
429
+ for (let cycle = 1; cycle <= CONFIG.TOTAL_CYCLES && this.isRunning; cycle++) {
430
+ const cycleStartTime = Date.now();
431
+
432
+ await this.runCoordinationCycle(cycle);
433
+
434
+ // Check for critical failures
435
+ const crashed = this.agents.filter(a => a.crashed).length;
436
+ if (crashed > 0) {
437
+ this.log(`CRITICAL: ${crashed} agents have crashed!`, 'error');
438
+ throw new Error(`Test failed: ${crashed} agents crashed`);
439
+ }
440
+
441
+ // Wait for next cycle
442
+ if (cycle < CONFIG.TOTAL_CYCLES) {
443
+ const elapsed = Date.now() - cycleStartTime;
444
+ const waitTime = Math.max(0, CONFIG.COORDINATION_INTERVAL - elapsed);
445
+
446
+ if (waitTime > 0) {
447
+ const nextCycle = new Date(Date.now() + waitTime).toISOString();
448
+ this.log(`Waiting ${(waitTime / 1000).toFixed(0)}s until next cycle (${nextCycle})`, 'info');
449
+ await this.sleep(waitTime);
450
+ }
451
+ }
452
+ }
453
+
454
+ // Phase 3: Generate report
455
+ this.log('All coordination cycles completed, generating report...', 'success');
456
+ const report = await this.generateReport();
457
+
458
+ return report;
459
+
460
+ } catch (error) {
461
+ this.log(`Stability test failed: ${error.message}`, 'error');
462
+ throw error;
463
+ } finally {
464
+ await this.cleanup();
465
+ }
466
+ }
467
+
468
+ async generateReport() {
469
+ const endTime = Date.now();
470
+ const totalDuration = endTime - this.startTime;
471
+
472
+ // Calculate memory growth
473
+ const finalMetrics = this.cycleMetrics[this.cycleMetrics.length - 1]?.postMetrics;
474
+ const memoryGrowth = finalMetrics
475
+ ? (finalMetrics.memory.totalRss - this.baselineMetrics.memory.totalRss) / this.baselineMetrics.memory.totalRss
476
+ : 0;
477
+
478
+ // Calculate FD stability
479
+ const fdValues = this.cycleMetrics.map(c => c.postMetrics.fileDescriptors.open);
480
+ const fdMean = fdValues.reduce((sum, v) => sum + v, 0) / fdValues.length;
481
+ const fdStdDev = Math.sqrt(fdValues.reduce((sum, v) => sum + Math.pow(v - fdMean, 2), 0) / fdValues.length);
482
+ const fdVariance = fdMean > 0 ? fdStdDev / fdMean : 0;
483
+
484
+ // Calculate coordination time variance
485
+ const coordTimes = this.cycleMetrics.map(c => c.coordination.durationMs);
486
+ const coordMean = coordTimes.reduce((sum, t) => sum + t, 0) / coordTimes.length;
487
+ const coordStdDev = Math.sqrt(coordTimes.reduce((sum, t) => sum + Math.pow(t - coordMean, 2), 0) / coordTimes.length);
488
+ const coordVariance = coordMean > 0 ? coordStdDev / coordMean : 0;
489
+
490
+ // Count crashes
491
+ const totalCrashes = this.agents.filter(a => a.crashed).length;
492
+
493
+ // Success criteria evaluation
494
+ const memoryPass = memoryGrowth < CONFIG.MEMORY_GROWTH_THRESHOLD;
495
+ const fdPass = fdVariance < CONFIG.FD_VARIANCE_THRESHOLD;
496
+ const coordPass = coordVariance < CONFIG.COORDINATION_VARIANCE_THRESHOLD;
497
+ const crashPass = totalCrashes === 0;
498
+ const overallPass = memoryPass && fdPass && coordPass && crashPass;
499
+
500
+ const report = {
501
+ testConfig: CONFIG,
502
+ execution: {
503
+ startTime: new Date(this.startTime).toISOString(),
504
+ endTime: new Date(endTime).toISOString(),
505
+ totalDurationMs: totalDuration,
506
+ totalDurationHours: (totalDuration / 1000 / 3600).toFixed(2),
507
+ cyclesCompleted: this.cycleMetrics.length,
508
+ agentsSpawned: CONFIG.AGENT_COUNT,
509
+ },
510
+ metrics: {
511
+ memory: {
512
+ baseline: this.baselineMetrics.memory.totalRss,
513
+ final: finalMetrics?.memory.totalRss || 0,
514
+ growth: memoryGrowth,
515
+ growthPct: (memoryGrowth * 100).toFixed(2),
516
+ threshold: CONFIG.MEMORY_GROWTH_THRESHOLD,
517
+ pass: memoryPass,
518
+ },
519
+ fileDescriptors: {
520
+ baseline: this.baselineMetrics.fileDescriptors.open,
521
+ mean: fdMean.toFixed(2),
522
+ stdDev: fdStdDev.toFixed(2),
523
+ variance: coordVariance.toFixed(4),
524
+ threshold: CONFIG.FD_VARIANCE_THRESHOLD,
525
+ pass: fdPass,
526
+ },
527
+ coordination: {
528
+ mean: coordMean.toFixed(2),
529
+ min: Math.min(...coordTimes),
530
+ max: Math.max(...coordTimes),
531
+ stdDev: coordStdDev.toFixed(2),
532
+ variance: coordVariance.toFixed(4),
533
+ threshold: CONFIG.COORDINATION_VARIANCE_THRESHOLD,
534
+ pass: coordPass,
535
+ },
536
+ crashes: {
537
+ total: totalCrashes,
538
+ threshold: 0,
539
+ pass: crashPass,
540
+ },
541
+ },
542
+ success: overallPass,
543
+ recommendations: this.generateRecommendations(memoryGrowth, fdVariance, coordVariance, totalCrashes),
544
+ timestamp: new Date().toISOString(),
545
+ };
546
+
547
+ // Write report to file
548
+ const reportFile = `stability-test-report-${Date.now()}.json`;
549
+ await fs.writeFile(reportFile, JSON.stringify(report, null, 2), 'utf8');
550
+
551
+ // Print report to console
552
+ this.printReport(report);
553
+
554
+ return report;
555
+ }
556
+
557
+ generateRecommendations(memoryGrowth, fdVariance, coordVariance, crashes) {
558
+ const recommendations = [];
559
+
560
+ if (!memoryGrowth || memoryGrowth >= CONFIG.MEMORY_GROWTH_THRESHOLD) {
561
+ recommendations.push({
562
+ severity: 'high',
563
+ category: 'memory',
564
+ message: `Memory growth ${(memoryGrowth * 100).toFixed(2)}% exceeds ${(CONFIG.MEMORY_GROWTH_THRESHOLD * 100)}% threshold`,
565
+ actions: [
566
+ 'Investigate memory leaks in agent processes',
567
+ 'Review coordination message handling for retained references',
568
+ 'Consider implementing periodic agent restart strategy',
569
+ ],
570
+ });
571
+ }
572
+
573
+ if (fdVariance >= CONFIG.FD_VARIANCE_THRESHOLD) {
574
+ recommendations.push({
575
+ severity: 'medium',
576
+ category: 'file-descriptors',
577
+ message: `FD variance ${(fdVariance * 100).toFixed(2)}% exceeds ${(CONFIG.FD_VARIANCE_THRESHOLD * 100)}% threshold`,
578
+ actions: [
579
+ 'Review file descriptor cleanup in coordination cycles',
580
+ 'Check for unclosed file handles or sockets',
581
+ 'Implement FD monitoring and cleanup strategy',
582
+ ],
583
+ });
584
+ }
585
+
586
+ if (coordVariance >= CONFIG.COORDINATION_VARIANCE_THRESHOLD) {
587
+ recommendations.push({
588
+ severity: 'medium',
589
+ category: 'coordination',
590
+ message: `Coordination time variance ${(coordVariance * 100).toFixed(2)}% exceeds ${(CONFIG.COORDINATION_VARIANCE_THRESHOLD * 100)}% threshold`,
591
+ actions: [
592
+ 'Investigate coordination bottlenecks',
593
+ 'Consider optimizing message passing strategy',
594
+ 'Review agent response timeout handling',
595
+ ],
596
+ });
597
+ }
598
+
599
+ if (crashes > 0) {
600
+ recommendations.push({
601
+ severity: 'critical',
602
+ category: 'crashes',
603
+ message: `${crashes} agents crashed during test`,
604
+ actions: [
605
+ 'Review agent crash logs for error patterns',
606
+ 'Implement better error handling in agent processes',
607
+ 'Consider agent health monitoring and automatic recovery',
608
+ ],
609
+ });
610
+ }
611
+
612
+ if (recommendations.length === 0) {
613
+ recommendations.push({
614
+ severity: 'info',
615
+ category: 'success',
616
+ message: 'All stability criteria passed',
617
+ actions: [
618
+ 'System is stable for 50-agent swarm operations',
619
+ 'Consider testing with larger agent counts',
620
+ 'Monitor production deployments for similar patterns',
621
+ ],
622
+ });
623
+ }
624
+
625
+ return recommendations;
626
+ }
627
+
628
+ printReport(report) {
629
+ console.log('\n' + '='.repeat(80));
630
+ console.log(' 8-HOUR STABILITY TEST REPORT - 50-AGENT SWARM');
631
+ console.log('='.repeat(80));
632
+
633
+ console.log('\nExecution Summary:');
634
+ console.log(` Start Time: ${report.execution.startTime}`);
635
+ console.log(` End Time: ${report.execution.endTime}`);
636
+ console.log(` Duration: ${report.execution.totalDurationHours} hours`);
637
+ console.log(` Cycles Completed: ${report.execution.cyclesCompleted}/${CONFIG.TOTAL_CYCLES}`);
638
+ console.log(` Agents Spawned: ${report.execution.agentsSpawned}`);
639
+
640
+ console.log('\nMetrics:');
641
+ console.log(` Memory Growth: ${report.metrics.memory.growthPct}% (threshold: ${(CONFIG.MEMORY_GROWTH_THRESHOLD * 100)}%) [${report.metrics.memory.pass ? 'PASS' : 'FAIL'}]`);
642
+ console.log(` FD Variance: ${(report.metrics.fileDescriptors.variance * 100).toFixed(2)}% (threshold: ${(CONFIG.FD_VARIANCE_THRESHOLD * 100)}%) [${report.metrics.fileDescriptors.pass ? 'PASS' : 'FAIL'}]`);
643
+ console.log(` Coordination Variance: ${(report.metrics.coordination.variance * 100).toFixed(2)}% (threshold: ${(CONFIG.COORDINATION_VARIANCE_THRESHOLD * 100)}%) [${report.metrics.coordination.pass ? 'PASS' : 'FAIL'}]`);
644
+ console.log(` Crashes: ${report.metrics.crashes.total} (threshold: ${report.metrics.crashes.threshold}) [${report.metrics.crashes.pass ? 'PASS' : 'FAIL'}]`);
645
+
646
+ console.log('\nCoordination Performance:');
647
+ console.log(` Mean: ${report.metrics.coordination.mean}ms`);
648
+ console.log(` Min: ${report.metrics.coordination.min}ms`);
649
+ console.log(` Max: ${report.metrics.coordination.max}ms`);
650
+ console.log(` Std Dev: ${report.metrics.coordination.stdDev}ms`);
651
+
652
+ console.log(`\nOverall Result: ${report.success ? '\x1b[32mPASS\x1b[0m' : '\x1b[31mFAIL\x1b[0m'}`);
653
+
654
+ if (report.recommendations.length > 0) {
655
+ console.log('\nRecommendations:');
656
+ report.recommendations.forEach((rec, i) => {
657
+ const severityColor = rec.severity === 'critical' ? '\x1b[31m' : rec.severity === 'high' ? '\x1b[33m' : '\x1b[36m';
658
+ console.log(`\n ${i + 1}. [${severityColor}${rec.severity.toUpperCase()}\x1b[0m] ${rec.category}`);
659
+ console.log(` ${rec.message}`);
660
+ rec.actions.forEach(action => {
661
+ console.log(` - ${action}`);
662
+ });
663
+ });
664
+ }
665
+
666
+ console.log('\n' + '='.repeat(80));
667
+ console.log(`\nDetailed logs written to: ${CONFIG.LOG_FILE}`);
668
+ console.log(`Full report written to: stability-test-report-${Date.now()}.json`);
669
+ console.log('');
670
+ }
671
+
672
+ async cleanup() {
673
+ if (!this.isRunning && this.agents.length === 0) {
674
+ return;
675
+ }
676
+
677
+ this.log('Cleaning up resources...', 'info');
678
+ this.isRunning = false;
679
+
680
+ if (this.healthCheckInterval) {
681
+ clearInterval(this.healthCheckInterval);
682
+ }
683
+
684
+ // Kill all agent processes
685
+ for (const agent of this.agents) {
686
+ if (agent.process && !agent.crashed) {
687
+ try {
688
+ agent.process.kill('SIGTERM');
689
+ await this.sleep(100);
690
+ if (!agent.process.killed) {
691
+ agent.process.kill('SIGKILL');
692
+ }
693
+ } catch (error) {
694
+ // Process may already be dead
695
+ }
696
+ }
697
+ }
698
+
699
+ // Wait for cleanup
700
+ await this.sleep(1000);
701
+
702
+ this.log('Cleanup completed', 'success');
703
+
704
+ // Don't exit if we're generating a report
705
+ if (this.cycleMetrics.length > 0) {
706
+ // Report will be generated by caller
707
+ } else {
708
+ process.exit(0);
709
+ }
710
+ }
711
+
712
+ sleep(ms) {
713
+ return new Promise(resolve => setTimeout(resolve, ms));
714
+ }
715
+ }
716
+
717
+ // Main execution
718
+ async function main() {
719
+ const runner = new StabilityTestRunner();
720
+
721
+ try {
722
+ const report = await runner.runStabilityTest();
723
+ process.exit(report.success ? 0 : 1);
724
+ } catch (error) {
725
+ console.error(`\x1b[31mTest failed: ${error.message}\x1b[0m`);
726
+ process.exit(1);
727
+ }
728
+ }
729
+
730
+ if (import.meta.url === `file://${process.argv[1]}`) {
731
+ main();
732
+ }
733
+
734
+ export { StabilityTestRunner, CONFIG };