Skip to main content

perspt_sdk/
error.rs

1//! SDK error type.
2//!
3//! The SDK refuses to silently accept a malformed residual, weight, or
4//! stability constant. Every numerical contract in PSP-8 (finite non-negative
5//! residual scores, strictly positive edge weights, `alpha > beta`, `mu > 0`)
6//! is enforced as a typed error rather than a soft pass.
7
8use thiserror::Error;
9
10/// Errors produced by the SRBN agent SDK.
11#[derive(Debug, Error, Clone, PartialEq)]
12pub enum SdkError {
13    /// A residual score was negative, NaN, or infinite.
14    #[error("invalid residual score: {0}")]
15    InvalidScore(String),
16
17    /// An energy weight was non-positive, NaN, or infinite.
18    #[error("invalid energy weight: {0}")]
19    InvalidWeight(String),
20
21    /// A descent tolerance, energy, or other gate input was out of range.
22    #[error("invalid gate parameter: {0}")]
23    InvalidGate(String),
24
25    /// A declared analytic stability constant violated its precondition.
26    #[error("invalid stability claim: {0}")]
27    InvalidStability(String),
28
29    /// The spectral energy-slope computation could not be completed.
30    #[error("spectral computation error: {0}")]
31    Spectral(String),
32
33    /// The underlying `srbn` kernel reported an error.
34    #[error("srbn kernel error: {0}")]
35    Kernel(String),
36
37    /// A domain package produced an inconsistent contract.
38    #[error("domain error: {0}")]
39    Domain(String),
40
41    /// A grant signature failed to encode, decode, or verify.
42    #[error("grant signature error: {0}")]
43    Signature(String),
44}
45
46impl From<srbn::Error> for SdkError {
47    fn from(err: srbn::Error) -> Self {
48        SdkError::Kernel(err.to_string())
49    }
50}
51
52/// SDK result alias.
53pub type Result<T> = std::result::Result<T, SdkError>;
54
55/// Validate that a value is finite and non-negative (PSP-8 residual contract).
56pub(crate) fn check_non_negative_finite(value: f64, what: &str) -> Result<()> {
57    if !value.is_finite() {
58        return Err(SdkError::InvalidScore(format!(
59            "{what} is not finite: {value}"
60        )));
61    }
62    if value < 0.0 {
63        return Err(SdkError::InvalidScore(format!(
64            "{what} is negative: {value}"
65        )));
66    }
67    Ok(())
68}
69
70/// Validate that a weight is finite and strictly positive (PSP-8 `w_e > 0`).
71pub(crate) fn check_positive_finite(value: f64, what: &str) -> Result<()> {
72    if !value.is_finite() {
73        return Err(SdkError::InvalidWeight(format!(
74            "{what} is not finite: {value}"
75        )));
76    }
77    if value <= 0.0 {
78        return Err(SdkError::InvalidWeight(format!(
79            "{what} must be strictly positive: {value}"
80        )));
81    }
82    Ok(())
83}