1pub mod fold;
4pub mod fold_gate;
5pub mod handlers;
6pub mod persist;
7pub mod serve_ledger;
8pub mod tunable;
9
10mod event;
11mod pack;
12
13pub(crate) use pack::sync_balanced_recall_record;
14pub use pack::{BrainPack, ENTITY_CACHE_CAPACITY};
15
16use std::collections::HashMap;
17
18use khive_brain_core::{SectionPosteriorState, SectionType};
19
20pub(crate) fn ensure_section_state_seeded<'a>(
30 section_states: &'a mut HashMap<String, SectionPosteriorState>,
31 profile_id: &str,
32) -> &'a mut SectionPosteriorState {
33 let section_state = section_states.entry(profile_id.to_owned()).or_default();
34 let defaults = SectionPosteriorState::default_priors();
35 for st in SectionType::all() {
36 if let Some(prior) = defaults.get(st) {
37 section_state
38 .posteriors
39 .entry(*st)
40 .or_insert_with(|| prior.clone());
41 section_state
42 .priors
43 .entry(*st)
44 .or_insert_with(|| prior.clone());
45 }
46 }
47 section_state
48}
49
50pub(crate) fn validate_section_signals(
59 ss: &serde_json::Value,
60) -> Result<(), khive_runtime::RuntimeError> {
61 let obj = ss.as_object().ok_or_else(|| {
62 khive_runtime::RuntimeError::InvalidInput(
63 "section_signals must be a JSON object mapping section names to signal strings".into(),
64 )
65 })?;
66 if obj.is_empty() {
67 return Err(khive_runtime::RuntimeError::InvalidInput(
68 "section_signals must not be empty; omit the field entirely to submit feedback \
69 without section evidence"
70 .into(),
71 ));
72 }
73 let valid_signals = ["useful", "not_useful", "wrong"];
77 let valid_sections = khive_brain_core::SectionType::NAMES;
78 for (key, val) in obj {
79 if !valid_sections.contains(&key.as_str()) {
80 return Err(khive_runtime::RuntimeError::InvalidInput(format!(
81 "section_signals: unknown section {key:?}; valid: {}",
82 valid_sections.join(", ")
83 )));
84 }
85 let sig = val.as_str().ok_or_else(|| {
86 khive_runtime::RuntimeError::InvalidInput(format!(
87 "section_signals: signal for section {key:?} must be one of: useful | not_useful | wrong"
88 ))
89 })?;
90 if !valid_signals.contains(&sig) {
91 return Err(khive_runtime::RuntimeError::InvalidInput(format!(
92 "section_signals: invalid signal {sig:?} for section {key:?}; \
93 valid: {}",
94 valid_signals.join(" | ")
95 )));
96 }
97 }
98 Ok(())
99}
100
101#[cfg(test)]
102mod tests;