bot-forge 1.0.0

Rust CLI for installing agent skills and developer tools from configurable forms.
Documentation
//! Human and machine report models and local report persistence.
//!
//! Reports are serialized after execution into the application data directory. Ordered lifecycle
//! events use the crate-level event capability and are not owned by final report persistence.

use std::path::PathBuf;

use serde::Serialize;

use crate::error::ForgeError;
use crate::fsutil::{atomic_write_file, create_dir_all};
use crate::model::InstallReport;
use crate::paths::app_home;
use crate::util::now_secs;

/// Persist an installation report as a timestamped JSON file.
///
/// # Errors
///
/// Returns [`ForgeError`] when the log directory cannot be created or the report cannot be
/// serialized or written atomically.
pub(crate) fn write_install_report_log(report: &InstallReport) -> Result<PathBuf, ForgeError> {
    let log_dir = app_home().join("logs");
    create_dir_all(&log_dir)?;
    let timestamp = now_secs();
    let path = log_dir.join(format!("install-{timestamp}.json"));
    write_json(&path, report, "installation log")?;
    Ok(path)
}

fn write_json(
    path: &std::path::Path,
    value: &impl Serialize,
    label: &str,
) -> Result<(), ForgeError> {
    let output = serde_json::to_vec_pretty(value)
        .map_err(|error| ForgeError::Parse(format!("failed to serialize {label}: {error}")))?;
    atomic_write_file(path, &output)
}