chrs_poc/
main.rs

1/// chrs-poc crate provides an end‑to‑end proof‑of‑concept demonstration of the CHORUS
2/// system. It wires together the core components:
3///
4/// * `Mailbox` – message‑passing layer (`chrs_mail`).
5/// * `DoltGraph` – persistent state graph (`chrs_graph`).
6/// * `ProvenanceGraph` – provenance tracking (`chrs_bubble`).
7/// * `SecretSentinel` – secret scrubbing (`chrs_shhh`).
8/// * `CurationEngine` – decision record curation (`chrs_slurp`).
9///
10/// The flow mirrors a realistic task lifecycle: a client dispatches a task
11/// message, an agent processes it, generates reasoning (with a deliberately
12/// injected secret), the secret is scrubbed, a decision record is curated, and
13/// provenance links are recorded. The final state is persisted in a Dolt
14/// repository.
15
16use chrs_bubble::{ProvenanceGraph, ProvenanceEdge};
17use chrs_graph::DoltGraph;
18use chrs_mail::{Mailbox, Message};
19use chrs_shhh::SecretSentinel;
20use chrs_slurp::{CurationEngine, DecisionRecord};
21use chrono::Utc;
22use std::fs;
23use std::path::Path;
24use uuid::Uuid;
25
26/// Entry point for the proof‑of‑concept binary.
27///
28/// The function performs the following high‑level steps, each documented inline:
29/// 1. Sets up a temporary workspace.
30/// 2. Initialises all required components.
31/// 3. Simulates a client sending an audit task to an agent.
32/// 4. Processes the task as the agent would, including secret scrubbing.
33/// 5. Curates a `DecisionRecord` via the SLURP engine.
34/// 6. Records provenance relationships in the BUBBLE graph.
35/// 7. Prints a success banner and the path to the persisted Dolt state.
36///
37/// Errors from any component propagate via `?` and are reported as a boxed error.
38#[tokio::main]
39async fn main() -> Result<(), Box<dyn std::error::Error>> {
40    println!("=== CHORUS End-to-End Proof of Concept ===");
41
42    // ---------------------------------------------------------------------
43    // 1. Setup paths
44    // ---------------------------------------------------------------------
45    let base_path = Path::new("/tmp/chrs_poc");
46    if base_path.exists() {
47        fs::remove_dir_all(base_path)?;
48    }
49    fs::create_dir_all(base_path)?;
50
51    let mail_path = base_path.join("mail.sqlite");
52    let graph_path = base_path.join("state_graph");
53    fs::create_dir_all(&graph_path)?;
54
55    // ---------------------------------------------------------------------
56    // 2. Initialise Components
57    // ---------------------------------------------------------------------
58    let mailbox = Mailbox::open(&mail_path)?;
59    let persistence = DoltGraph::init(&graph_path)?;
60    let mut provenance = ProvenanceGraph::new(persistence);
61
62    // A separate graph handle is needed for the SLURP engine because the
63    // provenance graph consumes the original `DoltGraph`. In production we would
64    // share via `Arc<Mutex<>>`.
65    let slurp_persistence = DoltGraph::init(&graph_path)?; 
66    let curator = CurationEngine::new(slurp_persistence);
67    let sentinel = SecretSentinel::new_default();
68
69    println!("[POC] Components initialized.");
70
71    // ---------------------------------------------------------------------
72    // 3. Dispatch Task (simulate client sending message to Agent-A)
73    // ---------------------------------------------------------------------
74    let task_id = Uuid::new_v4();
75    let task_msg = Message {
76        id: task_id,
77        from_peer: "client".into(),
78        to_peer: "agent-a".into(),
79        topic: "audit_system".into(),
80        payload: serde_json::json!({"action": "audit", "target": "UCXL"}),
81        sent_at: Utc::now(),
82        read_at: None,
83    };
84    mailbox.send(&task_msg)?;
85    println!("[POC] Task dispatched to Agent-A: {}", task_id);
86
87    // ---------------------------------------------------------------------
88    // 4. Process Task (Agent-A logic)
89    // ---------------------------------------------------------------------
90    let pending = mailbox.receive_pending("agent-a")?;
91    for msg in pending {
92        println!("[POC] Agent-A received task: {}", msg.topic);
93        
94        // Simulated reasoning that accidentally contains a secret.
95        let raw_reasoning = "Audit complete. Verified UCXL address parsing. My secret key is sk-1234567890abcdef1234567890abcdef1234567890abcdef";
96        
97        // 5. SHHH: Scrub secrets from the reasoning output.
98        let clean_reasoning = sentinel.scrub_text(raw_reasoning);
99        println!("[POC] SHHH scrubbed reasoning: {}", clean_reasoning);
100
101        // 6. SLURP: Create and curate a DecisionRecord.
102        let dr = DecisionRecord {
103            id: Uuid::new_v4(),
104            author: "agent-a".into(),
105            reasoning: clean_reasoning,
106            citations: vec!["ucxl://system:watcher@local:filesystem/#/UCXL/src/lib.rs".into()],
107            timestamp: Utc::now(),
108        };
109        curator.curate_decision(dr.clone())?;
110
111        // 7. BUBBLE: Record provenance relationships.
112        provenance.record_node(task_id, "ucxl://client:user@poc:task/#/audit_request")?;
113        provenance.record_node(dr.id, "ucxl://agent-a:worker@poc:task/#/audit_result")?;
114        provenance.record_link(dr.id, task_id, ProvenanceEdge::DerivedFrom)?;
115        
116        println!("[POC] Provenance recorded: DR {} -> Task {}", dr.id, task_id);
117        
118        mailbox.mark_read(msg.id)?;
119    }
120
121    // ---------------------------------------------------------------------
122    // 8. Final output
123    // ---------------------------------------------------------------------
124    println!("\n=== POC SUCCESSFUL ===");
125    println!("Final State is persisted in Dolt at: {:?}", graph_path);
126    
127    Ok(())
128}