@team-agent/installer 0.5.113 → 0.5.115

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 (52) hide show
  1. package/Cargo.lock +252 -84
  2. package/Cargo.toml +3 -1
  3. package/crates/team-agent/Cargo.toml +3 -0
  4. package/crates/team-agent/src/cli/adapters.rs +28 -15
  5. package/crates/team-agent/src/cli/diagnose.rs +36 -13
  6. package/crates/team-agent/src/cli/emit.rs +57 -22
  7. package/crates/team-agent/src/cli/leader.rs +16 -0
  8. package/crates/team-agent/src/cli/leader_prompt.rs +261 -0
  9. package/crates/team-agent/src/cli/mod.rs +157 -8
  10. package/crates/team-agent/src/cli/models.rs +119 -18
  11. package/crates/team-agent/src/cli/spec.rs +7 -1
  12. package/crates/team-agent/src/cli/status_port/brief.rs +268 -101
  13. package/crates/team-agent/src/cli/tests/base.rs +88 -0
  14. package/crates/team-agent/src/cli/tests/status_send.rs +2 -0
  15. package/crates/team-agent/src/compiler.rs +66 -18
  16. package/crates/team-agent/src/contract_runtime/backend.rs +959 -0
  17. package/crates/team-agent/src/contract_runtime/commands.rs +245 -0
  18. package/crates/team-agent/src/contract_runtime/config.rs +340 -0
  19. package/crates/team-agent/src/contract_runtime/config_tests.rs +56 -0
  20. package/crates/team-agent/src/contract_runtime/discovery.rs +383 -0
  21. package/crates/team-agent/src/contract_runtime/forward.rs +229 -0
  22. package/crates/team-agent/src/contract_runtime/framework.rs +294 -0
  23. package/crates/team-agent/src/contract_runtime/mcp.rs +396 -0
  24. package/crates/team-agent/src/contract_runtime/mod.rs +16 -0
  25. package/crates/team-agent/src/contract_runtime/prompt.rs +216 -0
  26. package/crates/team-agent/src/contract_runtime/pump.rs +269 -0
  27. package/crates/team-agent/src/contract_runtime/registry.rs +197 -0
  28. package/crates/team-agent/src/contract_runtime/workspace.rs +160 -0
  29. package/crates/team-agent/src/coordinator/tick.rs +26 -8
  30. package/crates/team-agent/src/leader/mod.rs +1 -0
  31. package/crates/team-agent/src/leader/prompt.rs +906 -0
  32. package/crates/team-agent/src/leader/start.rs +353 -21
  33. package/crates/team-agent/src/leader/tests/mod.rs +2 -0
  34. package/crates/team-agent/src/leader/tests/prompt_contract.rs +268 -0
  35. package/crates/team-agent/src/leader/types.rs +6 -0
  36. package/crates/team-agent/src/lib.rs +4 -0
  37. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +571 -389
  38. package/crates/team-agent/src/lifecycle/launch/spawn.rs +38 -9
  39. package/crates/team-agent/src/lifecycle/launch/state_projection.rs +15 -0
  40. package/crates/team-agent/src/lifecycle/launch.rs +45 -28
  41. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +23 -1
  42. package/crates/team-agent/src/lifecycle/restart/selection.rs +34 -0
  43. package/crates/team-agent/src/lifecycle/role_config.rs +17 -1
  44. package/crates/team-agent/src/lifecycle/types.rs +4 -1
  45. package/crates/team-agent/src/lifecycle/worker_command_context.rs +37 -27
  46. package/crates/team-agent/src/main.rs +6 -0
  47. package/crates/team-agent/src/messaging/delivery.rs +50 -1
  48. package/crates/team-agent/src/messaging/send.rs +10 -0
  49. package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +131 -0
  50. package/crates/team-agent/src/model/spec.rs +24 -12
  51. package/crates/team-agent/src/state/persist.rs +73 -0
  52. package/package.json +4 -4
@@ -22,6 +22,10 @@ enum CatalogFormat {
22
22
  }
23
23
 
