scud/
lib.rs

1//! # SCUD - Fast, DAG-driven Task Manager
2//!
3//! SCUD (Simple, Concurrent, Unified, Directed) is a task management system designed
4//! for AI-driven development workflows. It provides both a CLI tool and a library
5//! for managing tasks organized in directed acyclic graphs (DAGs).
6//!
7//! ## Features
8//!
9//! - **DAG-based execution**: Tasks have dependencies that form a directed acyclic graph,
10//!   ensuring work proceeds in the correct order
11//! - **Multi-phase support**: Organize tasks into phases (tags) for different project areas
12//! - **File locking**: Safe concurrent access with atomic read/write operations
13//! - **SCG format**: Token-efficient text format for task storage
14//! - **AI integration**: Parse PRDs and expand complex tasks using LLM providers
15//!
16//! ## Library Usage
17//!
18//! SCUD can be used as a library to programmatically manage tasks:
19//!
20//! ```no_run
21//! use scud::storage::Storage;
22//! use scud::models::{Phase, Task, TaskStatus};
23//!
24//! // Initialize storage (uses current directory by default)
25//! let storage = Storage::new(None);
26//!
27//! // Load all phases (task groups by tag)
28//! let phases = storage.load_tasks().expect("Failed to load tasks");
29//!
30//! // Load a specific phase by tag
31//! let auth_phase = storage.load_group("auth").expect("Phase not found");
32//!
33//! // Find the next available task (dependencies met, status pending)
34//! if let Some(next_task) = auth_phase.find_next_task() {
35//!     println!("Next task: {} - {}", next_task.id, next_task.title);
36//! }
37//!
38//! // Get phase statistics
39//! let stats = auth_phase.get_stats();
40//! println!("Progress: {}/{} done", stats.done, stats.total);
41//! ```
42//!
43//! ## Storage Format
44//!
45//! Tasks are stored in `.scud/tasks/tasks.scg` using the SCG (SCUD Graph) format.
46//! Multiple phases are separated by `---` delimiters:
47//!
48//! ```text
49//! @phase auth
50//!
51//! [1] Implement login endpoint
52//! status: pending
53//! complexity: 5
54//! deps: 2, 3
55//!
56//! ---
57//!
58//! @phase api
59//!
60//! [1] Create REST framework
61//! status: done
62//! ```
63//!
64//! ## CLI Usage
65//!
66//! The `scud` binary provides commands for task management:
67//!
68//! - `scud init` - Initialize a new SCUD project
69//! - `scud list` - List tasks in the active phase
70//! - `scud next` - Find and optionally claim the next available task
71//! - `scud show <id>` - Display task details
72//! - `scud set-status <id> <status>` - Update task status
73//! - `scud waves` - Show tasks organized by execution waves
74//! - `scud stats` - Display completion statistics
75//!
76//! ## Task Generation Pipeline
77//!
78//! SCUD provides a multi-phase pipeline for generating tasks from PRD documents.
79//! This can be invoked via the CLI (`scud generate`) or programmatically:
80//!
81//! ```no_run
82//! use scud::commands::generate::{generate, GenerateOptions};
83//! use std::path::PathBuf;
84//!
85//! #[tokio::main]
86//! async fn main() -> anyhow::Result<()> {
87//!     // Create options with required fields
88//!     let mut options = GenerateOptions::new(
89//!         PathBuf::from("docs/prd.md"),
90//!         "my-feature".to_string(),
91//!     );
92//!
93//!     // Customize the pipeline
94//!     options.num_tasks = 15;        // Generate up to 15 tasks
95//!     options.verbose = true;        // Show detailed output
96//!     options.no_expand = false;     // Run expansion phase
97//!     options.no_check_deps = false; // Run dependency validation
98//!
99//!     // Run the pipeline: parse → expand → check-deps
100//!     generate(options).await?;
101//!     Ok(())
102//! }
103//! ```
104//!
105//! The pipeline consists of three phases:
106//!
107//! 1. **Parse**: Convert a PRD document into initial tasks using AI
108//! 2. **Expand**: Break down complex tasks into subtasks
109//! 3. **Check Dependencies**: Validate and fix task dependencies
110//!
111//! Each phase can be skipped using `no_expand` and `no_check_deps` options.
112
113/// Agent definitions for model routing.
114///
115/// Allows tasks to specify which AI harness and model should run them.
116/// Agent definitions are loaded from `.scud/agents/<name>.toml` files.
117///
118/// # Example
119///
120/// ```toml
121/// # .scud/agents/reviewer.toml
122/// [agent]
123/// name = "reviewer"
124/// description = "Code review agent using smarter model"
125///
126/// [model]
127/// harness = "claude"
128/// model = "opus"
129/// ```
130pub mod agents;
131
132/// Failure attribution using git blame.
133///
134/// Maps validation errors to specific tasks by parsing error output for
135/// file:line references and using git blame to find which commits changed
136/// those lines. Task IDs are extracted from commit message prefixes like `[TASK-ID]`.
137///
138/// # Example
139///
140/// ```no_run
141/// use scud::attribution::{attribute_failure, AttributionConfidence};
142/// use std::path::Path;
143///
144/// let working_dir = Path::new(".");
145/// let wave_tasks = vec!["auth:1".to_string(), "auth:2".to_string()];
146///
147/// let attribution = attribute_failure(
148///     working_dir,
149///     "error: src/main.rs:42: undefined variable",
150///     "",
151///     &wave_tasks,
152///     None,
153/// ).unwrap();
154///
155/// match attribution.confidence {
156///     AttributionConfidence::High => println!("Clear responsible: {:?}", attribution.responsible_tasks),
157///     AttributionConfidence::Medium => println!("Multiple suspects: {:?}", attribution.responsible_tasks),
158///     AttributionConfidence::Low => println!("Cannot determine - all tasks suspect"),
159/// }
160/// ```
161pub mod attribution;
162
163/// Backpressure validation for maintaining code quality during automated execution.
164///
165/// Runs programmatic validation (build, test, lint) after task completion.
166/// See [`backpressure::run_validation`] for the main entry point.
167pub mod backpressure;
168
169/// CLI command implementations.
170///
171/// This module contains the implementation of all SCUD CLI commands including
172/// task listing, status updates, AI-powered parsing, and more. Each submodule
173/// corresponds to a CLI subcommand.
174///
175/// Key submodules:
176/// - `ai` - AI-powered commands (parse PRD, expand tasks, analyze complexity)
177/// - `generate` - Multi-phase task generation pipeline (parse → expand → check-deps)
178/// - `list` - List tasks with filtering
179/// - `next` - Find next available task
180/// - `set_status` - Update task status
181/// - `waves` - Display execution waves
182/// - `stats` - Show completion statistics
183/// - `spawn` - Parallel task execution
184/// - `swarm` - Wave-based parallel execution with backpressure
185///
186/// ## Generate Pipeline
187///
188/// The [`commands::generate`] module provides a complete pipeline for task generation:
189///
190/// ```no_run
191/// use scud::commands::generate::{generate, GenerateOptions};
192/// use std::path::PathBuf;
193///
194/// # async fn example() -> anyhow::Result<()> {
195/// let options = GenerateOptions::new(
196///     PathBuf::from("prd.md"),
197///     "feature".to_string(),
198/// );
199/// generate(options).await?;
200/// # Ok(())
201/// # }
202/// ```
203pub mod commands;
204
205/// Configuration management for SCUD projects.
206///
207/// Handles loading and saving of `.scud/config.toml` which stores:
208/// - LLM provider settings (provider, model, API endpoints)
209/// - Model tiers (smart/fast models for different task types)
210/// - Token limits and other provider-specific settings
211///
212/// # Example
213///
214/// ```no_run
215/// use scud::config::Config;
216/// use std::path::Path;
217///
218/// let config = Config::load(Path::new(".scud/config.toml"))
219///     .unwrap_or_default();
220/// println!("Using provider: {}", config.llm.provider);
221/// ```
222pub mod config;
223
224/// Task graph serialization formats.
225///
226/// Provides parsers and serializers for the SCG (SCUD Graph) format,
227/// a token-efficient text format designed for AI context windows.
228///
229/// # Format Overview
230///
231/// ```text
232/// @phase my-project
233///
234/// [1] First task
235/// status: pending
236/// complexity: 3
237///
238/// [2] Second task
239/// status: done
240/// deps: 1
241/// ```
242///
243/// Key exports:
244/// - [`formats::parse_scg`] - Parse SCG text into a Phase
245/// - [`formats::serialize_scg`] - Serialize a Phase to SCG text
246/// - [`formats::Format`] - Enum of supported formats (SCG, JSON)
247pub mod formats;
248
249/// LLM client and prompt management.
250///
251/// Provides integration with various LLM providers for AI-powered features:
252/// - PRD parsing to generate initial task lists
253/// - Task expansion into subtasks
254/// - Complexity analysis and dependency detection
255///
256/// Supported providers:
257/// - `claude-cli` - Anthropic Claude via CLI
258/// - `anthropic` - Direct Anthropic API
259/// - `xai` - xAI/Grok API
260/// - `openai` - OpenAI API
261/// - `openrouter` - OpenRouter API
262/// - `codex` - OpenAI Codex CLI
263pub mod llm;
264
265/// Core data models for tasks and phases.
266///
267/// This module defines the fundamental types used throughout SCUD:
268///
269/// - [`models::Task`] - Individual work items with status, complexity, dependencies
270/// - [`models::Phase`] - A collection of related tasks (identified by a tag)
271/// - [`models::TaskStatus`] - Task lifecycle states (Pending, InProgress, Done, etc.)
272/// - [`models::Priority`] - Task priority levels (Critical, High, Medium, Low)
273/// - [`models::IdFormat`] - ID generation strategy (Sequential or UUID)
274///
275/// # Example
276///
277/// ```
278/// use scud::models::{Task, TaskStatus, Phase};
279///
280/// let mut phase = Phase::new("my-feature".to_string());
281///
282/// let mut task = Task::new(
283///     "1".to_string(),
284///     "Implement feature".to_string(),
285///     "Add the new functionality".to_string(),
286/// );
287/// task.complexity = 5;
288/// task.dependencies = vec!["setup:1".to_string()]; // Cross-phase dependency
289///
290/// phase.add_task(task);
291///
292/// // Find tasks ready to work on
293/// if let Some(next) = phase.find_next_task() {
294///     println!("Ready: {}", next.title);
295/// }
296/// ```
297pub mod models;
298
299/// File-based task storage with locking.
300///
301/// Manages reading and writing of task data to the filesystem with:
302/// - File locking for safe concurrent access
303/// - Caching of active phase selection
304/// - Atomic read-modify-write operations
305///
306/// The storage layer handles:
307/// - `.scud/tasks/tasks.scg` - Main task storage
308/// - `.scud/active-tag` - Currently selected phase
309/// - `.scud/config.toml` - Project configuration
310/// - `.scud/guidance/*.md` - AI context files
311///
312/// # Example
313///
314/// ```no_run
315/// use scud::storage::Storage;
316/// use scud::models::TaskStatus;
317///
318/// let storage = Storage::new(None); // Use current directory
319///
320/// // Load and modify a phase atomically
321/// let mut phase = storage.load_group("my-phase").unwrap();
322/// if let Some(task) = phase.get_task_mut("1") {
323///     task.set_status(TaskStatus::Done);
324/// }
325/// storage.update_group("my-phase", &phase).unwrap();
326/// ```
327pub mod storage;
328
329/// Returns a greeting message.
330///
331/// # Example
332///
333/// ```
334/// assert_eq!(scud::hello(), "Hello, World!");
335/// ```
336pub fn hello() -> &'static str {
337    "Hello, World!"
338}