@team-agent/installer 0.5.65 → 0.5.66

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 (83) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/Cargo.toml +5 -0
  4. package/crates/team-agent/src/cli/adapters.rs +1 -1
  5. package/crates/team-agent/src/cli/tests/compile.rs +1 -1
  6. package/crates/team-agent/src/cli/tests/mod.rs +2 -2
  7. package/crates/team-agent/src/cli/tests/run_delegation.rs +1 -1
  8. package/crates/team-agent/src/cli/tests/verb_validate.rs +1 -1
  9. package/crates/team-agent/src/compiler/tests.rs +23 -20
  10. package/crates/team-agent/src/compiler.rs +25 -5
  11. package/crates/team-agent/src/conpty/backend.rs +16 -0
  12. package/crates/team-agent/src/leader/start.rs +167 -2
  13. package/crates/team-agent/src/leader/tests/team_in_team_state_scope_red.rs +1 -1
  14. package/crates/team-agent/src/lifecycle/launch/add_agent.rs +0 -2
  15. package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +7 -2
  16. package/crates/team-agent/src/lifecycle/launch/agent_state.rs +137 -2
  17. package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +1 -2
  18. package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +5 -0
  19. package/crates/team-agent/src/lifecycle/launch/spawn.rs +39 -2
  20. package/crates/team-agent/src/lifecycle/launch/spec_state.rs +105 -48
  21. package/crates/team-agent/src/lifecycle/launch/state_projection.rs +0 -2
  22. package/crates/team-agent/src/lifecycle/launch.rs +117 -21
  23. package/crates/team-agent/src/lifecycle/restart/agent.rs +89 -3
  24. package/crates/team-agent/src/lifecycle/restart/common.rs +6 -9
  25. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +59 -15
  26. package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +1 -1
  27. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +1 -1
  28. package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +1 -1
  29. package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +2 -2
  30. package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +4 -4
  31. package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +24 -32
  32. package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +2 -2
  33. package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +13 -11
  34. package/crates/team-agent/src/lifecycle/tests/core.rs +0 -18
  35. package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +1 -1
  36. package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +1 -1
  37. package/crates/team-agent/src/lifecycle/tests/f032_startup_prompt_best_effort_red.rs +1 -1
  38. package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +3 -0
  39. package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +3 -3
  40. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +2 -2
  41. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +17 -30
  42. package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +1 -1
  43. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +4 -4
  44. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +1 -1
  45. package/crates/team-agent/src/lifecycle/tests/quick_start_worker_readiness_red.rs +2 -2
  46. package/crates/team-agent/src/lifecycle/tests/restart_build_before_destroy_0540_contract.rs +1 -1
  47. package/crates/team-agent/src/lifecycle/tests/restart_liveness_red.rs +1 -1
  48. package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +1 -1
  49. package/crates/team-agent/src/lifecycle/tests/restart_session_capture_red.rs +2 -2
  50. package/crates/team-agent/src/lifecycle/tests/resume_recover_red.rs +1 -1
  51. package/crates/team-agent/src/lifecycle/tests/stale_team_saveconflict_contract.rs +1 -1
  52. package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +1 -1
  53. package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +3 -3
  54. package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +1 -1
  55. package/crates/team-agent/src/lifecycle/tests/swallow_batch4_semantics_red.rs +1 -1
  56. package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +1 -1
  57. package/crates/team-agent/src/lifecycle/tests/team_in_team_sibling_quick_start_red.rs +1 -1
  58. package/crates/team-agent/src/lifecycle/tests/team_in_team_state_scope_red.rs +1 -1
  59. package/crates/team-agent/src/lifecycle/tests/team_key_retirement_txn_red.rs +1 -1
  60. package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +1 -1
  61. package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +1 -1
  62. package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +2 -2
  63. package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +1 -1
  64. package/crates/team-agent/src/lifecycle/tests.rs +0 -2
  65. package/crates/team-agent/src/lifecycle/types.rs +0 -2
  66. package/crates/team-agent/src/lifecycle/worker_command_context.rs +115 -22
  67. package/crates/team-agent/src/messaging/tests/main_preserved.rs +1 -1
  68. package/crates/team-agent/src/model/spec.rs +129 -6
  69. package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +3 -1
  70. package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +3 -1
  71. package/crates/team-agent/src/model/testdata/team.spec.yaml +3 -1
  72. package/crates/team-agent/src/provider/adapters/claude.rs +5 -2
  73. package/crates/team-agent/src/provider/adapters/codex.rs +5 -2
  74. package/crates/team-agent/src/provider/adapters/copilot.rs +5 -2
  75. package/crates/team-agent/src/provider/bypass_flags.rs +80 -0
  76. package/crates/team-agent/src/provider/mod.rs +2 -0
  77. package/crates/team-agent/src/tmux_backend.rs +19 -0
  78. package/crates/team-agent/src/transport/test_support.rs +20 -0
  79. package/crates/team-agent/src/transport.rs +17 -0
  80. package/package.json +4 -4
  81. package/crates/team-agent/src/lifecycle/launch/approval.rs +0 -134
  82. package/crates/team-agent/src/lifecycle/tests/codex_mcp_approval_inheritance_red.rs +0 -1187
  83. package/crates/team-agent/src/lifecycle/tests/worker_dangerous_bypass_argv_red.rs +0 -327
