diff --git a/server/src/agents/pool/pipeline/merge/runner.rs b/server/src/agents/pool/pipeline/merge/runner.rs index f04026a2..a950cb68 100644 --- a/server/src/agents/pool/pipeline/merge/runner.rs +++ b/server/src/agents/pool/pipeline/merge/runner.rs @@ -186,6 +186,50 @@ impl AgentPool { .map(|k| k.is_self_evident_fix()) .unwrap_or(false); + // Bug 1101 diagnostic: log the classified failure_kind and the + // matched classifier-trigger substring with surrounding context, + // so we can confirm whether classify() is incorrectly matching + // a passing-step stdout substring (e.g. "Diff in " inside a + // failing test's panic message) and bouncing the story to a + // fixup coder. Remove once the fix lands. + if let Ok(r) = report.as_ref() + && let crate::agents::merge::MergeResult::GateFailure { + output: gate_output, + failure_kind: Some(k), + } = &r.result + { + const TRIGGERS: &[&str] = &[ + "CONFLICT (content):", + "Merge conflict:", + "Diff in ", + "would reformat", + "missing-docs direction", + "error[clippy::", + "warning[clippy::", + "missing_doc_comments", + "error[E", + ]; + let matched = TRIGGERS + .iter() + .find_map(|t| gate_output.find(t).map(|i| (*t, i))); + let (trigger, context) = match matched { + Some((t, i)) => { + let start = i.saturating_sub(30); + let end = (i + t.len() + 60).min(gate_output.len()); + let ctx = gate_output + .get(start..end) + .unwrap_or("") + .replace('\n', " "); + (Some(t), ctx) + } + None => (None, String::from("")), + }; + slog!( + "[merge] classify diagnostic for '{sid}': failure_kind={k:?} \ + is_fixup={is_fixup} trigger={trigger:?} context='{context}'" + ); + } + if is_no_commits { let reason = kind.display_reason(); if let Err(e) = crate::agents::lifecycle::transition_to_blocked(&sid, &reason) {