@team-agent/installer 0.5.85 → 0.5.89

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.
Files changed (63) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/adapters.rs +2 -2
  4. package/crates/team-agent/src/cli/emit.rs +56 -12
  5. package/crates/team-agent/src/cli/mod.rs +0 -1
  6. package/crates/team-agent/src/cli/status_port/brief.rs +187 -7
  7. package/crates/team-agent/src/compiler/tests.rs +13 -24
  8. package/crates/team-agent/src/compiler.rs +5 -57
  9. package/crates/team-agent/src/leader/start.rs +0 -2
  10. package/crates/team-agent/src/lifecycle/launch/add_agent.rs +0 -1
  11. package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +0 -1
  12. package/crates/team-agent/src/lifecycle/launch/agent_state.rs +0 -6
  13. package/crates/team-agent/src/lifecycle/launch/identity.rs +39 -22
  14. package/crates/team-agent/src/lifecycle/launch/layout.rs +0 -1
  15. package/crates/team-agent/src/lifecycle/launch/leader_context.rs +0 -1
  16. package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +0 -58
  17. package/crates/team-agent/src/lifecycle/launch/ownership.rs +0 -1
  18. package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +0 -3
  19. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +14 -24
  20. package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +0 -1
  21. package/crates/team-agent/src/lifecycle/launch/readiness.rs +0 -1
  22. package/crates/team-agent/src/lifecycle/launch/spawn.rs +5 -9
  23. package/crates/team-agent/src/lifecycle/launch/spec_state.rs +0 -1
  24. package/crates/team-agent/src/lifecycle/launch/state_projection.rs +0 -1
  25. package/crates/team-agent/src/lifecycle/launch/worker_env.rs +0 -1
  26. package/crates/team-agent/src/lifecycle/launch.rs +0 -9
  27. package/crates/team-agent/src/lifecycle/restart/common.rs +5 -9
  28. package/crates/team-agent/src/lifecycle/tests/b0_reader_hideone_audit_contract.rs +3 -3
  29. package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +1 -3
  30. package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +42 -46
  31. package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +30 -44
  32. package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +32 -77
  33. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +2 -13
  34. package/crates/team-agent/src/lifecycle/tests/pi_catalog_red.rs +0 -1
  35. package/crates/team-agent/src/lifecycle/tests/pi_command_red.rs +0 -2
  36. package/crates/team-agent/src/lifecycle/tests/pi_compiler_red.rs +14 -85
  37. package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +1 -1
  38. package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +0 -5
  39. package/crates/team-agent/src/lifecycle/tests/pi_session_delivery_red.rs +0 -1
  40. package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +4 -4
  41. package/crates/team-agent/src/lifecycle/tests.rs +0 -1
  42. package/crates/team-agent/src/lifecycle/types.rs +0 -10
  43. package/crates/team-agent/src/lifecycle/worker_command_context.rs +4 -248
  44. package/crates/team-agent/src/model/enums.rs +17 -38
  45. package/crates/team-agent/src/model/mod.rs +0 -1
  46. package/crates/team-agent/src/model/spec.rs +31 -91
  47. package/crates/team-agent/src/provider/adapter.rs +48 -50
  48. package/crates/team-agent/src/provider/adapters/claude.rs +5 -30
  49. package/crates/team-agent/src/provider/adapters/codex.rs +5 -25
  50. package/crates/team-agent/src/provider/adapters/copilot.rs +8 -41
  51. package/crates/team-agent/src/provider/adapters/cursor_agent.rs +4 -8
  52. package/crates/team-agent/src/provider/adapters/grok.rs +5 -58
  53. package/crates/team-agent/src/provider/adapters/mod.rs +5 -7
  54. package/crates/team-agent/src/provider/adapters/pi.rs +1 -56
  55. package/crates/team-agent/src/provider/bypass_flags.rs +1 -2
  56. package/crates/team-agent/src/provider/session/capture.rs +4 -4
  57. package/crates/team-agent/src/provider/tests/adapter.rs +7 -24
  58. package/crates/team-agent/src/provider/types.rs +1 -1
  59. package/crates/team-agent/src/provider/wire.rs +1 -1
  60. package/package.json +4 -4
  61. package/schemas/team.schema.json +4 -9
  62. package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +0 -784
  63. package/crates/team-agent/src/model/permissions.rs +0 -721
