Map a loaded `ProvenanceGraph` into the plain projector input. `change_hash` is the change the user asked to trace (it names the subgraph and the projected activity). `person_did` is the real signer's `did:atomic`, resolved from the signing identity by the caller — it is NOT in the graph. `graph.previous` is a hash of the PREVIOUS PROVENANCE GRAPH (not an activity id): we load that graph and use
(
repo: &Repository,
graph: &ProvenanceGraph,
change_hash: &Hash,
person_did: &str,
)
| 40 | /// id): we load that graph and use ITS activity id for `turnParent`. If it can't |
| 41 | /// be loaded, `turnParent` is omitted (best-effort) rather than fabricated. |
| 42 | pub fn map_graph_to_input( |
| 43 | repo: &Repository, |
| 44 | graph: &ProvenanceGraph, |
| 45 | change_hash: &Hash, |
| 46 | person_did: &str, |
| 47 | ) -> ProvActivityInput { |
| 48 | let change_id_base32 = change_hash.to_base32(); |
| 49 | let activity_id = activity_id_for(graph); |
| 50 | |
| 51 | let generated = graph |
| 52 | .changes_explained |
| 53 | .iter() |
| 54 | .map(|h| change_urn(&h.to_base32())) |
| 55 | .collect(); |
| 56 | |
| 57 | // `previous` is a hash of the previous PROVENANCE GRAPH — load it and use |
| 58 | // ITS own activity id (session_id # first-explained-change). Best-effort. |
| 59 | let turn_parent = graph.previous.and_then(|prev_hash| { |
| 60 | repo.load_provenance_graph(&prev_hash) |
| 61 | .ok() |
| 62 | // The parent activity is keyed the same graph-stable way as this one |
| 63 | // (activity_id_for), so trace walks a consistent, joinable chain. |
| 64 | .map(|prev| activity_urn(&activity_id_for(&prev))) |
| 65 | }); |
| 66 | |
| 67 | let agent_vendor = (!graph.agent_vendor.is_empty()).then(|| graph.agent_vendor.clone()); |
| 68 | |
| 69 | ProvActivityInput { |
| 70 | change_id_base32, |
| 71 | activity_id, |
| 72 | // Timestamp is Unix SECONDS on the graph but MILLISECONDS on nodes; |
| 73 | // to avoid mixing units the thin slice leaves times as None (the shape |
| 74 | // simply omits absent times). |
| 75 | started_at: None, |
| 76 | ended_at: None, |
| 77 | agent_slug: normalize_agent_slug(&graph.agent_name), |
| 78 | agent_display_name: graph.agent_display_name.clone(), |
| 79 | agent_vendor, |
| 80 | person_did: person_did.to_string(), |
| 81 | generated, |
| 82 | // The flywheel `used` edge (intents/memories the turn pulled). The current |
| 83 | // `atomic_core::ProvenanceGraph` capture records no structured inputs — |
| 84 | // only `nodes`/`edges`/`changes_explained` — so we supply an empty set |
| 85 | // (the projection omits `used` rather than inventing edges). Populating it |
| 86 | // is gated on the capture recording inputs (a separate capture-path change). |
| 87 | used: Vec::new(), |
| 88 | turn_parent, |
| 89 | } |
| 90 | } |
no test coverage detected