const MORPH_STUB_ORIGINAL_MIN: usize = 500;
const MORPH_STUB_FLOOR_BYTES: usize = 50;
pub(super) fn validate_morph_output(
original: &str,
merged: &str,
) -> std::result::Result<(), String> {
if merged.trim().is_empty() {
return Err("Morph returned an empty response".to_string());
}
if original.len() > MORPH_STUB_ORIGINAL_MIN && merged.len() < MORPH_STUB_FLOOR_BYTES {
return Err(format!(
"Morph response shrank from {} to {} bytes — likely truncated",
original.len(),
merged.len()
));
}
if original.ends_with('\n') && !merged.ends_with('\n') {
return Err(
"Morph response is missing the trailing newline — likely truncated mid-line"
.to_string(),
);
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rejects_empty() {
assert!(validate_morph_output("fn main() { println!(\"hi\"); }", "").is_err());
assert!(validate_morph_output("fn main() { println!(\"hi\"); }", " \n ").is_err());
}
#[test]
fn rejects_dramatic_shrink() {
let original =
"fn main() {\n".to_string() + &" println!(\"line\");\n".repeat(40) + "}\n";
let merged = "fn main() {\n";
assert!(validate_morph_output(&original, merged).is_err());
}
#[test]
fn accepts_reasonable_edits() {
let original =
"fn main() {\n".to_string() + &" println!(\"line\");\n".repeat(40) + "}\n";
let merged = "fn main() {\n".to_string() + &" println!(\"other\");\n".repeat(40) + "}\n";
assert!(validate_morph_output(&original, &merged).is_ok());
}
#[test]
fn allows_legitimate_small_stub() {
let original =
"fn main() {\n".to_string() + &" println!(\"line\");\n".repeat(40) + "}\n";
let merged = "fn main() {\n // trimmed down by user\n Ok(())\n}\n";
assert!(
merged.len() >= 50,
"test stub must be at or above the floor"
);
assert!(validate_morph_output(&original, merged).is_ok());
}
#[test]
fn rejects_missing_trailing_newline() {
let original = "line 1\nline 2\nline 3\n";
let merged = "line 1\nline 2\nline";
assert!(validate_morph_output(original, merged).is_err());
}
#[test]
fn allows_no_newline_when_original_had_none() {
let original = "no_trailing_newline";
let merged = "modified_no_trailing_newline";
assert!(validate_morph_output(original, merged).is_ok());
}
}