use assert_cmd::Command;
use std::fs;
use std::path::Path;
use std::time::{Duration, Instant};
const MANIFEST: &str = r#"
version = 1
canonical = "json-schema-2020-12"
authoring = "zod"
[[contracts]]
name = "user"
source = "contracts/user.zod.ts"
emit = ["zod"]
[[mappings]]
glob = "app/api/**/*.ts"
contracts = ["user"]
require = "boundary-validation"
[gates]
protected_paths = ["pushkin.toml"]
"#;
const NONCONFORMING: &str = "export async function POST(req: Request) {\n\
const body = await req.json();\n\
return Response.json({ name: body.name });\n\
}\n";
const HANDLER_PATH: &str = "app/api/users/route.ts";
const SAMPLES: usize = 200;
const WARMUP: usize = 20;
const BUDGET_MS: f64 = 100.0;
const CONTROLLED_ENV: &str = "PUSHKIN_LATENCY_CONTROLLED";
fn controlled_environment() -> bool {
std::env::var(CONTROLLED_ENV).is_ok_and(|value| value == "1")
}
fn assert_budget(label: &str, dist: &Distribution) {
assert!(
dist.p50 < BUDGET_MS,
"{label} p50 {:.1}ms exceeds the {BUDGET_MS}ms budget \
(spec §8.1; charter §C.3 — p50 is the regression tripwire)",
dist.p50
);
if controlled_environment() {
assert!(
dist.p95 < BUDGET_MS,
"{label} p95 {:.1}ms exceeds the {BUDGET_MS}ms budget in a \
CONTROLLED environment (spec §8.1; charter §C.3 phase-exit gate)",
dist.p95
);
}
}
fn payload() -> String {
serde_json::json!({
"session_id": "bench-session",
"tool_name": "Write",
"tool_input": { "file_path": HANDLER_PATH, "content": NONCONFORMING }
})
.to_string()
}
fn hook_once(dir: &Path) -> Result<Duration, String> {
let mut command = Command::cargo_bin("pushkin").map_err(|e| format!("binary resolves: {e}"))?;
let started = Instant::now();
let output = command
.current_dir(dir)
.args(["hook", "claude"])
.write_stdin(payload())
.output()
.map_err(|e| format!("hook run: {e}"))?;
let elapsed = started.elapsed();
if output.status.code() != Some(0) {
return Err(format!("hook exited {:?}", output.status.code()));
}
Ok(elapsed)
}
struct Distribution {
n: usize,
p50: f64,
p95: f64,
p99: f64,
max: f64,
over_budget: Vec<usize>,
}
fn summarize(samples_ms: &[f64]) -> Distribution {
let over_budget = samples_ms
.iter()
.enumerate()
.filter(|(_, ms)| **ms > BUDGET_MS)
.map(|(index, _)| index)
.collect();
let mut sorted = samples_ms.to_vec();
sorted.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
let n = sorted.len();
Distribution {
n,
p50: sorted[n / 2],
p95: sorted[(n * 95).div_ceil(100) - 1],
p99: sorted[(n * 99).div_ceil(100) - 1],
max: sorted[n - 1],
over_budget,
}
}
fn report(label: &str, dist: &Distribution) {
let line = format!(
"{label}: n={} p50={:.1}ms p95={:.1}ms p99={:.1}ms max={:.1}ms \
over_{BUDGET_MS:.0}ms={} indices={:?}",
dist.n,
dist.p50,
dist.p95,
dist.p99,
dist.max,
dist.over_budget.len(),
dist.over_budget,
);
println!("{line}");
let trend = Path::new(env!("CARGO_TARGET_TMPDIR")).join("latency-trend.tsv");
if let Ok(mut file) = fs::OpenOptions::new().create(true).append(true).open(trend) {
use std::io::Write as _;
let _ = writeln!(file, "{line}");
}
}
fn start_daemon(dir: &Path) -> Result<(), String> {
let mut command = Command::cargo_bin("pushkin").map_err(|e| format!("binary resolves: {e}"))?;
let output = command
.current_dir(dir)
.args(["daemon", "start"])
.output()
.map_err(|e| format!("daemon start: {e}"))?;
if output.status.code() != Some(0) {
return Err(format!(
"daemon start failed: {}",
String::from_utf8_lossy(&output.stderr)
));
}
Ok(())
}
fn stop_daemon(dir: &Path) {
let _ = Command::cargo_bin("pushkin")
.map(|mut command| command.current_dir(dir).args(["daemon", "stop"]).output());
}
#[test]
#[ignore = "latency gate: run release-mode in CI (--ignored)"]
fn bench_warm_per_file_check_under_100ms() {
let dir = tempfile::tempdir().unwrap();
fs::write(dir.path().join("pushkin.toml"), MANIFEST).unwrap();
start_daemon(dir.path()).unwrap();
for _ in 0..WARMUP {
hook_once(dir.path()).unwrap();
}
let samples_ms: Vec<f64> = (0..SAMPLES)
.map(|_| hook_once(dir.path()).unwrap().as_secs_f64() * 1000.0)
.collect();
let dist = summarize(&samples_ms);
report("warm hook round trip", &dist);
stop_daemon(dir.path());
assert_budget("warm per-file check", &dist);
}
fn bash_payload() -> String {
serde_json::json!({
"session_id": "bench-session",
"tool_name": "Bash",
"tool_input": { "command": "ls -la" }
})
.to_string()
}
fn bash_hook_once(dir: &Path) -> Result<Duration, String> {
let mut command = Command::cargo_bin("pushkin").map_err(|e| format!("binary resolves: {e}"))?;
let started = Instant::now();
let output = command
.current_dir(dir)
.args(["hook", "claude"])
.write_stdin(bash_payload())
.output()
.map_err(|e| format!("hook run: {e}"))?;
let elapsed = started.elapsed();
if output.status.code() != Some(0) {
return Err(format!("hook exited {:?}", output.status.code()));
}
Ok(elapsed)
}
#[test]
#[ignore = "latency gate: run release-mode in CI (--ignored)"]
fn bench_bash_matcher_entry_under_100ms() {
let dir = tempfile::tempdir().unwrap();
fs::write(
dir.path().join("pushkin.toml"),
format!("{MANIFEST}retrieval_paths = [\"crates/**/*.rs\"]\n"),
)
.unwrap();
start_daemon(dir.path()).unwrap();
for _ in 0..WARMUP {
bash_hook_once(dir.path()).unwrap();
}
let samples_ms: Vec<f64> = (0..SAMPLES)
.map(|_| bash_hook_once(dir.path()).unwrap().as_secs_f64() * 1000.0)
.collect();
let dist = summarize(&samples_ms);
report("bash matcher entry", &dist);
stop_daemon(dir.path());
assert_budget("bash matcher entry", &dist);
}