diff --git a/Cargo.lock b/Cargo.lock index cbc5687..3b60d22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -139,8 +139,8 @@ dependencies = [ [[package]] name = "echo-system-types" -version = "0.2.0" -source = "git+https://github.com/dnacenta/echo-system-types?tag=v0.2.0#acbadc847e4af646025d67b968330c07083a0d96" +version = "0.3.0" +source = "git+https://github.com/dnacenta/echo-system-types?tag=v0.3.0#ad901031f50fe6f0bef5a9476bbc97a778d00124" dependencies = [ "serde", "serde_json", @@ -505,7 +505,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "vigil-echo" -version = "0.2.0" +version = "0.3.0" dependencies = [ "clap", "dirs", diff --git a/Cargo.toml b/Cargo.toml index 5d91968..e35963a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vigil-echo" -version = "0.2.0" +version = "0.3.0" edition = "2021" description = "Metacognitive monitoring for AI self-evolution" license = "AGPL-3.0-only" @@ -10,7 +10,7 @@ categories = ["command-line-utilities"] authors = ["dnacenta"] [dependencies] -echo-system-types = { git = "https://github.com/dnacenta/echo-system-types", tag = "v0.2.0" } +echo-system-types = { git = "https://github.com/dnacenta/echo-system-types", tag = "v0.3.0" } clap = { version = "4", features = ["derive"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/src/runtime.rs b/src/runtime.rs index f43a49c..b5ffce2 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -403,6 +403,148 @@ where calc_float_trend(frames, |f| if extractor(f) { 1.0 } else { 0.0 }) } +// --------------------------------------------------------------------------- +// Trait implementation: CognitiveMonitor +// --------------------------------------------------------------------------- + +use echo_system_types::monitoring as shared; + +/// Concrete implementation of the CognitiveMonitor trait. +/// +/// pulse-null core creates this and stores it as `Arc`. +/// All existing functions are preserved for standalone CLI use. +pub struct VigilMonitor; + +impl VigilMonitor { + pub fn new() -> Self { + Self + } +} + +impl Default for VigilMonitor { + fn default() -> Self { + Self::new() + } +} + +// --- Internal ↔ Shared type conversions --- + +fn shared_status(s: &CognitiveStatus) -> shared::CognitiveStatus { + match s { + CognitiveStatus::Healthy => shared::CognitiveStatus::Healthy, + CognitiveStatus::Watch => shared::CognitiveStatus::Watch, + CognitiveStatus::Concern => shared::CognitiveStatus::Concern, + CognitiveStatus::Alert => shared::CognitiveStatus::Alert, + } +} + +fn shared_trend(t: &Trend) -> shared::Trend { + match t { + Trend::Improving => shared::Trend::Improving, + Trend::Stable => shared::Trend::Stable, + Trend::Declining => shared::Trend::Declining, + } +} + +fn shared_cognitive_health(h: &CognitiveHealth) -> shared::CognitiveHealth { + shared::CognitiveHealth { + status: shared_status(&h.status), + vocabulary_trend: shared_trend(&h.vocabulary_trend), + question_trend: shared_trend(&h.question_trend), + evidence_trend: shared_trend(&h.evidence_trend), + progress_trend: shared_trend(&h.progress_trend), + suggestions: h.suggestions.clone(), + sufficient_data: h.sufficient_data, + } +} + +fn internal_cognitive_health(h: &shared::CognitiveHealth) -> CognitiveHealth { + CognitiveHealth { + status: match h.status { + shared::CognitiveStatus::Healthy => CognitiveStatus::Healthy, + shared::CognitiveStatus::Watch => CognitiveStatus::Watch, + shared::CognitiveStatus::Concern => CognitiveStatus::Concern, + shared::CognitiveStatus::Alert => CognitiveStatus::Alert, + }, + vocabulary_trend: match h.vocabulary_trend { + shared::Trend::Improving => Trend::Improving, + shared::Trend::Stable => Trend::Stable, + shared::Trend::Declining => Trend::Declining, + }, + question_trend: match h.question_trend { + shared::Trend::Improving => Trend::Improving, + shared::Trend::Stable => Trend::Stable, + shared::Trend::Declining => Trend::Declining, + }, + evidence_trend: match h.evidence_trend { + shared::Trend::Improving => Trend::Improving, + shared::Trend::Stable => Trend::Stable, + shared::Trend::Declining => Trend::Declining, + }, + progress_trend: match h.progress_trend { + shared::Trend::Improving => Trend::Improving, + shared::Trend::Stable => Trend::Stable, + shared::Trend::Declining => Trend::Declining, + }, + suggestions: h.suggestions.clone(), + sufficient_data: h.sufficient_data, + } +} + +fn shared_signal_frame(f: &SignalFrame) -> shared::SignalFrame { + shared::SignalFrame { + timestamp: f.timestamp.clone(), + task_id: f.task_id.clone(), + vocabulary_diversity: f.vocabulary_diversity, + question_count: f.question_count, + evidence_references: f.evidence_references, + thought_progress: f.thought_progress, + } +} + +fn internal_signal_frame(f: &shared::SignalFrame) -> SignalFrame { + SignalFrame { + timestamp: f.timestamp.clone(), + task_id: f.task_id.clone(), + vocabulary_diversity: f.vocabulary_diversity, + question_count: f.question_count, + evidence_references: f.evidence_references, + thought_progress: f.thought_progress, + } +} + +impl shared::CognitiveMonitor for VigilMonitor { + fn assess( + &self, + root_dir: &Path, + window_size: usize, + min_samples: usize, + ) -> shared::CognitiveHealth { + let health = assess(root_dir, window_size, min_samples); + shared_cognitive_health(&health) + } + + fn render_for_prompt(&self, health: &shared::CognitiveHealth) -> String { + let internal = internal_cognitive_health(health); + render(&internal) + } + + fn extract(&self, content: &str, task_id: &str) -> shared::SignalFrame { + let frame = extract(content, task_id); + shared_signal_frame(&frame) + } + + fn record( + &self, + root_dir: &Path, + frame: shared::SignalFrame, + window_size: usize, + ) -> Result<(), Box> { + let internal = internal_signal_frame(&frame); + record(root_dir, internal, window_size) + } +} + // --------------------------------------------------------------------------- // Tests // ---------------------------------------------------------------------------