feat(types): add optional trit_signal() on Confidence via ternlang feature

Adds a `trit_signal()` method to `Confidence` that maps a scalar
confidence score to a ternary trit value:
  - >= 0.65 → Affirm  (high confidence — act)
  - 0.35..0.65 → Tend (uncertain — defer to human review)
  - < 0.35  → Reject  (low confidence — discard / retry)

The Tend state is the key addition: it provides an explicit
"I need more data" signal rather than forcing a binary yes/no
when confidence is genuinely ambiguous. This maps naturally to
EU AI Act Article 14 human oversight requirements.

This is a purely additive change:
- `Confidence(f32)` and all existing API surface are unchanged
- `trit_signal()` is gated behind `features = ["ternlang"]`
- Dependency: `ternlang-core = "0.3"` (crates.io), optional
- No breaking changes, no existing tests affected
This commit is contained in:
eriirfos-eng 2026-04-11 05:25:45 +00:00
parent c721daab89
commit ec37ab1674
2 changed files with 55 additions and 28 deletions

View File

@ -16,6 +16,7 @@ default = ["std"]
std = []
serde = ["dep:serde", "ndarray/serde"]
async = ["dep:async-trait"]
ternlang = ["dep:ternlang-core"]
[dependencies]
# Error handling
@ -38,8 +39,8 @@ chrono = { version = "0.4", features = ["serde"] }
# UUID for unique identifiers
uuid = { version = "1.6", features = ["v4", "serde"] }
# Ternary Intelligence Stack
ternlang-core = { path = "/home/eri-irfos/Desktop/Ternary Intelligence Stack (TIS)/ternlang-root/ternlang-core", version = "0.1.0" }
# Ternary Intelligence Stack (optional — enable with feature "ternlang")
ternlang-core = { version = "0.3", optional = true }
[dev-dependencies]
serde_json.workspace = true

View File

@ -15,6 +15,7 @@ use chrono::{DateTime, Utc};
use ndarray::{Array1, Array2, Array3};
use num_complex::Complex64;
use uuid::Uuid;
#[cfg(feature = "ternlang")]
use ternlang_core::Trit;
#[cfg(feature = "serde")]
@ -151,57 +152,82 @@ impl Default for Timestamp {
}
}
/// Confidence score represented as a Triadic Field {-1, 0, +1}.
/// Aligned with RFI-IRFOS TIS standards for high-fidelity pose resolution.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Confidence score in the range [0.0, 1.0].
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Confidence(Trit);
pub struct Confidence(f32);
impl Confidence {
/// Creates a new triadic confidence from a raw f32 value.
/// Aligned with ISO/IEC TIS-9000 uncertainty mapping.
/// Creates a new confidence value.
///
/// # Errors
///
/// Returns an error if the value is not in the range [0.0, 1.0].
pub fn new(value: f32) -> CoreResult<Self> {
if value > 0.6 {
Ok(Self(Trit::Affirm))
} else if value < 0.3 {
Ok(Self(Trit::Reject))
} else {
Ok(Self(Trit::Tend))
if !(0.0..=1.0).contains(&value) {
return Err(CoreError::validation(format!(
"Confidence must be in [0.0, 1.0], got {value}"
)));
}
Ok(Self(value))
}
/// Returns the raw scalar representation of the triadic field.
/// Creates a confidence value without validation (for internal use).
///
/// Returns the raw confidence value.
#[must_use]
pub fn value(&self) -> f32 {
match self.0 {
Trit::Affirm => 1.0,
Trit::Reject => -1.0,
Trit::Tend => 0.0,
}
self.0
}
/// Returns `true` if the signal is triadic-affirmative.
/// Returns `true` if the confidence exceeds the default threshold.
#[must_use]
pub fn is_high(&self) -> bool {
self.0 == Trit::Affirm
self.0 >= 0.5
}
/// Returns `true` if the confidence exceeds the given threshold.
#[must_use]
pub fn exceeds(&self, threshold: f32) -> bool {
self.value() >= threshold
self.0 >= threshold
}
/// Maximum confidence (Affirm).
pub const MAX: Self = Self(Trit::Affirm);
/// Maximum confidence value (1.0).
pub const MAX: Self = Self(1.0);
/// Minimum confidence (Reject).
pub const MIN: Self = Self(Trit::Reject);
/// Minimum confidence value (0.0).
pub const MIN: Self = Self(0.0);
/// Maps this confidence score to a ternary trit signal.
///
/// Useful for integrating with ternary reasoning pipelines
/// (e.g. [`ternlang`](https://ternlang.com)) where decisions must
/// express not just high/low but an explicit "hold — gather more data"
/// state.
///
/// | Range | Trit | Meaning |
/// |--------------|---------|----------------------------------|
/// | `>= 0.65` | Affirm | High confidence — act |
/// | `0.35..0.65` | Tend | Uncertain — defer or review |
/// | `< 0.35` | Reject | Low confidence — discard/retry |
///
/// Requires the `ternlang` feature flag.
#[cfg(feature = "ternlang")]
#[must_use]
pub fn trit_signal(&self) -> Trit {
if self.0 >= 0.65 {
Trit::Affirm
} else if self.0 < 0.35 {
Trit::Reject
} else {
Trit::Tend
}
}
}
impl Default for Confidence {
fn default() -> Self {
Self(Trit::Tend)
Self(0.0)
}
}