fix: post-squash compile errors reclassify as semantic merge conflicts
When deterministic-merge produces a clean git squash but the post-squash compile fails (typical when master gained a Stage payload field after the feature branch forked — e.g. story 1018 hit `error[E0063]: missing field plan` after 1010's PlanState landed), the failure is morally a merge conflict that git's diff3 missed: the conflicting literal lives in a different file from the type definition that changed on master. Routing it as GatesFailed left mergemaster idle and the story stuck. Changes: - gates.rs GateFailureKind::classify: detect rustc compile errors (`error[E\d+]`) as Build instead of falling through to Test. Clippy errors (`error[clippy::...]`) still classify as Lint. - agents/merge/mod.rs: new MergeResult::to_merge_failure_kind() method. GateFailure with failure_kind=Build maps to ConflictDetected (so the existing 998 subscriber auto-spawns mergemaster). Other gate failures stay GatesFailed. - agents/pool/pipeline/merge/runner.rs: replace the inline match with a call to the new method. Tests: 6 new unit tests covering the classifier branch and every to_merge_failure_kind arm. All 2932 tests pass.
This commit is contained in:
@@ -44,6 +44,13 @@ impl GateFailureKind {
|
||||
|| output.contains("missing_doc_comments")
|
||||
{
|
||||
GateFailureKind::Lint
|
||||
} else if output.contains("error[E") {
|
||||
// rustc compile errors (e.g. `error[E0063]: missing field`).
|
||||
// When this appears in the post-squash gate run, it almost always
|
||||
// signals cross-merge breakage — master gained a field/variant the
|
||||
// feature branch's code does not match. Mergemaster handles the
|
||||
// recovery in its ConflictDetected path.
|
||||
GateFailureKind::Build
|
||||
} else {
|
||||
GateFailureKind::Test
|
||||
}
|
||||
@@ -880,6 +887,29 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn classify_build_from_rustc_compile_error() {
|
||||
// Post-squash compile errors (typical when master drifts under a feature
|
||||
// branch — e.g. story 1018 hit `error[E0063]: missing field` after
|
||||
// master gained a Stage::Coding field the feature branch did not set).
|
||||
assert_eq!(
|
||||
GateFailureKind::classify(
|
||||
"error[E0063]: missing field `plan` in initializer of `Stage`\n --> server/src/foo.rs:166:20"
|
||||
),
|
||||
GateFailureKind::Build
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn classify_build_does_not_misfire_on_clippy_error() {
|
||||
// Clippy errors look like `error[clippy::name]` and must remain Lint,
|
||||
// not Build, because the `error[E` prefix would otherwise overlap.
|
||||
assert_eq!(
|
||||
GateFailureKind::classify("error[clippy::unused_variable]: unused variable `x`"),
|
||||
GateFailureKind::Lint
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn classify_test_failure_for_unrecognised_output() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user