MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / format_provenance_graph

Method format_provenance_graph

atomic-cli/src/commands/change/command.rs:601–689  ·  view source on GitHub ↗

Format the provenance decision graph for display. When `--verbose` is passed via the top-level `-p` flag the display includes the structured `detail` field from each provenance node so the user can see the actual commands, file paths, and diffs.

(&self, change_hash: &Hash, repo: &Repository)

Source from the content-addressed store, hash-verified

599 /// includes the structured `detail` field from each provenance node so
600 /// the user can see the actual commands, file paths, and diffs.
601 fn format_provenance_graph(&self, change_hash: &Hash, repo: &Repository) -> String {
602 let mut output = String::new();
603
604 let graphs = match repo.find_provenance_for_change(change_hash) {
605 Ok(g) if !g.is_empty() => g,
606 Ok(_) => {
607 output.push_str(&format!(
608 "{}\n",
609 hint("No provenance graph found for this change.")
610 ));
611 return output;
612 }
613 Err(e) => {
614 output.push_str(&format!(
615 "{}\n",
616 hint(&format!("Failed to load provenance: {}", e))
617 ));
618 return output;
619 }
620 };
621
622 for (_graph_hash, graph) in &graphs {
623 output.push_str(&format!("{}\n", emphasis("Provenance Graph:")));
624 output.push_str(&format!(" Session: {}\n", info(&graph.session_id)));
625 output.push_str(&format!(
626 " Agent: {} ({})\n",
627 info(&graph.agent_display_name),
628 hint(&graph.agent_vendor)
629 ));
630 output.push_str(&format!(
631 " Nodes: {} Edges: {} Changes: {}\n",
632 graph.node_count(),
633 graph.edge_count(),
634 graph.change_count()
635 ));
636 output.push('\n');
637
638 // Display nodes
639 for node in &graph.nodes {
640 let kind_str = format!("{}", node.kind);
641 let kind_styled = format!("{}", style(&kind_str).bold().cyan());
642 let duration = node
643 .duration_ms
644 .map(|ms| format!(" ({}ms)", ms))
645 .unwrap_or_default();
646 let tool = node.tool_name.as_deref().unwrap_or("");
647 let tool_str = if tool.is_empty() {
648 String::new()
649 } else {
650 format!(" {}", hint(&format!("[{}]", tool)))
651 };
652
653 // Extract a one-line detail string from the structured detail JSON
654 let detail_str = node
655 .detail
656 .as_ref()
657 .and_then(|d| format_node_detail(d))
658 .map(|s| format!("\n {}", hint(&s)))

Callers 1

format_defaultMethod · 0.80

Calls 6

format_node_detailFunction · 0.85
as_refMethod · 0.80
is_emptyMethod · 0.45
pushMethod · 0.45
edge_countMethod · 0.45

Tested by

no test coverage detected