@team-agent/installer 0.5.97 → 0.5.99

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 (62) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/adapters.rs +0 -64
  4. package/crates/team-agent/src/cli/diagnose.rs +0 -16
  5. package/crates/team-agent/src/cli/emit.rs +15 -42
  6. package/crates/team-agent/src/cli/mod.rs +130 -31
  7. package/crates/team-agent/src/cli/spec.rs +7 -10
  8. package/crates/team-agent/src/cli/tests/main_preserved.rs +0 -1
  9. package/crates/team-agent/src/cli/tests/missing_subcommands.rs +0 -1
  10. package/crates/team-agent/src/cli/tests/mod.rs +0 -1
  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/types.rs +0 -14
  14. package/crates/team-agent/src/compiler/tests.rs +5 -8
  15. package/crates/team-agent/src/compiler.rs +6 -14
  16. package/crates/team-agent/src/lifecycle/launch/add_agent.rs +1 -1
  17. package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +1 -1
  18. package/crates/team-agent/src/lifecycle/launch/agent_state.rs +5 -25
  19. package/crates/team-agent/src/lifecycle/launch/identity.rs +2 -18
  20. package/crates/team-agent/src/lifecycle/launch/layout.rs +7 -29
  21. package/crates/team-agent/src/lifecycle/launch/leader_context.rs +1 -1
  22. package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +1 -1
  23. package/crates/team-agent/src/lifecycle/launch/ownership.rs +1 -1
  24. package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +7 -7
  25. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +12 -49
  26. package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +3 -9
  27. package/crates/team-agent/src/lifecycle/launch/readiness.rs +1 -1
  28. package/crates/team-agent/src/lifecycle/launch/spawn.rs +2 -61
  29. package/crates/team-agent/src/lifecycle/launch/spec_state.rs +2 -15
  30. package/crates/team-agent/src/lifecycle/launch/state_projection.rs +3 -7
  31. package/crates/team-agent/src/lifecycle/launch/worker_env.rs +1 -1
  32. package/crates/team-agent/src/lifecycle/launch.rs +3 -4
  33. package/crates/team-agent/src/lifecycle/mod.rs +0 -8
  34. package/crates/team-agent/src/lifecycle/restart/agent.rs +62 -8
  35. package/crates/team-agent/src/lifecycle/restart/common.rs +0 -32
  36. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +0 -9
  37. package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +1 -2
  38. package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +0 -1
  39. package/crates/team-agent/src/lifecycle/tests/core.rs +0 -213
  40. package/crates/team-agent/src/lifecycle/tests/issue238_codex_effort_contract.rs +96 -0
  41. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +1 -0
  42. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +31 -77
  43. package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +2 -2
  44. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +4 -8
  45. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +7 -7
  46. package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +1 -1
  47. package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +3 -4
  48. package/crates/team-agent/src/lifecycle/tests.rs +1 -2
  49. package/crates/team-agent/src/lifecycle/types.rs +3 -133
  50. package/crates/team-agent/src/model/enums.rs +21 -71
  51. package/crates/team-agent/src/model/spec.rs +5 -20
  52. package/crates/team-agent/src/provider/adapters/codex.rs +2 -2
  53. package/crates/team-agent/src/provider/types.rs +6 -5
  54. package/examples/team.spec.yaml +0 -1
  55. package/package.json +4 -4
  56. package/schemas/team.schema.json +2 -2
  57. package/skills/team-agent/SKILL.md +1 -1
  58. package/skills/team-agent/references/team-agent-operator.md +23 -38
  59. package/crates/team-agent/src/cli/tests/compile.rs +0 -192
  60. package/crates/team-agent/src/lifecycle/display.rs +0 -550
  61. package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +0 -884
  62. package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +0 -481
@@ -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)]
@@ -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()];
@@ -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
 
@@ -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.97",
3
+ "version": "0.5.99",
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.97",
24
- "@team-agent/cli-darwin-x64": "0.5.97",
25
- "@team-agent/cli-linux-x64": "0.5.97"
23
+ "@team-agent/cli-darwin-arm64": "0.5.99",
24
+ "@team-agent/cli-darwin-x64": "0.5.99",
25
+ "@team-agent/cli-linux-x64": "0.5.99"
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