Skip to main content

oven_cli/agents/
planner.rs

1use anyhow::{Context, Result};
2use askama::Template;
3
4use crate::issues::PipelineIssue;
5
6#[derive(Template)]
7#[template(path = "planner.txt")]
8struct PlannerPrompt<'a> {
9    issues: &'a [PipelineIssue],
10}
11
12pub fn build_prompt(issues: &[PipelineIssue]) -> Result<String> {
13    let tmpl = PlannerPrompt { issues };
14    tmpl.render().context("rendering planner template")
15}
16
17#[cfg(test)]
18mod tests {
19    use super::*;
20    use crate::issues::IssueOrigin;
21
22    fn sample_issues() -> Vec<PipelineIssue> {
23        vec![
24            PipelineIssue {
25                number: 1,
26                title: "Add login".to_string(),
27                body: "implement login flow".to_string(),
28                source: IssueOrigin::Github,
29                target_repo: None,
30            },
31            PipelineIssue {
32                number: 2,
33                title: "Fix bug".to_string(),
34                body: "crash on startup".to_string(),
35                source: IssueOrigin::Github,
36                target_repo: None,
37            },
38        ]
39    }
40
41    #[test]
42    fn prompt_includes_issue_details() {
43        let prompt = build_prompt(&sample_issues()).unwrap();
44        assert!(prompt.contains("#1: Add login"));
45        assert!(prompt.contains("#2: Fix bug"));
46        assert!(prompt.contains("<issue_body>implement login flow</issue_body>"));
47        assert!(prompt.contains("<issue_body>crash on startup</issue_body>"));
48    }
49
50    #[test]
51    fn prompt_includes_complexity_classification() {
52        let prompt = build_prompt(&sample_issues()).unwrap();
53        assert!(prompt.contains("**simple**"));
54        assert!(prompt.contains("**full**"));
55        assert!(prompt.contains("Complexity Classification"));
56    }
57
58    #[test]
59    fn prompt_includes_conflict_detection() {
60        let prompt = build_prompt(&sample_issues()).unwrap();
61        assert!(prompt.contains("Conflict Detection"));
62        assert!(prompt.contains("CANNOT parallelize"));
63        assert!(prompt.contains("CAN parallelize"));
64    }
65
66    #[test]
67    fn prompt_structured_json_output_is_valid() {
68        let prompt = build_prompt(&sample_issues()).unwrap();
69        // The template includes an example JSON block -- verify it has the new fields
70        assert!(prompt.contains("\"complexity\": \"simple\""));
71        assert!(prompt.contains("\"has_migration\""));
72        assert!(prompt.contains("\"predicted_files\""));
73        assert!(prompt.contains("\"area\""));
74        assert!(prompt.contains("\"total_issues\""));
75        assert!(prompt.contains("\"parallel_capacity\""));
76    }
77}