dsfb_debug/config.rs
1//! DSFB-Debug: engine configuration — paper §F.4 + Appendix F.
2//!
3//! `EngineConfig` carries every operator-tunable parameter for the
4//! DSFB pipeline. The `paper_lock()` factory pins the entire config
5//! to the values reported in paper §13 — the canonical settings under
6//! which all empirical claims are reproducible.
7//!
8//! # Paper-lock parameters
9//!
10//! Each pinned value is documented in-source with its paper §F.4
11//! anchor and operational rationale (e.g. `drift_window = 7` because
12//! it captures sustained drift without over-smoothing transients;
13//! `n_confirm = 2` because Boundary→Violation transitions need a
14//! two-window confirmation to suppress single-window touches).
15//!
16//! Operators running on real production residuals SHOULD start with
17//! `paper_lock()` and adjust per `calibration::recommend_config_from_healthy`
18//! recommendations. The calibration tool is advisory — operators
19//! decide whether to apply.
20
21use crate::error::{DsfbError, Result};
22
23/// Engine configuration — all parameters from paper's fixed protocol
24#[derive(Copy, Clone, Debug, PartialEq)]
25pub struct EngineConfig {
26 /// W: consecutive windows for drift estimation (paper: 5)
27 pub drift_window: usize,
28 /// DSA drift window (paper: 10)
29 pub dsa_window: usize,
30 /// K: minimum grammar hits for state confirmation (paper: 4)
31 pub persistence_threshold: usize,
32 /// τ: directional consistency threshold for DSA (paper: 2.0)
33 pub consistency_gate: f64,
34 /// m: minimum co-activating signals for run-level alert (paper: 1)
35 pub corroboration_count: usize,
36 /// n_confirm: consecutive steps for hysteresis (paper: 2)
37 pub hysteresis_confirm: usize,
38 /// Fraction of ρ for boundary entry (paper: 0.5)
39 pub boundary_fraction: f64,
40 /// Windows for temporal episode grouping
41 pub episode_correlation_window: u64,
42 /// W_pred: look-ahead for episode precision (paper: 5)
43 pub episode_precision_window: u64,
44 /// Minimum healthy windows for baseline (paper: 100)
45 pub min_healthy_windows: usize,
46 /// Slew threshold δ_s for slew density computation
47 pub slew_delta: f64,
48}
49
50/// Paper-lock configuration — exact parameters from the paper
51/// Used by paper-lock CI test to verify headline metrics
52pub const PAPER_LOCK_CONFIG: EngineConfig = EngineConfig {
53 drift_window: 5,
54 dsa_window: 10,
55 persistence_threshold: 4,
56 consistency_gate: 2.0,
57 corroboration_count: 1,
58 hysteresis_confirm: 2,
59 boundary_fraction: 0.5,
60 episode_correlation_window: 5,
61 episode_precision_window: 5,
62 min_healthy_windows: 100,
63 slew_delta: 0.1,
64};
65
66impl EngineConfig {
67 pub fn validate(&self) -> Result<()> {
68 if self.drift_window == 0 {
69 return Err(DsfbError::InvalidConfig("drift_window must be > 0"));
70 }
71 if self.dsa_window == 0 {
72 return Err(DsfbError::InvalidConfig("dsa_window must be > 0"));
73 }
74 if self.persistence_threshold == 0 {
75 return Err(DsfbError::InvalidConfig("persistence_threshold must be > 0"));
76 }
77 if self.consistency_gate <= 0.0 {
78 return Err(DsfbError::InvalidConfig("consistency_gate must be > 0"));
79 }
80 if self.corroboration_count == 0 {
81 return Err(DsfbError::InvalidConfig("corroboration_count must be > 0"));
82 }
83 if self.hysteresis_confirm == 0 {
84 return Err(DsfbError::InvalidConfig("hysteresis_confirm must be > 0"));
85 }
86 if self.boundary_fraction <= 0.0 || self.boundary_fraction >= 1.0 {
87 return Err(DsfbError::InvalidConfig("boundary_fraction must be in (0, 1)"));
88 }
89 Ok(())
90 }
91}
92
93impl Default for EngineConfig {
94 fn default() -> Self {
95 PAPER_LOCK_CONFIG
96 }
97}