use crate::config;
use crate::paths::Paths;
use crate::store::{FileStore, Key, StateStore};
use anyhow::{Context, Result};
use std::fs;
use std::path::Path;
const SEED_PLAYBOOK: &str = include_str!("seed/PLAYBOOK.md");
const SEED_GOAL_SETUP: &str = include_str!("seed/setup.md");
const SEED_GOAL_PLAYBOOK_DAILY: &str = include_str!("seed/playbook-daily.md");
const SEED_SENSOR_TODAY: &str = include_str!("seed/today.sh");
const GITIGNORE: &str = "\
snapshots/
prompts/
runs/
claims/
reports/
asks/
answers/
.lock/
.last-tick-hash
.goal-activity.json
tick.log
events.jsonl
cost.jsonl
# worker scratch that can land in the data dir
.ruff_cache/
.pytest_cache/
.mypy_cache/
__pycache__/
";
pub fn ensure_dirs(paths: &Paths) -> Result<()> {
for d in [
paths
.config
.parent()
.unwrap_or(Path::new("."))
.to_path_buf(),
paths.sensors_dir(),
paths.snapshots_dir(),
paths.claims_dir(),
paths.reports_dir(),
paths.asks_dir(),
paths.answers_dir(),
paths.runs_dir(),
paths.goals_dir().join("archive"),
paths.prompts_dir(),
] {
fs::create_dir_all(&d).with_context(|| format!("mkdir -p {}", d.display()))?;
}
config::ensure_config(paths)?;
if !paths.playbook().is_file() {
seed_data(paths)?;
}
let gi = paths.data_dir.join(".gitignore");
if !gi.is_file() {
fs::write(&gi, GITIGNORE).with_context(|| format!("writing {}", gi.display()))?;
}
Ok(())
}
fn seed_data(paths: &Paths) -> Result<()> {
let store = FileStore::new(paths);
store.write_atomic(&Key::Playbook, SEED_PLAYBOOK)?;
store.write_atomic(&Key::Goal("setup".into()), SEED_GOAL_SETUP)?;
store.write_atomic(
&Key::Goal("playbook-daily".into()),
SEED_GOAL_PLAYBOOK_DAILY,
)?;
store.write_atomic(&Key::Sensor("today".into()), SEED_SENSOR_TODAY)?;
Ok(())
}