Skip to main content

bifp_core/
tap.rs

1//! A real, honestly-scoped implementation of the *behavior* the Ternlang whitepaper's
2//! Implementation Status section describes for "TAP" (Ternary Actuator Protocol) in one
3//! sentence: an interception layer that suspends uncertain (tend) nodes until a human or
4//! upstream agent resolves the signal.
5//!
6//! No TAP source code was found anywhere on this machine, under any name, at the time
7//! this was written (2026-07-02) — this module does not extend, wrap, or claim to be
8//! that project's TAP. It is BIFP's own primitive, built to match the *described*
9//! behavior, named separately so the two are never confused in provenance.
10
11use crate::trit::{decide, Trit};
12
13#[derive(Debug, Clone, PartialEq)]
14pub enum Signal {
15    /// The evidence was decisive — the action may proceed with this trit.
16    Resolved(Trit),
17    /// The evidence landed in the tend zone. This is not a failure state — it is the
18    /// point of the mechanism: don't force a decision, suspend and wait.
19    Held { confidence: f64 },
20}
21
22/// Evaluate evidence. Reject/Affirm resolve immediately; Tend holds instead of forcing
23/// a binary decision, mirroring the whitepaper's described suspend-on-uncertainty behavior.
24pub fn evaluate(evidence: &[f64]) -> Signal {
25    let (trit, confidence) = decide(evidence);
26    match trit {
27        Trit::Tend => Signal::Held { confidence },
28        resolved => Signal::Resolved(resolved),
29    }
30}
31
32/// A human or upstream agent resolves a held signal explicitly — the suspend is lifted
33/// only by an outside decision, never by the same evidence re-evaluating itself.
34pub fn resolve(_held: Signal, resolution: Trit) -> Trit {
35    resolution
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn decisive_evidence_resolves_immediately() {
44        assert_eq!(evaluate(&[0.9]), Signal::Resolved(Trit::Affirm));
45        assert_eq!(evaluate(&[-0.9]), Signal::Resolved(Trit::Reject));
46    }
47
48    #[test]
49    fn ambiguous_evidence_holds_instead_of_forcing_a_decision() {
50        match evaluate(&[0.1, -0.05]) {
51            Signal::Held { .. } => {}
52            other => panic!("expected Held, got {other:?}"),
53        }
54    }
55
56    #[test]
57    fn a_held_signal_can_be_explicitly_resolved() {
58        let held = evaluate(&[0.0]);
59        assert_eq!(resolve(held, Trit::Affirm), Trit::Affirm);
60    }
61}