orchestrator_config/config/
spawn.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5pub struct SpawnTaskAction {
6 pub goal: String,
8 #[serde(default, skip_serializing_if = "Option::is_none")]
10 pub workflow: Option<String>,
11 #[serde(default)]
13 pub inherit: SpawnInherit,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
18pub struct SpawnTasksAction {
19 pub from_var: String,
21 pub json_path: String,
23 pub mapping: SpawnMapping,
25 #[serde(default)]
27 pub inherit: SpawnInherit,
28 #[serde(default = "default_max_tasks")]
30 pub max_tasks: usize,
31 #[serde(default = "default_true")]
33 pub queue: bool,
34}
35
36fn default_max_tasks() -> usize {
37 5
38}
39
40fn default_true() -> bool {
41 true
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
46pub struct SpawnMapping {
47 pub goal: String,
49 #[serde(default, skip_serializing_if = "Option::is_none")]
51 pub workflow: Option<String>,
52 #[serde(default, skip_serializing_if = "Option::is_none")]
54 pub name: Option<String>,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
59pub struct SpawnInherit {
60 #[serde(default = "default_inherit_true")]
62 pub workspace: bool,
63 #[serde(default = "default_inherit_true")]
65 pub project: bool,
66 #[serde(default)]
68 pub target_files: bool,
69}
70
71fn default_inherit_true() -> bool {
72 true
73}
74
75impl Default for SpawnInherit {
76 fn default() -> Self {
77 Self {
78 workspace: true,
79 project: true,
80 target_files: false,
81 }
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_spawn_task_action_minimal() {
91 let json = r#"{"goal": "improve {area}"}"#;
92 let action: SpawnTaskAction = serde_json::from_str(json).expect("deserialize spawn task");
93 assert_eq!(action.goal, "improve {area}");
94 assert!(action.workflow.is_none());
95 assert!(action.inherit.workspace);
96 assert!(action.inherit.project);
97 assert!(!action.inherit.target_files);
98 }
99
100 #[test]
101 fn test_spawn_tasks_action_defaults() {
102 let json = r#"{
103 "from_var": "goals_output",
104 "json_path": "$.goals",
105 "mapping": {"goal": "$.description"}
106 }"#;
107 let action: SpawnTasksAction = serde_json::from_str(json).expect("deserialize spawn tasks");
108 assert_eq!(action.max_tasks, 5);
109 assert!(action.queue);
110 assert!(action.inherit.workspace);
111 }
112
113 #[test]
114 fn test_spawn_inherit_default() {
115 let inherit = SpawnInherit::default();
116 assert!(inherit.workspace);
117 assert!(inherit.project);
118 assert!(!inherit.target_files);
119 }
120
121 #[test]
122 fn test_spawn_tasks_action_full() {
123 let json = r#"{
124 "from_var": "analysis",
125 "json_path": "$.tasks",
126 "mapping": {
127 "goal": "$.goal",
128 "workflow": "$.workflow",
129 "name": "$.name"
130 },
131 "inherit": {"workspace": true, "project": false, "target_files": true},
132 "max_tasks": 10,
133 "queue": false
134 }"#;
135 let action: SpawnTasksAction =
136 serde_json::from_str(json).expect("deserialize full spawn tasks");
137 assert_eq!(action.max_tasks, 10);
138 assert!(!action.queue);
139 assert!(!action.inherit.project);
140 assert!(action.inherit.target_files);
141 }
142}