//! GyanDoot Kanban — Task decomposition, swarm execution, and diagnostics. //! //! The Kanban system manages tasks from decomposition into subtasks, //! parallel execution via a swarm of sub-agents, and diagnostics //! for tracking progress and bottlenecks. use gyandoot_core::{KanbanResult, Priority, Task, TaskStatus}; use uuid::Uuid; pub mod decompose; pub mod swarm; pub mod diagnostics; pub use decompose::Decomposer; pub use swarm::Swarm; pub use diagnostics::Diagnostics; /// The central Kanban board managing all tasks. pub struct KanbanBoard { tasks: Vec, decomposer: decompose::Decomposer, swarm: swarm::Swarm, diagnostics: diagnostics::Diagnostics, } impl KanbanBoard { /// Create a new empty Kanban board. pub fn new() -> Self { Self { tasks: Vec::new(), decomposer: decompose::Decomposer::new(), swarm: swarm::Swarm::new(), diagnostics: diagnostics::Diagnostics::new(), } } /// Add a task to the board. pub fn add_task(&mut self, title: String, description: String, priority: Priority) -> Task { let task = Task { id: Uuid::new_v4(), title, description, priority, status: TaskStatus::Backlog, assigned_agent: None, created_at: chrono::Utc::now(), updated_at: chrono::Utc::now(), subtasks: Vec::new(), dependencies: Vec::new(), tags: Vec::new(), }; self.tasks.push(task.clone()); task } /// Get a task by ID. pub fn get_task(&self, id: &Uuid) -> Option<&Task> { self.tasks.iter().find(|t| t.id == *id) } /// Update the status of a task. pub fn update_status(&mut self, id: &Uuid, status: TaskStatus) -> KanbanResult<()> { let task = self .tasks .iter_mut() .find(|t| t.id == *id) .ok_or_else(|| gyandoot_core::KanbanError::TaskNotFound(id.to_string()))?; task.status = status; task.updated_at = chrono::Utc::now(); Ok(()) } /// List all tasks with a given status. pub fn tasks_by_status(&self, status: TaskStatus) -> Vec<&Task> { self.tasks.iter().filter(|t| t.status == status).collect() } /// Get a reference to the decomposer. pub fn decomposer(&self) -> &decompose::Decomposer { &self.decomposer } /// Get a mutable reference to the decomposer. pub fn decomposer_mut(&mut self) -> &mut decompose::Decomposer { &mut self.decomposer } /// Get a reference to the swarm. pub fn swarm(&self) -> &swarm::Swarm { &self.swarm } /// Get a mutable reference to the swarm. pub fn swarm_mut(&mut self) -> &mut swarm::Swarm { &mut self.swarm } /// Get a reference to the diagnostics. pub fn diagnostics(&self) -> &diagnostics::Diagnostics { &self.diagnostics } } impl Default for KanbanBoard { fn default() -> Self { Self::new() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_board_lifecycle() { let mut board = KanbanBoard::new(); let task = board.add_task( "Write tests".to_string(), "Add unit tests for the agent loop".to_string(), Priority::High, ); assert_eq!(task.status, TaskStatus::Backlog); board.update_status(&task.id, TaskStatus::InProgress).unwrap(); assert_eq!(board.get_task(&task.id).unwrap().status, TaskStatus::InProgress); } }