@team-agent/installer 0.5.101 → 0.5.103

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 (49) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/emit.rs +2 -1
  4. package/crates/team-agent/src/cli/models.rs +92 -226
  5. package/crates/team-agent/src/cli/spec.rs +1 -1
  6. package/crates/team-agent/src/cli/tests/main_preserved.rs +0 -74
  7. package/crates/team-agent/src/compiler/tests.rs +20 -23
  8. package/crates/team-agent/src/compiler.rs +49 -65
  9. package/crates/team-agent/src/coordinator/tests/s3_bounded.rs +16 -48
  10. package/crates/team-agent/src/leader/start.rs +1 -14
  11. package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +37 -161
  12. package/crates/team-agent/src/lifecycle/launch/spawn.rs +1 -1
  13. package/crates/team-agent/src/lifecycle/restart/common.rs +1 -1
  14. package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +0 -28
  15. package/crates/team-agent/src/lifecycle/tests/pi_compiler_red.rs +11 -9
  16. package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +8 -401
  17. package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +2 -2
  18. package/crates/team-agent/src/lifecycle/worker_command_context.rs +22 -8
  19. package/crates/team-agent/src/mcp_server/helpers.rs +0 -16
  20. package/crates/team-agent/src/mcp_server/lifecycle_tools/mod.rs +2 -7
  21. package/crates/team-agent/src/mcp_server/lifecycle_tools/state_status.rs +1 -127
  22. package/crates/team-agent/src/mcp_server/mod.rs +7 -12
  23. package/crates/team-agent/src/mcp_server/tests/scoped.rs +1 -132
  24. package/crates/team-agent/src/mcp_server/tests/send.rs +1 -93
  25. package/crates/team-agent/src/mcp_server/tests/tools.rs +0 -61
  26. package/crates/team-agent/src/mcp_server/tests/wire.rs +6 -51
  27. package/crates/team-agent/src/mcp_server/tests.rs +4 -200
  28. package/crates/team-agent/src/mcp_server/tools.rs +5 -396
  29. package/crates/team-agent/src/mcp_server/types.rs +3 -36
  30. package/crates/team-agent/src/mcp_server/wire.rs +2 -223
  31. package/crates/team-agent/src/messaging/leader_receiver.rs +1 -1
  32. package/crates/team-agent/src/messaging/mod.rs +2 -2
  33. package/crates/team-agent/src/messaging/results.rs +11 -42
  34. package/crates/team-agent/src/messaging/scheduler.rs +2 -205
  35. package/crates/team-agent/src/messaging/tests/basic.rs +0 -31
  36. package/crates/team-agent/src/messaging/tests/main_preserved.rs +0 -73
  37. package/crates/team-agent/src/messaging/tests/runtime.rs +0 -26
  38. package/crates/team-agent/src/messaging/types.rs +0 -20
  39. package/crates/team-agent/src/model/spec.rs +14 -18
  40. package/crates/team-agent/src/provider/mod.rs +1 -0
  41. package/crates/team-agent/src/provider/model_catalog.rs +650 -0
  42. package/crates/team-agent/src/state/repository/tests.rs +1 -16
  43. package/crates/team-agent/src/state/repository.rs +1 -33
  44. package/package.json +4 -4
  45. package/skills/team-agent/SKILL.md +5 -5
  46. package/skills/team-agent/command-coverage.json +7 -0
  47. package/skills/team-agent/references/team-agent-operator.md +24 -116
  48. package/skills/team-agent/references/team-in-team.md +4 -19
  49. package/crates/team-agent/src/mcp_server/lifecycle_tools/agent_ops.rs +0 -484
@@ -140,23 +140,6 @@ fn activity_status_serde_byte_locked() {
140
140
  );
141
141
  }
142
142
 
