@team-agent/installer 0.5.98 → 0.5.100

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 (71) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/adapters.rs +1 -163
  4. package/crates/team-agent/src/cli/diagnose.rs +3 -19
  5. package/crates/team-agent/src/cli/emit.rs +20 -204
  6. package/crates/team-agent/src/cli/mod.rs +138 -205
  7. package/crates/team-agent/src/cli/send/coordinator.rs +2 -2
  8. package/crates/team-agent/src/cli/spec.rs +41 -67
  9. package/crates/team-agent/src/cli/tests/main_preserved.rs +2 -186
  10. package/crates/team-agent/src/cli/tests/missing_subcommands.rs +9 -10
  11. package/crates/team-agent/src/cli/tests/run_delegation.rs +0 -3
  12. package/crates/team-agent/src/cli/tests/verb_validate.rs +0 -1
  13. package/crates/team-agent/src/cli/triage.rs +1 -1
  14. package/crates/team-agent/src/cli/types.rs +0 -55
  15. package/crates/team-agent/src/compiler/tests.rs +5 -8
  16. package/crates/team-agent/src/compiler.rs +6 -14
  17. package/crates/team-agent/src/leader/lease.rs +1 -1
  18. package/crates/team-agent/src/lifecycle/launch/add_agent.rs +1 -1
  19. package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +1 -1
  20. package/crates/team-agent/src/lifecycle/launch/agent_state.rs +5 -25
  21. package/crates/team-agent/src/lifecycle/launch/identity.rs +2 -18
  22. package/crates/team-agent/src/lifecycle/launch/layout.rs +7 -29
  23. package/crates/team-agent/src/lifecycle/launch/leader_context.rs +1 -1
  24. package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +1 -1
  25. package/crates/team-agent/src/lifecycle/launch/ownership.rs +1 -1
  26. package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +7 -7
  27. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +12 -49
  28. package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +3 -9
  29. package/crates/team-agent/src/lifecycle/launch/readiness.rs +1 -1
  30. package/crates/team-agent/src/lifecycle/launch/spawn.rs +2 -61
  31. package/crates/team-agent/src/lifecycle/launch/spec_state.rs +2 -15
  32. package/crates/team-agent/src/lifecycle/launch/state_projection.rs +3 -7
  33. package/crates/team-agent/src/lifecycle/launch/worker_env.rs +1 -1
  34. package/crates/team-agent/src/lifecycle/launch.rs +3 -4
  35. package/crates/team-agent/src/lifecycle/mod.rs +0 -8
  36. package/crates/team-agent/src/lifecycle/restart/agent.rs +62 -8
  37. package/crates/team-agent/src/lifecycle/restart/common.rs +0 -32
  38. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +6 -15
  39. package/crates/team-agent/src/lifecycle/tests/b0_reader_hideone_audit_contract.rs +2 -2
  40. package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +1 -1
  41. package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +1 -2
  42. package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +0 -1
  43. package/crates/team-agent/src/lifecycle/tests/core.rs +0 -213
  44. package/crates/team-agent/src/lifecycle/tests/issue238_codex_effort_contract.rs +96 -0
  45. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +1 -0
  46. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +31 -77
  47. package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +2 -2
  48. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +4 -8
  49. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +16 -9
  50. package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +1 -1
  51. package/crates/team-agent/src/lifecycle/tests/realmachine_clusters_1_6_red.rs +0 -60
  52. package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +3 -4
  53. package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +2 -2
  54. package/crates/team-agent/src/lifecycle/tests.rs +1 -2
  55. package/crates/team-agent/src/lifecycle/types.rs +3 -133
  56. package/crates/team-agent/src/messaging/send.rs +2 -2
  57. package/crates/team-agent/src/model/enums.rs +21 -71
  58. package/crates/team-agent/src/model/spec.rs +5 -20
  59. package/crates/team-agent/src/provider/adapters/codex.rs +2 -2
  60. package/crates/team-agent/src/provider/types.rs +7 -6
  61. package/crates/team-agent/src/state/repository.rs +0 -5
  62. package/examples/team.spec.yaml +0 -1
  63. package/package.json +4 -4
  64. package/schemas/team.schema.json +2 -2
  65. package/skills/team-agent/SKILL.md +1 -1
  66. package/skills/team-agent/references/recovery-runbook.md +2 -2
  67. package/skills/team-agent/references/team-agent-operator.md +3 -10
  68. package/skills/team-agent/references/team-in-team.md +0 -6
  69. package/crates/team-agent/src/lifecycle/display.rs +0 -550
  70. package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +0 -884
  71. package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +0 -481
@@ -58,11 +58,9 @@ mod codex_weak_window_attribution_red;
58
58
  mod communication_mode_runtime_contract_red;
