Skip to main content

rto_graph/
provenance.rs

1//! Edge provenance classes.
2
3use serde::{Deserialize, Serialize};
4
5/// How an edge in the graph was produced.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "lowercase")]
8pub enum Provenance {
9    /// Deterministically extracted from source ASTs (tree-sitter).
10    Derived,
11    /// Authored by a human or agent in an ADR, blueprint, or annotation.
12    Authored,
13    /// Heuristically inferred (docs, embeddings); carries a confidence score.
14    Inferred,
15}
16
17impl Provenance {
18    /// Parse a provenance from its stable string token, returning `None` for an
19    /// unrecognised value (e.g. a corrupt database row).
20    #[must_use]
21    pub fn from_token(s: &str) -> Option<Self> {
22        match s {
23            "derived" => Some(Self::Derived),
24            "authored" => Some(Self::Authored),
25            "inferred" => Some(Self::Inferred),
26            _ => None,
27        }
28    }
29
30    /// Stable string form used in the `SQLite` store.
31    #[must_use]
32    pub fn as_str(self) -> &'static str {
33        match self {
34            Self::Derived => "derived",
35            Self::Authored => "authored",
36            Self::Inferred => "inferred",
37        }
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::Provenance;
44
45    #[test]
46    fn stable_string_forms() {
47        assert_eq!(Provenance::Derived.as_str(), "derived");
48        assert_eq!(Provenance::Authored.as_str(), "authored");
49        assert_eq!(Provenance::Inferred.as_str(), "inferred");
50    }
51
52    #[test]
53    fn from_token_round_trips_and_rejects_unknown() {
54        for p in [
55            Provenance::Derived,
56            Provenance::Authored,
57            Provenance::Inferred,
58        ] {
59            assert_eq!(Provenance::from_token(p.as_str()), Some(p));
60        }
61        assert_eq!(Provenance::from_token("bogus"), None);
62    }
63}