Convert a [`ProvenanceGraph`] into a [`TraceRecord`] suitable for appending to `.agent-trace/traces.jsonl`. `root` is the repository root used for computing relative paths and for resolving the git HEAD revision. This function never fails; any missing data is silently omitted.
(graph: &ProvenanceGraph, root: &Path)
| 182 | /// |
| 183 | /// This function never fails; any missing data is silently omitted. |
| 184 | pub fn to_agent_trace_record(graph: &ProvenanceGraph, root: &Path) -> TraceRecord { |
| 185 | let timestamp = DateTime::<Utc>::from_timestamp(graph.timestamp, 0) |
| 186 | .unwrap_or_else(Utc::now) |
| 187 | .to_rfc3339(); |
| 188 | |
| 189 | // Unique record ID: session + timestamp epoch |
| 190 | let id = format!("{}-{}", graph.session_id, graph.timestamp); |
| 191 | |
| 192 | // VCS: best-effort Atomic view Merkle state |
| 193 | let vcs = atomic_revision(root).map(|(view, revision)| VcsInfo { |
| 194 | vcs_type: "atomic".to_string(), |
| 195 | view, |
| 196 | revision, |
| 197 | }); |
| 198 | |
| 199 | // Tool info |
| 200 | let tool = ToolInfo { |
| 201 | name: graph.agent_name.clone(), |
| 202 | version: env!("CARGO_PKG_VERSION").to_string(), |
| 203 | }; |
| 204 | |
| 205 | // Build files + metadata["dev.atomic"] by walking nodes |
| 206 | let (files, dev_atomic) = build_files_and_metadata(graph); |
| 207 | |
| 208 | let mut metadata: HashMap<String, Value> = HashMap::new(); |
| 209 | metadata.insert("dev.atomic".to_string(), dev_atomic); |
| 210 | |
| 211 | TraceRecord { |
| 212 | version: "0.1.0".to_string(), |
| 213 | id, |
| 214 | timestamp, |
| 215 | vcs, |
| 216 | tool, |
| 217 | files, |
| 218 | metadata, |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | /// Append a [`TraceRecord`] as a single JSON line to |
| 223 | /// `{root}/.agent-trace/traces.jsonl`. |