huskies: merge 953
This commit is contained in:
@@ -872,3 +872,134 @@ stage = "coder"
|
||||
item.retry_count()
|
||||
);
|
||||
}
|
||||
|
||||
// ── bug 953: bug-645 path must not advance when feature branch has zero commits ──
|
||||
|
||||
/// Regression test for bug 953: when a coder agent exits with gates_passed=false
|
||||
/// but has captured passing test evidence AND the feature branch has ZERO commits
|
||||
/// ahead of master, the bug-645 salvage path must NOT advance the story to
|
||||
/// QA or Merge. Zero commits = no actual work was done; treat as no-progress.
|
||||
#[tokio::test]
|
||||
async fn coder_completion_with_test_evidence_and_zero_commits_does_not_advance() {
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let root = tmp.path();
|
||||
|
||||
// Init a git repo with an initial commit on master.
|
||||
Command::new("git")
|
||||
.args(["init"])
|
||||
.current_dir(root)
|
||||
.output()
|
||||
.unwrap();
|
||||
Command::new("git")
|
||||
.args(["config", "user.email", "test@test.com"])
|
||||
.current_dir(root)
|
||||
.output()
|
||||
.unwrap();
|
||||
Command::new("git")
|
||||
.args(["config", "user.name", "Test"])
|
||||
.current_dir(root)
|
||||
.output()
|
||||
.unwrap();
|
||||
Command::new("git")
|
||||
.args(["commit", "--allow-empty", "-m", "init"])
|
||||
.current_dir(root)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
// Create a worktree on a feature branch that has ZERO commits ahead of master.
|
||||
let wt_path = tmp.path().join("wt");
|
||||
Command::new("git")
|
||||
.args([
|
||||
"worktree",
|
||||
"add",
|
||||
&wt_path.to_string_lossy(),
|
||||
"-b",
|
||||
"feature/story-9953_story_zero_commits",
|
||||
])
|
||||
.current_dir(root)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
// Seed the story in CRDT.
|
||||
crate::crdt_state::init_for_test();
|
||||
crate::db::ensure_content_store();
|
||||
crate::db::write_item_with_content(
|
||||
"9953_story_zero_commits",
|
||||
"2_current",
|
||||
"---\nname: Zero Commits Test\n---\n",
|
||||
crate::db::ItemMeta::named("Zero Commits Test"),
|
||||
);
|
||||
|
||||
// Simulate the agent having called run_tests with a passing result (bug-645
|
||||
// evidence) — but the feature branch still has zero commits ahead of master.
|
||||
crate::db::write_content("9953_story_zero_commits:run_tests_ok", "1");
|
||||
|
||||
// Write a project.toml with max_retries=1 so the story blocks immediately,
|
||||
// giving us a clean assertion target (StoryBlocked event).
|
||||
fs::create_dir_all(root.join(".huskies")).unwrap();
|
||||
fs::write(
|
||||
root.join(".huskies/project.toml"),
|
||||
"max_retries = 1\n\n[[agent]]\nname = \"coder-1\"\nstage = \"coder\"\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let pool = AgentPool::new_test(3001);
|
||||
let mut rx = pool.watcher_tx.subscribe();
|
||||
|
||||
// Simulate coder completing with gates_passed=false (e.g. agent crashed).
|
||||
pool.run_pipeline_advance(
|
||||
"9953_story_zero_commits",
|
||||
"coder-1",
|
||||
crate::agents::CompletionReport {
|
||||
summary: "Agent crashed mid-output".to_string(),
|
||||
gates_passed: false,
|
||||
gate_output: "PTY write assertion failed".to_string(),
|
||||
},
|
||||
Some(root.to_path_buf()),
|
||||
Some(wt_path),
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
// The story must NOT have advanced to QA or Merge — it should be blocked
|
||||
// (zero commits = no progress, so the bug-645 salvage path must not fire).
|
||||
let mut got_blocked = false;
|
||||
while let Ok(evt) = rx.try_recv() {
|
||||
if let WatcherEvent::StoryBlocked { story_id, .. } = &evt
|
||||
&& story_id == "9953_story_zero_commits"
|
||||
{
|
||||
got_blocked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
got_blocked,
|
||||
"Story with zero commits ahead of master must be blocked even when \
|
||||
test evidence exists — the bug-645 salvage path must require commits_ahead > 0"
|
||||
);
|
||||
|
||||
// No QA or merge agent should have been started.
|
||||
let agents = pool.agents.lock().unwrap();
|
||||
let qa_or_merge_started = agents
|
||||
.values()
|
||||
.any(|a| a.agent_name.contains("qa") || a.agent_name.contains("merge"));
|
||||
assert!(
|
||||
!qa_or_merge_started,
|
||||
"No QA or merge agent must be started when feature branch has zero commits. \
|
||||
Pool: {:?}",
|
||||
agents
|
||||
.iter()
|
||||
.map(|(k, a)| format!("{k}: {}", a.agent_name))
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
// Test evidence must have been consumed (cleared) by the advance handler.
|
||||
assert!(
|
||||
crate::db::read_content("9953_story_zero_commits:run_tests_ok").is_none(),
|
||||
"run_tests evidence must be cleared after pipeline advance consumes it"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user