Files
rutster/crates/rutster-sim/src/thresholds.rs
Aaron D. Lee b248565bce feat(sim): rutster-sim crate skeleton + Scenario/ScenarioStep types (slice-4½ S1)
The critical-path foundation for the benchmark + simulation harness.
Scenario is a TOML-deserializable scripted-caller data type; ScenarioStep
covers speak_loud / speak_quiet / pause / await_reply / end. Determinism is
the point -- reproducible thresholds in CI (ADR-0010). All other sim
modules land as stubs here + fill in across S2-S7. Threshold consts
(BARGE_IN_KILL_TIME_P99_MS = 80.0, MOUTH_TO_EAR_P99_MS = 700.0,
TICK_LAG_MAX_MS = 10.0, TICK_OVERRUN_PCT_MAX = 1.0, SWEEP_CONCURRENCIES =
[1,10,50]) land now per the plan's S1 step 2 note (used by S5/S6/S7 wiring).

Adds toml = 0.8 to workspace.dependencies (the first consumer; spec §1.1
claim of pre-existing membership was inaccurate).

Task S1 of slice-4½ -- everything else depends on this landing.

Signed-off-by: Aaron D. Lee <himself@adlee.work>
2026-07-05 12:19:12 -04:00

59 lines
2.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! # thresholds — CI-regressed latency thresholds + sim-bench assertion tests
//!
//! See `docs/superpowers/specs/2026-07-05-slice-4-half-benchmark-sim-design.md`
//! §5.1 + §5.5.
//!
//! The threshold consts land here at S1 (per the plan's S1 step 2 note:
//! "the consts as immediate module-level `pub const` items per spec §5.1 —
//! they're used by S5/S6/S7 wiring"). The `#[cfg(feature = "sim-bench")]
//! #[tokio::test]` assertion tests land at S7.
//!
//! # Why these numbers
//!
//! See spec §5.1 for the budget-vs-assertion-slack reasoning. Each const
//! is paired with a doc-comment explaining the budget it enforces + the
//! slack rationale (so a future maintainer who needs to bump one knows
//! *why* the current value is what it is, not just *what* it is).
/// Slice-4 spec §5.1 + §7 done-criteria #8: kill-time budget is
/// ≤60 ms (3 debounce frames × 20 ms tick + 1 tick to drain + apply).
/// Observer slack to make CI deterministic-but-not-flaky on a slow
/// runner: effective CI assertion ≤80 ms (60 ms budget + 20 ms slack).
///
/// A regression here is the red X ADR-0010 demands — the wedge's
/// "local real-time reflexes that don't need the brain" claim is
/// arithmetic until this assertion fires on every PR.
pub const BARGE_IN_KILL_TIME_P99_MS: f64 = 80.0;
/// Slice-1 + slice-3 mouth-to-ear budget: 200 ms (slice-1 notification
/// budget) + 250 ms mock brain round-trip + 100 ms playout buffer.
/// CI assertion ceiling: 700 ms (allowance for CI runner variance
/// against the dev machine — the mock brain is deterministic but the
/// harness adds observer cost; the dev machine usually lands ~600 ms).
pub const MOUTH_TO_EAR_P99_MS: f64 = 700.0;
/// Slice-5/seams tick-lag gauge: the meta-tick must stay under 10 ms
/// (the loop's nominal period). At 1 call: ≤2 ms expected. At 50
/// calls: ≤10 ms expected. Tick overruns (count of ticks exceeding
/// 10 ms) at p50 across the sweep: ≤1% of total ticks per
/// `TICK_OVERRUN_PCT_MAX`.
///
/// If a concurrency sweep shows `tick_overrun_pct > 1.0` at 50 calls,
/// **the FOB reflex loop's single-thread debt is real and the
/// dedicated-threadpool-shard graduation (slice-4 §1.2 deferral #2)
/// gets its data-driven case.** That finding is the slice's
/// load-bearing output regardless of whether the latency thresholds
/// pass — the doctrine-drift detector worked.
pub const TICK_LAG_MAX_MS: f64 = 10.0;
pub const TICK_OVERRUN_PCT_MAX: f64 = 1.0;
/// Concurrency-sweep sample sizes per spec §2.4: 1 isolates the
/// baseline (cold-path latency with zero concurrency pressure —
/// slice-4's §5.1 ≤60 ms kill budget asserted here); 10 is the
/// warm working set (~peak spearhead-scale); 50 is the saturation
/// point (ADR-0010's "single-poll-task head-of-line-blocking debt"
/// lives here). We do NOT test 100/500/5000 — that's fleet-scale
/// (rung 3). 50 is the upper edge of the spearhead's "one binary,
/// one city" claim.
pub const SWEEP_CONCURRENCIES: &[usize] = &[1, 10, 50];