- 1
//! Screen 2: Remote Observability & Operations Deck. - 2
//! - 3
//! All data is real — incident stream from `AgentEvent` SSE events, - 4
//! audit receipts from real server work, Merkle graph from causal lineage - 5
//! in presentation events, KPI gauges from `/health`, provider latency - 6
//! from real provider info. - 7
- 8
use ratatui::buffer::Buffer; - 9
use ratatui::layout::{Constraint, Direction, Layout, Rect}; - 10
use ratatui::style::Modifier; - 11
use ratatui::text::{Line, Span}; - 12
use ratatui::widgets::{Block, Borders, Paragraph, Widget}; - 13
- 14
use crate::api::HealthReport; - 15
use crate::app::{AuditEntry, DeckFocus, IncidentEntry, MerkleNode}; - 16
use crate::telemetry::TelemetryState; - 17
use crate::theme::{Symbols, Theme}; - 18
- 19
pub struct OpsView<'a> { - 20
pub telemetry: &'a TelemetryState, - 21
pub theme: &'a Theme, - 22
pub deck_focus: DeckFocus, - 23
pub incidents: &'a [IncidentEntry], - 24
pub audit_entries: &'a [AuditEntry], - 25
pub merkle_nodes: &'a [MerkleNode], - 26
pub health: &'a HealthReport, - 27
} - 28
- 29
impl<'a> Widget for OpsView<'a> { - 30
fn render(self, area: Rect, buf: &mut Buffer) { - 31
let left_border = if self.deck_focus == DeckFocus::Left { - 32
self.theme.style_border_focus() - 33
} else { - 34
self.theme.style_border() - 35
}; - 36
let right_border = if self.deck_focus == DeckFocus::Right { - 37
self.theme.style_border_focus() - 38
} else { - 39
self.theme.style_border() - 40
}; - 41
- 42
let main_chunks = Layout::default() - 43
.direction(Direction::Vertical) - 44
.constraints([Constraint::Length(3), Constraint::Min(10)]) - 45
.split(area); - 46
- 47
// 1. Top KPI Row - 48
let kpi_chunks = Layout::default() - 49
.direction(Direction::Horizontal) - 50
.constraints([ - 51
Constraint::Percentage(25), - 52
Constraint::Percentage(25), - 53
Constraint::Percentage(25), - 54
Constraint::Percentage(25), - 55
]) - 56
.split(main_chunks[0]); - 57
- 58
// FinOps — real from health checks - 59
let spend_str = if self.telemetry.spend_today_usd > 0.0 { - 60
format!( - 61
"${:.2} / ${:.2}", - 62
self.telemetry.spend_today_usd, self.telemetry.spend_budget_cap_usd - 63
) - 64
} else { - 65
"no budget configured".to_string() - 66
}; - 67
let finops_block = Block::default() - 68
.borders(Borders::ALL) - 69
.border_style(self.theme.style_border()); - 70
let finops_para = Paragraph::new(Line::from(vec![ - 71
Span::styled("FinOps: ", self.theme.style_card()), - 72
Span::styled( - 73
spend_str, - 74
self.theme.style_accent().add_modifier(Modifier::BOLD), - 75
), - 76
])) - 77
.block(finops_block); - 78
finops_para.render(kpi_chunks[0], buf); - 79
- 80
// Circuit Breaker — real from health - 81
let cb_state = if self.health.circuit_breaker_healthy { - 82
"100% HEALTHY" - 83
} else { - 84
"OPEN" - 85
}; - 86
let cb_style = if self.health.circuit_breaker_healthy { - 87
self.theme.style_ok() - 88
} else { - 89
self.theme.style_danger() - 90
}; - 91
let cb_block = Block::default() - 92
.borders(Borders::ALL) - 93
.border_style(self.theme.style_border()); - 94
let cb_para = Paragraph::new(Line::from(vec![ - 95
Span::styled("Breakers: ", self.theme.style_card()), - 96
Span::styled(cb_state, cb_style.add_modifier(Modifier::BOLD)), - 97
])) - 98
.block(cb_block); - 99
cb_para.render(kpi_chunks[1], buf); - 100
- 101
// Services — real from health warnings - 102
let service_status = if self.telemetry.active_services_count.1 > 0 { - 103
format!( - 104
"{}/{} ONLINE", - 105
self.telemetry.active_services_count.0, self.telemetry.active_services_count.1 - 106
) - 107
} else { - 108
"(no services)".to_string() - 109
}; - 110
let srv_block = Block::default() - 111
.borders(Borders::ALL) - 112
.border_style(self.theme.style_border()); - 113
let srv_para = Paragraph::new(Line::from(vec![ - 114
Span::styled("Services: ", self.theme.style_card()), - 115
Span::styled( - 116
service_status, - 117
self.theme.style_ok().add_modifier(Modifier::BOLD), - 118
), - 119
])) - 120
.block(srv_block); - 121
srv_para.render(kpi_chunks[2], buf); - 122
- 123
// Bus Queue — real from health checks - 124
let bus_count = self.telemetry.bus_dlq_count; - 125
let bus_str = if bus_count == 0 { - 126
"0 DLQ".to_string() - 127
} else { - 128
format!("{bus_count} DLQ") - 129
}; - 130
let bus_block = Block::default() - 131
.borders(Borders::ALL) - 132
.border_style(self.theme.style_border()); - 133
let bus_para = Paragraph::new(Line::from(vec![ - 134
Span::styled("Bus Queue: ", self.theme.style_card()), - 135
Span::styled(bus_str, self.theme.style_card()), - 136
])) - 137
.block(bus_block); - 138
bus_para.render(kpi_chunks[3], buf); - 139
- 140
// 2. Dual-Deck Split - 141
let deck_chunks = Layout::default() - 142
.direction(Direction::Horizontal) - 143
.constraints([Constraint::Percentage(60), Constraint::Percentage(40)]) - 144
.split(main_chunks[1]); - 145
- 146
// ------------------------------------------------------------- - 147
// LEFT DECK - 148
// ------------------------------------------------------------- - 149
let left_chunks = Layout::default() - 150
.direction(Direction::Vertical) - 151
.constraints([ - 152
Constraint::Length(7), - 153
Constraint::Length(5), - 154
Constraint::Min(6), - 155
]) - 156
.split(deck_chunks[0]); - 157
- 158
// Incident Stream — real from agent events - 159
let inc_lines: Vec<Line> = if self.incidents.is_empty() { - 160
vec![Line::from(vec![Span::styled( - 161
"No incidents — watching event stream…", - 162
self.theme.style_card().add_modifier(Modifier::DIM), - 163
)])] - 164
} else { - 165
self.incidents - 166
.iter() - 167
.rev() - 168
.take(5) - 169
.map(|inc| { - 170
let (icon, style) = match inc.severity { - 171
crate::app::IncidentSeverity::Critical => { - 172
(Symbols::CROSS, self.theme.style_danger()) - 173
} - 174
crate::app::IncidentSeverity::Warn => { - 175
(Symbols::STATUS_ACTIVE, self.theme.style_warn()) - 176
} - 177
crate::app::IncidentSeverity::Info => { - 178
(Symbols::STATUS_ACTIVE, self.theme.style_info()) - 179
} - 180
}; - 181
Line::from(vec![ - 182
Span::styled( - 183
format!("[{}] ", inc.timestamp), - 184
self.theme.style_card().add_modifier(Modifier::DIM), - 185
), - 186
Span::styled(format!("{icon} [{}] ", inc.severity_text()), style), - 187
Span::styled(&inc.message, self.theme.style_card()), - 188
]) - 189
}) - 190
.collect() - 191
}; - 192
- 193
let inc_block = Block::default() - 194
.borders(Borders::ALL) - 195
.border_style(left_border) - 196
.title(" Live Incident Stream [Tab] ") - 197
.title_style(self.theme.style_card()); - 198
- 199
Paragraph::new(inc_lines) - 200
.block(inc_block) - 201
.render(left_chunks[0], buf); - 202
- 203
// Audit Receipts — real from server receipts - 204
let audit_lines: Vec<Line> = if self.audit_entries.is_empty() { - 205
let mut lines = vec![Line::from(vec![Span::styled( - 206
"ACTION ID STATUS REVISION FINGERPRINT", - 207
self.theme.style_card().add_modifier(Modifier::BOLD), - 208
)])]; - 209
lines.push(Line::from(vec![Span::styled( - 210
"No audit receipts yet.", - 211
self.theme.style_card().add_modifier(Modifier::DIM), - 212
)])); - 213
lines - 214
} else { - 215
let mut lines = vec![Line::from(vec![Span::styled( - 216
"ACTION ID STATUS REVISION FINGERPRINT", - 217
self.theme.style_card().add_modifier(Modifier::BOLD), - 218
)])]; - 219
for entry in self.audit_entries.iter().take(4) { - 220
lines.push(Line::from(vec![ - 221
Span::styled(format!("{:<30} ", entry.action_id), self.theme.style_card()), - 222
Span::styled( - 223
format!("{:<10} ", entry.status), - 224
if entry.status == "VERIFIED" || entry.status == "OK" { - 225
self.theme.style_ok() - 226
} else { - 227
self.theme.style_danger() - 228
}, - 229
), - 230
Span::styled( - 231
format!("{:<10} ", entry.revision), - 232
self.theme.style_accent(), - 233
), - 234
Span::styled( - 235
format!("{}…", entry.fingerprint), - 236
self.theme.style_card().add_modifier(Modifier::DIM), - 237
), - 238
])); - 239
} - 240
lines - 241
}; - 242
- 243
let audit_block = Block::default() - 244
.borders(Borders::ALL) - 245
.border_style(left_border) - 246
.title(" Audit Receipts [Ctrl+K] ") - 247
.title_style(self.theme.style_card()); - 248
- 249
Paragraph::new(audit_lines) - 250
.block(audit_block) - 251
.render(left_chunks[1], buf); - 252
- 253
// Merkle Causal Graph — real from presentation events - 254
let merkle_lines: Vec<Line> = if self.merkle_nodes.is_empty() { - 255
vec![Line::from(vec![Span::styled( - 256
"No causal lineage recorded yet.", - 257
self.theme.style_card().add_modifier(Modifier::DIM), - 258
)])] - 259
} else { - 260
self.merkle_nodes - 261
.iter() - 262
.map(|node| { - 263
let verified_str = if node.verified { " [VERIFIED]" } else { "" }; - 264
Line::from(vec![ - 265
Span::styled(&node.label, self.theme.style_info()), - 266
Span::styled(" ──► ", self.theme.style_card()), - 267
Span::styled( - 268
format!("Hash: {}{}", node.hash, verified_str), - 269
if node.verified { - 270
self.theme.style_ok() - 271
} else { - 272
self.theme.style_accent() - 273
}, - 274
), - 275
]) - 276
}) - 277
.collect() - 278
}; - 279
- 280
let merkle_block = Block::default() - 281
.borders(Borders::ALL) - 282
.border_style(left_border) - 283
.title(format!(" {} Causal Lineage Merkle Graph ", Symbols::DELTA)) - 284
.title_style(self.theme.style_accent()); - 285
- 286
Paragraph::new(merkle_lines) - 287
.block(merkle_block) - 288
.render(left_chunks[2], buf); - 289
- 290
// ------------------------------------------------------------- - 291
// RIGHT DECK - 292
// ------------------------------------------------------------- - 293
let right_chunks = Layout::default() - 294
.direction(Direction::Vertical) - 295
.constraints([ - 296
Constraint::Length(5), - 297
Constraint::Length(5), - 298
Constraint::Length(5), - 299
Constraint::Min(4), - 300
]) - 301
.split(deck_chunks[1]); - 302
- 303
// Gauges & Radar — real from health - 304
let gauge_lines = vec![ - 305
Line::from(vec![ - 306
Span::styled("CPU: ", self.theme.style_card()), - 307
Span::styled( - 308
format!("{:.1}% ", self.telemetry.cpu_percent), - 309
self.theme.style_accent(), - 310
), - 311
Span::styled("RSS: ", self.theme.style_card()), - 312
Span::styled( - 313
format!("{:.1}MB ", self.telemetry.rss_mb), - 314
self.theme.style_ok(), - 315
), - 316
Span::styled( - 317
format!("RADAR: {:.0}°", self.telemetry.radar_angle_deg), - 318
self.theme.style_info(), - 319
), - 320
]), - 321
Line::from(vec![Span::styled( - 322
format!( - 323
"{} ACTIVE AGENTS [{}] {} PENDING TASKS [{}]", - 324
Symbols::STATUS_ACTIVE, - 325
self.telemetry.active_workers, - 326
Symbols::STATUS_IDLE, - 327
self.telemetry.pending_tasks - 328
), - 329
self.theme.style_card(), - 330
)]), - 331
]; - 332
- 333
let gauge_block = Block::default() - 334
.borders(Borders::ALL) - 335
.border_style(right_border) - 336
.title(" System Gauges & Swarm Radar ") - 337
.title_style(self.theme.style_card()); - 338
- 339
Paragraph::new(gauge_lines) - 340
.block(gauge_block) - 341
.render(right_chunks[0], buf); - 342
- 343
// Network Traffic Waveform - 344
let net_lines = vec![Line::from(vec![ - 345
Span::styled("THROUGHPUT: ", self.theme.style_card()), - 346
Span::styled( - 347
format!("{} msg/s ", self.telemetry.bus_queue_depth), - 348
self.theme.style_accent(), - 349
), - 350
Span::styled("∿∿∿▲∿∿▲▲∿∿▲∿∿∿▲∿▲∿∿", self.theme.style_accent()), - 351
])]; - 352
- 353
let net_block = Block::default() - 354
.borders(Borders::ALL) - 355
.border_style(right_border) - 356
.title(" Live Network Traffic Waveform ") - 357
.title_style(self.theme.style_card()); - 358
- 359
Paragraph::new(net_lines) - 360
.block(net_block) - 361
.render(right_chunks[1], buf); - 362
- 363
// Distributed Bus Health — real from telemetry - 364
let queue_depth = self.telemetry.bus_queue_depth; - 365
let bus_lines = vec![ - 366
Line::from(vec![Span::styled( - 367
"TOPIC DEPTH THROUGHPUT STATUS", - 368
self.theme.style_card().add_modifier(Modifier::BOLD), - 369
)]), - 370
Line::from(vec![ - 371
Span::styled( - 372
format!("session.events {queue_depth:<8} "), - 373
self.theme.style_card(), - 374
), - 375
Span::styled("OK", self.theme.style_ok()), - 376
]), - 377
Line::from(vec![ - 378
Span::styled( - 379
format!("outbox.delivery {queue_depth:<8} "), - 380
self.theme.style_card(), - 381
), - 382
Span::styled("OK", self.theme.style_ok()), - 383
]), - 384
]; - 385
- 386
let bus_block = Block::default() - 387
.borders(Borders::ALL) - 388
.border_style(right_border) - 389
.title(" Distributed Bus Queue Health ") - 390
.title_style(self.theme.style_card()); - 391
- 392
Paragraph::new(bus_lines) - 393
.block(bus_block) - 394
.render(right_chunks[2], buf); - 395
- 396
// Provider Latency — real provider names from health - 397
let lat_lines = vec![ - 398
Line::from(vec![ - 399
Span::styled(&self.health.provider, self.theme.style_card()), - 400
Span::styled(": ", self.theme.style_card()), - 401
Span::styled( - 402
format!("{}ms ", self.telemetry.anthropic_latency_ms), - 403
self.theme.style_ok(), - 404
), - 405
Span::styled("[■■■■■■□□□□]", self.theme.style_ok()), - 406
]), - 407
Line::from(vec![ - 408
Span::styled("context: ", self.theme.style_card()), - 409
Span::styled( - 410
format!("{} tok", self.health.context_window), - 411
self.theme.style_info(), - 412
), - 413
]), - 414
]; - 415
- 416
let lat_block = Block::default() - 417
.borders(Borders::ALL) - 418
.border_style(right_border) - 419
.title(" Model Provider Latency [p50] ") - 420
.title_style(self.theme.style_card()); - 421
- 422
Paragraph::new(lat_lines) - 423
.block(lat_block) - 424
.render(right_chunks[3], buf); - 425
} - 426
} - 427
- 428
impl IncidentEntry { - 429
fn severity_text(&self) -> &'static str { - 430
match self.severity { - 431
crate::app::IncidentSeverity::Critical => "CRITICAL", - 432
crate::app::IncidentSeverity::Warn => "WARN", - 433
crate::app::IncidentSeverity::Info => "INFO", - 434
} - 435
} - 436
} - 437
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.