143
- #[test]
144
- fn alert_type_serde_byte_locked() {
145
- // scheduler.py:38 _ALERT_TYPES set members.
146
- assert_eq!(
147
- serde_json::to_string(&AlertType::Stuck).unwrap(),
148
- "\"stuck\""
149
- );
150
- assert_eq!(
151
- serde_json::to_string(&AlertType::IdleFallback).unwrap(),
152
- "\"idle_fallback\""
153
- );
154
- assert_eq!(
155
- serde_json::to_string(&AlertType::CrossWorkerDeadlock).unwrap(),
156
- "\"cross_worker_deadlock\""
157
- );
158
- }
159
-
160
143
  #[test]
161
144
  fn check_status_serde_byte_locked() {
162
145
  assert_eq!(
@@ -266,20 +249,6 @@ fn provider_sdk_calls_is_zero_only_when_all_three_zero() {
266
249
  .is_zero());
267
250
  }
268
251
 
269
- #[test]
270
- fn alert_type_all_is_sorted_full_set() {
271
- // scheduler.py:269 sorted(_ALERT_TYPES) =
272
- // ['cross_worker_deadlock','idle_fallback','stuck'].
273
- assert_eq!(
274
- AlertType::all(),
275
- [
276
- AlertType::CrossWorkerDeadlock,
277
- AlertType::IdleFallback,
278
- AlertType::Stuck
279
- ]
280
- );
281
- }
282
-
283
252
  #[test]
284
253
  fn activity_status_idle_takeover_gate_uncertain_never_idle() {
285
254
  // THE IRON LAW (bug-071/077/085): only Idle passes; Uncertain/Working/Stuck
@@ -1,78 +1,5 @@
1
1
  use super::*;
2
2
 
3
- // ── F1 [P1 byte-shape] — stuck_cancel suppression snapshot.delivered_message_ids must use golden's
4
- // _DELIVERED_MESSAGE_STATUSES = {visible, submitted, delivered, acknowledged} (scheduler.py:27,376-383),
5
- // sorted. The Rust delivered_message_ids (scheduler.rs:243) used {injected, visible, submitted,
6
- // submitted_unverified, delivered} — the WRONG set (reviewer's explicit warning: don't copy the
7
- // activity.rs deadlock query set): it EXCLUDES 'acknowledged' and INCLUDES 'injected'/'submitted_unverified'.
8
- // (The snapshot also must carry BOTH assigned_task_ids AND delivered_message_ids — that structural half
9
- // is already present; this pins the STATUS SET.)
10
- #[test]
11
- fn stuck_cancel_snapshot_delivered_message_ids_uses_golden_status_set() {
12
- let ws = tmp_ws("f1_delivered");
13
- crate::state::persist::save_runtime_state(
14
- &ws,
15
- &serde_json::json!({
16
- "active_team_key": "teamX",
17
- "agents": {"w1": {"status": "running", "provider": "codex"}}
18
- }),
19
- )
20
- .unwrap();
21
- let store = crate::message_store::MessageStore::open(&ws).unwrap();
22
- // golden-delivered (must be IN delivered_message_ids): acknowledged + visible.
23
- let m_ack = store
24
- .create_message(None, "leader", "w1", "ack-me", None, true, Some("teamX"))
25
- .unwrap();
26
- store.mark(&m_ack, "delivered", None).unwrap();
27
- store.mark(&m_ack, "acknowledged", None).unwrap();
28
- let m_vis = store
29
- .create_message(None, "leader", "w1", "vis", None, true, Some("teamX"))
30
- .unwrap();
31
- store.mark(&m_vis, "visible", None).unwrap();
32
- // NOT golden-delivered (must be EXCLUDED): injected.
33
- let m_inj = store
34
- .create_message(None, "leader", "w1", "inj", None, true, Some("teamX"))
35
- .unwrap();
36
- store.mark(&m_inj, "injected", None).unwrap();
37
- drop(store);
38
- let _ = stuck_cancel(&ws, "w1", None, "leader").unwrap();
39
- let state = crate::state::persist::load_runtime_state(&ws).unwrap();
40
- let snapshot =
41
- &state["coordinator"]["suppressed_idle_alerts"]["teamX"]["w1"]["stuck"]["snapshot"];
42
- assert!(
43
- snapshot.get("assigned_task_ids").is_some(),
44
- "F1: snapshot must carry assigned_task_ids; got {snapshot}"
45
- );
46
- let delivered = snapshot
47
- .get("delivered_message_ids")
48
- .and_then(serde_json::Value::as_array)
49
- .map(|a| {
50
- a.iter()
51
- .filter_map(|v| v.as_str().map(str::to_string))
52
- .collect::<Vec<_>>()
53
- })
54
- .unwrap_or_else(|| panic!("F1: snapshot must carry delivered_message_ids; got {snapshot}"));
55
- assert!(
56
- delivered.contains(&m_ack),
57
- "F1: golden _DELIVERED_MESSAGE_STATUSES includes 'acknowledged' — the acknowledged message must be \
58
- in delivered_message_ids; the Rust set omits it. got {delivered:?}"
59
- );
60
- assert!(
61
- delivered.contains(&m_vis),
62
- "F1: 'visible' is delivered (golden); got {delivered:?}"
63
- );
64
- assert!(
65
- !delivered.contains(&m_inj),
66
- "F1: 'injected' is NOT in golden _DELIVERED_MESSAGE_STATUSES — it must be EXCLUDED; the Rust set \
67
- wrongly includes it. got {delivered:?}"
68
- );
69
- let mut sorted = delivered.clone();
70
- sorted.sort();
71
- assert_eq!(
72
- delivered, sorted,
73
- "F1: delivered_message_ids must be sorted (golden sorts); got {delivered:?}"
74
- );
75
- }
76
3
  // ── collect --result-file INGEST SEMANTIC (golden results.py:58-73) ──────────────────────────────
77
4
  // Golden `collect(result_file=…)` INDEPENDENTLY INGESTS a standalone result: a valid result_envelope_v1
78
5
  // is `store.add_result(envelope)`'d (results.py:73) regardless of any in-flight delivery, then the
@@ -979,32 +979,6 @@ fn requeue_delivery_exhausted_watchers_reopens_only_exhausted() {
979
979
  );
980
980
  }
981
981
 
982
- // ════════════════════════════════════════════════════════════════════════
983
- // GROUP P — stuck_cancel owner-gate + invalid alert type refusal.
984
- // scheduler.py:262-294.
985
- // ════════════════════════════════════════════════════════════════════════
986
-
987
- #[test]
988
- fn stuck_cancel_none_alert_type_expands_to_all() {
989
- // alert_type None == Python "all" → sorted(_ALERT_TYPES) expansion.
990
- let ws = tmp_ws("stuckcancel");
991
- let out = stuck_cancel(&ws, "w1", None, "leader").unwrap();
992
- // The suppression result must enumerate all three alert types.
993
- let types = out.get("alert_types").and_then(|v| v.as_array()).map(|a| {
994
- a.iter()
995
- .filter_map(|x| x.as_str().map(str::to_string))
996
- .collect::<Vec<_>>()
997
- });
998
- assert_eq!(
999
- types,
1000
- Some(vec![
1001
- "cross_worker_deadlock".to_string(),
1002
- "idle_fallback".to_string(),
1003
- "stuck".to_string()
1004
- ])
1005
- );
1006
- }
1007
-
1008
982
  // ════════════════════════════════════════════════════════════════════════
1009
983
  // GROUP Q — collect intake (results.py:45-167): valid result advances task,
1010
984
  // returns collected_results + delivered_messages + results counts shape.
@@ -219,26 +219,6 @@ impl WorkerRuntimeState {
219
219
  }
220
220
  }
