1pub use lsp_max_protocol::{HookEvent, InstanceId, MaxDiagnostic, PolicyState, Receipt};
2
3#[derive(Debug, Clone)]
4pub enum MeshAction {
5 TransitionPolicyState {
6 instance_id: InstanceId,
7 new_state: PolicyState,
8 },
9 ClearDiagnostic {
10 instance_id: InstanceId,
11 diagnostic_id: String,
12 },
13 AddDiagnostic {
14 instance_id: InstanceId,
15 diagnostic: Box<MaxDiagnostic>,
16 },
17 EmitReceipt {
18 instance_id: InstanceId,
19 receipt: Receipt,
20 },
21 ExecuteBoundedAction {
22 instance_id: InstanceId,
23 action_id: String,
24 description: String,
25 },
26 ResetInstance {
27 instance_id: InstanceId,
28 },
29}
30
31impl std::fmt::Display for MeshAction {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 match self {
34 MeshAction::TransitionPolicyState {
35 instance_id,
36 new_state,
37 } => {
38 write!(f, "TransitionPolicyState({}, {:?})", instance_id, new_state)
39 }
40 MeshAction::ClearDiagnostic {
41 instance_id,
42 diagnostic_id,
43 } => {
44 write!(f, "ClearDiagnostic({}, {})", instance_id, diagnostic_id)
45 }
46 MeshAction::AddDiagnostic { instance_id, .. } => {
47 write!(f, "AddDiagnostic({})", instance_id)
48 }
49 MeshAction::EmitReceipt {
50 instance_id,
51 receipt,
52 } => {
53 write!(f, "EmitReceipt({}, {})", instance_id, receipt.receipt_id)
54 }
55 MeshAction::ExecuteBoundedAction {
56 instance_id,
57 action_id,
58 ..
59 } => {
60 write!(f, "ExecuteBoundedAction({}, {})", instance_id, action_id)
61 }
62 MeshAction::ResetInstance { instance_id } => {
63 write!(f, "ResetInstance({})", instance_id)
64 }
65 }
66 }
67}
68
69#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
71pub enum FailureMode {
72 RefuseEvent,
73 EmitDiagnostic,
74 Halt,
75}
76
77#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
79pub struct HookDescriptor {
80 pub name: &'static str,
81 pub input_type: &'static str,
82 pub output_type: &'static str,
83 pub trigger_law: &'static str,
84 pub failure_mode: FailureMode,
85}
86
87pub trait Hook: Send + Sync {
88 fn name(&self) -> &str;
89 fn trigger(&self, event: &HookEvent) -> Vec<MeshAction>;
90 fn descriptor(&self) -> HookDescriptor;
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
95pub enum LspPhase {
96 Uninitialized,
97 Initializing,
98 Initialized,
99 ShutDown,
100 Exited,
101}
102
103impl std::fmt::Display for LspPhase {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 match self {
106 LspPhase::Uninitialized => write!(f, "Uninitialized"),
107 LspPhase::Initializing => write!(f, "Initializing"),
108 LspPhase::Initialized => write!(f, "Initialized"),
109 LspPhase::ShutDown => write!(f, "ShutDown"),
110 LspPhase::Exited => write!(f, "Exited"),
111 }
112 }
113}
114
115#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
116pub struct LspInstance {
117 pub id: String,
118 pub phase: LspPhase,
119 pub diagnostics: Vec<MaxDiagnostic>,
120 pub receipts: Vec<Receipt>,
121 pub policy_state: Option<PolicyState>,
122 #[serde(skip)]
123 cached_score: std::cell::Cell<Option<f64>>,
124}
125
126impl LspInstance {
127 pub fn new(id: &str) -> Self {
128 Self {
129 id: id.to_string(),
130 phase: LspPhase::Uninitialized,
131 diagnostics: Vec::new(),
132 receipts: Vec::new(),
133 policy_state: None,
134 cached_score: std::cell::Cell::new(None),
135 }
136 }
137
138 #[inline]
139 pub fn invalidate_score_cache(&mut self) {
140 self.cached_score.set(None);
141 }
142
143 pub fn add_diagnostic(&mut self, diag: MaxDiagnostic) {
144 self.diagnostics.push(diag);
145 self.invalidate_score_cache();
146 }
147
148 pub fn remove_diagnostic(&mut self, diagnostic_id: &str) -> usize {
149 let before = self.diagnostics.len();
150 self.diagnostics
151 .retain(|d| d.diagnostic_id != diagnostic_id);
152 let removed = before - self.diagnostics.len();
153 if removed > 0 {
154 self.invalidate_score_cache();
155 }
156 removed
157 }
158
159 pub fn conformance_score(&self) -> f64 {
160 if let Some(score) = self.cached_score.get() {
161 return score;
162 }
163 let mut penalty: f64 = 0.0;
164 for diag in &self.diagnostics {
165 let p = match diag.lsp.severity {
166 Some(lsp_types_max::DiagnosticSeverity::ERROR) => 30.0,
167 Some(lsp_types_max::DiagnosticSeverity::WARNING) => 20.0,
168 Some(lsp_types_max::DiagnosticSeverity::INFORMATION) => 10.0,
169 Some(lsp_types_max::DiagnosticSeverity::HINT) => 5.0,
170 Some(_) => 30.0,
171 None => 30.0,
172 };
173 penalty += p;
174 }
175 let score = f64::max(100.0 - penalty, 0.0);
176 self.cached_score.set(Some(score));
177 score
178 }
179
180 pub fn conformance_grade(&self) -> ConformanceGrade {
181 ConformanceGrade::from_score(self.conformance_score())
182 }
183}
184
185impl Default for LspInstance {
186 fn default() -> Self {
187 Self {
188 id: String::new(),
189 phase: LspPhase::Uninitialized,
190 diagnostics: Vec::new(),
191 receipts: Vec::new(),
192 policy_state: None,
193 cached_score: std::cell::Cell::new(None),
194 }
195 }
196}
197
198#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
200pub enum ConformanceGrade {
201 Perfect,
202 Good,
203 Degraded,
204 Critical,
205}
206
207impl ConformanceGrade {
208 pub fn from_score(score: f64) -> Self {
209 if score >= 100.0 {
210 ConformanceGrade::Perfect
211 } else if score >= 75.0 {
212 ConformanceGrade::Good
213 } else if score >= 50.0 {
214 ConformanceGrade::Degraded
215 } else {
216 ConformanceGrade::Critical
217 }
218 }
219
220 pub fn as_str(&self) -> &'static str {
221 match self {
222 ConformanceGrade::Perfect => "perfect",
223 ConformanceGrade::Good => "good",
224 ConformanceGrade::Degraded => "degraded",
225 ConformanceGrade::Critical => "critical",
226 }
227 }
228}
229
230impl std::fmt::Display for ConformanceGrade {
231 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
232 write!(f, "{}", self.as_str())
233 }
234}
235
236#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
237pub struct AutonomicMeshState {
238 pub instances: std::collections::HashMap<String, LspInstance>,
239 pub event_log: Vec<HookEvent>,
240 pub executed_bounded_actions: Vec<String>,
241 #[serde(flatten)]
242 pub extra: std::collections::HashMap<String, serde_json::Value>,
243}
244
245impl std::fmt::Display for AutonomicMeshState {
246 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247 write!(
248 f,
249 "AutonomicMeshState {{ instances: {}, event_log: {} }}",
250 self.instances.len(),
251 self.event_log.len()
252 )
253 }
254}
255
256#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
257pub struct ConformanceDeltaEntry {
258 pub seq: u64,
259 pub instance_id: String,
260 pub old_score: f64,
261 pub new_score: f64,
262 pub timestamp: String,
264}
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq)]
267pub enum MaxMethod {
268 Snapshot,
269 ConformanceVector,
270 ClearDiagnostic,
271 ExplainDiagnostic,
272 RepairPlan,
273 ApplyRepairTransaction,
274 ExportAnalysisBundle,
275 RunGate,
276 Receipt,
277 Hook,
278 HookGraph,
279 Chain,
280 Propagate,
281 AutonomicLoop,
282 ManifoldSnapshot,
283 LawfulTransition,
284 Admission,
285 Refusal,
286 Replay,
287 ReleaseActuation,
288 InstanceList,
289 DumpState,
290 RestoreState,
291 Reset,
292 ConformanceDelta,
293 VerifyLedger,
294 LedgerReport,
295}
296
297impl MaxMethod {
298 pub fn as_str(self) -> &'static str {
299 match self {
300 MaxMethod::Snapshot => "max/snapshot",
301 MaxMethod::ConformanceVector => "max/conformanceVector",
302 MaxMethod::ClearDiagnostic => "max/clearDiagnostic",
303 MaxMethod::ExplainDiagnostic => "max/explainDiagnostic",
304 MaxMethod::RepairPlan => "max/repairPlan",
305 MaxMethod::ApplyRepairTransaction => "max/applyRepairTransaction",
306 MaxMethod::ExportAnalysisBundle => "max/exportAnalysisBundle",
307 MaxMethod::RunGate => "max/runGate",
308 MaxMethod::Receipt => "max/receipt",
309 MaxMethod::Hook => "max/hook",
310 MaxMethod::HookGraph => "max/hookGraph",
311 MaxMethod::Chain => "max/chain",
312 MaxMethod::Propagate => "max/propagate",
313 MaxMethod::AutonomicLoop => "max/autonomicLoop",
314 MaxMethod::ManifoldSnapshot => "max/manifoldSnapshot",
315 MaxMethod::LawfulTransition => "max/lawfulTransition",
316 MaxMethod::Admission => "max/admission",
317 MaxMethod::Refusal => "max/refusal",
318 MaxMethod::Replay => "max/replay",
319 MaxMethod::ReleaseActuation => "max/releaseActuation",
320 MaxMethod::InstanceList => "max/instanceList",
321 MaxMethod::DumpState => "max/dumpState",
322 MaxMethod::RestoreState => "max/restoreState",
323 MaxMethod::Reset => "max/reset",
324 MaxMethod::ConformanceDelta => "max/conformanceDelta",
325 MaxMethod::VerifyLedger => "max/verifyLedger",
326 MaxMethod::LedgerReport => "max/ledgerReport",
327 }
328 }
329}
330
331impl<'a> TryFrom<&'a str> for MaxMethod {
332 type Error = ();
333
334 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
335 match s {
336 "max/snapshot" => Ok(MaxMethod::Snapshot),
337 "max/conformanceVector" => Ok(MaxMethod::ConformanceVector),
338 "max/clearDiagnostic" => Ok(MaxMethod::ClearDiagnostic),
339 "max/explainDiagnostic" => Ok(MaxMethod::ExplainDiagnostic),
340 "max/repairPlan" => Ok(MaxMethod::RepairPlan),
341 "max/applyRepairTransaction" => Ok(MaxMethod::ApplyRepairTransaction),
342 "max/exportAnalysisBundle" => Ok(MaxMethod::ExportAnalysisBundle),
343 "max/runGate" => Ok(MaxMethod::RunGate),
344 "max/receipt" => Ok(MaxMethod::Receipt),
345 "max/hook" => Ok(MaxMethod::Hook),
346 "max/hookGraph" => Ok(MaxMethod::HookGraph),
347 "max/chain" => Ok(MaxMethod::Chain),
348 "max/propagate" => Ok(MaxMethod::Propagate),
349 "max/autonomicLoop" => Ok(MaxMethod::AutonomicLoop),
350 "max/manifoldSnapshot" => Ok(MaxMethod::ManifoldSnapshot),
351 "max/lawfulTransition" => Ok(MaxMethod::LawfulTransition),
352 "max/admission" => Ok(MaxMethod::Admission),
353 "max/refusal" => Ok(MaxMethod::Refusal),
354 "max/replay" => Ok(MaxMethod::Replay),
355 "max/releaseActuation" => Ok(MaxMethod::ReleaseActuation),
356 "max/instanceList" => Ok(MaxMethod::InstanceList),
357 "max/dumpState" => Ok(MaxMethod::DumpState),
358 "max/restoreState" => Ok(MaxMethod::RestoreState),
359 "max/reset" => Ok(MaxMethod::Reset),
360 "max/conformanceDelta" => Ok(MaxMethod::ConformanceDelta),
361 "max/verifyLedger" => Ok(MaxMethod::VerifyLedger),
362 "max/ledgerReport" => Ok(MaxMethod::LedgerReport),
363 _ => Err(()),
364 }
365 }
366}