@dipseth/opensearch-logs 0.1.0

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 (91) hide show
  1. package/.env.example +14 -0
  2. package/alerts/langfuse-usage.yaml +142 -0
  3. package/alerts/production-incidents.yaml +280 -0
  4. package/alerts/service-health.yaml +98 -0
  5. package/dashboards/langfuse-usage.yaml +57 -0
  6. package/dist/create-dashboards.d.ts +10 -0
  7. package/dist/create-dashboards.js +38 -0
  8. package/dist/create-dashboards.js.map +1 -0
  9. package/dist/interfaces/alert.interfaces.d.ts +323 -0
  10. package/dist/interfaces/alert.interfaces.js +6 -0
  11. package/dist/interfaces/alert.interfaces.js.map +1 -0
  12. package/dist/interfaces/dashboard-gen.interfaces.d.ts +33 -0
  13. package/dist/interfaces/dashboard-gen.interfaces.js +3 -0
  14. package/dist/interfaces/dashboard-gen.interfaces.js.map +1 -0
  15. package/dist/interfaces/interfaces.d.ts +312 -0
  16. package/dist/interfaces/interfaces.js +3 -0
  17. package/dist/interfaces/interfaces.js.map +1 -0
  18. package/dist/interfaces/playbook.interfaces.d.ts +140 -0
  19. package/dist/interfaces/playbook.interfaces.js +3 -0
  20. package/dist/interfaces/playbook.interfaces.js.map +1 -0
  21. package/dist/os-alert.d.ts +17 -0
  22. package/dist/os-alert.js +245 -0
  23. package/dist/os-alert.js.map +1 -0
  24. package/dist/os-dash.d.ts +9 -0
  25. package/dist/os-dash.js +53 -0
  26. package/dist/os-dash.js.map +1 -0
  27. package/dist/os-monitor.d.ts +12 -0
  28. package/dist/os-monitor.js +59 -0
  29. package/dist/os-monitor.js.map +1 -0
  30. package/dist/os-playbook.d.ts +9 -0
  31. package/dist/os-playbook.js +71 -0
  32. package/dist/os-playbook.js.map +1 -0
  33. package/dist/os-search.d.ts +11 -0
  34. package/dist/os-search.js +84 -0
  35. package/dist/os-search.js.map +1 -0
  36. package/dist/repositories/index.d.ts +1 -0
  37. package/dist/repositories/index.js +2 -0
  38. package/dist/repositories/index.js.map +1 -0
  39. package/dist/repositories/opensearch.repository.d.ts +51 -0
  40. package/dist/repositories/opensearch.repository.js +167 -0
  41. package/dist/repositories/opensearch.repository.js.map +1 -0
  42. package/dist/services/alert.service.d.ts +73 -0
  43. package/dist/services/alert.service.js +503 -0
  44. package/dist/services/alert.service.js.map +1 -0
  45. package/dist/services/dashboard-gen.service.d.ts +36 -0
  46. package/dist/services/dashboard-gen.service.js +162 -0
  47. package/dist/services/dashboard-gen.service.js.map +1 -0
  48. package/dist/services/dashboard.service.d.ts +33 -0
  49. package/dist/services/dashboard.service.js +428 -0
  50. package/dist/services/dashboard.service.js.map +1 -0
  51. package/dist/services/gchat.service.d.ts +45 -0
  52. package/dist/services/gchat.service.js +228 -0
  53. package/dist/services/gchat.service.js.map +1 -0
  54. package/dist/services/index.d.ts +8 -0
  55. package/dist/services/index.js +9 -0
  56. package/dist/services/index.js.map +1 -0
  57. package/dist/services/monitor.service.d.ts +18 -0
  58. package/dist/services/monitor.service.js +342 -0
  59. package/dist/services/monitor.service.js.map +1 -0
  60. package/dist/services/panel-layout.d.ts +21 -0
  61. package/dist/services/panel-layout.js +33 -0
  62. package/dist/services/panel-layout.js.map +1 -0
  63. package/dist/services/playbook-dashboard.service.d.ts +19 -0
  64. package/dist/services/playbook-dashboard.service.js +434 -0
  65. package/dist/services/playbook-dashboard.service.js.map +1 -0
  66. package/dist/services/playbook.service.d.ts +13 -0
  67. package/dist/services/playbook.service.js +621 -0
  68. package/dist/services/playbook.service.js.map +1 -0
  69. package/dist/services/search.service.d.ts +30 -0
  70. package/dist/services/search.service.js +885 -0
  71. package/dist/services/search.service.js.map +1 -0
  72. package/dist/utils/cli.d.ts +14 -0
  73. package/dist/utils/cli.js +90 -0
  74. package/dist/utils/cli.js.map +1 -0
  75. package/dist/utils/config.d.ts +20 -0
  76. package/dist/utils/config.js +104 -0
  77. package/dist/utils/config.js.map +1 -0
  78. package/dist/utils/index.d.ts +5 -0
  79. package/dist/utils/index.js +5 -0
  80. package/dist/utils/index.js.map +1 -0
  81. package/dist/utils/service-registry.d.ts +15 -0
  82. package/dist/utils/service-registry.js +56 -0
  83. package/dist/utils/service-registry.js.map +1 -0
  84. package/dist/utils/template.d.ts +18 -0
  85. package/dist/utils/template.js +66 -0
  86. package/dist/utils/template.js.map +1 -0
  87. package/package.json +76 -0
  88. package/playbooks/error-investigation.yaml +45 -0
  89. package/playbooks/incident-triage.yaml +32 -0
  90. package/playbooks/post-deploy-validation.yaml +24 -0
  91. package/playbooks/service-deep-dive.yaml +42 -0
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Monitor service — post-deploy validation and incident watch dashboards.
3
+ *
4
+ * Modes: post-deploy, incident-watch, spotlight, compare
5
+ */
6
+ import { resolveIndex, getServiceInfo } from "../utils/index.js";
7
+ // ── Known Patterns ────────────────────────────────────────────────────────
8
+ const INCIDENT_PATTERNS = {
9
+ "HTTP 500s": '"500 Internal Server Error"',
10
+ "HTTP 503s": "status=503",
11
+ "HTTP 502s": "status=502",
12
+ "Connection Refused": '"Connection refused"',
13
+ "Worker Shutdowns": '"Shutting down"',
14
+ "Worker Startups": '"Application startup complete"',
15
+ "Max Request Limit": '"Maximum request limit"',
16
+ "Playwright Failures": '"Failed to launch browser"',
17
+ "OOM / Memory": 'OOM OR "Cannot allocate memory"',
18
+ "API Key Missing": '"ENCORE_G_API_KEY: None" OR "ENCORE_G_API_KEY: NOT SET"',
19
+ "Client Timeouts (499)": "status=499",
20
+ };
21
+ const DEAL_STRUCTURE_PATTERNS = {
22
+ "deal_structure 500": 'log: "deal_structure" AND log: "500"',
23
+ "deal_structure 502": 'log: "deal_structure" AND log: "status=502"',
24
+ "deal_structure refused": 'log: "Connection refused" AND log: "deal_structure"',
25
+ "deal_structure 200": 'log: "deal_structure" AND log: "status=200"',
26
+ "deal_structure 422": 'log: "deal_structure" AND log: "status=422"',
27
+ };
28
+ export class MonitorService {
29
+ repo;
30
+ constructor(repo) {
31
+ this.repo = repo;
32
+ }
33
+ // ── Helpers ─────────────────────────────────────────────────────────
34
+ async countPatterns(index, patterns, fromDt, toDt) {
35
+ const timeFilter = { range: { "@timestamp": { gte: fromDt.toISOString(), lte: toDt.toISOString() } } };
36
+ const aggs = {};
37
+ for (const [name, query] of Object.entries(patterns)) {
38
+ const safe = name.replace(/[^a-zA-Z0-9]/g, "_");
39
+ aggs[safe] = {
40
+ filter: { bool: { must: [{ query_string: { query } }], filter: [timeFilter] } },
41
+ };
42
+ }
43
+ aggs._total = { filter: { bool: { filter: [timeFilter] } } };
44
+ const result = await this.repo.search(index, { size: 0, aggs });
45
+ const aggData = result.aggregations;
46
+ const counts = {};
47
+ for (const name of Object.keys(patterns)) {
48
+ const safe = name.replace(/[^a-zA-Z0-9]/g, "_");
49
+ counts[name] = aggData[safe]?.doc_count ?? 0;
50
+ }
51
+ counts._total = aggData._total?.doc_count ?? 0;
52
+ return counts;
53
+ }
54
+ async getRecentLogs(index, pattern, fromDt, toDt, limit = 5) {
55
+ const result = await this.repo.search(index, {
56
+ size: limit,
57
+ sort: [{ "@timestamp": "desc" }],
58
+ query: {
59
+ bool: {
60
+ must: [{ query_string: { query: pattern } }],
61
+ filter: [{ range: { "@timestamp": { gte: fromDt.toISOString(), lte: toDt.toISOString() } } }],
62
+ },
63
+ },
64
+ _source: ["@timestamp", "log", "service", "level", "status_code"],
65
+ });
66
+ return result.hits.hits.map(h => h._source);
67
+ }
68
+ fmtDelta(current, baseline) {
69
+ if (baseline === 0 && current === 0)
70
+ return " --";
71
+ if (baseline === 0)
72
+ return ` +${current} NEW`;
73
+ if (current === 0)
74
+ return ` (was ${baseline})`;
75
+ const diff = current - baseline;
76
+ const pct = (diff / baseline * 100);
77
+ if (diff > 0)
78
+ return ` +${diff} (+${Math.round(pct)}%)`;
79
+ if (diff < 0)
80
+ return ` ${diff} (${Math.round(pct)}%)`;
81
+ return " (unchanged)";
82
+ }
83
+ // ── Mode: post-deploy ───────────────────────────────────────────────
84
+ async modePostDeploy(args) {
85
+ const now = new Date();
86
+ const minutes = args.minutes ?? 15;
87
+ const currentFrom = new Date(now.getTime() - minutes * 60_000);
88
+ const currentTo = now;
89
+ const baselineTo = currentFrom;
90
+ const baselineFrom = new Date(baselineTo.getTime() - minutes * 60_000);
91
+ const index = resolveIndex("production", baselineFrom, currentTo);
92
+ const current = await this.countPatterns(index, INCIDENT_PATTERNS, currentFrom, currentTo);
93
+ const baseline = await this.countPatterns(index, INCIDENT_PATTERNS, baselineFrom, baselineTo);
94
+ const window = `${fmtTime(currentFrom)} - ${fmtTime(currentTo)} UTC`;
95
+ const baseWindow = `${fmtTime(baselineFrom)} - ${fmtTime(baselineTo)} UTC`;
96
+ console.log(`\n${"=".repeat(72)}`);
97
+ console.log(" POST-DEPLOY HEALTH CHECK");
98
+ console.log(` Current: ${window} (${current._total?.toLocaleString() ?? 0} log entries)`);
99
+ console.log(` Baseline: ${baseWindow} (${baseline._total?.toLocaleString() ?? 0} log entries)`);
100
+ console.log(`${"=".repeat(72)}\n`);
101
+ let criticalIssues = 0;
102
+ for (const name of Object.keys(INCIDENT_PATTERNS)) {
103
+ if ((current[name] ?? 0) > 0 && ["HTTP 500s", "Connection Refused", "OOM / Memory"].includes(name)) {
104
+ criticalIssues++;
105
+ }
106
+ }
107
+ if (criticalIssues === 0 && (current["HTTP 500s"] ?? 0) === 0) {
108
+ console.log(" STATUS: HEALTHY");
109
+ }
110
+ else if (criticalIssues > 0) {
111
+ console.log(` STATUS: DEGRADED (${criticalIssues} critical pattern(s) active)`);
112
+ }
113
+ else {
114
+ console.log(" STATUS: WARNING (non-critical issues detected)");
115
+ }
116
+ console.log(`\n ${"Pattern".padEnd(28)} ${"Now".padStart(8)} ${"Baseline".padStart(8)} ${"Change".padStart(18)}`);
117
+ console.log(` ${"-".repeat(28)} ${"-".repeat(8)} ${"-".repeat(8)} ${"-".repeat(18)}`);
118
+ for (const name of Object.keys(INCIDENT_PATTERNS)) {
119
+ const cur = current[name] ?? 0;
120
+ const base = baseline[name] ?? 0;
121
+ console.log(` ${name.padEnd(28)} ${String(cur).padStart(8)} ${String(base).padStart(8)} ${this.fmtDelta(cur, base)}`);
122
+ }
123
+ // Deal structure specific
124
+ console.log(`\n ── Deal Structure Service ──\n`);
125
+ const dsCurrent = await this.countPatterns(index, DEAL_STRUCTURE_PATTERNS, currentFrom, currentTo);
126
+ const dsBaseline = await this.countPatterns(index, DEAL_STRUCTURE_PATTERNS, baselineFrom, baselineTo);
127
+ console.log(` ${"Pattern".padEnd(28)} ${"Now".padStart(8)} ${"Baseline".padStart(8)} ${"Change".padStart(18)}`);
128
+ console.log(` ${"-".repeat(28)} ${"-".repeat(8)} ${"-".repeat(8)} ${"-".repeat(18)}`);
129
+ for (const name of Object.keys(DEAL_STRUCTURE_PATTERNS)) {
130
+ const cur = dsCurrent[name] ?? 0;
131
+ const base = dsBaseline[name] ?? 0;
132
+ console.log(` ${name.padEnd(28)} ${String(cur).padStart(8)} ${String(base).padStart(8)} ${this.fmtDelta(cur, base)}`);
133
+ }
134
+ console.log();
135
+ }
136
+ // ── Mode: incident-watch ────────────────────────────────────────────
137
+ async modeIncidentWatch(args) {
138
+ const now = new Date();
139
+ const hours = args.hours ?? 1;
140
+ const fromDt = new Date(now.getTime() - hours * 3600_000);
141
+ const toDt = now;
142
+ const index = resolveIndex("production", fromDt, toDt);
143
+ const counts = await this.countPatterns(index, INCIDENT_PATTERNS, fromDt, toDt);
144
+ const window = `${fmtTime(fromDt)} - ${fmtTime(toDt)} UTC`;
145
+ console.log(`\n${"=".repeat(64)}`);
146
+ console.log(` INCIDENT WATCHBOARD (${window})`);
147
+ console.log(` Total log entries: ${(counts._total ?? 0).toLocaleString()}`);
148
+ console.log(`${"=".repeat(64)}\n`);
149
+ const critical = [];
150
+ const warning = [];
151
+ const ok = [];
152
+ for (const [name] of Object.entries(INCIDENT_PATTERNS)) {
153
+ const count = counts[name] ?? 0;
154
+ const rate = hours > 0 ? count / hours : count;
155
+ if (["HTTP 500s", "Connection Refused", "OOM / Memory"].includes(name) && count > 0) {
156
+ critical.push([name, count, rate]);
157
+ }
158
+ else if (count > 0) {
159
+ warning.push([name, count, rate]);
160
+ }
161
+ else {
162
+ ok.push([name, count, rate]);
163
+ }
164
+ }
165
+ if (critical.length) {
166
+ console.log(" CRITICAL:\n");
167
+ for (const [name, count, rate] of critical) {
168
+ console.log(` ${name.padEnd(28)} ${String(count).padStart(6)} (${String(Math.round(rate)).padStart(6)}/hr)`);
169
+ }
170
+ }
171
+ if (warning.length) {
172
+ console.log(`\n WARNING:\n`);
173
+ for (const [name, count, rate] of warning) {
174
+ console.log(` ${name.padEnd(28)} ${String(count).padStart(6)} (${String(Math.round(rate)).padStart(6)}/hr)`);
175
+ }
176
+ }
177
+ if (ok.length) {
178
+ console.log(`\n OK:\n`);
179
+ for (const [name, count] of ok) {
180
+ console.log(` ${name.padEnd(28)} ${String(count).padStart(6)}`);
181
+ }
182
+ }
183
+ // Deal structure spotlight
184
+ console.log(`\n ── Deal Structure ──\n`);
185
+ const dsCounts = await this.countPatterns(index, DEAL_STRUCTURE_PATTERNS, fromDt, toDt);
186
+ for (const name of Object.keys(DEAL_STRUCTURE_PATTERNS)) {
187
+ const count = dsCounts[name] ?? 0;
188
+ if (name.includes("200")) {
189
+ console.log(` ${name.padEnd(28)} ${String(count).padStart(6)} (success)`);
190
+ }
191
+ else {
192
+ console.log(` ${name.padEnd(28)} ${String(count).padStart(6)}`);
193
+ }
194
+ }
195
+ // Recent errors
196
+ console.log(`\n ── Recent Error Samples ──\n`);
197
+ const errors = await this.getRecentLogs(index, '"500 Internal Server Error" OR "Connection refused"', fromDt, toDt, 5);
198
+ if (errors.length) {
199
+ for (const e of errors) {
200
+ const log = String(e.log ?? "").slice(0, 150);
201
+ console.log(` [${e["@timestamp"]}] ${log}`);
202
+ }
203
+ }
204
+ else {
205
+ console.log(" No 500s or Connection Refused in this window.");
206
+ }
207
+ console.log();
208
+ }
209
+ // ── Mode: spotlight ─────────────────────────────────────────────────
210
+ async modeSpotlight(args) {
211
+ if (!args.service) {
212
+ console.error("ERROR: --service is required for spotlight mode");
213
+ process.exit(1);
214
+ }
215
+ const service = args.service;
216
+ const svcInfo = getServiceInfo(service);
217
+ const svcName = svcInfo?.logName ?? service;
218
+ const desc = svcInfo?.description ?? service;
219
+ const port = svcInfo?.port ?? "";
220
+ const now = new Date();
221
+ const hours = args.hours ?? 1;
222
+ const fromDt = new Date(now.getTime() - hours * 3600_000);
223
+ const toDt = now;
224
+ const index = resolveIndex("production", fromDt, toDt);
225
+ const window = `${fmtTime(fromDt)} - ${fmtTime(toDt)} UTC`;
226
+ console.log(`\n${"=".repeat(64)}`);
227
+ console.log(` SERVICE SPOTLIGHT: ${desc} (${svcName})`);
228
+ console.log(` Port: ${port} | Window: ${window}`);
229
+ console.log(`${"=".repeat(64)}\n`);
230
+ const svcPatterns = {
231
+ [`${service} 200s`]: `log: "${service}" AND log: "status=200"`,
232
+ [`${service} 422s`]: `log: "${service}" AND log: "status=422"`,
233
+ [`${service} 500s`]: `log: "${service}" AND (log: "500" OR log: "status=500")`,
234
+ [`${service} 502s`]: `log: "${service}" AND log: "status=502"`,
235
+ [`${service} 503s`]: `log: "${service}" AND log: "status=503"`,
236
+ [`${service} conn refused`]: `log: "Connection refused" AND log: "${service}"`,
237
+ [`${service} timeouts (499)`]: `log: "${service}" AND log: "status=499"`,
238
+ };
239
+ const counts = await this.countPatterns(index, svcPatterns, fromDt, toDt);
240
+ console.log(" Traffic & Errors:\n");
241
+ console.log(` ${"Metric".padEnd(32)} ${"Count".padStart(8)}`);
242
+ console.log(` ${"-".repeat(32)} ${"-".repeat(8)}`);
243
+ for (const name of Object.keys(svcPatterns)) {
244
+ const count = counts[name] ?? 0;
245
+ const indicator = count === 0 || name.includes("200") ? "" : " !!";
246
+ console.log(` ${name.padEnd(32)} ${String(count).padStart(8)}${indicator}`);
247
+ }
248
+ // Recent activity
249
+ console.log(`\n ── Recent Activity ──\n`);
250
+ const logs = await this.getRecentLogs(index, `log: "${service}"`, fromDt, toDt, 10);
251
+ if (logs.length) {
252
+ for (const entry of logs) {
253
+ const log = String(entry.log ?? "").slice(0, 200);
254
+ console.log(` [${entry["@timestamp"]}] ${log}`);
255
+ }
256
+ }
257
+ else {
258
+ console.log(` No activity for ${service} in this window.`);
259
+ }
260
+ const linkQuery = encodeURIComponent(`log: "${service}"`);
261
+ const timeG = `_g=(time:(from:'${fromDt.toISOString()}',to:'${toDt.toISOString()}'))`;
262
+ const queryA = `_a=(query:(language:kuery,query:'${linkQuery}'))`;
263
+ console.log(`\n Dashboard: https://${this.repo.config.host}/app/dashboards?security_tenant=global#/view/python-services-production-health-v2?${timeG}&${queryA}`);
264
+ console.log(` Discover: https://${this.repo.config.host}/app/discover?security_tenant=global#/?${timeG}&${queryA}`);
265
+ console.log();
266
+ }
267
+ // ── Mode: compare ───────────────────────────────────────────────────
268
+ async modeCompare(args) {
269
+ if (!args.from1 || !args.to1 || !args.from2 || !args.to2) {
270
+ console.error("ERROR: --from1, --to1, --from2, --to2 are all required for compare mode");
271
+ process.exit(1);
272
+ }
273
+ const w1From = new Date(args.from1.replace("Z", "+00:00"));
274
+ const w1To = new Date(args.to1.replace("Z", "+00:00"));
275
+ const w2From = new Date(args.from2.replace("Z", "+00:00"));
276
+ const w2To = new Date(args.to2.replace("Z", "+00:00"));
277
+ const index = resolveIndex("production");
278
+ const w1Counts = await this.countPatterns(index, INCIDENT_PATTERNS, w1From, w1To);
279
+ const w2Counts = await this.countPatterns(index, INCIDENT_PATTERNS, w2From, w2To);
280
+ const w1Label = `${fmtTime(w1From)}-${fmtTime(w1To)}`;
281
+ const w2Label = `${fmtTime(w2From)}-${fmtTime(w2To)}`;
282
+ const w1Dur = (w1To.getTime() - w1From.getTime()) / 3_600_000;
283
+ const w2Dur = (w2To.getTime() - w2From.getTime()) / 3_600_000;
284
+ console.log(`\n${"=".repeat(72)}`);
285
+ console.log(" WINDOW COMPARISON");
286
+ console.log(` Window A: ${w1Label} (${w1Dur.toFixed(1)}h, ${(w1Counts._total ?? 0).toLocaleString()} logs)`);
287
+ console.log(` Window B: ${w2Label} (${w2Dur.toFixed(1)}h, ${(w2Counts._total ?? 0).toLocaleString()} logs)`);
288
+ console.log(`${"=".repeat(72)}\n`);
289
+ console.log(` ${"Pattern".padEnd(28)} ${"Window A".padStart(10)} ${"A/hr".padStart(8)} ${"Window B".padStart(10)} ${"B/hr".padStart(8)} ${"Change".padStart(12)}`);
290
+ console.log(` ${"-".repeat(28)} ${"-".repeat(10)} ${"-".repeat(8)} ${"-".repeat(10)} ${"-".repeat(8)} ${"-".repeat(12)}`);
291
+ for (const name of Object.keys(INCIDENT_PATTERNS)) {
292
+ const a = w1Counts[name] ?? 0;
293
+ const b = w2Counts[name] ?? 0;
294
+ const aRate = w1Dur > 0 ? a / w1Dur : 0;
295
+ const bRate = w2Dur > 0 ? b / w2Dur : 0;
296
+ let change;
297
+ if (a === 0 && b === 0)
298
+ change = "--";
299
+ else if (a === 0)
300
+ change = "NEW";
301
+ else if (b === 0)
302
+ change = "FIXED";
303
+ else if (b < a)
304
+ change = `-${Math.round(((a - b) / a) * 100)}%`;
305
+ else if (b > a)
306
+ change = `+${Math.round(((b - a) / a) * 100)}%`;
307
+ else
308
+ change = "same";
309
+ console.log(` ${name.padEnd(28)} ${String(a).padStart(10)} ${`${Math.round(aRate)}/h`.padStart(8)} ${String(b).padStart(10)} ${`${Math.round(bRate)}/h`.padStart(8)} ${change.padStart(12)}`);
310
+ }
311
+ // Deal structure comparison
312
+ console.log(`\n ── Deal Structure ──\n`);
313
+ const ds1 = await this.countPatterns(index, DEAL_STRUCTURE_PATTERNS, w1From, w1To);
314
+ const ds2 = await this.countPatterns(index, DEAL_STRUCTURE_PATTERNS, w2From, w2To);
315
+ console.log(` ${"Pattern".padEnd(28)} ${"Window A".padStart(10)} ${"Window B".padStart(10)} ${"Change".padStart(12)}`);
316
+ console.log(` ${"-".repeat(28)} ${"-".repeat(10)} ${"-".repeat(10)} ${"-".repeat(12)}`);
317
+ for (const name of Object.keys(DEAL_STRUCTURE_PATTERNS)) {
318
+ const a = ds1[name] ?? 0;
319
+ const b = ds2[name] ?? 0;
320
+ let change;
321
+ if (a === 0 && b === 0)
322
+ change = "--";
323
+ else if (a === 0)
324
+ change = "NEW";
325
+ else if (b === 0)
326
+ change = "FIXED";
327
+ else if (b < a)
328
+ change = `-${Math.round(((a - b) / a) * 100)}%`;
329
+ else if (b > a)
330
+ change = `+${Math.round(((b - a) / a) * 100)}%`;
331
+ else
332
+ change = "same";
333
+ console.log(` ${name.padEnd(28)} ${String(a).padStart(10)} ${String(b).padStart(10)} ${change.padStart(12)}`);
334
+ }
335
+ console.log();
336
+ }
337
+ }
338
+ // ── Helpers ─────────────────────────────────────────────────────────────
339
+ function fmtTime(d) {
340
+ return d.toISOString().slice(11, 16);
341
+ }
342
+ //# sourceMappingURL=monitor.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.service.js","sourceRoot":"","sources":["../../src/services/monitor.service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,YAAY,EAAoB,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnF,6EAA6E;AAE7E,MAAM,iBAAiB,GAA2B;IAChD,WAAW,EAAe,6BAA6B;IACvD,WAAW,EAAe,YAAY;IACtC,WAAW,EAAe,YAAY;IACtC,oBAAoB,EAAM,sBAAsB;IAChD,kBAAkB,EAAQ,iBAAiB;IAC3C,iBAAiB,EAAS,gCAAgC;IAC1D,mBAAmB,EAAO,yBAAyB;IACnD,qBAAqB,EAAK,4BAA4B;IACtD,cAAc,EAAY,iCAAiC;IAC3D,iBAAiB,EAAS,yDAAyD;IACnF,uBAAuB,EAAG,YAAY;CACvC,CAAC;AAEF,MAAM,uBAAuB,GAA2B;IACtD,oBAAoB,EAAM,sCAAsC;IAChE,oBAAoB,EAAM,6CAA6C;IACvE,wBAAwB,EAAE,qDAAqD;IAC/E,oBAAoB,EAAM,6CAA6C;IACvE,oBAAoB,EAAM,6CAA6C;CACxE,CAAC;AAEF,MAAM,OAAO,cAAc;IACL;IAApB,YAAoB,IAA0B;QAA1B,SAAI,GAAJ,IAAI,CAAsB;IAAG,CAAC;IAElD,uEAAuE;IAE/D,KAAK,CAAC,aAAa,CACzB,KAAa,EACb,QAAgC,EAChC,MAAY,EACZ,IAAU;QAEV,MAAM,UAAU,GAAgB,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,CAAC;QACpH,MAAM,IAAI,GAAgC,EAAE,CAAC;QAE7C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;YAChD,IAAI,CAAC,IAAI,CAAC,GAAG;gBACX,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE;aAChF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC;QAE7D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAmB,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,OAAO,GAAG,MAAM,CAAC,YAAa,CAAC;QAErC,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,IAAI,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,KAAa,EACb,OAAe,EACf,MAAY,EACZ,IAAU,EACV,KAAK,GAAG,CAAC;QAET,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;YAC3C,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;YAChC,KAAK,EAAE;gBACL,IAAI,EAAE;oBACJ,IAAI,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;oBAC5C,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,CAAC;iBAC9F;aACF;YACD,OAAO,EAAE,CAAC,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC;SAClE,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAEO,QAAQ,CAAC,OAAe,EAAE,QAAgB;QAChD,IAAI,QAAQ,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC;QACnD,IAAI,QAAQ,KAAK,CAAC;YAAE,OAAO,KAAK,OAAO,MAAM,CAAC;QAC9C,IAAI,OAAO,KAAK,CAAC;YAAE,OAAO,SAAS,QAAQ,GAAG,CAAC;QAC/C,MAAM,IAAI,GAAG,OAAO,GAAG,QAAQ,CAAC;QAChC,MAAM,GAAG,GAAG,CAAC,IAAI,GAAG,QAAQ,GAAG,GAAG,CAAC,CAAC;QACpC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,KAAK,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QACxD,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,IAAI,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QACtD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,uEAAuE;IAEvE,KAAK,CAAC,cAAc,CAAC,IAAiB;QACpC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QACnC,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,GAAG,CAAC;QACtB,MAAM,UAAU,GAAG,WAAW,CAAC;QAC/B,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC;QAEvE,MAAM,KAAK,GAAG,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;QAElE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QAC3F,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QAE9F,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC;QACrE,MAAM,UAAU,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;QAE3E,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7F,OAAO,CAAC,GAAG,CAAC,eAAe,UAAU,MAAM,QAAQ,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAEnC,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,oBAAoB,EAAE,cAAc,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnG,cAAc,EAAE,CAAC;YACnB,CAAC;QACH,CAAC;QAED,IAAI,cAAc,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9D,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,uBAAuB,cAAc,8BAA8B,CAAC,CAAC;QACnF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,OAAO,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnH,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAEvF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAClD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACzH,CAAC;QAED,0BAA0B;QAC1B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,uBAAuB,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QACnG,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QAEtG,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACjH,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACvF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,EAAE,CAAC;YACxD,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACzH,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,uEAAuE;IAEvE,KAAK,CAAC,iBAAiB,CAAC,IAAiB;QACvC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,GAAG,QAAQ,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,GAAG,CAAC;QACjB,MAAM,KAAK,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAEvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAE3D,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,GAAG,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAEnC,MAAM,QAAQ,GAA+B,EAAE,CAAC;QAChD,MAAM,OAAO,GAA+B,EAAE,CAAC;QAC/C,MAAM,EAAE,GAA+B,EAAE,CAAC;QAE1C,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACvD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YAC/C,IAAI,CAAC,WAAW,EAAE,oBAAoB,EAAE,cAAc,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACpF,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;YACrC,CAAC;iBAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACrB,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACnH,CAAC;QACH,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;gBAC1C,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACnH,CAAC;QACH,CAAC;QACD,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACzB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC/B,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAED,2BAA2B;QAC3B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACxF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,EAAE,CAAC;YACxD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;YAChF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAED,gBAAgB;QAChB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,qDAAqD,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvH,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,uEAAuE;IAEvE,KAAK,CAAC,aAAa,CAAC,IAAiB;QACnC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC;QAC5C,MAAM,IAAI,GAAG,OAAO,EAAE,WAAW,IAAI,OAAO,CAAC;QAC7C,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;QAEjC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,GAAG,QAAQ,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,GAAG,CAAC;QACjB,MAAM,KAAK,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAE3D,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,KAAK,OAAO,GAAG,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,gBAAgB,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAEnC,MAAM,WAAW,GAA2B;YAC1C,CAAC,GAAG,OAAO,OAAO,CAAC,EAAa,SAAS,OAAO,yBAAyB;YACzE,CAAC,GAAG,OAAO,OAAO,CAAC,EAAa,SAAS,OAAO,yBAAyB;YACzE,CAAC,GAAG,OAAO,OAAO,CAAC,EAAa,SAAS,OAAO,yCAAyC;YACzF,CAAC,GAAG,OAAO,OAAO,CAAC,EAAa,SAAS,OAAO,yBAAyB;YACzE,CAAC,GAAG,OAAO,OAAO,CAAC,EAAa,SAAS,OAAO,yBAAyB;YACzE,CAAC,GAAG,OAAO,eAAe,CAAC,EAAK,uCAAuC,OAAO,GAAG;YACjF,CAAC,GAAG,OAAO,iBAAiB,CAAC,EAAG,SAAS,OAAO,yBAAyB;SAC1E,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAE1E,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,SAAS,GAAG,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;YACnE,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC;QAC/E,CAAC;QAED,kBAAkB;QAClB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QACpF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;gBACzB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;gBAClD,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,YAAY,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,qBAAqB,OAAO,kBAAkB,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,mBAAmB,MAAM,CAAC,WAAW,EAAE,SAAS,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC;QACtF,MAAM,MAAM,GAAG,oCAAoC,SAAS,KAAK,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,qFAAqF,KAAK,IAAI,MAAM,EAAE,CAAC,CAAC;QACnK,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,0CAA0C,KAAK,IAAI,MAAM,EAAE,CAAC,CAAC;QACtH,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,uEAAuE;IAEvE,KAAK,CAAC,WAAW,CAAC,IAAiB;QACjC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACzD,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;YACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;QAEvD,MAAM,KAAK,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAEzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAElF,MAAM,OAAO,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC;QAC9D,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC;QAE9D,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,eAAe,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QAC9G,OAAO,CAAC,GAAG,CAAC,eAAe,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QAC9G,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAEnC,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACpK,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAE3H,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAClD,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAExC,IAAI,MAAc,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,GAAG,IAAI,CAAC;iBACjC,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,GAAG,KAAK,CAAC;iBAC5B,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,GAAG,OAAO,CAAC;iBAC9B,IAAI,CAAC,GAAG,CAAC;gBAAE,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;iBAC3D,IAAI,CAAC,GAAG,CAAC;gBAAE,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;;gBAC3D,MAAM,GAAG,MAAM,CAAC;YAErB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACjM,CAAC;QAED,4BAA4B;QAC5B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACnF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAEnF,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACxH,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAEzF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,EAAE,CAAC;YACxD,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,MAAc,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,GAAG,IAAI,CAAC;iBACjC,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,GAAG,KAAK,CAAC;iBAC5B,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,GAAG,OAAO,CAAC;iBAC9B,IAAI,CAAC,GAAG,CAAC;gBAAE,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;iBAC3D,IAAI,CAAC,GAAG,CAAC;gBAAE,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;;gBAC3D,MAAM,GAAG,MAAM,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACjH,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;CACF;AAED,2EAA2E;AAE3E,SAAS,OAAO,CAAC,CAAO;IACtB,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Auto-layout grid for OSD dashboard panels.
3
+ *
4
+ * OSD uses a 48-column grid. This class tracks a cursor that wraps
5
+ * automatically and provides newRow() for visual separation between sections.
6
+ */
7
+ export interface PanelPosition {
8
+ x: number;
9
+ y: number;
10
+ w: number;
11
+ h: number;
12
+ }
13
+ export declare class GridLayout {
14
+ private x;
15
+ private y;
16
+ private rowHeight;
17
+ /** Add a panel of the given size. Returns its position. */
18
+ add(w: number, h: number): PanelPosition;
19
+ /** Start a new row (flush current row height). */
20
+ newRow(): void;
21
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Auto-layout grid for OSD dashboard panels.
3
+ *
4
+ * OSD uses a 48-column grid. This class tracks a cursor that wraps
5
+ * automatically and provides newRow() for visual separation between sections.
6
+ */
7
+ const GRID_WIDTH = 48;
8
+ export class GridLayout {
9
+ x = 0;
10
+ y = 0;
11
+ rowHeight = 0;
12
+ /** Add a panel of the given size. Returns its position. */
13
+ add(w, h) {
14
+ if (this.x + w > GRID_WIDTH) {
15
+ this.x = 0;
16
+ this.y += this.rowHeight;
17
+ this.rowHeight = 0;
18
+ }
19
+ const pos = { x: this.x, y: this.y, w, h };
20
+ this.x += w;
21
+ this.rowHeight = Math.max(this.rowHeight, h);
22
+ return pos;
23
+ }
24
+ /** Start a new row (flush current row height). */
25
+ newRow() {
26
+ if (this.x > 0) {
27
+ this.x = 0;
28
+ this.y += this.rowHeight;
29
+ this.rowHeight = 0;
30
+ }
31
+ }
32
+ }
33
+ //# sourceMappingURL=panel-layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-layout.js","sourceRoot":"","sources":["../../src/services/panel-layout.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,MAAM,OAAO,UAAU;IACb,CAAC,GAAG,CAAC,CAAC;IACN,CAAC,GAAG,CAAC,CAAC;IACN,SAAS,GAAG,CAAC,CAAC;IAEtB,2DAA2D;IAC3D,GAAG,CAAC,CAAS,EAAE,CAAS;QACtB,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,UAAU,EAAE,CAAC;YAC5B,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACX,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC;YACzB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,MAAM,GAAG,GAAkB,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1D,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC7C,OAAO,GAAG,CAAC;IACb,CAAC;IAED,kDAAkD;IAClD,MAAM;QACJ,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACX,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC;YACzB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Playbook dashboard generator — transforms StepResult data into an OSD
3
+ * saved dashboard that mirrors the visual style of the static production
4
+ * health dashboard: metric tile rows + paired half-width line charts.
5
+ *
6
+ * Design principles:
7
+ * - Visuals first: metric tiles for key numbers, line charts for trends
8
+ * - Markdown only for header and evidence appendix (samples that can't
9
+ * be visualized as live queries)
10
+ * - Thematic chart grouping (HTTP errors, worker lifecycle, infrastructure)
11
+ * - Same panel sizes as the reference dashboard (8×6 metrics, 24×12 charts)
12
+ */
13
+ import type { OpenSearchRepository } from "../repositories/index.js";
14
+ import type { Playbook, StepResult, PipelineContext } from "../interfaces/playbook.interfaces.js";
15
+ export declare class PlaybookDashboardService {
16
+ private repo;
17
+ constructor(repo: OpenSearchRepository);
18
+ generate(playbook: Playbook, results: Map<string, StepResult>, ctx: PipelineContext): Promise<string>;
19
+ }