huskies: merge 954
This commit is contained in:
@@ -74,7 +74,58 @@ impl AgentPool {
|
||||
// Supervisors and unknown agents do not advance the pipeline.
|
||||
}
|
||||
PipelineStage::Coder => {
|
||||
if completion.gates_passed {
|
||||
if completion.needs_commit_recovery {
|
||||
// The coder exited with uncommitted content but no commits.
|
||||
// Check if this is already a second recovery attempt (the
|
||||
// first recovery respawn also produced no commits).
|
||||
let recovery_key = format!("{story_id}:commit_recovery_pending");
|
||||
if crate::db::read_content(&recovery_key).is_some() {
|
||||
// Second attempt still produced no commits → block.
|
||||
crate::db::delete_content(&recovery_key);
|
||||
slog!(
|
||||
"[pipeline] Coder '{agent_name}' (commit-recovery respawn) \
|
||||
still produced no commits for '{story_id}'. Blocking story."
|
||||
);
|
||||
let reason = "agent declined to commit recoverable work".to_string();
|
||||
if let Err(e) =
|
||||
crate::agents::lifecycle::transition_to_blocked(story_id, &reason)
|
||||
{
|
||||
slog_error!("[pipeline] Failed to block '{story_id}': {e}");
|
||||
}
|
||||
let _ = self.watcher_tx.send(WatcherEvent::StoryBlocked {
|
||||
story_id: story_id.to_string(),
|
||||
reason,
|
||||
});
|
||||
} else {
|
||||
// First occurrence: issue a commit-only recovery respawn.
|
||||
// This does NOT consume a retry_count slot.
|
||||
crate::db::write_content(&recovery_key, "1");
|
||||
slog!(
|
||||
"[pipeline] Coder '{agent_name}' exited with uncommitted work \
|
||||
for '{story_id}'. Issuing commit-only recovery respawn."
|
||||
);
|
||||
let addendum = "\n\nYou have uncommitted work in this worktree. \
|
||||
Your only task this session is run_tests → git_add → git_commit. \
|
||||
Do not explore further.";
|
||||
if let Err(e) = self
|
||||
.start_agent(
|
||||
&project_root,
|
||||
story_id,
|
||||
Some(agent_name),
|
||||
Some(addendum),
|
||||
previous_session_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
slog_error!(
|
||||
"[pipeline] Failed to start commit-recovery respawn \
|
||||
for '{story_id}': {e}"
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if completion.gates_passed {
|
||||
// Clear any stale recovery key when the coder succeeds normally.
|
||||
crate::db::delete_content(&format!("{story_id}:commit_recovery_pending"));
|
||||
// Determine effective QA mode for this story.
|
||||
let qa_mode = {
|
||||
let item_type = crate::agents::lifecycle::item_type_from_id(story_id);
|
||||
@@ -130,6 +181,9 @@ impl AgentPool {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Clear any stale recovery key when gates fail normally (agent committed
|
||||
// but the build is broken — treat as a standard retry, not a recovery).
|
||||
crate::db::delete_content(&format!("{story_id}:commit_recovery_pending"));
|
||||
// Bug 645 / 668: Before retry/block, check if the agent left committed
|
||||
// work AND the agent had a passing run_tests result captured during its
|
||||
// session. An agent may crash mid-output (e.g. Claude Code CLI PTY write
|
||||
|
||||
Reference in New Issue
Block a user