ainl_contracts/
learner.rs1use serde::{Deserialize, Serialize};
6
7use crate::vitals::CognitiveVitals;
8use crate::{ContextFreshness, ImpactDecision};
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12pub struct TrajectoryStep {
13 pub step_id: String,
14 pub timestamp_ms: i64,
16 pub adapter: String,
17 pub operation: String,
18 #[serde(default)]
19 pub inputs_preview: Option<String>,
20 #[serde(default)]
21 pub outputs_preview: Option<String>,
22 pub duration_ms: u64,
23 pub success: bool,
24 #[serde(default)]
25 pub error: Option<String>,
26 #[serde(default)]
27 pub vitals: Option<CognitiveVitals>,
28 #[serde(default)]
29 pub freshness_at_step: Option<ContextFreshness>,
30 #[serde(default, skip_serializing_if = "Option::is_none")]
32 pub frame_vars: Option<serde_json::Value>,
33 #[serde(default, skip_serializing_if = "Option::is_none")]
35 pub tool_telemetry: Option<serde_json::Value>,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
40#[serde(rename_all = "snake_case")]
41pub enum TrajectoryOutcome {
42 Success,
43 PartialSuccess,
44 Failure,
45 Aborted,
46}
47
48#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
50#[serde(rename_all = "snake_case", tag = "kind", content = "details")]
51pub enum FailureKind {
52 AdapterTypo {
53 offered: String,
54 #[serde(default)]
55 suggestion: Option<String>,
56 },
57 ValidatorReject {
58 rule: String,
59 },
60 AdapterTimeout {
61 adapter: String,
62 ms: u64,
63 },
64 ToolError {
65 tool: String,
66 message: String,
67 },
68 LoopGuardFire {
69 tool: String,
70 repeat_count: u32,
71 },
72 Other {
73 message: String,
74 },
75}
76
77#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79pub struct ProposalEnvelope {
80 pub schema_version: u32,
81 pub original_hash: String,
82 pub proposed_hash: String,
83 pub kind: String,
84 pub rationale: String,
85 pub freshness_at_proposal: ContextFreshness,
86 pub impact_decision: ImpactDecision,
87}