KeiSeiKit-1.0/_primitives/_rust/kei-brain-view/src/stats.rs
Parfii-bot 0be354a920 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

52 lines
1.7 KiB
Rust

//! Bucket counts over the hydrated graph.
//!
//! Constructor Pattern: one cube = `Stats` struct + `compute_stats` fn +
//! text renderer. Deterministic output order (sorted keys) so downstream
//! diffing / snapshot tests stay stable across runs.
use crate::graph::Graph;
use serde::Serialize;
use std::collections::BTreeMap;
#[derive(Debug, Default, Serialize)]
pub struct Stats {
pub total: usize,
/// status -> count (e.g. "running" -> 3, "done" -> 12)
pub by_status: BTreeMap<String, usize>,
/// has-dna count (non-NULL dna column)
pub with_dna: usize,
/// top-level roots (no parent_branch or parent outside the ledger)
pub roots: usize,
/// non-root forks
pub forks: usize,
}
/// Build `Stats` from an in-memory graph — pure, no I/O.
pub fn compute_stats(graph: &Graph) -> Stats {
let mut s = Stats::default();
s.total = graph.nodes.len();
s.roots = graph.roots.len();
s.forks = s.total.saturating_sub(s.roots);
for n in &graph.nodes {
*s.by_status.entry(n.status.clone()).or_insert(0) += 1;
if n.dna.is_some() {
s.with_dna += 1;
}
}
s
}
/// Human-readable text report. Ordering: total, roots/forks, with_dna,
/// then each status bucket alphabetically (BTreeMap iter).
pub fn render_stats(stats: &Stats) -> String {
let mut out = String::new();
out.push_str(&format!("total: {}\n", stats.total));
out.push_str(&format!("roots: {}\n", stats.roots));
out.push_str(&format!("forks: {}\n", stats.forks));
out.push_str(&format!("with_dna: {}\n", stats.with_dna));
out.push_str("by_status:\n");
for (status, count) in &stats.by_status {
out.push_str(&format!(" {status:<10} {count}\n"));
}
out
}