Skip to main content

assay_core/explain_next/
model.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4/// A single step in the explained trace
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct ExplainedStep {
7    pub index: usize,
8    pub tool: String,
9
10    /// Tool arguments (if available)
11    #[serde(default, skip_serializing_if = "Option::is_none")]
12    pub args: Option<serde_json::Value>,
13
14    /// Verdict for this step
15    pub verdict: StepVerdict,
16
17    /// Rules that were evaluated
18    pub rules_evaluated: Vec<RuleEvaluation>,
19
20    /// Current state of stateful rules after this step
21    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
22    pub state_snapshot: HashMap<String, String>,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
26#[serde(rename_all = "lowercase")]
27pub enum StepVerdict {
28    /// Tool call allowed
29    Allowed,
30    /// Tool call blocked by a rule
31    Blocked,
32    /// Tool call allowed but triggered a warning
33    Warning,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct RuleEvaluation {
38    pub rule_id: String,
39    pub rule_type: String,
40    pub passed: bool,
41    pub explanation: String,
42
43    #[serde(default, skip_serializing_if = "Option::is_none")]
44    pub context: Option<serde_json::Value>,
45}
46
47/// Complete explanation of a trace
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct TraceExplanation {
50    pub policy_name: String,
51    pub policy_version: String,
52    pub total_steps: usize,
53    pub allowed_steps: usize,
54    pub blocked_steps: usize,
55
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub first_block_index: Option<usize>,
58
59    /// Detailed step-by-step explanation
60    pub steps: Vec<ExplainedStep>,
61
62    /// Summary of rules that blocked
63    pub blocking_rules: Vec<String>,
64}
65
66/// Tool call input for explanation
67#[derive(Debug, Clone, Deserialize)]
68pub struct ToolCall {
69    /// Tool name
70    #[serde(alias = "name", alias = "tool_name")]
71    pub tool: String,
72
73    /// Tool arguments
74    #[serde(default)]
75    pub args: Option<serde_json::Value>,
76}