scud/commands/spawn/
agent.rs

1//! Agent prompt generation for Claude Code sessions
2//!
3//! Creates prompts that provide task context and instructions for Claude Code agents.
4
5use crate::models::task::Task;
6
7/// Generate a prompt for Claude Code with task context
8pub fn generate_prompt(task: &Task, tag: &str) -> String {
9    let mut prompt = format!(
10        r#"You are working on SCUD task {id}: {title}
11
12Tag: {tag}
13Complexity: {complexity}
14Priority: {priority:?}
15
16Description:
17{description}
18"#,
19        id = task.id,
20        title = task.title,
21        tag = tag,
22        complexity = task.complexity,
23        priority = task.priority,
24        description = task.description,
25    );
26
27    // Add details if present
28    if let Some(ref details) = task.details {
29        prompt.push_str(&format!(
30            r#"
31Technical Details:
32{}
33"#,
34            details
35        ));
36    }
37
38    // Add test strategy if present
39    if let Some(ref test_strategy) = task.test_strategy {
40        prompt.push_str(&format!(
41            r#"
42Test Strategy:
43{}
44"#,
45            test_strategy
46        ));
47    }
48
49    // Add dependencies info if any
50    if !task.dependencies.is_empty() {
51        prompt.push_str(&format!(
52            r#"
53Dependencies (should be done):
54{}
55"#,
56            task.dependencies.join(", ")
57        ));
58    }
59
60    // Add instructions
61    prompt.push_str(&format!(
62        r#"
63Instructions:
641. First, explore the codebase to understand the context for this task
652. Implement the task following project conventions and patterns
663. Write tests if applicable based on the test strategy
674. When complete, run: scud set-status {} done
685. If blocked by issues, run: scud set-status {} blocked
69
70Begin by understanding what needs to be done and exploring relevant code.
71"#,
72        task.id, task.id
73    ));
74
75    prompt
76}
77
78/// Generate a shorter prompt for tasks with less context
79pub fn generate_minimal_prompt(task: &Task, tag: &str) -> String {
80    format!(
81        r#"SCUD Task {}: {}
82
83Tag: {}
84Description: {}
85
86When done: scud set-status {} done
87If blocked: scud set-status {} blocked
88"#,
89        task.id, task.title, tag, task.description, task.id, task.id
90    )
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96    use crate::models::task::Task;
97
98    #[test]
99    fn test_generate_prompt_basic() {
100        let task = Task::new(
101            "auth:1".to_string(),
102            "Implement login".to_string(),
103            "Add user authentication flow".to_string(),
104        );
105
106        let prompt = generate_prompt(&task, "auth");
107
108        assert!(prompt.contains("auth:1"));
109        assert!(prompt.contains("Implement login"));
110        assert!(prompt.contains("Tag: auth"));
111        assert!(prompt.contains("scud set-status auth:1 done"));
112    }
113
114    #[test]
115    fn test_generate_prompt_with_details() {
116        let mut task = Task::new(
117            "api:2".to_string(),
118            "Add endpoint".to_string(),
119            "Create REST endpoint".to_string(),
120        );
121        task.details = Some("Use Express.js router pattern".to_string());
122        task.test_strategy = Some("Unit test with Jest".to_string());
123
124        let prompt = generate_prompt(&task, "api");
125
126        assert!(prompt.contains("Technical Details:"));
127        assert!(prompt.contains("Express.js router"));
128        assert!(prompt.contains("Test Strategy:"));
129        assert!(prompt.contains("Unit test with Jest"));
130    }
131
132    #[test]
133    fn test_generate_minimal_prompt() {
134        let task = Task::new(
135            "fix:1".to_string(),
136            "Quick fix".to_string(),
137            "Fix typo".to_string(),
138        );
139
140        let prompt = generate_minimal_prompt(&task, "fix");
141
142        assert!(prompt.contains("fix:1"));
143        assert!(prompt.contains("Quick fix"));
144        assert!(!prompt.contains("Technical Details"));
145    }
146}