hypersteeldb 0.1.0

A database that compiles questions instead of guessing answers: typed vocabulary discovered from your documents, queries type-checked before they run, roaring-bitmap set algebra over reified hyperedges, and Dempster-Shafer evidence with an explicit conflict guard.
Documentation
//! Deterministic answer synthesis — render a bitmap-program result (the structured JSON the analytics
//! programs return) into a grounded natural-language answer via a fixed template, with NO model in the
//! loop. This is the default path for small tool-caller drivers (Needle): the model selects the program
//! and arguments, the engine computes the numbers, and we phrase them here — so the answer can never
//! hallucinate figures the corpus doesn't support. When a synthesis-capable provider (Bedrock / a large
//! OpenAI-compatible model) is configured, the loop uses the model's prose instead.

use serde_json::Value;

/// Render a program result into a template answer, or `None` if it isn't a recognised program payload.
pub fn render_program(v: &Value) -> Option<String> {
    match v.get("program").and_then(|p| p.as_str()) {
        Some("breakdown") => Some(render_breakdown(v)),
        Some("crosstab") => Some(render_crosstab(v)),
        Some("rank") => Some(render_rank(v)),
        Some("structure") => render_structure(v),
        Some("profile") => Some(render_profile(v)),
        _ => None,
    }
}

/// Compose the auto-profile: render each routed section with its own program template.
fn render_profile(v: &Value) -> String {
    let sections = v.get("sections").and_then(|s| s.as_array()).cloned().unwrap_or_default();
    if sections.is_empty() {
        return "No informative structure found in the matching rows.".to_string();
    }
    let scope = v.get("scope_size").and_then(|x| x.as_u64()).unwrap_or(0);
    let mut out = vec![format!("Profile of {scope} matching situations:")];
    for s in &sections {
        if let Some(r) = s.get("result").and_then(render_program) {
            out.push(format!("\n{r}"));
        }
    }
    out.join("\n")
}

fn render_breakdown(v: &Value) -> String {
    let facet = v.get("facet").and_then(|x| x.as_str()).unwrap_or("value");
    let total = v.get("total").and_then(|x| x.as_u64()).unwrap_or(0);
    let parts = v.get("partition").and_then(|x| x.as_array()).cloned().unwrap_or_default();
    if parts.is_empty() {
        return format!("No {facet} values matched ({total} situations in scope).");
    }
    let items: Vec<String> = parts
        .iter()
        .map(|p| {
            let val = p.get("value").and_then(|x| x.as_str()).unwrap_or("?");
            let n = p.get("count").and_then(|x| x.as_u64()).unwrap_or(0);
            format!("{val} ({n})")
        })
        .collect();
    let top = parts[0].get("value").and_then(|x| x.as_str()).unwrap_or("?");
    format!("Breakdown by {facet} across {total} situations: {}. Most common: {top}.", items.join(", "))
}

fn render_crosstab(v: &Value) -> String {
    let row_facet = v.get("row_facet").and_then(|x| x.as_str()).unwrap_or("row");
    let col_facet = v.get("col_facet").and_then(|x| x.as_str()).unwrap_or("col");
    let total = v.get("total").and_then(|x| x.as_u64()).unwrap_or(0);
    let matrix = v.get("matrix").and_then(|x| x.as_array()).cloned().unwrap_or_default();
    if matrix.is_empty() {
        return format!("No {row_facet} × {col_facet} combinations matched ({total} situations).");
    }
    let mut lines = Vec::new();
    for row in &matrix {
        let name = row.get("row").and_then(|x| x.as_str()).unwrap_or("?");
        let cells = row.get("cells").and_then(|x| x.as_array()).cloned().unwrap_or_default();
        // argmax cell = the most common col value for this row (answers "which X is most common per Y")
        let mut best: Option<(&str, u64)> = None;
        let parts: Vec<String> = cells
            .iter()
            .map(|c| {
                let col = c.get("col").and_then(|x| x.as_str()).unwrap_or("?");
                let n = c.get("count").and_then(|x| x.as_u64()).unwrap_or(0);
                if best.map(|(_, bn)| n > bn).unwrap_or(true) {
                    best = Some((col, n));
                }
                format!("{col} {n}")
            })
            .collect();
        let most = best.filter(|(_, n)| *n > 0).map(|(c, _)| format!(" → most common: {c}")).unwrap_or_default();
        lines.push(format!("- {name}: {}{most}", parts.join(", ")));
    }
    format!("{row_facet} × {col_facet} ({total} situations):\n{}", lines.join("\n"))
}

