1use super::*;
7
8#[derive(Debug, Clone)]
9pub struct PlanReceiptV1 {
10 pub receipt_id: ArtifactId,
11 pub plan_id: ArtifactId,
12 pub step: u32,
13 pub action: String,
14 pub reason_codes: Vec<String>,
15}
16
17#[derive(Debug, Clone)]
18pub struct ToolRouteReceiptV1 {
19 pub receipt_id: ArtifactId,
20 pub plan_id: ArtifactId,
21 pub step: u32,
22 pub requested_tool_ids: Vec<String>,
23 pub exposed_tool_ids: Vec<String>,
24 pub reason_codes: Vec<String>,
25}
26
27#[derive(Debug, Clone)]
28pub struct ToolCallReceiptV1 {
29 pub receipt_id: ArtifactId,
30 pub plan_id: ArtifactId,
31 pub step: u32,
32 pub run_id: String,
33 pub permitted_tool_calls: usize,
34 pub blocked_tool_calls: usize,
35 pub succeeded_tool_calls: usize,
36 pub failed_tool_calls: usize,
37 pub reason_codes: Vec<String>,
38}
39
40#[derive(Debug, Clone)]
41pub struct VerificationReceiptV1 {
42 pub receipt_id: ArtifactId,
43 pub step: u32,
44 pub check: String,
45 pub passed: bool,
46 pub reason_codes: Vec<String>,
47}
48
49#[derive(Debug, Clone)]
50pub struct AbstentionReceiptV1 {
51 pub receipt_id: ArtifactId,
52 pub step: u32,
53 pub reason_code: String,
54 pub blocked_action: String,
55 pub evidence: Vec<String>,
56 pub required_permits: Vec<String>,
57 pub can_resume: bool,
58 pub support_impact: String,
59}
60
61#[derive(Debug, Clone)]
62pub struct RepairPlanDisplayReceiptV1 {
63 pub repair_id: ArtifactId,
64 pub source_run_id: Option<String>,
65 pub failure_kind: String,
66 pub candidate_repair_actions: Vec<String>,
67 pub required_verification: Vec<String>,
68 pub required_permits: Vec<String>,
69 pub risk_level: String,
70 pub canonical_owner: Option<String>,
71}
72
73#[derive(Debug, Clone)]
74pub struct FinalizationReceiptV1 {
75 pub receipt_id: ArtifactId,
76 pub step: u32,
77 pub outcome: String,
78 pub final_state: String,
79 pub blocked: bool,
80 pub support_label: String,
81 pub reason_codes: Vec<String>,
82}
83
84#[derive(Debug, Clone, PartialEq, Eq)]
85pub enum PlanActVerifyOutcomeV1 {
86 Success,
87 Abstained,
88 RepairNeeded,
89 Failed,
90}
91
92#[derive(Debug, Clone)]
93pub struct PlanActVerifyLoopV1Output {
94 pub agent_id: String,
95 pub app_id: String,
96 pub profile: String,
97 pub support_label: String,
98 pub outcome: PlanActVerifyOutcomeV1,
99 pub turns_used: u32,
100 pub max_turns: u32,
101 pub plan_receipts: Vec<PlanReceiptV1>,
102 pub tool_route_receipts: Vec<ToolRouteReceiptV1>,
103 pub tool_call_receipts: Vec<ToolCallReceiptV1>,
104 pub verification_receipts: Vec<VerificationReceiptV1>,
105 pub memory_grounding_receipts: Vec<String>,
106 pub abstention_receipt: Option<AbstentionReceiptV1>,
107 pub repair_plan: Option<RepairPlanDisplayReceiptV1>,
108 pub finalization: Option<FinalizationReceiptV1>,
109 pub run_output: Option<AiDENsRunOutput>,
110}
111
112impl PlanActVerifyLoopV1Output {
113 pub(crate) fn abstention(
114 agent: &AgentSpecV1,
115 step: u32,
116 reason_code: impl Into<String>,
117 ) -> Self {
118 Self {
119 agent_id: agent.agent_id.clone(),
120 app_id: "aidens-plan-act-verify-loop".into(),
121 profile: agent.profile.clone(),
122 support_label: agent.support_label.to_string(),
123 outcome: PlanActVerifyOutcomeV1::Abstained,
124 turns_used: 0,
125 max_turns: agent.budget_policy.max_turns,
126 plan_receipts: Vec::new(),
127 tool_route_receipts: Vec::new(),
128 tool_call_receipts: Vec::new(),
129 verification_receipts: Vec::new(),
130 memory_grounding_receipts: Vec::new(),
131 abstention_receipt: Some(AbstentionReceiptV1 {
132 receipt_id: display_only_unstable_id("agent-abstention"),
133 step,
134 reason_code: reason_code.into(),
135 blocked_action: "execution-blocked-before-run".into(),
136 evidence: Vec::new(),
137 required_permits: Vec::new(),
138 can_resume: true,
139 support_impact: "partial".into(),
140 }),
141 repair_plan: None,
142 finalization: None,
143 run_output: None,
144 }
145 }
146
147 #[allow(clippy::too_many_arguments)]
148 pub fn assemble_v3_bundle(
149 &self,
150 run_id: impl Into<String>,
151 profile: impl Into<String>,
152 canonical_execution_context: aidens_contracts::canonical_stack::ForgeExecutionContextV1,
153 event_log: AiDENsRunEventLogDigestV1,
154 budget: AiDENsRunBudgetDeadlineV1,
155 support: AiDENsRunSupportTierEvidenceV1,
156 support_labels: Vec<String>,
157 replay: AiDENsRunReplayNormalizationV1,
158 failure: AiDENsRunFailureTaxonomyV1,
159 attempt_family_id: ArtifactId,
160 attempt_id: StackAttemptId,
161 trial_id: StackTrialId,
162 agent_spec_digest: DisplayDigestV1,
163 memory_grounding_receipts: Vec<String>,
164 outputs: Vec<String>,
165 replay_instructions: Vec<String>,
166 blocked_checks: Vec<String>,
167 ) -> AiDENsRunBundleV3 {
168 let mut bundle = AiDENsRunBundleV3::new(
169 run_id,
170 profile,
171 canonical_execution_context,
172 event_log,
173 budget,
174 support,
175 support_labels,
176 replay,
177 failure,
178 attempt_family_id,
179 attempt_id,
180 trial_id,
181 agent_spec_digest,
182 );
183 bundle.provider_receipts = self
184 .tool_route_receipts
185 .iter()
186 .map(|receipt| receipt.receipt_id.to_string())
187 .collect();
188 bundle.tool_receipts = self
189 .tool_call_receipts
190 .iter()
191 .map(|receipt| receipt.receipt_id.to_string())
192 .collect();
193 bundle.permit_receipts = self
194 .tool_call_receipts
195 .iter()
196 .map(|receipt| format!("permit-use:{}", receipt.receipt_id))
197 .collect();
198 bundle.memory_grounding_receipts = memory_grounding_receipts;
199 bundle.verification_receipts = self
200 .verification_receipts
201 .iter()
202 .map(|receipt| receipt.receipt_id.to_string())
203 .collect();
204 bundle.abstention_receipts = self
205 .abstention_receipt
206 .as_ref()
207 .map(|receipt| vec![receipt.receipt_id.to_string()])
208 .unwrap_or_default();
209 bundle.repair_plan_receipts = self
210 .repair_plan
211 .as_ref()
212 .map(|receipt| vec![receipt.repair_id.to_string()])
213 .unwrap_or_default();
214 bundle.outputs = outputs;
215 bundle.replay_instructions = replay_instructions;
216 bundle.blocked_checks = blocked_checks;
217 bundle
218 }
219}