//! A turn from before sync began goes nowhere (M5c spec, section 5): the first check, before //! every other, by the time of the turn's `User` record against the ledger's `Began`. Do not //! edit. use bxcore::{DataClass, LogRecord, SessionStateReply, Timestamp}; use memoryd::honcho::decide::{BEFORE_SYNC, SECRET_CLASS, decide}; use memoryd::honcho::ledger::{Action, Workspace}; const AGENT: &str = "boxmaker0"; fn at(s: &str) -> Timestamp { Timestamp::parse(s).unwrap() } /// One finished turn, its `User` record at `time`. fn turn(time: &str, speaker: Option<&str>) -> Vec { vec![ LogRecord::User { time: at(time), content: "hello".to_string(), speaker: speaker.map(str::to_string), }, LogRecord::Assistant { time: at(time), content: Some("hi".to_string()), reasoning_content: None, tool_calls: Vec::new(), }, ] } fn state(class: DataClass) -> SessionStateReply { SessionStateReply { class, untrusted: false, } } fn skip(why: &str) -> Action { Action::Skip { why: why.to_string(), } } const BEGAN: &str = "2026-09-28T10:00:00.000Z"; #[test] fn the_text() { assert_eq!(BEFORE_SYNC, "the turn is from before sync began"); } #[test] fn a_turn_from_before_sync_began_goes_nowhere() { let began = Some(at(BEGAN)); let clean = state(DataClass::Private); let before = turn("2026-09-28T09:59:59.999Z", Some("kyle")); assert_eq!( decide(&clean, &before, 1, AGENT, began), Ok(skip(BEFORE_SYNC)) ); let same = turn(BEGAN, Some("kyle")); let to_trusted = Action::Turn { workspace: Workspace::Trusted, speaker: "kyle".to_string(), }; assert_eq!( decide(&clean, &same, 1, AGENT, began), Ok(to_trusted.clone()) ); let after = turn("2026-09-28T10:00:00.001Z", Some("kyle")); assert_eq!( decide(&clean, &after, 1, AGENT, began), Ok(to_trusted.clone()) ); // Without a time sync began, no turn is too old. assert_eq!(decide(&clean, &before, 1, AGENT, None), Ok(to_trusted)); } #[test] fn it_is_the_first_check() { let began = Some(at(BEGAN)); // A turn from before that also breaks the class and the speaker rules: before-sync wins. let before = turn("2026-09-28T09:00:00.000Z", None); assert_eq!( decide(&state(DataClass::Secret), &before, 1, AGENT, began), Ok(skip(BEFORE_SYNC)) ); // The same turn after it: the next rule decides. let after = turn("2026-09-28T11:00:00.000Z", None); assert_eq!( decide(&state(DataClass::Secret), &after, 1, AGENT, began), Ok(skip(SECRET_CLASS)) ); } #[test] fn each_turn_by_its_own_time() { let began = Some(at(BEGAN)); let mut records = turn("2026-09-28T09:00:00.000Z", Some("kyle")); records.extend(turn("2026-09-28T11:00:00.000Z", Some("kyle"))); let clean = state(DataClass::Private); assert_eq!( decide(&clean, &records, 1, AGENT, began), Ok(skip(BEFORE_SYNC)) ); assert!(matches!( decide(&clean, &records, 2, AGENT, began), Ok(Action::Turn { .. }) )); }