Skip to main content

tramli_plugins/api/
mod.rs

1use std::fmt;
2use tramli::{FlowDefinition, FlowEngine, FlowState};
3
4/// Plugin kind classification.
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum PluginKind {
7    Analysis,
8    Store,
9    Engine,
10    RuntimeAdapter,
11    Generation,
12    Documentation,
13}
14
15/// Plugin descriptor.
16#[derive(Debug, Clone)]
17pub struct PluginDescriptor {
18    pub id: &'static str,
19    pub display_name: &'static str,
20    pub description: &'static str,
21}
22
23/// A single report finding.
24#[derive(Debug, Clone)]
25pub struct Finding {
26    pub plugin_id: String,
27    pub severity: String,
28    pub message: String,
29}
30
31/// Collects analysis findings across plugins.
32#[derive(Debug, Default)]
33pub struct PluginReport {
34    entries: Vec<Finding>,
35}
36
37impl PluginReport {
38    pub fn new() -> Self {
39        Self { entries: Vec::new() }
40    }
41
42    pub fn add(&mut self, plugin_id: &str, severity: &str, message: &str) {
43        self.entries.push(Finding {
44            plugin_id: plugin_id.to_string(),
45            severity: severity.to_string(),
46            message: message.to_string(),
47        });
48    }
49
50    pub fn warn(&mut self, plugin_id: &str, message: &str) {
51        self.add(plugin_id, "WARN", message);
52    }
53
54    pub fn error(&mut self, plugin_id: &str, message: &str) {
55        self.add(plugin_id, "ERROR", message);
56    }
57
58    pub fn findings(&self) -> &[Finding] {
59        &self.entries
60    }
61
62    pub fn as_text(&self) -> String {
63        if self.entries.is_empty() {
64            return "No findings.".to_string();
65        }
66        self.entries
67            .iter()
68            .map(|e| format!("[{}] {}: {}", e.severity, e.plugin_id, e.message))
69            .collect::<Vec<_>>()
70            .join("\n")
71    }
72}
73
74impl fmt::Display for PluginReport {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        write!(f, "{}", self.as_text())
77    }
78}
79
80/// Analysis plugin — static analysis of FlowDefinition.
81pub trait AnalysisPlugin<S: FlowState>: Send + Sync {
82    fn descriptor(&self) -> PluginDescriptor;
83    fn analyze(&self, definition: &FlowDefinition<S>, report: &mut PluginReport);
84}
85
86/// Engine plugin — installs hooks on FlowEngine.
87pub trait EnginePlugin<S: FlowState>: Send + Sync {
88    fn descriptor(&self) -> PluginDescriptor;
89    fn install(&self, engine: &mut FlowEngine<S>);
90}
91
92/// Runtime adapter plugin — binds FlowEngine to return richer API.
93pub trait RuntimeAdapterPlugin<S: FlowState>: Send + Sync {
94    fn descriptor(&self) -> PluginDescriptor;
95    fn id(&self) -> &str { self.descriptor().id }
96}