use crate::dashboard::routes::helpers::detect_project_root_for_dashboard;
pub(super) fn handle(
path: &str,
_query_str: &str,
_method: &str,
_body: &str,
) -> Option<(&'static str, &'static str, String)> {
if path != "/api/signals" {
return None;
}
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map_or(0, |d| d.as_secs());
let editor = {
let raw = crate::core::editor_signal::load_raw_for_status();
match raw {
Some(s) if s.active_file.is_some() => {
let age = now.saturating_sub(s.updated_at);
serde_json::json!({
"active_file": s.active_file,
"age_secs": age,
"fresh": age <= crate::core::editor_signal::FRESHNESS_SECS,
})
}
_ => serde_json::json!({ "active_file": null, "age_secs": null, "fresh": false }),
}
};
let diagnostics = {
let snap = crate::core::diagnostics_store::snapshot();
let errors = snap
.iter()
.filter(|(_, s)| *s == crate::core::diagnostics_store::Severity::Error)
.count();
let warnings = snap.len() - errors;
let mut files: Vec<&str> = snap.iter().map(|(p, _)| p.as_str()).collect();
files.sort_unstable();
files.dedup();
files.truncate(8);
serde_json::json!({ "errors": errors, "warnings": warnings, "files": files })
};
let git = {
let project_root = detect_project_root_for_dashboard();
let signals = crate::core::git_signals::collect(&project_root);
let uncommitted = signals.recency.values().filter(|v| **v >= 1.0).count();
serde_json::json!({
"uncommitted": uncommitted,
"churned": signals.churn.len(),
})
};
let (tracked, forced) = crate::core::path_mode_memory::disk_summary();
let bounce_memory = serde_json::json!({
"tracked_paths": tracked,
"forced_full_paths": forced,
});
let auto_sources: Vec<serde_json::Value> =
crate::core::auto_mode_resolver::persisted_source_counts()
.into_iter()
.map(|(s, n)| serde_json::json!([s, n]))
.collect();
let bounce_trend: Vec<serde_json::Value> = crate::core::savings_ledger::daily_bounce_trend(14)
.into_iter()
.map(|(d, b, r)| serde_json::json!([d, b, r]))
.collect();
let echo_trend: Vec<serde_json::Value> = crate::core::output_echo::load_stats()
.daily_trend(14)
.into_iter()
.map(|(d, ratio, n)| serde_json::json!([d, (ratio * 1000.0).round() / 1000.0, n]))
.collect();
let payload = serde_json::json!({
"editor": editor,
"diagnostics": diagnostics,
"git": git,
"bounce_memory": bounce_memory,
"auto_mode_sources": auto_sources,
"bounce_trend": bounce_trend,
"echo_trend": echo_trend,
});
let json = serde_json::to_string(&payload).unwrap_or_else(|_| "{}".to_string());
Some(("200 OK", "application/json", json))
}