1pub mod diagnostic;
2pub mod similarity;
3
4pub use diagnostic::Diagnostic;
5
6pub fn try_map_error(err: &anyhow::Error) -> Option<Diagnostic> {
8 if let Some(diag) = err.downcast_ref::<Diagnostic>() {
10 return Some(diag.clone());
11 }
12
13 let msg = err.to_string();
14
15 if msg.contains("embedding dims mismatch") || msg.contains("dimension mismatch") {
19 return Some(
22 Diagnostic::new(
23 diagnostic::codes::E_EMB_DIMS,
24 "Embedding dimensions mismatch",
25 )
26 .with_context(serde_json::json!({ "raw_error": msg }))
27 .with_fix_step("Run: assay trace precompute-embeddings --trace <file> ...")
28 .with_fix_step(
29 "Ensure the same embedding model is used for baseline and candidate runs",
30 ),
31 );
32 }
33
34 if msg.contains("Baseline mismatch") || (msg.contains("baseline") && msg.contains("schema")) {
36 return Some(
37 Diagnostic::new(
38 diagnostic::codes::E_BASE_MISMATCH,
39 "Baseline incompatbile with current run",
40 )
41 .with_context(serde_json::json!({ "raw_error": msg }))
42 .with_fix_step("Regenerate baseline on main branch: assay ci --export-baseline ...")
43 .with_fix_step("Check that your config suite name matches the baseline suite"),
44 );
45 }
46
47 None
48}
49
50use std::fmt::{Display, Formatter};
51
52#[derive(Debug)]
53pub struct ConfigError(pub String);
54
55impl Display for ConfigError {
56 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
57 write!(f, "ConfigError: {}", self.0)
58 }
59}
60impl std::error::Error for ConfigError {}