fn render_rank(v: &Value) -> String {
    let facet = v.get("facet").and_then(|x| x.as_str()).unwrap_or("value");
    let ranked = v.get("ranked").and_then(|x| x.as_array()).cloned().unwrap_or_default();
    if ranked.is_empty() {
        return format!("No {facet} values to rank.");
    }
    let items: Vec<String> = ranked
        .iter()
        .take(8)
        .map(|r| {
            let tok = r.get("token").and_then(|x| x.as_str()).unwrap_or("?");
            let leaf = tok.rsplit('/').next().unwrap_or(tok);
            match r.get("mdus").and_then(|x| x.as_f64()) {
                Some(m) => format!("{leaf} ({m:.2})"),
                None => leaf.to_string(),
            }
        })
        .collect();
    format!("Top {facet} by salience: {}.", items.join(", "))
}

fn render_structure(v: &Value) -> Option<String> {
    match v.get("op").and_then(|x| x.as_str()) {
        Some("cooccurs") => {
            let focus = v.get("focus").and_then(|x| x.as_str()).unwrap_or("?");
            let co = v.get("cooccurs").and_then(|x| x.as_array()).cloned().unwrap_or_default();
            if co.is_empty() {
                return Some(format!("{focus} has no notable co-occurring tokens."));
            }
            let items: Vec<String> = co
                .iter()
                .take(8)
                .map(|c| {
                    let tok = c.get("token").and_then(|x| x.as_str()).unwrap_or("?");
                    let leaf = tok.rsplit('/').next().unwrap_or(tok);
                    let n = c.get("shared").and_then(|x| x.as_u64()).unwrap_or(0);
                    format!("{leaf} ({n})")
                })
                .collect();
            Some(format!("{focus} most co-occurs with: {}.", items.join(", ")))
        }
        Some("s_path") => {
            let (a, b) = (v.get("a").and_then(|x| x.as_str()).unwrap_or("?"), v.get("b").and_then(|x| x.as_str()).unwrap_or("?"));
            match v.get("path").and_then(|p| p.as_array()) {
                Some(p) if !p.is_empty() => {
                    let hops: Vec<&str> = p.iter().filter_map(|x| x.as_str()).map(|t| t.rsplit('/').next().unwrap_or(t)).collect();
                    Some(format!("Path {a} → {b}: {}.", hops.join(" → ")))
                }
                _ => Some(format!("No connecting path between {a} and {b} at this overlap threshold.")),
            }
        }
        Some("s_clusters") => {
            let cl = v.get("clusters").and_then(|x| x.as_array()).cloned().unwrap_or_default();
            if cl.is_empty() {
                return Some("No multi-token clusters at this overlap threshold.".into());
            }
            let lines: Vec<String> = cl
                .iter()
                .take(6)
                .map(|c| {
                    let size = c.get("size").and_then(|x| x.as_u64()).unwrap_or(0);
                    let toks: Vec<&str> = c
                        .get("tokens")
                        .and_then(|t| t.as_array())
                        .map(|a| a.iter().filter_map(|x| x.as_str()).map(|t| t.rsplit('/').next().unwrap_or(t)).take(8).collect())
                        .unwrap_or_default();
                    format!("- [{size}] {}", toks.join(", "))
                })
                .collect();
            Some(format!("{} concept clusters:\n{}", cl.len(), lines.join("\n")))
        }
        _ => None,
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json::json;

    #[test]
    fn crosstab_reports_argmax_per_row() {
        let v = json!({
            "program": "crosstab", "row_facet": "country", "col_facet": "powertrain", "total": 20,
            "matrix": [
                {"row": "japan", "cells": [{"col":"electric","count":2},{"col":"diesel","count":1},{"col":"hybrid","count":2}]},
                {"row": "germany", "cells": [{"col":"electric","count":3},{"col":"diesel","count":2},{"col":"hybrid","count":0}]}
            ]
        });
        let out = render_program(&v).unwrap();
        assert!(out.contains("country × powertrain"));
        assert!(out.contains("germany: electric 3, diesel 2, hybrid 0 → most common: electric"));
        // japan ties electric/hybrid at 2 → argmax keeps the first seen (electric)
        assert!(out.contains("japan:"));
    }

    #[test]
    fn breakdown_and_rank_render() {
        let b = json!({"program":"breakdown","facet":"country","total":20,"partition":[{"value":"usa","count":6},{"value":"japan","count":5}]});
        assert!(render_program(&b).unwrap().contains("Most common: usa"));
        let r = json!({"program":"rank","facet":"ent","ranked":[{"token":"ent/connect","mdus":1.0},{"token":"ent/agent","mdus":0.76}]});
        assert!(render_program(&r).unwrap().contains("connect (1.00)"));
    }

    #[test]
    fn non_program_returns_none() {
        assert!(render_program(&json!({"foo": "bar"})).is_none());
    }
}