@team-agent/installer 0.5.31 → 0.5.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,238 +0,0 @@
1
- use super::*;
2
-
3
- const SETTLE_SPEC_TEMPLATE: &str = r#"version: 1
4
- team:
5
- name: "fake-e2e"
6
- mode: "supervisor_worker"
7
- objective: "Exercise settle."
8
- workspace: "__WS__"
9
- leader:
10
- id: "leader"
11
- role: "leader"
12
- provider: "fake"
13
- model: null
14
- tools:
15
- - "fs_read"
16
- - "fs_list"
17
- - "mcp_team"
18
- context_policy:
19
- keep_user_thread: true
20
- receive_worker_outputs: "structured_only"
21
- max_worker_result_tokens: 2000
22
- agents:
23
- - id: "fake_impl"
24
- role: "implementation_engineer"
25
- provider: "fake"
26
- model: null
27
- working_directory: "__WS__"
28
- system_prompt:
29
- inline: "Handle fake implementation tasks."
30
- file: null
31
- tools:
32
- - "fs_read"
33
- - "fs_write"
34
- - "fs_list"
35
- - "execute_bash"
36
- - "git_diff"
37
- - "mcp_team"
38
- - "provider_builtin"
39
- permission_mode: "restricted"
40
- preferred_for:
41
- - "implementation"
42
- avoid_for: []
43
- output_contract:
44
- format: "result_envelope_v1"
45
- required_fields:
46
- - "task_id"
47
- - "status"
48
- - "summary"
49
- - "artifacts"
50
- routing:
51
- default_assignee: "leader"
52
- rules:
53
- - id: "implementation-to-fake"
54
- match:
55
- type:
56
- - "implementation"
57
- assign_to: "fake_impl"
58
- priority: 10
59
- communication:
60
- protocol: "mcp_inbox"
61
- topology: "leader_centered"
62
- worker_to_worker: true
63
- ack_timeout_sec: 2
64
- result_format: "result_envelope_v1"
65
- message_store:
66
- sqlite: ".team/runtime/team.db"
67
- mirror_files: ".team/messages"
68
- runtime:
69
- backend: "tmux"
70
- display_backend: "none"
71
- session_name: "team-agent-fake-e2e"
72
- auto_launch: true
73
- require_user_approval_before_launch: false
74
- max_active_agents: 1
75
- startup_order:
76
- - "fake_impl"
77
- context:
78
- state_file: "team_state.md"
79
- artifact_dir: ".team/artifacts"
80
- log_dir: ".team/logs"
81
- summarization:
82
- worker_full_logs: "retain_outside_leader_context"
83
- state_update: "after_each_result"
84
- tasks:
85
- - id: "task_impl"
86
- title: "Fake implementation"
87
- type: "implementation"
88
- assignee: null
89
- deps: []
90
- acceptance:
91
- - "fake result collected"
92
- status: "pending"
93
- "#;
94
-
95
- fn seed_settle_workspace(ws: &std::path::Path) {
96
- std::fs::create_dir_all(ws.join(".team").join("logs")).unwrap();
97
- std::fs::create_dir_all(ws.join(".team").join("runtime")).unwrap();
98
- std::fs::write(
99
- ws.join("team.spec.yaml"),
100
- SETTLE_SPEC_TEMPLATE.replace("__WS__", &ws.to_string_lossy()),
101
- )
102
- .unwrap();
103
- crate::state::persist::save_runtime_state(
104
- ws,
105
- &json!({
106
- "spec_path": ws.join("team.spec.yaml").to_string_lossy(),
107
- "session_name": "team-agent-fake-e2e",
108
- "leader": {"id": "leader"},
109
- "agents": {"fake_impl": {"status": "stopped", "provider": "fake"}},
110
- "tasks": [{
111
- "id": "task_impl",
112
- "title": "Fake implementation",
113
- "type": "implementation",
114
- "assignee": null,
115
- "deps": [],
116
- "acceptance": ["fake result collected"],
117
- "status": "pending"
118
- }]
119
- }),
120
- )
121
- .unwrap();
122
- }
123
-
124
- // Golden source:
125
- // - cli/parser.py:177-180 registers `settle --workspace . --json`; no timeout or polling args.
126
- // - cli/commands.py:86-87 delegates to `runtime.settle(Path(args.workspace).resolve())`.
127
- // - diagnose/quick_start.py:269-284: `settle` synchronously calls `collect(workspace)`,
128
- // then `status(workspace, as_json=True)`, writes `settle-<int(time.time())>.json`,
129
- // and returns `{ok, summary, next_actions, details_log, collect}`.
130
- // - cli/helpers.py:12-16 success `--json` uses pretty sorted JSON; human output uses dict
131
- // insertion order from the returned dict.
132
- //
133
- // Golden probe:
134
- // PYTHONPATH=/Users/alauda/Documents/code/team-agent-public/src python3 /tmp/probe_settle_cli.py
135
- // With a fake `tmux` executable returning exit 1, golden exits 0 and reports
136
- // summary `collected 0 result(s)`.
137
- #[test]
138
- fn settle_success_json_byte_shape_wraps_collect() {
139
- let ws = tmp_workspace();
140
- seed_settle_workspace(&ws);
141
-
142
- let result = cmd_settle(&SettleArgs {
143
- team: None,
144
- workspace: ws.clone(),
145
- json: true,
146
- })
147
- .expect("settle should return an ok result for an empty valid workspace");
148
-
149
- assert_eq!(result.exit, ExitCode::Ok);
150
- let CmdOutput::Json(value) = &result.output else {
151
- panic!("settle must return a JSON dict");
152
- };
153
- assert_eq!(value["ok"], json!(true));
154
- assert_eq!(value["summary"], json!("collected 0 result(s)"));
155
- assert_eq!(
156
- value["next_actions"],
157
- json!(["Review team_state.md and decide whether to continue or shutdown."])
158
- );
159
- assert!(
160
- value["details_log"]
161
- .as_str()
162
- .is_some_and(|p| p.contains("/.team/logs/settle-") && p.ends_with(".json")),
163
- "settle must write a settle-<timestamp>.json details log; got {value}",
164
- );
165
- assert_eq!(value["collect"]["ok"], json!(true));
166
- assert_eq!(value["collect"]["collected"], json!([]));
167
- assert_eq!(value["collect"]["collected_results"], json!([]));
168
- assert_eq!(value["collect"]["delivered_messages"], json!([]));
169
- assert_eq!(value["collect"]["invalid_results"], json!([]));
170
- assert_eq!(
171
- value["collect"]["results"],
172
- json!({
173
- "total": 0,
174
- "uncollected": 0,
175
- "collected": 0,
176
- "invalid": 0,
177
- "by_status": {},
178
- })
179
- );
180
- assert_eq!(
181
- value["collect"]["state_file"],
182
- json!(ws.join("team_state.md").to_string_lossy().to_string())
183
- );
184
- assert_eq!(value["collect"]["coordinator"]["ok"], json!(true));
185
- assert_eq!(value["collect"]["coordinator"]["status"], json!("started"));
186
- assert!(
187
- value["collect"]["coordinator"]["log"]
188
- .as_str()
189
- .is_some_and(|p| p.ends_with("/.team/runtime/coordinator.log")),
190
- "collect.coordinator.log must point at .team/runtime/coordinator.log; got {value}",
191
- );
192
-
193
- let expected = serde_json::to_string_pretty(&crate::cli::sort_json(value)).unwrap();
194
- assert_eq!(
195
- emit(&result.output, true).unwrap(),
196
- expected,
197
- "settle --json must emit Python's json.dumps(indent=2, sort_keys=True) byte shape",
198
- );
199
- let _ = std::fs::remove_dir_all(&ws);
200
- }
201
-
202
- #[test]
203
- fn settle_success_human_output_insertion_order() {
204
- let ws = tmp_workspace();
205
- seed_settle_workspace(&ws);
206
-
207
- let result = cmd_settle(&SettleArgs {
208
- team: None,
209
- workspace: ws.clone(),
210
- json: false,
211
- })
212
- .expect("settle should return an ok result for an empty valid workspace");
213
-
214
- let human = emit(&result.output, false).unwrap();
215
- assert!(
216
- human.starts_with(
217
- "ok: True\nsummary: collected 0 result(s)\nnext_actions: [\"Review team_state.md and decide whether to continue or shutdown.\"]\ndetails_log: "
218
- ),
219
- "non-json settle output must preserve Python returned-dict insertion order; got {human}",
220
- );
221
- assert!(
222
- human.contains("\ncollect: {\"ok\": true, \"collected\": [], \"collected_results\": []"),
223
- "non-json settle output must render nested collect as compact JSON after details_log; got {human}",
224
- );
225
- let _ = std::fs::remove_dir_all(&ws);
226
- }
227
-
228
- // Golden source:
229
- // - cli/parser.py:177-180 default workspace is `.`.
230
- // Current Rust dispatch has no `settle` arm; this must be RED until the porter routes it.
231
- #[test]
232
- fn dispatch_routes_settle_default_workspace() {
233
- let ws = tmp_workspace();
234
- seed_settle_workspace(&ws);
235
- let code = run(&["settle".to_string(), "--json".to_string()], &ws);
236
- assert_eq!(code, ExitCode::Ok, "`settle --json` must route and exit 0 for default workspace");
237
- let _ = std::fs::remove_dir_all(&ws);
238
- }