use std::path::Path;
use argonauts_core::NoteLevel;
use argonauts_core::api::{RunState, RunSummary};
use argonauts_core::paths::write_private_file;
use time::format_description::well_known::Rfc3339;
use crate::client;
const TOLD: &str = "told";
pub(crate) fn once(run_dir: &Path, run: &RunSummary) -> Option<(NoteLevel, String)> {
let line = line(run)?;
let stamp = run.updated.format(&Rfc3339).ok()?;
let marker = run_dir.join(TOLD);
if std::fs::read_to_string(&marker).is_ok_and(|told| told.trim() == stamp) {
return None;
}
if let Err(err) = write_private_file(&marker, stamp.as_bytes()) {
tracing::warn!("remembering {}: {err}", marker.display());
}
Some(line)
}
fn line(run: &RunSummary) -> Option<(NoteLevel, String)> {
let title = run.name.as_deref().unwrap_or(&run.title);
match run.state {
RunState::FromAnotherBuild => Some((
NoteLevel::Info,
client::from_another_build_line(run, "opened"),
)),
RunState::Crashed => Some((NoteLevel::Warn, format!("\"{title}\" {}", run.stopped_at))),
_ => None,
}
}
#[cfg(test)]
mod tests {
use argonauts_core::events::run::RunMode;
use argonauts_core::{RunId, Spend};
use time::macros::datetime;
use super::*;
fn run(state: RunState, title: &str, stopped_at: &str) -> RunSummary {
RunSummary {
run: RunId::new("run-20261004-072329-63c3").unwrap(),
title: title.to_owned(),
name: None,
mode: RunMode::Captain,
workflow: String::new(),
state,
stopped_at: stopped_at.to_owned(),
updated: datetime!(2026-10-04 07:23:29 UTC),
spent: Spend::default(),
sessions_to_resume: 0,
waiting: Vec::new(),
live: false,
remind: false,
shape_known: true,
}
}
fn pictured(first: &str) -> &'static str {
include_str!("../../../../tui/tests/golden/old_runs.txt")
.lines()
.find(|row| row.starts_with(first))
.expect("the picture has the row")
}
#[test]
fn a_run_from_an_older_build_is_said_once_and_plainly() {
let dir = tempfile::tempdir().unwrap();
let old = run(RunState::FromAnotherBuild, "hi", "");
let (level, text) = once(dir.path(), &old).unwrap();
assert_eq!(level, NoteLevel::Info);
assert_eq!(format!("● {text}"), pictured("● \"hi\" (Oct 4)"));
assert_eq!(once(dir.path(), &old), None, "the next start says nothing");
}
#[test]
fn a_stopped_run_is_said_once_with_what_resume_does_and_again_if_it_stops_again() {
let dir = tempfile::tempdir().unwrap();
let words = "stopped at 3m10s when its run host exited · /resume carries it on from \
Review";
let mut stopped = run(RunState::Crashed, "Add due dates", words);
let (level, text) = once(dir.path(), &stopped).unwrap();
assert_eq!(level, NoteLevel::Warn);
assert_eq!(format!("● {text}"), pictured("● \"Add due dates\" stopped"));
assert_eq!(once(dir.path(), &stopped), None);
stopped.updated = datetime!(2026-10-05 09:00:00 UTC);
assert!(once(dir.path(), &stopped).is_some());
}
#[test]
fn runs_that_go_wait_or_never_started_say_nothing_at_a_start() {
let dir = tempfile::tempdir().unwrap();
for state in [
RunState::Running,
RunState::Waiting,
RunState::NeverStarted,
RunState::Merged,
RunState::Stopped,
] {
assert_eq!(once(dir.path(), &run(state, "x", "")), None, "{state:?}");
}
assert!(!dir.path().join(TOLD).exists());
}
}