fix: add --all to cargo fmt in script/test and autoformat codebase

cargo fmt without --all fails with "Failed to find targets" in
workspace repos. This was blocking every story's gates. Also ran
cargo fmt --all to fix all existing formatting issues.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dave
2026-04-13 14:07:08 +00:00
parent ed2526ce41
commit 845b85e7a7
128 changed files with 3566 additions and 2395 deletions
+100 -47
View File
@@ -1,18 +1,15 @@
//! Pipeline advance — moves stories forward through pipeline stages after agent completion.
use crate::config::ProjectConfig;
use crate::io::watcher::WatcherEvent;
use crate::slog;
use crate::slog_error;
use crate::slog_warn;
use crate::io::watcher::WatcherEvent;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use tokio::sync::broadcast;
use super::super::super::{
CompletionReport, PipelineStage,
agent_config_stage, pipeline_stage,
};
use super::super::super::{CompletionReport, PipelineStage, agent_config_stage, pipeline_stage};
use super::super::{AgentPool, StoryAgent};
impl AgentPool {
@@ -66,14 +63,16 @@ impl AgentPool {
"[pipeline] Coder '{agent_name}' passed gates for '{story_id}'. \
qa: server — moving directly to merge."
);
if let Err(e) =
crate::agents::lifecycle::move_story_to_merge(&project_root, story_id)
{
if let Err(e) = crate::agents::lifecycle::move_story_to_merge(
&project_root,
story_id,
) {
slog_error!(
"[pipeline] Failed to move '{story_id}' to 4_merge/: {e}"
);
} else {
self.start_mergemaster_or_block(&project_root, story_id).await;
self.start_mergemaster_or_block(&project_root, story_id)
.await;
}
}
crate::io::story_metadata::QaMode::Agent => {
@@ -81,13 +80,17 @@ impl AgentPool {
"[pipeline] Coder '{agent_name}' passed gates for '{story_id}'. \
qa: agent — moving to QA."
);
if let Err(e) = crate::agents::lifecycle::move_story_to_qa(&project_root, story_id) {
if let Err(e) =
crate::agents::lifecycle::move_story_to_qa(&project_root, story_id)
{
slog_error!("[pipeline] Failed to move '{story_id}' to 3_qa/: {e}");
} else if let Err(e) = self
.start_agent(&project_root, story_id, Some("qa"), None, None)
.await
{
slog_error!("[pipeline] Failed to start qa agent for '{story_id}': {e}");
slog_error!(
"[pipeline] Failed to start qa agent for '{story_id}': {e}"
);
}
}
crate::io::story_metadata::QaMode::Human => {
@@ -95,7 +98,9 @@ impl AgentPool {
"[pipeline] Coder '{agent_name}' passed gates for '{story_id}'. \
qa: human — holding for human review."
);
if let Err(e) = crate::agents::lifecycle::move_story_to_qa(&project_root, story_id) {
if let Err(e) =
crate::agents::lifecycle::move_story_to_qa(&project_root, story_id)
{
slog_error!("[pipeline] Failed to move '{story_id}' to 3_qa/: {e}");
} else {
write_review_hold_to_store(story_id);
@@ -104,7 +109,8 @@ impl AgentPool {
}
} else {
// Increment retry count and check if blocked.
if let Some(reason) = should_block_story(story_id, config.max_retries, "coder") {
if let Some(reason) = should_block_story(story_id, config.max_retries, "coder")
{
// Story has exceeded retry limit — do not restart.
let _ = self.watcher_tx.send(WatcherEvent::StoryBlocked {
story_id: story_id.to_string(),
@@ -144,13 +150,14 @@ impl AgentPool {
.clone()
.unwrap_or_else(|| project_root.clone());
let cp = coverage_path.clone();
let coverage_result =
tokio::task::spawn_blocking(move || crate::agents::gates::run_coverage_gate(&cp))
.await
.unwrap_or_else(|e| {
slog_warn!("[pipeline] Coverage gate task panicked: {e}");
Ok((false, format!("Coverage gate task panicked: {e}")))
});
let coverage_result = tokio::task::spawn_blocking(move || {
crate::agents::gates::run_coverage_gate(&cp)
})
.await
.unwrap_or_else(|e| {
slog_warn!("[pipeline] Coverage gate task panicked: {e}");
Ok((false, format!("Coverage gate task panicked: {e}")))
});
let (coverage_passed, coverage_output) = match coverage_result {
Ok(pair) => pair,
Err(e) => (false, e),
@@ -184,17 +191,21 @@ impl AgentPool {
"[pipeline] QA passed gates and coverage for '{story_id}'. \
Moving directly to merge."
);
if let Err(e) =
crate::agents::lifecycle::move_story_to_merge(&project_root, story_id)
{
if let Err(e) = crate::agents::lifecycle::move_story_to_merge(
&project_root,
story_id,
) {
slog_error!(
"[pipeline] Failed to move '{story_id}' to 4_merge/: {e}"
);
} else {
self.start_mergemaster_or_block(&project_root, story_id).await;
self.start_mergemaster_or_block(&project_root, story_id)
.await;
}
}
} else if let Some(reason) = should_block_story(story_id, config.max_retries, "qa-coverage") {
} else if let Some(reason) =
should_block_story(story_id, config.max_retries, "qa-coverage")
{
// Story has exceeded retry limit — do not restart.
let _ = self.watcher_tx.send(WatcherEvent::StoryBlocked {
story_id: story_id.to_string(),
@@ -217,7 +228,8 @@ impl AgentPool {
slog_error!("[pipeline] Failed to restart qa for '{story_id}': {e}");
}
}
} else if let Some(reason) = should_block_story(story_id, config.max_retries, "qa") {
} else if let Some(reason) = should_block_story(story_id, config.max_retries, "qa")
{
// Story has exceeded retry limit — do not restart.
let _ = self.watcher_tx.send(WatcherEvent::StoryBlocked {
story_id: story_id.to_string(),
@@ -272,13 +284,14 @@ impl AgentPool {
"[pipeline] Mergemaster completed for '{story_id}'. Running post-merge tests on master."
);
let root = project_root.clone();
let test_result =
tokio::task::spawn_blocking(move || crate::agents::gates::run_project_tests(&root))
.await
.unwrap_or_else(|e| {
slog_warn!("[pipeline] Post-merge test task panicked: {e}");
Ok((false, format!("Test task panicked: {e}")))
});
let test_result = tokio::task::spawn_blocking(move || {
crate::agents::gates::run_project_tests(&root)
})
.await
.unwrap_or_else(|e| {
slog_warn!("[pipeline] Post-merge test task panicked: {e}");
Ok((false, format!("Test task panicked: {e}")))
});
let (passed, output) = match test_result {
Ok(pair) => pair,
Err(e) => (false, e),
@@ -309,7 +322,9 @@ impl AgentPool {
slog!(
"[pipeline] Story '{story_id}' done. Worktree preserved for inspection."
);
} else if let Some(reason) = should_block_story(story_id, config.max_retries, "mergemaster") {
} else if let Some(reason) =
should_block_story(story_id, config.max_retries, "mergemaster")
{
// Story has exceeded retry limit — do not restart.
let _ = self.watcher_tx.send(WatcherEvent::StoryBlocked {
story_id: story_id.to_string(),
@@ -564,7 +579,10 @@ mod tests {
)
.unwrap();
crate::db::ensure_content_store();
crate::db::write_content("9909_story_agent_qa", "---\nname: Test\nqa: agent\n---\ntest");
crate::db::write_content(
"9909_story_agent_qa",
"---\nname: Test\nqa: agent\n---\ntest",
);
let pool = AgentPool::new_test(3001);
pool.run_pipeline_advance(
@@ -758,10 +776,26 @@ stage = "qa"
let root = tmp.path();
// Init a bare git repo on master with one empty commit.
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();
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 feature branch that points at master HEAD (zero commits ahead).
// This replicates the incident where the worktree was reset to master.
@@ -775,7 +809,11 @@ stage = "qa"
let current = root.join(".huskies/work/2_current");
fs::create_dir_all(&current).unwrap();
fs::create_dir_all(root.join(".huskies/work/4_merge")).unwrap();
fs::write(current.join("9919_story_no_commits.md"), "---\nname: Test\n---\n").unwrap();
fs::write(
current.join("9919_story_no_commits.md"),
"---\nname: Test\n---\n",
)
.unwrap();
crate::db::ensure_content_store();
crate::db::write_content("9919_story_no_commits", "---\nname: Test\n---\n");
@@ -835,8 +873,8 @@ stage = "qa"
#[tokio::test]
async fn pipeline_advance_picks_up_waiting_qa_stories_after_completion() {
use std::fs;
use super::super::super::auto_assign::is_agent_free;
use std::fs;
let tmp = tempfile::tempdir().unwrap();
let root = tmp.path();
@@ -908,8 +946,7 @@ stage = "qa"
// After pipeline advance, auto_assign should have started QA on story 293.
let agents = pool.agents.lock().unwrap();
let qa_on_293 = agents.values().any(|a| {
a.agent_name == "qa"
&& matches!(a.status, AgentStatus::Pending | AgentStatus::Running)
a.agent_name == "qa" && matches!(a.status, AgentStatus::Pending | AgentStatus::Running)
});
assert!(
qa_on_293,
@@ -940,10 +977,26 @@ stage = "qa"
let root = tmp.path();
// Init a git repo so post-merge tests would pass if they ran.
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();
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();
// Set up pipeline dirs.
fs::create_dir_all(root.join(".huskies/work/5_done")).unwrap();
+12 -5
View File
@@ -1,11 +1,13 @@
//! Agent completion handling — processes exit results and triggers pipeline advancement.
use crate::slog;
use crate::io::watcher::WatcherEvent;
use crate::slog;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use tokio::sync::broadcast;
use super::super::super::{AgentEvent, AgentStatus, CompletionReport, PipelineStage, pipeline_stage};
use super::super::super::{
AgentEvent, AgentStatus, CompletionReport, PipelineStage, pipeline_stage,
};
use super::super::{AgentPool, StoryAgent, composite_key};
use super::advance::spawn_pipeline_advance;
@@ -207,7 +209,10 @@ pub(in crate::agents::pool) async fn run_server_owned_completion(
// hold the build lock while gates try to run.
if let Some(wt_path) = worktree_path.as_ref()
&& let Ok(output) = std::process::Command::new("pgrep")
.args(["-f", &format!("--manifest-path {}/Cargo.toml", wt_path.display())])
.args([
"-f",
&format!("--manifest-path {}/Cargo.toml", wt_path.display()),
])
.output()
{
let pids = String::from_utf8_lossy(&output.stdout);
@@ -216,7 +221,9 @@ pub(in crate::agents::pool) async fn run_server_owned_completion(
crate::slog!(
"[agents] Killing stale cargo process (pid {pid}) for '{story_id}' before running gates"
);
unsafe { libc::kill(pid, libc::SIGKILL); }
unsafe {
libc::kill(pid, libc::SIGKILL);
}
}
}
}
@@ -311,8 +318,8 @@ pub(in crate::agents::pool) async fn run_server_owned_completion(
#[cfg(test)]
mod tests {
use super::*;
use super::super::super::AgentPool;
use super::*;
use crate::agents::{AgentEvent, AgentStatus, CompletionReport};
use std::path::PathBuf;
use std::process::Command;
+6 -5
View File
@@ -85,10 +85,11 @@ impl AgentPool {
let sid = story_id.to_string();
let br = branch.clone();
let merge_result =
tokio::task::spawn_blocking(move || crate::agents::merge::run_squash_merge(&root, &br, &sid))
.await
.map_err(|e| format!("Merge task panicked: {e}"))??;
let merge_result = tokio::task::spawn_blocking(move || {
crate::agents::merge::run_squash_merge(&root, &br, &sid)
})
.await
.map_err(|e| format!("Merge task panicked: {e}"))??;
if !merge_result.success {
return Ok(crate::agents::merge::MergeReport {
@@ -185,8 +186,8 @@ impl AgentPool {
#[cfg(test)]
mod tests {
use super::*;
use super::super::super::AgentPool;
use super::*;
use crate::agents::merge::{MergeJob, MergeJobStatus};
use std::process::Command;