Files
huskies/server/src/agents/pool/worktree.rs
T
2026-05-13 11:52:51 +00:00

101 lines
3.1 KiB
Rust

//! Agent worktree management — creates and configures git worktrees for agents.
use crate::config::ProjectConfig;
use std::path::{Path, PathBuf};
use super::AgentPool;
impl AgentPool {
/// Create a worktree for the given story using the server port (writes .mcp.json).
pub async fn create_worktree(
&self,
project_root: &Path,
story_id: &str,
) -> Result<crate::worktree::WorktreeInfo, String> {
let config = ProjectConfig::load(project_root)?;
crate::worktree::create_worktree(project_root, story_id, &config, self.port).await
}
/// Get project root helper.
pub fn get_project_root(&self, state: &crate::state::SessionState) -> Result<PathBuf, String> {
state.get_project_root()
}
}
/// Return the active pipeline stage for `story_id`, or `None` if the story is not
/// in any active stage (`2_current/`, `3_qa/`, `4_merge/`).
pub(super) fn find_active_story_stage(
_project_root: &Path,
story_id: &str,
) -> Option<crate::pipeline_state::Stage> {
if let Ok(Some(item)) = crate::pipeline_state::read_typed(story_id)
&& matches!(
item.stage,
crate::pipeline_state::Stage::Coding
| crate::pipeline_state::Stage::Qa
| crate::pipeline_state::Stage::Merge { .. }
)
{
return Some(item.stage);
}
None
}
#[cfg(test)]
mod tests {
use super::find_active_story_stage;
#[test]
fn find_active_story_stage_detects_current() {
crate::db::ensure_content_store();
crate::db::write_item_with_content(
"10_story_test",
"2_current",
"---\nname: Test\n---\n",
crate::db::ItemMeta::named("Test"),
);
let tmp = tempfile::tempdir().unwrap();
assert!(matches!(
find_active_story_stage(tmp.path(), "10_story_test"),
Some(crate::pipeline_state::Stage::Coding)
));
}
#[test]
fn find_active_story_stage_detects_qa() {
crate::db::ensure_content_store();
crate::db::write_item_with_content(
"11_story_test",
"3_qa",
"---\nname: Test\n---\n",
crate::db::ItemMeta::named("Test"),
);
let tmp = tempfile::tempdir().unwrap();
assert!(matches!(
find_active_story_stage(tmp.path(), "11_story_test"),
Some(crate::pipeline_state::Stage::Qa)
));
}
#[test]
fn find_active_story_stage_detects_merge() {
crate::db::ensure_content_store();
crate::db::write_item_with_content(
"12_story_test",
"4_merge",
"---\nname: Test\n---\n",
crate::db::ItemMeta::named("Test"),
);
let tmp = tempfile::tempdir().unwrap();
assert!(matches!(
find_active_story_stage(tmp.path(), "12_story_test"),
Some(crate::pipeline_state::Stage::Merge { .. })
));
}
#[test]
fn find_active_story_stage_returns_none_for_unknown_story() {
let tmp = tempfile::tempdir().unwrap();
assert_eq!(find_active_story_stage(tmp.path(), "99_nonexistent"), None);
}
}