huskies: merge 982

This commit is contained in:
dave
2026-05-13 15:34:41 +00:00
parent e6d051d016
commit 91fbad568a
15 changed files with 357 additions and 117 deletions
@@ -901,4 +901,72 @@ mod tests {
through the watcher bridge (story 958 regression)"
);
}
/// AC5 (story 982): a merge failure with content conflicts — seeded via the
/// typed `transition_to_merge_failure(ConflictDetected)` path without any
/// direct content-store or MergeJob writes in the test — produces
/// `Stage::MergeFailure { kind: ConflictDetected(_), .. }` and
/// auto-spawn-mergemaster fires within one `auto_assign_available_work` call.
#[tokio::test]
async fn auto_spawn_mergemaster_for_conflict_detected_kind_without_content_store_writes() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".huskies");
std::fs::create_dir_all(&sk).unwrap();
std::fs::write(
sk.join("project.toml"),
"[[agent]]\nname = \"mergemaster\"\nstage = \"mergemaster\"\n",
)
.unwrap();
crate::crdt_state::init_for_test();
crate::db::ensure_content_store();
let story_id = "982_ac5_conflict_auto_spawn";
// Seed at Merge stage so the transition is valid.
crate::db::write_item_with_content(
story_id,
"4_merge",
"---\nname: AC5 auto-spawn test\n---\n",
crate::db::ItemMeta::named("AC5 auto-spawn test"),
);
// Transition to MergeFailure(ConflictDetected) via lifecycle — no direct
// content-store writes in this test body.
crate::agents::lifecycle::transition_to_merge_failure(
story_id,
crate::pipeline_state::MergeFailureKind::ConflictDetected(Some(
"CONFLICT (content): server/src/lib.rs".to_string(),
)),
)
.expect("transition to MergeFailure(ConflictDetected) should succeed");
// Verify the stage kind before triggering auto-assign.
let item = crate::pipeline_state::read_typed(story_id)
.unwrap()
.unwrap();
assert!(
matches!(
item.stage,
crate::pipeline_state::Stage::MergeFailure {
kind: crate::pipeline_state::MergeFailureKind::ConflictDetected(_),
..
}
),
"stage must be MergeFailure(ConflictDetected) before auto-assign: {:?}",
item.stage
);
// One auto-assign cycle should spawn mergemaster.
let pool = AgentPool::new_test(3001);
pool.auto_assign_available_work(tmp.path()).await;
let agents = pool.agents.lock().unwrap();
let mergemaster_spawned = agents.iter().any(|(key, a)| {
key.contains(story_id)
&& a.agent_name == "mergemaster"
&& matches!(a.status, AgentStatus::Pending | AgentStatus::Running)
});
assert!(
mergemaster_spawned,
"mergemaster must be auto-spawned for ConflictDetected kind in one auto-assign cycle"
);
}
}