#![cfg_attr(coverage_nightly, coverage(off))]
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowPrompt {
pub name: String,
pub description: String,
pub category: String,
pub priority: String,
pub prompt: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub methodology: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub constraints: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub heuristics: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub toyota_way_principles: Option<HashMap<String, serde_yaml_ng::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quality_gates: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub validation_tools: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub testing_approaches: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub coverage_target: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mutation_score_target: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub zero_tolerance: Option<HashMap<String, serde_yaml_ng::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub validation: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mutation_targets: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub improvement_goals: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub refactoring_targets: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub optimization_targets: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vulnerability_tolerance: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub security_tools: Option<Vec<String>>,
}
impl WorkflowPrompt {
pub fn from_yaml(yaml_str: &str) -> Result<Self, serde_yaml_ng::Error> {
serde_yaml_ng::from_str(yaml_str)
}
pub fn render(&self, variables: &HashMap<String, String>) -> String {
let mut rendered = self.prompt.clone();
for (key, value) in variables {
let placeholder = format!("${{{key}}}");
rendered = rendered.replace(&placeholder, value);
}
rendered
}
pub fn extract_variables(&self) -> Vec<String> {
let re = regex::Regex::new(r"\$\{([^}]+)\}").expect("internal error");
re.captures_iter(&self.prompt)
.map(|cap| cap[1].to_string())
.collect()
}
pub fn to_yaml(&self) -> Result<String, serde_yaml_ng::Error> {
serde_yaml_ng::to_string(self)
}
pub fn to_json(&self) -> Result<String, serde_json::Error> {
serde_json::to_string_pretty(self)
}
pub fn to_text(&self, variables: &HashMap<String, String>) -> String {
self.render(variables)
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
include!("prompt_model_tests.rs");
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests {
use super::*;
use proptest::prelude::*;
include!("prompt_model_property_tests.rs");
}