pub const AC_SHIP1_008_CANONICAL_SYSTEM: &str = "You are a helpful coding assistant.";
pub const AC_SHIP1_008_CANONICAL_USER: &str = "Write a Python function to compute the nth Fibonacci number.";
pub const AC_SHIP1_008_CANONICAL_GOLDEN: &str = "\
<|im_start|>system
You are a helpful coding assistant.<|im_end|>
<|im_start|>user
Write a Python function to compute the nth Fibonacci number.<|im_end|>
<|im_start|>assistant
";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Ship008Verdict {
Pass,
Fail,
}
#[must_use]
pub const fn verdict_from_chat_template_render(
rendered: &str,
golden: &str,
) -> Ship008Verdict {
let a = rendered.as_bytes();
let b = golden.as_bytes();
if a.len() != b.len() {
return Ship008Verdict::Fail;
}
let mut i = 0;
while i < a.len() {
if a[i] != b[i] {
return Ship008Verdict::Fail;
}
i += 1;
}
Ship008Verdict::Pass
}
#[cfg(test)]
mod ship_008_tests {
use super::*;
#[test]
fn falsify_ship_008_chat_template_render_bind() {
assert_eq!(
verdict_from_chat_template_render(
AC_SHIP1_008_CANONICAL_GOLDEN,
AC_SHIP1_008_CANONICAL_GOLDEN,
),
Ship008Verdict::Pass,
"byte-identical strings must yield Pass",
);
let engine = super::ChatMLTemplate::new();
let messages = vec![
super::ChatMessage::new("system", AC_SHIP1_008_CANONICAL_SYSTEM),
super::ChatMessage::new("user", AC_SHIP1_008_CANONICAL_USER),
];
let rendered = engine
.format_conversation(&messages)
.expect("canonical messages render without error");
assert_eq!(
verdict_from_chat_template_render(&rendered, AC_SHIP1_008_CANONICAL_GOLDEN),
Ship008Verdict::Pass,
"ChatML engine must produce byte-exact golden for canonical \
(system, user) input — divergence means template drift",
);
assert_eq!(
verdict_from_chat_template_render("", AC_SHIP1_008_CANONICAL_GOLDEN),
Ship008Verdict::Fail,
"empty render against non-empty golden must Fail",
);
let without_gen_prompt = "\
<|im_start|>system
You are a helpful coding assistant.<|im_end|>
<|im_start|>user
Write a Python function to compute the nth Fibonacci number.<|im_end|>
";
assert_eq!(
verdict_from_chat_template_render(
without_gen_prompt,
AC_SHIP1_008_CANONICAL_GOLDEN,
),
Ship008Verdict::Fail,
"render missing the assistant generation prompt must Fail \
— this is the class of bug that produced blank output \
in realizar during the Qwen2 migration (GH-PMAT-593)",
);
let wrong_delim = "\
<|user|>system
You are a helpful coding assistant.<|im_end|>
<|user|>user
Write a Python function to compute the nth Fibonacci number.<|im_end|>
<|user|>assistant
";
assert_eq!(
verdict_from_chat_template_render(wrong_delim, AC_SHIP1_008_CANONICAL_GOLDEN),
Ship008Verdict::Fail,
"wrong special-token delimiter must Fail — this is the \
cross-family drift class (ChatML → Llama2 mix)",
);
let swapped_roles = "\
<|im_start|>user
Write a Python function to compute the nth Fibonacci number.<|im_end|>
<|im_start|>system
You are a helpful coding assistant.<|im_end|>
<|im_start|>assistant
";
assert_eq!(
verdict_from_chat_template_render(swapped_roles, AC_SHIP1_008_CANONICAL_GOLDEN),
Ship008Verdict::Fail,
"role-order swap must Fail — engine must preserve message \
ordering for prompt-format stability",
);
let single_byte_flipped = {
let mut bytes = AC_SHIP1_008_CANONICAL_GOLDEN.as_bytes().to_vec();
*bytes.last_mut().expect("golden is non-empty") = b' ';
String::from_utf8(bytes).expect("ASCII flip stays valid UTF-8")
};
assert_eq!(
verdict_from_chat_template_render(
&single_byte_flipped,
AC_SHIP1_008_CANONICAL_GOLDEN,
),
Ship008Verdict::Fail,
"single trailing-byte flip (\\n → space) must Fail — \
byte-equality, not approx-equality",
);
assert_eq!(
verdict_from_chat_template_render(
AC_SHIP1_008_CANONICAL_GOLDEN,
"",
),
Ship008Verdict::Fail,
"non-empty vs empty must Fail regardless of argument order",
);
assert_eq!(
verdict_from_chat_template_render("", ""),
Ship008Verdict::Pass,
"empty == empty is vacuously Pass — the rule is byte-equality, \
not a minimum-length gate",
);
assert!(
AC_SHIP1_008_CANONICAL_GOLDEN.contains("<|im_start|>"),
"golden must contain ChatML im_start delimiter — drift \
from qwen2.yaml chat_template field",
);
assert!(
AC_SHIP1_008_CANONICAL_GOLDEN.contains("<|im_end|>"),
"golden must contain ChatML im_end delimiter",
);
assert!(
AC_SHIP1_008_CANONICAL_GOLDEN.ends_with("<|im_start|>assistant\n"),
"golden must end with the assistant generation prompt — \
this is what realizar feeds the sampler",
);
assert_eq!(
AC_SHIP1_008_CANONICAL_GOLDEN.matches("<|im_start|>").count(),
3,
"golden must have exactly 3 im_start occurrences \
(system + user + assistant) for the canonical 2-message input",
);
assert_eq!(
AC_SHIP1_008_CANONICAL_GOLDEN.matches("<|im_end|>").count(),
2,
"golden must have exactly 2 im_end occurrences (system + user); \
assistant is unterminated because generation has not yet run",
);
}
}