use std::str::FromStr;
use agent_migrate_core::{Endpoint, WatchDecision, WatchState, content_hash};
#[test]
fn same_hash_and_own_origin_are_suppressed() -> Result<(), Box<dyn std::error::Error>> {
let source = Endpoint::from_str("codex@local")?;
let target = Endpoint::from_str("pi@local")?;
let mut state = WatchState::new(source, target);
let hash = content_hash(b"stable configuration");
let initial = state.decide(&hash, None);
state.record_applied(&hash);
let unchanged = state.decide(&hash, None);
let own_origin = state.decide("different", Some(state.origin_id()));
assert_eq!(initial, WatchDecision::Apply);
assert_eq!(unchanged, WatchDecision::Unchanged);
assert_eq!(own_origin, WatchDecision::SuppressedOrigin);
Ok(())
}
#[test]
fn reverse_edge_shares_origin_while_unrelated_edge_does_not()
-> Result<(), Box<dyn std::error::Error>> {
let codex = Endpoint::from_str("codex@local")?;
let pi = Endpoint::from_str("pi@fixture")?;
let claude = Endpoint::from_str("claude@local")?;
let forward = WatchState::new(codex.clone(), pi.clone());
let reverse = WatchState::new(pi.clone(), codex);
let onward = WatchState::new(pi, claude);
assert_eq!(forward.origin_id(), reverse.origin_id());
assert_ne!(forward.origin_id(), onward.origin_id());
assert_eq!(
onward.decide("changed", Some(forward.origin_id())),
WatchDecision::Apply
);
Ok(())
}
#[test]
fn watch_state_persists_all_loop_identity() -> Result<(), Box<dyn std::error::Error>> {
let temp = tempfile::tempdir()?;
let path = temp.path().join("watch/state.json");
let mut state = WatchState::new(
Endpoint::from_str("claude@local")?,
Endpoint::from_str("codex@lab")?,
);
state.record_applied(content_hash(b"configuration"));
state.save(&path)?;
let restored = WatchState::load(&path)?;
assert_eq!(restored, state);
Ok(())
}