@glassmkr/crucible 0.7.1 → 0.8.1

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 (103) hide show
  1. package/dist/alerts/__tests__/rules.test.d.ts +1 -0
  2. package/dist/alerts/__tests__/rules.test.js +437 -0
  3. package/dist/alerts/__tests__/rules.test.js.map +1 -0
  4. package/dist/alerts/rules.d.ts +8 -0
  5. package/dist/alerts/rules.js +175 -34
  6. package/dist/alerts/rules.js.map +1 -1
  7. package/dist/api.d.ts +2 -0
  8. package/dist/api.js +7 -0
  9. package/dist/api.js.map +1 -0
  10. package/dist/collect/__tests__/dmi.test.d.ts +1 -0
  11. package/dist/collect/__tests__/dmi.test.js +133 -0
  12. package/dist/collect/__tests__/dmi.test.js.map +1 -0
  13. package/dist/collect/__tests__/ipmi.test.js +47 -1
  14. package/dist/collect/__tests__/ipmi.test.js.map +1 -1
  15. package/dist/collect/__tests__/thermal.test.d.ts +1 -0
  16. package/dist/collect/__tests__/thermal.test.js +224 -0
  17. package/dist/collect/__tests__/thermal.test.js.map +1 -0
  18. package/dist/collect/dmi.d.ts +19 -0
  19. package/dist/collect/dmi.js +118 -0
  20. package/dist/collect/dmi.js.map +1 -0
  21. package/dist/collect/ipmi.d.ts +27 -2
  22. package/dist/collect/ipmi.js +90 -2
  23. package/dist/collect/ipmi.js.map +1 -1
  24. package/dist/collect/thermal.d.ts +10 -0
  25. package/dist/collect/thermal.js +232 -0
  26. package/dist/collect/thermal.js.map +1 -0
  27. package/dist/config.d.ts +10 -0
  28. package/dist/config.js +2 -0
  29. package/dist/config.js.map +1 -1
  30. package/dist/index.js +51 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/lib/__tests__/capability.test.d.ts +1 -0
  33. package/dist/lib/__tests__/capability.test.js +87 -0
  34. package/dist/lib/__tests__/capability.test.js.map +1 -0
  35. package/dist/lib/__tests__/vendor-sensors.test.d.ts +1 -0
  36. package/dist/lib/__tests__/vendor-sensors.test.js +49 -0
  37. package/dist/lib/__tests__/vendor-sensors.test.js.map +1 -0
  38. package/dist/lib/capability.d.ts +21 -0
  39. package/dist/lib/capability.js +110 -0
  40. package/dist/lib/capability.js.map +1 -0
  41. package/dist/lib/cpu-thermal-chips.d.ts +2 -0
  42. package/dist/lib/cpu-thermal-chips.js +28 -0
  43. package/dist/lib/cpu-thermal-chips.js.map +1 -0
  44. package/dist/lib/types.d.ts +58 -0
  45. package/dist/lib/vendor-sensors.d.ts +27 -0
  46. package/dist/lib/vendor-sensors.js +63 -0
  47. package/dist/lib/vendor-sensors.js.map +1 -0
  48. package/dist/notify/telegram.js +1 -1
  49. package/dist/notify/telegram.js.map +1 -1
  50. package/package.json +16 -1
  51. package/rule-ids.json +29 -0
  52. package/.dockerignore +0 -13
  53. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -24
  54. package/.github/ISSUE_TEMPLATE/no_data.md +0 -26
  55. package/.github/workflows/docker.yml +0 -53
  56. package/.github/workflows/publish.yml +0 -25
  57. package/Dockerfile +0 -59
  58. package/config/collector.example.yaml +0 -43
  59. package/docker-compose.yml +0 -26
  60. package/scripts/sign-release.sh +0 -29
  61. package/src/__tests__/cli.test.ts +0 -74
  62. package/src/__tests__/reboot-marker.test.ts +0 -122
  63. package/src/alerts/evaluator.ts +0 -15
  64. package/src/alerts/rules.ts +0 -283
  65. package/src/alerts/state.ts +0 -92
  66. package/src/cli.ts +0 -112
  67. package/src/collect/__tests__/ipmi.test.ts +0 -96
  68. package/src/collect/__tests__/smart.test.ts +0 -68
  69. package/src/collect/__tests__/system.test.ts +0 -29
  70. package/src/collect/__tests__/zfs.test.ts +0 -72
  71. package/src/collect/conntrack.ts +0 -27
  72. package/src/collect/cpu.ts +0 -92
  73. package/src/collect/disks.ts +0 -91
  74. package/src/collect/fd.ts +0 -31
  75. package/src/collect/io-errors.ts +0 -23
  76. package/src/collect/io-latency.ts +0 -103
  77. package/src/collect/ipmi.ts +0 -207
  78. package/src/collect/memory.ts +0 -30
  79. package/src/collect/network.ts +0 -193
  80. package/src/collect/ntp.ts +0 -114
  81. package/src/collect/os-alerts.ts +0 -43
  82. package/src/collect/raid.ts +0 -40
  83. package/src/collect/security.ts +0 -268
  84. package/src/collect/smart.ts +0 -72
  85. package/src/collect/system.ts +0 -32
  86. package/src/collect/systemd.ts +0 -33
  87. package/src/collect/zfs.ts +0 -66
  88. package/src/config.ts +0 -65
  89. package/src/index.ts +0 -221
  90. package/src/lib/__tests__/parse.test.ts +0 -28
  91. package/src/lib/exec.ts +0 -16
  92. package/src/lib/parse.ts +0 -29
  93. package/src/lib/reboot-marker.ts +0 -88
  94. package/src/lib/types.ts +0 -226
  95. package/src/lib/version-check.ts +0 -39
  96. package/src/lib/version.ts +0 -33
  97. package/src/metrics-server.ts +0 -123
  98. package/src/notify/email.ts +0 -69
  99. package/src/notify/slack.ts +0 -47
  100. package/src/notify/telegram.ts +0 -65
  101. package/src/push/forge.ts +0 -109
  102. package/tsconfig.json +0 -15
  103. package/vitest.config.ts +0 -12
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,437 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { allRules } from "../rules.js";
3
+ const baseThresholds = {
4
+ ram_percent: 90,
5
+ swap_alert: true,
6
+ disk_percent: 85,
7
+ iowait_percent: 20,
8
+ nvme_wear_percent: 85,
9
+ disk_latency_nvme_ms: 50,
10
+ disk_latency_hdd_ms: 200,
11
+ cpu_temp_warning_c: 80,
12
+ cpu_temp_critical_c: 90,
13
+ interface_utilization_percent: 90,
14
+ };
15
+ function emptySnap() {
16
+ return {
17
+ collector_version: "test",
18
+ timestamp: "2026-01-01T00:00:00Z",
19
+ system: { hostname: "h", ip: "1.2.3.4", os: "linux", kernel: "6.0", uptime_seconds: 1000 },
20
+ cpu: { user_percent: 0, system_percent: 0, iowait_percent: 0, idle_percent: 100, load_1m: 0, load_5m: 0, load_15m: 0 },
21
+ memory: { total_mb: 16384, used_mb: 1000, available_mb: 15000, swap_total_mb: 0, swap_used_mb: 0 },
22
+ disks: [],
23
+ smart: [],
24
+ network: [],
25
+ raid: [],
26
+ ipmi: { available: false, sensors: [], ecc_errors: { correctable: 0, uncorrectable: 0 }, sel_entries_count: 0, sel_events_recent: [], fans: [] },
27
+ os_alerts: { oom_kills_recent: 0, zombie_processes: 0, time_drift_ms: 0 },
28
+ };
29
+ }
30
+ const diskLatencyRule = allRules.find(r => r.type === "disk_latency_high");
31
+ const swapHighRule = allRules.find(r => r.type === "swap_high");
32
+ describe("swap_high (formerly swap_active)", () => {
33
+ it("does not fire when no swap is in use", () => {
34
+ const snap = emptySnap();
35
+ expect(swapHighRule.evaluate(snap, baseThresholds)).toEqual([]);
36
+ });
37
+ it("fires warning when swap is in use", () => {
38
+ const snap = emptySnap();
39
+ snap.memory.swap_used_mb = 128;
40
+ const out = swapHighRule.evaluate(snap, baseThresholds);
41
+ expect(out).toHaveLength(1);
42
+ expect(out[0].severity).toBe("warning");
43
+ expect(out[0].type).toBe("swap_high");
44
+ expect(out[0].evidence.swap_used_mb).toBe(128);
45
+ });
46
+ it("respects t.swap_alert=false", () => {
47
+ const snap = emptySnap();
48
+ snap.memory.swap_used_mb = 128;
49
+ expect(swapHighRule.evaluate(snap, { ...baseThresholds, swap_alert: false })).toEqual([]);
50
+ });
51
+ });
52
+ const cpuTempRule = allRules.find(r => r.type === "cpu_temperature_high");
53
+ const eccRule = allRules.find(r => r.type === "ecc_errors");
54
+ const psuRule = allRules.find(r => r.type === "psu_redundancy_loss");
55
+ describe("ecc_errors (Dell-style SEL path)", () => {
56
+ it("fires when SEL ECC counts are higher than named-sensor counts", () => {
57
+ const snap = emptySnap();
58
+ snap.ipmi = {
59
+ available: true, sensors: [],
60
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
61
+ ecc_errors_from_sel: { correctable: 3, uncorrectable: 0, newest_event_timestamp: "2026-04-05T14:31:00Z" },
62
+ sel_entries_count: 3, sel_events_recent: [], fans: [],
63
+ };
64
+ const out = eccRule.evaluate(snap, baseThresholds);
65
+ expect(out).toHaveLength(1);
66
+ expect(out[0].severity).toBe("warning");
67
+ expect(out[0].evidence.source).toBe("ipmi_sel");
68
+ expect(out[0].evidence.correctable).toBe(3);
69
+ });
70
+ it("uses named-sensor source when those counts exceed SEL", () => {
71
+ const snap = emptySnap();
72
+ snap.ipmi = {
73
+ available: true, sensors: [],
74
+ ecc_errors: { correctable: 5, uncorrectable: 0 },
75
+ ecc_errors_from_sel: { correctable: 0, uncorrectable: 0, newest_event_timestamp: null },
76
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
77
+ };
78
+ const out = eccRule.evaluate(snap, baseThresholds);
79
+ expect(out[0].evidence.source).toBe("ipmi_sensors");
80
+ expect(out[0].evidence.correctable).toBe(5);
81
+ });
82
+ it("does not double-count when both sources are populated; uses max", () => {
83
+ const snap = emptySnap();
84
+ snap.ipmi = {
85
+ available: true, sensors: [],
86
+ ecc_errors: { correctable: 2, uncorrectable: 0 },
87
+ ecc_errors_from_sel: { correctable: 5, uncorrectable: 0, newest_event_timestamp: "2026-04-05T14:31:00Z" },
88
+ sel_entries_count: 5, sel_events_recent: [], fans: [],
89
+ };
90
+ const out = eccRule.evaluate(snap, baseThresholds);
91
+ expect(out[0].evidence.correctable).toBe(5); // max(2, 5)
92
+ });
93
+ it("escalates to critical on uncorrectable from SEL", () => {
94
+ const snap = emptySnap();
95
+ snap.ipmi = {
96
+ available: true, sensors: [],
97
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
98
+ ecc_errors_from_sel: { correctable: 0, uncorrectable: 1, newest_event_timestamp: "2026-04-05T14:31:00Z" },
99
+ sel_entries_count: 1, sel_events_recent: [], fans: [],
100
+ };
101
+ const out = eccRule.evaluate(snap, baseThresholds);
102
+ expect(out[0].severity).toBe("critical");
103
+ });
104
+ it("does not fire when both sources are zero", () => {
105
+ const snap = emptySnap();
106
+ snap.ipmi.available = true;
107
+ expect(eccRule.evaluate(snap, baseThresholds)).toEqual([]);
108
+ });
109
+ });
110
+ describe("psu_redundancy_loss (Dell + Supermicro)", () => {
111
+ it("fires from aggregate redundancy state on Dell even if individual PS sensors look OK", () => {
112
+ const snap = emptySnap();
113
+ snap.dmi = { available: true, vendor: "dell", raw_vendor: "Dell Inc.", product_name: "PowerEdge R740", bios_version: "2.21", bios_date: "2024-08-15", is_virtual: false };
114
+ snap.ipmi = {
115
+ available: true,
116
+ sensors: [
117
+ { name: "PS1 Status", value: "0x01", unit: "discrete", status: "ok" },
118
+ { name: "PS2 Status", value: "0x01", unit: "discrete", status: "ok" },
119
+ ],
120
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
121
+ psu_redundancy_state: "redundancy_lost",
122
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
123
+ };
124
+ const out = psuRule.evaluate(snap, baseThresholds);
125
+ expect(out).toHaveLength(1);
126
+ expect(out[0].evidence.source).toBe("aggregate_sensor");
127
+ expect(out[0].evidence.redundancy_state).toBe("redundancy_lost");
128
+ });
129
+ it("fires from per-PSU status on Dell when redundancy state is not set", () => {
130
+ const snap = emptySnap();
131
+ snap.dmi = { available: true, vendor: "dell", raw_vendor: "Dell Inc.", product_name: "PowerEdge R740", bios_version: null, bios_date: null, is_virtual: false };
132
+ snap.ipmi = {
133
+ available: true,
134
+ sensors: [
135
+ { name: "PS1 Status", value: "0x01", unit: "discrete", status: "ok" },
136
+ { name: "PS2 Status", value: "Failure detected", unit: "discrete", status: "failure" },
137
+ ],
138
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
139
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
140
+ };
141
+ const out = psuRule.evaluate(snap, baseThresholds);
142
+ expect(out).toHaveLength(1);
143
+ expect(out[0].evidence.source).toBe("per_psu_sensors");
144
+ expect(out[0].evidence.vendor).toBe("dell");
145
+ });
146
+ it("fires on Supermicro PSU1 Status critical (no regression from old behaviour)", () => {
147
+ const snap = emptySnap();
148
+ snap.dmi = { available: true, vendor: "supermicro", raw_vendor: "Supermicro", product_name: "X11", bios_version: null, bios_date: null, is_virtual: false };
149
+ snap.ipmi = {
150
+ available: true,
151
+ sensors: [
152
+ { name: "PSU1 Status", value: "absent", unit: "discrete", status: "absent" },
153
+ { name: "PSU2 Status", value: "OK", unit: "discrete", status: "ok" },
154
+ ],
155
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
156
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
157
+ };
158
+ const out = psuRule.evaluate(snap, baseThresholds);
159
+ expect(out).toHaveLength(1);
160
+ expect(out[0].evidence.vendor).toBe("supermicro");
161
+ });
162
+ it("does not fire on a VM with no PSU sensors", () => {
163
+ const snap = emptySnap();
164
+ snap.dmi = { available: true, vendor: "virtual", raw_vendor: "QEMU", product_name: "Standard PC", bios_version: null, bios_date: null, is_virtual: true };
165
+ snap.ipmi = {
166
+ available: true, sensors: [], ecc_errors: { correctable: 0, uncorrectable: 0 },
167
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
168
+ };
169
+ expect(psuRule.evaluate(snap, baseThresholds)).toEqual([]);
170
+ });
171
+ it("does not fire when fully redundant on Dell", () => {
172
+ const snap = emptySnap();
173
+ snap.dmi = { available: true, vendor: "dell", raw_vendor: "Dell Inc.", product_name: "PowerEdge R740", bios_version: null, bios_date: null, is_virtual: false };
174
+ snap.ipmi = {
175
+ available: true,
176
+ sensors: [
177
+ { name: "PS1 Status", value: "0x01", unit: "discrete", status: "ok" },
178
+ { name: "PS2 Status", value: "0x01", unit: "discrete", status: "ok" },
179
+ ],
180
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
181
+ psu_redundancy_state: "fully_redundant",
182
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
183
+ };
184
+ expect(psuRule.evaluate(snap, baseThresholds)).toEqual([]);
185
+ });
186
+ });
187
+ describe("cpu_temperature_high (hwmon path)", () => {
188
+ it("fires from hwmon when no IPMI is available (Pi)", () => {
189
+ const snap = emptySnap();
190
+ snap.thermal = {
191
+ available: true, source: "hwmon",
192
+ cpu_readings: [{ label: "cpu_thermal temp1", value_celsius: 85, source_chip: "cpu_thermal", source: "hwmon" }],
193
+ other_readings: [], max_cpu_celsius: 85,
194
+ };
195
+ const out = cpuTempRule.evaluate(snap, baseThresholds);
196
+ expect(out).toHaveLength(1);
197
+ expect(out[0].severity).toBe("warning");
198
+ expect(out[0].evidence.source).toBe("hwmon");
199
+ expect(out[0].evidence.chip).toBe("cpu_thermal");
200
+ });
201
+ it("fires critical when value_celsius >= cpu_temp_critical_c", () => {
202
+ const snap = emptySnap();
203
+ snap.thermal = {
204
+ available: true, source: "hwmon",
205
+ cpu_readings: [{ label: "coretemp Package id 0", value_celsius: 95, source_chip: "coretemp", source: "hwmon" }],
206
+ other_readings: [], max_cpu_celsius: 95,
207
+ };
208
+ const out = cpuTempRule.evaluate(snap, baseThresholds);
209
+ expect(out[0].severity).toBe("critical");
210
+ });
211
+ it("does not fire when max_cpu_celsius is null (VM)", () => {
212
+ const snap = emptySnap();
213
+ snap.thermal = { available: true, source: "none", cpu_readings: [], other_readings: [], max_cpu_celsius: null };
214
+ expect(cpuTempRule.evaluate(snap, baseThresholds)).toEqual([]);
215
+ });
216
+ it("falls back to IPMI substring filter when hwmon is unavailable", () => {
217
+ const snap = emptySnap();
218
+ snap.ipmi = {
219
+ available: true, ecc_errors: { correctable: 0, uncorrectable: 0 },
220
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
221
+ sensors: [{ name: "CPU1 Temp", value: 85, unit: "degrees C", status: "ok" }],
222
+ };
223
+ const out = cpuTempRule.evaluate(snap, baseThresholds);
224
+ expect(out).toHaveLength(1);
225
+ expect(out[0].evidence.source).toBe("ipmi");
226
+ });
227
+ it("hwmon takes priority over IPMI when both are present", () => {
228
+ const snap = emptySnap();
229
+ snap.thermal = {
230
+ available: true, source: "hwmon",
231
+ cpu_readings: [{ label: "coretemp Package id 0", value_celsius: 88, source_chip: "coretemp", source: "hwmon" }],
232
+ other_readings: [], max_cpu_celsius: 88,
233
+ };
234
+ snap.ipmi = {
235
+ available: true, ecc_errors: { correctable: 0, uncorrectable: 0 },
236
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
237
+ sensors: [{ name: "CPU1 Temp", value: 99, unit: "degrees C", status: "ok" }],
238
+ };
239
+ const out = cpuTempRule.evaluate(snap, baseThresholds);
240
+ expect(out).toHaveLength(1);
241
+ expect(out[0].evidence.source).toBe("hwmon");
242
+ expect(out[0].evidence.value).toBe(88);
243
+ });
244
+ });
245
+ describe("disk_latency_high", () => {
246
+ it("does not fire when io_latency is missing", () => {
247
+ const snap = emptySnap();
248
+ expect(diskLatencyRule.evaluate(snap, baseThresholds)).toEqual([]);
249
+ });
250
+ it("does not fire when io_latency is empty", () => {
251
+ const snap = emptySnap();
252
+ snap.io_latency = [];
253
+ expect(diskLatencyRule.evaluate(snap, baseThresholds)).toEqual([]);
254
+ });
255
+ it("does not fire on healthy NVMe (1ms)", () => {
256
+ const snap = emptySnap();
257
+ snap.io_latency = [
258
+ { device: "nvme0n1", avg_read_latency_ms: 1, avg_write_latency_ms: 0.5, read_iops: 100, write_iops: 50 },
259
+ ];
260
+ expect(diskLatencyRule.evaluate(snap, baseThresholds)).toEqual([]);
261
+ });
262
+ it("fires on hot NVMe (60ms read on default 50ms threshold)", () => {
263
+ const snap = emptySnap();
264
+ snap.io_latency = [
265
+ { device: "nvme0n1", avg_read_latency_ms: 60, avg_write_latency_ms: 1, read_iops: 100, write_iops: 50 },
266
+ ];
267
+ const out = diskLatencyRule.evaluate(snap, baseThresholds);
268
+ expect(out).toHaveLength(1);
269
+ expect(out[0].severity).toBe("warning");
270
+ expect(out[0].evidence.device).toBe("nvme0n1");
271
+ expect(out[0].evidence.threshold_ms).toBe(50);
272
+ });
273
+ it("fires on hot SATA HDD (250ms write on default 200ms threshold)", () => {
274
+ const snap = emptySnap();
275
+ snap.io_latency = [
276
+ { device: "sda", avg_read_latency_ms: 10, avg_write_latency_ms: 250, read_iops: 5, write_iops: 20 },
277
+ ];
278
+ const out = diskLatencyRule.evaluate(snap, baseThresholds);
279
+ expect(out).toHaveLength(1);
280
+ expect(out[0].evidence.device).toBe("sda");
281
+ expect(out[0].evidence.threshold_ms).toBe(200);
282
+ });
283
+ it("does not fire on borderline-cold SATA (180ms vs 200ms threshold)", () => {
284
+ const snap = emptySnap();
285
+ snap.io_latency = [
286
+ { device: "sda", avg_read_latency_ms: 180, avg_write_latency_ms: 50, read_iops: 5, write_iops: 5 },
287
+ ];
288
+ expect(diskLatencyRule.evaluate(snap, baseThresholds)).toEqual([]);
289
+ });
290
+ it("fires once per hot device when multiple devices present", () => {
291
+ const snap = emptySnap();
292
+ snap.io_latency = [
293
+ { device: "nvme0n1", avg_read_latency_ms: 1, avg_write_latency_ms: 1, read_iops: 100, write_iops: 50 }, // healthy
294
+ { device: "sda", avg_read_latency_ms: 300, avg_write_latency_ms: 10, read_iops: 5, write_iops: 5 }, // hot HDD
295
+ { device: "nvme1n1", avg_read_latency_ms: 80, avg_write_latency_ms: 0.5, read_iops: 100, write_iops: 50 }, // hot NVMe
296
+ ];
297
+ const out = diskLatencyRule.evaluate(snap, baseThresholds);
298
+ expect(out).toHaveLength(2);
299
+ expect(out.map(a => a.evidence.device).sort()).toEqual(["nvme1n1", "sda"]);
300
+ });
301
+ it("skips devices with zero IOPS over the interval (no samples)", () => {
302
+ const snap = emptySnap();
303
+ snap.io_latency = [
304
+ { device: "sda", avg_read_latency_ms: null, avg_write_latency_ms: null, read_iops: 0, write_iops: 0 },
305
+ ];
306
+ expect(diskLatencyRule.evaluate(snap, baseThresholds)).toEqual([]);
307
+ });
308
+ });
309
+ describe("ALL_RULE_IDS export sync", () => {
310
+ it("matches the actual rule definitions in allRules", async () => {
311
+ const { ALL_RULE_IDS } = await import("../rules.js");
312
+ const idsFromArray = allRules.map(r => r.type);
313
+ expect([...ALL_RULE_IDS]).toEqual(idsFromArray);
314
+ });
315
+ it("matches the static rule-ids.json file (npm-published metadata)", async () => {
316
+ const { ALL_RULE_IDS } = await import("../rules.js");
317
+ const fs = await import("node:fs/promises");
318
+ const url = await import("node:url");
319
+ const path = await import("node:path");
320
+ const here = path.dirname(url.fileURLToPath(import.meta.url));
321
+ const json = JSON.parse(await fs.readFile(path.resolve(here, "../../../rule-ids.json"), "utf-8"));
322
+ expect(json.rule_ids).toEqual([...ALL_RULE_IDS]);
323
+ });
324
+ });
325
+ describe("cpu_temperature_high IPMI fallback unit gate (regression for 0.8.0 P1)", () => {
326
+ it("does NOT fire on CPU_FAN at 2000 RPM (would have alerted as 2000°C critical)", () => {
327
+ const snap = emptySnap();
328
+ // hwmon empty => fallback path runs
329
+ snap.thermal = { available: true, source: "none", cpu_readings: [], other_readings: [], max_cpu_celsius: null };
330
+ snap.ipmi = {
331
+ available: true,
332
+ sensors: [{ name: "CPU_FAN1", value: 2000, unit: "RPM", status: "ok" }],
333
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
334
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
335
+ };
336
+ expect(cpuTempRule.evaluate(snap, baseThresholds)).toEqual([]);
337
+ });
338
+ it("does NOT fire on CPU Vcore at 1.2 V", () => {
339
+ const snap = emptySnap();
340
+ snap.ipmi = {
341
+ available: true,
342
+ sensors: [{ name: "CPU Vcore", value: 1.2, unit: "Volts", status: "ok" }],
343
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
344
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
345
+ };
346
+ expect(cpuTempRule.evaluate(snap, baseThresholds)).toEqual([]);
347
+ });
348
+ it("excludes ambient/inlet/PCH/DIMM sensors that read in degrees C", () => {
349
+ const snap = emptySnap();
350
+ snap.ipmi = {
351
+ available: true,
352
+ sensors: [
353
+ { name: "Inlet Temp", value: 88, unit: "degrees C", status: "ok" }, // not CPU
354
+ { name: "PCH Temp", value: 92, unit: "degrees C", status: "ok" },
355
+ { name: "DIMM A1 Temp", value: 90, unit: "degrees C", status: "ok" },
356
+ ],
357
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
358
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
359
+ };
360
+ expect(cpuTempRule.evaluate(snap, baseThresholds)).toEqual([]);
361
+ });
362
+ it("still fires on legitimate CPU temperature sensor with degrees C unit", () => {
363
+ const snap = emptySnap();
364
+ snap.ipmi = {
365
+ available: true,
366
+ sensors: [{ name: "CPU1 Temp", value: 88, unit: "degrees C", status: "ok" }],
367
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
368
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
369
+ };
370
+ const out = cpuTempRule.evaluate(snap, baseThresholds);
371
+ expect(out).toHaveLength(1);
372
+ expect(out[0].evidence.source).toBe("ipmi");
373
+ expect(out[0].evidence.unit).toBe("degrees C");
374
+ });
375
+ it("accepts the SI 'C' / '°C' unit spellings", () => {
376
+ const snap = emptySnap();
377
+ snap.ipmi = {
378
+ available: true,
379
+ sensors: [
380
+ { name: "Processor 1 Temp", value: 85, unit: "C", status: "ok" },
381
+ { name: "CPU2 Temp", value: 87, unit: "°C", status: "ok" },
382
+ ],
383
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
384
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
385
+ };
386
+ const out = cpuTempRule.evaluate(snap, baseThresholds);
387
+ expect(out).toHaveLength(2);
388
+ });
389
+ });
390
+ describe("psu_redundancy_loss cr/nr discrete codes (regression for 0.8.0 P1)", () => {
391
+ it("fires on Supermicro PSU1 with status='cr'", () => {
392
+ const snap = emptySnap();
393
+ snap.dmi = { available: true, vendor: "supermicro", raw_vendor: "Supermicro", product_name: "X11", bios_version: null, bios_date: null, is_virtual: false };
394
+ snap.ipmi = {
395
+ available: true,
396
+ sensors: [
397
+ { name: "PSU1 Status", value: "0x02", unit: "discrete", status: "cr" },
398
+ { name: "PSU2 Status", value: "0x01", unit: "discrete", status: "ok" },
399
+ ],
400
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
401
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
402
+ };
403
+ const out = psuRule.evaluate(snap, baseThresholds);
404
+ expect(out).toHaveLength(1);
405
+ expect(out[0].evidence.vendor).toBe("supermicro");
406
+ });
407
+ it("fires on Dell PS<N> with status='nr'", () => {
408
+ const snap = emptySnap();
409
+ snap.dmi = { available: true, vendor: "dell", raw_vendor: "Dell Inc.", product_name: "PowerEdge R740", bios_version: null, bios_date: null, is_virtual: false };
410
+ snap.ipmi = {
411
+ available: true,
412
+ sensors: [
413
+ { name: "PS1 Status", value: "0x01", unit: "discrete", status: "ok" },
414
+ { name: "PS2 Status", value: "0x02", unit: "discrete", status: "nr" },
415
+ ],
416
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
417
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
418
+ };
419
+ const out = psuRule.evaluate(snap, baseThresholds);
420
+ expect(out).toHaveLength(1);
421
+ });
422
+ it("does NOT fire on status='nc' (non-critical, e.g. derating)", () => {
423
+ const snap = emptySnap();
424
+ snap.dmi = { available: true, vendor: "supermicro", raw_vendor: "Supermicro", product_name: "X11", bios_version: null, bios_date: null, is_virtual: false };
425
+ snap.ipmi = {
426
+ available: true,
427
+ sensors: [
428
+ { name: "PSU1 Status", value: "0x01", unit: "discrete", status: "nc" },
429
+ { name: "PSU2 Status", value: "0x01", unit: "discrete", status: "ok" },
430
+ ],
431
+ ecc_errors: { correctable: 0, uncorrectable: 0 },
432
+ sel_entries_count: 0, sel_events_recent: [], fans: [],
433
+ };
434
+ expect(psuRule.evaluate(snap, baseThresholds)).toEqual([]);
435
+ });
436
+ });
437
+ //# sourceMappingURL=rules.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.test.js","sourceRoot":"","sources":["../../../src/alerts/__tests__/rules.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,MAAM,cAAc,GAAG;IACrB,WAAW,EAAE,EAAE;IACf,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,EAAE;IAChB,cAAc,EAAE,EAAE;IAClB,iBAAiB,EAAE,EAAE;IACrB,oBAAoB,EAAE,EAAE;IACxB,mBAAmB,EAAE,GAAG;IACxB,kBAAkB,EAAE,EAAE;IACtB,mBAAmB,EAAE,EAAE;IACvB,6BAA6B,EAAE,EAAE;CAClC,CAAC;AAEF,SAAS,SAAS;IAChB,OAAO;QACL,iBAAiB,EAAE,MAAM;QACzB,SAAS,EAAE,sBAAsB;QACjC,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE;QAC1F,GAAG,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;QACtH,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE;QAClG,KAAK,EAAE,EAAE;QACT,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QAChJ,SAAS,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;KAC1E,CAAC;AACJ,CAAC;AAED,MAAM,eAAe,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,CAAE,CAAC;AAC5E,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAE,CAAC;AAEjE,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC;QAC/B,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACxD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC;QAC/B,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,cAAc,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AACH,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAsB,CAAE,CAAC;AAC3E,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAE,CAAC;AAC7D,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,qBAAqB,CAAE,CAAC;AAEtE,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;YAC5B,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,mBAAmB,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,sBAAsB,EAAE,sBAAsB,EAAE;YACzG,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;YAC5B,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,mBAAmB,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,sBAAsB,EAAE,IAAI,EAAE;YACvF,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACpD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;YAC5B,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,mBAAmB,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,sBAAsB,EAAE,sBAAsB,EAAE;YACzG,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;YAC5B,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,mBAAmB,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,sBAAsB,EAAE,sBAAsB,EAAE;YACzG,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAC3B,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACvD,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC7F,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAC1K,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;gBACrE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;aACtE;YACD,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,oBAAoB,EAAE,iBAAiB;YACvC,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACxD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAChK,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;gBACrE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE;aACvF;YACD,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAC5J,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE;gBAC5E,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;aACrE;YACD,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QAC1J,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAC9E,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAChK,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;gBACrE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;aACtE;YACD,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,oBAAoB,EAAE,iBAAiB;YACvC,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG;YACb,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO;YAChC,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,EAAE,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;YAC9G,cAAc,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE;SACxC,CAAC;QACF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG;YACb,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO;YAChC,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,aAAa,EAAE,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;YAC/G,cAAc,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE;SACxC,CAAC;QACF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;QAChH,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YACjE,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;YACrD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SAC7E,CAAC;QACF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG;YACb,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO;YAChC,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,aAAa,EAAE,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;YAC/G,cAAc,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE;SACxC,CAAC;QACF,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YACjE,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;YACrD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SAC7E,CAAC;QACF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG;YAChB,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC,EAAE,oBAAoB,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE;SACzG,CAAC;QACF,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG;YAChB,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,EAAE,EAAE,EAAE,oBAAoB,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE;SACxG,CAAC;QACF,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAC3D,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG;YAChB,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE,EAAE,oBAAoB,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE;SACpG,CAAC;QACF,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAC3D,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG;YAChB,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE,oBAAoB,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;SACnG,CAAC;QACF,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG;YAChB,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,UAAU;YAClH,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE,oBAAoB,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,EAAE,UAAU;YAC9G,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,EAAE,EAAE,EAAE,oBAAoB,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,WAAW;SACvH,CAAC;QACF,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAC3D,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG;YAChB,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;SACtG,CAAC;QACF,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,wBAAwB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAClG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wEAAwE,EAAE,GAAG,EAAE;IACtF,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACtF,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,oCAAoC;QACpC,IAAI,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;QAChH,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACvE,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACzE,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,UAAU;gBAC9E,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE;gBAChE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE;aACrE;YACD,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YAC5E,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;gBAChE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;aAC3D;YACD,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oEAAoE,EAAE,GAAG,EAAE;IAClF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAC5J,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;gBACtE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;aACvE;YACD,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAChK,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;gBACrE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;aACtE;YACD,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAC5J,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI;YACf,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;gBACtE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;aACvE;YACD,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YAChD,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SACtD,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -4,4 +4,12 @@ export interface AlertRule {
4
4
  type: string;
5
5
  evaluate(snap: Snapshot, thresholds: Config["thresholds"]): AlertResult[];
6
6
  }
7
+ /**
8
+ * Stable, ordered list of every rule ID this collector ships. Exported as
9
+ * a public API so downstream tooling (Glassmkr's drift validator, Forge's
10
+ * UI registry) can verify both sides agree on what exists. When you add
11
+ * or remove a rule, this list updates automatically — but RULES.json in
12
+ * the Glassmkr monorepo is hand-maintained and must be updated separately.
13
+ */
14
+ export declare const ALL_RULE_IDS: readonly string[];
7
15
  export declare const allRules: AlertRule[];