use std::fs::OpenOptions;
use std::io::{ErrorKind, Write};
use anyhow::Result;
use camino::Utf8PathBuf;
const DEFAULT_CONFIG: &str = r#"# cordance.toml — generated by `cordance init`.
# Documentation: docs/COMMAND_SURFACE.md
[doctrine]
# Path to engineering-doctrine repo. Relative to this file or absolute.
source = "../engineering-doctrine"
# Where to clone doctrine from when the sibling path doesn't exist.
fallback_repo = "https://github.com/0ryant/engineering-doctrine"
# "auto" = use HEAD commit; any other value pins a specific SHA.
pin_commit = "auto"
[axiom]
# Path to the pai-axiom repo. Relative to this file or absolute.
source = "../pai-axiom"
# "auto" = read PAI/Algorithm/LATEST from the configured source.
algorithm_latest = "auto"
[llm]
# Provider: "none" | "ollama" | "lm-studio"
provider = "none"
[llm.ollama]
base_url = "http://localhost:11434"
model = "qwen2.5-coder:14b"
temperature = 0.1
num_ctx = 8192
[mcp]
# Additional roots that `--target` is permitted to canonicalise into when
# running `cordance serve`. Each path is resolved against the server's
# launch directory. Default: only the server's launch directory.
allowed_roots = []
"#;
pub fn run(target: &Utf8PathBuf) -> Result<()> {
let config_path = target.join("cordance.toml");
match OpenOptions::new()
.write(true)
.create_new(true)
.open(config_path.as_std_path())
{
Ok(mut file) => {
file.write_all(DEFAULT_CONFIG.as_bytes())?;
println!("Created {config_path}");
Ok(())
}
Err(e) if e.kind() == ErrorKind::AlreadyExists => {
println!("cordance.toml already exists at {config_path} — skipping.");
Ok(())
}
Err(e) => Err(e.into()),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_config_is_strict_loadable() {
let dir = tempfile::tempdir().expect("tempdir");
let target = Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).expect("tempdir is utf8");
std::fs::write(target.join("cordance.toml"), DEFAULT_CONFIG)
.expect("write default cordance.toml");
let cfg = crate::config::Config::load_strict(&target)
.expect("default cordance.toml must load_strict");
assert_eq!(cfg.llm.provider, "none");
assert_eq!(cfg.llm.ollama.model, "qwen2.5-coder:14b");
assert_eq!(cfg.llm.ollama.base_url, "http://localhost:11434");
assert_eq!(cfg.doctrine.source, "../engineering-doctrine");
assert_eq!(cfg.axiom.source, "../pai-axiom");
assert_eq!(cfg.axiom.algorithm_latest, "auto");
assert!(cfg.mcp.allowed_roots.is_empty());
}
#[test]
fn run_writes_template_that_load_strict_accepts() {
let dir = tempfile::tempdir().expect("tempdir");
let target = Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).expect("tempdir is utf8");
run(&target).expect("init succeeds");
assert!(target.join("cordance.toml").exists());
let cfg = crate::config::Config::load_strict(&target)
.expect("generated cordance.toml must load_strict");
assert_eq!(cfg.llm.ollama.model, "qwen2.5-coder:14b");
}
#[test]
fn run_skips_existing_config() {
let dir = tempfile::tempdir().expect("tempdir");
let target = Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).expect("tempdir is utf8");
let original = "[llm]\nprovider = \"ollama\"\n";
std::fs::write(target.join("cordance.toml"), original).expect("write");
run(&target).expect("init succeeds when file exists");
let on_disk = std::fs::read_to_string(target.join("cordance.toml")).expect("read back");
assert_eq!(on_disk, original, "init must not overwrite existing config");
}
#[test]
fn concurrent_init_races_do_not_clobber() {
use std::sync::{Arc, Barrier};
use std::thread;
let dir = tempfile::tempdir().expect("tempdir");
let target = Utf8PathBuf::from_path_buf(dir.path().to_path_buf()).expect("tempdir is utf8");
let barrier = Arc::new(Barrier::new(2));
let target_a = target.clone();
let target_b = target.clone();
let barrier_a = Arc::clone(&barrier);
let barrier_b = Arc::clone(&barrier);
let handle_a = thread::spawn(move || {
barrier_a.wait();
run(&target_a)
});
let handle_b = thread::spawn(move || {
barrier_b.wait();
run(&target_b)
});
let result_a = handle_a.join().expect("thread a panicked");
let result_b = handle_b.join().expect("thread b panicked");
result_a.expect("thread a should not error");
result_b.expect("thread b should not error");
let on_disk = std::fs::read_to_string(target.join("cordance.toml")).expect("read back");
assert_eq!(
on_disk, DEFAULT_CONFIG,
"concurrent init must leave exactly the canonical default config on disk"
);
}
}