weavatrix_memory/analytics/
model.rs1use crate::{
2 domain::MemoryFact,
3 id::{EntityId, FactId},
4 projection::ProjectionClock,
5 time::Timestamp,
6};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct BeliefRevisionRequest {
11 pub hypothesis: MemoryFact,
12 pub clock: ProjectionClock,
13 pub max_depth: usize,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
17pub struct Contradiction {
18 pub fact: FactId,
19 pub strength_bps: u16,
20 pub reason: String,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
24pub struct CascadeEffect {
25 pub entity: EntityId,
26 pub depth: usize,
27 pub revised_confidence_bps: u16,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31pub struct BeliefRevisionReport {
32 pub contradictions: Vec<Contradiction>,
33 pub cascade: Vec<CascadeEffect>,
34 pub invalidated_decisions: Vec<EntityId>,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub struct ReasoningGapRequest {
39 pub clock: ProjectionClock,
40 pub minimum_supports: usize,
41 pub low_confidence_bps: u16,
42 pub unstable_revision_count: usize,
43 pub stale_after_micros: i64,
44 pub max_results: usize,
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
48#[serde(rename_all = "snake_case")]
49pub enum GapKind {
50 UnjustifiedDecision,
51 SingleSourceInference,
52 LowConfidenceFoundation,
53 UnstableKnowledge,
54 StaleEvidence,
55}
56
57#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
58pub struct ReasoningGap {
59 pub entity: EntityId,
60 pub fact: Option<FactId>,
61 pub kind: GapKind,
62 pub severity_bps: u16,
63 pub downstream_entities: usize,
64 pub explanation: String,
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
68pub struct GapReport {
69 pub gaps: Vec<ReasoningGap>,
70 pub health_bps: u16,
71 pub analyzed_entities: usize,
72 pub analyzed_facts: usize,
73}
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
76#[serde(rename_all = "snake_case")]
77pub enum ChangeKind {
78 Initial,
79 Refined,
80 Corrected,
81 Reinforced,
82 Weakened,
83}
84
85#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
86pub struct DriftSnapshot {
87 pub fact: FactId,
88 pub target: EntityId,
89 pub recorded_at: Timestamp,
90 pub confidence_bps: u16,
91 pub change: ChangeKind,
92}
93
94#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
95pub struct DriftReport {
96 pub source: EntityId,
97 pub relation: String,
98 pub snapshots: Vec<DriftSnapshot>,
99 pub correction_count: usize,
100 pub stability_bps: u16,
101 pub likely_to_change: bool,
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
105#[serde(rename_all = "snake_case")]
106pub enum ConsolidationKind {
107 SupersedeDuplicate,
108 ReviewOrphan,
109 CompactRevisionChain,
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
113pub struct ConsolidationAction {
114 pub kind: ConsolidationKind,
115 pub keep: Option<FactId>,
116 pub affected_facts: Vec<FactId>,
117 pub affected_entities: Vec<EntityId>,
118 pub rationale: String,
119}
120
121#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
122pub struct ConsolidationPlan {
123 pub actions: Vec<ConsolidationAction>,
124 pub projected_savings: usize,
125 pub source_position: Option<u64>,
126}