59
59
  mod copilot_provider_red;
60
60
  mod core;
61
- mod core_034_real_red;
62
61
  mod cursor_mcp_overlay;
63
62
  mod cursor_require_explicit_model_red;
64
63
  mod cursor_restart_resume_red;
65
- mod display_adaptive_red;
66
64
  mod f032_startup_prompt_best_effort_red;
67
65
  mod grok_effort_argv_red;
68
66
  mod grok_mcp_overlay_red;
@@ -70,6 +68,7 @@ mod grok_require_explicit_model_red;
70
68
  mod grok_restart_resume_red;
71
69
  mod harvest2_a_batch_red;
72
70
  mod host_cotenant_death_p0_contract;
71
+ mod issue238_codex_effort_contract;
73
72
  mod lane_ops;
74
73
  mod launch_spawn;
75
74
  mod lifecycle_lock;
@@ -24,7 +24,6 @@
24
24
  //! ---
25
25
  //! lifecycle 数据类型:newtype / enum / data struct / error / outcome-report 集中定义。
26
26
 
27
- use std::collections::BTreeMap;
28
27
  use std::path::PathBuf;
29
28
 
30
29
  use serde::{Deserialize, Serialize};
@@ -32,9 +31,7 @@ use thiserror::Error;
32
31
 
33
32
  use crate::model::ids::AgentId;
34
33
  use crate::provider::{RolloutPath, SessionId};
35
- use crate::transport::{PaneId, SessionName, WindowName};
36
-
37
- use super::DisplayBackend;
34
+ use crate::transport::SessionName;
38
35
 
39
36
  // ===========================================================================
40
37
  // CROSS-LANE PLACEHOLDERS(13/14/15 兄弟 lane 尚未交付;leader 集成时 reconcile)
@@ -184,22 +181,6 @@ impl std::fmt::Display for PlanId {
184
181
  }
185
182
  }
186
183
 
187
- /// ghostty 派生的唯一 linked-session 名(`ghostty_display_session_name`,sha1 派生,
188
- /// `display/ghostty.py`)。与 worker 的 `SessionName` 类型上区分,防混传(card §57)。
189
- #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
190
- #[serde(transparent)]
191
- pub struct DisplaySessionName(pub String);
192
-
193
- impl DisplaySessionName {
194
- /// ---
195
- /// purpose: 取 ghostty 派生 display session 名的原始字符串
196
- /// returns: 内部保存的名字
197
- /// ---
198
- pub fn as_str(&self) -> &str {
199
- &self.0
200
- }
201
- }
202
-
203
184
  // ===========================================================================
204
185
  // ENUM(card §3/§11:散字符串 → 穷尽 enum)
205
186
  // ===========================================================================
@@ -240,30 +221,6 @@ pub enum FirstSendAtState {
240
221
  Corrupt,
241
222
  }
242
223
 
243
- /// adaptive 阻塞 reason(`ADAPTIVE_BLOCK_REASONS`,6 个封闭值,`display/adaptive.py:21`)。
244
- /// **必须 enum**(契约 C16 封闭集);`adaptive_blocked` 对越界 reason 兜底成
245
- /// `AggregatorRebuildFailed`。
246
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
247
- #[serde(rename_all = "snake_case")]
248
- pub enum AdaptiveBlockReason {
249
- LeaderNotInTmux,
250
- SplitFailed,
251
- WindowCreateFailed,
252
- WorkerSessionMissing,
253
- NotImplementedThisPlatform,
254
- AggregatorRebuildFailed,
255
- }
256
-
257
- /// display `status`(`agent_state["display"]["status"]`,`start.py:123`)。
258
- /// **应 enum**:决定 `start_agent` 是否重开显示。
259
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
260
- #[serde(rename_all = "snake_case")]
261
- pub enum DisplayStatus {
262
- Opened,
263
- Blocked,
264
- Stopped,
265
- }
266
-
267
224
  /// plan `status`(`orchestrator/__init__.py`)。**应 enum**:`start_plan` 对已
268
225
  /// running/halted/completed 幂等返回。
269
226
  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
@@ -285,64 +242,9 @@ pub enum DangerousApprovalSource {
285
242
  }
286
243
 
287
244
  // ===========================================================================
288
- // DATA STRUCT(每 worker display / restart 候选 / plan state / 危险审批)
245
+ // DATA STRUCT(restart 候选 / plan state / 危险审批)
289
246
  // ===========================================================================
290
247
 
