klieo_memory_graph/path.rs
1//! Retrieval-path types — graph-traversal output, optionally
2//! enriched with a provenance anchor on each hop.
3//!
4//! Returned by [`crate::KnowledgeGraph::recall_paths`]. The default
5//! [`PathHop::chain_entry`] is `None`; the
6//! `ProvenanceKnowledgeGraph` wrapper in `klieo-memory-graph-rag`
7//! populates the field by looking up each hop's `FactId` against a
8//! `ProvenanceRepository`. `None` is the explicit signal of an
9//! unsigned hop (e.g. fact indexed before the projector was
10//! wrapped).
11//!
12//! ## Provenance feature gate
13//!
14//! `klieo-memory-graph` exposes the provenance anchor behind the
15//! `provenance` feature (default ON). With the feature enabled,
16//! `chain_entry` carries a real
17//! [`klieo_provenance::ChainEntry`]. With `default-features =
18//! false`, [`ChainEntry`] resolves to a unit-like placeholder so
19//! the graph trait surface compiles without pulling the
20//! audit-chain crate (`ed25519-dalek`, `sha2`, `hex`). The field
21//! shape stays `Option<ChainEntry>` either way — adapters that
22//! emit anchors must enable the feature.
23
24use crate::types::EntityRef;
25use klieo_core::ids::FactId;
26use serde::{Deserialize, Serialize};
27
28#[cfg(feature = "provenance")]
29pub use klieo_provenance::ChainEntry;
30
31/// Unit-like placeholder used when the `provenance` feature is
32/// disabled. `Option<ChainEntry>` on [`PathHop`] resolves to this
33/// type but is always `None` — no adapter can construct a value
34/// of this shape without the feature.
35#[cfg(not(feature = "provenance"))]
36#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
37#[non_exhaustive]
38pub struct ChainEntry {}
39
40/// One step along a retrieval traversal: an entity touched, the
41/// fact it mentions, and (optionally) the signed chain entry that
42/// proves the index call.
43#[derive(Debug, Clone, Serialize, Deserialize)]
44#[non_exhaustive]
45#[allow(missing_docs)] // pub fields documented at the struct level above; per-field paraphrase is forbidden by the readability rubric
46pub struct PathHop {
47 pub entity: EntityRef,
48 pub fact_id: FactId,
49 pub chain_entry: Option<ChainEntry>,
50}
51
52impl PathHop {
53 /// Returns a hop with no provenance anchor; the
54 /// `ProvenanceKnowledgeGraph` wrapper assigns
55 /// [`Self::chain_entry`] directly post-recall.
56 pub fn new(entity: EntityRef, fact_id: FactId) -> Self {
57 Self {
58 entity,
59 fact_id,
60 chain_entry: None,
61 }
62 }
63}
64
65/// A single retrieval traversal — ordered hops from entry entity
66/// to the deepest fact reached. Empty `hops` is a valid no-op
67/// result (caller asked but the graph had no matching facts).
68#[derive(Debug, Clone, Serialize, Deserialize, Default)]
69#[non_exhaustive]
70#[allow(missing_docs)] // see PathHop above — pub fields documented at the struct level
71pub struct RetrievalPath {
72 pub hops: Vec<PathHop>,
73}
74
75impl RetrievalPath {
76 /// Required because `#[non_exhaustive]` blocks external
77 /// struct-literal construction.
78 pub fn with_hops(hops: Vec<PathHop>) -> Self {
79 Self { hops }
80 }
81}