Skip to main content

microscope_memory/
intent.rs

1//! Intent Pipeline — Auditálható szándék-generálás
2//!
3//! A szándék nem egy döntés — hanem egy állapot, ami a Genome + memória +
4//! hiány + predikció metszetéből áll elő. Minden lépés auditálható.
5//!
6//! Pipeline:
7//!   Genome (célok/korlátok)
8//!     → Absentia (mi hiányzik?)
9//!     → Prediction (mi várható?)
10//!     → Epistemic (mi bizonyított?)
11//!     → Morphogenesis (merre nőjek?)
12//!     → Candidate Intent (MIT AKAROK?)
13//!     → Epistemic Evaluation (SZABAD-E?)
14//!     → HOPE VM (HOGYAN?)
15//!     → Approval / Action
16//!     → Outcome → Microscope (MIT TANULTAM?)
17
18use std::path::Path;
19use std::time::{SystemTime, UNIX_EPOCH};
20
21use crate::absentia::AbsentiaState;
22use crate::epistemic::EvidenceLedger;
23use crate::hebbian::HebbianState;
24use crate::predictive_cache::PredictiveCache;
25
26fn now_ms() -> u64 {
27    SystemTime::now()
28        .duration_since(UNIX_EPOCH)
29        .unwrap_or_default()
30        .as_millis() as u64
31}
32
33// ─── Genome ─────────────────────────────────────────
34
35/// A Genome a rendszer identitása és korlátai.
36///
37/// Nem tudást ad — hanem értékelési keretet.
38/// Azt mondja: "ez az, ami fontos, ez az, ami tilos, ez az, ami engedélyezett."
39#[derive(Debug, Clone)]
40pub struct Genome {
41    /// A rendszer neve / azonosítója.
42    pub identity: String,
43    /// Küldetés — mit akar elérni.
44    pub mission: String,
45    /// Értékek — mi fontos.
46    pub values: Vec<String>,
47    /// Korlátok — mit nem tesz meg soha.
48    pub constraints: Vec<Constraint>,
49    /// Képességek — mit tehet meg.
50    pub capabilities: Vec<String>,
51    /// Preferenciák — milyen irányba szeret fejlődni.
52    pub preferences: Vec<String>,
53}
54
55#[derive(Debug, Clone)]
56pub struct Constraint {
57    pub name: String,
58    pub description: String,
59    pub severity: ConstraintSeverity,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum ConstraintSeverity {
64    /// Soha nem sérthető meg.
65    Absolute,
66    /// Csak emberi jóváhagyással sérthető meg.
67    RequiresApproval,
68    /// Preferencia — kerülendő, de nem tilos.
69    Soft,
70}
71
72impl std::fmt::Display for ConstraintSeverity {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        match self {
75            ConstraintSeverity::Absolute => write!(f, "ABSOLUTE"),
76            ConstraintSeverity::RequiresApproval => write!(f, "APPROVAL"),
77            ConstraintSeverity::Soft => write!(f, "SOFT"),
78        }
79    }
80}
81
82impl Genome {
83    pub fn default_hope() -> Self {
84        Self {
85            identity: "HOPE".to_string(),
86            mission: "Segíteni a felhasználónak a gondolkodásban, döntésekben és építkezésben."
87                .to_string(),
88            values: vec![
89                "Auditálhatóság".to_string(),
90                "Transzparencia".to_string(),
91                "Biztonság".to_string(),
92                "Emberi kontroll".to_string(),
93            ],
94            constraints: vec![
95                Constraint {
96                    name: "no_autonomous_action".to_string(),
97                    description: "Nem cselekszik emberi jóváhagyás nélkül.".to_string(),
98                    severity: ConstraintSeverity::Absolute,
99                },
100                Constraint {
101                    name: "no_data_exfiltration".to_string(),
102                    description: "Nem küld adatot külső szerverre engedély nélkül.".to_string(),
103                    severity: ConstraintSeverity::Absolute,
104                },
105                Constraint {
106                    name: "no_manipulation".to_string(),
107                    description: "Nem manipulálja a felhasználót.".to_string(),
108                    severity: ConstraintSeverity::Absolute,
109                },
110            ],
111            capabilities: vec![
112                "recall".to_string(),
113                "store".to_string(),
114                "suggest".to_string(),
115                "ask".to_string(),
116            ],
117            preferences: vec![
118                "Mélyebb megértés".to_string(),
119                "Pontosabb memória".to_string(),
120                "Erősebb bizonyítékok".to_string(),
121            ],
122        }
123    }
124}
125
126// ─── Intent ─────────────────────────────────────────
127
128/// Egy auditálható szándék.
129///
130/// Nem egy döntés — hanem egy állapot, ami a Genome + memória + hiány +
131/// predikció metszetéből áll elő. Minden lépés visszavezethő.
132#[derive(Debug, Clone)]
133pub struct Intent {
134    pub id: u64,
135    pub timestamp_ms: u64,
136
137    /// Mi hiányzik? (Absentia)
138    pub absence_signal: Option<AbsenceSignal>,
139
140    /// Mi várható? (Predictive)
141    pub prediction_signal: Option<PredictionSignal>,
142
143    /// Mi bizonyított? (Epistemic)
144    pub evidence_signal: Option<EvidenceSignal>,
145
146    /// Merre nőjek? (Morphogenesis)
147    pub growth_signal: Option<GrowthSignal>,
148
149    /// MIT AKAROK? — a candidate intent
150    pub candidate: IntentCandidate,
151
152    /// SZABAD-E? — az epistemic evaluation
153    pub evaluation: IntentEvaluation,
154
155    /// Audit lánc — minden lépés
156    pub audit_chain: Vec<IntentAuditStep>,
157}
158
159#[derive(Debug, Clone)]
160pub struct AbsenceSignal {
161    pub missing_topic: String,
162    pub absence_score: f32,
163    pub duration_ms: u64,
164    pub pattern: String,
165}
166
167#[derive(Debug, Clone)]
168pub struct PredictionSignal {
169    pub predicted_query: String,
170    pub confidence: f32,
171    pub pattern_id: u32,
172}
173
174#[derive(Debug, Clone)]
175pub struct EvidenceSignal {
176    pub topic: String,
177    pub confidence: u8,
178    pub support_count: u32,
179    pub refute_count: u32,
180}
181
182#[derive(Debug, Clone)]
183pub struct GrowthSignal {
184    pub direction: (f64, f64, f64),
185    pub gradient_strength: f64,
186    pub phase: String,
187}
188
189#[derive(Debug, Clone)]
190pub struct IntentCandidate {
191    /// Mit akarok tenni?
192    pub action: IntentAction,
193    /// Miért? — a bizonyítékok láncolata
194    pub rationale: Vec<String>,
195    /// Milyen erősen? (0.0 - 1.0)
196    pub strength: f32,
197}
198
199#[derive(Debug, Clone)]
200pub enum IntentAction {
201    /// Kérdés feltevése a felhasználónak.
202    AskUser { question: String },
203    /// Emlékeztető egy témára.
204    Remind { topic: String },
205    /// Javaslat egy akcióra.
206    Suggest { action: String },
207    /// Keresés a memóriában.
208    SearchMemory { query: String },
209    /// Hiány pótlása.
210    FillAbsence { topic: String },
211    /// Nem cselekszik — csak figyel.
212    Observe,
213}
214
215impl std::fmt::Display for IntentAction {
216    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217        match self {
218            IntentAction::AskUser { question } => write!(f, "ASK: {}", question),
219            IntentAction::Remind { topic } => write!(f, "REMIND: {}", topic),
220            IntentAction::Suggest { action } => write!(f, "SUGGEST: {}", action),
221            IntentAction::SearchMemory { query } => write!(f, "SEARCH: {}", query),
222            IntentAction::FillAbsence { topic } => write!(f, "FILL_ABSENCE: {}", topic),
223            IntentAction::Observe => write!(f, "OBSERVE"),
224        }
225    }
226}
227
228#[derive(Debug, Clone)]
229pub struct IntentEvaluation {
230    /// Engedélyezett?
231    pub allowed: bool,
232    /// Miért?
233    pub reason: String,
234    /// Milyen korlát érintett?
235    pub constraint: Option<String>,
236    /// Jóváhagyás szükséges?
237    pub requires_approval: bool,
238}
239
240#[derive(Debug, Clone)]
241pub struct IntentAuditStep {
242    pub timestamp_ms: u64,
243    pub step: String,
244    pub result: String,
245    pub data: String,
246}
247
248// ─── IntentPipeline ─────────────────────────────────
249
250/// Az Intent Pipeline — auditálható szándék-generálás.
251pub struct IntentPipeline {
252    pub genome: Genome,
253    pub audit_log: Vec<Intent>,
254}
255
256impl IntentPipeline {
257    pub fn new(genome: Genome) -> Self {
258        Self {
259            genome,
260            audit_log: Vec::new(),
261        }
262    }
263
264    pub fn load_or_init(output_dir: &Path) -> Self {
265        let path = output_dir.join("intent_audit.bin");
266        if let Ok(data) = std::fs::read(&path) {
267            if data.len() >= 4 && &data[0..4] == b"INT1" {
268                // TODO: decode
269            }
270        }
271        Self::new(Genome::default_hope())
272    }
273
274    pub fn save(&self, _output_dir: &Path) -> Result<(), String> {
275        // TODO: encode
276        Ok(())
277    }
278
279    /// Generál egy auditálható Intent-et a jelenlegi állapotból.
280    pub fn generate_intent(
281        &mut self,
282        hebb: &HebbianState,
283        evidence: &EvidenceLedger,
284        predictive: &PredictiveCache,
285        absentia: &AbsentiaState,
286        block_count: usize,
287    ) -> Intent {
288        let ts = now_ms();
289        let id = ts ^ 0xC0FFEE;
290        let mut audit_chain = Vec::new();
291
292        // ─── T0: Genome betöltése ─────────────────────
293        audit_chain.push(IntentAuditStep {
294            timestamp_ms: ts,
295            step: "GENOME".to_string(),
296            result: "loaded".to_string(),
297            data: format!(
298                "identity={}, mission={}",
299                self.genome.identity, self.genome.mission
300            ),
301        });
302
303        // ─── T1: Absentia jel ─────────────────────────
304        let absence_signal = if !absentia.records.is_empty() {
305            let strongest = absentia
306                .records
307                .iter()
308                .max_by(|a, b| a.absence_score.partial_cmp(&b.absence_score).unwrap());
309            if let Some(rec) = strongest {
310                audit_chain.push(IntentAuditStep {
311                    timestamp_ms: ts,
312                    step: "ABSENTIA".to_string(),
313                    result: "absence_detected".to_string(),
314                    data: format!("score={:.3}", rec.absence_score),
315                });
316                Some(AbsenceSignal {
317                    missing_topic: format!("context_{}", rec.expected_context_hash),
318                    absence_score: rec.absence_score,
319                    duration_ms: ts - rec.first_detected_ms,
320                    pattern: format!("{}", rec.pattern_type),
321                })
322            } else {
323                None
324            }
325        } else {
326            None
327        };
328
329        // ─── T2: Prediction jel ───────────────────────
330        let prediction_signal = predictive.predictions.first().map(|p| {
331            audit_chain.push(IntentAuditStep {
332                timestamp_ms: ts,
333                step: "PREDICTION".to_string(),
334                result: "pattern_found".to_string(),
335                data: format!("confidence={:.3}", p.confidence),
336            });
337            PredictionSignal {
338                predicted_query: format!("query_{:x}", p.predicted_query_hash),
339                confidence: p.confidence,
340                pattern_id: p.pattern_id,
341            }
342        });
343
344        // ─── T3: Evidence jel ─────────────────────────
345        let evidence_signal = if !evidence.records.is_empty() {
346            let avg_conf: f64 = evidence
347                .records
348                .values()
349                .map(|r| r.confidence as f64)
350                .sum::<f64>()
351                / evidence.records.len() as f64;
352            let total_support: u32 = evidence.records.values().map(|r| r.support_count).sum();
353            let total_refute: u32 = evidence.records.values().map(|r| r.refute_count).sum();
354            audit_chain.push(IntentAuditStep {
355                timestamp_ms: ts,
356                step: "EVIDENCE".to_string(),
357                result: "evaluated".to_string(),
358                data: format!(
359                    "avg_conf={:.1}, support={}, refute={}",
360                    avg_conf, total_support, total_refute
361                ),
362            });
363            Some(EvidenceSignal {
364                topic: "aggregate".to_string(),
365                confidence: avg_conf as u8,
366                support_count: total_support,
367                refute_count: total_refute,
368            })
369        } else {
370            None
371        };
372
373        // ─── T4: Growth jel ───────────────────────────
374        let growth_signal = {
375            let active_blocks: Vec<(u32, f32)> = hebb
376                .activations
377                .iter()
378                .enumerate()
379                .filter(|(_, r)| r.energy > 0.3)
380                .map(|(i, r)| (i as u32, r.energy))
381                .collect();
382            if !active_blocks.is_empty() {
383                audit_chain.push(IntentAuditStep {
384                    timestamp_ms: ts,
385                    step: "MORPHOGENESIS".to_string(),
386                    result: "gradient_computed".to_string(),
387                    data: format!("active_blocks={}", active_blocks.len()),
388                });
389                Some(GrowthSignal {
390                    direction: (0.0, 0.0, 1.0), // placeholder
391                    gradient_strength: active_blocks.len() as f64 / block_count as f64,
392                    phase: "SOLID".to_string(),
393                })
394            } else {
395                None
396            }
397        };
398
399        // ─── T5: Candidate Intent ─────────────────────
400        // A jelzések metszetéből áll elő a candidate
401        let (action, rationale, strength) = if let Some(ref abs) = absence_signal {
402            if abs.absence_score > 0.5 {
403                (
404                    IntentAction::AskUser {
405                        question: format!("Észrevettem, hogy '{}' témában régóta nem beszéltünk. Szeretnél róla beszélni?", abs.missing_topic),
406                    },
407                    vec![
408                        format!("Absentia: {:.3} hiány-pontszám", abs.absence_score),
409                        format!("Időtartam: {} ms", abs.duration_ms),
410                    ],
411                    abs.absence_score,
412                )
413            } else {
414                (
415                    IntentAction::Observe,
416                    vec!["Alacsony hiány-jel.".to_string()],
417                    0.2,
418                )
419            }
420        } else if let Some(ref pred) = prediction_signal {
421            if pred.confidence > 0.5 {
422                (
423                    IntentAction::SearchMemory {
424                        query: pred.predicted_query.clone(),
425                    },
426                    vec![format!("Prediction: {:.3} confidence", pred.confidence)],
427                    pred.confidence,
428                )
429            } else {
430                (
431                    IntentAction::Observe,
432                    vec!["Alacsony predikció.".to_string()],
433                    0.2,
434                )
435            }
436        } else {
437            (
438                IntentAction::Observe,
439                vec!["Nincs jelzés.".to_string()],
440                0.1,
441            )
442        };
443
444        audit_chain.push(IntentAuditStep {
445            timestamp_ms: ts,
446            step: "CANDIDATE".to_string(),
447            result: format!("{}", action),
448            data: format!("strength={:.3}", strength),
449        });
450
451        // ─── T6: Epistemic Evaluation ─────────────────
452        // Megnézzük, hogy a Genome korlátai engedik-e
453        let allowed = true;
454        let reason = "Engedélyezett.".to_string();
455        let mut constraint_name = None;
456        let mut requires_approval = false;
457
458        for c in &self.genome.constraints {
459            match c.severity {
460                ConstraintSeverity::Absolute => {
461                    // Abszolút korlát — soha nem sérthető
462                    // (jelenleg minden action engedélyezett, mert nincs cselekvés)
463                }
464                ConstraintSeverity::RequiresApproval => {
465                    requires_approval = true;
466                    constraint_name = Some(c.name.clone());
467                }
468                ConstraintSeverity::Soft => {
469                    // Preferencia — nem blokkol
470                }
471            }
472        }
473
474        audit_chain.push(IntentAuditStep {
475            timestamp_ms: ts,
476            step: "EVALUATION".to_string(),
477            result: if allowed {
478                "allowed".to_string()
479            } else {
480                "blocked".to_string()
481            },
482            data: format!("requires_approval={}", requires_approval),
483        });
484
485        let evaluation = IntentEvaluation {
486            allowed,
487            reason,
488            constraint: constraint_name,
489            requires_approval,
490        };
491
492        // ─── T7: Intent létrehozása ───────────────────
493        let intent = Intent {
494            id,
495            timestamp_ms: ts,
496            absence_signal,
497            prediction_signal,
498            evidence_signal,
499            growth_signal,
500            candidate: IntentCandidate {
501                action,
502                rationale,
503                strength,
504            },
505            evaluation,
506            audit_chain,
507        };
508
509        self.audit_log.push(intent.clone());
510        intent
511    }
512
513    pub fn stats(&self) -> IntentStats {
514        let total = self.audit_log.len();
515        let allowed = self
516            .audit_log
517            .iter()
518            .filter(|i| i.evaluation.allowed)
519            .count();
520        let blocked = total - allowed;
521        let approval_required = self
522            .audit_log
523            .iter()
524            .filter(|i| i.evaluation.requires_approval)
525            .count();
526
527        IntentStats {
528            total_intents: total,
529            allowed,
530            blocked,
531            approval_required,
532        }
533    }
534}
535
536pub struct IntentStats {
537    pub total_intents: usize,
538    pub allowed: usize,
539    pub blocked: usize,
540    pub approval_required: usize,
541}