291
- /// adaptive 能力探测结果(`probe_display_capabilities`,`display/adaptive.py:31`)。
292
- /// **C13 一等公民**:分支只看 probe,不看 `cfg!(target_os)`;Windows/WSL →
293
- /// `NotImplementedThisPlatform`。
294
- #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
295
- pub struct DisplayProbe {
296
- pub in_tmux: bool,
297
- pub platform: String,
298
- pub leader_session: Option<SessionName>,
299
- pub leader_pane: Option<PaneId>,
300
- pub caps: CapsFlags,
301
- /// 探测后的 adaptive 状态(可开 / 已封闭+reason)。
302
- pub adaptive_status: DisplayStatus,
303
- /// 封闭时填 reason(C16 封闭集)。
304
- pub reason: Option<AdaptiveBlockReason>,
305
- }
306
-
307
- /// 平台能力位(`caps{tmux_append_windows, adaptive_display}`)。
308
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
309
- pub struct CapsFlags {
310
- pub tmux_append_windows: bool,
311
- pub adaptive_display: bool,
312
- }
313
-
314
- /// 每 worker display state(写进 `state.agents.<id>.display`)。adaptive vs ghostty_window
315
- /// vs ghostty_workspace 字段不同 → enum 区分(card §50)。
316
- #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
317
- #[serde(tag = "backend", rename_all = "snake_case")]
318
- pub enum WorkerDisplay {
319
- Adaptive {
320
- status: DisplayStatus,
321
- window: Option<WindowName>,
322
- workspace_window: Option<WindowName>,
323
- pane_id: Option<PaneId>,
324
- pane_title: Option<String>,
325
- target: Option<String>,
326
- target_worker_session: Option<String>,
327
- linked_session: Option<String>,
328
- leader_session: Option<SessionName>,
329
- display_session: Option<SessionName>,
330
- fallback: Option<String>,
331
- },
332
- GhosttyWindow {
333
- status: DisplayStatus,
334
- linked_session: DisplaySessionName,
335
- display_session: DisplaySessionName,
336
- },
337
- GhosttyWorkspace {
338
- status: DisplayStatus,
339
- display_session: DisplaySessionName,
340
- },
341
- Blocked {
342
- reason: AdaptiveBlockReason,
343
- },
344
- }
345
-
346
248
  /// `RestartCandidate`(`restart/selection.py:27`)。`select_restart_state` 多 team 选择;
347
249
  /// `has_context` 是 resume 可行性粗判。
348
250
  #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@@ -464,8 +366,7 @@ impl PlanCondition {
464
366
  // ERROR(card §10:fallible 边界;daemon/CLI 入口返 rich Result<Report, Error>)
465
367
  // ===========================================================================
466
368
 
467
- /// lifecycle 子系统错误。能力性降级(adaptive blocked)**不**走这里 —— 那是 typed
468
- /// outcome(`DisplayStatus::Blocked` / `AdaptiveBlockReason`)。这里只装真失败:
369
+ /// lifecycle 子系统错误。这里只装真失败:
469
370
  /// owner-gate 拒绝、session 冲突、state 写崩(bug-084)、provider/transport I/O、回滚失败。
470
371
  #[derive(Debug, Error)]
