Skip to main content

yoagent_state/
patch.rs

1use crate::{ActorRef, ArtifactRef, NodeId, PatchId};
2use serde::{Deserialize, Serialize};
3use serde_json::Value as JsonValue;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
6pub enum StateOp {
7    CreateNode {
8        id: NodeId,
9        kind: String,
10        props: JsonValue,
11    },
12    UpdateNode {
13        id: NodeId,
14        props: JsonValue,
15    },
16    TombstoneNode {
17        id: NodeId,
18        reason: String,
19    },
20    CreateRelation {
21        from: NodeId,
22        rel: String,
23        to: NodeId,
24        props: JsonValue,
25    },
26    DeleteRelation {
27        from: NodeId,
28        rel: String,
29        to: NodeId,
30    },
31    MarkStale {
32        id: NodeId,
33        reason: String,
34    },
35    AttachArtifact {
36        id: NodeId,
37        artifact: ArtifactRef,
38    },
39}
40
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
42pub struct StatePatch {
43    pub id: PatchId,
44    pub title: String,
45    pub summary: String,
46    pub base_state_version: u64,
47    pub base_project_ref: Option<ProjectRef>,
48    pub ops: Vec<StateOp>,
49    pub preconditions: Vec<Precondition>,
50    pub expected_effects: Vec<ExpectedEffect>,
51    pub evidence: Vec<NodeId>,
52    pub artifacts: Vec<ArtifactRef>,
53    pub status: PatchStatus,
54    pub created_by: ActorRef,
55}
56
57impl StatePatch {
58    pub fn new(
59        id: PatchId,
60        title: impl Into<String>,
61        summary: impl Into<String>,
62        created_by: ActorRef,
63    ) -> Self {
64        Self {
65            id,
66            title: title.into(),
67            summary: summary.into(),
68            base_state_version: 0,
69            base_project_ref: None,
70            ops: Vec::new(),
71            preconditions: Vec::new(),
72            expected_effects: Vec::new(),
73            evidence: Vec::new(),
74            artifacts: Vec::new(),
75            status: PatchStatus::Proposed,
76            created_by,
77        }
78    }
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
82pub enum PatchStatus {
83    Proposed,
84    AppliedInFork,
85    Evaluated,
86    Approved,
87    Rejected,
88    Promoted,
89    Stale,
90    Conflicted,
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94pub struct ProjectRef {
95    pub repo: String,
96    pub branch: Option<String>,
97    pub commit: Option<String>,
98    pub worktree: Option<String>,
99}
100
101#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
102pub enum Precondition {
103    StateVersionIs(u64),
104    ProjectCommitIs(String),
105    NodeExists(NodeId),
106    NodeDoesNotExist(NodeId),
107    TestStillFailing { name: String },
108    FileHashIs { path: String, hash: String },
109}
110
111#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
112pub enum ExpectedEffect {
113    TestPasses { name: String },
114    EvalScoreAtLeast { metric: String, value: f64 },
115    FailureResolved { failure: NodeId },
116    NoRegression { metric: String },
117}