//! 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 { 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 { 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 { if let Ok(Some(item)) = crate::pipeline_state::read_typed(story_id) && item.stage.is_active() { 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"); 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"); 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"); 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); } }