use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use super::yes;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "rule", rename_all = "snake_case", deny_unknown_fields)]
pub enum Promotion {
Never {},
Automatic {},
RepeatedValidation {
#[serde(default = "default_times")]
times: u32,
},
HumanApproval {},
}
fn default_times() -> u32 {
3
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct NamespacePolicy {
#[serde(default = "yes")]
pub enabled: bool,
#[serde(default)]
pub retention_days: Option<u32>,
#[serde(default = "default_promotion")]
pub promotion: Promotion,
#[serde(default = "default_min_confidence")]
pub min_confidence: f64,
#[serde(default = "yes")]
pub require_provenance: bool,
}
fn default_promotion() -> Promotion {
Promotion::RepeatedValidation {
times: default_times(),
}
}
fn default_min_confidence() -> f64 {
0.75
}
impl Default for NamespacePolicy {
fn default() -> Self {
Self {
enabled: true,
retention_days: None,
promotion: default_promotion(),
min_confidence: default_min_confidence(),
require_provenance: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct Namespaces {
#[serde(default = "episodic_default")]
pub episodic: NamespacePolicy,
#[serde(default)]
pub semantic: NamespacePolicy,
#[serde(default)]
pub procedural: NamespacePolicy,
#[serde(default = "failure_default")]
pub failure: NamespacePolicy,
}
fn episodic_default() -> NamespacePolicy {
NamespacePolicy {
promotion: Promotion::Never {},
require_provenance: false,
..NamespacePolicy::default()
}
}
fn failure_default() -> NamespacePolicy {
NamespacePolicy {
promotion: Promotion::Automatic {},
..NamespacePolicy::default()
}
}
impl Default for Namespaces {
fn default() -> Self {
Self {
episodic: episodic_default(),
semantic: NamespacePolicy::default(),
procedural: NamespacePolicy::default(),
failure: failure_default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct MemoryPolicy {
#[serde(default = "default_carry")]
pub carry_summaries: usize,
#[serde(default)]
pub summary_provider: Option<String>,
#[serde(default = "default_max_chars")]
pub max_summary_chars: usize,
#[serde(default)]
pub namespaces: Namespaces,
#[serde(default = "default_max_retrieved")]
pub max_retrieved: usize,
}
fn default_carry() -> usize {
2
}
fn default_max_chars() -> usize {
1200
}
fn default_max_retrieved() -> usize {
10
}
impl Default for MemoryPolicy {
fn default() -> Self {
Self {
carry_summaries: default_carry(),
summary_provider: None,
max_summary_chars: default_max_chars(),
namespaces: Namespaces::default(),
max_retrieved: default_max_retrieved(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn episodes_are_never_promoted_by_default() {
assert_eq!(Namespaces::default().episodic.promotion, Promotion::Never {});
}
#[test]
fn failures_are_promoted_automatically_by_default() {
assert_eq!(
Namespaces::default().failure.promotion,
Promotion::Automatic {}
);
}
#[test]
fn beliefs_need_corroboration_by_default() {
for p in [
Namespaces::default().semantic.promotion,
Namespaces::default().procedural.promotion,
] {
assert!(
matches!(p, Promotion::RepeatedValidation { times } if times > 1),
"a belief should need more than one sighting, got {p:?}"
);
}
}
}