use crate::engine::Paradigm;
use crate::symbol::ParadigmSet;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Verdict {
pub valid: bool,
pub confidence: Confidence,
pub paradigms_evaluated: ParadigmSet,
pub trace: LogicTrace,
pub cross_validation: CrossValidation,
#[cfg(feature = "alloc")]
pub formal_notation: alloc::string::String,
#[cfg(feature = "alloc")]
pub citations: alloc::vec::Vec<Citation>,
}
impl Verdict {
pub fn deny_immediate(reason: &'static str) -> Self {
let mut trace = LogicTrace::new();
trace.push(TraceEntry {
stage: Stage::CrossValidation,
paradigm: Some(Paradigm::Deontic),
description: reason,
outcome: EntryOutcome::Denied,
});
Verdict {
valid: false,
confidence: Confidence::CERTAIN,
paradigms_evaluated: {
let mut s = ParadigmSet::empty();
s.insert(Paradigm::Deontic);
s
},
trace,
cross_validation: CrossValidation {
consistent: false,
conflicts_detected: 1,
conflict_detail: Some(reason),
},
#[cfg(feature = "alloc")]
formal_notation: alloc::format!("¬permitted({reason})"),
#[cfg(feature = "alloc")]
citations: alloc::vec![],
}
}
pub fn permit_immediate(reason: &'static str) -> Self {
let mut trace = LogicTrace::new();
trace.push(TraceEntry {
stage: Stage::CrossValidation,
paradigm: Some(Paradigm::Deontic),
description: reason,
outcome: EntryOutcome::Permitted,
});
Verdict {
valid: true,
confidence: Confidence::CERTAIN,
paradigms_evaluated: {
let mut s = ParadigmSet::empty();
s.insert(Paradigm::Deontic);
s
},
trace,
cross_validation: CrossValidation {
consistent: true,
conflicts_detected: 0,
conflict_detail: None,
},
#[cfg(feature = "alloc")]
formal_notation: alloc::format!("permitted({reason})"),
#[cfg(feature = "alloc")]
citations: alloc::vec![],
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Confidence(pub u8);
impl Confidence {
pub const CERTAIN: Confidence = Confidence(255);
pub const HIGH: Confidence = Confidence(204); pub const MEDIUM: Confidence = Confidence(153); pub const LOW: Confidence = Confidence(102); pub const UNCERTAIN: Confidence = Confidence(51); pub const NONE: Confidence = Confidence(0);
pub fn from_agreement(agreed: u8, total: u8) -> Self {
if total == 0 {
return Confidence::NONE;
}
Confidence(((agreed as u16 * 255) / total as u16) as u8)
}
pub fn as_f32(self) -> f32 {
self.0 as f32 / 255.0
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct CrossValidation {
pub consistent: bool,
pub conflicts_detected: u8,
pub conflict_detail: Option<&'static str>,
}
impl CrossValidation {
pub fn ok() -> Self {
CrossValidation {
consistent: true,
conflicts_detected: 0,
conflict_detail: None,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct LogicTrace {
#[cfg(feature = "alloc")]
pub entries: alloc::vec::Vec<TraceEntry>,
#[cfg(not(feature = "alloc"))]
pub entries: heapless::Vec<TraceEntry, 64>,
}
impl LogicTrace {
pub fn new() -> Self {
LogicTrace {
#[cfg(feature = "alloc")]
entries: alloc::vec::Vec::new(),
#[cfg(not(feature = "alloc"))]
entries: heapless::Vec::new(),
}
}
pub fn push(&mut self, entry: TraceEntry) {
#[cfg(feature = "alloc")]
self.entries.push(entry);
#[cfg(not(feature = "alloc"))]
let _ = self.entries.push(entry);
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
impl Default for LogicTrace {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct TraceEntry {
pub stage: Stage,
pub paradigm: Option<Paradigm>,
pub description: &'static str,
pub outcome: EntryOutcome,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Stage {
Tokenization,
ParadigmDetection,
AstConstruction,
EngineRouting,
EngineEvaluation,
CrossValidation,
VerdictSynthesis,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum EntryOutcome {
Permitted,
Denied,
Evaluated,
Routed,
Conflict,
Skipped,
}
#[cfg(feature = "alloc")]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Citation {
pub id: alloc::string::String,
pub description: alloc::string::String,
}