From d3075dc235a500959c39423c3a349ace403980df Mon Sep 17 00:00:00 2001 From: ProofOfConcept Date: Fri, 6 Mar 2026 21:41:26 -0500 Subject: [PATCH] provenance: add label() method, show provenance in history output Move provenance_label() from query.rs private function to a pub label() method on Provenance, eliminating duplication. History command now shows provenance, human-readable timestamps, and content size for each version. Handle pre-migration nodes with bogus timestamps gracefully instead of panicking. --- src/main.rs | 18 +++++++++++++----- src/query.rs | 20 +------------------- src/store/types.rs | 21 +++++++++++++++++++++ 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/main.rs b/src/main.rs index a2f358e..7ffb44a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1583,16 +1583,24 @@ fn cmd_history(args: &[String]) -> Result<(), String> { } eprintln!("{} versions of '{}':\n", versions.len(), key); - for (i, node) in versions.iter().enumerate() { - let preview: String = node.content.chars().take(200).collect(); + for node in &versions { + let ts = if node.timestamp > 0 && node.timestamp < 4_000_000_000 { + store::format_datetime(node.timestamp) + } else { + format!("(raw:{})", node.timestamp) + }; + let content_len = node.content.len(); + let preview: String = node.content.chars().take(120).collect(); let preview = preview.replace('\n', "\\n"); - eprintln!(" v{} (w={:.3}, {}): {}", - node.version, node.weight, node.timestamp, preview); + eprintln!(" v{:<3} {} {:24} w={:.3} {}b", + node.version, ts, node.provenance.label(), node.weight, content_len); + eprintln!(" {}", preview); } // Show latest full content if let Some(latest) = versions.last() { - eprintln!("\n--- Latest content (v{}) ---", latest.version); + eprintln!("\n--- Latest content (v{}, {}) ---", + latest.version, latest.provenance.label()); print!("{}", latest.content); } diff --git a/src/query.rs b/src/query.rs index 5076280..04aeff6 100644 --- a/src/query.rs +++ b/src/query.rs @@ -173,7 +173,7 @@ fn resolve_field(field: &str, key: &str, store: &Store, graph: &Graph) -> Option "weight" => Some(Value::Num(node.weight as f64)), "category" => Some(Value::Str(node.category.label().to_string())), "node_type" => Some(Value::Str(node_type_label(node.node_type).to_string())), - "provenance" => Some(Value::Str(provenance_label(node.provenance).to_string())), + "provenance" => Some(Value::Str(node.provenance.label().to_string())), "emotion" => Some(Value::Num(node.emotion as f64)), "retrievals" => Some(Value::Num(node.retrievals as f64)), "uses" => Some(Value::Num(node.uses as f64)), @@ -200,24 +200,6 @@ fn node_type_label(nt: NodeType) -> &'static str { } } -fn provenance_label(p: Provenance) -> &'static str { - match p { - Provenance::Manual => "manual", - Provenance::Journal => "journal", - Provenance::Agent => "agent", - Provenance::Dream => "dream", - Provenance::Derived => "derived", - Provenance::AgentExperienceMine => "agent:experience-mine", - Provenance::AgentKnowledgeObservation => "agent:knowledge-observation", - Provenance::AgentKnowledgePattern => "agent:knowledge-pattern", - Provenance::AgentKnowledgeConnector => "agent:knowledge-connector", - Provenance::AgentKnowledgeChallenger => "agent:knowledge-challenger", - Provenance::AgentConsolidate => "agent:consolidate", - Provenance::AgentDigest => "agent:digest", - Provenance::AgentFactMine => "agent:fact-mine", - Provenance::AgentDecay => "agent:decay", - } -} fn rel_type_label(r: RelationType) -> &'static str { match r { diff --git a/src/store/types.rs b/src/store/types.rs index f47982d..c87b03b 100644 --- a/src/store/types.rs +++ b/src/store/types.rs @@ -247,6 +247,27 @@ pub enum Provenance { AgentDecay, } +impl Provenance { + pub fn label(&self) -> &'static str { + match self { + Self::Manual => "manual", + Self::Journal => "journal", + Self::Agent => "agent", + Self::Dream => "dream", + Self::Derived => "derived", + Self::AgentExperienceMine => "agent:experience-mine", + Self::AgentKnowledgeObservation => "agent:knowledge-observation", + Self::AgentKnowledgePattern => "agent:knowledge-pattern", + Self::AgentKnowledgeConnector => "agent:knowledge-connector", + Self::AgentKnowledgeChallenger => "agent:knowledge-challenger", + Self::AgentConsolidate => "agent:consolidate", + Self::AgentDigest => "agent:digest", + Self::AgentFactMine => "agent:fact-mine", + Self::AgentDecay => "agent:decay", + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)] #[archive(check_bytes)] pub enum Category {