bug-210: prevent pipeline from moving story to done when mergemaster reports failure
The pipeline advancement logic was ignoring report_merge_failure and blindly trusting the server-owned completion gates_passed result. Now report_merge_failure sets a flag on the agent entry that the pipeline checks before advancing — stories stay in 4_merge/ when merge fails. Squash merge of feature/story-210 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -899,7 +899,7 @@ async fn handle_tools_call(
|
||||
// Mergemaster tools
|
||||
"merge_agent_work" => tool_merge_agent_work(&args, ctx).await,
|
||||
"move_story_to_merge" => tool_move_story_to_merge(&args, ctx).await,
|
||||
"report_merge_failure" => tool_report_merge_failure(&args),
|
||||
"report_merge_failure" => tool_report_merge_failure(&args, ctx),
|
||||
// QA tools
|
||||
"request_qa" => tool_request_qa(&args, ctx).await,
|
||||
// Diagnostics
|
||||
@@ -1645,7 +1645,7 @@ async fn tool_move_story_to_merge(args: &Value, ctx: &AppContext) -> Result<Stri
|
||||
.map_err(|e| format!("Serialization error: {e}"))
|
||||
}
|
||||
|
||||
fn tool_report_merge_failure(args: &Value) -> Result<String, String> {
|
||||
fn tool_report_merge_failure(args: &Value, ctx: &AppContext) -> Result<String, String> {
|
||||
let story_id = args
|
||||
.get("story_id")
|
||||
.and_then(|v| v.as_str())
|
||||
@@ -1656,6 +1656,7 @@ fn tool_report_merge_failure(args: &Value) -> Result<String, String> {
|
||||
.ok_or("Missing required argument: reason")?;
|
||||
|
||||
slog!("[mergemaster] Merge failure reported for '{story_id}': {reason}");
|
||||
ctx.agents.set_merge_failure_reported(story_id);
|
||||
|
||||
Ok(format!(
|
||||
"Merge failure for '{story_id}' recorded. Story remains in work/4_merge/. Reason: {reason}"
|
||||
@@ -2638,24 +2639,33 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn tool_report_merge_failure_missing_story_id() {
|
||||
let result = tool_report_merge_failure(&json!({"reason": "conflicts"}));
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let ctx = test_ctx(tmp.path());
|
||||
let result = tool_report_merge_failure(&json!({"reason": "conflicts"}), &ctx);
|
||||
assert!(result.is_err());
|
||||
assert!(result.unwrap_err().contains("story_id"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tool_report_merge_failure_missing_reason() {
|
||||
let result = tool_report_merge_failure(&json!({"story_id": "42_story_foo"}));
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let ctx = test_ctx(tmp.path());
|
||||
let result = tool_report_merge_failure(&json!({"story_id": "42_story_foo"}), &ctx);
|
||||
assert!(result.is_err());
|
||||
assert!(result.unwrap_err().contains("reason"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tool_report_merge_failure_returns_confirmation() {
|
||||
let result = tool_report_merge_failure(&json!({
|
||||
"story_id": "42_story_foo",
|
||||
"reason": "Unresolvable merge conflicts in src/main.rs"
|
||||
}));
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let ctx = test_ctx(tmp.path());
|
||||
let result = tool_report_merge_failure(
|
||||
&json!({
|
||||
"story_id": "42_story_foo",
|
||||
"reason": "Unresolvable merge conflicts in src/main.rs"
|
||||
}),
|
||||
&ctx,
|
||||
);
|
||||
assert!(result.is_ok());
|
||||
let msg = result.unwrap();
|
||||
assert!(msg.contains("42_story_foo"));
|
||||
|
||||
Reference in New Issue
Block a user