221
221
 
222
- /// 告警类型 (card §49;`scheduler.py:38` `_ALERT_TYPES`)。`stuck_cancel` 还接 `all` (展开全集)。
223
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
224
- #[serde(rename_all = "snake_case")]
225
- pub enum AlertType {
226
- Stuck,
227
- IdleFallback,
228
- CrossWorkerDeadlock,
229
- }
230
-
231
- impl AlertType {
232
- /// `stuck_cancel(alert_type="all")` → `sorted(_ALERT_TYPES)` 全集 (`scheduler.py:269`)。
233
- pub fn all() -> [AlertType; 3] {
234
- [
235
- AlertType::CrossWorkerDeadlock,
236
- AlertType::IdleFallback,
237
- AlertType::Stuck,
238
- ]
239
- }
240
- }
241
-
242
222
  /// selftest check 状态 (card §47;`diagnose/comms.py`)。§19 必变 enum。
243
223
  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
244
224
  #[serde(rename_all = "snake_case")]
@@ -1135,19 +1135,10 @@ mod tests {
1135
1135
  );
1136
1136
  }
1137
1137
 
1138
- // 0.5.66 bypass 单源 §4.1:7 触发面共用同一 spec 校验层——compile_team 是它们的共同
1139
- // 必经点(quick-start/restart/add/fork 都调用),缺字段一律 fail-loud。此处验证
1140
- // compile 级校验确实 fail-loud,即各触发面(经 compile_team)都被覆盖。
1138
+ // 0.5.66 bypass 单源 §4.1:7 个生命周期入口共享编译后的 spec。
1139
+ // 缺失 role frontmatter 值时由编译器注入 true;此处锁定公共编译入口的默认结果。
1141
1140
  #[test]
