huskies: merge 1100 bug Multiple LLM agents can run concurrently on the same story (coder + mergemaster + others) — enforce one-agent-per-story invariant
This commit is contained in:
@@ -271,6 +271,42 @@ impl AgentPool {
|
||||
'{conflicting_name}' is already active at the same pipeline stage"
|
||||
));
|
||||
}
|
||||
// Cross-stage LLM agent guard: reject if any Coder/Qa/Mergemaster agent
|
||||
// is already Running or Pending on this story at a *different* pipeline stage.
|
||||
// These are stale agents left over from a previous stage transition that has
|
||||
// since advanced. The periodic reconciler (reconcile_canonical_agents) stops
|
||||
// them; here we surface the conflict so the caller waits for reconciliation.
|
||||
if matches!(
|
||||
resolved_stage,
|
||||
PipelineStage::Coder | PipelineStage::Qa | PipelineStage::Mergemaster
|
||||
) && let Some(stale_name) = agents.iter().find_map(|(k, a)| {
|
||||
let k_story = k.rsplit_once(':').map(|(s, _)| s).unwrap_or(k);
|
||||
if k_story != story_id || a.agent_name == resolved_name {
|
||||
return None;
|
||||
}
|
||||
if !matches!(a.status, AgentStatus::Running | AgentStatus::Pending) {
|
||||
return None;
|
||||
}
|
||||
let a_stage = config
|
||||
.find_agent(&a.agent_name)
|
||||
.map(agent_config_stage)
|
||||
.unwrap_or_else(|| pipeline_stage(&a.agent_name));
|
||||
if matches!(
|
||||
a_stage,
|
||||
PipelineStage::Coder | PipelineStage::Qa | PipelineStage::Mergemaster
|
||||
) && a_stage != resolved_stage
|
||||
{
|
||||
Some(a.agent_name.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) {
|
||||
return Err(format!(
|
||||
"story '{story_id}' already has an active LLM agent '{stale_name}'; \
|
||||
refusing to spawn '{resolved_name}'"
|
||||
));
|
||||
}
|
||||
|
||||
// Enforce single-instance concurrency for explicitly-named agents:
|
||||
// if this agent is already running on any other story, reject.
|
||||
// Auto-selected agents are already guaranteed idle by
|
||||
|
||||
Reference in New Issue
Block a user