rigscope 0.1.0 → 0.1.2

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 (124) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +2 -2
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  5. package/.next/server/app/_global-error.html +1 -1
  6. package/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  10. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  11. package/.next/server/app/_not-found.html +1 -1
  12. package/.next/server/app/_not-found.rsc +2 -2
  13. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  14. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  15. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  16. package/.next/server/app/administration/page_client-reference-manifest.js +1 -1
  17. package/.next/server/app/administration.html +1 -1
  18. package/.next/server/app/administration.rsc +2 -2
  19. package/.next/server/app/administration.segments/_full.segment.rsc +2 -2
  20. package/.next/server/app/administration.segments/_tree.segment.rsc +2 -2
  21. package/.next/server/app/administration.segments/administration/__PAGE__.segment.rsc +2 -2
  22. package/.next/server/app/alerts/page_client-reference-manifest.js +1 -1
  23. package/.next/server/app/alerts.html +1 -1
  24. package/.next/server/app/alerts.rsc +2 -2
  25. package/.next/server/app/alerts.segments/_full.segment.rsc +2 -2
  26. package/.next/server/app/alerts.segments/_tree.segment.rsc +2 -2
  27. package/.next/server/app/alerts.segments/alerts/__PAGE__.segment.rsc +2 -2
  28. package/.next/server/app/connections/page_client-reference-manifest.js +1 -1
  29. package/.next/server/app/connections.html +1 -1
  30. package/.next/server/app/connections.rsc +2 -2
  31. package/.next/server/app/connections.segments/_full.segment.rsc +2 -2
  32. package/.next/server/app/connections.segments/_tree.segment.rsc +2 -2
  33. package/.next/server/app/connections.segments/connections/__PAGE__.segment.rsc +2 -2
  34. package/.next/server/app/history/page.js +2 -2
  35. package/.next/server/app/history/page_client-reference-manifest.js +1 -1
  36. package/.next/server/app/history.html +1 -1
  37. package/.next/server/app/history.rsc +5 -5
  38. package/.next/server/app/history.segments/_full.segment.rsc +5 -5
  39. package/.next/server/app/history.segments/_tree.segment.rsc +2 -2
  40. package/.next/server/app/history.segments/history/__PAGE__.segment.rsc +5 -5
  41. package/.next/server/app/index.html +1 -1
  42. package/.next/server/app/index.rsc +2 -2
  43. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  44. package/.next/server/app/index.segments/_full.segment.rsc +2 -2
  45. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  46. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  47. package/.next/server/app/login.html +1 -1
  48. package/.next/server/app/login.rsc +2 -2
  49. package/.next/server/app/login.segments/_full.segment.rsc +2 -2
  50. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  51. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  52. package/.next/server/app/machines/[machineId]/page.js +1 -1
  53. package/.next/server/app/machines/[machineId]/page_client-reference-manifest.js +1 -1
  54. package/.next/server/app/page_client-reference-manifest.js +1 -1
  55. package/.next/server/app/processes/page_client-reference-manifest.js +1 -1
  56. package/.next/server/app/processes.html +1 -1
  57. package/.next/server/app/processes.rsc +2 -2
  58. package/.next/server/app/processes.segments/_full.segment.rsc +2 -2
  59. package/.next/server/app/processes.segments/_tree.segment.rsc +2 -2
  60. package/.next/server/app/processes.segments/processes/__PAGE__.segment.rsc +2 -2
  61. package/.next/server/app-paths-manifest.json +2 -2
  62. package/.next/server/chunks/168.js +1 -1
  63. package/.next/server/middleware-build-manifest.js +1 -1
  64. package/.next/server/pages/404.html +1 -1
  65. package/.next/server/pages/500.html +1 -1
  66. package/.next/static/chunks/408-4fe7147e38981ee1.js +1 -0
  67. package/.next/static/chunks/app/history/page-22be927a4c3a9c76.js +3 -0
  68. package/.next/static/chunks/app/machines/[machineId]/page-916ee73de5eb067d.js +1 -0
  69. package/.next/static/css/3fbf75e4c471c6a8.css +1 -0
  70. package/CHANGELOG.md +27 -0
  71. package/README.md +53 -136
  72. package/dist/collector.cjs +9 -1
  73. package/dist/hub.cjs +14 -5
  74. package/dist/ops.cjs +8 -4
  75. package/docs/bottlenecks.md +1 -1
  76. package/docs/configuration.md +85 -0
  77. package/docs/development.md +1 -1
  78. package/docs/installation.md +205 -376
  79. package/docs/monitoring.md +112 -0
  80. package/docs/operations.md +103 -68
  81. package/docs/releasing.md +16 -14
  82. package/docs/scale-validation.md +34 -3
  83. package/docs/stress-2026-11-04/180301-probe-m100-u1-s1-20000ms.json +412 -0
  84. package/docs/stress-2026-11-04/180335-probe-m200-u1-s1-20000ms.json +412 -0
  85. package/docs/stress-2026-11-04/180409-probe-m400-u1-s1-20000ms.json +412 -0
  86. package/docs/stress-2026-11-04/180443-probe-m800-u1-s1-20000ms.json +412 -0
  87. package/docs/stress-2026-11-04/180518-probe-m600-u1-s1-20000ms.json +412 -0
  88. package/docs/stress-2026-11-04/180553-probe-m500-u1-s1-20000ms.json +412 -0
  89. package/docs/stress-2026-11-04/180628-probe-m550-u1-s1-20000ms.json +412 -0
  90. package/docs/stress-2026-11-04/180716-probe-m800-u1-s0-20000ms.json +415 -0
  91. package/docs/stress-2026-11-04/180751-probe-m1600-u1-s0-20000ms.json +415 -0
  92. package/docs/stress-2026-11-04/180828-probe-m3200-u1-s0-20000ms.json +416 -0
  93. package/docs/stress-2026-11-04/180941-probe-m2400-u1-s0-20000ms.json +416 -0
  94. package/docs/stress-2026-11-04/181031-probe-m2000-u1-s0-20000ms.json +416 -0
  95. package/docs/stress-2026-11-04/181114-probe-m1800-u1-s0-20000ms.json +416 -0
  96. package/docs/stress-2026-11-04/181203-probe-m100-u64-s64-20000ms.json +418 -0
  97. package/docs/stress-2026-11-04/181304-probe-m200-u64-s64-20000ms.json +418 -0
  98. package/docs/stress-2026-11-04/181405-probe-m400-u64-s64-20000ms.json +418 -0
  99. package/docs/stress-2026-11-04/181507-probe-m500-u64-s64-20000ms.json +418 -0
  100. package/docs/stress-2026-11-04/181609-probe-m450-u64-s64-20000ms.json +418 -0
  101. package/docs/stress-2026-11-04/181845-probe-m2-u2-s2-3000ms.json +419 -0
  102. package/docs/stress-2026-11-04/181931-probe-m500-u64-s64-30000ms.json +420 -0
  103. package/docs/stress-2026-11-04/182108-probe-m1800-u1-s0-120000ms.json +418 -0
  104. package/docs/stress-2026-11-04/182354-probe-m1200-u1-s0-120000ms.json +418 -0
  105. package/docs/stress-2026-11-04/182625-probe-m900-u1-s0-120000ms.json +418 -0
  106. package/docs/stress-2026-11-04/182847-probe-m1050-u1-s0-120000ms.json +418 -0
  107. package/docs/stress-2026-11-04/183112-probe-m1125-u1-s0-120000ms.json +418 -0
  108. package/docs/stress-2026-11-04/193608-probe-m500-u64-s64-120000ms.json +420 -0
  109. package/docs/stress-2026-11-04/193909-probe-m529-u1-s1-15000ms.json +420 -0
  110. package/docs/stress-2026-11-04/193940-probe-m530-u1-s1-15000ms.json +420 -0
  111. package/docs/stress-2026-11-04/194011-probe-m100-u1-s65-10000ms.json +421 -0
  112. package/docs/stress-2026-11-04/README.md +205 -0
  113. package/docs/stress-2026-11-04/index.jsonl +29 -0
  114. package/docs/stress-2026-11-04/manifest.json +13 -0
  115. package/docs/stress-2026-11-04/results.html +22 -0
  116. package/docs/system-installation.md +195 -0
  117. package/package.json +9 -1
  118. package/packaging/system/README.md +1 -1
  119. package/.next/static/chunks/408-18819c6490a5f8d3.js +0 -1
  120. package/.next/static/chunks/app/history/page-3fa5846eca26b7f7.js +0 -3
  121. package/.next/static/chunks/app/machines/[machineId]/page-a5aa1d8676272f38.js +0 -1
  122. package/.next/static/css/e41ccbccc3afaae5.css +0 -1
  123. /package/.next/static/{DZKWF9ur7H5wI0c7RAhdq → npHoP6NSY976Yaye-xi86}/_buildManifest.js +0 -0
  124. /package/.next/static/{DZKWF9ur7H5wI0c7RAhdq → npHoP6NSY976Yaye-xi86}/_ssgManifest.js +0 -0
