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
}