//! # rutster-sim — the self-hostable benchmark + simulation harness //! //! **Status:** spearhead step 4½ (ADR-0010). The wedge's measurement surface. //! //! This crate drives synthetic callers through the SAME media-leg path real //! callers use, measures p50/p99 mouth-to-ear latency + barge-in kill-time //! against slice-4's ≤60 ms kill budget, and runs the same measurements at //! 1 / 10 / 50 concurrent calls. A separate CI job //! (`cargo test --all --features=sim-bench`) asserts thresholds per commit; //! a latency regression fails the build (ADR-0010). //! //! # Why this crate exists (the FOB differentiator) //! //! Slice-4 ships a reflex loop + a synthetic e2e test. SIM-BENCH is the //! artifact that turns arithmetic latency claims into CI-regressed //! measurement. See //! [`docs/superpowers/specs/2026-07-05-slice-4-half-benchmark-sim-design.md`] //! for the design. //! //! # Why a separate crate (not in-tree tests) //! //! The harness is hot-path-adjacent + differentiating (ADR-0008 FOB) — it //! earns cratehood the same way `rutster-tap` did. The dep direction is //! clean: `rutster-sim` → `rutster-media` + `rutster`. The harness //! consumes types; it doesn't ride on the binary's internal plumbing. //! //! # Module map (lands across S1-S7) //! //! - [`scenario`] (S1) — `Scenario` + `ScenarioStep` TOML-deserializable //! scripted-caller data types. Determinism is the point. //! - [`sim_audio_pipe`] (S2) — `SimAudioPipe: AudioPipe` test-double that //! IS the caller; captures both clocks (`Instant::now()` at onset + //! receipt). The measurement boundary (spec §2.2). //! - [`latency`] (S3) — `LatencyProbe`: post-hoc p50/p99 kill + mouth-to-ear //! computation from the `Capture` event stream. //! - [`runner`] (S4) — `SimCall` + `ScenarioRunner`: drives one synthetic //! caller end-to-end against the FOB reflex loop standalone in tokio //! (no `MediaThread` extension per S4 standalone-path conclusion). //! - [`concurrency`] (S5) — `ConcurrencyRunner`: N concurrent `SimCall`s //! against the same MockRealtimeBrain; aggregates per-call latencies //! into a `SweepReport`. //! - [`tick_lag`] (S6) — `TickLagGauge`: the ADR-0010 doctrine-drift //! detector. Surfaces `tick_overruns` / `last_tick_micros` in the //! `SweepReport`. //! - [`thresholds`] (S7) — Threshold consts + the `#[cfg(feature = //! "sim-bench")] #[tokio::test]` assertion tests. A latency regression //! fails the build. // All modules declared upfront so the lib.rs is stable across task // commits; each module file grows from a `//! stub` header to its full // impl as its task lands. Only the `pub use` re-exports for landed // modules are present — they grow as each task's symbols become available. pub mod concurrency; pub mod latency; pub mod runner; pub mod scenario; pub mod sim_audio_pipe; pub mod thresholds; pub mod tick_lag; pub use concurrency::{ConcurrencyRunner, PerConcurrencyReport, SweepReport}; pub use latency::LatencyProbe; pub use runner::{ScenarioRunner, SimCall}; pub use scenario::{Scenario, ScenarioError, ScenarioStep}; pub use sim_audio_pipe::{Capture, SimAudioPipe}; pub use thresholds::{ BARGE_IN_KILL_TIME_P99_MS, MOUTH_TO_EAR_P99_MS, SWEEP_CONCURRENCIES, TICK_LAG_MAX_MS, TICK_OVERRUN_PCT_MAX, }; pub use tick_lag::{TickLagGauge, TickLagStats};