lean_ctx/core/context_kernel/
dashboard_report.rs1use serde::Serialize;
4
5#[derive(Debug, Clone, Serialize)]
7pub struct SubsystemStatus {
8 pub name: String,
10 pub active: bool,
12 pub detail: String,
14}
15
16#[derive(Debug, Clone, Default, Serialize)]
18pub struct TokenSavingsSummary {
19 pub dedup_hits: usize,
21 pub schema_tokens_saved: usize,
23 pub evidence_dispatches: usize,
25 pub response_cached: usize,
27}
28
29#[derive(Debug, Clone, Serialize)]
31pub struct DashboardReport {
32 pub version: &'static str,
34 pub kernel_enabled: bool,
36 pub health_status: String,
38 pub subsystems: Vec<SubsystemStatus>,
40 pub savings: TokenSavingsSummary,
42 pub provider_distribution: Vec<super::envelope_bridge::ProviderStat>,
44}
45
46#[must_use]
48pub fn generate_report() -> DashboardReport {
49 let kernel_enabled = super::kernel_config::is_enabled();
50 let dedup = super::ctx_read_dedup::dedup_summary();
51 let schema = super::schema_wiring::schema_savings();
52 let evidence = super::evidence_wiring::dispatch_summary();
53 let adaptive = super::adaptive_bridge::adaptive_summary();
54 let search = crate::tools::search_kernel::search_summary();
55 let response = super::response_evidence::response_summary();
56 let dispatches = evidence.tool_dispatches + evidence.proxy_dispatches;
57 let health_status = if !kernel_enabled {
58 "disabled"
59 } else if super::health::is_healthy() {
60 "healthy"
61 } else {
62 "degraded"
63 };
64
65 DashboardReport {
66 version: env!("CARGO_PKG_VERSION"),
67 kernel_enabled,
68 health_status: health_status.to_owned(),
69 subsystems: vec![
70 status(
71 "Content Dedup",
72 dedup.total_reads > 0,
73 format!(
74 "{} hits, {} tokens saved",
75 dedup.dedup_hits, dedup.tokens_saved
76 ),
77 ),
78 status(
79 "Schema Opt",
80 schema.optimizations_applied > 0,
81 format!(
82 "{} optimizations, {} tokens saved",
83 schema.optimizations_applied, schema.total_tokens_saved
84 ),
85 ),
86 status(
87 "Evidence",
88 dispatches > 0,
89 format!("{dispatches} dispatches recorded"),
90 ),
91 status(
92 "Adaptive",
93 adaptive.signals_received > 0,
94 format!(
95 "bounce rate {:.2}, advice: {:?}",
96 adaptive.current_bounce_rate, adaptive.advice
97 ),
98 ),
99 status(
100 "Search",
101 search.total_searches > 0,
102 format!(
103 "{} searches, {} repeats detected",
104 search.total_searches, search.repeated_queries
105 ),
106 ),
107 status(
108 "Response",
109 response.total_responses > 0,
110 format!(
111 "{} responses, {:.0}% cache hit",
112 response.total_responses,
113 response.cache_hit_rate * 100.0
114 ),
115 ),
116 ],
117 savings: TokenSavingsSummary {
118 dedup_hits: dedup.dedup_hits,
119 schema_tokens_saved: schema.total_tokens_saved,
120 evidence_dispatches: dispatches,
121 response_cached: response.cached_responses,
122 },
123 provider_distribution: super::envelope_bridge::provider_stats(),
124 }
125}
126
127fn status(name: &str, active: bool, detail: String) -> SubsystemStatus {
128 SubsystemStatus {
129 name: name.to_owned(),
130 active,
131 detail,
132 }
133}
134
135#[must_use]
137pub fn format_report(report: &DashboardReport) -> String {
138 let kernel = if report.kernel_enabled { "ON" } else { "OFF" };
139 let subsystems = report
140 .subsystems
141 .iter()
142 .map(|subsystem| {
143 let marker = if subsystem.active { '✓' } else { '○' };
144 format!(" {marker} {:<15} — {}", subsystem.name, subsystem.detail)
145 })
146 .collect::<Vec<_>>()
147 .join("\n");
148 format!(
149 "═══ lean-ctx Kernel Dashboard ═══\n\
150 Version: {} | Status: {} | Kernel: {kernel}\n\n\
151 Subsystems:\n{subsystems}\n\n\
152 Savings: dedup={} schema={}tok evidence={} cached={}",
153 report.version,
154 report.health_status,
155 report.savings.dedup_hits,
156 report.savings.schema_tokens_saved,
157 report.savings.evidence_dispatches,
158 report.savings.response_cached,
159 )
160}
161
162#[must_use]
164pub fn report_json(report: &DashboardReport) -> String {
165 serde_json::to_string_pretty(report)
166 .unwrap_or_else(|_| r#"{"error":"dashboard serialization failed"}"#.to_owned())
167}
168
169#[cfg(test)]
170mod tests {
171 use super::{format_report, generate_report, report_json};
172
173 #[test]
174 fn report_populated() {
175 assert!(!generate_report().subsystems.is_empty());
176 }
177
178 #[test]
179 fn format_contains_sections() {
180 let formatted = format_report(&generate_report());
181 assert!(formatted.contains("Dashboard"));
182 assert!(formatted.contains("Subsystems"));
183 assert!(formatted.contains("Savings"));
184 }
185
186 #[test]
187 fn json_valid() {
188 let json = report_json(&generate_report());
189 assert!(serde_json::from_str::<serde_json::Value>(&json).is_ok());
190 }
191}