Skip to main content

agent_policy/render/
copilot_instructions.rs

1//! Renderer for `.github/copilot-instructions.md`.
2
3use camino::Utf8PathBuf;
4use minijinja::Environment;
5
6use crate::{
7    error::{Error, Result},
8    model::normalized::Policy,
9    render::RenderedOutput,
10};
11
12const TEMPLATE: &str = include_str!("../../templates/copilot-instructions.md.j2");
13
14/// Render the `.github/copilot-instructions.md` output for the given policy.
15///
16/// # Errors
17///
18/// Returns [`Error::Render`] if the template fails to compile or render.
19pub fn render(policy: &Policy) -> Result<RenderedOutput> {
20    let mut env = Environment::new();
21    env.add_template("copilot-instructions.md", TEMPLATE)
22        .map_err(|e| Error::Render {
23            target: "copilot-instructions.md".to_owned(),
24            source: e,
25        })?;
26
27    let tmpl = env
28        .get_template("copilot-instructions.md")
29        .map_err(|e| Error::Render {
30            target: "copilot-instructions.md".to_owned(),
31            source: e,
32        })?;
33
34    let commands_defined = !policy.commands.is_empty();
35    let content = tmpl
36        .render(minijinja::context! {
37            project => &policy.project,
38            commands => &policy.commands,
39            commands_defined => commands_defined,
40            paths => &policy.paths,
41            roles => &policy.roles,
42            constraints => &policy.constraints,
43        })
44        .map_err(|e| Error::Render {
45            target: "copilot-instructions.md".to_owned(),
46            source: e,
47        })?;
48
49    Ok(RenderedOutput {
50        path: Utf8PathBuf::from(".github/copilot-instructions.md"),
51        content,
52    })
53}