use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::{ActorId, BlockId};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ProvenanceChain {
pub nodes: Vec<ProvenanceNode>,
}
impl ProvenanceChain {
pub fn with_cause(mut self, cause: CauseKind, actor: ActorId) -> Self {
self.nodes.push(ProvenanceNode {
cause,
actor,
timestamp: Utc::now(),
});
self
}
pub fn immediate_cause(&self) -> Option<&ProvenanceNode> {
self.nodes.last()
}
pub fn root_cause(&self) -> Option<&ProvenanceNode> {
self.nodes.first()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProvenanceNode {
pub cause: CauseKind,
pub actor: ActorId,
pub timestamp: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum CauseKind {
HumanPrompt { prompt_summary: String },
BlockOutput { block_id: BlockId },
ToolResult { tool_name: String },
ApprovalGranted { approval_block_id: BlockId },
AgentPlan { plan_description: String },
System { reason: String },
}