471
372
  pub enum LifecycleError {
@@ -560,10 +461,6 @@ pub struct StartedAgent {
560
461
  pub claude_config_dir: Option<PathBuf>,
561
462
  pub provider_projects_root: Option<PathBuf>,
562
463
  pub managed_mcp_config: bool,
563
- pub layout_window: Option<WindowName>,
564
- pub layout_index: Option<usize>,
565
- pub pane_index: Option<usize>,
566
- pub display: WorkerDisplay,
567
464
  }
568
465
 
569
466
  /// 路由决策(`routing.decision` 事件 / launch `routes[]`)。
@@ -603,7 +500,6 @@ pub enum QuickStartReport {
603
500
  launch: Box<LaunchReport>,
604
501
  next_actions: Vec<String>,
605
502
  attach_commands: Vec<String>,
606
- display_backend: String,
607
503
  /// BUG-7: real readiness verdict. `Ready` ⇒ the wrapper completed AND the
608
504
  /// caller already verified tool-set availability; the framework itself
609
505
  /// never emits this without an external observable confirming worker
@@ -940,32 +836,6 @@ pub struct RestartPlan {
940
836
  pub unresumable: Vec<UnresumableWorker>,
941
837
  }
942
838
 
943
- /// display 解析结果(`resolve_display_backend`,`display/backend.py`)。非默认时非静默
944
- /// 发 `display.backend_resolved`。
945
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
946
- pub struct ResolvedBackend {
947
- pub backend: DisplayBackend,
948
- /// 是否非默认(默认 adaptive;非默认非静默发事件)。
949
- pub non_default: bool,
950
- }
951
-
952
- /// `open_worker_displays` 结果(`display/worker_window.py`)。每 worker 一个
953
- /// `WorkerDisplay`,失败不阻塞 team readiness(C14)。
954
- #[derive(Debug, Clone, PartialEq, Eq)]
955
- pub struct OpenDisplaysReport {
956
- pub backend: DisplayBackend,
957
- pub displays: BTreeMap<String, WorkerDisplay>,
958
- }
959
-
960
- /// `close_team_display_backends` 结果(`display/close.py`,C9 close-by-recorded-backend)。
961
- #[derive(Debug, Clone, PartialEq, Eq)]
962
- pub struct CloseDisplaysReport {
963
- /// 按 state 记录的后端关掉的窗口/会话标识。
964
- pub closed: Vec<String>,
965
- /// orphan 清理(adaptive 只删带 team tag 的窗口,C2 leader pane 安全)。
966
- pub orphans_cleaned: Vec<String>,
967
- }
968
-
969
839
  /// plan 状态机推进结果(`orchestrator/__init__.py` start_plan / handle_report_result /
970
840
  /// halt_plan 的 typed 版)。
971
841
  #[derive(Debug, Clone, PartialEq, Eq)]
@@ -551,11 +551,11 @@ fn coordinator_unavailable_outcome(
551
551
  );
552
552
  let warning = if persist {
553
553
  format!(
554
- "coordinator is not running; message was queued for {recipient} and will retry. Run `team-agent diagnose` or restart the team."
554
+ "coordinator is not running; message was queued for {recipient} and will retry. Run `team-agent doctor` or restart the team."
555
555
  )
556
556
  } else {
557
557
  format!(
558
- "coordinator protocol or schema is incompatible; message was not queued for {recipient}. Run `team-agent diagnose` or upgrade the runtime."
558
+ "coordinator protocol or schema is incompatible; message was not queued for {recipient}. Run `team-agent doctor` or upgrade the runtime."
559
559
  )
560
560
  };
561
561
  event_log.write(
@@ -34,15 +34,18 @@ pub enum Provider {
34
34
 
35
35
  /// 0.4.x Provider effort MVP: reasoning effort level passed to the provider.
36
36
  /// Configuration sources (resolution order):
37
- /// 1. role doc front matter `effort: low|medium|high|xhigh|max`
38
- /// 2. TEAM.md front matter `provider_effort: low|medium|high|xhigh|max`
37
+ /// 1. role doc front matter `effort: low|medium|high|xhigh|max|ultra`
38
+ /// 2. TEAM.md front matter `provider_effort: low|medium|high|xhigh|max|ultra` (except Pi)
39
39
  /// 3. provider default (framework passes no flag)
40
40
  ///
41
41
  /// Provider support:
42
42
  /// - claude / claude_code: low|medium|high|xhigh|max → `--effort <level>`
43
- /// - codex: low|medium|high|xhigh (NOT max) → `-c model_reasoning_effort=<level>`
44
- /// - grok: low|medium|high|xhigh (NOT max) → `--effort <level>`
45
- /// - copilot / gemini_cli / cursor_agent / fake: unsupported — warning event, no flag
43
+ /// - codex: low|medium|high|xhigh|max|ultra → `-c model_reasoning_effort=<level>`
44
+ /// Ultra adds Codex client delegation to max reasoning; it is not an API effort.
45
+ /// - pi: low|medium|high|xhigh|max → `--thinking <level>`
46
+ /// - grok: low|medium|high|xhigh → `--effort <level>`; max/ultra rejected
47
+ /// - copilot / gemini_cli / fake: low..xhigh ignored with warning; max/ultra rejected
48
+ /// - cursor_agent: all effort rejected
46
49
  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
47
50
  pub enum ProviderEffort {
48
51
  #[serde(rename = "low")]
@@ -55,6 +58,8 @@ pub enum ProviderEffort {
55
58
  XHigh,
56
59
  #[serde(rename = "max")]
57
60
  Max,
61
+ #[serde(rename = "ultra")]
62
+ Ultra,
58
63
  }
59
64
 
60
65
  impl ProviderEffort {
@@ -66,6 +71,7 @@ impl ProviderEffort {
66
71
  "high" => Some(Self::High),
67
72
  "xhigh" => Some(Self::XHigh),
68
73
  "max" => Some(Self::Max),
74
+ "ultra" => Some(Self::Ultra),
69
75
  _ => None,
70
76
  }
71
77
  }
@@ -78,20 +84,17 @@ impl ProviderEffort {
78
84
  Self::High => "high",
79
85
  Self::XHigh => "xhigh",
80
86
  Self::Max => "max",
87
+ Self::Ultra => "ultra",
81
88
  }
82
89
  }
83
90
 
84
- /// Effort levels Claude-only (Codex / others must reject `max`).
85
- pub fn is_claude_only(self) -> bool {
86
- matches!(self, Self::Max)
87
- }
88
-
89
- /// Native command support. Claude/Pi accept max; Codex/Grok accept
90
- /// the other levels. Use resolve_for_provider for admission/ignore policy.
91
+ /// Native command support: Codex through ultra, Claude/Pi through max,
92
+ /// Grok through xhigh. Use resolve_for_provider for admission/ignore policy.
91
93
  pub fn is_supported_by(self, provider: Provider) -> bool {
92
94
  match provider {
93
- Provider::Claude | Provider::ClaudeCode | Provider::Pi => true,
94
- Provider::Codex | Provider::Grok => !self.is_claude_only(),
95
+ Provider::Codex => true,
96
+ Provider::Claude | Provider::ClaudeCode | Provider::Pi => self != Self::Ultra,
97
+ Provider::Grok => !matches!(self, Self::Max | Self::Ultra),
95
98
  Provider::Copilot | Provider::GeminiCli | Provider::CursorAgent | Provider::Fake => {
96
99
  false
97
100
  }
@@ -106,8 +109,10 @@ impl ProviderEffort {
106
109
  }
107
110
  if self.is_supported_by(provider) {
108
111
  Ok(Some(self))
109
- } else if self.is_claude_only() {
110
- Err("effort 'max' is only supported by claude/claude_code/pi")
112
+ } else if self == Self::Ultra {
113
+ Err("effort 'ultra' is only supported by codex")
114
+ } else if self == Self::Max {
115
+ Err("effort 'max' is only supported by claude/claude_code/codex/pi")
111
116
  } else {
112
117
  Ok(None)
113
118
  }
@@ -208,30 +213,6 @@ pub enum Backend {
208
213
  Pty,
209
214
  }
210
215
 
211
- /// display backend(`VALID_DISPLAY_BACKENDS` `display/backend.py:7-9`)。
212
- /// **`adaptive` 在代码集里但不在 JSON schema enum** —— 以代码为准(陷阱 #5)。
213
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
214
- #[serde(rename_all = "snake_case")]
215
- pub enum DisplayBackend {
216
- None,
217
- TmuxAttach,
218
- Iterm,
219
- Ghostty,
220
- GhosttyWindow,
221
- GhosttyWorkspace,
222
- Adaptive,
223
- }
224
-
225
- impl DisplayBackend {
226
- /// `DISPLAY_BACKENDS_WITH_WORKER_VIEWS = GHOSTTY_* | {adaptive}`(`display/backend.py:8`)。
227
- pub fn has_worker_views(self) -> bool {
228
- matches!(
229
- self,
230
- Self::Ghostty | Self::GhosttyWindow | Self::GhosttyWorkspace | Self::Adaptive
231
- )
232
- }
233
- }
234
-
235
216
  /// agent permission mode(schema `agent.permission_mode`;compiler 恒发 `restricted`)。
236
217
  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
237
218
  #[serde(rename_all = "snake_case")]
@@ -324,18 +305,6 @@ mod tests {
324
305
  serde_json::to_string(&CommProtocol::McpInbox).unwrap(),
325
306
  "\"mcp_inbox\"",
326
307
  ),
327
- (
328
- serde_json::to_string(&DisplayBackend::TmuxAttach).unwrap(),
329
- "\"tmux_attach\"",
330
- ),
331
- (
332
- serde_json::to_string(&DisplayBackend::GhosttyWorkspace).unwrap(),
333
- "\"ghostty_workspace\"",
334
- ),
335
- (
336
- serde_json::to_string(&DisplayBackend::Adaptive).unwrap(),
337
- "\"adaptive\"",
338
- ),
339
308
  (
340
309
  serde_json::to_string(&PaneLiveness::Unknown).unwrap(),
341
310
  "\"unknown\"",
@@ -380,25 +349,6 @@ mod tests {
380
349
  }
381
350
  }
382
351
 
383
- #[test]
384
- fn display_backend_worker_views() {
385
- for b in [
386
- DisplayBackend::Ghostty,
387
- DisplayBackend::GhosttyWindow,
388
- DisplayBackend::GhosttyWorkspace,
389
- DisplayBackend::Adaptive,
390
- ] {
391
- assert!(b.has_worker_views());
392
- }
393
- for b in [
394
- DisplayBackend::None,
395
- DisplayBackend::TmuxAttach,
396
- DisplayBackend::Iterm,
397
- ] {
398
- assert!(!b.has_worker_views());
399
- }
400
- }
401
-
402
352
  #[test]
403
353
  fn receive_worker_outputs_passthrough_preserves_drift_value() {
404
354
  // compiler 发的 drift 值必须原样保留(byte 不丢),不被拒。
@@ -20,6 +20,8 @@ use crate::model::yaml::Value as Yaml;
20
20
  use crate::model::yaml;
21
21
  use crate::provider::wire::parse_canonical_provider;
22
22
 
23
+ const LEGACY_DISPLAY_KEY: &str = concat!("display", "_backend");
24
+
23
25
  /// result_envelope_v1 顶层 required(= allowed)。
24
26
  const RESULT_REQUIRED: &[&str] = &[
25
27
  "schema_version",
@@ -211,15 +213,6 @@ const ROOT_KEYS: &[&str] = &[
211
213
  "tasks",
212
214
  ];
213
215
  const AUTH_MODES: &[&str] = &["subscription", "official_api", "compatible_api"];
214
- const VALID_DISPLAY_BACKENDS: &[&str] = &[
215
- "none",
216
- "tmux_attach",
217
- "iterm",
218
- "ghostty",
219
- "ghostty_window",
220
- "ghostty_workspace",
221
- "adaptive",
222
- ];
223
216
  const TASK_STATUS_STRS: &[&str] = &[
224
217
  "pending",
225
218
  "ready",
@@ -319,7 +312,7 @@ fn basic_schema_errors(spec: &Yaml) -> Vec<String> {
319
312
  if let Some(raw) = team.get("provider_effort").and_then(Yaml::as_str) {
320
313
  if crate::model::enums::ProviderEffort::parse(raw).is_none() {
321
314
  e.push(format!(
322
- "/team/provider_effort: unknown effort '{raw}' (allowed: low|medium|high|xhigh|max)"
315
+ "/team/provider_effort: unknown effort '{raw}' (allowed: low|medium|high|xhigh|max|ultra)"
323
316
  ));
324
317
  }
325
318
  }
@@ -460,7 +453,7 @@ fn check_agent(agent: &Yaml, path: &str, errors: &mut Vec<String>) {
460
453
  match crate::model::enums::ProviderEffort::parse(raw) {
461
454
  None => {
462
455
  errors.push(format!(
463
- "{path}/effort: unknown effort '{raw}' (allowed: low|medium|high|xhigh|max)"
456
+ "{path}/effort: unknown effort '{raw}' (allowed: low|medium|high|xhigh|max|ultra)"
464
457
  ));
465
458
  }
466
459
  Some(effort) => {
@@ -598,7 +591,7 @@ fn check_runtime(runtime: Option<&Yaml>, errors: &mut Vec<String>) {
598
591
  "require_user_approval_before_launch",
599
592
  "max_active_agents",
600
593
  "startup_order",
601
- "display_backend",
594
+ LEGACY_DISPLAY_KEY,
602
595
  "auto_attach_leader",
603
596
  "fast",
604
597
  "tick_interval_sec",
@@ -614,14 +607,6 @@ fn check_runtime(runtime: Option<&Yaml>, errors: &mut Vec<String>) {
614
607
  if !matches!(get("backend").and_then(Yaml::as_str), Some("tmux" | "pty")) {
615
608
  errors.push("/runtime/backend: invalid backend".to_string());
616
609
  }
617
- if let Some(db) = get("display_backend") {
618
- if !db
619
- .as_str()
620
- .is_some_and(|s| VALID_DISPLAY_BACKENDS.contains(&s))
621
- {
622
- errors.push("/runtime/display_backend: invalid display backend".to_string());
623
- }
624
- }
625
610
  if get("auto_trust_own_workspace").is_some_and(|v| !matches!(v, Yaml::Bool(_))) {
626
611
  errors.push("/runtime/auto_trust_own_workspace: must be a boolean".to_string());
627
612
  }
@@ -21,8 +21,8 @@ pub(crate) fn codex_base_command(
21
21
  // 0.4.x provider effort MVP step 6: when Some, inject
22
22
  // `-c model_reasoning_effort=<level>` AFTER existing profile
23
23
  // codex_config overrides — explicit launch effort wins over profile.
24
- // Codex does not support `max`; the caller filters that case via
25
- // `ProviderEffort::is_supported_by` before reaching this point.
24
+ // Preserve max/ultra verbatim: ultra enables Codex client delegation
25
+ // on top of max reasoning, rather than a separate model API effort.
26
26
  effort: Option<crate::model::enums::ProviderEffort>,
27
27
  ) -> Vec<String> {
28
28
  let mut argv = vec!["codex".to_string()];
@@ -172,7 +172,7 @@ pub enum AuthHintStatus {
172
172
  pub enum NoPingReason {
173
173
  /// worker 从未 open 过 turn(`idle_predicate.py:61`)。
174
174
  NotArmedNoWorkerTurn,
175
- /// suppress flag 置位(acknowledge-idle 后,`idle_predicate.py:63`)。
175
+ /// Suppress flag from a legacy idle acknowledgement (`idle_predicate.py:63`).
176
176
  Acknowledged,
177
177
  /// armed 但 elapsed < debounce(`idle_predicate.py:65`)。
178
178
  DebounceActive,
@@ -352,11 +352,12 @@ pub struct ProviderCommandContext<'a> {
352
352
  /// from role doc / TEAM.md / provider default. `None` means the
353
353
  /// framework passes no effort flag (provider default).
354
354
  /// - Claude / ClaudeCode: low|medium|high|xhigh|max → `--effort <level>`
355
- /// - Codex: low|medium|high|xhigh → `-c model_reasoning_effort=<level>`
356
- /// - Grok: low|medium|high|xhigh (NOT max) → `--effort <level>`
357
- /// - Copilot / Gemini / CursorAgent / Fake: ignored, warning event
358
- /// emitted at the caller (lifecycle/launch.rs / lifecycle/restart)
359
- /// before construct.
355
+ /// - Codex: low|medium|high|xhigh|max|ultra → `-c model_reasoning_effort=<level>`
356
+ /// Ultra enables Codex client delegation on top of max reasoning.
357
+ /// - Pi: low|medium|high|xhigh|max → `--thinking <level>`; ultra rejected
358
+ /// - Grok: low|medium|high|xhigh → `--effort <level>`; max/ultra rejected
359
+ /// - Copilot / Gemini / Fake: low..xhigh ignored with a caller warning;
360
+ /// max/ultra rejected. CursorAgent rejects all effort.
360
361
  pub effort: Option<crate::model::enums::ProviderEffort>,
361
362
  }
362
363
 
@@ -419,9 +419,6 @@ pub enum StateWriteIntent<'a> {
419
419
  SchedulerSuppression {
420
420
  owner_team_id: Option<&'a str>,
421
421
  },
422
- IdleAck {
423
- team_key: Option<&'a str>,
424
- },
425
422
  TaskRepair {
426
423
  team_key: Option<&'a str>,
427
424
  },
@@ -650,8 +647,6 @@ fn route_direct(
650
647
  },
651
648
  // SchedulerSuppression -> root save (messaging/scheduler.rs:259).
652
649
  StateWriteIntent::SchedulerSuppression { .. } => helper_write_root(workspace, state),
653
- // IdleAck -> root save (cli/mod.rs:2544).
654
- StateWriteIntent::IdleAck { .. } => helper_write_root(workspace, state),
655
650
  // TaskRepair -> `save_team_scoped_state` (cli/adapters.rs:675).
656
651
  StateWriteIntent::TaskRepair { .. } => helper_write_team_scoped(workspace, state),
657
652
  // FakeE2eSeed / SelfMigration are diagnostic seams. The current
@@ -136,7 +136,6 @@ communication:
136
136
  mirror_files: .team/messages
137
137
  runtime:
138
138
  backend: tmux
139
- display_backend: none
140
139
  session_name: teamspec-full-example
141
140
  auto_launch: true
142
141
  require_user_approval_before_launch: true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-agent/installer",
3
- "version": "0.5.98",
3
+ "version": "0.5.100",
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.98",
24
- "@team-agent/cli-darwin-x64": "0.5.98",
25
- "@team-agent/cli-linux-x64": "0.5.98"
23
+ "@team-agent/cli-darwin-arm64": "0.5.100",
24
+ "@team-agent/cli-darwin-x64": "0.5.100",
25
+ "@team-agent/cli-linux-x64": "0.5.100"
26
26
  },
27
27
  "scripts": {
28
28
  "postinstall": "node npm/bincheck.mjs",
@@ -59,11 +59,11 @@
59
59
  },
60
60
  "runtime": {
61
61
  "type": "object",
62
- "required": ["backend", "display_backend", "session_name", "auto_launch", "require_user_approval_before_launch", "max_active_agents", "startup_order"],
62
+ "required": ["backend", "session_name", "auto_launch", "require_user_approval_before_launch", "max_active_agents", "startup_order"],
63
63
  "additionalProperties": false,
64
64
  "properties": {
65
65
  "backend": { "enum": ["tmux", "pty"] },
66
- "display_backend": { "enum": ["none", "tmux_attach", "iterm", "ghostty", "ghostty_window", "ghostty_workspace"] },
66
+ "display_backend": {},
67
67
  "session_name": { "type": "string", "minLength": 1 },
68
68
  "auto_launch": { "type": "boolean" },
69
69
  "require_user_approval_before_launch": { "type": "boolean" },
@@ -17,7 +17,7 @@ team-agent --help
17
17
  team-agent doctor --help
18
18
  ```
19
19
 
20
- **Launch** from a tmux-addressable pane: `team-agent claude` or `team-agent codex`, then `team-agent quick-start .team/current`. Do not start a real team from a naked terminal. Existing tmux/Ghostty layouts are valid if `quick-start` runs from the leader pane.
20
+ **Launch** from a tmux-addressable pane: `team-agent claude` or `team-agent codex`, then `team-agent quick-start .team/current`. Do not start a real team from a naked terminal. Workers always run in independent background windows on the workspace-scoped tmux server.
21
21
 
22
22
  **Operate**
23
23
 
@@ -157,10 +157,10 @@ Resume/repair:
157
157
  team-agent restart "$WORKSPACE" --team "$TEAM" --json
158
158
  ```
159
159
 
160
- For a single worker where the leader has explicitly selected that worker:
160
+ A single-worker clean-context reset is not a resume operation. Only after the user explicitly approves discarding that worker's session, use:
161
161
 
162
162
  ```bash
163
- team-agent restart-agent "$AGENT_ID" --workspace "$WORKSPACE" --team "$TEAM" --json
163
+ team-agent reset-agent "$AGENT_ID" --workspace "$WORKSPACE" --team "$TEAM" --discard-session --json
164
164
  ```
165
165
 
166
166
  Validate:
@@ -43,7 +43,7 @@ team-agent codex
43
43
  team-agent claude
44
44
  ```
45
45
 
46
- Pass provider flags after the provider name, for example `team-agent codex --dangerously-bypass-approvals-and-sandbox`. Existing tmux layouts are valid too, including Finder/Ghostty launchers, as long as `team-agent quick-start` is invoked from the leader's current tmux pane. Do not start a real team from a naked terminal that Team Agent cannot address through tmux.
46
+ Pass provider flags after the provider name, for example `team-agent codex --dangerously-bypass-approvals-and-sandbox`. Run `team-agent quick-start` from the leader's current tmux pane. Do not start a real team from a naked terminal that Team Agent cannot address through tmux.
47
47
 
48
48
  **0.5.66:** leader `--dangerously-*` flags no longer inherit bypass to workers. Per-worker bypass is the role field `dangerously_skip_permissions` (see Permissions).
49
49
 
@@ -98,14 +98,7 @@ team-agent quick-start .team/current
98
98
 
99
99
  YAML lists must be block style. Use `tools:\n - fs_read`; do not use `tools: [fs_read, mcp_team]`.
100
100
 
101
- Display choices (set `display_backend:` in `TEAM.md` to opt in):
102
-
103
- - `none` (default): headless / no GUI window manager. The team runs entirely in the per-workspace tmux server; this is what the demo above uses.
104
- - `adaptive`: framework picks an available GUI layout for the local platform.
105
- - `ghostty_workspace`: one Ghostty window. Workers are shown in tmux tabs/windows, up to 3 side-by-side panes per tab. Four workers become `3 + 1`; eight become `3 + 3 + 2`.
106
- - `ghostty_window`: one Ghostty window per worker.
107
-
108
- **Omitting `display_backend` defaults to `none`** (changed in 0.3.4). Set `display_backend: adaptive` (or one of the explicit ghostty variants) in `TEAM.md` only when the user wants GUI windows.
101
+ Workers always run headlessly in independent windows on the per-workspace tmux server. No GUI display backend is configured in `TEAM.md`.
109
102
 
110
103
  ## Private Tmux Socket
111
104
 
@@ -267,7 +260,7 @@ Observed (all exit 0):
267
260
 
268
261
  ```text
269
262
  usage: team-agent restart [WORKSPACE] [--team TEAM] [--allow-fresh] [--session-converge-deadline SECONDS] [--json]
270
- usage: team-agent add-agent AGENT --role-file FILE [--force] [--workspace WORKSPACE] [--team TEAM] [--no-display] [--json]
263
+ usage: team-agent add-agent AGENT --role-file FILE [--force] [--workspace WORKSPACE] [--team TEAM] [--json]
271
264
  usage: team-agent shutdown [--workspace WORKSPACE] [--team TEAM] [--keep-logs] [--json]
272
265
  ```
273
266
 
@@ -112,12 +112,6 @@ For an existing worker that should restart with a blank provider context, the le
112
112
  team-agent reset-agent "$AGENT_ID" --workspace "$WORKSPACE" --team "$TEAM" --discard-session --json
113
113
  ```
114
114
 
115
- or the equivalent restart form:
116
-
117
- ```bash
118
- team-agent restart-agent "$AGENT_ID" --workspace "$WORKSPACE" --team "$TEAM" --discard-session --json
119
- ```
120
-
121
115
  Use this only when the user intentionally wants a clean context. For incident recovery, follow `recovery-runbook.md`, where context-preserving repair comes first.
122
116
 
123
117
  ## Framework Gaps To Track