24
24
  pub fn cmd_models(args: &ModelsArgs) -> Result<CmdResult, CliError> {
25
+ #[cfg(unix)]
26
+ if crate::contract_runtime::registry::descriptor(&args.provider).is_some() {
27
+ return crate::contract_runtime::discovery::models(args);
28
+ }
25
29
  let records = match crate::provider::model_catalog::discover_model_catalog(&args.provider) {
26
30
  Ok(records) => records,
27
31
  Err(error) => {
@@ -36,7 +40,12 @@ pub fn cmd_models(args: &ModelsArgs) -> Result<CmdResult, CliError> {
36
40
  fn render_catalog(args: &ModelsArgs, all: Vec<ModelRecord>) -> Result<CmdResult, CliError> {
37
41
  let visible = args.search.as_deref().map_or_else(
38
42
  || all.clone(),
39
- |search| all.iter().filter(|model| crate::provider::model_catalog::model_matches(model, search)).cloned().collect(),
43
+ |search| {
44
+ all.iter()
45
+ .filter(|model| crate::provider::model_catalog::model_matches(model, search))
46
+ .cloned()
47
+ .collect()
48
+ },
40
49
  );
41
50
  let current = if args.provider == "pi" {
42
51
  current_role_model(&all.iter().map(|model| model.id.clone()).collect::<Vec<_>>())
@@ -66,14 +75,31 @@ fn render_catalog(args: &ModelsArgs, all: Vec<ModelRecord>) -> Result<CmdResult,
66
75
  preserve_json_order: true,
67
76
  })
68
77
  } else {
69
- let mut lines = vec![format!("models.v1 | {provider} models (copyable model_id):")];
78
+ let mut lines = vec![format!(
79
+ "models.v1 | {provider} models (copyable model_id):"
80
+ )];
70
81
  lines.push("PROVIDER VENDOR MODEL_ID DISPLAY_NAME CURRENT DEFAULT".to_string());
71
- lines.extend(visible.iter().map(|model| format!(
72
- "{} {} {} {} {} {}", model.provider, model.vendor, model.id, model.display_name,
73
- if args.provider == "pi" { (current.as_deref() == Some(model.id.as_str())).to_string() } else { "—".to_string() },
74
- model.default.map_or_else(|| "—".to_string(), |value| value.to_string()),
75
- )));
76
- lines.push(format!("auth: ok (catalog_visibility); {} model(s)", visible.len()));
82
+ lines.extend(visible.iter().map(|model| {
83
+ format!(
84
+ "{} {} {} {} {} {}",
85
+ model.provider,
86
+ model.vendor,
87
+ model.id,
88
+ model.display_name,
89
+ if args.provider == "pi" {
90
+ (current.as_deref() == Some(model.id.as_str())).to_string()
91
+ } else {
92
+ "—".to_string()
93
+ },
94
+ model
95
+ .default
96
+ .map_or_else(|| "—".to_string(), |value| value.to_string()),
97
+ )
98
+ }));
99
+ lines.push(format!(
100
+ "auth: ok (catalog_visibility); {} model(s)",
101
+ visible.len()
102
+ ));
77
103
  if visible.is_empty() {
78
104
  lines.push("No models matched --search/query; rerun without a search to list the full catalog.".to_string());
79
105
  }
@@ -83,12 +109,23 @@ fn render_catalog(args: &ModelsArgs, all: Vec<ModelRecord>) -> Result<CmdResult,
83
109
 
84
110
  /// Existing injectable Pi boundary retained for deterministic command/timeout tests.
85
111
  #[cfg(test)]
86
- fn cmd_models_with(args: &ModelsArgs, program: &Path, timeout: Duration, max_bytes: u64) -> Result<CmdResult, CliError> {
112
+ fn cmd_models_with(
113
+ args: &ModelsArgs,
114
+ program: &Path,
115
+ timeout: Duration,
116
+ max_bytes: u64,
117
+ ) -> Result<CmdResult, CliError> {
87
118
  cmd_models_with_format(args, program, CatalogFormat::Pi, timeout, max_bytes)
88
119
  }
89
120
 
90
121
  #[cfg(test)]
91
- fn cmd_models_with_format(args: &ModelsArgs, program: &Path, format: CatalogFormat, timeout: Duration, max_bytes: u64) -> Result<CmdResult, CliError> {
122
+ fn cmd_models_with_format(
123
+ args: &ModelsArgs,
124
+ program: &Path,
125
+ format: CatalogFormat,
126
+ timeout: Duration,
127
+ max_bytes: u64,
128
+ ) -> Result<CmdResult, CliError> {
92
129
  let bytes = match run_catalog(program, timeout, max_bytes) {
93
130
  Ok(bytes) => bytes,
94
131
  Err(message) => return Ok(failure(args, &message)),
@@ -102,7 +139,10 @@ fn cmd_models_with_format(args: &ModelsArgs, program: &Path, format: CatalogForm
102
139
 
103
140
  #[cfg(test)]
104
141
  fn parse_catalog(bytes: &[u8], format: CatalogFormat) -> Result<Vec<ModelRecord>, String> {
105
- let provider = match format { CatalogFormat::Pi => "pi", CatalogFormat::CursorAgent => "cursor_agent" };
142
+ let provider = match format {
143
+ CatalogFormat::Pi => "pi",
144
+ CatalogFormat::CursorAgent => "cursor_agent",
145
+ };
106
146
  let result = match format {
107
147
  CatalogFormat::Pi => crate::provider::model_catalog::parse_pi_catalog(bytes),
108
148
  CatalogFormat::CursorAgent => crate::provider::model_catalog::parse_cursor_catalog(bytes),
@@ -124,7 +164,12 @@ fn model_matches(model: &ModelRecord, search: &str) -> bool {
124
164
  #[cfg(test)]
125
165
  fn current_model_for(format: CatalogFormat, models: &[ModelRecord]) -> Option<String> {
126
166
  match format {
127
- CatalogFormat::Pi => current_role_model(&models.iter().map(|model| model.id.clone()).collect::<Vec<_>>()),
167
+ CatalogFormat::Pi => current_role_model(
168
+ &models
169
+ .iter()
170
+ .map(|model| model.id.clone())
171
+ .collect::<Vec<_>>(),
172
+ ),
128
173
  CatalogFormat::CursorAgent => None,
129
174
  }
130
175
  }
@@ -148,8 +193,14 @@ fn failure(args: &ModelsArgs, message: &str) -> CmdResult {
148
193
  fn failure_with_action(args: &ModelsArgs, message: &str, action: &str) -> CmdResult {
149
194
  let value = json!({ "schema_version": "models.v1", "ok": false, "provider": args.provider, "auth": "not_ready", "auth_basis": "catalog_visibility", "models": Value::Array(Vec::new()), "current_role_model": Value::Null, "error": message, "action": action });
150
195
  if args.json {
151
- let text = serde_json::to_string_pretty(&value).unwrap_or_else(|_| "{\"schema_version\":\"models.v1\",\"ok\":false}".to_string());
152
- CmdResult { output: CmdOutput::Human(text), exit: ExitCode::Error, as_json: false, preserve_json_order: true }
196
+ let text = serde_json::to_string_pretty(&value)
197
+ .unwrap_or_else(|_| "{\"schema_version\":\"models.v1\",\"ok\":false}".to_string());
198
+ CmdResult {
199
+ output: CmdOutput::Human(text),
200
+ exit: ExitCode::Error,
201
+ as_json: false,
202
+ preserve_json_order: true,
203
+ }
153
204
  } else {
154
205
  CmdResult { output: CmdOutput::Human(format!("models.v1 | error: {message}\naction: {action}\nauth: not_ready (catalog_visibility)")), exit: ExitCode::Error, as_json: false, preserve_json_order: false }
155
206
  }
@@ -387,6 +438,57 @@ mod tests {
387
438
  assert_eq!(models[0]["default"], true);
388
439
  }
389
440
 
441
+ #[cfg(unix)]
442
+ #[test]
443
+ fn cursor_contract_catalog_uses_public_launcher_metadata_then_exact_ids() {
444
+ let program = fixture_program("cursor-agent", r#"
445
+ test "$#" = 1 || exit 9
446
+ case "$1" in
447
+ --version) printf '%s\n' '2026.10.01-a1b2c3' ;;
448
+ --list-models) exec /bin/cat "$TEAM_AGENT_MODELS_FIXTURE" ;;
449
+ *) exit 9 ;;
450
+ esac"#);
451
+ let mut cursor = CliFixture::new(program);
452
+ let response = cursor.program.with_extension("stdout");
453
+ std::fs::write(&response, include_bytes!("../provider/testdata/cursor-list-models-native.stdout")).unwrap();
454
+ cursor.response = Some(response);
455
+ let output = run_public_models_cli(&cursor.program, cursor.response.as_deref(),
456
+ &["models", "--provider", "cursor", "--search", "gpt-5.6-luna-xhigh", "--json"]);
457
+ let text = public_cli_text(&output);
458
+ let calls = std::fs::read_to_string(cursor.program.with_extension("count")).unwrap();
459
+ assert!(output.status.success(), "{text}");
460
+ assert_eq!(calls, "1:--version\n1:--list-models\n");
461
+ let value: Value = serde_json::from_str(text.trim()).unwrap();
462
+ assert_eq!(value["provider"], "cursor");
463
+ assert_eq!(value["auth"], "unknown");
464
+ assert_eq!(value["source"]["schema"], "cursor-list-models-text-v1");
465
+ assert_eq!(value["source"]["identity_scope"], "catalog_only");
466
+ assert!(value["models"].as_array().unwrap().iter().any(|row| row["model_id"] == "gpt-5.6-luna-xhigh"));
467
+ assert!(value["models"].as_array().unwrap().iter().all(|row| row["role_model"] == row["model_id"]));
468
+ assert!(value["current_role_model"].is_null());
469
+ }
470
+
471
+ #[cfg(unix)]
472
+ #[test]
473
+ fn cursor_contract_bad_version_has_no_legacy_entrypoint_fallback() {
474
+ use std::os::unix::fs::PermissionsExt;
475
+ let cursor = CliFixture::new(fixture_program("cursor-agent", "printf '%s\\n' 'Cursor release unknown'"));
476
+ let legacy = cursor.program.parent().unwrap().join("agent");
477
+ std::fs::write(&legacy, "#!/bin/sh\nprintf 'called' > \"$0.called\"\nexit 9\n").unwrap();
478
+ std::fs::set_permissions(&legacy, std::fs::Permissions::from_mode(0o700)).unwrap();
479
+ let output = run_public_models_cli(&cursor.program, None,
480
+ &["models", "--provider", "cursor", "--json"]);
481
+ let text = public_cli_text(&output);
482
+ assert!(!output.status.success(), "{text}");
483
+ assert_eq!(std::fs::read_to_string(cursor.program.with_extension("count")).unwrap(), "1:--version\n");
484
+ assert!(!legacy.with_extension("called").exists());
485
+ let value: Value = serde_json::from_str(text.trim()).unwrap();
486
+ assert_eq!(value["provider"], "cursor");
487
+ assert_eq!(value["ok"], false);
488
+ assert_eq!(value["models"], json!([]));
489
+ assert!(value["error"].as_str().unwrap().contains("Cursor release unknown"));
490
+ }
491
+
390
492
  #[cfg(unix)]
391
493
  #[test]
392
494
  fn grok_public_cli_uses_native_catalog_and_keeps_shared_projection() {
@@ -1271,10 +1373,9 @@ mod tests {
1271
1373
  ),
1272
1374
  ExitCode::Error
1273
1375
  );
1274
- assert_eq!(
1275
- crate::cli::spec::command_spec("models").unwrap().usage,
1276
- "team-agent models [--provider pi|cursor_agent|codex|claude|claude_code|grok] [QUERY|--search TEXT] [--json]"
1277
- );
1376
+ let usage = "team-agent models [--provider pi|cursor|cursor_agent|codex|claude|claude_code|grok|kiro] [QUERY|--search TEXT] [--json]";
1377
+ assert_eq!(crate::cli::spec::command_spec("models").unwrap().usage, usage);
1378
+ assert!(crate::cli::emit::command_help(Some("models")).contains(usage));
1278
1379
  }
1279
1380
 
1280
1381
  #[test]
@@ -36,6 +36,7 @@ pub(crate) enum DispatchKind {
36
36
  Send,
37
37
  Status,
38
38
  Models,
39
+ KiroLeader,
39
40
  Inbox,
40
41
  Restart,
41
42
  Shutdown,
@@ -50,6 +51,7 @@ pub(crate) enum DispatchKind {
50
51
  Doctor,
51
52
  Approvals,
52
53
  Route,
54
+ LeaderPrompt,
53
55
  Profile,
54
56
  InstallSkill,
55
57
  ClaimLeader,
@@ -61,6 +63,7 @@ pub(crate) const ALL_DISPATCH_KINDS: &[DispatchKind] = &[
61
63
  DispatchKind::Send,
62
64
  DispatchKind::Status,
63
65
  DispatchKind::Models,
66
+ DispatchKind::KiroLeader,
64
67
  DispatchKind::Inbox,
65
68
  DispatchKind::Restart,
66
69
  DispatchKind::Shutdown,
@@ -75,6 +78,7 @@ pub(crate) const ALL_DISPATCH_KINDS: &[DispatchKind] = &[
75
78
  DispatchKind::Doctor,
76
79
  DispatchKind::Approvals,
77
80
  DispatchKind::Route,
81
+ DispatchKind::LeaderPrompt,
78
82
  DispatchKind::Profile,
79
83
  DispatchKind::InstallSkill,
80
84
  DispatchKind::ClaimLeader,
@@ -109,7 +113,7 @@ pub(crate) const COMMAND_SPECS: &[CommandSpec] = &[
109
113
  CommandSpec { name: "quick-start", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::Dispatch(DispatchKind::QuickStart), summary: "Create a team from role files; use restart for an initialized team", usage: "team-agent quick-start [TEAMDIR] [--workspace WORKSPACE] [--team TEAM] [--name NAME] [--team-id TEAM] [--yes] [--backend tmux|conpty] [--json] [--detail]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, sunset: None, action: None, governance: None },
110
114
  CommandSpec { name: "send", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::Dispatch(DispatchKind::Send), summary: "Send a task to a specified agent", usage: "team-agent send <agent> MESSAGE... [--workspace WORKSPACE] [--team TEAM] [--mailbox] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, sunset: Some("a future compatibility release"), action: Some("Use team-agent send <agent> 'task message'; select scope with --workspace and --team"), governance: None },
111
115
  CommandSpec { name: "status", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::Dispatch(DispatchKind::Status), summary: "Check agent status without reading conversation content", usage: "team-agent status [<agent>] [--workspace WORKSPACE] [--team TEAM] [--json] [--summary|--detail]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
112
- CommandSpec { name: "models", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::Dispatch(DispatchKind::Models), summary: "Discover model names supported by the native provider", usage: "team-agent models [--provider pi|cursor_agent|codex|claude|claude_code|grok] [QUERY|--search TEXT] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
116
+ CommandSpec { name: "models", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::Dispatch(DispatchKind::Models), summary: "Discover model names supported by the native provider", usage: "team-agent models [--provider pi|cursor|cursor_agent|codex|claude|claude_code|grok|kiro] [QUERY|--search TEXT] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
113
117
  CommandSpec { name: "inbox", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::Dispatch(DispatchKind::Inbox), summary: "Read agent replies", usage: "team-agent inbox <agent> [-n N|--limit N] [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
114
118
  CommandSpec { name: "restart", tier: CommandTier::Core, category: CommandCategory::TeamLifecycle, kind: CommandKind::Dispatch(DispatchKind::Restart), summary: "Restart an existing team using saved sessions when available", usage: "team-agent restart [WORKSPACE] [--team TEAM] [--allow-fresh] [--session-converge-deadline SECONDS] [--json] [--detail]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, sunset: None, action: None, governance: None },
115
119
  CommandSpec { name: "shutdown", tier: CommandTier::Core, category: CommandCategory::TeamLifecycle, kind: CommandKind::Dispatch(DispatchKind::Shutdown), summary: "Shut down the selected team and report residual resources", usage: "team-agent shutdown [--workspace WORKSPACE] [--team TEAM] [--keep-logs] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
@@ -124,11 +128,13 @@ pub(crate) const COMMAND_SPECS: &[CommandSpec] = &[
124
128
  CommandSpec { name: "doctor", tier: CommandTier::Core, category: CommandCategory::Observe, kind: CommandKind::Dispatch(DispatchKind::Doctor), summary: "Diagnose a team and suggest recovery; read-only by default", usage: "team-agent doctor [SPEC] [--workspace WORKSPACE] [--team TEAM] [--comms] [--gate orphans|comms] [--fix] [--fix-schema] [--cleanup-orphans] [--confirm] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
125
129
  CommandSpec { name: "approvals", tier: CommandTier::Core, category: CommandCategory::Observe, kind: CommandKind::Dispatch(DispatchKind::Approvals), summary: "List pending agent approvals", usage: "team-agent approvals [<agent>] [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
126
130
  CommandSpec { name: "route", tier: CommandTier::Core, category: CommandCategory::Setup, kind: CommandKind::Dispatch(DispatchKind::Route), summary: "Configure additional provider launch arguments", usage: "team-agent route [status|enable|disable|show [TOOL]|set TOOL -- ARG...|add TOOL -- ARG...|clear TOOL] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
131
+ CommandSpec { name: "leader-prompt", tier: CommandTier::Core, category: CommandCategory::Setup, kind: CommandKind::Dispatch(DispatchKind::LeaderPrompt), summary: "Persist supplemental instructions for new Leaders only", usage: "team-agent leader-prompt [show|set|append|clear] [--json] [--file PATH | -- TEXT]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
127
132
  CommandSpec { name: "profile", tier: CommandTier::Core, category: CommandCategory::Setup, kind: CommandKind::Dispatch(DispatchKind::Profile), summary: "Manage authentication and proxy profiles", usage: "team-agent profile init|doctor|show NAME [--workspace WORKSPACE] [--team TEAM] [--auth-mode MODE] [--proxy-mode direct|inherit] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
128
133
  CommandSpec { name: "install-skill", tier: CommandTier::Core, category: CommandCategory::Setup, kind: CommandKind::Dispatch(DispatchKind::InstallSkill), summary: "Optionally install an existing public operation skill", usage: "team-agent install-skill (--source DIR|--uninstall) [--target codex|claude|copilot|all] [--dest DIR] [--dry-run] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
129
134
  CommandSpec { name: "claim-leader", tier: CommandTier::Guided, category: CommandCategory::GuidedRecovery, kind: CommandKind::Dispatch(DispatchKind::ClaimLeader), summary: "Register the current terminal as leader only when diagnosis recommends it", usage: "team-agent claim-leader [--workspace WORKSPACE] [--team TEAM] [--confirm] [--json] [--detail]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
130
135
  CommandSpec { name: "takeover", tier: CommandTier::Guided, category: CommandCategory::GuidedRecovery, kind: CommandKind::Dispatch(DispatchKind::Takeover), summary: "Take over an existing team only after diagnosis and confirmation", usage: "team-agent takeover [--workspace WORKSPACE] [--team TEAM] [--confirm] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
131
136
  CommandSpec { name: "attach-leader", tier: CommandTier::Guided, category: CommandCategory::GuidedRecovery, kind: CommandKind::Dispatch(DispatchKind::AttachLeader), summary: "Attach a verified leader terminal only when diagnosis recommends it", usage: "team-agent attach-leader [--workspace WORKSPACE] [--team TEAM] --pane PANE --provider TOOL [--confirm] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
137
+ CommandSpec { name: "kiro", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::Dispatch(DispatchKind::KiroLeader), summary: "Check Kiro leader launch admission (currently refused)", usage: "team-agent kiro [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, sunset: None, action: None, governance: None },
132
138
  CommandSpec { name: "pi", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::LeaderPassthrough { provider: "pi" }, summary: "Open a leader session with Pi", usage: "team-agent pi [--attach-existing] [--confirm] [--attach-session SESSION] [--external-leader] [--allow-nested-attach] [--json] [-- TOOL_ARGS...]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, sunset: None, action: None, governance: None },
133
139
  CommandSpec { name: "codex", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::LeaderPassthrough { provider: "codex" }, summary: "Open a leader session with Codex", usage: "team-agent codex [--attach-existing] [--confirm] [--attach-session SESSION] [--external-leader] [--allow-nested-attach] [--json] [-- TOOL_ARGS...]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, sunset: None, action: None, governance: None },
134
140
  CommandSpec { name: "claude", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::LeaderPassthrough { provider: "claude" }, summary: "Open a leader session with Claude Code", usage: "team-agent claude [--attach-existing] [--confirm] [--attach-session SESSION] [--external-leader] [--allow-nested-attach] [--json] [-- TOOL_ARGS...]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, sunset: None, action: None, governance: None },