huskies: merge 954

This commit is contained in:
dave
2026-05-13 09:30:44 +00:00
parent c228ae1640
commit 765d54fc4b
8 changed files with 290 additions and 9 deletions
@@ -95,10 +95,13 @@ pub(in crate::agents::pool) async fn run_server_owned_completion(
}
}
// Run acceptance gates.
let (gates_passed, gate_output) = if let Some(wt_path) = worktree_path {
// Run acceptance gates. Third element of the tuple is `needs_commit_recovery`:
// true when the coder exited with uncommitted content but zero commits — the
// pipeline advance will issue a commit-only recovery respawn rather than a
// normal retry, and will NOT consume a `retry_count` slot.
let (gates_passed, gate_output, needs_commit_recovery) = if let Some(wt_path) = worktree_path {
let path = wt_path;
match tokio::task::spawn_blocking(move || {
match tokio::task::spawn_blocking(move || -> Result<(bool, String, bool), String> {
// If the worktree is dirty, check whether committed work survived.
// An agent crash (e.g. Claude Code CLI's `output.write(&bytes).is_ok()`
// assertion — bug 645) can leave uncommitted files behind even though
@@ -133,7 +136,10 @@ pub(in crate::agents::pool) async fn run_server_owned_completion(
})
.unwrap_or(false)
} else {
return Ok((false, dirty_msg));
// Dirty worktree AND no committed work: the coder exited
// without committing. Signal a commit-only recovery respawn
// rather than consuming a normal retry slot.
return Ok((false, dirty_msg, true));
}
} else {
false
@@ -152,9 +158,10 @@ pub(in crate::agents::pool) async fn run_server_owned_completion(
"Agent exited with no commits on the feature branch. \
The agent did not produce any code changes."
.to_string(),
false,
));
}
let result = crate::agents::gates::run_acceptance_gates(&path);
let (passed, output) = crate::agents::gates::run_acceptance_gates(&path)?;
// Restore stashed uncommitted changes.
if stashed {
let _ = std::process::Command::new("git")
@@ -162,18 +169,19 @@ pub(in crate::agents::pool) async fn run_server_owned_completion(
.current_dir(&path)
.output();
}
result
Ok((passed, output, false))
})
.await
{
Ok(Ok(result)) => result,
Ok(Err(e)) => (false, e),
Err(e) => (false, format!("Gate check task panicked: {e}")),
Ok(Err(e)) => (false, e, false),
Err(e) => (false, format!("Gate check task panicked: {e}"), false),
}
} else {
(
false,
"No worktree path available to run acceptance gates".to_string(),
false,
)
};
@@ -192,6 +200,7 @@ pub(in crate::agents::pool) async fn run_server_owned_completion(
summary: "Agent process exited normally".to_string(),
gates_passed,
gate_output,
needs_commit_recovery,
};
// Store completion report, extract data for pipeline advance, then