use super::KnowledgeContent;
use super::store::HiveStore;
use super::trust::{TrustStore, TrustTier};
pub fn build_hive_context(
store: &HiveStore,
trust_store: &TrustStore,
inject_unverified: bool,
max_units: usize,
) -> String {
let all = store.all_units();
if all.is_empty() {
return String::new();
}
let mut scored: Vec<(&super::KnowledgeUnit, f64, TrustTier)> = all
.iter()
.filter_map(|unit| {
let tier = trust_store
.get(&unit.source_peer)
.map(|t| t.tier())
.unwrap_or(TrustTier::Suggested);
if tier == TrustTier::Ignored && !inject_unverified {
return None;
}
let score = unit.confidence * unit.evidence_count as f64;
Some((*unit, score, tier))
})
.collect();
scored.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
let limit = if max_units > 0 {
max_units
} else {
scored.len()
};
let mut lines = Vec::new();
let mut peer_count = std::collections::HashSet::new();
for (unit, _, tier) in scored.iter().take(limit) {
peer_count.insert(unit.source_peer.clone());
let label = tier.label();
let summary = unit.content.summary_line();
let evidence = unit.evidence_count;
let peer = &unit.source_peer;
lines.push(format!(
"- [{label}] {summary} — {evidence} decisions from {peer}"
));
}
if lines.is_empty() {
return String::new();
}
let total = scored.len();
let shown = lines.len();
let truncated = if shown < total {
format!(" (showing top {shown} of {total})")
} else {
String::new()
};
let header = format!(
"## Hive Knowledge ({} peers, {} units{})\n",
peer_count.len(),
shown,
truncated,
);
header + &lines.join("\n")
}
pub fn check_concordance(
decision_tool: Option<&str>,
decision_command: Option<&str>,
user_action: &str,
store: &HiveStore,
) -> Vec<(String, bool)> {
let tool = match decision_tool {
Some(t) => t,
None => return Vec::new(),
};
let user_approves = matches!(
user_action,
"accept" | "auto" | "user_approve" | "rule_approve"
);
let user_denies = matches!(
user_action,
"reject" | "deny_rule_override" | "rule_deny" | "conflict_deny"
);
if !user_approves && !user_denies {
return Vec::new(); }
let mut results = Vec::new();
for unit in store.all_units() {
if let KnowledgeContent::Pattern {
tool: ref pattern_tool,
command_pattern: ref pattern_cmd,
ref preferred_action,
..
} = unit.content
{
if pattern_tool != tool {
continue;
}
if let Some(cmd_pattern) = pattern_cmd {
if let Some(cmd) = decision_command {
if !cmd.contains(cmd_pattern.as_str()) {
continue;
}
} else {
continue; }
}
let hive_approves = preferred_action == "approve";
let concordant = (user_approves && hive_approves) || (user_denies && !hive_approves);
results.push((unit.source_peer.clone(), concordant));
}
}
results
}
#[cfg(test)]
mod tests {
use super::*;
use crate::hive::{KnowledgeContent, KnowledgeScope, KnowledgeUnit};
fn make_pattern_unit(
id: &str,
tool: &str,
cmd: Option<&str>,
action: &str,
peer: &str,
) -> KnowledgeUnit {
KnowledgeUnit {
id: id.into(),
scope: KnowledgeScope::Universal,
category: crate::hive::KnowledgeCategory::BestPractice,
content: KnowledgeContent::Pattern {
tool: tool.into(),
command_pattern: cmd.map(|s| s.into()),
preferred_action: action.into(),
accept_rate: 0.9,
sample_count: 10,
conditions: vec![],
},
evidence_count: 10,
confidence: 0.9,
source_peer: peer.into(),
originated_at: 1000,
last_validated_at: 2000,
propagation_count: 0,
version: 1,
}
}
fn empty_store() -> HiveStore {
HiveStore::load_from(std::path::Path::new("/nonexistent"))
}
#[test]
fn build_context_empty_store() {
let store = empty_store();
let trust_store = TrustStore::load_with_default(0.5);
let ctx = build_hive_context(&store, &trust_store, true, 0);
assert!(ctx.is_empty());
}
#[test]
fn build_context_with_units() {
let mut store = empty_store();
store.insert(make_pattern_unit(
"ku_1",
"Bash",
Some("cargo test"),
"approve",
"peer-a",
));
store.insert(make_pattern_unit("ku_2", "Write", None, "deny", "peer-b"));
let trust_store = TrustStore::load_with_default(0.5);
let ctx = build_hive_context(&store, &trust_store, true, 0);
assert!(ctx.contains("## Hive Knowledge"));
assert!(ctx.contains("2 units"));
assert!(ctx.contains("[hive, suggested]")); }
#[test]
fn build_context_confirmed_tier() {
let mut store = empty_store();
store.insert(make_pattern_unit(
"ku_1",
"Bash",
Some("test"),
"approve",
"peer-a",
));
let mut trust_store = TrustStore::load_with_default(0.5);
trust_store.set_trust("peer-a", 0.9);
let ctx = build_hive_context(&store, &trust_store, true, 0);
assert!(ctx.contains("[hive]")); assert!(!ctx.contains("[hive, suggested]"));
}
#[test]
fn build_context_excludes_ignored_unless_flag() {
let mut store = empty_store();
store.insert(make_pattern_unit(
"ku_1",
"Bash",
Some("test"),
"approve",
"peer-a",
));
let mut trust_store = TrustStore::load_with_default(0.5);
trust_store.set_trust("peer-a", 0.1);
let ctx = build_hive_context(&store, &trust_store, false, 0);
assert!(ctx.is_empty());
let ctx = build_hive_context(&store, &trust_store, true, 0);
assert!(ctx.contains("[hive, ignored]"));
}
#[test]
fn concordance_approves_match() {
let mut store = empty_store();
store.insert(make_pattern_unit(
"ku_1",
"Bash",
Some("cargo test"),
"approve",
"peer-a",
));
let results = check_concordance(Some("Bash"), Some("cargo test --all"), "accept", &store);
assert_eq!(results.len(), 1);
assert_eq!(results[0].0, "peer-a");
assert!(results[0].1); }
#[test]
fn concordance_deny_match() {
let mut store = empty_store();
store.insert(make_pattern_unit(
"ku_1",
"Bash",
Some("rm -rf"),
"deny",
"peer-a",
));
let results = check_concordance(Some("Bash"), Some("rm -rf /tmp"), "reject", &store);
assert_eq!(results.len(), 1);
assert!(results[0].1); }
#[test]
fn concordance_disagree() {
let mut store = empty_store();
store.insert(make_pattern_unit(
"ku_1",
"Bash",
Some("cargo test"),
"approve",
"peer-a",
));
let results = check_concordance(Some("Bash"), Some("cargo test"), "reject", &store);
assert_eq!(results.len(), 1);
assert!(!results[0].1); }
#[test]
fn concordance_no_tool_returns_empty() {
let mut store = empty_store();
store.insert(make_pattern_unit(
"ku_1",
"Bash",
Some("test"),
"approve",
"peer-a",
));
let results = check_concordance(None, None, "accept", &store);
assert!(results.is_empty());
}
#[test]
fn concordance_wrong_tool_no_match() {
let mut store = empty_store();
store.insert(make_pattern_unit(
"ku_1",
"Bash",
Some("test"),
"approve",
"peer-a",
));
let results = check_concordance(Some("Write"), Some("test"), "accept", &store);
assert!(results.is_empty());
}
#[test]
fn concordance_ambiguous_action_skipped() {
let mut store = empty_store();
store.insert(make_pattern_unit(
"ku_1",
"Bash",
Some("test"),
"approve",
"peer-a",
));
let results = check_concordance(Some("Bash"), Some("test"), "user_input", &store);
assert!(results.is_empty());
}
}