use futures_util::future::BoxFuture;
use hotl_engine::{EngineConfig, Outcome};
use hotl_provider::ScriptedProvider;
use hotl_testkit::Harness;
use hotl_tools::{Permission, Registry, Tool, ToolOutcome};
use serde_json::json;
use tokio_util::sync::CancellationToken;
const TOOL_ROUND_TRIPS: usize = 20;
const TRIAL_COUNT: usize = 15;
const TEETH_CHECK_TRIALS: usize = 5;
const REGRESSION_BAND_MULTIPLIER: u64 = 3;
const NOISE_FLOOR_P50_NS: u64 = 200_000; const NOISE_FLOOR_P99_NS: u64 = 1_000_000;
const ADVISORY_P50_NS: u64 = 300_000; const ADVISORY_P99_NS: u64 = 2_000_000;
static MEASUREMENT: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(());
fn baseline_path() -> std::path::PathBuf {
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("loop-baseline.json")
}
fn read_baseline() -> (u64, u64) {
let raw = std::fs::read_to_string(baseline_path()).unwrap_or_else(|e| {
panic!(
"no committed baseline at {:?} ({e}); generate one with \
`HOTL_UPDATE_LOOP_BASELINE=1 cargo test -p hotl-testkit --test loop_overhead`",
baseline_path()
)
});
let v: serde_json::Value = serde_json::from_str(&raw).expect("parse loop-baseline.json");
let p50 = v["overhead_p50_ns"].as_u64().expect("overhead_p50_ns");
let p99 = v["overhead_p99_ns"].as_u64().expect("overhead_p99_ns");
(p50, p99)
}
fn write_baseline(p50_ns: u64, p99_ns: u64) {
let v = json!({
"overhead_p50_ns": p50_ns,
"overhead_p99_ns": p99_ns,
});
let text = serde_json::to_string_pretty(&v).expect("serialize baseline");
std::fs::write(baseline_path(), format!("{text}\n")).expect("write loop-baseline.json");
}
fn advisory_status(measured: u64, budget: u64) -> &'static str {
if measured <= budget {
"PASS"
} else {
"EXCEED"
}
}
fn median(values: &mut [u64]) -> u64 {
assert!(!values.is_empty(), "median of zero trials is undefined");
values.sort_unstable();
values[values.len() / 2]
}
fn exceeds_band(measured: u64, baseline: u64, multiplier: u64, floor: u64) -> bool {
let over_band = measured > baseline.saturating_mul(multiplier);
let regression = measured.saturating_sub(baseline);
over_band && regression >= floor
}
struct NoOpTool;
impl Tool for NoOpTool {
fn name(&self) -> &'static str {
"noop"
}
fn description(&self) -> &str {
"does nothing; exists to isolate loop overhead from tool work"
}
fn schema(&self) -> serde_json::Value {
json!({"type": "object"})
}
fn permission(&self, _input: &serde_json::Value) -> Permission {
Permission::None
}
fn read_only(&self) -> bool {
true
}
fn parallel_safe(&self) -> bool {
true
}
fn run<'a>(
&'a self,
_input: serde_json::Value,
_cancel: CancellationToken,
) -> BoxFuture<'a, ToolOutcome> {
Box::pin(async { ToolOutcome::ok("") })
}
}
fn registry() -> Registry {
let mut reg = Registry::builtin();
reg.register(Box::new(NoOpTool));
reg
}
async fn run_scenario(use_seam: bool) -> (u64, u64) {
let mut scripts: Vec<_> = (0..TOOL_ROUND_TRIPS)
.map(|i| ScriptedProvider::tool_call(&format!("t{i}"), "noop", json!({})))
.collect();
scripts.push(ScriptedProvider::text_reply("done"));
let config = EngineConfig {
max_turns: TOOL_ROUND_TRIPS as i64 + 5,
..Default::default()
};
let mut h = if use_seam {
Harness::with_registry_sync_noop(scripts, config, registry())
} else {
Harness::with_registry(scripts, config, registry())
};
let outcome = h.prompt_and_wait("drive several no-op rounds").await;
assert!(
matches!(outcome, Outcome::Done { .. }),
"scenario must finish clean: {outcome:?}"
);
assert_eq!(h.ledger_reports.len(), 1, "one turn, one flush");
let report = &h.ledger_reports[0];
assert_eq!(
report.sample_count,
TOOL_ROUND_TRIPS + 1,
"every scripted sample must be reflected in the ledger"
);
(report.overhead_p50_ns, report.overhead_p99_ns)
}
#[tokio::test]
async fn loop_overhead_stays_within_the_regression_band() {
let _measuring = MEASUREMENT.lock().await;
let mut p50s = Vec::with_capacity(TRIAL_COUNT);
let mut p99s = Vec::with_capacity(TRIAL_COUNT);
for _ in 0..TRIAL_COUNT {
let (p50, p99) = run_scenario(true).await;
p50s.push(p50);
p99s.push(p99);
}
let median_p50 = median(&mut p50s);
let median_p99 = median(&mut p99s);
println!(
"loop overhead (median of {TRIAL_COUNT} trials): \
p50={median_p50}ns (advisory {ADVISORY_P50_NS}ns: {}), \
p99={median_p99}ns (advisory {ADVISORY_P99_NS}ns: {})",
advisory_status(median_p50, ADVISORY_P50_NS),
advisory_status(median_p99, ADVISORY_P99_NS),
);
if std::env::var_os("HOTL_UPDATE_LOOP_BASELINE").is_some() {
write_baseline(median_p50, median_p99);
println!(
"HOTL_UPDATE_LOOP_BASELINE=1: wrote {:?} (median of {TRIAL_COUNT} trials: \
p50={median_p50}ns p99={median_p99}ns)",
baseline_path()
);
return;
}
let (baseline_p50, baseline_p99) = read_baseline();
assert!(
!exceeds_band(
median_p50,
baseline_p50,
REGRESSION_BAND_MULTIPLIER,
NOISE_FLOOR_P50_NS
),
"p50 loop overhead regressed: median-of-{TRIAL_COUNT}-trials={median_p50}ns \
baseline={baseline_p50}ns (exceeds {REGRESSION_BAND_MULTIPLIER}x baseline AND \
the {NOISE_FLOOR_P50_NS}ns floor)"
);
assert!(
!exceeds_band(
median_p99,
baseline_p99,
REGRESSION_BAND_MULTIPLIER,
NOISE_FLOOR_P99_NS
),
"p99 loop overhead regressed: median-of-{TRIAL_COUNT}-trials={median_p99}ns \
baseline={baseline_p99}ns (exceeds {REGRESSION_BAND_MULTIPLIER}x baseline AND \
the {NOISE_FLOOR_P99_NS}ns floor)"
);
}
#[tokio::test]
async fn gate_would_catch_a_real_regression() {
let _measuring = MEASUREMENT.lock().await;
let mut p50s = Vec::with_capacity(TEETH_CHECK_TRIALS);
let mut p99s = Vec::with_capacity(TEETH_CHECK_TRIALS);
for _ in 0..TEETH_CHECK_TRIALS {
let (p50, p99) = run_scenario(false).await;
p50s.push(p50);
p99s.push(p99);
}
let median_p50 = median(&mut p50s);
let median_p99 = median(&mut p99s);
let (baseline_p50, baseline_p99) = read_baseline();
assert!(
exceeds_band(
median_p50,
baseline_p50,
REGRESSION_BAND_MULTIPLIER,
NOISE_FLOOR_P50_NS
),
"a real regression (sync-noop seam disabled) must trip the p50 gate: \
median-of-{TEETH_CHECK_TRIALS}-trials={median_p50}ns baseline={baseline_p50}ns"
);
assert!(
exceeds_band(
median_p99,
baseline_p99,
REGRESSION_BAND_MULTIPLIER,
NOISE_FLOOR_P99_NS
),
"a real regression (sync-noop seam disabled) must trip the p99 gate: \
median-of-{TEETH_CHECK_TRIALS}-trials={median_p99}ns baseline={baseline_p99}ns"
);
}