Skip to main content

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}