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

Method populate_session_tables

atomic-core/src/pristine/txn/write/mod.rs:76–289  ·  view source on GitHub ↗

Populate the session tables from a provenance graph. Called during `save_provenance_graph` for provenance produced by any** agent — Sherpa, Claude Code, OpenCode, the generic `atomic-agent`, etc. Sherpa graphs (`profile == "sherpa-trace/1.0.0"`) carry richer structured `detail` JSON (intent/todo/phase/verification), so they populate the intent and phase tables more fully; graphs from other agents

(
        &mut self,
        provenance_id: u64,
        graph: &crate::change::ProvenanceGraph,
    )

Source from the content-addressed store, hash-verified

74 ///
75 /// Best-effort: parse errors on individual nodes are logged and skipped.
76 pub fn populate_session_tables(
77 &mut self,
78 provenance_id: u64,
79 graph: &crate::change::ProvenanceGraph,
80 ) -> PristineResult<()> {
81 use crate::change::provenance_graph::ProvenanceNodeKind;
82 use crate::change::session::*;
83
84 // No profile gate: provenance from any agent is indexed into the
85 // session tables. The per-node extraction below is profile-agnostic
86 // and falls back to node summary / kind labels when the richer
87 // Sherpa-specific `detail` keys are absent.
88
89 // Open all four tables.
90 let mut events_table = self.txn.open_table(SESSION_EVENTS)?;
91 let mut todos_table = self.txn.open_table(SESSION_TODOS)?;
92 let mut phases_table = self.txn.open_table(SESSION_PHASES)?;
93 let mut intents_table = self.txn.open_table(SESSION_INTENTS)?;
94
95 for (seq, node) in graph.nodes.iter().enumerate() {
96 let seq = seq as u64;
97 let detail: Option<serde_json::Value> = if let Some(s) = node.detail.as_deref() {
98 match serde_json::from_str(s) {
99 Ok(v) => Some(v),
100 Err(e) => {
101 log::warn!(
102 "Warning: failed to parse provenance node detail JSON (node id={}, kind={}): {}",
103 node.id,
104 node.kind.label(),
105 e
106 );
107 None
108 }
109 }
110 } else {
111 None
112 };
113
114 // Write every node as a SessionEvent regardless of kind.
115 //
116 // `event_kind` and `record_type` are populated from the original
117 // Sherpa/agent-trace `record_type` field stored in the detail JSON
118 // (e.g. "intent", "todo_status", "phase_transition"). We fall back
119 // to `node.kind.label()` only when no such field is present so that
120 // non-Sherpa nodes still get a meaningful discriminant.
121 let sherpa_record_type = detail
122 .as_ref()
123 .and_then(|d| d["record_type"].as_str())
124 .map(|s| s.to_string());
125 let event_kind = sherpa_record_type
126 .clone()
127 .unwrap_or_else(|| node.kind.label().to_string());
128 let event = SessionEvent {
129 seq,
130 timestamp: format_timestamp_ms(node.timestamp),
131 event_kind,
132 place: None,
133 transition: None,

Calls 14

format_timestamp_msFunction · 0.85
encode_session_event_keyFunction · 0.85
encode_session_phase_keyFunction · 0.85
encode_session_todo_keyFunction · 0.85
as_refMethod · 0.80
as_u64Method · 0.80
getMethod · 0.65
iterMethod · 0.45
as_strMethod · 0.45
cloneMethod · 0.45
labelMethod · 0.45
to_bytesMethod · 0.45