@team-agent/installer 0.5.94 → 0.5.98
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.
- package/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/crates/team-agent/src/cli/adapters.rs +381 -214
- package/crates/team-agent/src/cli/diagnose.rs +40 -10
- package/crates/team-agent/src/cli/emit.rs +6 -26
- package/crates/team-agent/src/cli/mod.rs +114 -30
- package/crates/team-agent/src/cli/spec.rs +2 -5
- package/crates/team-agent/src/cli/tests/base.rs +20 -10
- package/crates/team-agent/src/cli/tests/divergence.rs +12 -21
- package/crates/team-agent/src/cli/tests/main_preserved.rs +6 -1
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +20 -11
- package/crates/team-agent/src/cli/tests/mod.rs +0 -1
- package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +43 -0
- package/crates/team-agent/src/cli/triage.rs +31 -31
- package/crates/team-agent/src/cli/types.rs +3 -9
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +26 -0
- package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +10 -4
- package/crates/team-agent/src/lifecycle/tests/restart_build_before_destroy_0540_contract.rs +128 -11
- package/package.json +4 -4
- package/skills/team-agent/references/team-agent-operator.md +20 -28
- package/crates/team-agent/src/cli/tests/compile.rs +0 -192
|
@@ -55,7 +55,7 @@ When the user has been communicating in Chinese throughout the conversation, all
|
|
|
55
55
|
|
|
56
56
|
## Minimal Copy-Paste Team
|
|
57
57
|
|
|
58
|
-
`dangerously_skip_permissions` is **required** on every role doc (boolean). `TEAM.md` `dangerous_auto_approve` is **not** the 0.5.66 bypass switch (see Permissions). Values under `provider_models:` below are **fill-ins for omitted role `model`**, not a validity catalog
|
|
58
|
+
`dangerously_skip_permissions` is **required** on every role doc (boolean). `TEAM.md` `dangerous_auto_approve` is **not** the 0.5.66 bypass switch (see Permissions). Values under `provider_models:` below are **fill-ins for omitted role `model`**, not a validity catalog; the values are configuration fallbacks.
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
61
|
mkdir -p .team/current/agents
|
|
@@ -179,7 +179,7 @@ codex debug models
|
|
|
179
179
|
|
|
180
180
|
That command is the Codex catalog. This skill does **not** keep a model id list. If `codex` is not on PATH, the lookup is unavailable; do not invent slugs.
|
|
181
181
|
|
|
182
|
-
Role docs may omit `model` for non-grok subscription workers; compile then fills from `TEAM.md` `provider_models` or leaves `null` when a profile is present (see compatible_api). **Do not treat those fill-ins as a validity catalog.** **Grok roles cannot omit `model`** —
|
|
182
|
+
Role docs may omit `model` for non-grok subscription workers; compile then fills from `TEAM.md` `provider_models` or leaves `null` when a profile is present (see compatible_api). **Do not treat those fill-ins as a validity catalog.** **Grok roles cannot omit `model`** — the internal compiler fails closed.
|
|
183
183
|
|
|
184
184
|
Claude: run `claude auth status`; if missing, run `claude auth login`. Team Agent stores Claude worker sessions by passing `--session-id` and resumes with `--resume`.
|
|
185
185
|
Use `provider: claude` or `provider: claude_code` for Claude workers.
|
|
@@ -233,15 +233,17 @@ POST {BASE_URL}/v1/chat/completions
|
|
|
233
233
|
|
|
234
234
|
Fail = report the HTTP/body. Success = leave the id alone. **Do not substitute a different id.**
|
|
235
235
|
|
|
236
|
-
How
|
|
236
|
+
How role `model` and profile `MODEL` are resolved (not a validity list):
|
|
237
|
+
|
|
238
|
+
The internal compiler preserves a role `model:` when present. If it is omitted, provider/team defaults may fill it; a profile-deferred role may remain `null`. A profile's `MODEL` does not override an explicit role model, and the compiler does not compare the two. Actual profile/provider readiness is checked during launch and preflight, not by a public export command.
|
|
239
|
+
|
|
240
|
+
For an existing spec file or team directory at `$d`, run the retained validation:
|
|
237
241
|
|
|
238
242
|
```bash
|
|
239
|
-
team-agent
|
|
243
|
+
team-agent validate "$d" --json
|
|
240
244
|
```
|
|
241
245
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
Recreate: `auth_mode: compatible_api` without `profile` → compile exit 1 `profile is required when auth_mode is 'compatible_api'`. Role `model:` set + `profile:` set → compiled agent `model` is the role string; profile `MODEL` is not read at compile. Role omits `model` + `profile:` → compiled `model: null`. Compile does **not** compare the two. Whether launch refuses a mismatch was **not** spawned-verified.
|
|
246
|
+
A file input runs schema structural validation. A team-directory input internally compiles `TEAM.md` and `agents/*.md` and validates role-document completeness. Neither input writes or exports a spec file.
|
|
245
247
|
|
|
246
248
|
How to check `--auth-mode` literals (the CLI does not print an allow-list on this gauge):
|
|
247
249
|
|
|
@@ -289,26 +291,19 @@ team-agent permission-modes
|
|
|
289
291
|
|
|
290
292
|
Observed (exit 1): `invalid choice: 'permission-modes'`.
|
|
291
293
|
|
|
292
|
-
`team-agent --help` does **not** list `permission_mode`, `TEAM_AGENT_LEADER_BYPASS`, or `dangerous_auto_approve`.
|
|
294
|
+
`team-agent --help` does **not** list `permission_mode`, `TEAM_AGENT_LEADER_BYPASS`, or `dangerous_auto_approve`. Use `team-agent validate "$d" --json` with an existing spec file or team directory; it does not enumerate permission modes.
|
|
293
295
|
|
|
294
296
|
### Live control: role `dangerously_skip_permissions`
|
|
295
297
|
|
|
296
|
-
Required boolean on every role doc. Missing or non-bool fails
|
|
298
|
+
Required boolean on every role doc. Missing or non-bool fails the internal compiler; this is checked again before lifecycle launch.
|
|
297
299
|
|
|
298
|
-
|
|
300
|
+
For an existing spec file, the retained schema check is:
|
|
299
301
|
|
|
300
302
|
```bash
|
|
301
|
-
|
|
302
|
-
printf '%s\n' '---' 'name: t' 'objective: t' 'provider: fake' '---' 'x' > "$d/TEAM.md"
|
|
303
|
-
printf '%s\n' '---' 'name: coder' 'role: Worker' 'provider: fake' 'model: fake' 'auth_mode: subscription' 'tools:' ' - mcp_team' '---' 'b' > "$d/agents/coder.md"
|
|
304
|
-
team-agent compile --team "$d" --out /tmp/ta-compile-out.yaml --json
|
|
303
|
+
team-agent validate "$d" --json
|
|
305
304
|
```
|
|
306
305
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
Non-bool (`dangerously_skip_permissions: bypass`) observed (exit 1): `front matter field dangerously_skip_permissions must be a boolean.`
|
|
310
|
-
|
|
311
|
-
Legal values reachable from that error: **boolean `true` or `false`**. No other literals are accepted.
|
|
306
|
+
With a team-directory input, `validate` internally compiles `TEAM.md` and `agents/*.md` and validates role-document completeness; with a file input, it runs schema structural validation. Neither input writes or exports a spec file. The internal compiler rejects non-bool (`dangerously_skip_permissions: bypass`) and accepts only boolean **`true`** or **`false`**.
|
|
312
307
|
|
|
313
308
|
`true` is the per-worker bypass opt-in. `false` is the default you should copy unless the user explicitly wants prompts skipped.
|
|
314
309
|
|
|
@@ -345,7 +340,7 @@ What the sources actually do (reader can re-open these files):
|
|
|
345
340
|
| `required_dangerously_skip_permissions` | `crates/team-agent/src/compiler.rs` | Compile **requires** role `dangerously_skip_permissions` bool. This is the 0.5.66 worker bypass source. |
|
|
346
341
|
| `resolved_tool_strings_for_command` | `crates/team-agent/src/lifecycle/worker_command_context.rs` | `true` appends tool sentinel `dangerous_auto_approve`; comment: no longer consumes team/runtime/leader `DangerousApproval`. |
|
|
347
342
|
| `provider_bypass_flag` | `crates/team-agent/src/provider/bypass_flags.rs` | **唯一权威**: role `dangerously_skip_permissions: true` decides whether to add a provider bypass argv flag. Maps provider → flag string only. |
|
|
348
|
-
| spec allowed key `permission_mode` | `crates/team-agent/src/model/spec.rs` | Historical; **not consumed** by compiler (comment: 0.5.66 起不再被 compiler 消费)
|
|
343
|
+
| spec allowed key `permission_mode` | `crates/team-agent/src/model/spec.rs` | Historical; **not consumed** by compiler (comment: 0.5.66 起不再被 compiler 消费); the key is absent from the compiled agent spec. |
|
|
349
344
|
| `apply_mcp_auto_approval_env` | `crates/team-agent/src/lifecycle/launch/worker_env.rs` | Writes `TEAM_AGENT_LEADER_BYPASS` `1`/`0` from `DangerousApproval` when source is `LeaderProcess`. Separate from compile. |
|
|
350
345
|
| `worker_spawn_env` test | `crates/team-agent/src/layout/worker_env.rs` | **Strips** inherited `TEAM_AGENT_LEADER_BYPASS` from parent env. |
|
|
351
346
|
| `claude_dangerous_auto_approve` (and siblings) | `crates/team-agent/src/provider/adapters/*.rs` | Adapters look for tool name `dangerous_auto_approve`, not `TEAM.md`. |
|
|
@@ -462,7 +457,7 @@ On success, `send --json` includes `message_id`. The deprecation warning itself
|
|
|
462
457
|
- `team-agent start-agent coder --workspace .` repairs one missing worker window without interrupting other workers.
|
|
463
458
|
- `team-agent doctor` checks local dependencies and provider auth hints.
|
|
464
459
|
- `team-agent results --case CASE_ID` reads reported results for a case.
|
|
465
|
-
- `team-agent
|
|
460
|
+
- `team-agent validate` is hidden from top-level `--help` but `--help` on the verb works; use it to check an existing spec without launching.
|
|
466
461
|
|
|
467
462
|
<!-- command-coverage:normative-start -->
|
|
468
463
|
### Normative command inventory
|
|
@@ -620,16 +615,13 @@ For any non-zero `team-agent` exit, report the command, exit code, last about 20
|
|
|
620
615
|
|
|
621
616
|
**If the error JSON/text includes a structured `action` field, run that `action` first.** This rule does not expire with skill versions.
|
|
622
617
|
|
|
623
|
-
|
|
618
|
+
For an existing spec file or team directory, use the retained validation:
|
|
624
619
|
|
|
625
620
|
```bash
|
|
626
|
-
|
|
627
|
-
printf '%s\n' '---' 'name: t' 'objective: t' 'provider: fake' '---' 'x' > "$d/TEAM.md"
|
|
628
|
-
printf '%s\n' '---' 'name: coder' 'role: Worker' 'provider: fake' 'model: fake' 'auth_mode: subscription' 'tools:' ' - mcp_team' '---' 'b' > "$d/agents/coder.md"
|
|
629
|
-
team-agent compile --team "$d" --out /tmp/ta-failure-rules-compile.yaml --json
|
|
621
|
+
team-agent validate "$d" --json
|
|
630
622
|
```
|
|
631
623
|
|
|
632
|
-
|
|
624
|
+
A validation failure may include a structured `action`; prefer that action over guessing flags.
|
|
633
625
|
|
|
634
626
|
`coordinator.session_missing` is a self-healing transient: run `team-agent status --json`, if `ready` is true (or workers show `running`) continue; do not shutdown and wait.
|
|
635
627
|
|
|
@@ -637,7 +629,7 @@ Observed (exit 1): JSON includes `"ok": false` and `"action": "run \`team-agent
|
|
|
637
629
|
|
|
638
630
|
Examples of `action` observed on this gauge:
|
|
639
631
|
|
|
640
|
-
-
|
|
632
|
+
- add-agent usage failure: `"action": "run \`team-agent doctor\` or inspect the log path shown here"`
|
|
641
633
|
- send with no runtime: `"action": "Run team-agent quick-start/restart in the target workspace, or choose a workspace that has .team/runtime/state.json"`
|
|
642
634
|
- `claim-leader` from a worker pane: `"action": "pane %21 is registered as worker developer-d108; run claim-leader from the leader's own pane, not a worker pane"` (exit 1, `ok: false`, `reason: caller_not_leader_shaped`)
|
|
643
635
|
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
use super::*;
|
|
2
|
-
|
|
3
|
-
fn compile_team_dir(tag: &str) -> std::path::PathBuf {
|
|
4
|
-
let team = tmp_workspace().join(tag);
|
|
5
|
-
std::fs::create_dir_all(team.join("agents")).unwrap();
|
|
6
|
-
std::fs::write(
|
|
7
|
-
team.join("TEAM.md"),
|
|
8
|
-
"---\nname: compileteam\nobjective: Compile probe.\nprovider: fake\n---\n\nCompile team.\n",
|
|
9
|
-
)
|
|
10
|
-
.unwrap();
|
|
11
|
-
std::fs::write(
|
|
12
|
-
team.join("agents").join("worker.md"),
|
|
13
|
-
"---\nname: worker\nrole: Worker\nprovider: fake\nmodel: fake\ntools:\n - mcp_team\ndangerously_skip_permissions: false\n---\n\nWorker role.\n",
|
|
14
|
-
)
|
|
15
|
-
.unwrap();
|
|
16
|
-
team
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
fn compile_team_dir_with_owner_team_id(tag: &str) -> std::path::PathBuf {
|
|
20
|
-
let team = compile_team_dir(tag);
|
|
21
|
-
std::fs::write(
|
|
22
|
-
team.join("TEAM.md"),
|
|
23
|
-
"---\nname: compileteam\nobjective: Compile probe.\nprovider: fake\nowner_team_id: user-set-owner\n---\n\nCompile team.\n",
|
|
24
|
-
)
|
|
25
|
-
.unwrap();
|
|
26
|
-
team
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
#[test]
|
|
30
|
-
fn cmd_compile_json_and_human_match_golden_shape_and_writes_out() {
|
|
31
|
-
let team = compile_team_dir("compile-ok");
|
|
32
|
-
let out = team.parent().unwrap().join("out.yaml");
|
|
33
|
-
let args = CompileArgs {
|
|
34
|
-
team: team.clone(),
|
|
35
|
-
out: out.clone(),
|
|
36
|
-
json: true,
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
let result = cmd_compile(&args).expect("compile");
|
|
40
|
-
assert_eq!(result.exit, ExitCode::Ok);
|
|
41
|
-
assert!(
|
|
42
|
-
out.exists(),
|
|
43
|
-
"compile must write the compiled spec to --out"
|
|
44
|
-
);
|
|
45
|
-
assert!(
|
|
46
|
-
std::fs::read_to_string(&out)
|
|
47
|
-
.unwrap()
|
|
48
|
-
.contains("version: 1"),
|
|
49
|
-
"compiled out file must contain the spec YAML"
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
let json_text = emit(&result.output, true).unwrap();
|
|
53
|
-
let expected_json = format!(
|
|
54
|
-
"{{\n \"agents\": [\n \"worker\"\n ],\n \"ok\": true,\n \"out\": \"{}\",\n \"team_dir\": \"{}\"\n}}",
|
|
55
|
-
out.to_string_lossy(),
|
|
56
|
-
team.to_string_lossy()
|
|
57
|
-
);
|
|
58
|
-
assert_eq!(
|
|
59
|
-
json_text, expected_json,
|
|
60
|
-
"golden --json is sorted pretty JSON"
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
let human_text = emit(&result.output, false).unwrap();
|
|
64
|
-
let expected_human = format!(
|
|
65
|
-
"ok: True\nteam_dir: {}\nout: {}\nagents: [\"worker\"]",
|
|
66
|
-
team.to_string_lossy(),
|
|
67
|
-
out.to_string_lossy()
|
|
68
|
-
);
|
|
69
|
-
assert_eq!(
|
|
70
|
-
human_text, expected_human,
|
|
71
|
-
"golden human output preserves cmd_compile insertion order"
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
#[test]
|
|
76
|
-
fn cmd_compile_ignores_user_owner_team_id_and_emits_warning_event() {
|
|
77
|
-
let team = compile_team_dir_with_owner_team_id("compile-ignored-owner");
|
|
78
|
-
let workspace = team.parent().unwrap().to_path_buf();
|
|
79
|
-
let out = workspace.join("ignored-owner-out.yaml");
|
|
80
|
-
let args = CompileArgs {
|
|
81
|
-
team: team.clone(),
|
|
82
|
-
out: out.clone(),
|
|
83
|
-
json: true,
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
let result = cmd_compile(&args).expect("compile");
|
|
87
|
-
assert_eq!(result.exit, ExitCode::Ok);
|
|
88
|
-
let compiled = std::fs::read_to_string(&out).unwrap();
|
|
89
|
-
assert!(
|
|
90
|
-
!compiled.contains("owner_team_id"),
|
|
91
|
-
"user-set owner_team_id must not be compiled into team.spec.yaml"
|
|
92
|
-
);
|
|
93
|
-
let events = crate::event_log::EventLog::new(&workspace).tail(0).unwrap();
|
|
94
|
-
let event = events
|
|
95
|
-
.iter()
|
|
96
|
-
.find(|event| {
|
|
97
|
-
event.get("event").and_then(serde_json::Value::as_str) == Some("spec.field_ignored")
|
|
98
|
-
})
|
|
99
|
-
.expect("owner_team_id warning event");
|
|
100
|
-
assert_eq!(
|
|
101
|
-
event.get("field").and_then(serde_json::Value::as_str),
|
|
102
|
-
Some("owner_team_id")
|
|
103
|
-
);
|
|
104
|
-
assert_eq!(
|
|
105
|
-
event.get("value").and_then(serde_json::Value::as_str),
|
|
106
|
-
Some("user-set-owner")
|
|
107
|
-
);
|
|
108
|
-
assert_eq!(
|
|
109
|
-
event.get("action").and_then(serde_json::Value::as_str),
|
|
110
|
-
Some("remove owner_team_id from TEAM.md")
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
#[test]
|
|
115
|
-
fn cmd_compile_without_owner_team_id_emits_no_ignored_field_event() {
|
|
116
|
-
let team = compile_team_dir("compile-no-ignored-owner");
|
|
117
|
-
let workspace = team.parent().unwrap().to_path_buf();
|
|
118
|
-
let out = workspace.join("no-ignored-owner-out.yaml");
|
|
119
|
-
let args = CompileArgs {
|
|
120
|
-
team: team.clone(),
|
|
121
|
-
out,
|
|
122
|
-
json: true,
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
let result = cmd_compile(&args).expect("compile");
|
|
126
|
-
assert_eq!(result.exit, ExitCode::Ok);
|
|
127
|
-
let events = crate::event_log::EventLog::new(&workspace).tail(0).unwrap();
|
|
128
|
-
assert!(
|
|
129
|
-
events.iter().all(|event| {
|
|
130
|
-
event.get("event").and_then(serde_json::Value::as_str) != Some("spec.field_ignored")
|
|
131
|
-
}),
|
|
132
|
-
"TEAM.md without owner_team_id must not emit ignored-field warning"
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
#[test]
|
|
137
|
-
fn run_dispatches_compile_and_error_path_exits_error() {
|
|
138
|
-
let team = compile_team_dir("compile-dispatch");
|
|
139
|
-
let out = team.parent().unwrap().join("dispatch.yaml");
|
|
140
|
-
let argv = vec![
|
|
141
|
-
"compile".to_string(),
|
|
142
|
-
"--team".to_string(),
|
|
143
|
-
team.to_string_lossy().to_string(),
|
|
144
|
-
"--out".to_string(),
|
|
145
|
-
out.to_string_lossy().to_string(),
|
|
146
|
-
"--json".to_string(),
|
|
147
|
-
];
|
|
148
|
-
assert_eq!(run(&argv, team.parent().unwrap()), ExitCode::Ok);
|
|
149
|
-
assert!(
|
|
150
|
-
out.exists(),
|
|
151
|
-
"dispatch compile must route to cmd_compile and write --out"
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
let bad = tmp_workspace().join("compile-bad");
|
|
155
|
-
std::fs::create_dir_all(bad.join("agents")).unwrap();
|
|
156
|
-
std::fs::write(
|
|
157
|
-
bad.join("TEAM.md"),
|
|
158
|
-
"---\nname: badteam\nobjective: Bad.\nprovider: fake\n---\n",
|
|
159
|
-
)
|
|
160
|
-
.unwrap();
|
|
161
|
-
std::fs::write(
|
|
162
|
-
bad.join("agents").join("broken.md"),
|
|
163
|
-
"---\nname: broken\nrole: Broken\nmodel: fake\n---\n",
|
|
164
|
-
)
|
|
165
|
-
.unwrap();
|
|
166
|
-
let bad_out = bad.parent().unwrap().join("bad.yaml");
|
|
167
|
-
let bad_args = CompileArgs {
|
|
168
|
-
team: bad.clone(),
|
|
169
|
-
out: bad_out.clone(),
|
|
170
|
-
json: true,
|
|
171
|
-
};
|
|
172
|
-
let err = cmd_compile(&bad_args).unwrap_err().to_string();
|
|
173
|
-
assert!(
|
|
174
|
-
err.contains("missing front matter field provider"),
|
|
175
|
-
"got {err}"
|
|
176
|
-
);
|
|
177
|
-
assert_eq!(
|
|
178
|
-
run(
|
|
179
|
-
&[
|
|
180
|
-
"compile".to_string(),
|
|
181
|
-
"--team".to_string(),
|
|
182
|
-
bad.to_string_lossy().to_string(),
|
|
183
|
-
"--out".to_string(),
|
|
184
|
-
bad_out.to_string_lossy().to_string(),
|
|
185
|
-
"--json".to_string(),
|
|
186
|
-
],
|
|
187
|
-
bad.parent().unwrap(),
|
|
188
|
-
),
|
|
189
|
-
ExitCode::Error,
|
|
190
|
-
"invalid compile input must exit 1, not fall through as an unknown subcommand"
|
|
191
|
-
);
|
|
192
|
-
}
|