@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.
@@ -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 (lookup: `team-agent compile --team <dir> --out /tmp/spec.yaml --json` and read the compiled agent `model`).
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`** — compile fails closed (same `compile --team` command as below).
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 compile currently wires role `model` vs profile `MODEL` (not a validity list):
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 compile --help
243
+ team-agent validate "$d" --json
240
244
  ```
241
245
 
242
- Observed (exit 0): `usage: team-agent compile --team TEAM [--out FILE] [--json]`.
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`. Lookup is `team-agent compile` / `team-agent validate` on a throwaway team dir, not a flag enum.
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 compile.
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
- Recreate:
300
+ For an existing spec file, the retained schema check is:
299
301
 
300
302
  ```bash
301
- d=$(mktemp -d) && mkdir -p "$d/agents"
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
- Observed (exit 1): `missing front matter field dangerously_skip_permissions. This field must be declared explicitly; it controls whether the agent launches with permission prompts bypassed.` JSON also includes `"action": "run \`team-agent doctor\` or inspect the log path shown here"`.
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 消费). CLI compile of `permission_mode: bypass` and `permission_mode: not-a-mode` both `ok: true` with the key absent from spec. |
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 compile` / `team-agent validate` are hidden from top-level `--help` but `--help` on those verbs works; use them to check role docs without launching.
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
- Reproduce a structured `action` (missing `dangerously_skip_permissions` → compile JSON):
618
+ For an existing spec file or team directory, use the retained validation:
624
619
 
625
620
  ```bash
626
- d=$(mktemp -d) && mkdir -p "$d/agents"
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
- Observed (exit 1): JSON includes `"ok": false` and `"action": "run \`team-agent doctor\` or inspect the log path shown here"`, plus `missing front matter field dangerously_skip_permissions`. Prefer the `action` over guessing flags.
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
- - compile/add-agent usage failure: `"action": "run \`team-agent doctor\` or inspect the log path shown here"`
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
- }