use crate::model::ProjectPlan; pub fn render_prompt(plan: &ProjectPlan) -> String { let mut s = String::new(); s.push_str("# Project Implementation Plan\n\n"); s.push_str("You are an expert software engineer. Implement the following project carefully, with minimal errors, following the plan, stack, and standards below. Ask clarifying questions only if truly necessary; otherwise proceed.\n\n"); s.push_str("## 1. Project Overview\n"); s.push_str(&format!("- **Name:** {}\n", plan.name)); s.push_str(&format!("- **Description:** {}\n", plan.description)); s.push_str(&format!("- **Type:** {}\n", plan.project_type)); s.push_str(&format!("- **Audience:** {}\n", plan.audience)); s.push_str(&format!("- **Scale:** {}\n", plan.scale)); s.push_str(&format!("- **Created:** {}\n\n", plan.created_at)); s.push_str("## 2. Requirements\n"); for r in &plan.requirements { if r.key != "constraint" { s.push_str(&format!("- **{}:** {}\n", r.key, r.value)); } } s.push('\n'); let constraints: Vec<&crate::model::Requirement> = plan.requirements.iter().filter(|r| r.key == "constraint").collect(); if !constraints.is_empty() { s.push_str("## Constraints\n"); for r in constraints { s.push_str(&format!("- {}\n", r.value)); } s.push('\n'); } s.push_str("## 3. Chosen Stack\n"); s.push_str(&format!("- **Language:** {}\n", plan.stack.language)); if let Some(f) = &plan.stack.framework { s.push_str(&format!("- **Framework:** {}\n", f)); } s.push_str(&format!("- **Libraries:** {}\n", plan.stack.libraries.join(", "))); s.push_str(&format!("- **Rationale:** {}\n\n", plan.stack.rationale)); s.push_str("## 4. Libraries (details)\n"); for l in &plan.libraries { s.push_str(&format!("- **{}** ({}, {}): {}{}\n", l.name, l.lang, l.domain, l.purpose, l.note.as_ref().map(|n| format!(" — {}", n)).unwrap_or_default())); } s.push('\n'); s.push_str("## 5. Architecture\n"); s.push_str(&format!("{}\n\n", plan.architecture)); s.push_str("## 6. Suggested File Structure\n"); for f in &plan.file_tree { s.push_str(&format!("- `{}`\n", f)); } s.push('\n'); s.push_str("## 7. Feature Plan\n"); let feature_reqs: Vec<&crate::model::Requirement> = plan.requirements.iter().filter(|r| r.key == "feature").collect(); if feature_reqs.is_empty() { s.push_str("- (no specific features listed; derive from description)\n"); } else { for r in feature_reqs { s.push_str(&format!("- {}\n", r.value)); } } s.push('\n'); s.push_str("## 8. Implementation Plan (Milestones)\n"); for m in &plan.milestones { s.push_str(&format!("### {} — {}\n", m.name, m.goal)); for t in &m.tasks { s.push_str(&format!("- [ ] **{}** {}: {}\n", t.id, t.title, t.description)); if !t.depends_on.is_empty() { s.push_str(&format!(" (depends on: {})\n", t.depends_on.join(", "))); } } s.push('\n'); } s.push_str("## 9. Coding Standards\n"); for c in &plan.coding_standards { s.push_str(&format!("- {}\n", c)); } s.push('\n'); s.push_str("## 10. Risks & Mitigations\n"); if plan.risks.is_empty() { s.push_str("- None identified.\n"); } else { for r in &plan.risks { s.push_str(&format!("- {}\n", r)); } } s.push('\n'); s.push_str("## Common Pitfalls\n"); if plan.pitfalls.is_empty() { s.push_str("- None identified.\n"); } else { for p in &plan.pitfalls { s.push_str(&format!("- {}\n", p)); } } s.push('\n'); if let Some(t) = &plan.template { s.push_str(&format!("## 11. Template Used\n- {}\n\n", t)); } if let Some(g) = &plan.language_guidance { s.push_str("## Language Guidance\n"); s.push_str(g); s.push_str("\n\n"); } if !plan.domain.is_empty() { s.push_str(&format!("## Domain\n- {}\n\n", plan.domain)); } if let Some(g) = &plan.domain_guidance { s.push_str("## Domain Guidance\n"); s.push_str(g); s.push_str("\n\n"); } if let Some(ai) = &plan.ai_assistance { s.push_str("## AI Assistant (Local Model) Notes\n"); s.push_str(ai); s.push_str("\n\n"); } s.push_str("## Final Instructions to the LLM\n"); s.push_str("1. Follow the milestones in order; do not skip setup.\n"); s.push_str("2. Use ONLY the chosen stack and libraries unless a strong reason exists; explain deviations.\n"); s.push_str("3. Produce complete, runnable code for each file in the suggested structure.\n"); s.push_str("4. Include tests for core logic.\n"); s.push_str("5. Handle errors and edge cases; no panics in production paths.\n"); s.push_str("6. End with a short summary of what was implemented and how to run it.\n"); s }