replace libc date math with chrono, extract memory_subdir helper

- date_to_epoch, iso_week_info, weeks_in_month: replaced unsafe libc
  (mktime, strftime, localtime_r) with chrono NaiveDate and IsoWeek
- epoch_to_local: replaced unsafe libc localtime_r with chrono Local
- New util.rs with memory_subdir() helper: ensures subdir exists and
  propagates errors instead of silently ignoring them
- Removed three duplicate agent_results_dir() definitions across
  digest.rs, consolidate.rs, enrich.rs
- load_digest_files, parse_all_digest_links, find_consolidation_reports
  now return Result to properly propagate directory creation errors

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2026-03-03 17:23:43 -05:00
parent 50da0b7b26
commit f4364e299c
7 changed files with 75 additions and 129 deletions

View file

@ -19,11 +19,7 @@ use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
fn agent_results_dir() -> PathBuf {
let dir = store::memory_dir().join("agent-results");
fs::create_dir_all(&dir).ok();
dir
}
use crate::util::memory_subdir;
/// Simple append-only log writer for consolidate-full.
struct LogWriter {
@ -49,7 +45,7 @@ impl LogWriter {
/// Run the full autonomous consolidation pipeline with logging.
pub fn consolidate_full(store: &mut Store) -> Result<(), String> {
let start = std::time::Instant::now();
let log_path = agent_results_dir().join("consolidate-full.log");
let log_path = memory_subdir("agent-results")?.join("consolidate-full.log");
let mut log = LogWriter::new(&log_path)?;
log.write("=== CONSOLIDATE FULL ===")?;
@ -162,7 +158,7 @@ pub fn consolidate_full(store: &mut Store) -> Result<(), String> {
let ts = store::format_datetime(store::now_epoch())
.replace([':', '-', 'T'], "");
let report_name = format!("consolidation-{}-{}.md", agent_type, ts);
let report_path = agent_results_dir().join(&report_name);
let report_path = memory_subdir("agent-results")?.join(&report_name);
fs::write(&report_path, &response)
.map_err(|e| format!("write report: {}", e))?;
reports.push(report_path.clone());
@ -233,7 +229,7 @@ pub fn consolidate_full(store: &mut Store) -> Result<(), String> {
println!("\n--- Applying digest links ---");
*store = Store::load()?;
let links = digest::parse_all_digest_links();
let links = digest::parse_all_digest_links()?;
let (applied, skipped, fallbacks) = digest::apply_digest_links(store, &links);
store.save()?;
log.write(&format!(" {} links applied, {} skipped, {} fallbacks",
@ -265,8 +261,8 @@ pub fn consolidate_full(store: &mut Store) -> Result<(), String> {
}
/// Find the most recent set of consolidation reports.
fn find_consolidation_reports() -> Vec<PathBuf> {
let dir = agent_results_dir();
fn find_consolidation_reports() -> Result<Vec<PathBuf>, String> {
let dir = memory_subdir("agent-results")?;
let mut reports: Vec<PathBuf> = fs::read_dir(&dir)
.map(|entries| {
entries.filter_map(|e| e.ok())
@ -283,7 +279,7 @@ fn find_consolidation_reports() -> Vec<PathBuf> {
reports.sort();
reports.reverse();
if reports.is_empty() { return reports; }
if reports.is_empty() { return Ok(reports); }
// Group by timestamp (last segment of stem before .md)
let latest_ts = reports[0].file_stem()
@ -299,7 +295,7 @@ fn find_consolidation_reports() -> Vec<PathBuf> {
.ends_with(latest_ts.as_str())
});
reports
Ok(reports)
}
fn build_consolidation_prompt(reports: &[PathBuf]) -> Result<String, String> {
@ -321,7 +317,7 @@ pub fn apply_consolidation(store: &mut Store, do_apply: bool, report_file: Optio
let reports = if let Some(path) = report_file {
vec![PathBuf::from(path)]
} else {
find_consolidation_reports()
find_consolidation_reports()?
};
if reports.is_empty() {
@ -350,7 +346,7 @@ pub fn apply_consolidation(store: &mut Store, do_apply: bool, report_file: Optio
// Save actions
let timestamp = store::format_datetime(store::now_epoch())
.replace([':', '-'], "");
let actions_path = agent_results_dir()
let actions_path = memory_subdir("agent-results")?
.join(format!("consolidation-actions-{}.json", timestamp));
fs::write(&actions_path, serde_json::to_string_pretty(&actions_value).unwrap())
.map_err(|e| format!("write {}: {}", actions_path.display(), e))?;