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}