@@ -37,7 +37,7 @@ fn bin() -> &'static str {
37
37
 
38
38
  #[test]
39
39
  #[serial(env)]
40
- fn claude_worker_spawn_argv_uses_compiled_prompt_and_resolved_role_tools() {
40
+ fn claude_worker_spawn_argv_uses_compiled_prompt_without_tool_restrictions() {
41
41
  let _hermetic = enter_hermetic("core034-claude-argv");
42
42
  let _ancestry = EnvGuard::set(
43
43
  "TEAM_AGENT_TEST_PROCESS_ANCESTRY_ARGV_JSON",
@@ -80,7 +80,6 @@ fn claude_worker_spawn_argv_uses_compiled_prompt_and_resolved_role_tools() {
80
80
  "send_message(to='leader'",
81
81
  "report_result exactly once",
82
82
  "ROLE BODY SENTINEL",
83
- "Permission note",
84
83
  ] {
85
84
  if !prompt.contains(marker) {
86
85
  failures.push(format!("B2 missing compiled prompt marker {marker:?}"));
@@ -90,31 +89,15 @@ fn claude_worker_spawn_argv_uses_compiled_prompt_and_resolved_role_tools() {
90
89
  failures.push("B2 prompt collapsed to the bare role label".to_string());
91
90
  }
92
91
 
93
- let disallowed = flag_values(&spawn.argv, "--disallowedTools");
94
- for forbidden in [
95
- "Bash",
96
- "Read",
97
- "Edit",
98
- "Write",
99
- "MultiEdit",
100
- "NotebookEdit",
101
- "Glob",
102
- "Grep",
103
- ] {
104
- if disallowed.iter().any(|tool| tool == forbidden) {
105
- failures.push(format!(
106
- "B1 declared capability still disallowed via --disallowedTools {forbidden:?}"
107
- ));
108
- }
92
+ if argv_has_flag(&spawn.argv, "--disallowedTools") {
93
+ failures.push("B1 Claude argv must not derive --disallowedTools from tools metadata".to_string());
109
94
  }
110
95
  if argv_has_flag(&spawn.argv, "--allowedTools") {
111
- failures.push(
112
- "B1 Python parity violated: Claude argv must not switch to --allowedTools".to_string(),
113
- );
96
+ failures.push("B1 Claude argv must not derive --allowedTools from tools metadata".to_string());
114
97
  }
115
98
  assert!(
116
99
  failures.is_empty(),
117
- "B1/B2 worker argv contract failed:\n{}\nprompt={prompt:?}\ndisallowed={disallowed:?}\nargv={:?}",
100
+ "B1/B2 worker argv contract failed:\n{}\nprompt={prompt:?}\nargv={:?}",
118
101
  failures.join("\n"),
119
102
  spawn.argv
120
103
  );
@@ -122,7 +105,7 @@ fn claude_worker_spawn_argv_uses_compiled_prompt_and_resolved_role_tools() {
122
105
 
123
106
  #[test]
124
107
  #[serial(env)]
125
- fn claude_control_role_without_native_tools_still_disallows_native_tools() {
108
+ fn claude_control_role_does_not_derive_native_tool_restrictions() {
126
109
  let _hermetic = enter_hermetic("core034-claude-control");
127
110
  let _ancestry = EnvGuard::set(
128
111
  "TEAM_AGENT_TEST_PROCESS_ANCESTRY_ARGV_JSON",
@@ -156,29 +139,21 @@ fn claude_control_role_without_native_tools_still_disallows_native_tools() {
156
139
  .expect("quick-start should record the control worker command");
157
140
 
158
141
  let spawn = transport.single_spawn();
159
- let disallowed = flag_values(&spawn.argv, "--disallowedTools");
160
- for expected in [
161
- "Bash",
162
- "Read",
163
- "Edit",
164
- "Write",
165
- "MultiEdit",
166
- "NotebookEdit",
167
- "Glob",
168
- "Grep",
169
- ] {
170
- assert!(
171
- disallowed.iter().any(|tool| tool == expected),
172
- "B1 negative case: mcp_team-only control roles must still disallow native Claude tools; \
173
- missing={expected} disallowed={disallowed:?}\nargv={:?}",
174
- spawn.argv
175
- );
176
- }
142
+ assert!(
143
+ !argv_has_flag(&spawn.argv, "--disallowedTools"),
144
+ "B1 control role must not derive native-tool restrictions from tools metadata; argv={:?}",
145
+ spawn.argv
146
+ );
147
+ assert!(
148
+ !argv_has_flag(&spawn.argv, "--allowedTools"),
149
+ "B1 control role must not derive an allowlist from tools metadata; argv={:?}",
150
+ spawn.argv
151
+ );
177
152
  }
178
153
 
179
154
  #[test]
180
155
  #[serial(env)]
181
- fn restart_claude_worker_resolves_tools_from_spec_when_runtime_state_has_no_raw_tools() {
156
+ fn restart_claude_worker_does_not_derive_tool_restrictions_when_runtime_state_has_no_raw_tools() {
182
157
  let _hermetic = enter_hermetic("core034-restart-tools");
183
158
  let _ancestry = EnvGuard::set(
184
159
  "TEAM_AGENT_TEST_PROCESS_ANCESTRY_ARGV_JSON",
@@ -215,34 +190,20 @@ fn restart_claude_worker_resolves_tools_from_spec_when_runtime_state_has_no_raw_
215
190
  let report = restart_with_transport(&ws, true, Some("restarttools"), &restart_transport)
216
191
  .expect("restart should reach worker command construction");
217
192
  let spawn = restart_transport.single_spawn();
218
- let disallowed = flag_values(&spawn.argv, "--disallowedTools");
219
-
220
- for forbidden in [
221
- "Bash",
222
- "Read",
223
- "Edit",
224
- "Write",
225
- "MultiEdit",
226
- "NotebookEdit",
227
- "Glob",
228
- "Grep",
229
- ] {
230
- assert!(
231
- !disallowed.iter().any(|tool| tool == forbidden),
232
- "B1 restart contract: when runtime state lacks raw tools, restart must resolve tools from the selected spec/role through resolve_permissions. \
233
- {forbidden} must not be disallowed for this role; disallowed={disallowed:?}\nargv={:?}\nreport={report:?}",
234
- spawn.argv
235
- );
236
- }
193
+ assert!(
194
+ !argv_has_flag(&spawn.argv, "--disallowedTools"),
195
+ "B1 restart must not derive native-tool restrictions from tools metadata; argv={:?} report={report:?}",
196
+ spawn.argv
197
+ );
237
198
  assert!(
238
199
  !argv_has_flag(&spawn.argv, "--allowedTools"),
239
- "B1 Python parity: restart must keep --disallowedTools semantics, not switch to --allowedTools; argv={:?}",
200
+ "B1 restart must not derive an allowlist from tools metadata; argv={:?} report={report:?}",
240
201
  spawn.argv
241
202
  );
242
203
  }
243
204
 
244
205
  #[test]
245
- fn worker_command_context_uses_single_prompt_and_permission_sources() {
206
+ fn worker_command_context_uses_single_prompt_without_permission_sources() {
246
207
  let crate_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
247
208
  let src_root = crate_root.join("src");
248
209
  let launch = composite_source::composite_source("src/lifecycle/launch.rs");
@@ -276,10 +237,9 @@ fn worker_command_context_uses_single_prompt_and_permission_sources() {
276
237
  && all_src.contains("runtime_contract_section")
277
238
  && all_src.contains("identity_section")
278
239
  && all_src.contains("role_body")
279
- && all_src.contains("output_contract")
280
- && all_src.contains("permission_notes"),
281
- "B2 grep guard: worker command construction needs one compiled prompt helper with the CR-approved five sections \
282
- (runtime_contract_section, identity_section, role_body, output_contract, permission_notes)."
240
+ && all_src.contains("output_contract"),
241
+ "B2 grep guard: worker command construction needs one compiled prompt helper with the CR-approved four sections \
242
+ (runtime_contract_section, identity_section, role_body, output_contract)."
283
243
  );
284
244
  assert!(
285
245
  !command_sources.contains("system_prompt: role"),
@@ -296,8 +256,9 @@ fn worker_command_context_uses_single_prompt_and_permission_sources() {
296
256
  );
297
257
 
298
258
  assert!(
299
- all_src.contains("resolve_permissions") && all_src.contains("resolved_tool_strings"),
300
- "B1 grep guard: command argv tools must be calculated through a single resolve_permissions helper, including role defaults and leader ceiling."
259
+ !command_sources.contains("resolve_permissions")
260
+ && !command_sources.contains("resolved_tool_strings"),
261
+ "B1 grep guard: command construction must not derive argv restrictions from tools metadata."
301
262
  );
302
263
  assert!(
303
264
  !command_sources.contains("worker_tool_refs(agent_tool_strings")
@@ -305,8 +266,8 @@ fn worker_command_context_uses_single_prompt_and_permission_sources() {
305
266
  "B1 grep guard: command construction must not raw-pass agent.tools/tool_refs into ProviderCommandContext."
306
267
  );
307
268
  assert!(
308
- adapter.contains("--disallowedTools") && !adapter.contains("--allowedTools"),
309
- "B1 Python parity: provider adapter must keep Claude --disallowedTools and not invent --allowedTools."
269
+ !adapter.contains("--disallowedTools") && !adapter.contains("--allowedTools"),
270
+ "B1 provider adapter must not derive Claude tool restrictions from tools metadata."
310
271
  );
311
272
  assert!(
312
273
  !adapter.contains("resolve_permissions"),
@@ -837,12 +798,6 @@ fn flag_value(argv: &[String], flag: &str) -> Option<String> {
837
798
  .find_map(|pair| (pair[0] == flag).then(|| pair[1].clone()))
838
799
  }
839
800
 
840
- fn flag_values(argv: &[String], flag: &str) -> Vec<String> {
841
- argv.windows(2)
842
- .filter_map(|pair| (pair[0] == flag).then(|| pair[1].clone()))
843
- .collect()
844
- }
845
-
846
801
  fn argv_has_flag(argv: &[String], flag: &str) -> bool {
847
802
  argv.iter().any(|arg| arg == flag)
848
803
  }
@@ -520,8 +520,8 @@ fn launch_dry_run_resolves_real_plan_not_stub_error() {
520
520
  Ok(report) => {
521
521
  assert!(report.dry_run, "dry_run launch must report dry_run=true");
522
522
  assert!(
523
- !report.routes.is_empty() || !report.permissions.is_empty(),
524
- "dry_run launch must resolve a real route/permission plan from the compiled spec"
523
+ !report.routes.is_empty(),
524
+ "dry_run launch must resolve a real route plan from the compiled spec"
525
525
  );
526
526
  }
527
527
  // any OTHER Err (a real requirement/transport error) still proves the stub is gone.
@@ -3210,7 +3210,6 @@ fn quick_start_running_agent_state_shape_after_spawn_is_golden() {
3210
3210
  "profile",
3211
3211
  "window",
3212
3212
  "mcp_config",
3213
- "permissions",
3214
3213
  "effective_approval_policy",
3215
3214
  // 0.5.66 bypass 单源:fresh spawn 记录运行面 bypass 值(restart drift 挡板)。
3216
3215
  "as_launched_dangerously_skip_permissions",
@@ -3239,16 +3238,6 @@ fn quick_start_running_agent_state_shape_after_spawn_is_golden() {
3239
3238
  .join(".team/runtime/mcp/implementer.json")
3240
3239
  .to_string_lossy())
3241
3240
  );
3242
- assert_eq!(
3243
- agent["permissions"],
3244
- json!({
3245
- "agent_id": "implementer",
3246
- "provider": "codex",
3247
- "tools": ["mcp_team"],
3248
- "resolved_tools": [{"tool": "mcp_team", "enforcement": "prompt_only"}],
3249
- "has_prompt_only": true
3250
- })
3251
- );
3252
3241
  assert!(agent["session_id"].is_null());
3253
3242
  assert!(agent["rollout_path"].is_null());
3254
3243
  assert!(agent["captured_at"].is_null());
@@ -91,7 +91,6 @@ fn command_for_model(model: &str) -> Vec<String> {
91
91
  model: Some(model),
92
92
  effort: Some(ProviderEffort::Medium),
93
93
  system_prompt: "worker contract",
94
- tool_categories: &["mcp_team"],
95
94
  session_dir: Some(Path::new("/workspace/.team/runtime/pi/t1/w1/sessions")),
96
95
  session: PiSessionSelector::Fresh {
97
96
  session_id: "716ba0cb-c491-4471-b41a-43c8d5e1f05a",
@@ -10,7 +10,6 @@ fn request(session: PiSessionSelector<'static>) -> PiCommandRequest<'static> {
10
10
  model: Some("team-agent/qwen3.8-27b"),
11
11
  effort: Some(ProviderEffort::High),
12
12
  system_prompt: "frozen worker prompt",
13
- tool_categories: &["mcp_team", "fs_read", "fs_write", "execute_bash"],
14
13
  session_dir: Some(Path::new(
15
14
  "/workspace/.team/runtime/pi/team-a/worker-a/sessions",
16
15
  )),
@@ -38,7 +37,6 @@ fn leader_request() -> PiCommandRequest<'static> {
38
37
  model: None,
39
38
  effort: None,
40
39
  system_prompt: "frozen leader prompt",
41
- tool_categories: &["mcp_team", "fs_read", "fs_write", "execute_bash"],
42
40
  session_dir: None,
43
41
  session: PiSessionSelector::Fresh {
44
42
  session_id: "da8c3622-2378-4d05-a26c-e826a6ef6d63",
@@ -6,9 +6,7 @@ use crate::lifecycle::launch::pi_mcp::{parse_pi_list_models_table, select_exact_
6
6
  use crate::model::enums::ProviderEffort;
7
7
  use crate::model::yaml::Value;
8
8
  use crate::model::ModelError;
9
- use crate::provider::adapters::pi::{
10
- build_pi_command_argv, pi_tool_mapping, PiCommandRequest, PiSessionSelector, PiToolMapping,
11
- };
9
+ use crate::provider::adapters::pi::{build_pi_command_argv, PiCommandRequest, PiSessionSelector};
12
10
 
13
11
  const CATALOG: &[u8] = include_bytes!("fixtures/pi_list_models_g0.stdout.txt");
14
12
  static NEXT_ROLE: AtomicU32 = AtomicU32::new(0);
@@ -51,13 +49,12 @@ fn compile_error(result: Result<CompiledRole, ModelError>) -> ModelError {
51
49
  }
52
50
  }
53
51
 
54
- fn command(tools: &[&str], effort: ProviderEffort, model: &str) -> Result<Vec<String>, String> {
52
+ fn command(_tools: &[&str], effort: ProviderEffort, model: &str) -> Result<Vec<String>, String> {
55
53
  build_pi_command_argv(PiCommandRequest {
56
54
  extension: Path::new("/workspace/.team/runtime/pi/t1/pi-worker/team-mcp.ts"),
57
55
  model: Some(model),
58
56
  effort: Some(effort),
59
57
  system_prompt: "Pi worker contract.",
60
- tool_categories: tools,
61
58
  session_dir: Some(Path::new(
62
59
  "/workspace/.team/runtime/pi/t1/pi-worker/sessions",
63
60
  )),
@@ -70,24 +67,22 @@ fn command(tools: &[&str], effort: ProviderEffort, model: &str) -> Result<Vec<St
70
67
  }
71
68
 
72
69
  #[test]
73
- fn pi_role_requires_mcp_team_and_preserves_provider_defaults() {
70
+ fn pi_role_ignores_tools_and_preserves_provider_defaults() {
74
71
  let positive = compile_pi_role(&valid_role_with(""));
75
72
  assert!(positive.is_ok(), "fully explicit Pi role must compile");
76
73
 
77
- let missing_mcp = valid_role_with("").replace(" - mcp_team\n", "");
74
+ let missing_tools = valid_role_with("").replace(
75
+ "tools:\n - mcp_team\n - fs_read\n - fs_list\n - fs_write\n - execute_bash\n",
76
+ "",
77
+ );
78
+ compile_pi_role(&missing_tools).expect("omitted tools metadata must compile");
78
79
  let unqualified =
79
80
  valid_role_with("").replace("model: team-agent/qwen3.8-27b", "model: qwen3.8-27b");
80
-
81
- for (label, role) in [
82
- ("mcp_team", missing_mcp),
83
- ("qualified exact model", unqualified),
84
- ] {
85
- let error = compile_error(compile_pi_role(&role));
86
- assert!(
87
- error.to_string().to_ascii_lowercase().contains(label),
88
- "error must name {label}; got {error}"
89
- );
90
- }
81
+ let error = compile_error(compile_pi_role(&unqualified));
82
+ assert!(
83
+ error.to_string().to_ascii_lowercase().contains("qualified exact model"),
84
+ "error must name qualified model; got {error}"
85
+ );
91
86
 
92
87
  let defaults = valid_role_with("")
93
88
  .replace("model: team-agent/qwen3.8-27b\n", "")
@@ -195,42 +190,7 @@ fn pi_max_effort_is_supported_without_model_suffix() {
195
190
  }
196
191
 
197
192
  #[test]
198
- fn pi_role_tools_validate_team_capabilities_without_replacing_direct_pi_tools() {
199
- assert_eq!(pi_tool_mapping("mcp_team"), PiToolMapping::Mcp);
200
- assert_eq!(
201
- pi_tool_mapping("fs_read"),
202
- PiToolMapping::Builtin(&["read"])
203
- );
204
- assert_eq!(
205
- pi_tool_mapping("fs_list"),
206
- PiToolMapping::Builtin(&["grep", "find", "ls"])
207
- );
208
- assert_eq!(
209
- pi_tool_mapping("fs_write"),
210
- PiToolMapping::Builtin(&["edit", "write"])
211
- );
212
- assert_eq!(
213
- pi_tool_mapping("execute_bash"),
214
- PiToolMapping::Builtin(&["bash"])
215
- );
216
-
217
- for unsupported in ["git_diff", "network", "provider_builtin", "not_a_tool"] {
218
- assert_eq!(
219
- pi_tool_mapping(unsupported),
220
- PiToolMapping::Unsupported,
221
- "unknown categories must not silently broaden to bash"
222
- );
223
- assert!(
224
- command(
225
- &["mcp_team", unsupported],
226
- ProviderEffort::Medium,
227
- "team-agent/qwen3.8-27b"
228
- )
229
- .is_err(),
230
- "unsupported tool must refuse the command: {unsupported}"
231
- );
232
- }
233
-
193
+ fn pi_role_command_ignores_legacy_tool_metadata() {
234
194
  let argv = command(
235
195
  &["mcp_team", "fs_write", "fs_read", "fs_list", "execute_bash"],
236
196
  ProviderEffort::Medium,
@@ -242,34 +202,3 @@ fn pi_role_tools_validate_team_capabilities_without_replacing_direct_pi_tools()
242
202
  "role tools validate Team Agent capabilities but must not replace direct Pi tools: {argv:?}"
243
203
  );
244
204
  }
245
-
246
- #[test]
247
- fn pi_role_rejects_unsupported_categories_during_compile() {
248
- compile_pi_role(&valid_role_with("")).expect("supported Pi tools must compile");
249
-
250
- for unsupported in ["git_diff", "network", "provider_builtin"] {
251
- let role = valid_role_with("").replace(
252
- " - execute_bash\n",
253
- &format!(" - execute_bash\n - {unsupported}\n"),
254
- );
255
- let error = compile_error(compile_pi_role(&role)).to_string();
256
- assert!(
257
- error.contains(&format!("Pi does not support Team Agent tool category {unsupported:?}")),
258
- "compile must reject {unsupported} before launch preparation: {error}"
259
- );
260
- assert!(
261
- error.contains("remove it from the role's tools"),
262
- "compile error must provide an actionable fix: {error}"
263
- );
264
- }
265
-
266
- let alias = valid_role_with("").replace(
267
- " - execute_bash\n",
268
- " - execute_bash\n - \"@builtin\"\n",
269
- );
270
- let error = compile_error(compile_pi_role(&alias)).to_string();
271
- assert!(
272
- error.contains("Pi does not support Team Agent tool category \"provider_builtin\""),
273
- "@builtin must use the same Pi capability contract: {error}"
274
- );
275
- }
@@ -300,7 +300,7 @@ fn pi_leader_and_teammate_body(hermetic: &HermeticTestEnv) {
300
300
  mcp_config: None,
301
301
  system_prompt: None,
302
302
  model: None,
303
- tools: &[],
303
+ dangerously_skip_permissions: false,
304
304
  profile_launch: None,
305
305
  agent_id_hint: None,
306
306
  effort: None,
@@ -572,7 +572,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
572
572
  model: None,
573
573
  effort: None,
574
574
  system_prompt: "native leader fixture",
575
- tool_categories: &["mcp_team"],
576
575
  team_mcp_tools: &["send_message"],
577
576
  mcp_config: &native_config,
578
577
  session_scope: PiSessionScope::NativeDefault,
@@ -605,7 +604,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
605
604
  model: Some("team-agent/qwen3.8-27b"),
606
605
  effort: Some(ProviderEffort::Medium),
607
606
  system_prompt: "isolated worker fixture",
608
- tool_categories: &["mcp_team"],
609
607
  team_mcp_tools: &["send_message"],
610
608
  mcp_config: &isolated_config,
611
609
  session_scope: PiSessionScope::Isolated,
@@ -633,7 +631,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
633
631
  model: None,
634
632
  effort: None,
635
633
  system_prompt: "isolated resume fixture",
636
- tool_categories: &["mcp_team"],
637
634
  team_mcp_tools: &["send_message"],
638
635
  mcp_config: &isolated_config,
639
636
  session_scope: PiSessionScope::Isolated,
@@ -664,7 +661,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
664
661
  model: None,
665
662
  effort: None,
666
663
  system_prompt: "native resume fixture",
667
- tool_categories: &["mcp_team"],
668
664
  team_mcp_tools: &["send_message"],
669
665
  mcp_config: &native_config,
670
666
  session_scope: PiSessionScope::NativeDefault,
@@ -699,7 +695,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
699
695
  model: None,
700
696
  effort: None,
701
697
  system_prompt: "isolated negative resume fixture",
702
- tool_categories: &["mcp_team"],
703
698
  team_mcp_tools: &["send_message"],
704
699
  mcp_config: &isolated_config,
705
700
  session_scope: PiSessionScope::Isolated,
@@ -58,7 +58,6 @@ fn resume_argv(path: &Path) -> Result<Vec<String>, ProviderError> {
58
58
  model: Some("team-agent/qwen3.8-27b"),
59
59
  effort: Some(ProviderEffort::Medium),
60
60
  system_prompt: "worker contract",
61
- tool_categories: &["mcp_team"],
62
61
  session_dir: Some(Path::new(
63
62
  "/workspace/.team/runtime/pi/team-a/worker-a/sessions",
64
63
  )),
@@ -901,13 +901,13 @@ impl ProviderAdapter for StaticCaptureAdapter {
901
901
  Ok(vec!["fake".to_string()])
902
902
  }
903
903
 
904
- fn build_command_with_tools(
904
+ fn build_command_with_permissions(
905
905
  &self,
906
906
  auth_mode: AuthMode,
907
907
  mcp_config: Option<&McpConfig>,
908
908
  system_prompt: Option<&str>,
909
909
  model: Option<&str>,
910
- _tools: &[&str],
910
+ _dangerously_skip_permissions: bool,
911
911
  ) -> Result<Vec<String>, ProviderError> {
912
912
  self.build_command(auth_mode, mcp_config, system_prompt, model)
913
913
  }
@@ -959,7 +959,7 @@ impl ProviderAdapter for StaticCaptureAdapter {
959
959
  mcp_config: Option<&McpConfig>,
960
960
  _system_prompt: Option<&str>,
961
961
  _model: Option<&str>,
962
- _tools: &[&str],
962
+ _dangerously_skip_permissions: bool,
963
963
  ) -> Result<Vec<String>, ProviderError> {
964
964
  self.build_resume_command(session_id, auth_mode, mcp_config)
965
965
  }
@@ -980,7 +980,7 @@ impl ProviderAdapter for StaticCaptureAdapter {
980
980
  mcp_config: Option<&McpConfig>,
981
981
  _system_prompt: Option<&str>,
982
982
  _model: Option<&str>,
983
- _tools: &[&str],
983
+ _dangerously_skip_permissions: bool,
984
984
  ) -> Result<Vec<String>, ProviderError> {
985
985
  self.fork(session_id, auth_mode, mcp_config)
986
986
  }
@@ -64,7 +64,6 @@ mod cursor_require_explicit_model_red;
64
64
  mod cursor_restart_resume_red;
65
65
  mod display_adaptive_red;
66
66
  mod f032_startup_prompt_best_effort_red;
67
- mod g1_silent_faces;
68
67
  mod grok_effort_argv_red;
69
68
  mod grok_mcp_overlay_red;
70
69
  mod grok_require_explicit_model_red;
@@ -540,8 +540,6 @@ pub struct LaunchReport {
540
540
  pub tmux_endpoint: Option<String>,
541
541
  /// 路由决策(每 task 一条;`routing.decision` 事件)。
542
542
  pub routes: Vec<RoutingDecision>,
543
- /// 权限摘要(每 agent 一条)。
544
- pub permissions: Vec<PermissionSummary>,
545
543
  /// leader receiver(attach 成功时;经 step10 leader::attach_leader_to_state)。
546
544
  pub leader_receiver_attached: bool,
547
545
  pub leader_bind_stage: Option<String>,
@@ -577,14 +575,6 @@ pub struct RoutingDecision {
577
575
  pub manual_override: bool,
578
576
  }
579
577
 
580
- /// 权限摘要(`resolve_permissions(agent)` 的 typed 版)。**PLACEHOLDER 字段**:
581
- /// 实际形状由 step6 compiler 的 `resolve_permissions` 决定,集成时映射。
582
- #[derive(Debug, Clone, PartialEq, Eq)]
583
- pub struct PermissionSummary {
584
- pub agent_id: AgentId,
585
- pub raw: serde_json::Value,
586
- }
587
-
588
578
  /// BUG-7 (0.3.1): quick-start cannot honestly report "ready" before the workers'
589
579
  /// MCP tool sets have actually loaded — provider-side schema rejections (codex
590
580
  /// invalid_function_parameters etc.) happen AFTER spawn and silently disable the