package/Cargo.lock CHANGED
@@ -575,7 +575,7 @@ dependencies = [
575
575
 
576
576
  [[package]]
577
577
  name = "team-agent"
578
- version = "0.5.65"
578
+ version = "0.5.66"
579
579
  dependencies = [
580
580
  "anyhow",
581
581
  "chrono",
package/Cargo.toml CHANGED
@@ -9,7 +9,7 @@ members = ["crates/team-agent", "crates/win-conpty-phase0", "crates/conpty-trans
9
9
 
10
10
  [workspace.package]
11
11
  edition = "2021"
12
- version = "0.5.65"
12
+ version = "0.5.66"
13
13
  license = "AGPL-3.0"
14
14
  rust-version = "1.95"
15
15
 
@@ -57,5 +57,10 @@ serial_test = { version = "3", features = ["file_locks"] }
57
57
  name = "e2e"
58
58
  path = "tests/e2e/main.rs"
59
59
 
60
+ # 0.5.66 bypass 单源:E2E 验证角色字段 → 运行面 → drift 挡板 → force fresh spawn。
61
+ [[test]]
62
+ name = "e2e_bypass_single_source"
63
+ path = "tests/e2e_bypass_single_source.rs"
64
+
60
65
  [lints]
61
66
  workspace = true
@@ -75,7 +75,7 @@ pub fn cmd_init(args: &InitArgs) -> Result<CmdResult, CliError> {
75
75
  if args.force || !default_agent_path.exists() {
76
76
  std::fs::write(
77
77
  &default_agent_path,
78
- "---\nname: worker\nrole: Worker\nprovider: fake\ntools:\n - mcp_team\n---\n\nWait for instructions.\n",
78
+ "---\nname: worker\nrole: Worker\nprovider: fake\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWait for instructions.\n",
79
79
  )?;
80
80
  }
81
81
  if args.force || !state_path.exists() {
@@ -10,7 +10,7 @@ fn compile_team_dir(tag: &str) -> std::path::PathBuf {
10
10
  .unwrap();
11
11
  std::fs::write(
12
12
  team.join("agents").join("worker.md"),
13
- "---\nname: worker\nrole: Worker\nprovider: fake\nmodel: fake\ntools:\n - mcp_team\n---\n\nWorker role.\n",
13
+ "---\nname: worker\nrole: Worker\nprovider: fake\nmodel: fake\ntools:\n - mcp_team\ndangerously_skip_permissions: false\n---\n\nWorker role.\n",
14
14
  )
15
15
  .unwrap();
16
16
  team
@@ -73,8 +73,8 @@ fn seed_send_workspace() -> std::path::PathBuf {
73
73
  dir
74
74
  }
75
75
 
76
- const DELEG_VALID_ROLE: &str = "---\nname: implementer\nrole: Implementation Engineer\nprovider: fake\nmodel: fake\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nImplement bounded tasks.\n";
77
- const DELEG_INVALID_ROLE: &str = "---\nname: broken\nrole: Broken Worker\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nNo provider field.\n";
76
+ const DELEG_VALID_ROLE: &str = "---\nname: implementer\nrole: Implementation Engineer\nprovider: fake\nmodel: fake\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nImplement bounded tasks.\n";
77
+ const DELEG_INVALID_ROLE: &str = "---\nname: broken\nrole: Broken Worker\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nNo provider field.\n";
78
78
  const DELEG_TEAM_MD: &str =
79
79
  "---\nname: clidelegteam\nobjective: Delegation probe.\nprovider: fake\n---\n\nteam.\n";
80
80
 
@@ -182,7 +182,7 @@ fn run_dispatches_quick_start_compiles_spec() {
182
182
  .unwrap();
183
183
  std::fs::write(
184
184
  dir.join("agents").join("implementer.md"),
185
- "---\nname: implementer\nrole: Impl\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nImpl.\n",
185
+ "---\nname: implementer\nrole: Impl\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nImpl.\n",
186
186
  )
187
187
  .unwrap();
188
188
  let argv = vec![
@@ -36,7 +36,7 @@ agents:
36
36
  - "git_diff"
37
37
  - "mcp_team"
38
38
  - "provider_builtin"
39
- permission_mode: "restricted"
39
+ dangerously_skip_permissions: false
40
40
  preferred_for:
41
41
  - "implementation"
42
42
  avoid_for: []
@@ -105,6 +105,7 @@ role: Implementation Engineer
105
105
  provider: codex
106
106
  model: gpt-5.5
107
107
  auth_mode: subscription
108
+ dangerously_skip_permissions: false
108
109
  tools:
109
110
  - fs_read
110
111
  - fs_write
@@ -189,7 +190,7 @@ fn front_matter_non_object_errors() {
189
190
  // separators=(",",":"))` with the workspace path templated to __WS__.
190
191
  // (team-agent-public v0.2.11, /tmp/probe_compiler.py.)
191
192
 
192
- const BASE_NOPROFILE_JSON: &str = r#"{"version":1,"team":{"name":"doc-team","mode":"supervisor_worker","objective":"Compile role docs.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":"gpt-5.5","tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"implementer","role":"Implementation Engineer","provider":"codex","model":"gpt-5.5","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Implement bounded tasks and report result_envelope_v1.","file":null},"tools":["fs_read","fs_write","execute_bash","mcp_team"],"permission_mode":"restricted","communication_mode":"leader_centric","preferred_for":["implementer","Implementation Engineer"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"implementer","rules":[{"id":"route-implementer","match":{"assignee":["implementer"]},"assign_to":"implementer","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"adaptive","session_name":"team-doc-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":1,"startup_order":["implementer"],"dangerous_auto_approve":false,"fast":false,"tick_interval_sec":2,"push_min_interval_sec":60,"stuck_timeout_sec":300},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"implementer","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
193
+ const BASE_NOPROFILE_JSON: &str = r#"{"version":1,"team":{"name":"doc-team","mode":"supervisor_worker","objective":"Compile role docs.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":"gpt-5.5","tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"implementer","role":"Implementation Engineer","provider":"codex","model":"gpt-5.5","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Implement bounded tasks and report result_envelope_v1.","file":null},"tools":["fs_read","fs_write","execute_bash","mcp_team"],"dangerously_skip_permissions":false,"communication_mode":"leader_centric","preferred_for":["implementer","Implementation Engineer"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"implementer","rules":[{"id":"route-implementer","match":{"assignee":["implementer"]},"assign_to":"implementer","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"adaptive","session_name":"team-doc-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":1,"startup_order":["implementer"],"fast":false,"tick_interval_sec":2,"push_min_interval_sec":60,"stuck_timeout_sec":300},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"implementer","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
193
194
 
194
195
  #[test]
195
196
  fn compile_base_noprofile_matches_python_dict_order_and_values() {
@@ -254,12 +255,13 @@ provider: codex
254
255
  tools:
255
256
  - fs_read
256
257
  - mcp_team
258
+ dangerously_skip_permissions: false
257
259
  ---
258
260
 
259
261
  Implement bounded tasks.
260
262
  ";
261
263
 
262
- const RUNTIME_DEFAULTS_JSON: &str = r#"{"version":1,"team":{"name":"doc-team","mode":"supervisor_worker","objective":"Compile role docs.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":null,"tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"implementer","role":"Implementation Engineer","provider":"codex","model":"gpt-5.4","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Implement bounded tasks.","file":null},"tools":["fs_read","mcp_team"],"permission_mode":"restricted","communication_mode":"leader_centric","preferred_for":["implementer","Implementation Engineer"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"implementer","rules":[{"id":"route-implementer","match":{"assignee":["implementer"]},"assign_to":"implementer","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"ghostty_window","session_name":"team-doc-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":1,"startup_order":["implementer"],"dangerous_auto_approve":true,"fast":true,"tick_interval_sec":1,"push_min_interval_sec":3,"stuck_timeout_sec":5},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"implementer","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
264
+ const RUNTIME_DEFAULTS_JSON: &str = r#"{"version":1,"team":{"name":"doc-team","mode":"supervisor_worker","objective":"Compile role docs.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":null,"tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"implementer","role":"Implementation Engineer","provider":"codex","model":"gpt-5.4","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Implement bounded tasks.","file":null},"tools":["fs_read","mcp_team"],"dangerously_skip_permissions":false,"communication_mode":"leader_centric","preferred_for":["implementer","Implementation Engineer"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"implementer","rules":[{"id":"route-implementer","match":{"assignee":["implementer"]},"assign_to":"implementer","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"ghostty_window","session_name":"team-doc-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":1,"startup_order":["implementer"],"fast":true,"tick_interval_sec":1,"push_min_interval_sec":3,"stuck_timeout_sec":5},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"implementer","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
263
265
 
264
266
  #[test]
265
267
  fn compile_runtime_front_matter_defaults_match_python() {
@@ -294,12 +296,13 @@ role: Editor and Defender
294
296
  provider: claude_code
295
297
  tools:
296
298
  - mcp_team
299
+ dangerously_skip_permissions: false
297
300
  ---
298
301
 
299
302
  Edit and defend the argument.
300
303
  ";
301
304
 
302
- const ALIAS_JSON: &str = r#"{"version":1,"team":{"name":"debate-team","mode":"supervisor_worker","objective":"Compile thin role docs.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":null,"tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"editor","role":"Editor and Defender","provider":"claude_code","model":"claude-sonnet-4-6","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Edit and defend the argument.","file":null},"tools":["mcp_team"],"permission_mode":"restricted","communication_mode":"leader_centric","preferred_for":["editor","Editor and Defender"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"editor","rules":[{"id":"route-editor","match":{"assignee":["editor"]},"assign_to":"editor","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"none","session_name":"team-debate-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":1,"startup_order":["editor"],"dangerous_auto_approve":false,"fast":false,"tick_interval_sec":2,"push_min_interval_sec":60,"stuck_timeout_sec":300},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"editor","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
305
+ const ALIAS_JSON: &str = r#"{"version":1,"team":{"name":"debate-team","mode":"supervisor_worker","objective":"Compile thin role docs.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":null,"tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"editor","role":"Editor and Defender","provider":"claude_code","model":"claude-sonnet-4-6","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Edit and defend the argument.","file":null},"tools":["mcp_team"],"dangerously_skip_permissions":false,"communication_mode":"leader_centric","preferred_for":["editor","Editor and Defender"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"editor","rules":[{"id":"route-editor","match":{"assignee":["editor"]},"assign_to":"editor","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"none","session_name":"team-debate-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":1,"startup_order":["editor"],"fast":false,"tick_interval_sec":2,"push_min_interval_sec":60,"stuck_timeout_sec":300},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"editor","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
303
306
 
304
307
  #[test]
305
308
  fn compile_provider_models_claude_code_falls_back_to_claude_alias() {
@@ -325,6 +328,7 @@ name: implementer
325
328
  role: Implementation Engineer
326
329
  provider: codex
327
330
  auth_mode: subscription
331
+ dangerously_skip_permissions: false
328
332
  tools:
329
333
  - mcp_team
330
334
  ---
@@ -332,7 +336,7 @@ tools:
332
336
  Implement bounded tasks.
333
337
  ";
334
338
 
335
- const BUILTIN_JSON: &str = r#"{"version":1,"team":{"name":"default-model-team","mode":"supervisor_worker","objective":"Compile role docs without model fields.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":null,"tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"implementer","role":"Implementation Engineer","provider":"codex","model":"gpt-5.5","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Implement bounded tasks.","file":null},"tools":["mcp_team"],"permission_mode":"restricted","communication_mode":"leader_centric","preferred_for":["implementer","Implementation Engineer"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"implementer","rules":[{"id":"route-implementer","match":{"assignee":["implementer"]},"assign_to":"implementer","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"none","session_name":"team-default-model-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":1,"startup_order":["implementer"],"dangerous_auto_approve":false,"fast":false,"tick_interval_sec":2,"push_min_interval_sec":60,"stuck_timeout_sec":300},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"implementer","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
339
+ const BUILTIN_JSON: &str = r#"{"version":1,"team":{"name":"default-model-team","mode":"supervisor_worker","objective":"Compile role docs without model fields.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":null,"tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"implementer","role":"Implementation Engineer","provider":"codex","model":"gpt-5.5","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Implement bounded tasks.","file":null},"tools":["mcp_team"],"dangerously_skip_permissions":false,"communication_mode":"leader_centric","preferred_for":["implementer","Implementation Engineer"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"implementer","rules":[{"id":"route-implementer","match":{"assignee":["implementer"]},"assign_to":"implementer","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"none","session_name":"team-default-model-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":1,"startup_order":["implementer"],"fast":false,"tick_interval_sec":2,"push_min_interval_sec":60,"stuck_timeout_sec":300},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"implementer","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
336
340
 
337
341
  #[test]
338
342
  fn compile_subscription_without_model_uses_builtin_provider_default() {
@@ -351,6 +355,7 @@ role: Alpha Worker
351
355
  provider: codex
352
356
  model: gpt-5.5
353
357
  auth_mode: subscription
358
+ dangerously_skip_permissions: false
354
359
  tools:
355
360
  - mcp_team
356
361
  ---
@@ -365,6 +370,7 @@ role: Bravo Worker
365
370
  provider: codex
366
371
  model: gpt-5.5
367
372
  auth_mode: subscription
373
+ dangerously_skip_permissions: false
368
374
  tools:
369
375
  - mcp_team
370
376
  ---
@@ -372,7 +378,7 @@ tools:
372
378
  Bravo body.
373
379
  ";
374
380
 
375
- const TWO_AGENTS_JSON: &str = r#"{"version":1,"team":{"name":"doc-team","mode":"supervisor_worker","objective":"Compile role docs.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":"gpt-5.5","tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"alpha","role":"Alpha Worker","provider":"codex","model":"gpt-5.5","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Alpha body.","file":null},"tools":["mcp_team"],"permission_mode":"restricted","communication_mode":"leader_centric","preferred_for":["alpha","Alpha Worker"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}},{"id":"bravo","role":"Bravo Worker","provider":"codex","model":"gpt-5.5","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Bravo body.","file":null},"tools":["mcp_team"],"permission_mode":"restricted","communication_mode":"leader_centric","preferred_for":["bravo","Bravo Worker"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"alpha","rules":[{"id":"route-alpha","match":{"assignee":["alpha"]},"assign_to":"alpha","priority":10},{"id":"route-bravo","match":{"assignee":["bravo"]},"assign_to":"bravo","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"adaptive","session_name":"team-doc-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":2,"startup_order":["alpha","bravo"],"dangerous_auto_approve":false,"fast":false,"tick_interval_sec":2,"push_min_interval_sec":60,"stuck_timeout_sec":300},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"alpha","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
381
+ const TWO_AGENTS_JSON: &str = r#"{"version":1,"team":{"name":"doc-team","mode":"supervisor_worker","objective":"Compile role docs.","workspace":"__WS__"},"leader":{"id":"leader","role":"leader","provider":"codex","model":"gpt-5.5","tools":["fs_read","fs_list","mcp_team"],"context_policy":{"keep_user_thread":true,"receive_worker_outputs":"business_messages_and_short_summaries","max_worker_result_tokens":2000}},"agents":[{"id":"alpha","role":"Alpha Worker","provider":"codex","model":"gpt-5.5","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Alpha body.","file":null},"tools":["mcp_team"],"dangerously_skip_permissions":false,"communication_mode":"leader_centric","preferred_for":["alpha","Alpha Worker"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}},{"id":"bravo","role":"Bravo Worker","provider":"codex","model":"gpt-5.5","auth_mode":"subscription","working_directory":"__WS__","system_prompt":{"inline":"Bravo body.","file":null},"tools":["mcp_team"],"dangerously_skip_permissions":false,"communication_mode":"leader_centric","preferred_for":["bravo","Bravo Worker"],"avoid_for":[],"output_contract":{"format":"result_envelope_v1","required_fields":["task_id","status","summary","artifacts"]}}],"routing":{"default_assignee":"alpha","rules":[{"id":"route-alpha","match":{"assignee":["alpha"]},"assign_to":"alpha","priority":10},{"id":"route-bravo","match":{"assignee":["bravo"]},"assign_to":"bravo","priority":10}]},"communication":{"protocol":"mcp_inbox","topology":"leader_centered","worker_to_worker":true,"ack_timeout_sec":60,"result_format":"result_envelope_v1","message_store":{"sqlite":".team/runtime/team.db","mirror_files":".team/messages"}},"runtime":{"backend":"tmux","display_backend":"adaptive","session_name":"team-doc-team","auto_launch":true,"require_user_approval_before_launch":true,"max_active_agents":2,"startup_order":["alpha","bravo"],"fast":false,"tick_interval_sec":2,"push_min_interval_sec":60,"stuck_timeout_sec":300},"context":{"state_file":"team_state.md","artifact_dir":".team/artifacts","log_dir":".team/logs","summarization":{"worker_full_logs":"retain_outside_leader_context","state_update":"after_each_result"}},"tasks":[{"id":"task_initial","title":"Initial document-driven team task","type":"implementation","assignee":"alpha","deps":[],"acceptance":["Worker reports valid result_envelope_v1"],"status":"pending","requires_tools":["mcp_team"],"files":[],"risk":"low"}]}"#;
376
382
 
377
383
  #[test]
378
384
  fn compile_two_agents_sorted_by_filename_with_routing_and_startup_order() {
@@ -394,6 +400,7 @@ name: implementer
394
400
  role: Implementation Engineer
395
401
  model: gpt-5.5
396
402
  auth_mode: subscription
403
+ dangerously_skip_permissions: false
397
404
  tools:
398
405
  - mcp_team
399
406
  ---
@@ -419,6 +426,7 @@ role: Implementation Engineer
419
426
  provider: codex
420
427
  model: gpt-5.5
421
428
  auth_mode: compatible_api
429
+ dangerously_skip_permissions: false
422
430
  tools:
423
431
  - mcp_team
424
432
  ---
@@ -448,7 +456,7 @@ fn compile_compatible_api_without_profile_errors() {
448
456
  const TM_CODEX: &str = "---\nname: T\nprovider: codex\n---\nx\n";
449
457
 
450
458
  fn role_nomodel(provider: &str) -> String {
451
- format!("---\nname: w\nrole: R\nprovider: {provider}\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nbody\n")
459
+ format!("---\nname: w\nrole: R\nprovider: {provider}\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nbody\n")
452
460
  }
453
461
 
454
462
  fn agent0(spec: &Value) -> &Value {
@@ -626,7 +634,7 @@ fn fix_a5_session_name_override_wins() {
626
634
 
627
635
  #[test]
628
636
  fn fix_a6_tools_shell_maps_to_execute_bash() {
629
- let role = "---\nname: w\nrole: R\nprovider: codex\nauth_mode: subscription\ntools:\n - shell\n - mcp_team\n---\nb\n";
637
+ let role = "---\nname: w\nrole: R\nprovider: codex\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - shell\n - mcp_team\n---\nb\n";
630
638
  let team = build_team(TM_CODEX, &[("w.md", role)], &[]);
631
639
  let spec = compile_team(&team).expect("shell must normalize to execute_bash and compile");
632
640
  assert_eq!(
@@ -637,7 +645,7 @@ fn fix_a6_tools_shell_maps_to_execute_bash() {
637
645
 
638
646
  #[test]
639
647
  fn fix_a6_missing_tools_errors() {
640
- let role = "---\nname: w\nrole: R\nprovider: codex\nauth_mode: subscription\n---\nb\n";
648
+ let role = "---\nname: w\nrole: R\nprovider: codex\nauth_mode: subscription\ndangerously_skip_permissions: false\n---\nb\n";
641
649
  let team = build_team(TM_CODEX, &[("w.md", role)], &[]);
642
650
  let err = compile_team(&team).unwrap_err();
643
651
  assert!(
@@ -648,7 +656,7 @@ fn fix_a6_missing_tools_errors() {
648
656
 
649
657
  #[test]
650
658
  fn fix_a6_tools_not_a_list_errors() {
651
- let role = "---\nname: w\nrole: R\nprovider: codex\nauth_mode: subscription\ntools: justastring\n---\nb\n";
659
+ let role = "---\nname: w\nrole: R\nprovider: codex\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools: justastring\n---\nb\n";
652
660
  let team = build_team(TM_CODEX, &[("w.md", role)], &[]);
653
661
  let err = compile_team(&team).unwrap_err();
654
662
  assert!(
@@ -661,7 +669,7 @@ fn fix_a6_tools_not_a_list_errors() {
661
669
 
662
670
  #[test]
663
671
  fn fix_a7_empty_body_inline_falls_back_to_role() {
664
- let role = "---\nname: w\nrole: Reviewer Role\nprovider: codex\nauth_mode: subscription\ntools:\n - mcp_team\n---\n";
672
+ let role = "---\nname: w\nrole: Reviewer Role\nprovider: codex\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n";
665
673
  let team = build_team(TM_CODEX, &[("w.md", role)], &[]);
666
674
  let spec = compile_team(&team).unwrap();
667
675
  assert_eq!(
@@ -675,7 +683,7 @@ fn fix_a7_empty_body_inline_falls_back_to_role() {
675
683
  #[test]
676
684
  fn fix_a8_official_api_without_profile_errors() {
677
685
  // official_api (any non-subscription) without profile MUST NOT silently compile.
678
- let role = "---\nname: w\nrole: R\nprovider: codex\nauth_mode: official_api\ntools:\n - mcp_team\n---\nb\n";
686
+ let role = "---\nname: w\nrole: R\nprovider: codex\nauth_mode: official_api\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\nb\n";
679
687
  let team = build_team(TM_CODEX, &[("w.md", role)], &[]);
680
688
  let err = compile_team(&team).unwrap_err();
681
689
  assert!(
@@ -706,14 +714,9 @@ fn fix_a8_compatible_api_error_names_the_auth_mode() {
706
714
  #[test]
707
715
  fn fix_a9_bool_coercion_yes_and_one_are_true() {
708
716
  for v in ["yes", "1"] {
709
- let tm = format!("---\nname: T\nprovider: codex\ndangerous_auto_approve: {v}\nworker_to_worker: {v}\n---\nx\n");
717
+ let tm = format!("---\nname: T\nprovider: codex\nworker_to_worker: {v}\n---\nx\n");
710
718
  let team = build_team(&tm, &[("w.md", &role_nomodel("codex"))], &[]);
711
719
  let spec = compile_team(&team).unwrap();
712
- assert_eq!(
713
- get_path(&spec, &["runtime", "dangerous_auto_approve"]),
714
- Some(&Value::Bool(true)),
715
- "value {v}"
716
- );
717
720
  assert_eq!(
718
721
  get_path(&spec, &["communication", "worker_to_worker"]),
719
722
  Some(&Value::Bool(true)),
@@ -726,11 +729,11 @@ fn fix_a9_bool_coercion_yes_and_one_are_true() {
726
729
  fn fix_a9_bool_coercion_no_is_python_truthy() {
727
730
  // FLAG: Python bool("no") is TRUE (only 0/false/False are falsy). The contract
728
731
  // note said "no->false" but Python golden is no->true; we lock Python.
729
- let tm = "---\nname: T\nprovider: codex\ndangerous_auto_approve: no\n---\nx\n";
732
+ let tm = "---\nname: T\nprovider: codex\nworker_to_worker: no\n---\nx\n";
730
733
  let team = build_team(tm, &[("w.md", &role_nomodel("codex"))], &[]);
731
734
  let spec = compile_team(&team).unwrap();
732
735
  assert_eq!(
733
- get_path(&spec, &["runtime", "dangerous_auto_approve"]),
736
+ get_path(&spec, &["communication", "worker_to_worker"]),
734
737
  Some(&Value::Bool(true))
735
738
  );
736
739
  }
@@ -753,7 +756,7 @@ fn fix_a9_int_coercion_of_quoted_string() {
753
756
  fn fix_a10_crlf_role_doc_front_matter_is_parsed() {
754
757
  // Windows-authored \r\n doc: read_text universal-newlines normalizes before
755
758
  // the "---\n" check, so the front matter parses (current keeps \r\n → no FM).
756
- let crlf_role = "---\r\nname: crlfworker\r\nrole: R\r\nprovider: codex\r\nauth_mode: subscription\r\ntools:\r\n - mcp_team\r\n---\r\n\r\nbody\r\n";
759
+ let crlf_role = "---\r\nname: crlfworker\r\nrole: R\r\nprovider: codex\r\nauth_mode: subscription\r\ndangerously_skip_permissions: false\r\ntools:\r\n - mcp_team\r\n---\r\n\r\nbody\r\n";
757
760
  let team = build_team(TM_CODEX, &[("w.md", crlf_role)], &[]);
758
761
  let spec = compile_team(&team).expect("CRLF role doc must parse its front matter");
759
762
  assert_eq!(
@@ -299,10 +299,6 @@ pub fn compile_team(team_dir: &Path) -> Result<Value, ModelError> {
299
299
  Value::Int(max_active_agents(agent_ids.len())),
300
300
  ),
301
301
  ("startup_order", list_str(agent_ids)),
302
- (
303
- "dangerous_auto_approve",
304
- bool_field(&team_meta, "dangerous_auto_approve", false),
305
- ),
306
302
  ("fast", bool_field(&team_meta, "fast", false)),
307
303
  (
308
304
  "tick_interval_sec",
@@ -421,7 +417,12 @@ fn compile_role_agent_with_mode(
421
417
  ]),
422
418
  ),
423
419
  ("tools", list_str(tools)),
424
- ("permission_mode", Value::Str("restricted".to_string())),
420
+ // 0.5.66 bypass 单源:compiler 透传角色 md 的 `dangerously_skip_permissions`
421
+ // (必填 bool,spec 校验保证存在)。取代旧"恒发 permission_mode: restricted"。
422
+ (
423
+ "dangerously_skip_permissions",
424
+ Value::Bool(required_dangerously_skip_permissions(&meta, role_path)?),
425
+ ),
425
426
  (
426
427
  "communication_mode",
427
428
  Value::Str(communication_mode.as_str().to_string()),
@@ -549,6 +550,25 @@ fn required_string(meta: &Value, path: &Path, key: &str) -> Result<String, Model
549
550
  })
550
551
  }
551
552
 
553
+ /// 0.5.66 bypass 单源:角色 md 的 `dangerously_skip_permissions` 必填 bool。
554
+ /// 缺 = 编译失败(消息含硬串);非 bool = 同 fail-loud。
555
+ fn required_dangerously_skip_permissions(
556
+ meta: &Value,
557
+ path: &Path,
558
+ ) -> Result<bool, ModelError> {
559
+ match meta.get("dangerously_skip_permissions") {
560
+ Some(Value::Bool(value)) => Ok(*value),
561
+ Some(_) => Err(ModelError::Validation(format!(
562
+ "{}: front matter field dangerously_skip_permissions must be a boolean. This field must be declared explicitly; it controls whether the agent launches with permission prompts bypassed.",
563
+ path.display()
564
+ ))),
565
+ None => Err(ModelError::Validation(format!(
566
+ "{}: missing front matter field dangerously_skip_permissions. This field must be declared explicitly; it controls whether the agent launches with permission prompts bypassed.",
567
+ path.display()
568
+ ))),
569
+ }
570
+ }
571
+
552
572
  fn optional_string_value(meta: &Value, key: &str) -> Value {
553
573
  match string_field(meta, key) {
554
574
  Some(s) => Value::Str(s),
@@ -644,6 +644,22 @@ impl Transport for ConPtyBackend {
644
644
  Ok(SetEnvOutcome::InternalizedAtSpawn)
645
645
  }
646
646
 
647
+ fn set_window_option(
648
+ &self,
649
+ _session: &SessionName,
650
+ _window: &WindowName,
651
+ _option: &str,
652
+ _value: &str,
653
+ ) -> Result<(), TransportError> {
654
+ // Design §Transport Boundary: window options are tmux concepts; ConPTY
655
+ // has no per-window option registry, so this is a typed capability
656
+ // refusal. Callers must `let _ =` this (A-55 lockdown is best-effort).
657
+ Err(TransportError::MuxUnavailable {
658
+ backend: BackendKind::ConPty,
659
+ detail: "set-window-option is tmux-only".to_string(),
660
+ })
661
+ }
662
+
647
663
  fn has_pane(&self, pane: &PaneId) -> Result<Option<bool>, TransportError> {
648
664
  let resp = self.dispatch(Op::HasPane, serde_json::json!({"pane_id": pane.as_str()}))?;
649
665
  Ok(Some(resp.result["present"].as_bool().unwrap_or(false)))