Skip to main content

lsp_max/pipeline/
types.rs

1use serde::{Deserialize, Serialize};
2
3/// A wasm4pm cognitive breed name (must match wasm4pm-cognition BreedId string IDs).
4pub type BreedName = String;
5
6/// Configuration passed to a breed node during pipeline evaluation.
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct BreedNodeConfig {
9    /// The breed to invoke at this pipeline node.
10    pub breed: BreedName,
11    /// Arbitrary JSON params forwarded to the breed's BreedInput.params.
12    pub params: serde_json::Value,
13}
14
15/// A linear pipeline: sequence of breed operations applied in order.
16///
17/// For the initial implementation, pipelines are linear chains (not trees).
18/// Tree pipelines are CANDIDATE for a future iteration.
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct BreedPipeline {
21    /// Unique identifier for this pipeline instance.
22    pub id: String,
23    /// Ordered sequence of breed nodes to execute.
24    pub nodes: Vec<BreedNodeConfig>,
25}
26
27/// Bounded status for pipeline operations.
28///
29/// All variants use bounded language. No victory terms.
30#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31pub enum PipelineBoundedStatus {
32    /// Fitness threshold met; pipeline admitted for this evaluation.
33    Admitted,
34    /// Search in progress or partial convergence observed.
35    Partial,
36    /// Insufficient data to evaluate; gap in tracing or precondition not met.
37    Unknown,
38    /// Hard failure: breed error, empty pipeline, or unrecoverable state.
39    Refused,
40    /// Gate condition blocks evaluation; resolve active ANDON before retrying.
41    Blocked,
42}
43
44impl PipelineBoundedStatus {
45    /// Returns the canonical uppercase string representation of this status.
46    pub fn as_str(&self) -> &'static str {
47        match self {
48            Self::Admitted => "ADMITTED",
49            Self::Partial => "PARTIAL",
50            Self::Unknown => "UNKNOWN",
51            Self::Refused => "REFUSED",
52            Self::Blocked => "BLOCKED",
53        }
54    }
55}
56
57impl std::fmt::Display for PipelineBoundedStatus {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        f.write_str(self.as_str())
60    }
61}
62
63/// Result of evaluating a single pipeline against an OCEL event log.
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct PipelineEvalResult {
66    /// ID of the evaluated pipeline (matches [`BreedPipeline::id`]).
67    pub pipeline_id: String,
68    /// Fitness score in [0.0, 1.0]. Higher = better conformance.
69    pub fitness: f64,
70    /// Bounded status of this evaluation.
71    pub status: PipelineBoundedStatus,
72    /// Breed-level sub-results, one entry per node in evaluation order.
73    pub node_statuses: Vec<BreedNodeStatus>,
74    /// Human-readable summary (one line, no victory language).
75    pub summary: String,
76}
77
78/// Status of a single breed node within a pipeline evaluation.
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct BreedNodeStatus {
81    /// The breed that was evaluated.
82    pub breed: BreedName,
83    /// Bounded status for this node's execution.
84    pub status: PipelineBoundedStatus,
85    /// Short detail string describing the node outcome.
86    pub detail: String,
87}
88
89/// Options for a TPOT2-style pipeline search.
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct PipelineSearchConfig {
92    /// Number of candidate pipelines in each generation.
93    pub population_size: usize,
94    /// Number of generations to evolve.
95    pub generations: usize,
96    /// Probability of a node mutation per generation (0.0–1.0).
97    pub mutation_rate: f64,
98    /// Minimum fitness to consider a pipeline ADMITTED (0.0–1.0).
99    pub admission_threshold: f64,
100    /// Maximum pipeline length (number of breed nodes).
101    pub max_pipeline_length: usize,
102    /// Minimum pipeline length.
103    pub min_pipeline_length: usize,
104}
105
106impl Default for PipelineSearchConfig {
107    fn default() -> Self {
108        Self {
109            population_size: 20,
110            generations: 10,
111            mutation_rate: 0.1,
112            admission_threshold: 0.7,
113            max_pipeline_length: 5,
114            min_pipeline_length: 1,
115        }
116    }
117}
118
119/// Output of a TPOT2 pipeline search run.
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct PipelineSearchResult {
122    /// Bounded status of the overall search run.
123    pub status: PipelineBoundedStatus,
124    /// Best pipeline found, if any generation produced a candidate.
125    pub best_pipeline: Option<BreedPipeline>,
126    /// Fitness score of the best pipeline (0.0 if no candidate found).
127    pub best_fitness: f64,
128    /// Number of generations actually executed.
129    pub generations_run: usize,
130    /// Total number of pipeline evaluations performed.
131    pub evaluations: usize,
132    /// Human-readable summary (one line, no victory language).
133    pub summary: String,
134}