@@ -0,0 +1,29 @@
1
+ {"pass": true, "reasons": [], "machines": 100, "users": 1, "sseClients": 1, "durationMs": 20000, "committedPerSecond": 100.0, "sampleCadenceRatio": 0.9998, "historyCadenceRatio": 0.9998, "ackP95Ms": 61.13, "historyP95Ms": 11.29, "eventLoopP99Ms": 34.28, "sseNewestSampleP95Ms": 405, "hubCpuPercentOneCore": 12.69, "hubRssPeakMiB": 131.3, "sseMegabytes": 4.5, "report": "docs/stress-2026-11-04/180301-probe-m100-u1-s1-20000ms.json", "resources": "docs/stress-2026-11-04/180301-probe-m100-u1-s1-20000ms.resources.json", "wallSeconds": 34.1, "minimumAvailableMemoryGiB": 109.4, "peakHostCpuPercent": 6.15, "peakTestRssMiB": 274.1, "swapOutDeltaBytes": 0}
2
+ {"pass": true, "reasons": [], "machines": 200, "users": 1, "sseClients": 1, "durationMs": 20000, "committedPerSecond": 199.9, "sampleCadenceRatio": 0.9997, "historyCadenceRatio": 0.9997, "ackP95Ms": 63.33, "historyP95Ms": 13.55, "eventLoopP99Ms": 44.73, "sseNewestSampleP95Ms": 266, "hubCpuPercentOneCore": 20.42, "hubRssPeakMiB": 153.5, "sseMegabytes": 9.1, "report": "docs/stress-2026-11-04/180335-probe-m200-u1-s1-20000ms.json", "resources": "docs/stress-2026-11-04/180335-probe-m200-u1-s1-20000ms.resources.json", "wallSeconds": 34.1, "minimumAvailableMemoryGiB": 109.8, "peakHostCpuPercent": 3.94, "peakTestRssMiB": 272.3, "swapOutDeltaBytes": 0}
3
+ {"pass": true, "reasons": [], "machines": 400, "users": 1, "sseClients": 1, "durationMs": 20000, "committedPerSecond": 399.1, "sampleCadenceRatio": 0.9978, "historyCadenceRatio": 1.0498, "ackP95Ms": 56.62, "historyP95Ms": 30.29, "eventLoopP99Ms": 45.38, "sseNewestSampleP95Ms": 79, "hubCpuPercentOneCore": 34.98, "hubRssPeakMiB": 192.4, "sseMegabytes": 18.2, "report": "docs/stress-2026-11-04/180409-probe-m400-u1-s1-20000ms.json", "resources": "docs/stress-2026-11-04/180409-probe-m400-u1-s1-20000ms.resources.json", "wallSeconds": 34.1, "minimumAvailableMemoryGiB": 109.7, "peakHostCpuPercent": 4.98, "peakTestRssMiB": 366.0, "swapOutDeltaBytes": 0}
4
+ {"pass": false, "reasons": ["SSE admission/delivery incomplete (0/1)"], "machines": 800, "users": 1, "sseClients": 1, "durationMs": 20000, "committedPerSecond": 799.8, "sampleCadenceRatio": 0.9998, "historyCadenceRatio": 1.0498, "ackP95Ms": 53.04, "historyP95Ms": 5.26, "eventLoopP99Ms": 48.37, "sseNewestSampleP95Ms": 133, "hubCpuPercentOneCore": 60.76, "hubRssPeakMiB": 237.6, "sseMegabytes": 1.6, "report": "docs/stress-2026-11-04/180443-probe-m800-u1-s1-20000ms.json", "resources": "docs/stress-2026-11-04/180443-probe-m800-u1-s1-20000ms.resources.json", "wallSeconds": 35.1, "minimumAvailableMemoryGiB": 109.5, "peakHostCpuPercent": 4.76, "peakTestRssMiB": 382.2, "swapOutDeltaBytes": 0}
5
+ {"pass": false, "reasons": ["SSE admission/delivery incomplete (0/1)"], "machines": 600, "users": 1, "sseClients": 1, "durationMs": 20000, "committedPerSecond": 599.8, "sampleCadenceRatio": 0.9996, "historyCadenceRatio": 1.0498, "ackP95Ms": 54.43, "historyP95Ms": 14.49, "eventLoopP99Ms": 46.2, "sseNewestSampleP95Ms": 71, "hubCpuPercentOneCore": 49.28, "hubRssPeakMiB": 214.1, "sseMegabytes": 1.2, "report": "docs/stress-2026-11-04/180518-probe-m600-u1-s1-20000ms.json", "resources": "docs/stress-2026-11-04/180518-probe-m600-u1-s1-20000ms.resources.json", "wallSeconds": 35.1, "minimumAvailableMemoryGiB": 109.6, "peakHostCpuPercent": 4.08, "peakTestRssMiB": 351.9, "swapOutDeltaBytes": 0}
6
+ {"pass": true, "reasons": [], "machines": 500, "users": 1, "sseClients": 1, "durationMs": 20000, "committedPerSecond": 499.9, "sampleCadenceRatio": 0.9997, "historyCadenceRatio": 1.0497, "ackP95Ms": 55.22, "historyP95Ms": 22.71, "eventLoopP99Ms": 56.03, "sseNewestSampleP95Ms": 149, "hubCpuPercentOneCore": 43.76, "hubRssPeakMiB": 212.6, "sseMegabytes": 37.6, "report": "docs/stress-2026-11-04/180553-probe-m500-u1-s1-20000ms.json", "resources": "docs/stress-2026-11-04/180553-probe-m500-u1-s1-20000ms.resources.json", "wallSeconds": 35.1, "minimumAvailableMemoryGiB": 109.6, "peakHostCpuPercent": 4.1, "peakTestRssMiB": 384.7, "swapOutDeltaBytes": 0}
7
+ {"pass": false, "reasons": ["SSE admission/delivery incomplete (0/1)"], "machines": 550, "users": 1, "sseClients": 1, "durationMs": 20000, "committedPerSecond": 549.8, "sampleCadenceRatio": 0.9997, "historyCadenceRatio": 1.0498, "ackP95Ms": 57.6, "historyP95Ms": 6.43, "eventLoopP99Ms": 50.23, "sseNewestSampleP95Ms": 69, "hubCpuPercentOneCore": 46.03, "hubRssPeakMiB": 184.0, "sseMegabytes": 1.1, "report": "docs/stress-2026-11-04/180628-probe-m550-u1-s1-20000ms.json", "resources": "docs/stress-2026-11-04/180628-probe-m550-u1-s1-20000ms.resources.json", "wallSeconds": 35.1, "minimumAvailableMemoryGiB": 109.7, "peakHostCpuPercent": 4.14, "peakTestRssMiB": 322.7, "swapOutDeltaBytes": 0}
8
+ {"pass": true, "reasons": [], "machines": 800, "users": 1, "sseClients": 0, "durationMs": 20000, "committedPerSecond": 799.9, "sampleCadenceRatio": 0.9999, "historyCadenceRatio": 1.0499, "ackP95Ms": 53.46, "historyP95Ms": 10.13, "eventLoopP99Ms": 46.33, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 61.88, "hubRssPeakMiB": 217.0, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/180716-probe-m800-u1-s0-20000ms.json", "resources": "docs/stress-2026-11-04/180716-probe-m800-u1-s0-20000ms.resources.json", "wallSeconds": 35.1, "minimumAvailableMemoryGiB": 109.6, "peakHostCpuPercent": 4.45, "peakTestRssMiB": 383.4, "swapOutDeltaBytes": 0}
9
+ {"pass": true, "reasons": [], "machines": 1600, "users": 1, "sseClients": 0, "durationMs": 20000, "committedPerSecond": 1605.4, "sampleCadenceRatio": 1.0034, "historyCadenceRatio": 1.0499, "ackP95Ms": 59.54, "historyP95Ms": 19.92, "eventLoopP99Ms": 40.99, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 95.33, "hubRssPeakMiB": 279.9, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/180751-probe-m1600-u1-s0-20000ms.json", "resources": "docs/stress-2026-11-04/180751-probe-m1600-u1-s0-20000ms.resources.json", "wallSeconds": 37.1, "minimumAvailableMemoryGiB": 109.5, "peakHostCpuPercent": 4.41, "peakTestRssMiB": 445.5, "swapOutDeltaBytes": 0}
10
+ {"pass": false, "reasons": ["ack p95 3464.84 > 500 ms", "durable sample cadence 37.1% < 95%", "collector rejection, retry, loss, backpressure or send error", "storage queue, write failure or physical pressure"], "machines": 3200, "users": 1, "sseClients": 0, "durationMs": 20000, "committedPerSecond": 1188.7, "sampleCadenceRatio": 0.3715, "historyCadenceRatio": 1.0499, "ackP95Ms": 3464.84, "historyP95Ms": 33.87, "eventLoopP99Ms": 37.98, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 110.71, "hubRssPeakMiB": 401.6, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/180828-probe-m3200-u1-s0-20000ms.json", "resources": "docs/stress-2026-11-04/180828-probe-m3200-u1-s0-20000ms.resources.json", "wallSeconds": 72.3, "minimumAvailableMemoryGiB": 109.2, "peakHostCpuPercent": 5.59, "peakTestRssMiB": 653.5, "swapOutDeltaBytes": 0}
11
+ {"pass": false, "reasons": ["ack p95 2897.57 > 500 ms", "durable sample cadence 61.6% < 95%", "collector rejection, retry, loss, backpressure or send error", "storage queue, write failure or physical pressure"], "machines": 2400, "users": 1, "sseClients": 0, "durationMs": 20000, "committedPerSecond": 1478.3, "sampleCadenceRatio": 0.616, "historyCadenceRatio": 1.0499, "ackP95Ms": 2897.57, "historyP95Ms": 27.21, "eventLoopP99Ms": 31.46, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 110.85, "hubRssPeakMiB": 339.8, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/180941-probe-m2400-u1-s0-20000ms.json", "resources": "docs/stress-2026-11-04/180941-probe-m2400-u1-s0-20000ms.resources.json", "wallSeconds": 50.6, "minimumAvailableMemoryGiB": 109.3, "peakHostCpuPercent": 4.9, "peakTestRssMiB": 543.2, "swapOutDeltaBytes": 0}
12
+ {"pass": false, "reasons": ["ack p95 2524.02 > 500 ms", "durable sample cadence 87.4% < 95%", "collector rejection, retry, loss, backpressure or send error", "storage queue, write failure or physical pressure"], "machines": 2000, "users": 1, "sseClients": 0, "durationMs": 20000, "committedPerSecond": 1747.1, "sampleCadenceRatio": 0.8736, "historyCadenceRatio": 1.05, "ackP95Ms": 2524.02, "historyP95Ms": 20.9, "eventLoopP99Ms": 24.85, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 111.43, "hubRssPeakMiB": 328.9, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/181031-probe-m2000-u1-s0-20000ms.json", "resources": "docs/stress-2026-11-04/181031-probe-m2000-u1-s0-20000ms.resources.json", "wallSeconds": 42.3, "minimumAvailableMemoryGiB": 109.4, "peakHostCpuPercent": 5.37, "peakTestRssMiB": 548.2, "swapOutDeltaBytes": 0}
13
+ {"pass": true, "reasons": [], "machines": 1800, "users": 1, "sseClients": 0, "durationMs": 20000, "committedPerSecond": 1802.1, "sampleCadenceRatio": 1.0012, "historyCadenceRatio": 1.0499, "ackP95Ms": 88.45, "historyP95Ms": 23.84, "eventLoopP99Ms": 31.03, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 103.43, "hubRssPeakMiB": 291.2, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/181114-probe-m1800-u1-s0-20000ms.json", "resources": "docs/stress-2026-11-04/181114-probe-m1800-u1-s0-20000ms.resources.json", "wallSeconds": 38.2, "minimumAvailableMemoryGiB": 109.4, "peakHostCpuPercent": 4.04, "peakTestRssMiB": 469.2, "swapOutDeltaBytes": 0}
14
+ {"pass": true, "reasons": [], "machines": 100, "users": 64, "sseClients": 64, "durationMs": 20000, "committedPerSecond": 99.8, "sampleCadenceRatio": 0.998, "historyCadenceRatio": 1.0472, "ackP95Ms": 60.85, "historyP95Ms": 78.43, "eventLoopP99Ms": 44.89, "sseNewestSampleP95Ms": 544, "hubCpuPercentOneCore": 23.82, "hubRssPeakMiB": 288.0, "sseMegabytes": 290.5, "report": "docs/stress-2026-11-04/181203-probe-m100-u64-s64-20000ms.json", "resources": "docs/stress-2026-11-04/181203-probe-m100-u64-s64-20000ms.resources.json", "wallSeconds": 60.9, "minimumAvailableMemoryGiB": 109.4, "peakHostCpuPercent": 3.36, "peakTestRssMiB": 525.8, "swapOutDeltaBytes": 0}
15
+ {"pass": true, "reasons": [], "machines": 200, "users": 64, "sseClients": 64, "durationMs": 20000, "committedPerSecond": 199.6, "sampleCadenceRatio": 0.9982, "historyCadenceRatio": 1.0091, "ackP95Ms": 69.06, "historyP95Ms": 211.65, "eventLoopP99Ms": 61.31, "sseNewestSampleP95Ms": 764, "hubCpuPercentOneCore": 33.47, "hubRssPeakMiB": 298.1, "sseMegabytes": 582.1, "report": "docs/stress-2026-11-04/181304-probe-m200-u64-s64-20000ms.json", "resources": "docs/stress-2026-11-04/181304-probe-m200-u64-s64-20000ms.resources.json", "wallSeconds": 61.0, "minimumAvailableMemoryGiB": 109.4, "peakHostCpuPercent": 3.31, "peakTestRssMiB": 588.6, "swapOutDeltaBytes": 0}
16
+ {"pass": true, "reasons": [], "machines": 400, "users": 64, "sseClients": 64, "durationMs": 20000, "committedPerSecond": 381.0, "sampleCadenceRatio": 0.9526, "historyCadenceRatio": 0.9425, "ackP95Ms": 407.39, "historyP95Ms": 493.21, "eventLoopP99Ms": 96.4, "sseNewestSampleP95Ms": 963, "hubCpuPercentOneCore": 48.46, "hubRssPeakMiB": 363.2, "sseMegabytes": 1266.4, "report": "docs/stress-2026-11-04/181405-probe-m400-u64-s64-20000ms.json", "resources": "docs/stress-2026-11-04/181405-probe-m400-u64-s64-20000ms.resources.json", "wallSeconds": 62.0, "minimumAvailableMemoryGiB": 109.2, "peakHostCpuPercent": 4.64, "peakTestRssMiB": 840.1, "swapOutDeltaBytes": 0}
17
+ {"pass": false, "reasons": ["ack p95 533.47 > 500 ms", "durable sample cadence 88.7% < 95%", "History cadence 89.9% < 90%"], "machines": 500, "users": 64, "sseClients": 64, "durationMs": 20000, "committedPerSecond": 443.6, "sampleCadenceRatio": 0.8872, "historyCadenceRatio": 0.8987, "ackP95Ms": 533.47, "historyP95Ms": 585.44, "eventLoopP99Ms": 94.24, "sseNewestSampleP95Ms": 1174, "hubCpuPercentOneCore": 49.77, "hubRssPeakMiB": 452.7, "sseMegabytes": 1393.3, "report": "docs/stress-2026-11-04/181507-probe-m500-u64-s64-20000ms.json", "resources": "docs/stress-2026-11-04/181507-probe-m500-u64-s64-20000ms.resources.json", "wallSeconds": 62.0, "minimumAvailableMemoryGiB": 108.8, "peakHostCpuPercent": 4.8, "peakTestRssMiB": 966.3, "swapOutDeltaBytes": 0}
18
+ {"pass": false, "reasons": ["ack p95 560.42 > 500 ms", "durable sample cadence 87.7% < 95%", "History cadence 88.9% < 90%"], "machines": 450, "users": 64, "sseClients": 64, "durationMs": 20000, "committedPerSecond": 394.8, "sampleCadenceRatio": 0.8774, "historyCadenceRatio": 0.8888, "ackP95Ms": 560.42, "historyP95Ms": 541.9, "eventLoopP99Ms": 91.95, "sseNewestSampleP95Ms": 1060, "hubCpuPercentOneCore": 49.71, "hubRssPeakMiB": 369.7, "sseMegabytes": 1310.9, "report": "docs/stress-2026-11-04/181609-probe-m450-u64-s64-20000ms.json", "resources": "docs/stress-2026-11-04/181609-probe-m450-u64-s64-20000ms.resources.json", "wallSeconds": 62.0, "minimumAvailableMemoryGiB": 109.0, "peakHostCpuPercent": 4.33, "peakTestRssMiB": 742.5, "swapOutDeltaBytes": 0}
19
+ {"pass": false, "reasons": ["durable sample cadence 92.8% < 95%"], "machines": 2, "users": 2, "sseClients": 2, "durationMs": 3000, "committedPerSecond": 1.9, "sampleCadenceRatio": 0.9281, "historyCadenceRatio": 1.2375, "ackP95Ms": 31.04, "historyP95Ms": 5.89, "eventLoopP99Ms": 11.32, "sseNewestSampleP95Ms": 848, "hubCpuPercentOneCore": 2.73, "hubRssPeakMiB": 115.9, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/181845-probe-m2-u2-s2-3000ms.json", "resources": "docs/stress-2026-11-04/181845-probe-m2-u2-s2-3000ms.resources.json", "wallSeconds": 17.5, "minimumAvailableMemoryGiB": 109.7, "peakHostCpuPercent": 3.33, "peakTestRssMiB": 403.5, "swapOutDeltaBytes": 0}
20
+ {"pass": true, "reasons": [], "machines": 500, "users": 64, "sseClients": 64, "durationMs": 30000, "committedPerSecond": 500.2, "sampleCadenceRatio": 1.0003, "historyCadenceRatio": 1.0325, "ackP95Ms": 172.35, "historyP95Ms": 154.04, "eventLoopP99Ms": 92.6, "sseNewestSampleP95Ms": 384, "hubCpuPercentOneCore": 66.11, "hubRssPeakMiB": 430.0, "sseMegabytes": 3187.7, "report": "docs/stress-2026-11-04/181931-probe-m500-u64-s64-30000ms.json", "resources": "docs/stress-2026-11-04/181931-probe-m500-u64-s64-30000ms.resources.json", "wallSeconds": 73.3, "minimumAvailableMemoryGiB": 108.4, "peakHostCpuPercent": 9.69, "peakTestRssMiB": 1349.9, "swapOutDeltaBytes": 0}
21
+ {"pass": false, "reasons": ["ack p95 3872.03 > 500 ms", "durable sample cadence 74.4% < 95%", "collector rejection, retry, loss, backpressure or send error", "storage queue, write failure or physical pressure"], "machines": 1800, "users": 1, "sseClients": 0, "durationMs": 120000, "committedPerSecond": 1338.8, "sampleCadenceRatio": 0.7438, "historyCadenceRatio": 1.0083, "ackP95Ms": 3872.03, "historyP95Ms": 34.32, "eventLoopP99Ms": 37.75, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 108.35, "hubRssPeakMiB": 311.0, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/182108-probe-m1800-u1-s0-120000ms.json", "resources": "docs/stress-2026-11-04/182108-probe-m1800-u1-s0-120000ms.resources.json", "wallSeconds": 138.4, "minimumAvailableMemoryGiB": 109.2, "peakHostCpuPercent": 5.16, "peakTestRssMiB": 508.7, "swapOutDeltaBytes": 0}
22
+ {"pass": false, "reasons": ["ack p95 2154.32 > 500 ms", "collector rejection, retry, loss, backpressure or send error", "storage queue, write failure or physical pressure"], "machines": 1200, "users": 1, "sseClients": 0, "durationMs": 120000, "committedPerSecond": 1167.0, "sampleCadenceRatio": 0.9725, "historyCadenceRatio": 1.0083, "ackP95Ms": 2154.32, "historyP95Ms": 29.82, "eventLoopP99Ms": 49.51, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 92.41, "hubRssPeakMiB": 262.4, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/182354-probe-m1200-u1-s0-120000ms.json", "resources": "docs/stress-2026-11-04/182354-probe-m1200-u1-s0-120000ms.resources.json", "wallSeconds": 136.4, "minimumAvailableMemoryGiB": 109.3, "peakHostCpuPercent": 4.22, "peakTestRssMiB": 440.1, "swapOutDeltaBytes": 0}
23
+ {"pass": true, "reasons": [], "machines": 900, "users": 1, "sseClients": 0, "durationMs": 120000, "committedPerSecond": 900.0, "sampleCadenceRatio": 0.9999, "historyCadenceRatio": 1.0083, "ackP95Ms": 71.98, "historyP95Ms": 27.25, "eventLoopP99Ms": 60.85, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 75.13, "hubRssPeakMiB": 225.0, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/182625-probe-m900-u1-s0-120000ms.json", "resources": "docs/stress-2026-11-04/182625-probe-m900-u1-s0-120000ms.resources.json", "wallSeconds": 135.3, "minimumAvailableMemoryGiB": 109.4, "peakHostCpuPercent": 6.34, "peakTestRssMiB": 371.3, "swapOutDeltaBytes": 0}
24
+ {"pass": true, "reasons": [], "machines": 1050, "users": 1, "sseClients": 0, "durationMs": 120000, "committedPerSecond": 1046.0, "sseWorkers": 4, "clientWarmupMs": 0, "historyMetricSet": "standard", "historyIntervalMs": 1000, "sampleCadenceRatio": 0.9962, "historyCadenceRatio": 1.0083, "ackP95Ms": 140.06, "historyP95Ms": 27.62, "eventLoopP99Ms": 54.85, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 82.24, "hubRssPeakMiB": 260.2, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/182847-probe-m1050-u1-s0-120000ms.json", "resources": "docs/stress-2026-11-04/182847-probe-m1050-u1-s0-120000ms.resources.json", "wallSeconds": 135.3, "minimumAvailableMemoryGiB": 109.2, "peakHostCpuPercent": 5.34, "peakTestRssMiB": 432.1, "swapOutDeltaBytes": 0}
25
+ {"pass": false, "reasons": ["ack p95 538.2 > 500 ms"], "machines": 1125, "users": 1, "sseClients": 0, "durationMs": 120000, "committedPerSecond": 1113.5, "sseWorkers": 4, "clientWarmupMs": 0, "historyMetricSet": "standard", "historyIntervalMs": 1000, "sampleCadenceRatio": 0.9898, "historyCadenceRatio": 1.0083, "ackP95Ms": 538.2, "historyP95Ms": 30.91, "eventLoopP99Ms": 51.9, "sseNewestSampleP95Ms": 0, "hubCpuPercentOneCore": 86.73, "hubRssPeakMiB": 258.7, "sseMegabytes": 0.0, "report": "docs/stress-2026-11-04/183112-probe-m1125-u1-s0-120000ms.json", "resources": "docs/stress-2026-11-04/183112-probe-m1125-u1-s0-120000ms.resources.json", "wallSeconds": 135.3, "minimumAvailableMemoryGiB": 108.9, "peakHostCpuPercent": 8.98, "peakTestRssMiB": 439.3, "swapOutDeltaBytes": 0}
26
+ {"pass": true, "reasons": [], "machines": 500, "users": 64, "sseClients": 64, "durationMs": 120000, "committedPerSecond": 499.8, "sseWorkers": 4, "clientWarmupMs": 1000, "historyMetricSet": "standard", "historyIntervalMs": 1000, "sampleCadenceRatio": 0.9996, "historyCadenceRatio": 1.0081, "ackP95Ms": 222.83, "historyP95Ms": 180.56, "eventLoopP99Ms": 123.34, "sseNewestSampleP95Ms": 407, "hubCpuPercentOneCore": 74.68, "hubRssPeakMiB": 559.5, "sseMegabytes": 11733.6, "report": "docs/stress-2026-11-04/193608-probe-m500-u64-s64-120000ms.json", "resources": "docs/stress-2026-11-04/193608-probe-m500-u64-s64-120000ms.resources.json", "wallSeconds": 163.0, "minimumAvailableMemoryGiB": 108.2, "peakHostCpuPercent": 8.27, "peakTestRssMiB": 1474.6, "swapOutDeltaBytes": 0}
27
+ {"pass": true, "reasons": [], "machines": 529, "users": 1, "sseClients": 1, "durationMs": 15000, "committedPerSecond": 529.0, "sseWorkers": 1, "clientWarmupMs": 1000, "historyMetricSet": "standard", "historyIntervalMs": 1000, "sampleCadenceRatio": 1.0, "historyCadenceRatio": 1.0665, "ackP95Ms": 57.98, "historyP95Ms": 8.92, "eventLoopP99Ms": 52, "sseNewestSampleP95Ms": 79, "hubCpuPercentOneCore": 45.72, "hubRssPeakMiB": 200.4, "sseMegabytes": 32.5, "report": "docs/stress-2026-11-04/193909-probe-m529-u1-s1-15000ms.json", "resources": "docs/stress-2026-11-04/193909-probe-m529-u1-s1-15000ms.resources.json", "wallSeconds": 31.0, "minimumAvailableMemoryGiB": 109.5, "peakHostCpuPercent": 4.52, "peakTestRssMiB": 465.4, "swapOutDeltaBytes": 0}
28
+ {"pass": false, "reasons": ["SSE admission/delivery incomplete (0/1)", "live update rate below one update per two seconds per viewer"], "machines": 530, "users": 1, "sseClients": 1, "durationMs": 15000, "committedPerSecond": 531.9, "sseWorkers": 1, "clientWarmupMs": 1000, "historyMetricSet": "standard", "historyIntervalMs": 1000, "sampleCadenceRatio": 1.0037, "historyCadenceRatio": 1.0666, "ackP95Ms": 57.67, "historyP95Ms": 18.22, "eventLoopP99Ms": 51.41, "sseNewestSampleP95Ms": 64, "hubCpuPercentOneCore": 45.05, "hubRssPeakMiB": 189.2, "sseMegabytes": 1.0, "report": "docs/stress-2026-11-04/193940-probe-m530-u1-s1-15000ms.json", "resources": "docs/stress-2026-11-04/193940-probe-m530-u1-s1-15000ms.resources.json", "wallSeconds": 31.0, "minimumAvailableMemoryGiB": 109.5, "peakHostCpuPercent": 5.69, "peakTestRssMiB": 418.2, "swapOutDeltaBytes": 0}
29
+ {"pass": false, "reasons": ["SSE admission/delivery incomplete (64/65)"], "machines": 100, "users": 1, "sseClients": 65, "durationMs": 10000, "committedPerSecond": 100.0, "sseWorkers": 4, "clientWarmupMs": 1000, "historyMetricSet": "standard", "historyIntervalMs": 1000, "sampleCadenceRatio": 0.9999, "historyCadenceRatio": 0.9999, "ackP95Ms": 63.78, "historyP95Ms": 5.28, "eventLoopP99Ms": 37.03, "sseNewestSampleP95Ms": 481, "hubCpuPercentOneCore": 15.65, "hubRssPeakMiB": 162.4, "sseMegabytes": 176.8, "report": "docs/stress-2026-11-04/194011-probe-m100-u1-s65-10000ms.json", "resources": "docs/stress-2026-11-04/194011-probe-m100-u1-s65-10000ms.resources.json", "wallSeconds": 24.8, "minimumAvailableMemoryGiB": 109.3, "peakHostCpuPercent": 5.14, "peakTestRssMiB": 772.3, "swapOutDeltaBytes": 0}
@@ -0,0 +1,13 @@
1
+ {
2
+ "baseRevision": "3b77feaed4afc9ebd9af156008c78bd0278f9015",
3
+ "attemptCount": 29,
4
+ "resourceAborts": [],
5
+ "remainingTemporaryDirectories": [],
6
+ "totalWriteFailuresAcrossCases": 0,
7
+ "largestFinalDatabaseMiB": 320.3,
8
+ "sourceSha256": {
9
+ "scripts/scale-harness.ts": "8d67637bee926bfea6458536828939b95be4919edfec78f1c8b562f05b3c2f30",
10
+ "scripts/stress-hub.py": "1519a5868c0654eec76eab66df0c38f486c7aa4e88b235bcba83017b9f1ad7e6",
11
+ "tests/scale-harness.test.ts": "f87279588b95f02a78bf12861d27086131033ad5eca8191900004635d645584e"
12
+ }
13
+ }
@@ -0,0 +1,22 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Rigscope hub stress results</title><style>
2
+ #stress-results {font-family:var(--font-sans, system-ui);color:var(--foreground, CanvasText);font-size:14px;line-height:1.45}
3
+ #stress-results h2 {font-size:16px;font-weight:500;margin:0 0 4px}
4
+ #stress-results p {margin:0 0 18px;color:var(--muted-foreground, GrayText);font-size:12px}
5
+ #stress-results .axis,#stress-results .row {display:grid;grid-template-columns:70px minmax(60px,1fr) 118px;gap:12px;align-items:center}
6
+ #stress-results .axis {font-size:11px;color:var(--muted-foreground, GrayText);margin-bottom:8px}
7
+ #stress-results .axis-scale {position:relative;display:flex;justify-content:space-between}
8
+ #stress-results .axis-scale b {position:absolute;left:20%;transform:translateX(-50%);font-weight:400;white-space:nowrap;color:var(--foreground, CanvasText)}
9
+ #stress-results .row {height:44px;font-variant-numeric:tabular-nums}
10
+ #stress-results .track {position:relative;height:20px;background:color-mix(in srgb,var(--foreground, CanvasText) 6%,transparent);border-radius:3px}
11
+ #stress-results .bar {height:20px;border-radius:3px;min-width:3px}
12
+ #stress-results .pass {background:var(--chart-1, Highlight)}
13
+ #stress-results .fail {background:var(--chart-2, GrayText)}
14
+ #stress-results .limit {position:absolute;top:-7px;bottom:-7px;left:20%;border-left:1px dashed var(--foreground, CanvasText);opacity:.6}
15
+ #stress-results .value {text-align:right}
16
+ #stress-results small {display:block;font-size:11px;color:var(--muted-foreground, GrayText)}
17
+ #stress-results .mixed {margin-top:22px;padding-top:14px;border-top:1px solid var(--border, GrayText)}
18
+ #stress-results .metrics {display:flex;flex-wrap:wrap;gap:14px 32px;margin-top:10px}
19
+ #stress-results .metric {font-variant-numeric:tabular-nums}
20
+ #stress-results .metric strong {font-size:18px;font-weight:500}
21
+ @media(max-width:440px){#stress-results .axis,#stress-results .row{grid-template-columns:55px minmax(55px,1fr) 94px;gap:8px}#stress-results .axis-scale b{top:-16px}#stress-results .axis{margin-top:28px}}
22
+ </style></head><body><div id="stress-results"><h2>Ingestion gets slower near 1,100 collectors</h2><p>Two-minute runs · one sample per collector per second · no live viewers</p><div class="axis"><span>Collectors</span><span class="axis-scale"><span>0</span><b>500 ms limit</b><span>2,500 ms</span></span><span style="text-align:right">Ack p95</span></div><div class="row" aria-label="900 collectors, acknowledgment p95 72 milliseconds, Pass"><span>900</span><div class="track"><div class="bar pass" style="width:2.88%"></div><span class="limit"></span></div><span class="value">72 ms <small>Pass</small></span></div><div class="row" aria-label="1050 collectors, acknowledgment p95 140 milliseconds, Pass"><span>1,050</span><div class="track"><div class="bar pass" style="width:5.60%"></div><span class="limit"></span></div><span class="value">140 ms <small>Pass</small></span></div><div class="row" aria-label="1125 collectors, acknowledgment p95 538 milliseconds, Over threshold"><span>1,125</span><div class="track"><div class="bar fail" style="width:21.53%"></div><span class="limit"></span></div><span class="value">538 ms <small>Over threshold</small></span></div><div class="row" aria-label="1200 collectors, acknowledgment p95 2154 milliseconds, Over threshold"><span>1,200</span><div class="track"><div class="bar fail" style="width:86.17%"></div><span class="limit"></span></div><span class="value">2,154 ms <small>Over threshold</small></span></div><div class="mixed"><h2>500 collectors + 64 live sessions passed for two minutes</h2><div class="metrics"><div class="metric"><strong>223 ms</strong><small>Acknowledgment p95</small></div><div class="metric"><strong>181 ms</strong><small>History p95 · 64 polls/s</small></div><div class="metric"><strong>560 MiB</strong><small>Hub memory peak</small></div></div></div></div></body></html>
@@ -0,0 +1,195 @@
1
+ # System installation
2
+
3
+ System installation runs Rigscope under dedicated service accounts and starts
4
+ at boot without user lingering. For the default per-user npm setup, use the
5
+ [installation guide](installation.md).
6
+
7
+ Review the plan before applying changes. Commands that change the installation
8
+ require root and `--apply`; otherwise they only print the proposed changes.
9
+ The installed `rigscope system` command and `dist/system.cjs` use the same code.
10
+
11
+ | Task | Section |
12
+ | --- | --- |
13
+ | Review paths and permissions | [Generated layout](#scope-and-generated-layout) |
14
+ | Install or control services | [Component lifecycle](#system-component-lifecycle) |
15
+ | Enroll with another hub | [Connect to a hub](#connecting-to-an-independent-hub) |
16
+ | Grant package-energy access | [CPU package power](#cpu-package-power) |
17
+
18
+ ### Scope and generated layout
19
+
20
+ ```text
21
+ /opt/rigscope/ root:root 0755
22
+ releases/<version>/ immutable root-owned release
23
+ current -> releases/<version>
24
+ previous -> releases/<previous> retained for rollback
25
+ node/node root-owned Node 26 when the selected binary was not root-owned
26
+ /etc/rigscope/
27
+ hub.env root:root 0600 (credentials, never printed)
28
+ collector.env root:root 0600
29
+ /var/lib/rigscope/
30
+ hub/telemetry.sqlite rigscope-hub 0600, private 0700 directory
31
+ hub/enrollment.json rigscope-hub 0600
32
+ hub/run/hub.sock private Unix socket (remote mode)
33
+ collector/state.json rigscope-collector 0600
34
+ collector/outbox/ durable collector outboxes
35
+ backups/ root:root 0700, pre-upgrade/pre-rollback SQLite copies
36
+ system-install.json root:root 0600, version 2 component state/versions/backups/adoption
37
+ power-access.json root:root 0600, original counter modes for reversal
38
+ /etc/systemd/system/rigscope-hub.service root:root 0644, hub boot unit
39
+ /etc/systemd/system/rigscope-collector.service root:root 0644, collector boot unit
40
+ /etc/sysusers.d/rigscope.conf root:root 0644, both nologin accounts
41
+ /etc/sysusers.d/rigscope-rapl.conf root:root 0644, collector-only power membership
42
+ /etc/udev/rules.d/90-rigscope-rapl.rules root:root 0644
43
+ ```
44
+
45
+ Build the checkout before using `dist/system.cjs`; an installed package exposes the same commands through `rigscope system`. Reference copies are in `packaging/system/`. They are for review only; the
46
+ renderer in `src/cli/system.ts` is authoritative.
47
+
48
+ `systemd-sysusers` creates `rigscope-hub` and `rigscope-collector` as nologin
49
+ system accounts even when one component is disabled, so the other can be
50
+ enabled later without reinstalling. The hub and collector never run as root.
51
+ The units set `NoNewPrivileges=yes`, `ProtectSystem=strict`,
52
+ `ProtectHome=yes`, an empty `CapabilityBoundingSet=`/`AmbientCapabilities=`,
53
+ `UMask=0077`, explicit writable state paths and a read-only release tree. The
54
+ collector uses `--await-connection` to exit cleanly when no destinations are
55
+ configured, including after an interrupted enrollment. The
56
+ collector does **not** use `PrivateDevices=yes` because GPU telemetry still
57
+ needs real device nodes. The hub does.
58
+
59
+ ### System component lifecycle
60
+
61
+ All mutating commands require `--apply` and root. Without `--apply`, the exact
62
+ files and command sequence are printed and nothing is written. Every component
63
+ operation touches only its own unit; enabling or starting one component never
64
+ stops or restarts the other.
65
+
66
+ ```sh
67
+ # Package first (from a built checkout).
68
+ node scripts/package-release.cjs --output /var/tmp/rigscope-<version>.tar.gz
69
+
70
+ # Review a release before granting sudo.
71
+ node dist/system.cjs plan \
72
+ --source /var/tmp/rigscope-<version>.tar.gz --role local --node /usr/bin/node
73
+
74
+ # Install one complete package. --role selects the initial enabled preset.
75
+ sudo node dist/system.cjs install \
76
+ --source /var/tmp/rigscope-<version>.tar.gz --role hub \
77
+ --node /usr/bin/node --install-deps --enable --apply
78
+
79
+ # Add the other component later; no reinstall and no new package are needed.
80
+ sudo node dist/system.cjs enable collector --apply
81
+ sudo node dist/system.cjs enable hub --apply
82
+
83
+ # Component-specific lifecycle when both exist.
84
+ sudo node dist/system.cjs disable collector --apply
85
+ sudo node dist/system.cjs restart hub --apply
86
+ sudo node dist/system.cjs restart collector --apply
87
+ sudo node dist/system.cjs restart --apply # enabled components only
88
+
89
+ # Component-specific status and logs.
90
+ node dist/system.cjs status
91
+ node dist/system.cjs status collector --json
92
+ node dist/system.cjs logs hub --follow
93
+ ```
94
+
95
+ `install` stages a complete release, verifies both runtimes and UI artifacts,
96
+ copies a non-root-owned Node executable into the root-owned prefix, installs
97
+ production dependencies when `--install-deps` is given, writes private
98
+ configuration and both units, creates both accounts, then switches `current`.
99
+ Staging happens before any service is stopped.
100
+
101
+ - With `--enable`, `--role local` initially enables both components.
102
+ - With `--enable`, `--role hub` initially enables only the hub.
103
+ - With `--enable`, `--role collector` initially enables only the collector.
104
+ - Without `--enable`, both components are installed but disabled.
105
+ - `--start` starts only the requested preset and verifies those components.
106
+ - `--without-power` skips the collector RAPL grant at that mutation.
107
+
108
+ `enable hub` creates the owner account once when `HUB_BROWSER_USERS` is empty
109
+ and prints the password only in that mutation. It is never stored in plaintext
110
+ or printed again. `enable collector` completes the collector account, unit,
111
+ identity and RAPL grant. With no destination it tries the colocated hub:
112
+
113
+ - A live configured hub gets a short-lived, single-use grant in its
114
+ authoritative SQLite registry. The collector then enrolls through the normal
115
+ hub API, which updates the live registry without stopping or restarting the
116
+ hub.
117
+ - A stopped hub gets the identity written to the authoritative registry (or a
118
+ static `HUB_COLLECTORS` bootstrap when the registry is not initialized yet);
119
+ enabling the collector never starts the hub.
120
+ - If there is no configured hub, the collector is enabled but stays dormant and
121
+ reports `Awaiting connection`. Its unit uses `--await-connection` to exit
122
+ cleanly before collection until a destination is saved.
123
+
124
+ Configured remote destinations and credentials are never overwritten. Re-running
125
+ `enable collector` leaves its destination, token, identity and outboxes intact.
126
+
127
+ ### Connecting to an independent hub
128
+
129
+ For a hub-first test where the hub and collector are separate installations,
130
+ create a connection grant in the hub's admin Collectors panel. Save the grant to
131
+ a private file and connect the system collector:
132
+
133
+ ```sh
134
+ # On the collector host; the grant file must be root-owned and 0600.
135
+ sudo install -m 0600 /dev/null /root/collector-grant
136
+ sudoedit /root/collector-grant # paste the single-use grant, save, quit
137
+ sudo node dist/system.cjs connect https://<hub-host> \
138
+ --token-file /root/collector-grant --apply
139
+ sudo rm /root/collector-grant
140
+ ```
141
+
142
+ `connect` stops only the collector while it enrolls, calls the hub's normal
143
+ enrollment API, persists the issued credential under
144
+ `/var/lib/rigscope/collector/state.json`, and starts the collector if it is
145
+ enabled. The grant is never printed. Re-running `connect` on a configured
146
+ collector is refused rather than replacing a remote destination.
147
+
148
+ Status reports each component independently:
149
+
150
+ ```text
151
+ Components:
152
+ hub: installed, enabled, active, ready
153
+ collector: installed, enabled, active, ready, 1 destination(s)
154
+ ```
155
+
156
+ `readiness` is `ready`, `stopped`, `unconfigured`, `awaiting-connection`,
157
+ `invalid-config`, `invalid-state` or `missing`.
158
+
159
+ ### CPU package power
160
+
161
+ `collector/sampling/hwmon.ts` already reads top-level RAPL package counters,
162
+ sums multiple sockets, handles wrap/reset and returns unavailable rather than
163
+ zero. On hosts where `energy_uj` is root-only, system scope grants a narrow
164
+ read path instead of elevating Node.
165
+
166
+ ```sh
167
+ node dist/system.cjs power status
168
+ sudo node dist/system.cjs power grant --apply
169
+ sudo node dist/system.cjs power revoke --apply
170
+ ```
171
+
172
+ Mechanism:
173
+
174
+ - `/etc/sysusers.d/rigscope-rapl.conf` creates `rigscope-rapl` and adds only
175
+ `rigscope-collector`; the hub is not a member.
176
+ - A `powercap` udev rule matches only top-level `intel-rapl:N` devices named
177
+ `package*` and changes only `energy_uj` and `max_energy_range_uj` to
178
+ `0440 root:rigscope-rapl`. Subdomains, constraint files and power-limit
179
+ writes are untouched.
180
+ - `udevadm trigger --subsystem-match=powercap --action=change` applies the rule
181
+ immediately. Because the rule lives in `/etc/udev/rules.d`, device
182
+ recreation and boot reapply it.
183
+ - The collector unit adds `SupplementaryGroups=rigscope-rapl`; it does not use
184
+ file capabilities, ambient capabilities or a privileged Node helper.
185
+ - Grant records each existing counter's original mode/uid/gid in
186
+ `/var/lib/rigscope/power-access.json`. Revoke removes the rule and group
187
+ membership and restores those recorded values (defaults `0400` for
188
+ `energy_uj` and `0444` for `max_energy_range_uj` when no record exists).
189
+ - `power status` reports driver modules, package domains, collector
190
+ readability, persistence, world readability and every problem. A missing
191
+ counter is reported unavailable, never as zero watts.
192
+
193
+ Verify real watts in History after granting access and restarting the collector;
194
+ do not treat a mocked value or a one-time manual `chmod` as installation
195
+ evidence. Unsupported hardware remains unavailable.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rigscope",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "rigscopeConfigVersion": 2,
5
5
  "private": false,
6
6
  "engines": {
@@ -68,6 +68,9 @@
68
68
  "README.md",
69
69
  "CHANGELOG.md",
70
70
  "docs/installation.md",
71
+ "docs/system-installation.md",
72
+ "docs/configuration.md",
73
+ "docs/monitoring.md",
71
74
  "docs/operations.md",
72
75
  "docs/bottlenecks.md",
73
76
  "docs/exports.md",
@@ -76,6 +79,11 @@
76
79
  "docs/scale-validation.md",
77
80
  "docs/scale-validation.json",
78
81
  "docs/scale-acceptance.json",
82
+ "docs/stress-2026-11-04/README.md",
83
+ "docs/stress-2026-11-04/index.jsonl",
84
+ "docs/stress-2026-11-04/manifest.json",
85
+ "docs/stress-2026-11-04/results.html",
86
+ "docs/stress-2026-11-04/*ms.json",
79
87
  "ARCHITECTURE.md",
80
88
  "DESIGN.md",
81
89
  "LICENSE",
@@ -2,4 +2,4 @@
2
2
 
3
3
  These files illustrate dedicated `rigscope-hub` and `rigscope-collector` accounts, systemd units and read-only package-energy access. The renderer in `src/cli/system.ts` is authoritative; do not install examples blindly.
4
4
 
5
- See [system installation](../../docs/installation.md#system-installation) for planning, `--apply`, independent component controls and RAPL permission limits. The collector needs GPU device access and does not use `PrivateDevices=yes`; the hub does. Both run without root privileges, with private state and bounded writable paths.
5
+ See [System installation](../../docs/system-installation.md) for planning, `--apply`, component controls and CPU package-power permissions. The collector needs GPU device access and does not use `PrivateDevices=yes`; the hub does. Both run without root privileges.
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[408],{4567:(e,t,r)=>{r.d(t,{Cv:()=>s,H9:()=>i,Lf:()=>u,P$:()=>n,RL:()=>g,bP:()=>h,er:()=>m,oB:()=>a,ue:()=>f,yv:()=>d});let i=[{metric:"cpu.usage",label:"CPU usage",shortLabel:"CPU",unit:"percent",family:"cpu",colorSlot:0,description:"Total processor utilization"},{metric:"cpu.core",label:"Per-core CPU",shortLabel:"Per-core",unit:"percent",family:"cpu",colorSlot:0,description:"Logical-core utilization; heatmap for large selections"},{metric:"cpu.temperature",label:"CPU temperature",shortLabel:"Temperature",unit:"celsius",family:"cpu",colorSlot:3,description:"Identifiable CPU hwmon sensor temperature"},{metric:"cpu.power",label:"CPU package power",shortLabel:"Power",unit:"watts",family:"cpu",colorSlot:4,description:"Top-level RAPL package power draw"},{metric:"cpu.iowait",label:"CPU I/O wait",shortLabel:"I/O wait",unit:"percent",family:"cpu",colorSlot:2,description:"Processor time waiting on I/O"},{metric:"cpu.pressure",label:"CPU pressure",shortLabel:"Pressure",unit:"percent",family:"cpu",colorSlot:4,description:"Linux PSI CPU stall pressure (avg10)"},{metric:"memory.used",label:"Memory used",shortLabel:"Memory",unit:"bytes",family:"memory",colorSlot:1,description:"Physical memory in use"},{metric:"memory.usage",label:"Memory usage",shortLabel:"Memory %",unit:"percent",family:"memory",colorSlot:1,description:"Physical memory used as a share of total"},{metric:"memory.pressure.some",label:"Memory pressure (some)",shortLabel:"Pressure some",unit:"percent",family:"memory",colorSlot:2,description:"Linux PSI memory stall pressure, some tasks (avg10)"},{metric:"memory.pressure.full",label:"Memory pressure (full)",shortLabel:"Pressure full",unit:"percent",family:"memory",colorSlot:4,description:"Linux PSI memory stall pressure, all tasks (avg10)"},{metric:"swap.used",label:"Swap used",shortLabel:"Swap",unit:"bytes",family:"swap",colorSlot:2,description:"Swap space in use"},{metric:"gpu.utilization",label:"GPU utilization",shortLabel:"Utilization",unit:"percent",family:"gpus",colorSlot:0,description:"Per-card graphics processor utilization"},{metric:"gpu.memory.used",label:"GPU memory used",shortLabel:"VRAM",unit:"bytes",family:"gpus",colorSlot:1,description:"Per-card video memory in use"},{metric:"gpu.temperature",label:"GPU temperature",shortLabel:"Temperature",unit:"celsius",family:"gpus",colorSlot:3,description:"Per-card temperature"},{metric:"gpu.power",label:"GPU power",shortLabel:"Power",unit:"watts",family:"gpus",colorSlot:4,description:"Per-card power draw"},{metric:"fs.used",label:"Filesystem used",shortLabel:"Filesystem",unit:"bytes",family:"disks",colorSlot:1,description:"Used space per mounted filesystem"},{metric:"fs.usage",label:"Filesystem usage",shortLabel:"Filesystem %",unit:"percent",family:"disks",colorSlot:1,description:"Used capacity per mounted filesystem, derived from a positive total"},{metric:"fs.inodes.usage",label:"Inode usage",shortLabel:"Inodes %",unit:"percent",family:"disks",colorSlot:2,description:"Used inodes per filesystem where the collector can read them"},{metric:"disk.read",label:"Disk read",shortLabel:"Read",unit:"bytes_per_second",family:"disks",colorSlot:0,description:"Device read throughput"},{metric:"disk.write",label:"Disk write",shortLabel:"Write",unit:"bytes_per_second",family:"disks",colorSlot:2,description:"Device write throughput"},{metric:"disk.read.latency",label:"Disk read latency",shortLabel:"Read latency",unit:"milliseconds",family:"disks",colorSlot:0,description:"Average device read latency"},{metric:"disk.write.latency",label:"Disk write latency",shortLabel:"Write latency",unit:"milliseconds",family:"disks",colorSlot:2,description:"Average device write latency"},{metric:"disk.utilization",label:"Disk utilization",shortLabel:"Utilization",unit:"percent",family:"disks",colorSlot:3,description:"Share of time the device had I/O in flight"},{metric:"io.pressure.some",label:"I/O pressure (some)",shortLabel:"I/O some",unit:"percent",family:"disks",colorSlot:3,description:"Linux PSI I/O stall pressure, some tasks (avg10)"},{metric:"io.pressure.full",label:"I/O pressure (full)",shortLabel:"I/O full",unit:"percent",family:"disks",colorSlot:4,description:"Linux PSI I/O stall pressure, all tasks (avg10)"},{metric:"net.rx",label:"Network received",shortLabel:"Received",unit:"bytes_per_second",family:"network",colorSlot:0,description:"Interface receive rate"},{metric:"net.tx",label:"Network sent",shortLabel:"Sent",unit:"bytes_per_second",family:"network",colorSlot:2,description:"Interface transmit rate"}];function s(e,t){return e.filter(r=>{for(let[i,s,n]of[["memory","memory.used","memory.usage"],["filesystem","fs.used","fs.usage"]])if(e.includes(s)&&e.includes(n)&&(r===s||r===n))return r===("percent"===t[i]?n:s);return!0})}let n=[{id:"cpu",label:"CPU",metrics:["cpu.usage","cpu.core","cpu.iowait","cpu.pressure","cpu.temperature","cpu.power"]},{id:"memory",label:"Memory",metrics:["memory.used","memory.usage","swap.used","memory.pressure.some","memory.pressure.full"]},{id:"gpu",label:"GPU",metrics:["gpu.utilization","gpu.memory.used","gpu.temperature","gpu.power"]},{id:"disk",label:"Storage",metrics:["fs.used","fs.usage","fs.inodes.usage","disk.read","disk.write","disk.read.latency","disk.write.latency","disk.utilization","io.pressure.some","io.pressure.full"]},{id:"network",label:"Network",metrics:["net.rx","net.tx"]}],l=["var(--cpu)","var(--mem)","color-mix(in oklab, var(--swap) 75%, var(--foreground))","var(--warn)","var(--crit)","var(--accent)"],o=[void 0,"7 4","2 3","10 3 2 3","4 4","1 3"];function a(e){return i.find(t=>t.metric===e)??null}function u(e,t){let r=Math.max(0,t),i=e.colorSlot+r,s=(r+Math.floor(i/l.length))%o.length;return{color:l[i%l.length],dash:o[s]}}let c={cpu:"CPU",memory:"Memory",swap:"Swap",gpus:"GPU metrics",disks:"Disk metrics",network:"Network metrics"};function d(e,t){let r=a(t);if(null===r||void 0===e)return{available:!0,reason:null};let i=e.inventory?.capabilities?.[r.family];if(!i||"supported"===i.status)return{available:!0,reason:null};let s=i.reason?.trim();return{available:!1,reason:s?`${c[r.family]}: ${i.status} — ${s}`:`${c[r.family]} are ${i.status} on this machine.`}}function m(e){if(void 0===e)return[];let t=[],r=r=>{!(t.length>=16)&&d(e,r).available&&t.push(r)};r("cpu.usage"),r("memory.used");let i=function(e){let t=e.inventory?.memory.swapTotalBytes;if("number"==typeof t)return t;let r=e.metrics?.payload.swap;return r?.status==="ok"?r.totalBytes:null}(e);return null!==i&&i>0&&r("swap.used"),f(e,[]).length>0&&(r("gpu.utilization"),r("gpu.memory.used")),t}function p(e){let t=e.includes(":")?e.slice(e.indexOf(":")+1):e;return t.length<=18?t:`${t.slice(0,10)}…${t.slice(-4)}`}function f(e,t){let r=new Set(t.filter(e=>e.metric.startsWith("gpu.")&&""!==e.resourceId).map(e=>e.resourceId)),i=[],s=new Set;(e?.inventory?.gpus??[]).forEach(e=>{let t="supported"===e.telemetry;(t||r.has(e.id))&&(s.add(e.id),i.push({id:e.id,label:e.name.trim()||p(e.id),index:i.length,totalBytes:e.memoryTotalBytes,supported:t,hasHistory:r.has(e.id)}))});let n=e?.metrics?.payload.gpus;if(n?.status==="ok")for(let e of n.devices)s.has(e.id)||"ok"!==e.status||(s.add(e.id),i.push({id:e.id,label:p(e.id),index:i.length,totalBytes:e.memoryTotalBytes,supported:!0,hasHistory:r.has(e.id)}));for(let e of[...r].sort())s.has(e)||i.push({id:e,label:p(e),index:i.length,totalBytes:null,supported:!0,hasHistory:!0});return i}function h(e,t,r){if(""===r)return a(t)?.shortLabel??"Total";let i=a(t);if(null===i)return p(r);switch(i.family){case"gpus":{let t=e?.inventory?.gpus.find(e=>e.id===r);return t?.name.trim()||p(r)}case"disks":{if(t.startsWith("fs.")){let t=e?.inventory?.filesystems.find(e=>e.id===r);return t?.mountPoint||p(r)}let i=e?.inventory?.disks.find(e=>e.id===r);return i?.name||p(r)}case"network":{let t=e?.inventory?.network.find(e=>e.id===r);return t?.name||p(r)}case"cpu":{let e=/^core:(\d+)$/.exec(r);return e?`Core ${e[1]}`:p(r)}default:return p(r)}}function g(e){switch(e){case"percent":return"%";case"bytes":return"bytes";case"bytes_per_second":return"bytes/s";case"celsius":return"\xb0C";case"watts":return"W";case"milliseconds":return"ms";default:return e}}},5078:(e,t,r)=>{r.d(t,{Ah:()=>d,I_:()=>h,O5:()=>f,Vw:()=>k,bf:()=>v,dd:()=>c,ei:()=>m,fH:()=>g,ly:()=>s,pI:()=>i,r6:()=>p,zp:()=>n});let i=[{id:"10m",shortLabel:"10m",label:"Last 10 minutes",ms:6e5,refreshMs:1e3},{id:"1h",shortLabel:"1h",label:"Last hour",ms:36e5,refreshMs:1e3},{id:"6h",shortLabel:"6h",label:"Last 6 hours",ms:216e5,refreshMs:1e3},{id:"24h",shortLabel:"24h",label:"Last 24 hours",ms:864e5,refreshMs:1e3},{id:"7d",shortLabel:"7d",label:"Last 7 days",ms:6048e5,refreshMs:1e3}];function s(e){return i.find(t=>t.id===e)??i[0]}function n(e){return s(e).refreshMs}let l=["B","KiB","MiB","GiB","TiB","PiB"];function o(e){let t=Math.abs(e),r=0;for(;t>=1024&&r<l.length-1;)t/=1024,r+=1;return{value:e<0?-t:t,unit:l[r]}}function a(e,t){return String(Number(e.toFixed(t)))}function u(e,t=""){let{value:r,unit:i}=o(e),s=Math.abs(r)>=100?0:1;return`${a(r,s)} ${i}${t}`}function c(e,t){if(null==e||!Number.isFinite(e))return"—";switch(t){case"percent":return`${a(e,1)}%`;case"bytes":return u(e);case"bytes_per_second":return u(e,"/s");case"celsius":return`${a(e,1)}\xb0C`;case"watts":return`${a(e,1)} W`;case"milliseconds":return`${a(e,10>Math.abs(e)?2:1)} ms`;default:return a(e,2)}}function d(e,t){if(!Number.isFinite(e))return"—";switch(t){case"percent":return`${a(e,0)}%`;case"bytes":case"bytes_per_second":{let{value:r,unit:i}=o(e),s=Math.abs(r)>=10||0===r?0:1;return`${a(r,s)} ${i}${"bytes_per_second"===t?"/s":""}`}case"celsius":return`${a(e,0)}\xb0C`;case"watts":return`${a(e,0)} W`;case"milliseconds":return`${a(e,+(10>Math.abs(e)))} ms`;default:return a(e,1)}}function m(e){return new Date(e).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1})}function p(e){return new Date(e).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"medium"})}function f(e,t){let r=new Date(e);return t>=1728e5?r.toLocaleDateString(void 0,{month:"short",day:"numeric"}):t>=864e5?r.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}):r.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",hour12:!1})}function h(e){let t=Math.max(0,e);return t>=36e5?`${a(t/36e5,1)} h`:t>=6e4?`${a(t/6e4,1)} min`:`${a(t/1e3,1)} s`}function g(e,t,r){let i=e.filter(e=>e.toMs>=t&&e.fromMs<=r);if(0===i.length)return"No recorded gaps in this range.";let s=i.filter(e=>"dropped"===e.kind).length,n=i.length-s,l=[];n>0&&l.push(`${n} missed interval${1===n?"":"s"}`),s>0&&l.push(`${s} dropped report${1===s?"":"s"}`);let o=[...new Set(i.map(e=>e.reason).filter(e=>"string"==typeof e&&e.length>0))],a=o.length>0?` (${o.slice(0,3).join("; ")})`:"";return`${l.join(" and ")}${a}.`}function y(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function b(e){return"number"==typeof e&&Number.isFinite(e)}function x(e){return null===e||b(e)}function v(e){if(!y(e)||"string"!=typeof e.machineId||0===e.machineId.length||!b(e.fromMs)||!b(e.toMs)||e.toMs<=e.fromMs||!b(e.stepMs)||e.stepMs<=0||"raw"!==e.tier&&"1m"!==e.tier&&"1h"!==e.tier||"boolean"!=typeof e.truncated||!b(e.elapsedMs)||!Array.isArray(e.series)||!Array.isArray(e.gaps))return null;let t=[];for(let r of e.series){if(!y(r)||"string"!=typeof r.metric||"string"!=typeof r.resourceId||"string"!=typeof r.unit||!Array.isArray(r.points))return null;let e=[];for(let t of r.points){if(!y(t)||!b(t.t)||!x(t.min)||!x(t.max)||!x(t.avg))return null;e.push({t:t.t,min:t.min,max:t.max,avg:t.avg})}t.push({metric:r.metric,resourceId:r.resourceId,unit:r.unit,points:e})}let r=[];for(let t of e.gaps){if(!y(t)||!b(t.fromMs)||!b(t.toMs)||"missing"!==t.kind&&"dropped"!==t.kind)return null;let e={fromMs:t.fromMs,toMs:t.toMs,kind:t.kind};"string"==typeof t.reason&&(e.reason=t.reason),b(t.droppedRecords)&&(e.droppedRecords=t.droppedRecords),r.push(e)}return{machineId:e.machineId,fromMs:e.fromMs,toMs:e.toMs,stepMs:e.stepMs,tier:e.tier,series:t,gaps:r,truncated:e.truncated,elapsedMs:e.elapsedMs}}function k(e,t,r,i,n=600,l){let{fromMs:o,toMs:a}={fromMs:i-s(r).ms,toMs:i},u=new URLSearchParams({machineId:e,metrics:t.join(","),from:String(Math.floor(o)),to:String(Math.floor(a)),maxPoints:String(n)});return void 0!==l&&u.set("coreIds",l.join(",")),`/api/history?${u.toString()}`}},7284:(e,t,r)=>{r.d(t,{t:()=>o});var i=r(5155),s=r(7726),n=r(5078),l=r(4567);function o(e){let{title:t,unit:r,series:o,fromMs:a,toMs:u,stepMs:c,gaps:d,hiddenKeys:m,onToggleSeries:p,emptyMessage:f,note:h}=e,g=o.filter(e=>!m.has(e.key)),y=g.flatMap(e=>e.points),b=y.some(e=>null!==e.avg||null!==e.min||null!==e.max),x=Math.max(1,u-a),v=(0,s.$z)(d,a,u),k=(0,s.kk)(r,y.flatMap(e=>[e.min,e.max,e.avg]).filter(e=>null!==e)),w=Math.max(1e-9,k.max-k.min),M=e=>6+(Math.min(u,Math.max(a,e))-a)/x*788,$=e=>6+(1-(e-k.min)/w)*148,S=g.map(t=>{let r=(0,s.SG)(t.points,e.maxDrawPoints??600,c),i=(0,s.o)(r,{stepMs:c,gaps:d,fromMs:a,toMs:u});return{...t,segments:i}}),L=function(e,t,r,i,l,o){if(0===r.length)return`${e} chart: no series selected.`;let a=r.map(e=>{let r=(0,s.T6)(e.points);return`${e.label}: ${function(e,t){let r=[];if(null!==e.latest){let i=null!==e.latestT?(0,n.ei)(e.latestT):null;r.push(`latest ${(0,n.dd)(e.latest,t)}${i?` at ${i}`:""}`)}return r.push(`average ${(0,n.dd)(e.avg,t)}`),null!==e.min&&null!==e.max&&r.push(`recorded range ${(0,n.dd)(e.min,t)} to ${(0,n.dd)(e.max,t)}`),r.join(", ")}(r,t)}`}),u=o>0?`${o} shaded interval${1===o?"":"s"} without stored data.`:"";return`${e} time-series chart. ${a.join(". ")}. ${u} Time range ${(0,n.ei)(i)} to ${(0,n.ei)(l)}.`}(t,r,g,a,u,v.length);return(0,i.jsxs)("figure",{className:`flex min-w-0 flex-col gap-2 ${e.className??""}`,children:[(0,i.jsxs)("div",{className:"flex min-h-8 flex-wrap items-center justify-between gap-2",children:[(0,i.jsx)("h3",{className:"text-xs font-medium tracking-tight text-foreground",children:t}),(0,i.jsxs)("div",{className:"flex items-center gap-3",children:[(0,i.jsx)("span",{className:"tnum shrink-0 text-xs text-muted-foreground",children:h??(0,l.RL)(r)}),e.action]})]}),b?(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)("div",{className:"flex min-w-0 gap-2",children:[(0,i.jsx)("div",{"aria-hidden":!0,className:"flex h-40 w-14 shrink-0 flex-col justify-between py-0.5 text-right text-xs leading-none tnum text-muted-foreground",children:[...k.ticks].reverse().map(e=>(0,i.jsx)("span",{children:(0,n.Ah)(e,r)},e))}),(0,i.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,i.jsxs)("svg",{viewBox:"0 0 800 160",preserveAspectRatio:"none",role:"img","aria-label":L,className:"block h-40 w-full",children:[(0,i.jsx)("title",{children:t}),k.ticks.map(e=>(0,i.jsx)("line",{x1:6,x2:794,y1:$(e),y2:$(e),stroke:"var(--border)",strokeWidth:"1",vectorEffect:"non-scaling-stroke"},`grid-${e}`)),v.map(e=>(0,i.jsx)("rect",{x:M(e.fromMs),y:6,width:Math.max(1,M(e.toMs)-M(e.fromMs)),height:148,fill:"var(--muted-foreground)",opacity:"0.09"},`gap-${e.fromMs}-${e.toMs}-${e.kind}`)),S.map(e=>{var t;let r=(t=e.segments,t.filter(e=>e.length>1).map(e=>{let t=e.map(e=>`${M(e.t).toFixed(2)},${$(e.max??e.avg).toFixed(2)}`),r=[...e].reverse().map(e=>`${M(e.t).toFixed(2)},${$(e.min??e.avg).toFixed(2)}`);return`M${t.join("L")}L${r.join("L")}Z`}).join(" "));return""===r?null:(0,i.jsx)("path",{d:r,fill:e.color,opacity:"0.14",stroke:"none"},`band-${e.key}`)}),S.map(e=>{var t;let r=(t=e.segments,t.filter(e=>e.length>1).map(e=>e.map((e,t)=>`${0===t?"M":"L"}${M(e.t).toFixed(2)},${$(e.avg).toFixed(2)}`).join(" ")).join(" "));return""===r?null:(0,i.jsx)("path",{d:r,fill:"none",stroke:e.color,strokeWidth:"2",strokeDasharray:e.dash,strokeLinecap:"round",strokeLinejoin:"round",vectorEffect:"non-scaling-stroke"},`line-${e.key}`)}),S.flatMap(e=>e.segments.filter(e=>1===e.length).map(t=>{let r=t[0],s=M(r.t),n=$(r.avg);return(0,i.jsx)("line",{x1:s-2.5,x2:s+2.5,y1:n,y2:n,stroke:e.color,strokeWidth:"2.5",strokeLinecap:"round",vectorEffect:"non-scaling-stroke"},`dot-${e.key}-${r.t}`)}))]}),(0,i.jsx)("div",{"aria-hidden":!0,className:"mt-1 flex justify-between gap-2 text-xs leading-tight tnum text-muted-foreground",children:(0,s.Cf)(a,u).map((e,t,r)=>(0,i.jsx)("span",{className:`${0===t?"text-left":t===r.length-1?"text-right":"hidden text-center sm:inline"}`,children:(0,n.O5)(e,x)},e))})]})]}),(0,i.jsx)("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-1.5 text-xs",children:o.map(e=>{let t=!m.has(e.key),l=(0,s.T6)(e.points);return(0,i.jsxs)("label",{className:"inline-flex min-h-7 cursor-pointer items-center gap-1.5",title:t?`Hide ${e.label}`:`Show ${e.label}`,children:[(0,i.jsx)("input",{type:"checkbox",checked:t,onChange:()=>p(e.key),className:"peer sr-only"}),(0,i.jsx)("span",{"aria-hidden":!0,className:"flex h-4 w-5 shrink-0 items-center justify-center rounded-sm peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:[outline-color:var(--focus)]",children:(0,i.jsx)("svg",{viewBox:"0 0 20 8",className:"h-2 w-5","aria-hidden":!0,children:(0,i.jsx)("line",{x1:"1",y1:"4",x2:"19",y2:"4",stroke:e.color,strokeWidth:"2.5",strokeDasharray:e.dash,strokeLinecap:"round"})})}),(0,i.jsx)("span",{className:t?"text-foreground":"text-muted-foreground line-through",children:e.label}),(0,i.jsx)("span",{className:"tnum text-muted-foreground",children:(0,n.dd)(l.latest,r)})]},`legend-${e.key}`)})})]}):(0,i.jsx)("div",{className:"flex min-h-32 items-center justify-center rounded-lg border border-dashed border-border px-4 py-6 text-center text-xs text-muted-foreground",children:0===o.length?f:0===g.length?"All series are hidden. Re-enable one in the legend below.":f}),!b&&o.length>0?(0,i.jsx)("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-1.5 text-xs",children:o.map(e=>{let t=!m.has(e.key);return(0,i.jsxs)("label",{className:"inline-flex min-h-7 cursor-pointer items-center gap-1.5",children:[(0,i.jsx)("input",{type:"checkbox",checked:t,onChange:()=>p(e.key),className:"peer sr-only"}),(0,i.jsx)("span",{"aria-hidden":!0,className:"flex h-4 w-5 shrink-0 items-center justify-center peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:[outline-color:var(--focus)]",children:(0,i.jsx)("svg",{viewBox:"0 0 20 8",className:"h-2 w-5","aria-hidden":!0,children:(0,i.jsx)("line",{x1:"1",y1:"4",x2:"19",y2:"4",stroke:e.color,strokeWidth:"2.5",strokeDasharray:e.dash,strokeLinecap:"round"})})}),(0,i.jsx)("span",{className:t?"text-foreground":"text-muted-foreground line-through",children:e.label})]},`legend-empty-${e.key}`)})}):null]})}},7726:(e,t,r)=>{function i(e){return null!==e.avg&&Number.isFinite(e.avg)}function s(e){return null!==e&&Number.isFinite(e)?e:null}function n(e,t,r){let i=e.map(e=>({...e,fromMs:Math.max(t,e.fromMs),toMs:Math.min(r,e.toMs)})).filter(e=>e.toMs>e.fromMs).sort((e,t)=>e.fromMs-t.fromMs||e.toMs-t.toMs),s=[];for(let e of i){let t=s.at(-1);if(void 0!==t&&e.fromMs<=t.toMs){t.toMs=Math.max(t.toMs,e.toMs),"missing"===t.kind&&"dropped"===e.kind&&(t.kind="dropped"),void 0===t.reason&&void 0!==e.reason&&(t.reason=e.reason),void 0===t.droppedRecords&&void 0!==e.droppedRecords&&(t.droppedRecords=e.droppedRecords);continue}s.push({...e})}return s}function l(e,t,r){return Math.max(e,"1h"===t?36e5:"1m"===t?6e4:100,r??0)}function o(e,t){let r=[...e].sort((e,t)=>e.t-t.t),s=n(t.gaps,t.fromMs,t.toMs),l=Math.max(1,t.stepMs),o=[],a=[],u=()=>{a.length>0&&o.push(a),a=[]};for(let e of r){if(!i(e)){u();continue}let t=a.at(-1);if(void 0!==t){let r=!e.merged&&!t.merged&&(e.t<t.t||e.t-t.t>1.5*l),i=!0===e.gapBefore||function(e,t,r){return r.some(r=>r.toMs>e&&r.fromMs<t)}(t.t,e.t,s);(r||i)&&u()}a.push(e)}return u(),o}function a(e,t,r){if(t<=0)return[];let n=[...e].sort((e,t)=>e.t-t.t);if(n.length<=t)return n.map(e=>({...e}));let l=Math.max(2,Math.ceil(n.length/t)),o=Math.max(1,r),a=[],u=[],c=!1,d=null,m=()=>{if(0===u.length)return;let e=null,t=null,r=0,i=0;for(let n of u){let l=s(n.min),o=s(n.max);null!==l&&(null===e||l<e)&&(e=l),null!==o&&(null===t||o>t)&&(t=o);let a=s(n.avg);null!==a&&(r+=a,i+=1)}a.push({t:u[0].t,min:e,max:t,avg:i>0?r/i:null,...u.length>1?{merged:!0}:{},...c?{gapBefore:!0}:{}}),u=[],c=!1};for(let e of n){if(!i(e)){m(),a.push({...e}),d=null;continue}let t=null!==d&&e.t>=d.t&&e.t-d.t<=1.5*o;u.length>0&&(!t||u.length>=l)&&m(),0===u.length&&(c=null!==d&&!t),u.push(e),d=e}return m(),a}function u(e){let t=null,r=null,i=0,n=0,l=null,o=null,a=null,u=null;for(let c of e){if(null===c.avg)continue;(null===a||c.t<a)&&(a=c.t),(null===u||c.t>u)&&(u=c.t);let e=s(c.min),d=s(c.max);null!==e&&(null===t||e<t)&&(t=e),null!==d&&(null===r||d>r)&&(r=d),null!==c.avg&&Number.isFinite(c.avg)&&(i+=c.avg,n+=1,l=c.avg,o=c.t)}return{count:n,min:t,max:r,avg:n>0?i/n:null,latest:l,latestT:o,firstT:a,lastT:u}}function c(e){if(!Number.isFinite(e)||e<=0)return 1;let t=Math.pow(10,Math.floor(Math.log10(e))),r=e/t;return(r<=1?1:r<=2?2:r<=5?5:10)*t}function d(e,t){if("percent"===e)return{min:0,max:100,ticks:[0,25,50,75,100]};let r=t.filter(e=>null!==e&&Number.isFinite(e));if(0===r.length)return{min:0,max:1,ticks:[0,1]};let i=Math.min(...r),s=Math.max(...r);if("celsius"===e){let e=Math.max(1,(s-i)*.1);i=5*Math.floor((i-e)/5),s=5*Math.ceil((s+e)/5)}else i=0,s=s>0?s:1;s<=i&&(s=i+1);let n=c((s-i)/4),l=Math.floor(i/n)*n,o=Math.ceil(s/n)*n,a=function(e,t,r=4){if(!Number.isFinite(e)||!Number.isFinite(t))return[0,1];if(t<=e)return[e];let i=c((t-e)/Math.max(1,r)),s=Math.ceil(e/i)*i,n=[];for(let e=s;e<=t+.001*i&&n.length<20;e+=i)n.push(Number(e.toPrecision(12)));return n.length>0?n:[e,t]}(l,o,4);return{min:l,max:o,ticks:a}}function m(e,t,r=4){let i=Math.max(2,Math.floor(r)),s=Math.max(0,t-e);return Array.from({length:i},(t,r)=>e+s*r/(i-1))}r.d(t,{$z:()=>n,Cf:()=>m,SG:()=>a,T6:()=>u,jl:()=>l,kk:()=>d,o:()=>o})},9429:(e,t,r)=>{r.d(t,{n:()=>l});var i=r(2115),s=r(5078);async function n(e){let t=null;try{let r=await e.json();if(null!==r&&"object"==typeof r&&"error"in r){let e=r.error;"string"==typeof e&&(t=e)}}catch{}switch(e.status){case 401:return{kind:"unauthorized",message:"Your session is no longer accepted."};case 403:return{kind:"denied",message:t??"You do not have access to this machine's history."};case 404:return{kind:"missing",message:t??"This machine is not available to the hub."};case 429:return{kind:"rate-limited",message:t??"The hub is limiting history requests."};case 503:return{kind:"unavailable",message:t??"History is temporarily unavailable."};default:return{kind:"invalid",message:t??`The hub could not answer this history query (${e.status}).`}}}function l({machineId:e,metricsKey:t,coreIdsKey:r,range:o,enabled:a=!0,autoRefresh:u=!0,refreshNonce:c=0}){let[d,m]=(0,i.useState)({machineId:e,metricsKey:t,coreIdsKey:r,range:o}),p=d.machineId===e&&d.range===o;(0,i.useEffect)(()=>{if(!p)return void m({machineId:e,metricsKey:t,coreIdsKey:r,range:o});let i=window.setTimeout(()=>m({machineId:e,metricsKey:t,coreIdsKey:r,range:o}),300);return()=>window.clearTimeout(i)},[e,t,r,o,p]);let f=p?d:{machineId:e,metricsKey:t,coreIdsKey:r,range:o},h=f.metricsKey,g=f.coreIdsKey,y=`${e}|${h}|${o}|${g??"all"}`,[b,x]=(0,i.useState)(null),[v,k]=(0,i.useState)(null),[w,M]=(0,i.useState)(null),$=(0,i.useRef)(c);return(0,i.useEffect)(()=>{let t=$.current!==c;if($.current=c,!a||!e||!h)return;let r=!0,i=!1,l=!1,d=-1/0,m=new AbortController,p=(0,s.zp)(o),f=async(t=!1)=>{if(r&&!i&&!l){i=!0,d=Date.now(),M({key:y,manual:t});try{let t=await fetch((0,s.Vw)(e,h.split(","),o,Date.now(),600,void 0===g?void 0:g.split(",").filter(Boolean)),{signal:"function"!=typeof AbortSignal.any||"function"!=typeof AbortSignal.timeout?m.signal:AbortSignal.any([m.signal,AbortSignal.timeout(2e4)]),cache:"no-store",headers:{Accept:"application/json"}});if(!t.ok)throw await n(t);let i=(0,s.bf)(await t.json());if(null===i||i.machineId!==e)throw{kind:"invalid",message:"Unexpected history response."};if(!r)return;x({key:y,range:o,result:i,loadedAt:Date.now()}),k(null)}catch(t){if(!r||m.signal.aborted)return;let e=null!==t&&"object"==typeof t&&"kind"in t&&"message"in t&&"string"==typeof t.message?t:{kind:"network",message:"Could not reach the hub. Try again."};l="rate-limited"===e.kind,["unauthorized","denied","missing"].includes(e.kind)&&x(null),k({key:y,error:e})}finally{i=!1,r&&M(null)}}},b=()=>{"visible"!==document.visibilityState||Date.now()-d<p||f()};f(t);let v=u?window.setInterval(b,p):null;return u&&document.addEventListener("visibilitychange",b),()=>{r=!1,m.abort(),null!==v&&window.clearInterval(v),document.removeEventListener("visibilitychange",b)}},[a,e,h,g,o,y,u,c]),{data:a&&b?.result.machineId===e&&b.range===o?b:null,error:a&&v?.key===y?v.error:null,loading:a&&w?.key===y,manualRefreshing:a&&w?.key===y&&w.manual}}}}]);
@@ -1,3 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[429],{1:(e,t,s)=>{"use strict";s.d(t,{PE:()=>o,UR:()=>d,kg:()=>l,uW:()=>c});let r=/^[\u0009\u000a\u000d ]*[=+\-@]/,n=/^[\u0009\u000a\u000d]/;function i(e){if(null==e)return"";if("number"==typeof e)return Number.isFinite(e)?String(e):"";if("boolean"==typeof e)return e?"true":"false";let t=0===e.length?e:r.test(e)||n.test(e)?`'${e}`:e;return/[",\t\r\n]/.test(t)?`"${t.replace(/"/g,'""')}"`:t}function a(e){return e.map(i).join(",")}function l(e){return`${e.map(a).join("\r\n")}\r
2
- `}function o(e,t,s){if("u"<typeof document)return;let r=new Blob([t],{type:s}),n=URL.createObjectURL(r),i=document.createElement("a");i.href=n,i.download=e,i.rel="noopener",i.style.display="none",document.body.append(i),i.click(),i.remove(),globalThis.setTimeout(()=>URL.revokeObjectURL(n),0)}let d="text/csv;charset=utf-8",c="application/json;charset=utf-8"},438:(e,t,s)=>{"use strict";s.d(t,{A:()=>r});let r=(0,s(8698).A)("Clock",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["polyline",{points:"12 6 12 12 16 14",key:"68esgv"}]])},2910:(e,t,s)=>{"use strict";s.d(t,{A:()=>r});let r=(0,s(8698).A)("Pause",[["rect",{x:"14",y:"4",width:"4",height:"16",rx:"1",key:"zuxfzm"}],["rect",{x:"6",y:"4",width:"4",height:"16",rx:"1",key:"1okwgv"}]])},6582:(e,t,s)=>{"use strict";s.d(t,{E:()=>f,x:()=>g});var r=s(5155),n=s(8500),i=s.n(n),a=s(828),l=s(6914),o=s(7029),d=s(438),c=s(7422),u=s(1735),m=s(3440),h=s(9939);function p(e){return(0,r.jsxs)("button",{type:"button",onClick:e.onClick,className:"inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-card-strong",children:[(0,r.jsx)(a.A,{className:"h-3.5 w-3.5","aria-hidden":!0}),e.children]})}function x(e){return(0,r.jsx)(i(),{href:e.href,className:e.primary?"inline-flex items-center gap-1.5 rounded-md bg-accent px-3 py-1.5 text-xs font-medium text-accent-foreground transition-colors hover:bg-accent/90":"inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-card-strong",children:e.children})}function g(){let{session:e,phase:t,retryConnection:s}=(0,h.M)();switch(e.kind){case"restoring":return(0,r.jsx)(m.Z,{title:"Checking session",className:"mx-auto my-12 max-w-md",children:(0,r.jsx)(m.p,{icon:l.A,note:"Checking your session…"})});case"restore-failed":return(0,r.jsxs)(m.Z,{title:"Hub unreachable",className:"mx-auto my-12 max-w-md",children:[(0,r.jsx)(m.p,{icon:o.A,note:"The hub is unreachable right now."}),(0,r.jsx)("div",{className:"flex justify-center",children:(0,r.jsx)(p,{onClick:s,children:"Check again"})})]});case"signed-out":if("expired"===t)return(0,r.jsxs)(m.Z,{title:"Session ended",className:"mx-auto my-12 max-w-md",children:[(0,r.jsx)(m.p,{icon:d.A,note:"Your session ended."}),(0,r.jsx)("div",{className:"flex justify-center",children:(0,r.jsx)(x,{href:"/login",primary:!0,children:"Sign in"})})]});return(0,r.jsxs)(m.Z,{title:"Sign in required",className:"mx-auto my-12 max-w-md",children:[(0,r.jsx)(m.p,{icon:l.A,note:"Sign in required."}),(0,r.jsx)("div",{className:"flex justify-center",children:(0,r.jsx)(x,{href:"/login",primary:!0,children:"Sign in"})})]});case"auth-unavailable":return(0,r.jsx)(m.Z,{title:"Sign-in unavailable",className:"mx-auto my-12 max-w-md",children:(0,r.jsx)(m.p,{icon:c.A,note:"Browser sign-in is not configured on this hub."})})}return"expired"===t?(0,r.jsxs)(m.Z,{title:"Session ended",className:"mx-auto my-12 max-w-md",children:[(0,r.jsx)(m.p,{icon:d.A,note:"Your session ended."}),(0,r.jsx)("div",{className:"flex justify-center",children:(0,r.jsx)(x,{href:"/login",primary:!0,children:"Sign in"})})]}):"no-permission"===t?(0,r.jsxs)(m.Z,{title:"No permission",className:"mx-auto my-12 max-w-md",children:[(0,r.jsx)(m.p,{icon:c.A,note:`You are signed in as ${e.user.username}, but this hub grants no machine view to this account.`}),(0,r.jsx)("div",{className:"flex justify-center",children:(0,r.jsx)(p,{onClick:s,children:"Check again"})})]}):null}function f(){let{phase:e,retryConnection:t}=(0,h.M)();return"reconnecting"!==e&&"disconnected"!==e&&"connecting"!==e?null:"connecting"===e?(0,r.jsxs)("div",{role:"status",className:"mb-5 flex items-center gap-2 rounded-lg border border-border bg-card px-4 py-2.5 text-xs text-muted-foreground",children:[(0,r.jsx)(a.A,{className:"h-3.5 w-3.5 shrink-0","aria-hidden":!0}),"Connecting to the live feed — waiting for the first snapshot."]}):(0,r.jsxs)("div",{role:"status",className:"mb-5 flex flex-wrap items-center gap-x-3 gap-y-2 rounded-lg border border-border bg-card px-4 py-2.5 text-xs text-muted-foreground",children:[(0,r.jsx)(u.A,{className:"h-3.5 w-3.5 shrink-0 text-warn","aria-hidden":!0}),(0,r.jsxs)("span",{children:["Connection lost — values below are ",(0,r.jsx)("strong",{className:"font-medium text-foreground",children:"last known"}),", not live measurements","reconnecting"===e?" — retrying with backoff…":" — retries stopped."]}),"disconnected"===e?(0,r.jsx)(p,{onClick:t,children:"Retry now"}):null]})}},7148:(e,t,s)=>{Promise.resolve().then(s.bind(s,8250)),Promise.resolve().then(s.bind(s,1721)),Promise.resolve().then(s.bind(s,2701)),Promise.resolve().then(s.bind(s,2394))},7499:(e,t,s)=>{"use strict";function r(e,t,s,r){return`rigscope-${e}-${function(e,t="machine"){let s=e.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,48).replace(/-+$/g,"");return s.length>0?s:t}(t)}-${!Number.isFinite(s)?"unknown-time":new Date(s).toISOString().replace(/[-:]/g,"").replace(/\.\d{3}Z$/,"Z")}.${r}`}s.d(t,{Y8:()=>r})},8250:(e,t,s)=>{"use strict";s.d(t,{HistoryView:()=>eM});var r=s(5155),n=s(8500),i=s.n(n),a=s(2115),l=s(7422),o=s(3896),d=s(1735),c=s(7029),u=s(828),m=s(4173),h=s(3440),p=s(940),x=s(802),g=s(6582),f=s(9939),b=s(8664),y=s(4567),j=s(592);let N=j.U8,v=/^core:(\d+)$/;function w(e){let t=v.exec(e);if(null===t)return null;let s=Number(t[1]);return!Number.isSafeInteger(s)||s<0||s>=j.U8?null:s}function k(e){return[...new Set(e)].sort((e,t)=>(w(e)??0)-(w(t)??0))}function M(e,t=[]){var s;let r=e?.metrics?.payload.cpu,n=new Set(!Number.isFinite(s=Math.max(e?.inventory?.cpu.logicalCores??0,r?.status==="ok"?r.perCore.length:0))?[]:Array.from({length:Math.min(j.U8,Math.max(0,Math.floor(s)))},(e,t)=>`core:${t}`));for(let e of t)"cpu.core"===e.metric&&null!==w(e.resourceId)&&n.add(e.resourceId);return k([...n])}function $(e,t){let s=new Set(t);if(null===e)return k(t).slice(0,N);let r=[];for(let t of e)if(s.has(t)&&null!==w(t)&&(r.push(t),r.length>=N))break;return k(r)}function C(e){let t=w(e);return null===t?e:`Core ${t}`}var A=s(5078),S=s(2910),I=s(9942),P=s(8698);let U=(0,P.A)("ChevronDown",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]),R=(0,P.A)("Check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);var L=s(6114);let _=Object.freeze([]),T=new Set(y.H9.map(e=>e.metric)),B=e=>"boolean"==typeof e?e:null,z=e=>Array.isArray(e)&&e.every(e=>"string"==typeof e)?e.slice(0,1e3):null,E=e=>A.pI.some(t=>t.id===e)?e:null,O=e=>"string"==typeof e&&(""===e||e.split(",").every(e=>T.has(e)))?e:null,Z=/^core:\d+$/,H=e=>Array.isArray(e)&&e.every(e=>"string"==typeof e&&Z.test(e))?[...new Set(e)].slice(0,j.U8):null;function D(e,t){return(0,L.u)(`history.hidden.${t}.${e}`,_,z)}function G(e){return(0,L.u)(`history.cores.${e}`,null,H)}let q=e=>"bytes"===e||"percent"===e?e:null;function F(e,t){return(0,L.u)(`history.units.${t}.${e}`,"bytes",q)}let V="peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:[outline-color:var(--focus)]";function W({label:e,action:t}){return(0,r.jsxs)("div",{className:"flex min-w-0 items-center gap-2.5",children:[(0,r.jsx)("span",{className:"text-xs text-muted-foreground",children:e}),(0,r.jsx)("span",{"aria-hidden":!0,className:"h-px min-w-0 flex-1 bg-border"}),t]})}let Y="inline-flex min-h-8 items-center gap-1.5 rounded-md border border-transparent px-2.5 text-xs transition-colors",J=`${Y} ${V} bg-selected text-foreground`,K=`${Y} ${V} bg-card-strong text-muted-foreground hover:text-foreground`;function Q(e){let{machine:t,range:s,selectedMetrics:n,catalog:i,catalogError:a,gpuCards:l,hiddenCards:o,autoRefresh:d,loading:c,manualRefreshing:m,statusText:h,onRangeChange:p,onToggleMetric:x,onSetMetrics:g,onToggleCard:f,onToggleAutoRefresh:b,onRefresh:j}=e,[N,v]=(0,L.u)("history.controlsOpen",!1,B,"session"),w=new Set(n),k=y.H9.filter(({metric:e})=>(0,y.yv)(t,e).available&&(null===i||void 0!==i[e])).map(({metric:e})=>e),P=new Set(k),_=(e,t)=>{let s=new Set(n);for(let r of e)t&&P.has(r)?s.add(r):t||s.delete(r);g([...s])},T=n.some(e=>e.startsWith("gpu.")),z=w.has("cpu.core"),[E,O]=G(t?.machineId??""),Z=z?M(t):[],H=$(E,Z),D=new Set(H);return(0,r.jsxs)("section",{"aria-labelledby":"history-query-heading","aria-busy":c,className:"mb-5 min-w-0 rounded-xl border border-border bg-card",children:[(0,r.jsx)("h2",{id:"history-query-heading",className:"sr-only",children:"History query"}),(0,r.jsxs)("div",{className:"flex flex-wrap items-end gap-x-5 gap-y-4 p-4 md:p-5",children:[(0,r.jsxs)("fieldset",{className:"flex min-w-0 flex-col gap-1.5",children:[(0,r.jsx)("legend",{className:"mb-1.5 text-xs text-muted-foreground",children:"Time range"}),(0,r.jsx)("div",{className:"inline-flex flex-wrap rounded-lg border border-border bg-background p-0.5",children:A.pI.map(e=>{let t=s===e.id;return(0,r.jsxs)("label",{className:"cursor-pointer",children:[(0,r.jsx)("input",{type:"radio",name:"history-range",value:e.id,checked:t,onChange:()=>p(e.id),className:"peer sr-only"}),(0,r.jsxs)("span",{className:`inline-flex min-h-8 items-center rounded-md px-2.5 text-xs transition-colors ${V} ${t?"bg-selected font-medium text-foreground":"text-muted-foreground hover:text-foreground"}`,children:[e.shortLabel,(0,r.jsxs)("span",{className:"sr-only",children:[" — ",e.label]})]})]},e.id)})})]}),(0,r.jsxs)("div",{className:"flex min-w-0 flex-wrap items-center gap-2 sm:ml-auto",children:[(0,r.jsx)("p",{className:"order-first w-full text-xs text-muted-foreground sm:order-none sm:w-auto",children:h}),(0,r.jsxs)("button",{type:"button",onClick:j,disabled:m,className:"inline-flex min-h-8 items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-xs text-foreground transition-colors hover:bg-card-strong disabled:opacity-60",children:[(0,r.jsx)(u.A,{className:`h-3.5 w-3.5 ${m?"animate-spin":""}`,"aria-hidden":!0}),"Refresh"]}),(0,r.jsxs)("button",{type:"button",onClick:b,"aria-pressed":d,className:`inline-flex min-h-8 items-center gap-1.5 rounded-md border px-2.5 text-xs transition-colors ${d?"border-accent/40 bg-selected text-foreground":"border-border bg-background text-muted-foreground hover:bg-card-strong hover:text-foreground"}`,children:[d?(0,r.jsx)(S.A,{className:"h-3.5 w-3.5","aria-hidden":!0}):(0,r.jsx)(I.A,{className:"h-3.5 w-3.5","aria-hidden":!0}),d?"Pause":"Resume"]})]})]}),(0,r.jsxs)("div",{className:"border-t border-border px-4 py-4 md:px-5",children:[(0,r.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,r.jsxs)("button",{type:"button","aria-expanded":N,"aria-controls":"history-metric-options",onClick:()=>v(!N),className:"inline-flex min-h-8 items-center gap-1.5 rounded-md text-sm font-medium",children:["Metrics ",(0,r.jsxs)("span",{className:"tnum text-xs font-normal text-muted-foreground",children:[w.size," selected"]}),(0,r.jsx)(U,{"aria-hidden":!0,className:`h-3.5 w-3.5 text-muted-foreground transition-transform ${N?"rotate-180":""}`})]}),(0,r.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,r.jsx)("button",{type:"button",onClick:()=>_(k,!0),disabled:k.every(e=>w.has(e)),className:"inline-flex min-h-8 items-center rounded-md border border-border bg-background px-2.5 text-xs text-foreground transition-colors hover:bg-card-strong disabled:opacity-50",children:"Select all"}),(0,r.jsx)("button",{type:"button",onClick:()=>g([]),disabled:0===w.size,className:"inline-flex min-h-8 items-center rounded-md border border-border bg-background px-2.5 text-xs text-foreground transition-colors hover:bg-card-strong disabled:opacity-50",children:"Unselect all"})]})]}),(0,r.jsx)("div",{id:"history-metric-options",hidden:!N,children:(0,r.jsxs)("div",{className:"mt-4 min-w-0 md:col-span-2",children:[(0,r.jsx)("div",{className:"min-w-0",children:(0,r.jsx)("div",{className:"grid gap-x-6 gap-y-5 md:grid-cols-2 xl:grid-cols-3",children:y.P$.map(e=>(0,r.jsxs)("fieldset",{className:`min-w-0 ${"disk"===e.id?"xl:col-span-2":""}`,children:[(0,r.jsx)("legend",{className:"sr-only",children:e.label}),(0,r.jsx)(W,{label:e.label,action:(0,r.jsxs)("div",{className:"flex shrink-0 gap-2",children:[(0,r.jsx)("button",{type:"button","aria-label":`Select all ${e.label} metrics`,onClick:()=>_(e.metrics,!0),disabled:e.metrics.filter(e=>P.has(e)).every(e=>w.has(e)),className:"min-h-6 rounded-sm text-xs text-muted-foreground hover:text-foreground hover:underline disabled:opacity-50",children:"All"}),(0,r.jsx)("button",{type:"button","aria-label":`Unselect all ${e.label} metrics`,onClick:()=>_(e.metrics,!1),disabled:!e.metrics.some(e=>w.has(e)),className:"min-h-6 rounded-sm text-xs text-muted-foreground hover:text-foreground hover:underline disabled:opacity-50",children:"None"})]})}),(0,r.jsx)("div",{className:"mt-2 flex flex-wrap gap-1.5",children:e.metrics.map(e=>{var s;let n=(0,y.oB)(e);if(null===n)return null;let a=(0,y.yv)(t,e),l=null===i||void 0!==i[e],o=a.available&&l,d=w.has(e),c=(0,y.Lf)(n,0);return(0,r.jsxs)("label",{className:o?"cursor-pointer":"cursor-not-allowed",title:a.available?l?n.description:"This hub does not record this metric.":a.reason??void 0,children:[(0,r.jsx)("input",{type:"checkbox",checked:d,onChange:()=>x(e),disabled:!o&&!d,className:"peer sr-only","aria-label":n.label}),(0,r.jsxs)("span",{className:`${!o?d?`${Y} ${V} bg-card-strong text-muted-foreground line-through`:`${Y} text-muted-foreground opacity-50`:d?J:K}`,children:[(0,r.jsx)("span",{"aria-hidden":!0,className:"flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-sm border border-current",style:{color:c.color},children:d?(0,r.jsx)(R,{className:"h-3 w-3",strokeWidth:3}):null}),(s=n.label,({"cpu.usage":"Usage","cpu.core":"Per-core","cpu.iowait":"I/O wait","cpu.pressure":"Pressure","cpu.temperature":"Temperature","cpu.power":"Package power","memory.used":"Used bytes","memory.usage":"Usage %","swap.used":"Swap","memory.pressure.some":"Pressure (some)","memory.pressure.full":"Pressure (full)","gpu.utilization":"Utilization","gpu.memory.used":"VRAM","gpu.temperature":"Temperature","gpu.power":"Power","fs.used":"Space used","fs.usage":"Capacity %","fs.inodes.usage":"Inodes %","net.rx":"Received","net.tx":"Sent"})[e]??s)]})]},e)})}),"gpu"===e.id&&T&&l.length>0?(0,r.jsxs)("fieldset",{className:"mt-4 border-t border-border pt-3",children:[(0,r.jsx)("legend",{className:"sr-only",children:"GPU cards"}),(0,r.jsx)(W,{label:"GPU cards"}),(0,r.jsx)("div",{className:"mt-1.5 flex flex-wrap gap-1.5",children:l.map((e,t)=>{let s=e.id,n=!o.has(s);return(0,r.jsxs)("label",{className:"cursor-pointer",children:[(0,r.jsx)("input",{type:"checkbox",checked:n,onChange:()=>f(s),className:"peer sr-only"}),(0,r.jsxs)("span",{className:n?J:K,children:[(0,r.jsx)("span",{className:"tnum text-xs text-muted-foreground",children:t+1}),e.label]})]},e.id)})})]}):null,"cpu"===e.id&&z?(0,r.jsxs)("fieldset",{className:"mt-4 border-t border-border pt-3",children:[(0,r.jsx)("legend",{className:"sr-only",children:"CPU cores"}),(0,r.jsx)(W,{label:`CPU cores \xb7 ${H.length} / ${Z.length}`,action:(0,r.jsxs)("div",{className:"flex shrink-0 gap-2",children:[(0,r.jsx)("button",{type:"button",onClick:()=>O(null),disabled:H.length===Z.length,className:"min-h-6 rounded-sm text-xs text-muted-foreground hover:text-foreground disabled:opacity-50",children:"All cores"}),(0,r.jsx)("button",{type:"button",onClick:()=>O([]),disabled:0===H.length,"aria-label":"Unselect all CPU cores",className:"min-h-6 rounded-sm text-xs text-muted-foreground hover:text-foreground disabled:opacity-50",children:"None"})]})}),0===Z.length?(0,r.jsx)("p",{className:"mt-2 text-xs text-muted-foreground",children:"Core count unavailable."}):(0,r.jsxs)("details",{className:"mt-2",children:[(0,r.jsxs)("summary",{className:"inline-flex min-h-8 cursor-pointer items-center gap-1 rounded-md text-xs text-muted-foreground hover:text-foreground",children:["Choose cores ",(0,r.jsx)(U,{className:"h-3.5 w-3.5","aria-hidden":!0})]}),(0,r.jsx)("div",{className:"mt-2 grid max-h-48 grid-cols-3 gap-1.5 overflow-y-auto p-1",children:Z.map(e=>{let t=D.has(e);return(0,r.jsxs)("label",{className:"min-w-0 cursor-pointer",children:[(0,r.jsx)("input",{type:"checkbox",checked:t,onChange:()=>{var s;return s=!t,void O(t=>{let r=$(t,Z);return s?r.includes(e)?t:[...r,e]:r.filter(t=>t!==e)})},className:"peer sr-only"}),(0,r.jsxs)("span",{className:`${t?J:K} w-full px-1.5`,children:[(0,r.jsx)("span",{"aria-hidden":!0,className:"flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-sm border border-current",children:t?(0,r.jsx)(R,{className:"h-3 w-3"}):null}),C(e)]})]},e)})})]})]}):null]},e.id))})}),a?(0,r.jsx)("p",{className:"mt-2 text-xs text-muted-foreground",children:a}):null]})})]})]})}var X=s(9429),ee=s(7726),et=s(7284);let es="grid grid-cols-[3rem_minmax(0,1fr)_2.5rem] items-center gap-2 sm:grid-cols-[3.5rem_minmax(0,1fr)_3rem_3rem]";function er({title:e,series:t,fromMs:s,toMs:n,gaps:i,hiddenKeys:l,onToggleSeries:o}){let[d,c]=(0,a.useState)(!1),u=t.map(e=>({...e,stats:(0,ee.T6)(e.points)}));d&&u.sort((e,t)=>(t.stats.max??-1)-(e.stats.max??-1));let m=u.filter(e=>!l.has(e.key)).reduce((e,t)=>null!==t.stats.max&&(e?.stats.max===null||null===e||t.stats.max>e.stats.max)?t:e,null),h=Math.max(1,n-s),p=(0,ee.$z)(i,s,n);return(0,r.jsxs)("figure",{className:"min-w-0 lg:col-span-full",children:[(0,r.jsxs)("div",{className:"mb-3 flex flex-wrap items-center justify-between gap-2",children:[(0,r.jsx)("h3",{className:"text-xs font-medium text-foreground",children:e}),(0,r.jsxs)("div",{className:"flex flex-wrap items-center gap-3 text-xs",children:[m?(0,r.jsxs)("span",{className:"tnum text-muted-foreground",children:["Peak \xb7 ",m.label," ",(0,r.jsx)("span",{className:"text-foreground",children:(0,A.dd)(m.stats.max,"percent")})]}):null,(0,r.jsx)("button",{type:"button","aria-pressed":d,onClick:()=>c(!d),className:`min-h-8 rounded-md border border-border px-2 ${d?"bg-selected text-foreground":"bg-background text-muted-foreground hover:text-foreground"}`,children:"Busiest first"})]})]}),(0,r.jsxs)("div",{className:`${es} mb-1 text-xs text-muted-foreground`,"aria-hidden":!0,children:[(0,r.jsx)("span",{children:"Core"}),(0,r.jsxs)("span",{children:[(0,r.jsx)("span",{className:"sm:hidden",children:"History"}),(0,r.jsx)("span",{className:"hidden sm:inline",children:"Peak usage over time"})]}),(0,r.jsx)("span",{className:"hidden text-right sm:block",children:"Last"}),(0,r.jsx)("span",{className:"text-right",children:"Peak"})]}),(0,r.jsx)("div",{role:"region","aria-label":"Per-core history rows",tabIndex:0,className:"max-h-96 overflow-y-auto rounded-md",children:0===u.length?(0,r.jsx)("p",{className:"py-8 text-center text-xs text-muted-foreground",children:"No stored per-core readings."}):u.map(e=>{let t=!l.has(e.key),i=Array(10).fill("");return(function(e,t,s,r=120){let n=Array(r).fill(null),i=Math.max(1,s-t);for(let a of e){if(a.t<t||a.t>s)continue;let e=a.max??a.avg;if(null===e||!Number.isFinite(e))continue;let l=Math.min(r-1,Math.floor((a.t-t)/i*r));n[l]=Math.max(n[l]??0,Math.min(100,Math.max(0,e)))}return n})(e.points,s,n,120).forEach((e,t)=>{if(null===e)return;let s=Math.min(9,Math.floor(e/10));i[s]+=`M${t},1h1v16h-1z`}),(0,r.jsxs)("div",{className:`${es} min-h-7 border-b border-border/40 text-xs`,children:[(0,r.jsxs)("label",{className:"inline-flex min-h-7 cursor-pointer items-center rounded-sm",children:[(0,r.jsx)("input",{type:"checkbox",checked:t,onChange:()=>o(e.key),className:"peer sr-only"}),(0,r.jsx)("span",{className:`${t?"text-foreground":"text-muted-foreground line-through"} rounded-sm peer-focus-visible:outline-2 peer-focus-visible:outline-accent`,children:e.label})]}),(0,r.jsxs)("svg",{viewBox:"0 0 120 18",preserveAspectRatio:"none",role:"img","aria-label":`${e.label}: latest ${(0,A.dd)(e.stats.latest,"percent")}, peak ${(0,A.dd)(e.stats.max,"percent")}${t?"":", hidden"}`,className:`h-5 w-full ${t?"":"opacity-20"}`,children:[(0,r.jsxs)("title",{children:[e.label," \xb7 Last ",(0,A.dd)(e.stats.latest,"percent")," \xb7 Peak ",(0,A.dd)(e.stats.max,"percent")]}),t?i.map((e,t)=>e?(0,r.jsx)("path",{d:e,fill:t<5?"var(--cpu)":t<8?"var(--warn)":"var(--crit)",opacity:t<5?.15+.17*t:.65+t%5*.07},t):null):null,p.map(e=>(0,r.jsx)("rect",{x:(e.fromMs-s)/h*120,width:(e.toMs-e.fromMs)/h*120,y:0,height:18,fill:"var(--card)"},`${e.fromMs}-${e.toMs}`))]}),(0,r.jsx)("span",{className:"tnum hidden text-right text-muted-foreground sm:block",children:t?(0,A.dd)(e.stats.latest,"percent"):"—"}),(0,r.jsx)("span",{className:`tnum text-right ${t&&(e.stats.max??0)>=80?"text-crit":"text-muted-foreground"}`,children:t?(0,A.dd)(e.stats.max,"percent"):"—"})]},e.key)})}),(0,r.jsxs)("div",{className:`${es} mt-2 text-xs text-muted-foreground`,"aria-hidden":!0,children:[(0,r.jsx)("span",{}),(0,r.jsx)("div",{className:"flex justify-between gap-2 tnum",children:(0,ee.Cf)(s,n,3).map((e,t)=>(0,r.jsx)("span",{className:1===t?"hidden sm:inline":"",children:(0,A.O5)(e,h)},e))}),(0,r.jsx)("span",{className:"hidden sm:block"}),(0,r.jsx)("span",{})]}),(0,r.jsxs)("div",{className:"mt-3 flex flex-wrap items-center gap-3 text-xs text-muted-foreground",children:[[{label:"0–49%",color:"var(--cpu)"},{label:"50–79%",color:"var(--warn)"},{label:"80–100%",color:"var(--crit)"}].map(e=>(0,r.jsxs)("span",{className:"inline-flex items-center gap-1.5",children:[(0,r.jsx)("span",{"aria-hidden":!0,className:"h-2 w-4 rounded-sm",style:{backgroundColor:e.color}}),e.label]},e.label)),(0,r.jsx)("span",{children:"No fill \xb7 no reading"})]})]})}function en(e,t){return`${e}\0${t}`}function ei(e,t,s,r,n){let i=(0,y.oB)(s);return null===i?[]:e.series.filter(e=>e.metric===s&&(void 0===r||e.resourceId===r)).map((e,r)=>{let a=(0,y.Lf)(i,r),l=n?.(e,i,r)??(0,y.bP)(t,s,e.resourceId);return{key:en(e.metric,e.resourceId),label:l,metric:e.metric,resourceId:e.resourceId,color:a.color,dash:a.dash,points:e.points}})}function ea(e){let{machine:t,result:s,selectedMetrics:n,hiddenCards:i,hiddenSeries:a,onToggleSeries:l}=e,[o]=G(t.machineId),d=$(o,M(t,s.series)),c=function(e){let{machine:t,result:s,selectedMetrics:r,hiddenCards:n,coreIds:i}=e,a=new Set(r),l=[];if(["cpu.usage","cpu.core","cpu.temperature","cpu.power","cpu.iowait","cpu.pressure"].filter(e=>a.has(e)).length>0){let e=[],r=["cpu.usage","cpu.iowait","cpu.pressure"].filter(e=>a.has(e));if(r.length>0&&e.push({key:"cpu.usage",title:r.length>1?"Usage & stalls":(0,y.oB)(r[0]).label,unit:"percent",series:r.flatMap(e=>ei(s,t,e,void 0,(t,s)=>"cpu.pressure"===e?"Pressure (some)":s.shortLabel)),emptyMessage:"No stored CPU readings in this range."}),a.has("cpu.core")){let r=(0,y.oB)("cpu.core"),n=M(t,s.series),a=i??$(null,n),l=function(e,t){let s=(0,y.oB)("cpu.core");if(null===s)return[];let r=new Map(e.series.filter(e=>"cpu.core"===e.metric).map(e=>[e.resourceId,e]));return t.flatMap((e,t)=>{let n=r.get(e),i=(0,y.Lf)(s,t);return[{key:en("cpu.core",e),label:C(e),metric:"cpu.core",resourceId:e,color:i.color,dash:i.dash,points:n?.points??[]}]})}(s,a),o=n.length>a.length;e.push({key:"cpu.core",title:o?`Per-core usage \xb7 ${a.length} of ${n.length}`:"Per-core usage",unit:r.unit,series:l,emptyMessage:0===n.length?"No stored per-core readings in this range.":0===a.length?"No CPU cores are selected. Choose cores under Metrics.":"No stored per-core readings for the selected cores in this range."})}if(a.has("cpu.temperature")){let r=(0,y.oB)("cpu.temperature");e.push({key:"cpu.temperature",title:"Temperature",unit:r.unit,series:ei(s,t,"cpu.temperature"),emptyMessage:"No stored CPU temperature readings in this range."})}if(a.has("cpu.power")){let r=(0,y.oB)("cpu.power");e.push({key:"cpu.power",title:"Package power",unit:r.unit,series:ei(s,t,"cpu.power"),emptyMessage:"No stored CPU package power readings in this range."})}l.push({key:"cpu",title:"CPU",charts:e})}if(["memory.used","memory.usage","memory.pressure.some","memory.pressure.full","swap.used"].filter(e=>a.has(e)).length>0){let e=[],r=["memory.used","memory.usage"].filter(e=>a.has(e));if(r.length>0){let n=r.map(e=>({unit:(0,y.oB)(e).unit,series:ei(s,t,e,void 0,()=>"RAM")}));e.push({key:"memory.capacity",title:"RAM",...n[0],unitGroup:"memory",views:n,emptyMessage:"No stored memory readings in this range."})}a.has("swap.used")&&e.push({key:"swap.used",title:"Swap",unit:"bytes",series:ei(s,t,"swap.used"),emptyMessage:"No stored swap readings in this range."});let n=["memory.pressure.some","memory.pressure.full"].filter(e=>a.has(e));if(n.length>0){let r=(0,y.oB)(n[0]),i=n.flatMap(e=>ei(s,t,e,void 0,(t,s)=>"memory.pressure.some"===e?"Some":"memory.pressure.full"===e?"Full":s.shortLabel));e.push({key:"memory.pressure",title:"Memory pressure",unit:r.unit,series:i,emptyMessage:"No stored memory pressure in this range."})}l.push({key:"memory",title:"Memory",charts:e})}let o=["gpu.utilization","gpu.memory.used","gpu.temperature","gpu.power"].filter(e=>a.has(e));if(o.length>0){let e=(0,y.ue)(t,s.series),r=e.filter(e=>!n.has(e.id));for(let n of(0===r.length&&l.push({key:"gpu-empty",title:"GPU",charts:[{key:"gpu-empty",title:"Per-card history",unit:"percent",series:[],emptyMessage:e.length>0?"All GPU cards are hidden. Re-enable a card under Metrics to see its panels.":"No supported GPU cards or stored GPU history in this range."}]}),r)){let e=o.map(e=>{let r=(0,y.oB)(e),i=function(e,t,s,r){return ei(e,t,s,r,(e,t)=>"gpu.utilization"===s?"Utilization":"gpu.memory.used"===s?"VRAM used":t.shortLabel).map(e=>({...e}))}(s,t,e,n.id),a="gpu.memory.used"===e&&null!==n.totalBytes?`of ${(0,A.dd)(n.totalBytes,"bytes")}`:void 0;return{key:`${n.id}-${e}`,title:r.shortLabel,unit:r.unit,series:i,emptyMessage:`No stored ${r.shortLabel.toLowerCase()} readings for this card in this range.`,note:a}});l.push({key:`gpu-${n.id}`,title:`GPU ${n.index+1}${n.label?` \xb7 ${n.label}`:""}`,charts:e})}}if(["fs.used","fs.usage","fs.inodes.usage"].filter(e=>a.has(e)).length>0){let e=[],r=["fs.used","fs.usage"].filter(e=>a.has(e));if(r.length>0){let n=r.map(e=>({unit:(0,y.oB)(e).unit,series:ei(s,t,e)}));e.push({key:"fs.capacity",title:"Capacity used",...n[0],unitGroup:"filesystem",views:n,emptyMessage:"No stored filesystem usage in this range."})}if(a.has("fs.inodes.usage")){let r=(0,y.oB)("fs.inodes.usage");e.push({key:"fs.inodes.usage",title:"Inodes used",unit:r.unit,series:ei(s,t,"fs.inodes.usage"),emptyMessage:"No stored inode usage in this range."})}l.push({key:"filesystems",title:"Filesystems",charts:e})}let d=["disk.read","disk.write"].filter(e=>a.has(e));if(d.length>0){let e=d.flatMap(e=>{let r=(0,y.oB)(e);return ei(s,t,e,void 0,s=>`${(0,y.bP)(t,e,s.resourceId)} ${r.shortLabel.toLowerCase()}`)});l.push({key:"disk",title:"Disk throughput",charts:[{key:"disk",title:"Read and write",unit:"bytes_per_second",series:e,emptyMessage:"No stored disk throughput in this range."}]})}let c=["disk.read.latency","disk.write.latency"].filter(e=>a.has(e)),u=["io.pressure.some","io.pressure.full"].filter(e=>a.has(e));if(c.length>0||u.length>0||a.has("disk.utilization")){let e=[];if(c.length>0){let r=c.flatMap(e=>{let r=(0,y.oB)(e);return ei(s,t,e,void 0,s=>`${(0,y.bP)(t,e,s.resourceId)} ${r.shortLabel.toLowerCase()}`)}),n=(0,y.oB)(c[0]);e.push({key:"disk.latency",title:"Latency",unit:n.unit,series:r,emptyMessage:"No stored disk latency in this range."})}if(a.has("disk.utilization")){let r=(0,y.oB)("disk.utilization");e.push({key:"disk.utilization",title:"Utilization",unit:r.unit,series:ei(s,t,"disk.utilization"),emptyMessage:"No stored disk utilization in this range."})}if(u.length>0){let r=(0,y.oB)(u[0]),n=u.flatMap(e=>ei(s,t,e,void 0,(t,s)=>"io.pressure.some"===e?"Some":"io.pressure.full"===e?"Full":s.shortLabel));e.push({key:"io.pressure",title:"I/O pressure",unit:r.unit,series:n,emptyMessage:"No stored I/O pressure in this range."})}l.push({key:"disk-health",title:"Disk health",charts:e})}let m=["net.rx","net.tx"].filter(e=>a.has(e));if(m.length>0){let e=m.flatMap(e=>{let r=(0,y.oB)(e);return ei(s,t,e,void 0,s=>`${(0,y.bP)(t,e,s.resourceId)} ${r.shortLabel.toLowerCase()}`)});l.push({key:"network",title:"Network throughput",charts:[{key:"network",title:"Received and sent",unit:"bytes_per_second",series:e,emptyMessage:"No stored network throughput in this range."}]})}return l}({machine:t,result:s,selectedMetrics:n,hiddenCards:i,coreIds:d});return(0,r.jsx)("div",{className:"grid grid-cols-1 gap-5",children:c.map(n=>{let i=n.charts.find(e=>"cpu.core"===e.key&&e.series.length>4),o=i?[...n.charts.filter(e=>e!==i),i]:n.charts,d=i&&4===o.length?"grid gap-6 lg:grid-cols-2 xl:grid-cols-3":o.length>1&&!(i&&2===o.length)?"grid gap-6 lg:grid-cols-2":"flex flex-col gap-6";return(0,r.jsx)(h.Z,{title:n.title,children:(0,r.jsx)("div",{className:d,children:o.map((n,d)=>{let c=n.unitGroup,u=c?e.capacityUnits[c]:void 0,m=n.views?.find(e=>e.unit===u)??n.views?.[0]??n,h=n===i||!i&&o.length%2==1&&d===o.length-1;return"cpu.core"===n.key&&n.series.length>8?(0,r.jsx)(er,{title:n.title,series:n.series,fromMs:s.fromMs,toMs:s.toMs,gaps:s.gaps,hiddenKeys:a,onToggleSeries:l},n.key):(0,r.jsx)(et.t,{title:n.title,unit:m.unit,series:m.series,fromMs:s.fromMs,toMs:s.toMs,stepMs:(0,ee.jl)(s.stepMs,s.tier,t.expectedIntervalMs),gaps:s.gaps,hiddenKeys:a,onToggleSeries:l,emptyMessage:n.emptyMessage,note:n.note,action:c&&n.views&&n.views.length>1?(0,r.jsx)("div",{role:"group","aria-label":`${n.title} units`,className:"inline-flex rounded-md border border-border bg-background p-0.5",children:n.views.map(t=>(0,r.jsx)("button",{type:"button","aria-pressed":t.unit===m.unit,onClick:()=>e.onCapacityUnitChange(c,t.unit),className:`min-h-7 rounded px-2 text-xs transition-colors ${t.unit===m.unit?"bg-selected text-foreground":"text-muted-foreground hover:text-foreground"}`,children:"bytes"===t.unit?"Bytes":"%"},t.unit))}):void 0,maxDrawPoints:"cpu.core"===n.key?150:void 0,className:h?"lg:col-span-full":void 0},n.key)})})},n.key)})})}var el=s(1),eo=s(7499);let ed={raw:"raw samples","1m":"1-minute rollups","1h":"1-hour rollups"};function ec(e){return e.displayName?.trim()||e.hostname.trim()||e.machineId}function eu(e,t){return`${e}\0${t}`}function em(e){let t=new Set(e.selectedMetrics),s=new Set((0,y.ue)(e.machine,e.result.series).filter(t=>!e.hiddenCards.has(t.id)).map(e=>e.id));return e.result.series.filter(r=>!(!t.has(r.metric)||e.hiddenSeries.has(eu(r.metric,r.resourceId))||"cpu.core"===r.metric&&void 0!==e.coreIds&&!e.coreIds.includes(r.resourceId)||r.metric.startsWith("gpu.")&&""!==r.resourceId&&!s.has(r.resourceId)))}function eh(e){return new Date(e).toISOString()}function ep(e){return(0,y.oB)(e)?.label??e}function ex(e){return em(e).map(t=>({metric:t.metric,label:ep(t.metric),resourceId:t.resourceId,resourceLabel:(0,y.bP)(e.machine,t.metric,t.resourceId),unit:t.unit,unitLabel:(0,y.RL)(t.unit),stats:(0,ee.T6)(t.points),points:t.points.map(t=>{let s=Math.min(e.result.toMs,t.t+e.result.stepMs),r=null!==t.min||null!==t.max||null!==t.avg;return{t:t.t,tIso:eh(t.t),bucketStartMs:t.t,bucketStartIso:eh(t.t),bucketEndMs:s,bucketEndIso:eh(s),min:t.min,max:t.max,avg:t.avg,state:r?"recorded":"unavailable"}})}))}function eg(e){return(0,ee.$z)(e.result.gaps,e.result.fromMs,e.result.toMs).map(e=>({...e,fromIso:eh(e.fromMs),toIso:eh(e.toMs)}))}function ef(e){let t=new Set(e.result.series.map(e=>e.metric));return e.selectedMetrics.filter(e=>!t.has(e))}function eb(e){let t=new Set(e.selectedMetrics),s=new Set(em(e).map(e=>eu(e.metric,e.resourceId)));return e.result.series.filter(e=>t.has(e.metric)&&!s.has(eu(e.metric,e.resourceId))).length}function ey(e,t){let s=e.result,r=["Only the visible series from the loaded History result are included; this export does not query more data."];"raw"!==s.tier&&r.push(`Values are ${ed[s.tier]}, not individual raw samples.`),s.truncated&&r.push("The loaded result is partial: the hub limited or shortened this history query.");let n=eg(e);n.length>0&&r.push(`${n.length} recorded data gap${1===n.length?"":"s"} included.`),t.length>0&&r.push(`Selected metrics without stored data: ${t.join(", ")}.`);let i=eb(e);return i>0&&r.push(`${i} selected series hidden in this view were not exported.`),r}let ej=["record_type","metric","metric_label","resource_id","resource_label","unit","bucket_start_ms","bucket_start_iso","bucket_end_ms","bucket_end_iso","min","max","avg","value_state","gap_kind","gap_reason","gap_dropped_records"],eN="inline-flex min-h-7 items-center rounded-md border border-border bg-background px-2 text-xs text-foreground transition-colors hover:bg-card-strong disabled:cursor-not-allowed disabled:opacity-50";function ev(e){let[t,s]=(0,a.useState)(null),n=em(e).length,i=t=>{let r=Date.now(),n={...e,exportedAt:r};try{let e,i,a,l,o,d,c,u,m=function(e,t,s=Date.now()){return(0,eo.Y8)("history",ec(e.machine),s,t)}(n,t,r),h="csv"===t?function(e){let t,s,r,n,i,a,l=e.exportedAt??Date.now(),o=(t=(0,A.ly)(e.range),s=e.result,r=em(e),n=ef(e),i=eg(e),a=e.selectedMetrics.map(ep).join("; "),[["Rigscope History export"],["Scope","Visible series from the loaded History result"],["Machine",ec(e.machine)],["Machine ID",e.machine.machineId],["Query",a],["Range",`${t.label} (${eh(s.fromMs)} – ${eh(s.toMs)})`],["Resolution",`${ed[s.tier]} \xb7 ${s.stepMs} ms buckets`],["Loaded at",eh(e.loadedAt)],["Exported at",eh(l)],["Partial",s.truncated?"true":"false"],["Gaps",String(i.length)],["Visible series",String(r.length)],["Selected without stored data",n.length>0?n.join(", "):"none"],["Note",ey(e,n).join(" ")],[]]);for(let t of(o.push([...ej]),ex(e)))for(let e of t.points)o.push(["bucket",t.metric,t.label,t.resourceId,t.resourceLabel,t.unit,e.bucketStartMs,e.bucketStartIso,e.bucketEndMs,e.bucketEndIso,e.min,e.max,e.avg,e.state,"","",""]);for(let t of eg(e))o.push(["gap","","","","","",t.fromMs,t.fromIso,t.toMs,t.toIso,"","","","gap",t.kind,t.reason??"",t.droppedRecords??""]);return(0,el.kg)(o)}(n):(e=n.exportedAt??Date.now(),i=(0,A.ly)(n.range),a=n.result,l=ex(n),o=ef(n),d=eg(n),c=eb(n),u={app:"Rigscope",kind:"history",version:1,exportedAt:eh(e),scope:{description:"Visible series from the loaded History result",machine:{id:n.machine.machineId,name:ec(n.machine),hostname:n.machine.hostname,connected:n.machine.connected,lastReceivedAt:n.machine.lastReceivedAt},query:{range:{id:i.id,label:i.label,fromMs:a.fromMs,fromIso:eh(a.fromMs),toMs:a.toMs,toIso:eh(a.toMs)},selectedMetrics:[...n.selectedMetrics],visibleSeries:l.length,hiddenSeriesCount:c}},resolution:{tier:a.tier,label:ed[a.tier],stepMs:a.stepMs,expectedIntervalMs:n.machine.expectedIntervalMs??null},loadedAt:eh(n.loadedAt),partial:a.truncated,gaps:d,series:l.map(e=>({metric:e.metric,label:e.label,resourceId:e.resourceId,resourceLabel:e.resourceLabel,unit:e.unit,unitLabel:e.unitLabel,summary:{points:e.stats.count,min:e.stats.min,max:e.stats.max,averageOfBucketAverages:e.stats.avg,latest:e.stats.latest,latestAt:null===e.stats.latestT?null:eh(e.stats.latestT),firstAt:null===e.stats.firstT?null:eh(e.stats.firstT),lastAt:null===e.stats.lastT?null:eh(e.stats.lastT)},points:e.points})),missingData:o.map(e=>({metric:e,label:ep(e),reason:"No stored series in the loaded result."})),notes:ey(n,o)},`${JSON.stringify(u,null,2)}
3
- `);(0,el.PE)(m,h,"csv"===t?el.UR:el.uW),s(null)}catch{s("The history export could not be created.")}};return(0,r.jsxs)("div",{className:"flex min-w-0 flex-wrap items-center gap-1.5",children:[(0,r.jsxs)("span",{className:"text-xs text-muted-foreground",children:["Export visible",(0,r.jsx)("span",{className:"sr-only",children:` (${n} series from the loaded result)`})]}),(0,r.jsx)("button",{type:"button",onClick:()=>i("csv"),"aria-label":"Download visible history as CSV",title:"Download the visible series from this loaded result as CSV",className:eN,children:"CSV"}),(0,r.jsx)("button",{type:"button",onClick:()=>i("json"),"aria-label":"Download visible history as JSON",title:"Download the visible series from this loaded result as JSON",className:eN,children:"JSON"}),null!==t?(0,r.jsxs)("span",{role:"status",className:"inline-flex items-center gap-1 text-xs text-warn",children:[(0,r.jsx)(d.A,{className:"h-3 w-3","aria-hidden":!0}),t]}):null]})}function ew(e){return e.displayName?.trim()||e.hostname.trim()||e.machineId}function ek(){return(0,r.jsxs)("div",{className:"grid grid-cols-1 gap-5 xl:grid-cols-2","aria-busy":"true",children:[(0,r.jsx)(h.Z,{title:"Loading stored history",children:(0,r.jsx)("div",{className:"h-40 animate-pulse rounded-lg bg-card-strong","aria-hidden":!0})}),(0,r.jsx)(h.Z,{title:"Preparing charts",children:(0,r.jsx)("div",{className:"h-40 animate-pulse rounded-lg bg-card-strong","aria-hidden":!0})})]})}function eM(){let e,t,s,n,{session:j,phase:N,machines:v,retryConnection:w}=(0,f.M)(),k=(0,g.x)(),{machine:C,machineId:S,requestedMachineId:I}=(0,b.JG)("history"),[P,U]=F(S,"memory"),[R,_]=F(S,"filesystem"),T={memory:P,filesystem:R},[z,Z]=(0,L.u)("history.range","10m",E),[H,q]=(0,L.u)(`history.metrics.${S}`,null,O),[V]=G(S),W=M(C),Y=$(V,W),[J,K]=D(S,"cards"),[ee,et]=D(S,"series"),es=(0,a.useMemo)(()=>new Set(J),[J]),er=(0,a.useMemo)(()=>new Set(ee),[ee]),[en,ei]=(0,L.u)("history.autoRefresh",!0,B,"session"),[el,eo]=(0,a.useState)(null),[ed,ec]=(0,a.useState)(null),[eu,em]=(0,a.useState)(0),eh=(0,a.useMemo)(()=>void 0===C?"":(0,y.er)(C).join(","),[C?.machineId,C?.inventory,C?.metrics?.payload.gpus]),ep=H??eh,ex=""===ep?[]:ep.split(","),eg="signed-in"===j.kind&&void 0!==C&&""!==S&&""!==ep;(0,a.useEffect)(()=>{if(""===S){eo(null),ec(null);return}let e=new AbortController;return eo(null),ec(null),fetch(`/api/history/metrics?machineId=${encodeURIComponent(S)}`,{signal:e.signal,cache:"no-store",headers:{Accept:"application/json"}}).then(async t=>{if(!t.ok){if(401===t.status||403===t.status||404===t.status)return;throw Error(`catalog ${t.status}`)}let s=await t.json();if(null===s||"object"!=typeof s||!("metrics"in s))throw Error("catalog shape");let r=s.metrics;if(null===r||"object"!=typeof r)throw Error("catalog shape");let n=Object.create(null);for(let[e,t]of Object.entries(r))null!==t&&"object"==typeof t&&"string"==typeof t.unit&&(n[e]={unit:t.unit});e.signal.aborted||eo(n)}).catch(()=>{e.signal.aborted||ec("The hub's metric catalog could not be loaded; standard metric names are shown.")}),()=>e.abort()},[S]);let{data:ef,error:eb,loading:ey,manualRefreshing:ej}=(0,X.n)({machineId:S,metricsKey:ep,coreIdsKey:ex.includes("cpu.core")&&Y.length!==W.length?Y.join(","):void 0,range:z,enabled:eg,autoRefresh:en,refreshNonce:eu});(0,a.useEffect)(()=>{eb?.kind==="rate-limited"&&ei(!1)},[eb?.kind,ei]);let eN=ef?.result??null,eM=void 0===C?[]:(0,y.ue)(C,eN?.series??[]),e$=(0,A.ly)(z),eC=null!==eb?null!==ef?`${"rate-limited"===eb.kind?"Refresh paused":"Refresh failed"} \xb7 ${(0,A.ei)(ef.loadedAt)}`:"History unavailable":null!==ef?`Updated ${(0,A.ei)(ef.loadedAt)}`:ey?"Loading…":"",eA=eg&&null===ef&&null===eb,eS=v.length,eI="disconnected"===N;return(0,r.jsx)(m.G,{title:"History",machineId:S,machineView:"history",headerRight:(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(p.$E,{}),(0,r.jsx)(x.B,{})]}),children:k||(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("p",{role:"status","aria-live":"polite",className:"sr-only",children:eb?.message??""}),(0,r.jsx)(Q,{machine:C,range:z,selectedMetrics:ex,catalog:el,catalogError:ed,gpuCards:eM,hiddenCards:es,autoRefresh:en,loading:ey,manualRefreshing:ej,statusText:eC,onRangeChange:Z,onToggleMetric:e=>{let t=new Set(ex);t.has(e)?t.delete(e):t.add(e),q([...t].sort().join(","))},onSetMetrics:e=>q([...new Set(e)].sort().join(",")),onToggleCard:e=>{K(t=>{let s=new Set(t);return s.has(e)?s.delete(e):s.add(e),[...s]})},onToggleAutoRefresh:()=>ei(e=>!e),onRefresh:()=>em(e=>e+1)}),"reconnecting"===N||"disconnected"===N?(0,r.jsxs)("div",{role:"status",className:"mb-4 flex items-start gap-2 rounded-lg border border-border bg-card px-4 py-2.5 text-xs text-muted-foreground",children:[(0,r.jsx)(d.A,{className:"mt-0.5 h-3.5 w-3.5 shrink-0 text-warn","aria-hidden":!0}),(0,r.jsxs)("span",{children:["Live feed ","disconnected"===N?"disconnected":"reconnecting"," \xb7 stored history available"]}),"disconnected"===N?(0,r.jsxs)("button",{type:"button",onClick:w,className:"ml-auto inline-flex min-h-8 shrink-0 items-center gap-1.5 rounded-md border border-border px-2.5 text-xs text-foreground transition-colors hover:bg-card-strong",children:[(0,r.jsx)(u.A,{className:"h-3 w-3","aria-hidden":!0}),"Retry now"]}):null]}):null,void 0===C?eI?(0,r.jsxs)(h.Z,{title:"Hub disconnected",className:"mx-auto mt-3 max-w-xl",children:[(0,r.jsx)(h.p,{icon:c.A,note:"The hub is unreachable, so the authorized machine list is unavailable."}),(0,r.jsx)("div",{className:"mt-2 flex justify-center",children:(0,r.jsxs)("button",{type:"button",onClick:w,className:"inline-flex min-h-8 items-center gap-1.5 rounded-md border border-border px-3 text-xs text-foreground transition-colors hover:bg-card-strong",children:[(0,r.jsx)(u.A,{className:"h-3.5 w-3.5","aria-hidden":!0}),"Check again"]})})]}):0!==eS||eI||"idle"!==N&&"connecting"!==N&&"reconnecting"!==N?0===eS?(0,r.jsx)(h.Z,{title:"No machines",className:"mx-auto mt-3 max-w-xl",children:(0,r.jsx)(h.p,{icon:o.A,note:"No machines are available in your authorized fleet."})}):(0,r.jsxs)(h.Z,{title:"Machine not found",className:"mx-auto mt-3 max-w-xl",children:[(0,r.jsx)(h.p,{icon:o.A,note:"This machine is unavailable or outside your access."}),I?(0,r.jsxs)("p",{className:"tnum mt-2 text-center text-xs text-muted-foreground",children:["Requested identifier: ",I]}):null,(0,r.jsx)("div",{className:"mt-2 flex justify-center",children:(0,r.jsx)(i(),{href:"/",className:"inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-card-strong",children:"Back to fleet"})})]}):(0,r.jsx)(h.Z,{title:"Waiting for machines",className:"mx-auto mt-3 max-w-xl",children:(0,r.jsx)(h.p,{icon:o.A,note:"Waiting for the hub to report your authorized machines…"})}):0===ex.length?(0,r.jsx)(h.Z,{title:"No metrics selected",className:"mx-auto mt-3 max-w-xl",children:(0,r.jsx)(h.p,{icon:o.A,note:""===eh?"No metric families are shared with this hub.":"Choose at least one metric above to draw history."})}):null!==eb&&null===ef?(t=(e=function(e){switch(e.kind){case"unauthorized":return{title:"Session ended",note:"Your session is no longer accepted, so stored history is hidden.",icon:l.A};case"denied":return{title:"History access denied",note:e.message,icon:l.A};case"missing":return{title:"Machine unavailable",note:e.message,icon:o.A};case"rate-limited":return{title:"History requests limited",note:e.message,icon:d.A};case"unavailable":return{title:"History unavailable",note:e.message,icon:c.A};case"network":return{title:"Hub unreachable",note:"The hub could not be reached for stored history.",icon:c.A};case"invalid":return{title:"Unexpected history response",note:e.message,icon:d.A}}}(eb)).icon,(0,r.jsxs)(h.Z,{title:e.title,className:"mx-auto mt-3 max-w-xl",children:[(0,r.jsx)(h.p,{icon:t,note:e.note}),(0,r.jsxs)("div",{className:"mt-2 flex flex-wrap justify-center gap-2",children:[(0,r.jsxs)("button",{type:"button",onClick:()=>em(e=>e+1),className:"inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-card-strong",children:[(0,r.jsx)(u.A,{className:"h-3.5 w-3.5","aria-hidden":!0}),"Try again"]}),"unauthorized"===eb.kind?(0,r.jsx)(i(),{href:"/login",className:"inline-flex items-center rounded-md bg-accent px-3 py-1.5 text-xs font-medium text-accent-foreground transition-colors hover:bg-accent/90",children:"Sign in"}):null]})]})):(ey||eA)&&null===ef?(0,r.jsx)(ek,{}):null===ef?(0,r.jsx)(h.Z,{title:"History",className:"mx-auto mt-3 max-w-xl",children:(0,r.jsx)(h.p,{icon:o.A,note:"No stored history has arrived yet."})}):(n="raw"===(s=ef.result).tier?"raw samples":"1m"===s.tier?"1-minute rollups":"1-hour rollups",(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("div",{className:"mb-3 flex flex-wrap items-baseline gap-x-4 gap-y-1 text-xs text-muted-foreground",children:[(0,r.jsxs)("span",{className:"inline-flex items-center gap-1.5 text-foreground",children:[(0,r.jsx)("span",{"aria-hidden":!0,className:`inline-block h-2 w-2 shrink-0 rounded-full ${C.connected?"bg-ok":"bg-crit"}`}),ew(C)]}),(0,r.jsxs)("span",{children:[(0,A.r6)(s.fromMs)," – ",(0,A.r6)(s.toMs)]}),(0,r.jsxs)("span",{className:"tnum",title:n,children:[(0,A.I_)(s.stepMs)," buckets"]}),(0,r.jsx)("div",{className:"ml-auto self-center",children:(0,r.jsx)(ev,{machine:C,result:s,range:z,selectedMetrics:(0,y.Cv)(ex,T),hiddenCards:es,hiddenSeries:er,coreIds:Y,loadedAt:ef.loadedAt})})]}),s.truncated?(0,r.jsxs)("div",{role:"status",className:"mb-4 flex items-start gap-2 rounded-lg bg-warn-soft px-4 py-2.5 text-xs text-foreground",children:[(0,r.jsx)(d.A,{className:"mt-0.5 h-3.5 w-3.5 shrink-0 text-warn","aria-hidden":!0}),(0,r.jsx)("span",{children:"Partial history \xb7 narrow the range for more detail."})]}):null,s.gaps.length>0?(0,r.jsxs)("details",{className:"mb-4 max-w-3xl text-xs text-muted-foreground",children:[(0,r.jsxs)("summary",{className:"inline-flex min-h-8 cursor-pointer items-center gap-2 rounded-md text-warn",children:[(0,r.jsx)(d.A,{className:"mt-0.5 h-3.5 w-3.5 shrink-0 text-warn","aria-hidden":!0}),(0,r.jsxs)("span",{children:[(0,r.jsx)("strong",{className:"font-medium",children:"Data gaps:"})," ",(0,A.fH)(s.gaps,s.fromMs,s.toMs)]})]}),(0,r.jsxs)("ul",{className:"mt-1.5 flex flex-col gap-1",children:[s.gaps.slice(0,20).map(e=>(0,r.jsxs)("li",{className:"tnum text-xs",children:[(0,A.r6)(e.fromMs)," – ",(0,A.r6)(e.toMs)," (",(0,A.I_)(e.toMs-e.fromMs),"):"," ","dropped"===e.kind?"dropped":"missed",e.reason?` \xb7 ${e.reason}`:"",void 0!==e.droppedRecords?` \xb7 ${e.droppedRecords} record${1===e.droppedRecords?"":"s"}`:""]},`${e.fromMs}-${e.toMs}-${e.kind}`)),s.gaps.length>20?(0,r.jsxs)("li",{className:"text-xs text-muted-foreground",children:["…and ",s.gaps.length-20," more."]}):null]})]}):null,0===s.series.length?(0,r.jsx)(h.Z,{title:"No stored points",className:"mx-auto max-w-xl",children:(0,r.jsx)(h.p,{icon:o.A,note:`No stored readings for ${void 0===C?"this machine":ew(C)} in ${e$.label.toLowerCase()}.`})}):(0,r.jsx)(ea,{machine:C,result:s,selectedMetrics:ex,hiddenCards:es,hiddenSeries:er,onToggleSeries:e=>{et(t=>{let s=new Set(t);return s.has(e)?s.delete(e):s.add(e),[...s]})},capacityUnits:T,onCapacityUnitChange:(e,t)=>("memory"===e?U:_)(t)})]}))]})})}},9942:(e,t,s)=>{"use strict";s.d(t,{A:()=>r});let r=(0,s(8698).A)("Play",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]])}},e=>{e.O(0,[157,939,103,408,441,794,358],()=>e(e.s=7148)),_N_E=e.O()}]);