1use schemars::JsonSchema;
19use serde::{Deserialize, Serialize};
20use serde_json::Value as JsonValue;
21
22use super::{
23 BlockingState, CliSpec, Config, GitPublishMode, GitRevertMode, QueueFile, RunnerApprovalMode,
24 Task,
25};
26
27pub const MACHINE_SYSTEM_INFO_VERSION: u32 = 1;
28pub const MACHINE_QUEUE_READ_VERSION: u32 = 1;
29pub const MACHINE_QUEUE_VALIDATE_VERSION: u32 = 1;
30pub const MACHINE_QUEUE_REPAIR_VERSION: u32 = 1;
31pub const MACHINE_QUEUE_UNDO_VERSION: u32 = 1;
32pub const MACHINE_CONFIG_RESOLVE_VERSION: u32 = 3;
33pub const MACHINE_TASK_CREATE_VERSION: u32 = 1;
34pub const MACHINE_TASK_MUTATION_VERSION: u32 = 2;
35pub const MACHINE_GRAPH_READ_VERSION: u32 = 1;
36pub const MACHINE_DASHBOARD_READ_VERSION: u32 = 1;
37pub const MACHINE_DECOMPOSE_VERSION: u32 = 2;
38pub const MACHINE_RUN_EVENT_VERSION: u32 = 3;
39pub const MACHINE_RUN_SUMMARY_VERSION: u32 = 2;
40pub const MACHINE_DOCTOR_REPORT_VERSION: u32 = 2;
41pub const MACHINE_PARALLEL_STATUS_VERSION: u32 = 2;
42pub const MACHINE_CLI_SPEC_VERSION: u32 = 2;
43
44#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
45#[serde(deny_unknown_fields)]
46pub struct MachineSystemInfoDocument {
47 pub version: u32,
48 pub cli_version: String,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
52#[serde(deny_unknown_fields)]
53pub struct MachineQueuePaths {
54 pub repo_root: String,
55 pub queue_path: String,
56 pub done_path: String,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub project_config_path: Option<String>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub global_config_path: Option<String>,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
64#[serde(deny_unknown_fields)]
65pub struct MachineQueueReadDocument {
66 pub version: u32,
67 pub paths: MachineQueuePaths,
68 pub active: QueueFile,
69 pub done: QueueFile,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub next_runnable_task_id: Option<String>,
72 #[schemars(schema_with = "json_value_schema")]
73 pub runnability: JsonValue,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
77#[serde(deny_unknown_fields)]
78pub struct MachineContinuationAction {
79 pub title: String,
80 pub command: String,
81 pub detail: String,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
85#[serde(deny_unknown_fields)]
86pub struct MachineContinuationSummary {
87 pub headline: String,
88 pub detail: String,
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub blocking: Option<BlockingState>,
91 #[serde(default)]
92 pub next_steps: Vec<MachineContinuationAction>,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
96#[serde(deny_unknown_fields)]
97pub struct MachineValidationWarning {
98 pub task_id: String,
99 pub message: String,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
103#[serde(deny_unknown_fields)]
104pub struct MachineQueueValidateDocument {
105 pub version: u32,
106 pub valid: bool,
107 #[serde(skip_serializing_if = "Option::is_none")]
108 pub blocking: Option<BlockingState>,
109 #[serde(default)]
110 pub warnings: Vec<MachineValidationWarning>,
111 pub continuation: MachineContinuationSummary,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
115#[serde(deny_unknown_fields)]
116pub struct MachineQueueRepairDocument {
117 pub version: u32,
118 pub dry_run: bool,
119 pub changed: bool,
120 #[serde(skip_serializing_if = "Option::is_none")]
121 pub blocking: Option<BlockingState>,
122 #[schemars(schema_with = "json_value_schema")]
123 pub report: JsonValue,
124 pub continuation: MachineContinuationSummary,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
128#[serde(deny_unknown_fields)]
129pub struct MachineQueueUndoDocument {
130 pub version: u32,
131 pub dry_run: bool,
132 pub restored: bool,
133 #[serde(skip_serializing_if = "Option::is_none")]
134 pub blocking: Option<BlockingState>,
135 #[schemars(schema_with = "option_json_value_schema")]
136 #[serde(skip_serializing_if = "Option::is_none")]
137 pub result: Option<JsonValue>,
138 pub continuation: MachineContinuationSummary,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
142#[serde(deny_unknown_fields)]
143pub struct MachineResumeDecision {
144 pub status: String,
145 pub scope: String,
146 pub reason: String,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub task_id: Option<String>,
149 pub message: String,
150 pub detail: String,
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
154#[serde(deny_unknown_fields)]
155pub struct MachineConfigResolveDocument {
156 pub version: u32,
157 pub paths: MachineQueuePaths,
158 pub safety: MachineConfigSafetySummary,
159 pub config: Config,
160 #[serde(skip_serializing_if = "Option::is_none")]
161 pub resume_preview: Option<MachineResumeDecision>,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
165#[serde(deny_unknown_fields)]
166pub struct MachineConfigSafetySummary {
167 pub repo_trusted: bool,
168 pub dirty_repo: bool,
169 pub git_publish_mode: GitPublishMode,
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub approval_mode: Option<RunnerApprovalMode>,
172 pub ci_gate_enabled: bool,
173 pub git_revert_mode: GitRevertMode,
174 pub parallel_configured: bool,
175 pub execution_interactivity: String,
176 pub interactive_approval_supported: bool,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
180#[serde(deny_unknown_fields)]
181pub struct MachineCliSpecDocument {
182 pub version: u32,
183 pub spec: CliSpec,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
187#[serde(deny_unknown_fields)]
188pub struct MachineTaskCreateRequest {
189 pub version: u32,
190 pub title: String,
191 #[serde(skip_serializing_if = "Option::is_none")]
192 pub description: Option<String>,
193 pub priority: String,
194 #[serde(default)]
195 pub tags: Vec<String>,
196 #[serde(default, skip_serializing_if = "Vec::is_empty")]
197 pub scope: Vec<String>,
198 #[serde(skip_serializing_if = "Option::is_none")]
199 pub template: Option<String>,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 pub target: Option<String>,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
205#[serde(deny_unknown_fields)]
206pub struct MachineTaskCreateDocument {
207 pub version: u32,
208 pub task: Task,
209}
210
211#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
212#[serde(deny_unknown_fields)]
213pub struct MachineTaskMutationDocument {
214 pub version: u32,
215 #[serde(skip_serializing_if = "Option::is_none")]
216 pub blocking: Option<BlockingState>,
217 #[schemars(schema_with = "json_value_schema")]
218 pub report: JsonValue,
219 pub continuation: MachineContinuationSummary,
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
223#[serde(deny_unknown_fields)]
224pub struct MachineGraphReadDocument {
225 pub version: u32,
226 #[schemars(schema_with = "json_value_schema")]
227 pub graph: JsonValue,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
231#[serde(deny_unknown_fields)]
232pub struct MachineDashboardReadDocument {
233 pub version: u32,
234 #[schemars(schema_with = "json_value_schema")]
235 pub dashboard: JsonValue,
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
239#[serde(deny_unknown_fields)]
240pub struct MachineDecomposeDocument {
241 pub version: u32,
242 #[serde(skip_serializing_if = "Option::is_none")]
243 pub blocking: Option<BlockingState>,
244 #[schemars(schema_with = "json_value_schema")]
245 pub result: JsonValue,
246 pub continuation: MachineContinuationSummary,
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
250#[serde(deny_unknown_fields)]
251pub struct MachineDoctorReportDocument {
252 pub version: u32,
253 #[serde(skip_serializing_if = "Option::is_none")]
254 pub blocking: Option<BlockingState>,
255 #[schemars(schema_with = "json_value_schema")]
256 pub report: JsonValue,
257}
258
259#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
260#[serde(deny_unknown_fields)]
261pub struct MachineParallelStatusDocument {
262 pub version: u32,
263 #[serde(skip_serializing_if = "Option::is_none")]
264 pub blocking: Option<BlockingState>,
265 pub continuation: MachineContinuationSummary,
266 #[schemars(schema_with = "json_value_schema")]
267 pub status: JsonValue,
268}
269
270#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
271#[serde(rename_all = "snake_case")]
272pub enum MachineRunEventKind {
273 RunStarted,
274 QueueSnapshot,
275 ConfigResolved,
276 ResumeDecision,
277 TaskSelected,
278 PhaseEntered,
279 PhaseCompleted,
280 RunnerOutput,
281 BlockedStateChanged,
282 BlockedStateCleared,
283 Warning,
284 RunFinished,
285}
286
287#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
288#[serde(deny_unknown_fields)]
289pub struct MachineRunEventEnvelope {
290 pub version: u32,
291 pub kind: MachineRunEventKind,
292 pub timestamp: String,
293 #[serde(skip_serializing_if = "Option::is_none")]
294 pub run_mode: Option<String>,
295 #[serde(skip_serializing_if = "Option::is_none")]
296 pub task_id: Option<String>,
297 #[serde(skip_serializing_if = "Option::is_none")]
298 pub phase: Option<String>,
299 #[serde(skip_serializing_if = "Option::is_none")]
300 pub exit_code: Option<i32>,
301 #[serde(skip_serializing_if = "Option::is_none")]
302 pub message: Option<String>,
303 #[serde(skip_serializing_if = "Option::is_none")]
304 pub stream: Option<String>,
305 #[schemars(schema_with = "option_json_value_schema")]
306 #[serde(skip_serializing_if = "Option::is_none")]
307 pub payload: Option<JsonValue>,
308}
309
310#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
311#[serde(deny_unknown_fields)]
312pub struct MachineRunSummaryDocument {
313 pub version: u32,
314 pub task_id: Option<String>,
315 pub exit_code: i32,
316 pub outcome: String,
317 #[serde(skip_serializing_if = "Option::is_none")]
318 pub blocking: Option<BlockingState>,
319}
320
321fn json_value_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
322 <JsonValue as JsonSchema>::json_schema(generator)
323}
324
325fn option_json_value_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
326 <Option<JsonValue> as JsonSchema>::json_schema(generator)
327}