Skip to main content

tj_core/classifier/
mod.rs

1//! Event classifier: takes a chat chunk + recent task context,
2//! returns suggested event_type + task_id + confidence.
3
4use crate::event::{EventType, EvidenceStrength};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize)]
8pub struct ClassifyInput {
9    pub text: String,
10    pub author_hint: String,
11    pub recent_tasks: Vec<TaskContext>,
12}
13
14#[derive(Debug, Clone, Serialize)]
15pub struct TaskContext {
16    pub task_id: String,
17    pub title: String,
18    pub last_events: Vec<String>,
19}
20
21#[derive(Debug, Clone, Deserialize, Serialize)]
22pub struct ClassifyOutput {
23    pub event_type: EventType,
24    pub task_id_guess: Option<String>,
25    pub confidence: f64,
26    pub evidence_strength: Option<EvidenceStrength>,
27    pub suggested_text: String,
28}
29
30pub trait Classifier: Send + Sync {
31    fn classify(&self, input: &ClassifyInput) -> anyhow::Result<ClassifyOutput>;
32}
33
34use crate::event::EventStatus;
35
36pub const CONFIDENCE_THRESHOLD: f64 = 0.85;
37
38pub fn decide_status(confidence: f64) -> EventStatus {
39    if confidence >= CONFIDENCE_THRESHOLD {
40        EventStatus::Confirmed
41    } else {
42        EventStatus::Suggested
43    }
44}
45
46pub mod cli;
47pub mod http;
48pub mod mock;
49pub mod prompt;
50pub mod telemetry;
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55    #[test]
56    fn classify_input_serializes() {
57        let i = ClassifyInput {
58            text: "Adopted Rust for the journal".into(),
59            author_hint: "assistant".into(),
60            recent_tasks: vec![],
61        };
62        let s = serde_json::to_string(&i).unwrap();
63        assert!(s.contains("Adopted Rust"));
64    }
65
66    #[test]
67    fn decide_status_high_confidence_is_confirmed() {
68        assert_eq!(decide_status(0.95), EventStatus::Confirmed);
69        assert_eq!(decide_status(0.85), EventStatus::Confirmed);
70    }
71
72    #[test]
73    fn decide_status_low_confidence_is_suggested() {
74        assert_eq!(decide_status(0.84), EventStatus::Suggested);
75        assert_eq!(decide_status(0.0), EventStatus::Suggested);
76    }
77}