use crate::AmbiguityScore;
use crate::{EvaluationResult, InterviewResult, Seed};
pub fn degraded_interview(user_input: &str) -> InterviewResult {
let has_verb = contains_action_verb(user_input);
let has_specifics = contains_specifics(user_input);
let goal_clarity = if has_verb { 0.5 } else { 0.2 };
let constraint_clarity = if has_specifics { 0.5 } else { 0.2 };
let success_clarity = 0.2;
let mut result = InterviewResult::new();
result.original_message = user_input.to_string();
result.is_task = has_verb;
if has_verb {
result.add_exchange(
"Could you describe the goal in more detail? What specific outcome do you expect?",
"",
);
} else {
result.chat_response = "Hello! How can I help you today?".to_string();
}
result.update_ambiguity(AmbiguityScore::new(
goal_clarity,
constraint_clarity,
success_clarity,
));
result
}
pub fn degraded_seed(interview: &InterviewResult) -> Seed {
let goal = if !interview.original_message.is_empty() {
interview.original_message.clone()
} else {
"Task from user input".to_string()
};
let mut seed = Seed::new(&goal);
seed.original_request = goal;
seed.constraints.push(
"Requires human clarification: Seed generation failed, spec may be incomplete".to_string(),
);
seed.acceptance_criteria
.push("Task completes without errors".to_string());
seed
}
pub fn degraded_evaluation(seed: &Seed, output: &str, mechanical_pass: bool) -> EvaluationResult {
let output_lower = output.to_lowercase();
let mut matched = 0;
for criterion in &seed.acceptance_criteria {
let keywords: Vec<&str> = criterion
.split_whitespace()
.filter(|w| w.len() > 3 && !matches!(*w, "the" | "must" | "should" | "shall"))
.collect();
let keyword_match = keywords
.iter()
.any(|kw| output_lower.contains(&kw.to_lowercase()));
if keyword_match {
matched += 1;
}
}
let ratio = if seed.acceptance_criteria.is_empty() {
0.5
} else {
matched as f64 / seed.acceptance_criteria.len() as f64
};
let score = if mechanical_pass { 0.7 } else { ratio * 0.6 };
let notes = if mechanical_pass {
vec!["Evaluation parsing failed; using mechanical + keyword fallback.".to_string()]
} else {
vec![
"Evaluation parsing failed; using keyword fallback.".to_string(),
format!(
"Keywords matched: {}/{} criteria",
matched,
seed.acceptance_criteria.len()
),
]
};
EvaluationResult {
mechanical_pass,
semantic_pass: Some(ratio > 0.5),
consensus_pass: None,
score,
notes,
}
}
fn contains_action_verb(text: &str) -> bool {
let verbs = [
"create",
"make",
"build",
"fix",
"find",
"deploy",
"analyze",
"review",
"write",
"read",
"run",
"execute",
"delete",
"update",
"move",
"copy",
"implement",
"refactor",
"debug",
"test",
"install",
"configure",
"setup",
];
let lower = text.to_lowercase();
verbs.iter().any(|v| lower.contains(v))
}
fn contains_specifics(text: &str) -> bool {
if text.contains('/') || text.contains(".rs") || text.contains(".py") || text.contains(".ts") {
return true;
}
if text.contains('"') || text.contains('\'') {
return true;
}
let specifics = [
"rust",
"python",
"typescript",
"javascript",
"go",
"java",
"tokio",
"react",
"axum",
"cargo",
"npm",
"docker",
];
let lower = text.to_lowercase();
specifics.iter().any(|s| lower.contains(s))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_degraded_interview_with_task() {
let result = degraded_interview("Create a new Rust file called main.rs");
assert!(result.is_task);
assert!(!result.original_message.is_empty());
assert!(!result.questions.is_empty());
}
#[test]
fn test_degraded_interview_with_greeting() {
let result = degraded_interview("Hello, how are you?");
assert!(!result.is_task);
}
#[test]
fn test_degraded_seed_preserves_input() {
let mut interview = InterviewResult::new();
interview.original_message = "Fix the login bug".to_string();
let seed = degraded_seed(&interview);
assert_eq!(seed.goal, "Fix the login bug");
}
#[test]
fn test_degraded_evaluation_keyword_match() {
let seed = Seed::new("Create config.toml");
let output = "Created config.toml with default settings";
let result = degraded_evaluation(&seed, output, false);
assert!(result.score > 0.0);
}
#[test]
fn test_contains_action_verb() {
assert!(contains_action_verb("Please fix the bug"));
assert!(contains_action_verb("Create a new file"));
assert!(!contains_action_verb("Hello there"));
}
#[test]
fn test_contains_specifics() {
assert!(contains_specifics("Edit src/main.rs"));
assert!(contains_specifics("Use Rust and Tokio"));
assert!(!contains_specifics("Help me with something"));
}
}