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 directory name 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<&'static str> { const STAGES: [&str; 3] = ["2_current", "3_qa", "4_merge"]; // Try CRDT first — primary source of truth. if let Some(item) = crate::crdt_state::read_item(story_id) { for stage in &STAGES { if item.stage == *stage { return Some(stage); } } } // Also check filesystem (backwards compat / tests). for stage in &STAGES { let path = project_root .join(".huskies") .join("work") .join(stage) .join(format!("{story_id}.md")); if path.exists() { return Some(stage); } } None } #[cfg(test)] mod tests { use super::find_active_story_stage; #[test] fn find_active_story_stage_detects_current() { use std::fs; let tmp = tempfile::tempdir().unwrap(); let root = tmp.path(); let current = root.join(".huskies/work/2_current"); fs::create_dir_all(¤t).unwrap(); fs::write(current.join("10_story_test.md"), "test").unwrap(); assert_eq!( find_active_story_stage(root, "10_story_test"), Some("2_current") ); } #[test] fn find_active_story_stage_detects_qa() { use std::fs; let tmp = tempfile::tempdir().unwrap(); let root = tmp.path(); let qa = root.join(".huskies/work/3_qa"); fs::create_dir_all(&qa).unwrap(); fs::write(qa.join("11_story_test.md"), "test").unwrap(); assert_eq!(find_active_story_stage(root, "11_story_test"), Some("3_qa")); } #[test] fn find_active_story_stage_detects_merge() { use std::fs; let tmp = tempfile::tempdir().unwrap(); let root = tmp.path(); let merge = root.join(".huskies/work/4_merge"); fs::create_dir_all(&merge).unwrap(); fs::write(merge.join("12_story_test.md"), "test").unwrap(); assert_eq!( find_active_story_stage(root, "12_story_test"), Some("4_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); } }