use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EvaluationResult {
pub request_id: String,
pub decision: Decision,
pub score: u8,
pub consensus_achieved: bool,
pub votes: HashMap<String, ModelVote>,
pub findings: Vec<Finding>,
pub feedback: String,
pub timestamp: chrono::DateTime<chrono::Utc>,
}
impl EvaluationResult {
pub fn success(request_id: impl Into<String>, score: u8, feedback: impl Into<String>) -> Self {
Self {
request_id: request_id.into(),
decision: Decision::Pass,
score,
consensus_achieved: true,
votes: HashMap::new(),
findings: Vec::new(),
feedback: feedback.into(),
timestamp: chrono::Utc::now(),
}
}
pub fn failure(request_id: impl Into<String>, score: u8, feedback: impl Into<String>) -> Self {
Self {
request_id: request_id.into(),
decision: Decision::Block,
score,
consensus_achieved: false,
votes: HashMap::new(),
findings: Vec::new(),
feedback: feedback.into(),
timestamp: chrono::Utc::now(),
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum Decision {
Pass,
Revise,
Block,
}
impl std::fmt::Display for Decision {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Decision::Pass => write!(f, "PASS"),
Decision::Revise => write!(f, "REVISE"),
Decision::Block => write!(f, "BLOCK"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelVote {
pub executor: String,
pub vote: Vote,
pub score: u8,
pub reasoning: String,
pub issues: Vec<String>,
pub suggestions: Vec<String>,
}
impl ModelVote {
pub fn new(executor: impl Into<String>, vote: Vote, score: u8) -> Self {
Self {
executor: executor.into(),
vote,
score,
reasoning: String::new(),
issues: Vec::new(),
suggestions: Vec::new(),
}
}
pub fn with_reasoning(mut self, reasoning: impl Into<String>) -> Self {
self.reasoning = reasoning.into();
self
}
pub fn with_issues(mut self, issues: Vec<String>) -> Self {
self.issues = issues;
self
}
pub fn with_suggestions(mut self, suggestions: Vec<String>) -> Self {
self.suggestions = suggestions;
self
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum Vote {
Pass,
Warn,
Fail,
}
impl std::fmt::Display for Vote {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Vote::Pass => write!(f, "PASS"),
Vote::Warn => write!(f, "WARN"),
Vote::Fail => write!(f, "FAIL"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Finding {
pub severity: Severity,
#[serde(default)]
pub category: String,
pub issue: String,
#[serde(default)]
pub lines: Option<Vec<u32>>,
#[serde(default)]
pub suggestion: Option<String>,
#[serde(default)]
pub source: String,
#[serde(default)]
pub consensus_strength: String,
}
impl Finding {
pub fn new(severity: Severity, category: impl Into<String>, issue: impl Into<String>) -> Self {
Self {
severity,
category: category.into(),
issue: issue.into(),
lines: None,
suggestion: None,
source: String::new(),
consensus_strength: String::new(),
}
}
pub fn with_lines(mut self, lines: Vec<u32>) -> Self {
self.lines = Some(lines);
self
}
pub fn with_suggestion(mut self, suggestion: impl Into<String>) -> Self {
self.suggestion = Some(suggestion.into());
self
}
pub fn with_source(mut self, source: impl Into<String>) -> Self {
self.source = source.into();
self
}
pub fn with_consensus_strength(mut self, strength: impl Into<String>) -> Self {
self.consensus_strength = strength.into();
self
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "snake_case")]
pub enum Severity {
Info,
Warning,
Error,
Critical,
}
impl std::fmt::Display for Severity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Severity::Info => write!(f, "INFO"),
Severity::Warning => write!(f, "WARNING"),
Severity::Error => write!(f, "ERROR"),
Severity::Critical => write!(f, "CRITICAL"),
}
}
}