@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
@@ -2557,6 +2557,25 @@ impl Transport for TmuxBackend {
2557
2557
  Ok(SetEnvOutcome::Applied)
2558
2558
  }
2559
2559
 
2560
+ fn set_window_option(
2561
+ &self,
2562
+ session: &SessionName,
2563
+ window: &WindowName,
2564
+ option: &str,
2565
+ value: &str,
2566
+ ) -> Result<(), TransportError> {
2567
+ let target = format!("{}:{}", session.as_str(), window.as_str());
2568
+ let argv = vec![
2569
+ "tmux".to_string(),
2570
+ "set-window-option".to_string(),
2571
+ "-t".to_string(),
2572
+ target,
2573
+ option.to_string(),
2574
+ value.to_string(),
2575
+ ];
2576
+ self.run_ok(&argv)
2577
+ }
2578
+
2560
2579
  fn kill_server(&self) -> Result<(), TransportError> {
2561
2580
  TmuxBackend::kill_server(self);
2562
2581
  Ok(())
@@ -35,6 +35,7 @@ struct OfflineState {
35
35
  calls: Vec<&'static str>,
36
36
  spawns: Vec<SpawnRecord>,
37
37
  pane_titles: Vec<(String, String, String, String)>,
38
+ window_options: Vec<(String, String)>,
38
39
  inject_targets: Vec<Target>,
39
40
  inject_payloads: Vec<String>,
40
41
  tmux_endpoint: Option<String>,
@@ -70,6 +71,7 @@ impl Default for OfflineState {
70
71
  calls: Vec::new(),
71
72
  spawns: Vec::new(),
72
73
  pane_titles: Vec::new(),
74
+ window_options: Vec::new(),
73
75
  inject_targets: Vec::new(),
74
76
  inject_payloads: Vec::new(),
75
77
  tmux_endpoint: None,
@@ -267,6 +269,10 @@ impl OfflineTransport {
267
269
  self.with_state(|state| state.pane_titles.clone())
268
270
  }
269
271
 
272
+ pub fn window_options(&self) -> Vec<(String, String)> {
273
+ self.with_state(|state| state.window_options.clone())
274
+ }
275
+
270
276
  pub fn inject_targets(&self) -> Vec<Target> {
271
277
  self.with_state(|state| state.inject_targets.clone())
272
278
  }
@@ -555,6 +561,20 @@ impl Transport for OfflineTransport {
555
561
  Ok(SetEnvOutcome::Applied)
556
562
  }
557
563
 
564
+ fn set_window_option(
565
+ &self,
566
+ _session: &SessionName,
567
+ _window: &WindowName,
568
+ option: &str,
569
+ value: &str,
570
+ ) -> Result<(), TransportError> {
571
+ self.with_state(|state| {
572
+ state.calls.push("set_window_option");
573
+ state.window_options.push((option.to_string(), value.to_string()));
574
+ });
575
+ Ok(())
576
+ }
577
+
558
578
  fn kill_session(&self, session: &SessionName) -> Result<(), TransportError> {
559
579
  self.with_state(|state| {
560
580
  state.calls.push("kill_session");
@@ -762,6 +762,23 @@ pub trait Transport: Send + Sync {
762
762
  value: &str,
763
763
  ) -> Result<SetEnvOutcome, TransportError>;
764
764
 
765
+ /// A-55 (window rename race): set a tmux per-window option (e.g.
766
+ /// `allow-rename off`, `automatic-rename off`) on an existing window.
767
+ /// tmux=`set-window-option -t SESSION:WINDOW`; non-tmux backends refuse
768
+ /// via the default (typed unsupported).
769
+ fn set_window_option(
770
+ &self,
771
+ _session: &SessionName,
772
+ _window: &WindowName,
773
+ _option: &str,
774
+ _value: &str,
775
+ ) -> Result<(), TransportError> {
776
+ Err(TransportError::MuxUnavailable {
777
+ backend: self.kind(),
778
+ detail: "set-window-option is tmux-only".to_string(),
779
+ })
780
+ }
781
+
765
782
  // —— LIFECYCLE(SL)——
766
783
 
767
784
  fn kill_server(&self) -> Result<(), TransportError> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-agent/installer",
3
- "version": "0.5.65",
3
+ "version": "0.5.66",
4
4
  "description": "npx installer for Team Agent",
5
5
  "keywords": [
6
6
  "codex",
@@ -20,9 +20,9 @@
20
20
  "team-agent-installer": "npm/install.mjs"
21
21
  },
22
22
  "optionalDependencies": {
23
- "@team-agent/cli-darwin-arm64": "0.5.65",
24
- "@team-agent/cli-darwin-x64": "0.5.65",
25
- "@team-agent/cli-linux-x64": "0.5.65"
23
+ "@team-agent/cli-darwin-arm64": "0.5.66",
24
+ "@team-agent/cli-darwin-x64": "0.5.66",
25
+ "@team-agent/cli-linux-x64": "0.5.66"
26
26
  },
27
27
  "scripts": {
28
28
  "postinstall": "node npm/bincheck.mjs",
@@ -1,134 +0,0 @@
1
- use std::path::Path;
2
-
3
- use crate::lifecycle::{DangerousApproval, DangerousApprovalSource, LifecycleError};
4
-
5
- /// `detect_inherited_dangerous_permissions`(`launch/config.py`):扫进程祖先链找
6
- /// `--dangerously-*` flag,产出危险审批继承态。launch 在 inherited=false 且无 --yes 时拒。
7
- pub fn detect_dangerous_approval() -> Result<DangerousApproval, LifecycleError> {
8
- if let Ok(raw) = std::env::var("TEAM_AGENT_TEST_PROCESS_ANCESTRY_ARGV_JSON") {
9
- let argv_tokens = serde_json::from_str::<Vec<String>>(&raw).map_err(|e| {
10
- LifecycleError::StatePersist(format!("invalid test ancestry argv: {e}"))
11
- })?;
12
- return Ok(detect_dangerous_approval_in_argv(&argv_tokens)
13
- .unwrap_or_else(disabled_dangerous_approval));
14
- }
15
- for argv_tokens in process_ancestry_argv(std::process::id()) {
16
- if let Some(detected) = detect_dangerous_approval_in_argv(&argv_tokens) {
17
- return Ok(detected);
18
- }
19
- }
20
- Ok(disabled_dangerous_approval())
21
- }
22
-
23
- pub(super) fn disabled_dangerous_approval() -> DangerousApproval {
24
- DangerousApproval {
25
- enabled: false,
26
- source: DangerousApprovalSource::Disabled,
27
- inherited: false,
28
- provider: None,
29
- flag: None,
30
- worker_capability_above_leader: false,
31
- ancestry_binary_name: None,
32
- unexpected_binary: false,
33
- }
34
- }
35
-
36
- pub(super) fn detect_dangerous_approval_in_argv(
37
- argv_tokens: &[String],
38
- ) -> Option<DangerousApproval> {
39
- let argv0 = argv_tokens.first().map(String::as_str).unwrap_or("");
40
- let ancestry_binary_name = binary_name(argv0);
41
- for token in argv_tokens {
42
- for (provider, flag) in dangerous_leader_flags() {
43
- if token == flag {
44
- let unexpected_binary =
45
- !binary_matches_provider(provider, ancestry_binary_name.as_deref());
46
- return Some(DangerousApproval {
47
- enabled: true,
48
- source: DangerousApprovalSource::LeaderProcess,
49
- inherited: true,
50
- provider: Some((*provider).to_string()),
51
- flag: Some((*flag).to_string()),
52
- worker_capability_above_leader: false,
53
- ancestry_binary_name,
54
- unexpected_binary,
55
- });
56
- }
57
- }
58
- }
59
- None
60
- }
61
-
62
- pub(super) fn dangerous_leader_flags() -> &'static [(&'static str, &'static str)] {
63
- // Process argv command grammar, not persisted provider identity parsing.
64
- &[
65
- ("claude", "--dangerously-skip-permissions"),
66
- ("claude", "--dangerously-skip-permission"),
67
- ("codex", "--dangerously-bypass-approvals-and-sandbox"),
68
- // 0.3.27 P1 (E54 symptom 2): copilot's full-permission flags. Without
69
- // these entries, a copilot leader running with --allow-all / --yolo would
70
- // NOT propagate bypass to claude/codex workers because
71
- // detect_dangerous_approval scans the coordinator's ancestor argv and
72
- // only matches entries in THIS table.
73
- ("copilot", "--allow-all"),
74
- ("copilot", "--yolo"),
75
- ]
76
- }
77
-
78
- pub(super) fn binary_matches_provider(provider: &str, binary: Option<&str>) -> bool {
79
- // Binary-name command grammar, not provider identity parsing.
80
- match (provider, binary) {
81
- ("codex", Some("codex")) => true,
82
- ("claude", Some("claude" | "claude-code" | "claude_code")) => true,
83
- // 0.3.27 P1 (E54): copilot binary detection for dangerous-approval scan.
84
- ("copilot", Some("copilot" | "github-copilot" | "gh-copilot")) => true,
85
- _ => false,
86
- }
87
- }
88
-
89
- pub(super) fn binary_name(argv0: &str) -> Option<String> {
90
- Path::new(argv0)
91
- .file_name()
92
- .and_then(|v| v.to_str())
93
- .filter(|s| !s.is_empty())
94
- .map(str::to_string)
95
- }
96
-
97
- pub(super) fn process_ancestry_argv(pid: u32) -> Vec<Vec<String>> {
98
- let mut out = Vec::new();
99
- let mut current = pid;
100
- let mut seen = std::collections::BTreeSet::new();
101
- for _ in 0..12 {
102
- if current == 0 || !seen.insert(current) {
103
- break;
104
- }
105
- if let Some(argv_tokens) = process_argv_tokens(current) {
106
- out.push(argv_tokens);
107
- }
108
- let Some(parent) = process_parent_pid(current) else {
109
- break;
110
- };
111
- if parent <= 1 || parent == current {
112
- break;
113
- }
114
- current = parent;
115
- }
116
- out
117
- }
118
-
119
- // 0.5.x Windows portability Batch 4: `process_argv_tokens` and
120
- // `process_parent_pid` route through `crate::platform::argv`. Unix
121
- // impls are byte-preserving (Linux `/proc/<pid>/cmdline`, macOS
122
- // `sysctl(KERN_PROCARGS2)`, other Unix `ps -p ... -o command=`).
123
- // Windows returns `None` per design §Batch 4 conservative anchor:
124
- // unknown argv must never infer elevated approval; callers already
125
- // treat `None` as "no elevation inherited" via
126
- // `disabled_dangerous_approval()`.
127
-
128
- pub(super) fn process_argv_tokens(pid: u32) -> Option<Vec<String>> {
129
- crate::platform::argv::argv_tokens(pid)
130
- }
131
-
132
- pub(super) fn process_parent_pid(pid: u32) -> Option<u32> {
133
- crate::platform::argv::parent_pid(pid)
134
- }