pub mod checkpoint;
pub mod compact;
pub mod conversation;
pub mod crypto;
pub mod fence;
pub mod fold;
pub mod journal;
pub mod lease;
pub mod net_relay;
pub mod oplog;
pub mod partition;
pub mod relay;
pub mod session;
pub use checkpoint::{
resume_anchored, verify_anchored, AnchorError, Checkpoint, CheckpointError, FrontierEntry,
};
pub use compact::{
apply_retention, as_of_from_ops, compact_and_truncate, is_tombstone, plan_compaction, AckTable,
CompactError, CompactionOutcome, CompactionPlan, RetentionPolicy, RetentionReport,
RetentionRule, RUNS_MAX_AGE_MS, RUNS_MAX_PER_AGENT,
};
pub use conversation::{Role, Turn, DEFAULT_CONVERSATION};
pub use crypto::{
derive_key, encryption_audience, CryptoError, DerivedKeyProvider, Envelope, LocalKeyCipher,
PayloadCipher, SyncKeyProvider, ALG_CHACHA20POLY1305,
};
pub use fence::{check_dispatch, FenceDecision};
pub use fold::{
fold, fold_onto, hlc_version, registry_as_lww, state_hash, FoldTier, FoldedRecord, IntentAgent,
SyncState,
};
pub use journal::{OplogJournal, TruncationMarker};
pub use lease::{
InMemoryLeaseCoordinator, Intent, IntentStatus, Lease, LeaseCoordinator, LeaseError,
};
pub use net_relay::{
LeaseWire, LoopbackTransport, NetworkLeaseCoordinator, NetworkRelay, SyncTransport,
TransportError,
};
pub use oplog::{
canonical_json, logical_clock, system_clock, verify_log, ChainError, DeviceLog, Hlc, HlcClock,
OpRecord, Scope, Surface, WallClock,
};
pub use partition::{
is_portable, policy_for, portable_domains, SurfacePolicy, SyncClass, SURFACE_POLICIES,
};
pub use relay::{
checkpoint_frontier, frontier_of, AckOutcome, DeviceStatus, Frontier, FsRelay, GcReport,
InMemoryRelay, PullResult, PushOutcome, Relay, RelayConfig, RelayError, RosterEntry,
};
pub use session::{PumpReport, SessionError, SyncSession};
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
fn two_device_ops() -> Vec<OpRecord> {
let mut a = DeviceLog::new("device-a");
let mut b = DeviceLog::new("device-b");
let mut ops = vec![
a.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "fact-1", "body": "the sky is blue"}),
),
a.append(
Scope::Personal,
Surface::Declagent,
json!({"id": "agent-1", "name": "milo", "rev": "a1"}),
),
b.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "fact-2", "body": "water is wet"}),
),
];
for op in &ops {
b.observe(&op.hlc);
}
ops.push(b.append(
Scope::Personal,
Surface::Declagent,
json!({"id": "agent-1", "name": "milo", "rev": "b2"}),
));
ops.push(a.append(
Scope::Personal,
Surface::Conversation,
json!({"speaker": "user", "text": "hi", "timestamp": 1}),
));
ops
}
fn permutations<T: Clone>(items: &[T]) -> Vec<Vec<T>> {
fn heap<T: Clone>(k: usize, arr: &mut Vec<T>, out: &mut Vec<Vec<T>>) {
if k == 1 {
out.push(arr.clone());
return;
}
for i in 0..k {
heap(k - 1, arr, out);
if k.is_multiple_of(2) {
arr.swap(i, k - 1);
} else {
arr.swap(0, k - 1);
}
}
}
let mut arr = items.to_vec();
let mut out = Vec::new();
heap(arr.len(), &mut arr, &mut out);
out
}
#[test]
fn fold_is_permutation_invariant() {
let ops = two_device_ops();
let baseline = fold(&ops);
let baseline_hash = state_hash(&baseline);
for perm in permutations(&ops) {
let folded = fold(&perm);
assert_eq!(folded, baseline, "fold must be order-independent");
assert_eq!(state_hash(&folded), baseline_hash);
}
}
#[test]
fn fold_is_idempotent_over_duplicated_ops() {
let ops = two_device_ops();
let mut doubled = ops.clone();
doubled.extend(ops.iter().cloned());
assert_eq!(fold(&doubled), fold(&ops));
assert_eq!(fold(&ops), fold(&ops));
}
#[test]
fn divergent_replica_union_matches_crdt_merge() {
let ops = two_device_ops();
let a_ops: Vec<OpRecord> = ops
.iter()
.filter(|o| o.device_id == "device-a")
.cloned()
.collect();
let b_ops: Vec<OpRecord> = ops
.iter()
.filter(|o| o.device_id == "device-b")
.cloned()
.collect();
let union_lww = registry_as_lww(&fold(&ops), &Surface::Declagent.tag());
let a_lww = registry_as_lww(&fold(&a_ops), &Surface::Declagent.tag());
let b_lww = registry_as_lww(&fold(&b_ops), &Surface::Declagent.tag());
let merged_ab = car_state::crdt::merge_maps(&a_lww, &b_lww);
let merged_ba = car_state::crdt::merge_maps(&b_lww, &a_lww);
assert_eq!(merged_ab, union_lww, "fold(union) == crdt_merge(exports)");
assert_eq!(merged_ba, union_lww, "in either merge order");
assert_eq!(union_lww["id:agent-1"].value["rev"], json!("b2"));
assert_eq!(union_lww["id:agent-1"].replica, "device-b");
}
#[test]
fn journal_round_trip_load_fold_verify() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("oplog.jsonl");
let ops = two_device_ops();
{
let mut journal = OplogJournal::open(&path).unwrap();
for op in &ops {
journal.append(op).unwrap();
}
}
let loaded = OplogJournal::load(&path).unwrap();
assert_eq!(loaded, ops);
verify_log(&loaded).expect("loaded log must chain-verify");
assert_eq!(state_hash(&fold(&loaded)), state_hash(&fold(&ops)));
}
fn all_surface_ops() -> (Vec<OpRecord>, usize) {
let mut a = DeviceLog::new("dev-a");
let mut b = DeviceLog::new("dev-b");
let mut ops = vec![
a.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "f1", "timestamp": 10}),
),
a.append(Scope::Personal, Surface::Skill, json!({"id": "s1"})),
a.append(
Scope::Personal,
Surface::Conversation,
json!({"speaker": "u", "text": "hi", "timestamp": 11}),
),
a.append(
Scope::Personal,
Surface::Run,
json!({"id": "r1", "agent_id": "milo", "timestamp": 12}),
),
a.append(
Scope::Personal,
Surface::Trajectory,
json!({"id": "t1", "timestamp": 13}),
),
a.append(
Scope::Personal,
Surface::Declagent,
json!({"id": "agent-1", "rev": "a"}),
),
a.append(
Scope::Shared { org: "acme".into() },
Surface::Registry {
kind: "agents".into(),
},
json!({"id": "reg-1", "v": 1}),
),
a.append(Scope::Personal, Surface::Routing, json!({"sample": 1.0})),
a.append(Scope::Personal, Surface::Routing, json!({"sample": 1.0})), ];
for op in &ops {
b.observe(&op.hlc);
}
ops.push(b.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "f2", "timestamp": 20}),
));
let split = ops.len();
ops.push(b.append(
Scope::Personal,
Surface::Conversation,
json!({"speaker": "a", "text": "yo", "timestamp": 21}),
));
ops.push(b.append(
Scope::Personal,
Surface::Declagent,
json!({"id": "agent-1", "rev": "b"}),
)); ops.push(b.append(Scope::Personal, Surface::Routing, json!({"sample": 0.0})));
ops.push(b.append(
Scope::Personal,
Surface::Run,
json!({"id": "r2", "agent_id": "milo", "timestamp": 22}),
));
for op in &ops[split..] {
a.observe(&op.hlc);
}
ops.push(a.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "f1", "timestamp": 99}),
)); (ops, split)
}
fn acks_at(ops: &[OpRecord], split: usize) -> AckTable {
let frontier = ops[..split].iter().map(|o| o.hlc.clone()).max().unwrap();
let mut acks = AckTable::new();
for op in ops {
acks.ack(op.device_id.clone(), frontier.clone());
}
acks
}
#[test]
fn compaction_equivalence_fold_full_equals_checkpoint_plus_tail() {
let (ops, split) = all_surface_ops();
let acks = acks_at(&ops, split);
let plan = plan_compaction(&ops, &acks, &RetentionPolicy::keep_all(), None).unwrap();
assert_eq!(plan.dropped_ops, split);
assert_eq!(plan.retained_ops.len(), ops.len() - split);
let full = fold(&ops);
let reconstructed = fold_onto(&plan.checkpoint.state, &plan.retained_ops);
assert_eq!(reconstructed, full);
assert_eq!(state_hash(&reconstructed), state_hash(&full));
assert_eq!(
reconstructed.registries[&Surface::Declagent.tag()]["id:agent-1"].payload["rev"],
json!("b"),
"LWW: the tail's later write wins over the checkpointed one"
);
assert_eq!(
reconstructed.logs[&Surface::Knowledge.tag()]["id:f1"].payload["timestamp"],
json!(10),
"grow-only: the checkpointed earliest writer keeps the slot"
);
assert_eq!(
reconstructed.log_entries(&Surface::Routing.tag()).len(),
3,
"multiset: 2 checkpointed observations (incl. the repeat) + 1 tail"
);
let ema =
|s: f64, rec: &FoldedRecord| 0.7 * s + 0.3 * rec.payload["sample"].as_f64().unwrap();
assert_eq!(
reconstructed.replay(&Surface::Routing.tag(), 0.5_f64, ema),
full.replay(&Surface::Routing.tag(), 0.5_f64, ema),
"order-sensitive replay agrees across the compaction"
);
verify_anchored(&plan.checkpoint, &plan.retained_ops).unwrap();
}
#[test]
fn retention_coherence_local_compaction_equals_global() {
let (ops, split) = all_surface_ops();
let acks = acks_at(&ops, split);
let policy = RetentionPolicy::proposal_default(1, u64::MAX);
let as_of = 1_000u64;
let plan = plan_compaction(&ops, &acks, &policy, Some(as_of)).unwrap();
assert_eq!(
plan.as_of_ms, as_of,
"explicit as_of wins over the derived default"
);
let (global, _) = apply_retention(&fold(&ops), &policy, as_of).unwrap();
let (local, _) = apply_retention(
&fold_onto(&plan.checkpoint.state, &plan.retained_ops),
&policy,
as_of,
)
.unwrap();
assert_eq!(local, global);
assert_eq!(state_hash(&local), state_hash(&global));
assert_eq!(
plan.checkpoint.state.logs[&Surface::Conversation.tag()].len(),
1
);
}
#[test]
fn retention_coherence_survives_cross_frontier_supersedes() {
let mut a = DeviceLog::new("a");
let mut b = DeviceLog::new("b");
let mut ops = vec![
a.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "f1", "timestamp": 1}),
),
a.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "f2", "timestamp": 2}),
),
];
let split = ops.len();
for op in &ops {
b.observe(&op.hlc);
}
ops.push(b.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "f3", "timestamp": 3, "supersedes": "f1"}),
));
let acks = acks_at(&ops, split);
let mut policy = RetentionPolicy::keep_all();
policy
.rules
.insert("knowledge".to_string(), RetentionRule::LastN { n: 1 });
let plan = plan_compaction(&ops, &acks, &policy, Some(10)).unwrap();
assert_eq!(plan.dropped_ops, split);
let tag = Surface::Knowledge.tag();
assert!(is_tombstone(&plan.checkpoint.state.logs[&tag]["id:f1"]));
let (global, _) = apply_retention(&fold(&ops), &policy, 10).unwrap();
let (local, _) = apply_retention(
&fold_onto(&plan.checkpoint.state, &plan.retained_ops),
&policy,
10,
)
.unwrap();
assert_eq!(
local, global,
"no divergence despite the cross-frontier supersedes"
);
assert_eq!(state_hash(&local), state_hash(&global));
assert_eq!(
global.logs[&tag]["id:f3"].payload["supersedes"],
json!("f1")
);
assert!(is_tombstone(&global.logs[&tag]["id:f1"]));
assert!(is_tombstone(&local.logs[&tag]["id:f1"]));
}
#[test]
fn crash_ordering_checkpoint_durable_first_then_truncate() {
let dir = tempfile::tempdir().unwrap();
let journal_path = dir.path().join("oplog.jsonl");
let ckpt_dir = dir.path().join("checkpoints");
let (ops, split) = all_surface_ops();
let acks = acks_at(&ops, split);
let policy = RetentionPolicy::keep_all();
{
let mut journal = OplogJournal::open(&journal_path).unwrap();
for op in &ops {
journal.append(op).unwrap();
}
let plan = plan_compaction(
&OplogJournal::load(&journal_path).unwrap(),
&acks,
&policy,
None,
)
.unwrap();
let ckpt_path = plan.checkpoint.save(&ckpt_dir).unwrap();
let survived = OplogJournal::load(&journal_path).unwrap();
assert_eq!(survived, ops, "journal intact after crash-before-truncate");
let ckpt = Checkpoint::load(&ckpt_path).unwrap();
assert_eq!(fold_onto(&ckpt.state, &plan.retained_ops), fold(&ops));
}
let mut journal = OplogJournal::open(&journal_path).unwrap();
let outcome = compact_and_truncate(&mut journal, &ckpt_dir, &acks, &policy, None).unwrap();
assert_eq!(outcome.plan.dropped_ops, split);
assert!(
OplogJournal::load(&journal_path).is_err(),
"naive load is fenced"
);
let (marker, tail) = OplogJournal::load_with_marker(&journal_path).unwrap();
assert_eq!(
marker.unwrap().checkpoint_hash,
outcome.plan.checkpoint.checkpoint_hash,
"marker names the covering checkpoint"
);
assert_eq!(tail, ops[split..].to_vec());
verify_log(&tail).expect("truncated journal verifies on its own (anchored non-zero start)");
let ckpt = Checkpoint::load(&outcome.checkpoint_path.unwrap()).unwrap();
verify_anchored(&ckpt, &tail).unwrap();
assert_eq!(
fold_onto(&ckpt.state, &tail),
fold(&ops),
"nothing acknowledged was lost"
);
let count = std::fs::read_dir(&ckpt_dir).unwrap().count();
assert_eq!(count, 1);
}
#[test]
fn truncated_journal_resumes_and_keeps_verifying_end_to_end() {
let dir = tempfile::tempdir().unwrap();
let journal_path = dir.path().join("oplog.jsonl");
let ckpt_dir = dir.path().join("checkpoints");
let (ops, split) = all_surface_ops();
let acks = acks_at(&ops, split);
let mut journal = OplogJournal::open(&journal_path).unwrap();
for op in &ops {
journal.append(op).unwrap();
}
let outcome = compact_and_truncate(
&mut journal,
&ckpt_dir,
&acks,
&RetentionPolicy::keep_all(),
None,
)
.unwrap();
let ckpt = Checkpoint::load(&outcome.checkpoint_path.unwrap()).unwrap();
let (_, tail) = OplogJournal::load_with_marker(&journal_path).unwrap();
assert!(matches!(
DeviceLog::resume("dev-a", &tail),
Err(ChainError::TruncatedChain { .. })
));
let mut dev_a = resume_anchored("dev-a", &ckpt, &tail).unwrap();
let next = dev_a.append(Scope::Personal, Surface::Knowledge, json!({"id": "f-new"}));
journal.append(&next).unwrap();
let (marker, reloaded) = OplogJournal::load_with_marker(&journal_path).unwrap();
assert!(marker.is_some(), "marker survives post-truncation appends");
verify_anchored(&ckpt, &reloaded).expect("checkpoint anchors the growing truncated log");
let full_plus = {
let mut v = ops.clone();
v.push(next);
v
};
assert_eq!(fold_onto(&ckpt.state, &reloaded), fold(&full_plus));
}
use crate::session::SyncSession;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
fn manual_clock() -> (Arc<AtomicU64>, WallClock) {
let t = Arc::new(AtomicU64::new(0));
let reader = t.clone();
(t, Arc::new(move || reader.load(Ordering::SeqCst)))
}
fn session(device: &str, root: &std::path::Path, wall: WallClock) -> SyncSession {
SyncSession::open(
device,
&root.join(device).join("oplog.jsonl"),
&root.join(device).join("checkpoints"),
wall,
)
.unwrap()
}
#[test]
fn two_macs_converge_through_the_filesystem_loopback_relay() {
let tmp = tempfile::tempdir().unwrap();
let relay_dir = tmp.path().join("shared-relay");
let (ta, wall_a) = manual_clock();
let (tb, wall_b) = manual_clock();
let (tr, wall_r) = manual_clock();
ta.store(1_000, Ordering::SeqCst);
tb.store(940, Ordering::SeqCst); tr.store(970, Ordering::SeqCst);
let mut relay_a =
FsRelay::open(&relay_dir, RelayConfig::default(), wall_r.clone()).unwrap();
let mut relay_b = FsRelay::open(&relay_dir, RelayConfig::default(), wall_r).unwrap();
let mut a = session("mac-a", tmp.path(), wall_a);
let mut b = session("mac-b", tmp.path(), wall_b);
a.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "f1", "v": 1}),
)
.unwrap();
a.append(
Scope::Personal,
Surface::Declagent,
json!({"id": "milo", "owner": "a"}),
)
.unwrap();
b.append(Scope::Personal, Surface::Routing, json!({"sample": 1.0}))
.unwrap();
b.append(
Scope::Personal,
Surface::Conversation,
json!({"speaker": "u", "text": "hi", "timestamp": 5}),
)
.unwrap();
a.pump(&mut relay_a).unwrap();
b.pump(&mut relay_b).unwrap();
b.append(
Scope::Personal,
Surface::Declagent,
json!({"id": "milo", "owner": "b"}),
)
.unwrap();
b.pump(&mut relay_b).unwrap();
a.pump(&mut relay_a).unwrap();
assert_eq!(a.state_hash(), b.state_hash());
assert_eq!(
a.state().registries[&Surface::Declagent.tag()]["id:milo"].payload["owner"],
json!("b"),
"causality beats wall-clock skew"
);
verify_log(a.ops()).unwrap();
verify_log(b.ops()).unwrap();
}
#[test]
fn straggler_eviction_and_lossless_cold_reentry() {
let tmp = tempfile::tempdir().unwrap();
let (t, wall) = manual_clock();
let mut relay = InMemoryRelay::new(
RelayConfig {
eviction_horizon_ms: Some(1_000),
},
wall.clone(),
);
let mut a = session("dev-a", tmp.path(), wall.clone());
let mut b = session("dev-b", tmp.path(), wall.clone());
let mut c = session("dev-c", tmp.path(), wall.clone());
t.store(100, Ordering::SeqCst);
a.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "a1", "timestamp": 100}),
)
.unwrap();
c.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "c1", "timestamp": 100}),
)
.unwrap();
a.pump(&mut relay).unwrap();
c.pump(&mut relay).unwrap();
b.pump(&mut relay).unwrap();
a.pump(&mut relay).unwrap();
c.pump(&mut relay).unwrap();
assert_eq!(a.state_hash(), c.state_hash());
t.store(500, Ordering::SeqCst);
let unpushed = c
.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "c-dark", "timestamp": 500}),
)
.unwrap();
t.store(800, Ordering::SeqCst);
a.append(
Scope::Personal,
Surface::Knowledge,
json!({"id": "a2", "timestamp": 800}),
)
.unwrap();
a.pump(&mut relay).unwrap();
b.pump(&mut relay).unwrap();
a.pump(&mut relay).unwrap();
let pinned = relay.stable_frontier().unwrap().unwrap();
t.store(2_000, Ordering::SeqCst);
a.pump(&mut relay).unwrap();
b.pump(&mut relay).unwrap();
let roster: std::collections::BTreeMap<String, RosterEntry> = relay
.roster()
.unwrap()
.into_iter()
.map(|e| (e.device_id.clone(), e))
.collect();
assert_eq!(roster["dev-c"].status, DeviceStatus::Evicted);
let unpinned = relay.stable_frontier().unwrap().unwrap();
assert!(
unpinned > pinned,
"the evicted device's ack no longer holds the frontier"
);
assert_eq!(
relay.gc().unwrap().total(),
0,
"no covering checkpoint → no GC"
);
let ckpt = a.publish_checkpoint(&mut relay).unwrap().unwrap();
let report = relay.gc().unwrap();
assert!(report.total() > 0, "covered + below-frontier ops now drop");
let mut since = Frontier::new();
for (device, entry) in &ckpt.frontier {
since.insert(device.clone(), entry.seq);
}
for op in relay.pull("dev-a", &since).unwrap().ops {
assert!(
op.hlc > unpinned
|| ckpt
.frontier
.get(&op.device_id)
.is_none_or(|e| op.seq > e.seq)
);
}
t.store(3_000, Ordering::SeqCst);
let err = c.pump(&mut relay).unwrap_err();
assert!(
matches!(
err,
SessionError::Relay(RelayError::FrontierTruncated { .. })
),
"got {err:?}"
);
assert!(
relay
.pull("dev-a", &{
let mut f = since.clone();
f.insert("dev-c".to_string(), 0);
f
})
.unwrap()
.ops
.iter()
.any(|op| op.op_id == unpushed.op_id),
"the failed pump's push half already landed the unpushed op"
);
assert!(c.rebase(&mut relay).unwrap());
assert_eq!(c.base().unwrap().checkpoint_hash, ckpt.checkpoint_hash);
assert!(
c.ops().iter().any(|op| op.op_id == unpushed.op_id),
"the straggler's unpushed write survives cold re-entry"
);
let c_journal = tmp.path().join("dev-c").join("oplog.jsonl");
assert!(
OplogJournal::load(&c_journal).is_err(),
"truncation marker fences load()"
);
let report = c.pump(&mut relay).unwrap();
assert_eq!(
(report.pushed, report.push_deduped),
(0, 1),
"the unpushed op reached the relay exactly once"
);
let roster: std::collections::BTreeMap<String, RosterEntry> = relay
.roster()
.unwrap()
.into_iter()
.map(|e| (e.device_id.clone(), e))
.collect();
assert_eq!(
roster["dev-c"].status,
DeviceStatus::Active,
"caught-up ack reinstates"
);
assert!(unpushed.hlc < relay.stable_frontier().unwrap().unwrap());
assert_eq!(
relay.gc().unwrap().total(),
0,
"late op is safe until a checkpoint covers it"
);
a.pump(&mut relay).unwrap();
b.pump(&mut relay).unwrap();
assert_eq!(a.state_hash(), b.state_hash());
assert_eq!(a.state_hash(), c.state_hash());
assert!(a.state().logs[&Surface::Knowledge.tag()].contains_key("id:c-dark"));
verify_log(a.ops()).unwrap();
verify_log(b.ops()).unwrap();
verify_anchored(c.base().unwrap(), c.ops()).unwrap();
}
#[test]
fn replay_over_permuted_opsets_is_deterministic() {
let mut a = DeviceLog::new("dev-a");
let mut b = DeviceLog::new("dev-b");
let mut ops = vec![
a.append(Scope::Personal, Surface::Routing, json!({"sample": 1.0})),
a.append(Scope::Personal, Surface::Routing, json!({"sample": 0.0})),
];
for op in &ops {
b.observe(&op.hlc);
}
ops.push(b.append(Scope::Personal, Surface::Routing, json!({"sample": 1.0})));
let ema = |state: f64, rec: &FoldedRecord| {
0.7 * state + 0.3 * rec.payload["sample"].as_f64().unwrap()
};
let folded = fold(&ops);
assert_eq!(folded.log_entries(&Surface::Routing.tag()).len(), 3);
let baseline = folded.replay(&Surface::Routing.tag(), 0.5_f64, ema);
assert!((baseline - 0.6185).abs() < 1e-12, "got {baseline}");
for perm in permutations(&ops) {
assert_eq!(
fold(&perm).replay(&Surface::Routing.tag(), 0.5_f64, ema),
baseline
);
}
}
}