use std::path::Path;
use crate::config::Config;
use crate::diagnostic::{DiagnosticResult, Diagnostics};
use crate::ui;
use crate::write::{WriteOp, create_dir_all, write_file};
include!(concat!(env!("OUT_DIR"), "/skill_assets.rs"));
const AGENT_TEMPLATES: &[(&str, &str)] = &[
(
"agents/rfc-reviewer.md",
include_str!("../../../.claude/agents/rfc-reviewer.md"),
),
(
"agents/adr-reviewer.md",
include_str!("../../../.claude/agents/adr-reviewer.md"),
),
(
"agents/wi-reviewer.md",
include_str!("../../../.claude/agents/wi-reviewer.md"),
),
(
"agents/compliance-checker.md",
include_str!("../../../.claude/agents/compliance-checker.md"),
),
];
include!(concat!(env!("OUT_DIR"), "/agent_codex_templates.rs"));
pub fn sync_skills(
config: &Config,
force: bool,
format: &crate::SkillFormat,
dir_override: Option<&Path>,
op: WriteOp,
) -> DiagnosticResult<Diagnostics> {
let format_default = match format {
crate::SkillFormat::Claude => std::path::Path::new(".claude"),
crate::SkillFormat::Codex => std::path::Path::new(".codex"),
};
let agent_dir_owned;
let agent_dir = if let Some(dir) = dir_override {
if dir.is_relative() {
agent_dir_owned = config
.gov_root
.parent()
.unwrap_or(std::path::Path::new("."))
.join(dir);
&agent_dir_owned
} else {
agent_dir_owned = dir.to_path_buf();
&agent_dir_owned
}
} else if config.paths.agent_dir != crate::config::default_agent_dir() {
&config.paths.agent_dir
} else {
agent_dir_owned = config
.gov_root
.parent()
.unwrap_or(std::path::Path::new("."))
.join(format_default);
&agent_dir_owned
};
let agent_templates: &[(&str, &str)] = match format {
crate::SkillFormat::Claude => AGENT_TEMPLATES,
crate::SkillFormat::Codex => AGENT_TEMPLATES_CODEX,
};
let mut synced = 0;
let mut skipped = 0;
for (rel_path, template) in SKILL_ASSETS.iter().chain(agent_templates.iter()) {
let path = agent_dir.join(rel_path);
let display_path = config.display_path(&path);
if let Some(parent) = path.parent() {
let display_parent = config.display_path(parent);
create_dir_all(parent, op, Some(&display_parent))?;
}
if path.exists() && !force && !op.is_preview() {
skipped += 1;
if !op.is_preview() {
ui::sub_info(format!(
"Skipped {} (already exists, use -f to overwrite)",
path.display()
));
}
continue;
}
write_file(&path, template, op, Some(&display_path))?;
if !op.is_preview() {
if path.exists() && force {
ui::info(format!("Updated {}", display_path.display()));
} else {
ui::created_path(&display_path);
}
}
synced += 1;
}
if !op.is_preview() {
if synced > 0 {
ui::success(format!("Synced {} asset(s)", synced));
}
if skipped > 0 {
ui::info(format!(
"{} asset(s) skipped (use -f to overwrite)",
skipped
));
}
if synced == 0 && skipped == 0 {
ui::info("No assets to sync");
}
}
Ok(vec![])
}