Skip to main content

disyn_core/
ports.rs

1use async_trait::async_trait;
2
3use crate::Result;
4use crate::types::{
5    ApprovedPlan, DeceptionReport, ExecutionReport, Facts, FormalSpec, GroundedExtraction,
6    MemoryContext, Observation, PlanDraft, ProofVerdict, RetrievalStrategy, SymbolicAnchor,
7    VerificationReport, WeightedPassage,
8};
9
10#[async_trait]
11pub trait FactExtractor: Send + Sync {
12    async fn extract(&self, observation: &Observation) -> Result<Facts>;
13}
14
15#[async_trait]
16pub trait ProposalEngine: Send + Sync {
17    async fn propose(&self, facts: &Facts, memory: &MemoryContext) -> Result<PlanDraft>;
18}
19
20pub trait Verifier: Send + Sync {
21    fn verify(&self, draft: &PlanDraft) -> VerificationReport;
22}
23
24/// Implementations must preserve `PlannedStep::idempotency_key` for steps
25/// with identical actions. New steps introduced by repair get fresh UUIDs.
26pub trait RepairEngine: Send + Sync {
27    fn repair(&self, draft: &PlanDraft, report: &VerificationReport) -> Option<PlanDraft>;
28}
29
30#[async_trait]
31pub trait MemoryStore: Send + Sync {
32    async fn retrieve(&self, facts: &Facts) -> Result<MemoryContext>;
33    async fn persist(&self, report: &ExecutionReport) -> Result<()>;
34}
35
36#[async_trait]
37pub trait ActionExecutor: Send + Sync {
38    async fn execute(&self, plan: &ApprovedPlan) -> Result<ExecutionReport>;
39}
40
41#[async_trait]
42pub trait GraphStore: Send + Sync {
43    async fn index(&self, facts: &Facts) -> Result<()>;
44    async fn traverse(
45        &self,
46        facts: &Facts,
47        strategy: &RetrievalStrategy,
48    ) -> Result<Vec<WeightedPassage>>;
49    fn resolve_anchors(&self, facts: &Facts) -> Vec<SymbolicAnchor>;
50}
51
52pub trait TelemetrySink: Send + Sync {
53    fn emit(&self, event: &SpanEvent);
54}
55
56pub trait FormalVerifier: Send + Sync {
57    fn synthesize(&self, extraction: &GroundedExtraction) -> FormalSpec;
58    fn verify_spec(&self, spec: &FormalSpec, extraction: &GroundedExtraction) -> ProofVerdict;
59    fn scan_deception(&self, _extraction: &GroundedExtraction) -> DeceptionReport {
60        DeceptionReport {
61            detected: false,
62            level: None,
63            evidence_fact_ids: vec![],
64        }
65    }
66}
67
68#[derive(Debug, Clone)]
69pub enum SpanKind {
70    ProposalGenerate,
71    VerifierCheck,
72    RepairApply,
73    ExecutorDispatch,
74}
75
76#[derive(Debug, Clone)]
77pub enum SpanStatus {
78    Ok,
79    Error(String),
80}
81
82#[derive(Debug, Clone)]
83pub struct SpanEvent {
84    pub kind: SpanKind,
85    pub trace_id: uuid::Uuid,
86    pub parent_id: Option<uuid::Uuid>,
87    pub duration_ms: u64,
88    pub status: SpanStatus,
89    pub metadata: serde_json::Value,
90}