@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
@@ -31,8 +31,8 @@ struct HermeticTestEnv;
31
31
 
32
32
  const QS_TEAM_MD: &str =
33
33
  "---\nname: quickteam\nobjective: Quick start.\nprovider: codex\n---\n\nQuick-start team.\n";
34
- pub(super) const QS_VALID_ROLE: &str = "---\nname: implementer\nrole: Implementation Engineer\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nImplement bounded tasks.\n";
35
- const QS_ROLE_NO_PROVIDER: &str = "---\nname: implementer\nrole: Implementation Engineer\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nImplement bounded tasks.\n";
34
+ pub(super) const QS_VALID_ROLE: &str = "---\nname: implementer\nrole: Implementation Engineer\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nImplement bounded tasks.\n";
35
+ const QS_ROLE_NO_PROVIDER: &str = "---\nname: implementer\nrole: Implementation Engineer\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nImplement bounded tasks.\n";
36
36
 
37
37
  /// A REAL team dir `<base>/teamdir/{TEAM.md, agents/implementer.md}` — already in team-dir
38
38
  /// layout, so quick_start's prepare_quick_start_team returns it as-is and writes the compiled
@@ -57,7 +57,7 @@ fn quick_start_team_dir_with_roles(role_docs: &[(&str, &str)]) -> PathBuf {
57
57
 
58
58
  fn role_doc(id: &str) -> String {
59
59
  format!(
60
- "---\nname: {id}\nrole: {id} Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{id} worker.\n"
60
+ "---\nname: {id}\nrole: {id} Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{id} worker.\n"
61
61
  )
62
62
  }
63
63
 
@@ -448,7 +448,7 @@ fn add_agent_proceeds_past_owner_gate_and_reaches_recompile() {
448
448
  let role = ws.join("w2-role.md");
449
449
  std::fs::write(
450
450
  &role,
451
- "---\nname: w2\nrole: Second Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nSecond worker.\n",
451
+ "---\nname: w2\nrole: Second Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nSecond worker.\n",
452
452
  )
453
453
  .unwrap();
454
454
  let transport = OfflineTransport::new();
@@ -617,23 +617,8 @@ fn spine_quick_start_seeds_state_under_team_workspace_not_team_dir() {
617
617
  );
618
618
  }
619
619
 
620
- // #10 — launch dry-run safety is derived from spec.runtime.dangerous_auto_approve (source=runtime_config),
621
- // NOT a hardcoded Disabled. Golden config.py:effective_runtime_config.
622
- #[test]
623
- fn spine_launch_dry_run_safety_reflects_spec_dangerous() {
624
- let team = quick_start_team_dir_custom(QS_TEAM_MD_DANGEROUS, QS_VALID_ROLE);
625
- let spec_path = compiled_spec_path(&team);
626
- let report = launch(&spec_path, true, false, true).expect("dry_run launch");
627
- assert!(
628
- report.safety.enabled,
629
- "safety must reflect spec.runtime.dangerous_auto_approve=true"
630
- );
631
- assert_eq!(
632
- report.safety.source,
633
- DangerousApprovalSource::RuntimeConfig,
634
- "safety source must be runtime_config when spec-declared"
635
- );
636
- }
620
+ // #10 removed — launch dry-run safety was derived from spec.runtime.dangerous_auto_approve.
621
+ // 0.5.66 bypass 单源:该字段废弃,safety 改由 per-agent `dangerously_skip_permissions` 派生。
637
622
 
638
623
  // #12 — launch dry-run produces one RoutingDecision PER spec.task via route_task, with the real task id
639
624
  // and the route_task reason taxonomy — not one synthetic 'default_assignee' route. Golden core.py:77-88.
@@ -709,7 +694,7 @@ fn e5_add_agent_does_not_copy_role_into_platform_dir_and_injects_into_spec() {
709
694
  seed_canonical_team_identity(&team, "teamdir");
710
695
  // External role file OUTSIDE team_dir/agents, with recognizable body content.
711
696
  let role = team.parent().unwrap().join("w2-external-role.md");
712
- let role_body = "---\nname: w2\nrole: Second Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nUNIQUE-E5-BUG1-MARKER body for w2.\n";
697
+ let role_body = "---\nname: w2\nrole: Second Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nUNIQUE-E5-BUG1-MARKER body for w2.\n";
713
698
  std::fs::write(&role, role_body).unwrap();
714
699
  let transport = OfflineTransport::new();
715
700
  // The spawn may not complete under OfflineTransport; we only assert the no-copy + spec-inject
@@ -749,7 +734,7 @@ fn e5_restart_rebuilds_runtime_spec_from_role_docs() {
749
734
  // Edit a role doc AFTER initial compile: change alpha's role text.
750
735
  std::fs::write(
751
736
  ws.join("agents").join("alpha.md"),
752
- "---\nname: alpha\nrole: RENAMED Alpha Role\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nAlpha edited.\n",
737
+ "---\nname: alpha\nrole: RENAMED Alpha Role\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nAlpha edited.\n",
753
738
  )
754
739
  .unwrap();
755
740
  let transport = OfflineTransport::new();
@@ -974,7 +959,7 @@ fn e5_add_agent_resolves_team_dir_to_role_dir_when_runtime_spec_exists() {
974
959
  let role = team.join("w2-role.md");
975
960
  std::fs::write(
976
961
  &role,
977
- "---\nname: w2\nrole: Second Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nw2.\n",
962
+ "---\nname: w2\nrole: Second Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nw2.\n",
978
963
  )
979
964
  .unwrap();
980
965
  let transport = OfflineTransport::new();
@@ -1563,9 +1548,9 @@ fn quick_start_fresh_ws_spawns_resident_tmux_and_coordinator() {
1563
1548
  // Golden: restart/orchestration.py (Route-B resume spawn), lifecycle/start.py, lifecycle/operations.py.
1564
1549
  // ═════════════════════════════════════════════════════════════════════════
1565
1550
 
1566
- pub(super) const DELEG_ROLE_ALPHA: &str = "---\nname: alpha\nrole: Alpha Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nAlpha.\n";
1567
- pub(super) const DELEG_ROLE_BRAVO: &str = "---\nname: bravo\nrole: Bravo Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nBravo.\n";
1568
- const DELEG_ROLE_WORKER2: &str = "---\nname: worker2\nrole: Second Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nSecond worker.\n";
1551
+ pub(super) const DELEG_ROLE_ALPHA: &str = "---\nname: alpha\nrole: Alpha Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nAlpha.\n";
1552
+ pub(super) const DELEG_ROLE_BRAVO: &str = "---\nname: bravo\nrole: Bravo Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nBravo.\n";
1553
+ const DELEG_ROLE_WORKER2: &str = "---\nname: worker2\nrole: Second Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nSecond worker.\n";
1569
1554
 
1570
1555
  /// A workspace (= self-contained team dir) with a compiled 2-agent spec + state listing alpha/bravo as
1571
1556
  /// RESUMABLE (running, valid first_send_at, session_id) + a seeded HEALTHY coordinator.
@@ -2437,7 +2422,7 @@ fn restart_allow_fresh_copilot_keeps_session_id_null_until_capture_confirms() {
2437
2422
  .unwrap();
2438
2423
  std::fs::write(
2439
2424
  ws.join("agents").join("alpha.md"),
2440
- "---\nname: alpha\nrole: Alpha Worker\nprovider: copilot\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nAlpha.\n",
2425
+ "---\nname: alpha\nrole: Alpha Worker\nprovider: copilot\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nAlpha.\n",
2441
2426
  )
2442
2427
  .unwrap();
2443
2428
  let spec = crate::compiler::compile_team(&ws).expect("compile copilot team");
@@ -2541,7 +2526,7 @@ fn restart_allow_fresh_claude_clears_poisoned_session_id() {
2541
2526
  .unwrap();
2542
2527
  std::fs::write(
2543
2528
  ws.join("agents").join("alpha.md"),
2544
- "---\nname: alpha\nrole: Alpha\nprovider: claude\nmodel: sonnet\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nAlpha.\n",
2529
+ "---\nname: alpha\nrole: Alpha\nprovider: claude\nmodel: sonnet\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nAlpha.\n",
2545
2530
  )
2546
2531
  .unwrap();
2547
2532
  let spec = crate::compiler::compile_team(&ws).expect("compile");
@@ -2612,7 +2597,7 @@ fn fork_refuses_source_with_partial_tuple() {
2612
2597
  .unwrap();
2613
2598
  std::fs::write(
2614
2599
  ws.join("agents").join("src.md"),
2615
- "---\nname: src\nrole: Source\nprovider: codex\nmodel: gpt\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nSrc.\n",
2600
+ "---\nname: src\nrole: Source\nprovider: codex\nmodel: gpt\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nSrc.\n",
2616
2601
  )
2617
2602
  .unwrap();
2618
2603
  let spec = crate::compiler::compile_team(&ws).expect("compile");
@@ -3084,6 +3069,8 @@ fn quick_start_running_agent_state_shape_after_spawn_is_golden() {
3084
3069
  "mcp_config",
3085
3070
  "permissions",
3086
3071
  "effective_approval_policy",
3072
+ // 0.5.66 bypass 单源:fresh spawn 记录运行面 bypass 值(restart drift 挡板)。
3073
+ "as_launched_dangerously_skip_permissions",
3087
3074
  "session_id",
3088
3075
  "rollout_path",
3089
3076
  "captured_at",
@@ -410,7 +410,7 @@ impl RollbackFixture {
410
410
 
411
411
  fn agent_doc(name: &str, role: &str) -> String {
412
412
  format!(
413
- "---\nname: {name}\nrole: {role}\nprovider: codex\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{role}.\n"
413
+ "---\nname: {name}\nrole: {role}\nprovider: codex\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{role}.\n"
414
414
  )
415
415
  }
416
416
 
@@ -463,8 +463,8 @@ fn team_dir_with_roles(role_docs: &[(&str, &str)]) -> PathBuf {
463
463
  }
464
464
 
465
465
  fn breal_workspace() -> (PathBuf, PathBuf) {
466
- let w1 = "---\nname: w1\nrole: Phase B Real Worker One\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker one body.\n";
467
- let w2 = "---\nname: w2\nrole: Phase B Real Worker Two\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker two body.\n";
466
+ let w1 = "---\nname: w1\nrole: Phase B Real Worker One\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker one body.\n";
467
+ let w2 = "---\nname: w2\nrole: Phase B Real Worker Two\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker two body.\n";
468
468
  let team = team_dir_with_roles(&[("w1.md", w1), ("w2.md", w2)]);
469
469
  let workspace = team.parent().expect("team workspace").to_path_buf();
470
470
  seed_healthy_coordinator(&workspace);
@@ -483,7 +483,7 @@ fn breal_workspace() -> (PathBuf, PathBuf) {
483
483
  }
484
484
 
485
485
  fn breal_one_worker_workspace() -> (PathBuf, PathBuf) {
486
- let w1 = "---\nname: w1\nrole: Phase B Real Worker One\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker one body.\n";
486
+ let w1 = "---\nname: w1\nrole: Phase B Real Worker One\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker one body.\n";
487
487
  let team = team_dir_with_roles(&[("w1.md", w1)]);
488
488
  let workspace = team.parent().expect("team workspace").to_path_buf();
489
489
  seed_healthy_coordinator(&workspace);
@@ -526,7 +526,7 @@ fn strip_runtime_command_context(workspace: &std::path::Path) {
526
526
 
527
527
  fn role_doc(id: &str) -> String {
528
528
  format!(
529
- "---\nname: {id}\nrole: {id} Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{id} worker.\n"
529
+ "---\nname: {id}\nrole: {id} Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{id} worker.\n"
530
530
  )
531
531
  }
532
532
 
@@ -387,7 +387,7 @@ fn codex_ready_transport() -> OfflineTransport {
387
387
 
388
388
  fn role_doc(id: &str) -> String {
389
389
  format!(
390
- "---\nname: {id}\nrole: {id} Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{id} worker.\n"
390
+ "---\nname: {id}\nrole: {id} Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{id} worker.\n"
391
391
  )
392
392
  }
393
393
 
@@ -38,9 +38,9 @@ use hermetic::HermeticTestEnv;
38
38
  const TEAM_MD: &str =
39
39
  "---\nname: bug7\nobjective: BUG-7 worker readiness honesty contract.\nprovider: codex\n---\n\nTeam.\n";
40
40
 
41
- const CODEX_ROLE: &str = "---\nname: codexer\nrole: Codex Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nCodex worker.\n";
41
+ const CODEX_ROLE: &str = "---\nname: codexer\nrole: Codex Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nCodex worker.\n";
42
42
 
43
- const CLAUDE_ROLE: &str = "---\nname: clauder\nrole: Claude Worker\nprovider: claude\nmodel: claude-sonnet-4-6\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nClaude worker.\n";
43
+ const CLAUDE_ROLE: &str = "---\nname: clauder\nrole: Claude Worker\nprovider: claude\nmodel: claude-sonnet-4-6\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nClaude worker.\n";
44
44
 
45
45
  #[test]
46
46
  #[ignore = "real-machine: quick-start worker readiness gate"]
@@ -218,7 +218,7 @@ fn write_team_docs(team_dir: &Path, workers: &[String], provider: ProviderShape)
218
218
  fs::write(
219
219
  team_dir.join("agents").join(format!("{worker}.md")),
220
220
  format!(
221
- "---\nname: {worker}\nrole: Worker {worker}\nprovider: {}\nmodel: {}\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{worker}.\n",
221
+ "---\nname: {worker}\nrole: Worker {worker}\nprovider: {}\nmodel: {}\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{worker}.\n",
222
222
  provider.provider(),
223
223
  provider.model()
224
224
  ),
@@ -492,7 +492,7 @@ impl RestartFixture {
492
492
  std::fs::write(
493
493
  team.join("agents").join(format!("{agent}.md")),
494
494
  format!(
495
- "---\nname: {agent}\nrole: Worker {agent}\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n"
495
+ "---\nname: {agent}\nrole: Worker {agent}\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker.\n"
496
496
  ),
497
497
  )
498
498
  .unwrap();
@@ -342,7 +342,7 @@ impl HotfixCase {
342
342
  std::fs::write(
343
343
  dir.join("agents").join(format!("{agent_id}.md")),
344
344
  format!(
345
- "---\nname: {agent_id}\nrole: Greeter\nprovider: {}\nmodel: test\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n",
345
+ "---\nname: {agent_id}\nrole: Greeter\nprovider: {}\nmodel: test\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker.\n",
346
346
  provider_name(provider)
347
347
  ),
348
348
  )
@@ -1371,7 +1371,7 @@ impl RestartFixture {
1371
1371
  std::fs::write(
1372
1372
  team.join("agents/worker_a.md"),
1373
1373
  format!(
1374
- "---\nname: worker_a\nrole: Worker\nprovider: {provider}\nmodel: {}\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n",
1374
+ "---\nname: worker_a\nrole: Worker\nprovider: {provider}\nmodel: {}\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker.\n",
1375
1375
  if provider == "claude" {
1376
1376
  "claude-sonnet-4-6"
1377
1377
  } else {
@@ -1409,7 +1409,7 @@ impl RestartFixture {
1409
1409
  std::fs::write(
1410
1410
  team.join("agents/worker_a.md"),
1411
1411
  format!(
1412
- "---\nname: worker_a\nrole: Worker\nprovider: {provider}\nmodel: {}\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n",
1412
+ "---\nname: worker_a\nrole: Worker\nprovider: {provider}\nmodel: {}\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker.\n",
1413
1413
  if provider == "claude" {
1414
1414
  "claude-sonnet-4-6"
1415
1415
  } else {
@@ -151,7 +151,7 @@ impl ResumeFixture {
151
151
  .unwrap();
152
152
  std::fs::write(
153
153
  team.join("agents").join("worker_a.md"),
154
- "---\nname: worker_a\nrole: Worker A\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n",
154
+ "---\nname: worker_a\nrole: Worker A\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker.\n",
155
155
  )
156
156
  .unwrap();
157
157
  let spec = team_agent::compiler::compile_team(&team).unwrap();
@@ -291,7 +291,7 @@ fn agent(id: &str, status: &str, topology: bool) -> Value {
291
291
  }
292
292
 
293
293
  fn role_doc(id: &str) -> String {
294
- format!("---\nname: {id}\nrole: {id}\nprovider: fake\nmodel: fake\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{id}.\n")
294
+ format!("---\nname: {id}\nrole: {id}\nprovider: fake\nmodel: fake\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{id}.\n")
295
295
  }
296
296
 
297
297
  fn assert_no_standards(case: &Case) {
@@ -488,7 +488,7 @@ fn write_team_docs(team_dir: &Path, workers: usize) {
488
488
 
489
489
  fn role_doc(worker: &str) -> String {
490
490
  format!(
491
- "---\nname: {worker}\nrole: Worker {worker}\nprovider: fake\nmodel: fake\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{worker}.\n"
491
+ "---\nname: {worker}\nrole: Worker {worker}\nprovider: fake\nmodel: fake\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{worker}.\n"
492
492
  )
493
493
  }
494
494
 
@@ -368,7 +368,7 @@ fn red6_cli_restart_reports_and_top_level_error_logs_are_redacted() {
368
368
  }
369
369
 
370
370
  #[test]
371
- #[serial(env)]
371
+ #[serial(env, pid_probe)]
372
372
  fn red7_pane_and_profile_scrubbers_converge_without_losing_existing_policy() {
373
373
  let root = Path::new(env!("CARGO_MANIFEST_DIR"));
374
374
  let tmux = fs::read_to_string(root.join("src/tmux_backend.rs")).unwrap();
@@ -685,12 +685,12 @@ fn write_profile_fixture(root: &Path, base_url: &str, token: &str) -> PathBuf {
685
685
  .unwrap();
686
686
  fs::write(
687
687
  team.join("TEAM.md"),
688
- "---\nname: redact-profile\nobjective: Synthetic redaction profile contract.\nprovider: claude\nauth_mode: compatible_api\n---\n\nTeam.\n",
688
+ "---\nname: redact-profile\nobjective: Synthetic redaction profile contract.\nprovider: claude\nauth_mode: compatible_api\ndangerously_skip_permissions: false\n---\n\nTeam.\n",
689
689
  )
690
690
  .unwrap();
691
691
  fs::write(
692
692
  team.join("agents/worker.md"),
693
- "---\nname: worker\nrole: Worker\nprovider: claude\nauth_mode: compatible_api\nprofile: local\nmodel: null\ntools:\n - mcp_team\n---\n\nWorker.\n",
693
+ "---\nname: worker\nrole: Worker\nprovider: claude\nauth_mode: compatible_api\ndangerously_skip_permissions: false\nprofile: local\nmodel: null\ntools:\n - mcp_team\n---\n\nWorker.\n",
694
694
  )
695
695
  .unwrap();
696
696
  team
@@ -861,7 +861,7 @@ fn contract_c_lifecycle_launch_command_carries_role_tools_and_real_mcp_context()
861
861
  .unwrap();
862
862
  std::fs::write(
863
863
  teamdir.join("agents").join("w1.md"),
864
- "---\nname: w1\nrole: Worker must call report_result exactly once.\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nAlways use report_result for completion.\n",
864
+ "---\nname: w1\nrole: Worker must call report_result exactly once.\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nAlways use report_result for completion.\n",
865
865
  )
866
866
  .unwrap();
867
867
  let spec = team_agent::compiler::compile_team(&teamdir).unwrap();
@@ -172,7 +172,7 @@ fn write_claude_compatible_team(ws: &Path) -> PathBuf {
172
172
  .unwrap();
173
173
  std::fs::write(
174
174
  team.join("agents/worker_a.md"),
175
- "---\nname: worker_a\nrole: Compat Worker\nprovider: claude\nmodel: claude-haiku\nauth_mode: compatible_api\nprofile: relay\ntools:\n - mcp_team\n---\n\nCompat worker.\n",
175
+ "---\nname: worker_a\nrole: Compat Worker\nprovider: claude\nmodel: claude-haiku\nauth_mode: compatible_api\ndangerously_skip_permissions: false\nprofile: relay\ntools:\n - mcp_team\n---\n\nCompat worker.\n",
176
176
  )
177
177
  .unwrap();
178
178
  std::fs::write(
@@ -244,7 +244,7 @@ fn write_team_dir(root: &Path, dir_name: &str, agent: &str) -> PathBuf {
244
244
 
245
245
  fn role_doc(agent: &str) -> String {
246
246
  format!(
247
- "---\nname: {agent}\nrole: Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n"
247
+ "---\nname: {agent}\nrole: Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker.\n"
248
248
  )
249
249
  }
250
250
 
@@ -881,7 +881,7 @@ fn team_dir_with_name(root: &Path, dir_name: &str, spec_name: &str, agent_id: &s
881
881
 
882
882
  fn role_doc(name: &str) -> String {
883
883
  format!(
884
- "---\nname: {name}\nrole: Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n"
884
+ "---\nname: {name}\nrole: Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker.\n"
885
885
  )
886
886
  }
887
887
 
@@ -1057,7 +1057,7 @@ fn team_dir(root: &Path, name: &str, agents: &[(&str, &str)]) -> PathBuf {
1057
1057
 
1058
1058
  fn role_doc(name: &str, role: &str) -> String {
1059
1059
  format!(
1060
- "---\nname: {name}\nrole: {role}\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{role}.\n"
1060
+ "---\nname: {name}\nrole: {role}\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{role}.\n"
1061
1061
  )
1062
1062
  }
1063
1063
 
@@ -390,7 +390,7 @@ impl RollbackFixture {
390
390
 
391
391
  fn agent_doc(name: &str, role: &str) -> String {
392
392
  format!(
393
- "---\nname: {name}\nrole: {role}\nprovider: codex\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{role}.\n"
393
+ "---\nname: {name}\nrole: {role}\nprovider: codex\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{role}.\n"
394
394
  )
395
395
  }
396
396
 
@@ -393,7 +393,7 @@ impl RestartAutoAttachCase {
393
393
  std::fs::write(
394
394
  workspace.join("agents").join(format!("{WORKER}.md")),
395
395
  format!(
396
- "---\nname: {WORKER}\nrole: Worker {WORKER}\nprovider: fake\nmodel: fake\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n"
396
+ "---\nname: {WORKER}\nrole: Worker {WORKER}\nprovider: fake\nmodel: fake\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker.\n"
397
397
  ),
398
398
  )
399
399
  .expect("write worker role");
@@ -456,7 +456,7 @@ impl UpgradeFixture {
456
456
  std::fs::create_dir_all(self.team_dir.join("agents")).unwrap();
457
457
  std::fs::write(
458
458
  self.team_dir.join("agents").join("upgrade_worker.md"),
459
- "---\nname: upgrade_worker\nrole: Upgrade Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nWorker.\n",
459
+ "---\nname: upgrade_worker\nrole: Upgrade Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nWorker.\n",
460
460
  )
461
461
  .unwrap();
462
462
  let spec = team_agent::compiler::compile_team(&self.team_dir).unwrap();
@@ -39,9 +39,9 @@ use hermetic::HermeticTestEnv;
39
39
  const TEAM_MD: &str =
40
40
  "---\nname: verify031\nobjective: Verify mixed provider windows.\nprovider: codex\n---\n\nTeam.\n";
41
41
 
42
- const CODEX_ROLE: &str = "---\nname: codexer\nrole: Codex Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nCodex worker.\n";
42
+ const CODEX_ROLE: &str = "---\nname: codexer\nrole: Codex Worker\nprovider: codex\nmodel: gpt-5.5\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nCodex worker.\n";
43
43
 
44
- const CLAUDE_ROLE: &str = "---\nname: clauder\nrole: Claude Worker\nprovider: claude\nmodel: claude-sonnet-4-6\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\nClaude worker.\n";
44
+ const CLAUDE_ROLE: &str = "---\nname: clauder\nrole: Claude Worker\nprovider: claude\nmodel: claude-sonnet-4-6\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\nClaude worker.\n";
45
45
 
46
46
  #[test]
47
47
  #[serial(env)]
@@ -329,7 +329,7 @@ fn compiled_team_dir(label: &str, agents: &[(&str, &str)]) -> PathBuf {
329
329
 
330
330
  fn role_doc(name: &str, role: &str) -> String {
331
331
  format!(
332
- "---\nname: {name}\nrole: {role}\nprovider: codex\nmodel: codex-test-model\nauth_mode: subscription\ntools:\n - mcp_team\n---\n\n{role}.\n"
332
+ "---\nname: {name}\nrole: {role}\nprovider: codex\nmodel: codex-test-model\nauth_mode: subscription\ndangerously_skip_permissions: false\ntools:\n - mcp_team\n---\n\n{role}.\n"
333
333
  )
334
334
  }
335
335
 
@@ -58,7 +58,6 @@ mod b0_legacy_snapshot_nonauthority_contract;
58
58
  mod b0_reader_hideone_audit_contract;
59
59
  mod behavioral_diff_264_red;
60
60
  mod claude_profile_launch_red;
61
- mod codex_mcp_approval_inheritance_red;
62
61
  mod codex_weak_window_attribution_red;
63
62
  mod copilot_provider_red;
64
63
  mod display_adaptive_red;
@@ -88,7 +87,6 @@ mod team_key_retirement_txn_red;
88
87
  mod test_isolation_escape_contract;
89
88
  mod upgrade_compat_0211_red;
90
89
  mod verify_rs031_window_consistency_red;
91
- mod worker_dangerous_bypass_argv_red;
92
90
  mod worker_spawn_env_red;
93
91
  mod acceptance_b_batch_red;
94
92
  mod claude_compatible_config_red;
@@ -473,8 +473,6 @@ pub struct LaunchReport {
473
473
  pub routes: Vec<RoutingDecision>,
474
474
  /// 权限摘要(每 agent 一条)。
475
475
  pub permissions: Vec<PermissionSummary>,
476
- /// 危险审批安全态(dry-run 报告里的 `safety`)。
477
- pub safety: DangerousApproval,
478
476
  /// leader receiver(attach 成功时;经 step10 leader::attach_leader_to_state)。
479
477
  pub leader_receiver_attached: bool,
480
478
  pub session_capture_incomplete_agents: Vec<String>,