1142
- fn test_all_7_triggers_run_field_check() {
1143
- // compile_team 是 7 触发面的 spec 校验必经点:
1144
- // quick-start(quick_start.rs:233 compile_team)
1145
- // restart(rebuild.rs:3245 rebuild_runtime_spec_from_roles → compile_team)
1146
- // add-agent(add_agent.rs:331 compile_role_agent)
1147
- // clone-agent(clone_agent.rs:62 → add_agent)
1148
- // fork-agent(fork_agent.rs:96 validate_spec)
1149
- // start-agent / reset-agent(操作已编译 spec,团队创建时经 compile_team 校验)
1150
- // 验证 compile_team 对缺字段的角色文档 fail-loud。
1141
+ fn test_all_7_triggers_use_compiled_default_bypass() {
1151
1142
  let team = std::env::temp_dir().join(format!(
1152
1143
  "ta-spec-7trigger-{}",
1153
1144
  std::process::id()
@@ -1159,17 +1150,22 @@ mod tests {
1159
1150
  "---\nname: t7\nobjective: 7 trigger.\nprovider: codex\n---\n\nteam.\n",
1160
1151
  )
1161
1152
  .unwrap();
1162
- // 角色文档故意缺 dangerously_skip_permissions
1153
+ // 角色文档故意省略该字段;纯文本默认必须写入 compiled spec。
1163
1154
  std::fs::write(
1164
1155
  team.join("agents").join("w.md"),
1165
1156
  "---\nname: w\nrole: Worker\nprovider: codex\ntools:\n - mcp_team\n---\n\nw.\n",
1166
1157
  )
1167
1158
  .unwrap();
1168
- let err = crate::compiler::compile_team(&team).unwrap_err().to_string();
1169
- assert!(
1170
- err.contains("missing front matter field dangerously_skip_permissions")
1171
- && err.contains("This field must be declared explicitly; it controls whether the agent launches with permission prompts bypassed."),
1172
- "compile_team must fail-loud on missing field (shared by all 7 triggers); got {err}"
1159
+ let spec = crate::compiler::compile_team(&team)
1160
+ .expect("compile_team must materialize the default bypass value");
1161
+ let agent = spec
1162
+ .get("agents")
1163
+ .and_then(Yaml::as_list)
1164
+ .and_then(|agents| agents.first())
1165
+ .expect("compiled spec has a worker");
1166
+ assert_eq!(
1167
+ agent.get("dangerously_skip_permissions"),
1168
+ Some(&Yaml::Bool(true))
1173
1169
  );
1174
1170
  let _ = std::fs::remove_dir_all(&team);
1175
1171
  }
@@ -51,6 +51,7 @@ pub(crate) mod adapters;
51
51
  pub mod approvals;
52
52
  pub mod classify;
53
53
  pub mod faults;
54
+ pub mod model_catalog;
54
55
  pub mod session;
55
56
  pub mod session_scan;
56
57
  pub mod startup_prompt;