mod arise;
mod background;
mod d2skill;
mod erl;
mod outcomes;
mod preferences;
mod rl;
mod skill_commands;
mod trust;
#[cfg(test)]
mod tests;
use super::{Agent, Channel};
impl<C: Channel> Agent<C> {
pub(crate) fn is_learning_enabled(&self) -> bool {
self.learning_engine.is_enabled()
}
async fn is_skill_trusted_for_learning(&self, skill_name: &str) -> bool {
let Some(memory) = &self.memory_state.memory else {
return true;
};
let Ok(Some(row)) = memory.sqlite().load_skill_trust(skill_name).await else {
return true; };
matches!(row.trust_level.as_str(), "trusted" | "verified")
}
pub(crate) async fn record_skill_outcomes(
&self,
outcome: &str,
error_context: Option<&str>,
outcome_detail: Option<&str>,
) {
if self.skill_state.active_skill_names.is_empty() {
return;
}
let Some(memory) = &self.memory_state.memory else {
return;
};
if let Err(e) = memory
.sqlite()
.record_skill_outcomes_batch(
&self.skill_state.active_skill_names,
self.memory_state.conversation_id,
outcome,
error_context,
outcome_detail,
)
.await
{
tracing::warn!("failed to record skill outcomes: {e:#}");
}
if outcome != "success" {
for name in &self.skill_state.active_skill_names {
self.check_rollback(name).await;
}
}
let names: Vec<String> = self.skill_state.active_skill_names.clone();
for name in &names {
self.check_trust_transition(name).await;
}
self.update_skill_confidence_metrics().await;
self.spawn_rl_head_update(outcome);
self.spawn_stem_detection(outcome);
if outcome == "success" {
for name in &names {
self.spawn_arise_trace_improvement(name);
self.spawn_erl_reflection(name);
}
}
}
pub(crate) async fn update_skill_confidence_metrics(&self) {
let Some(memory) = &self.memory_state.memory else {
return;
};
let Ok(stats) = memory.sqlite().load_skill_outcome_stats().await else {
return;
};
let confidences: Vec<crate::metrics::SkillConfidence> = stats
.iter()
.map(|s| {
let suc = u32::try_from(s.successes).unwrap_or(0);
let fail = u32::try_from(s.failures).unwrap_or(0);
crate::metrics::SkillConfidence {
name: s.skill_name.clone(),
posterior: zeph_skills::trust_score::posterior_mean(suc, fail),
total_uses: u32::try_from(s.total).unwrap_or(0),
}
})
.collect();
self.update_metrics(|m| m.skill_confidence = confidences);
}
}