@team-agent/installer 0.5.65 → 0.5.68

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 (208) hide show
  1. package/Cargo.lock +8 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/Cargo.toml +6 -0
  4. package/crates/team-agent/src/cli/adapters.rs +6 -1
  5. package/crates/team-agent/src/cli/diagnose.rs +82 -0
  6. package/crates/team-agent/src/cli/emit.rs +3 -3
  7. package/crates/team-agent/src/cli/grok_slot.rs +299 -0
  8. package/crates/team-agent/src/cli/leader.rs +21 -7
  9. package/crates/team-agent/src/cli/leaders.rs +125 -1
  10. package/crates/team-agent/src/cli/mod.rs +20 -0
  11. package/crates/team-agent/src/cli/send/presentation.rs +7 -1
  12. package/crates/team-agent/src/cli/spec.rs +2 -0
  13. package/crates/team-agent/src/cli/status_port/compact.rs +28 -0
  14. package/crates/team-agent/src/cli/status_port/snapshot.rs +25 -1
  15. package/crates/team-agent/src/cli/tests/base.rs +26 -3
  16. package/crates/team-agent/src/cli/tests/compile.rs +1 -1
  17. package/crates/team-agent/src/cli/tests/missing_subcommands.rs +129 -19
  18. package/crates/team-agent/src/cli/tests/mod.rs +2 -2
  19. package/crates/team-agent/src/cli/tests/run_delegation.rs +1 -1
  20. package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +387 -6
  21. package/crates/team-agent/src/cli/tests/status_send.rs +79 -10
  22. package/crates/team-agent/src/cli/tests/verb_validate.rs +1 -1
  23. package/crates/team-agent/src/communication_mode/mod.rs +6 -4
  24. package/crates/team-agent/src/compiler/tests.rs +23 -20
  25. package/crates/team-agent/src/compiler.rs +84 -5
  26. package/crates/team-agent/src/conpty/backend.rs +16 -0
  27. package/crates/team-agent/src/coordinator/backoff.rs +55 -0
  28. package/crates/team-agent/src/coordinator/conpty_shim.rs +82 -0
  29. package/crates/team-agent/src/coordinator/health.rs +173 -0
  30. package/crates/team-agent/src/coordinator/mod.rs +31 -0
  31. package/crates/team-agent/src/coordinator/orphan.rs +31 -0
  32. package/crates/team-agent/src/coordinator/runtime_detectors.rs +30 -0
  33. package/crates/team-agent/src/coordinator/runtime_observation.rs +25 -0
  34. package/crates/team-agent/src/coordinator/steps/abnormal.rs +59 -0
  35. package/crates/team-agent/src/coordinator/steps/delivery.rs +10 -0
  36. package/crates/team-agent/src/coordinator/steps/health_sync.rs +10 -0
  37. package/crates/team-agent/src/coordinator/steps/mod.rs +22 -0
  38. package/crates/team-agent/src/coordinator/steps/persist.rs +10 -0
  39. package/crates/team-agent/src/coordinator/steps/runtime_prompts.rs +10 -0
  40. package/crates/team-agent/src/coordinator/steps/session_gate.rs +10 -0
  41. package/crates/team-agent/src/coordinator/tick.rs +133 -22
  42. package/crates/team-agent/src/coordinator/types.rs +49 -0
  43. package/crates/team-agent/src/db/message_store.rs +39 -5
  44. package/crates/team-agent/src/layout/worker_env.rs +20 -3
  45. package/crates/team-agent/src/layout/worker_window_helpers.rs +2 -0
  46. package/crates/team-agent/src/leader/provider_attribution.rs +53 -0
  47. package/crates/team-agent/src/leader/registry.rs +65 -0
  48. package/crates/team-agent/src/leader/start.rs +1080 -58
  49. package/crates/team-agent/src/leader/tests/team_in_team_state_scope_red.rs +1 -1
  50. package/crates/team-agent/src/lifecycle/display.rs +56 -0
  51. package/crates/team-agent/src/lifecycle/helpers.rs +57 -0
  52. package/crates/team-agent/src/lifecycle/launch/add_agent.rs +332 -14
  53. package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +69 -2
  54. package/crates/team-agent/src/lifecycle/launch/agent_state.rs +196 -2
  55. package/crates/team-agent/src/lifecycle/launch/clone_agent.rs +101 -11
  56. package/crates/team-agent/src/lifecycle/launch/cursor_create_chat.rs +229 -0
  57. package/crates/team-agent/src/lifecycle/launch/cursor_mcp.rs +332 -0
  58. package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +204 -457
  59. package/crates/team-agent/src/lifecycle/launch/fork_entry.rs +24 -0
  60. package/crates/team-agent/src/lifecycle/launch/grok_per_seat.rs +260 -0
  61. package/crates/team-agent/src/lifecycle/launch/identity.rs +146 -0
  62. package/crates/team-agent/src/lifecycle/launch/layout.rs +60 -0
  63. package/crates/team-agent/src/lifecycle/launch/leader_context.rs +112 -0
  64. package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +530 -0
  65. package/crates/team-agent/src/lifecycle/launch/ownership.rs +40 -0
  66. package/crates/team-agent/src/lifecycle/launch/plan.rs +31 -0
  67. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +66 -0
  68. package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +78 -0
  69. package/crates/team-agent/src/lifecycle/launch/readiness.rs +85 -38
  70. package/crates/team-agent/src/lifecycle/launch/role_source.rs +44 -44
  71. package/crates/team-agent/src/lifecycle/launch/spawn.rs +101 -4
  72. package/crates/team-agent/src/lifecycle/launch/spec_state.rs +244 -48
  73. package/crates/team-agent/src/lifecycle/launch/state_projection.rs +109 -2
  74. package/crates/team-agent/src/lifecycle/launch/worker_env.rs +214 -1
  75. package/crates/team-agent/src/lifecycle/launch.rs +209 -43
  76. package/crates/team-agent/src/lifecycle/lock.rs +42 -1
  77. package/crates/team-agent/src/lifecycle/mod.rs +11 -0
  78. package/crates/team-agent/src/lifecycle/pane_input_lock.rs +161 -0
  79. package/crates/team-agent/src/lifecycle/profile_launch.rs +98 -0
  80. package/crates/team-agent/src/lifecycle/profile_smoke.rs +51 -1
  81. package/crates/team-agent/src/lifecycle/restart/agent.rs +213 -3
  82. package/crates/team-agent/src/lifecycle/restart/common.rs +373 -18
  83. package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +27 -0
  84. package/crates/team-agent/src/lifecycle/restart/preflight.rs +25 -0
  85. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +165 -15
  86. package/crates/team-agent/src/lifecycle/restart/remove.rs +196 -5
  87. package/crates/team-agent/src/lifecycle/restart/selection.rs +72 -0
  88. package/crates/team-agent/src/lifecycle/restart/team_state.rs +22 -0
  89. package/crates/team-agent/src/lifecycle/restart.rs +29 -0
  90. package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +1 -1
  91. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +3 -4
  92. package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +1 -1
  93. package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +2 -2
  94. package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +4 -4
  95. package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +309 -0
  96. package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +159 -174
  97. package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +2 -2
  98. package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +15 -13
  99. package/crates/team-agent/src/lifecycle/tests/core.rs +4 -18
  100. package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +1 -1
  101. package/crates/team-agent/src/lifecycle/tests/cursor_mcp_overlay.rs +287 -0
  102. package/crates/team-agent/src/lifecycle/tests/cursor_require_explicit_model_red.rs +229 -0
  103. package/crates/team-agent/src/lifecycle/tests/cursor_restart_resume_red.rs +353 -0
  104. package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +1 -1
  105. package/crates/team-agent/src/lifecycle/tests/f032_startup_prompt_best_effort_red.rs +1 -1
  106. package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +784 -0
  107. package/crates/team-agent/src/lifecycle/tests/gate_fixtures.rs +562 -0
  108. package/crates/team-agent/src/lifecycle/tests/grok_effort_argv_red.rs +239 -0
  109. package/crates/team-agent/src/lifecycle/tests/grok_mcp_overlay_red.rs +498 -0
  110. package/crates/team-agent/src/lifecycle/tests/grok_require_explicit_model_red.rs +250 -0
  111. package/crates/team-agent/src/lifecycle/tests/grok_restart_resume_red.rs +293 -0
  112. package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +3 -0
  113. package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +3 -3
  114. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +65 -40
  115. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +20 -32
  116. package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +17 -9
  117. package/crates/team-agent/src/lifecycle/tests/mcp_tool_name_format_red.rs +69 -0
  118. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +24 -23
  119. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +98 -62
  120. package/crates/team-agent/src/lifecycle/tests/quick_start_worker_readiness_red.rs +2 -2
  121. package/crates/team-agent/src/lifecycle/tests/restart_build_before_destroy_0540_contract.rs +1 -1
  122. package/crates/team-agent/src/lifecycle/tests/restart_liveness_red.rs +1 -1
  123. package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +3 -1
  124. package/crates/team-agent/src/lifecycle/tests/restart_session_capture_red.rs +2 -2
  125. package/crates/team-agent/src/lifecycle/tests/resume_recover_red.rs +1 -1
  126. package/crates/team-agent/src/lifecycle/tests/stale_team_saveconflict_contract.rs +1 -1
  127. package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +41 -8
  128. package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +3 -3
  129. package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +1 -1
  130. package/crates/team-agent/src/lifecycle/tests/swallow_batch4_semantics_red.rs +1 -1
  131. package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +1 -1
  132. package/crates/team-agent/src/lifecycle/tests/team_in_team_sibling_quick_start_red.rs +1 -1
  133. package/crates/team-agent/src/lifecycle/tests/team_in_team_state_scope_red.rs +1 -1
  134. package/crates/team-agent/src/lifecycle/tests/team_key_retirement_txn_red.rs +1 -1
  135. package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +60 -2
  136. package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +1 -1
  137. package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +2 -2
  138. package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +69 -26
  139. package/crates/team-agent/src/lifecycle/tests.rs +23 -15
  140. package/crates/team-agent/src/lifecycle/types.rs +61 -2
  141. package/crates/team-agent/src/lifecycle/worker_command_context.rs +200 -33
  142. package/crates/team-agent/src/mcp_server/tests/scoped.rs +100 -1
  143. package/crates/team-agent/src/mcp_server/tests.rs +196 -2
  144. package/crates/team-agent/src/messaging/delivery.rs +405 -40
  145. package/crates/team-agent/src/messaging/helpers.rs +2 -0
  146. package/crates/team-agent/src/messaging/leader_receiver.rs +53 -1
  147. package/crates/team-agent/src/messaging/results.rs +4 -0
  148. package/crates/team-agent/src/messaging/send.rs +34 -0
  149. package/crates/team-agent/src/messaging/tests/dup_inject.rs +406 -0
  150. package/crates/team-agent/src/messaging/tests/e23.rs +9 -0
  151. package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +66 -0
  152. package/crates/team-agent/src/messaging/tests/main_preserved.rs +1 -1
  153. package/crates/team-agent/src/messaging/tests/mod.rs +1 -0
  154. package/crates/team-agent/src/messaging/types.rs +4 -1
  155. package/crates/team-agent/src/model/enums.rs +14 -5
  156. package/crates/team-agent/src/model/permissions.rs +3 -0
  157. package/crates/team-agent/src/model/spec.rs +129 -6
  158. package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +3 -1
  159. package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +3 -1
  160. package/crates/team-agent/src/model/testdata/team.spec.yaml +3 -1
  161. package/crates/team-agent/src/os_probe.rs +73 -2
  162. package/crates/team-agent/src/provider/adapter.rs +231 -4
  163. package/crates/team-agent/src/provider/adapters/claude.rs +5 -2
  164. package/crates/team-agent/src/provider/adapters/codex.rs +5 -2
  165. package/crates/team-agent/src/provider/adapters/copilot.rs +5 -2
  166. package/crates/team-agent/src/provider/adapters/cursor_agent.rs +86 -0
  167. package/crates/team-agent/src/provider/adapters/grok.rs +157 -0
  168. package/crates/team-agent/src/provider/adapters/mod.rs +2 -0
  169. package/crates/team-agent/src/provider/bypass_flags.rs +124 -0
  170. package/crates/team-agent/src/provider/classify.rs +4 -2
  171. package/crates/team-agent/src/provider/faults.rs +2 -1
  172. package/crates/team-agent/src/provider/mod.rs +13 -0
  173. package/crates/team-agent/src/provider/session/capture.rs +158 -20
  174. package/crates/team-agent/src/provider/session/context_fork/claude.rs +38 -1
  175. package/crates/team-agent/src/provider/session/context_fork/codex.rs +72 -1
  176. package/crates/team-agent/src/provider/session/context_fork/outcome.rs +57 -1
  177. package/crates/team-agent/src/provider/session/context_fork.rs +77 -3
  178. package/crates/team-agent/src/provider/session/mod.rs +18 -0
  179. package/crates/team-agent/src/provider/session/resume.rs +57 -0
  180. package/crates/team-agent/src/provider/session_scan/claude.rs +125 -1
  181. package/crates/team-agent/src/provider/session_scan/codex.rs +94 -1
  182. package/crates/team-agent/src/provider/session_scan/common.rs +204 -2
  183. package/crates/team-agent/src/provider/session_scan/copilot.rs +33 -1
  184. package/crates/team-agent/src/provider/session_scan/cursor.rs +538 -0
  185. package/crates/team-agent/src/provider/session_scan/grok.rs +288 -0
  186. package/crates/team-agent/src/provider/session_scan.rs +8 -0
  187. package/crates/team-agent/src/provider/submit_now.rs +94 -0
  188. package/crates/team-agent/src/provider/tests/adapter.rs +304 -0
  189. package/crates/team-agent/src/provider/types.rs +4 -2
  190. package/crates/team-agent/src/provider/wire.rs +23 -1
  191. package/crates/team-agent/src/state/persist.rs +301 -8
  192. package/crates/team-agent/src/state/repository.rs +5 -0
  193. package/crates/team-agent/src/tmux_backend/tests.rs +1737 -42
  194. package/crates/team-agent/src/tmux_backend.rs +1083 -75
  195. package/crates/team-agent/src/transport/test_support.rs +20 -0
  196. package/crates/team-agent/src/transport/tests/wire.rs +28 -2
  197. package/crates/team-agent/src/transport.rs +265 -1
  198. package/npm/install.mjs +129 -73
  199. package/package.json +4 -4
  200. package/skills/team-agent/SKILL.md +33 -238
  201. package/skills/team-agent/command-coverage.json +31 -0
  202. package/crates/team-agent/src/lifecycle/launch/approval.rs +0 -134
  203. package/crates/team-agent/src/lifecycle/launch/fork_agent/completion.rs +0 -59
  204. package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +0 -483
  205. package/crates/team-agent/src/lifecycle/launch/fork_pending.rs +0 -109
  206. package/crates/team-agent/src/lifecycle/launch/fork_state.rs +0 -447
  207. package/crates/team-agent/src/lifecycle/tests/codex_mcp_approval_inheritance_red.rs +0 -1187
  208. package/crates/team-agent/src/lifecycle/tests/worker_dangerous_bypass_argv_red.rs +0 -327
@@ -1,7 +1,29 @@
1
+ //! ---
2
+ //! purpose: plan 的停止与状态读取
3
+ //! contract:
4
+ //! provides:
5
+ //! - name: halt_plan
6
+ //! what: 读出 plan 状态并返回 Halted 结论
7
+ //! - name: plan_status
8
+ //! what: 读出 plan 的持久化状态
9
+ //! depends:
10
+ //! - crate::lifecycle::helpers
11
+ //! boundary:
12
+ //! - 只读状态文件,本文件不改写 plan 状态
13
+ //! - 不向席位投递任何消息
14
+ //! maturity: wired
15
+ //! ---
1
16
  use super::*;
2
17
 
3
18
  // ── lifecycle::orchestrator —— plan 多 stage 状态机(halt / status)──────────
4
19
 
20
+ /// ---
21
+ /// purpose: 对指定 plan 返回 Halted 结论
22
+ /// params:
23
+ /// reason: 当前实现未使用
24
+ /// returns: Halted,理由恒为 already_terminal;注意它不写盘,磁盘上的 status 不变
25
+ /// errors: 状态文件不存在或解析失败时返回 InvalidPlan
26
+ /// ---
5
27
  /// `halt_plan(workspace, plan_id, reason)`(`orchestrator/__init__.py:152`)。停 plan;
6
28
  /// 非 running → 幂等返回。
7
29
  pub(crate) fn halt_plan(
@@ -25,6 +47,11 @@ pub(crate) fn halt_plan(
25
47
  })
26
48
  }
27
49
 
50
+ /// ---
51
+ /// purpose: 读出 plan 的持久化状态
52
+ /// returns: 反序列化出的 PlanState
53
+ /// errors: 状态文件不存在或解析失败时返回 InvalidPlan
54
+ /// ---
28
55
  /// `plan_status(workspace, plan_id)`(`orchestrator/__init__.py:177`)。读 plan 持久态。
29
56
  pub(crate) fn plan_status(workspace: &Path, plan_id: &PlanId) -> Result<PlanState, LifecycleError> {
30
57
  let path = plan_state_path(workspace, plan_id);
@@ -1,3 +1,18 @@
1
+ //! ---
2
+ //! purpose: restart 拆除 worker session 之前的身份守卫,防止误杀 leader 会话
3
+ //! contract:
4
+ //! provides:
5
+ //! - name: SessionPreflight
6
+ //! what: 守卫结论,通过或指出 worker session 名其实是 leader 会话名
7
+ //! - name: check_session_preflight
8
+ //! what: 纯函数检查 state 里的 session 名字段
9
+ //! depends:
10
+ //! - crate::layout::RuntimeSessions
11
+ //! boundary:
12
+ //! - 纯计算,不做 IO 也不改 state
13
+ //! - 只判这一种异常,其他 session 异常不在本守卫范围
14
+ //! maturity: wired
15
+ //! ---
1
16
  //! unit-3 (Stage 1) — restart preflight session-identity guard.
2
17
  //!
3
18
  //! Single check that runs BEFORE the worker-session teardown in
@@ -27,12 +42,22 @@ pub enum SessionPreflight {
27
42
  }
28
43
 
29
44
  impl SessionPreflight {
45
+ /// ---
46
+ /// purpose: 判断守卫是否放行
47
+ /// returns: 结论为 Ok 时为 true
48
+ /// ---
30
49
  /// True when the preflight passed and the caller may proceed.
31
50
  pub fn is_ok(&self) -> bool {
32
51
  matches!(self, SessionPreflight::Ok)
33
52
  }
34
53
  }
35
54
 
55
+ /// ---
56
+ /// purpose: 检查 state 里的 session 名,决定接下来的 worker session 拆除是否安全
57
+ /// params:
58
+ /// state: runtime state
59
+ /// returns: 发现 worker session 名带 leader 前缀时返回拒绝结论并附名字与原因,否则 Ok
60
+ /// ---
36
61
  /// Inspect `state.json` and decide whether the upcoming worker-session
37
62
  /// kill is safe. Pure: no I/O, no mutation.
38
63
  pub fn check_session_preflight(state: &serde_json::Value) -> SessionPreflight {
@@ -1,3 +1,33 @@
1
+ //! ---
2
+ //! purpose: 整队重建,先算 resume 计划与拒绝结论,再做破坏性拆除与重起
3
+ //! contract:
4
+ //! provides:
5
+ //! - name: restart
6
+ //! what: 整队重建入口,解析 team 与它实际使用的 transport 后执行
7
+ //! - name: restart_with_transport_with_session_convergence_deadline
8
+ //! what: 重建的实体实现,含入口门、spec 重建、计划分类、四种拒绝与重起
9
+ //! - name: RestartPhaseTimer
10
+ //! what: 阶段计时器,把 restart 与 launch 的分段耗时写成事件
11
+ //! - name: restart_candidates
12
+ //! what: 列出本 workspace 可重启的团队
13
+ //! - name: select_restart_state
14
+ //! what: 按 team 参数或唯一性选出重启目标
15
+ //! depends:
16
+ //! - crate::lifecycle::lock
17
+ //! - crate::lifecycle::display
18
+ //! - crate::lifecycle::restart::selection
19
+ //! - crate::lifecycle::restart::preflight
20
+ //! - crate::lifecycle::restart::remove
21
+ //! - crate::state::selector
22
+ //! - crate::state::projection
23
+ //! - crate::state::persist
24
+ //! - crate::event_log::EventLog
25
+ //! boundary:
26
+ //! - 四种拒绝一律先于任何 teardown 产出,拒绝时现场不变
27
+ //! - 每个非 paused 席位必发一条 resume 决策事件
28
+ //! - 只有计划里不含 Resumed 时才并行起席,串行臂的会话消失检测没有并发等价物
29
+ //! maturity: wired
30
+ //! ---
1
31
  use super::common::*;
2
32
  use super::selection::classify_restart_plan_with_resume_validation;
3
33
  use super::*;
@@ -17,16 +47,31 @@ pub(crate) struct RestartPhaseTimer {
17
47
  }
18
48
 
19
49
  impl RestartPhaseTimer {
50
+ /// ---
51
+ /// purpose: 起一个阶段计时器
52
+ /// returns: 以当前单调时钟为起点的计时器
53
+ /// ---
20
54
  pub(crate) fn start() -> Self {
21
55
  Self {
22
56
  started_at: std::time::Instant::now(),
23
57
  }
24
58
  }
25
59
 
60
+ /// ---
61
+ /// purpose: 取从起点到现在的毫秒数
62
+ /// returns: 毫秒数,溢出时取上限值
63
+ /// ---
26
64
  pub(crate) fn elapsed_ms(&self) -> u64 {
27
65
  u64::try_from(self.started_at.elapsed().as_millis()).unwrap_or(u64::MAX)
28
66
  }
29
67
 
68
+ /// ---
69
+ /// purpose: 写一条带阶段名与已用毫秒数的事件
70
+ /// params:
71
+ /// kind: 事件名,restart.phase 或 launch.phase
72
+ /// phase: 阶段名
73
+ /// returns: 写事件失败被吞掉,不影响主流程
74
+ /// ---
30
75
  pub(crate) fn emit(&self, workspace: &Path, kind: &'static str, phase: &'static str) {
31
76
  let event_log = crate::event_log::EventLog::new(workspace);
32
77
  let _ = event_log.write(
@@ -41,6 +86,15 @@ impl RestartPhaseTimer {
41
86
 
42
87
  // ── lifecycle::restart —— 整队 Route B resume-or-fresh 重建 ──────────────────
43
88
 
89
+ /// ---
90
+ /// purpose: 整队重建的对外入口
91
+ /// params:
92
+ /// allow_fresh: 允许把不可 resume 的席位改跑全新会话
93
+ /// team: 指定团队,None 时按唯一性选
94
+ /// returns: 重建报告,含成功与失败席位,或四种拒绝之一
95
+ /// errors: 选不到 team 返回 TeamSelect,路径归一失败返回 StatePersist
96
+ /// contract_id: lifecycle.rebuild.restart_entry
97
+ /// ---
44
98
  /// `restart(workspace, allow_fresh, team)`(`restart/orchestration.py:26`)。整队重建:
45
99
  /// **先**算 resume 决策(Route B)+ `first_send_at` 严格校验(corrupt → hard refuse),
46
100
  /// **再**做破坏性 teardown(关显示、建 session)、起后 leader rebind、adaptive 显示重建。
@@ -53,6 +107,14 @@ pub fn restart(
53
107
  restart_with_session_convergence_deadline(workspace, allow_fresh, team, None)
54
108
  }
55
109
 
110
+ /// ---
111
+ /// purpose: 带会话收敛等待上限的整队重建入口
112
+ /// params:
113
+ /// session_converge_deadline_ms: 等待会话收敛的上限,None 用默认
114
+ /// returns: 重建报告
115
+ /// errors: 同 restart
116
+ /// contract_id: lifecycle.rebuild.restart_entry
117
+ /// ---
56
118
  pub fn restart_with_session_convergence_deadline(
57
119
  workspace: &Path,
58
120
  allow_fresh: bool,
@@ -106,6 +168,12 @@ fn resolve_restart_context(
106
168
  })
107
169
  }
108
170
 
171
+ /// ---
172
+ /// purpose: 带注入 transport 的整队重建入口
173
+ /// returns: 重建报告
174
+ /// errors: 透传实体实现的错误
175
+ /// contract_id: lifecycle.rebuild.restart_entry
176
+ /// ---
109
177
  /// `restart` with an injected transport (tests: recording mock; prod: real TmuxBackend). The Route-B
110
178
  /// resume/fresh worker spawn + start_coordinator are wired here over `transport`. (rt-host-a sweep:
111
179
  /// was a stub returning RequirementUnmet at the spawn boundary — never spawned/resumed/started coordinator.)
@@ -118,6 +186,13 @@ pub(crate) fn restart_with_transport(
118
186
  restart_with_transport_with_readiness_deadline(workspace, allow_fresh, team, transport, None)
119
187
  }
120
188
 
189
+ /// ---
190
+ /// purpose: 带就绪等待上限的重建入口
191
+ /// params:
192
+ /// readiness_deadline_ms: 等待就绪的上限
193
+ /// returns: 重建报告;注意本入口把 RefusedResumeNotReady 重映射成 RefusedResumeAtomicity 并把原因记为会话捕获未收敛,两种拒绝在此入口不可分辨
194
+ /// errors: 透传实体实现的错误
195
+ /// ---
121
196
  pub(crate) fn restart_with_transport_with_readiness_deadline(
122
197
  workspace: &Path,
123
198
  allow_fresh: bool,
@@ -158,6 +233,14 @@ pub(crate) fn restart_with_transport_with_readiness_deadline(
158
233
  }
159
234
  }
160
235
 
236
+ /// ---
237
+ /// purpose: 整队重建的实体实现
238
+ /// params:
239
+ /// session_converge_deadline_ms: 会话收敛等待上限
240
+ /// readiness_deadline_ms: 就绪等待上限
241
+ /// returns: 重建报告,或计划分类给出的拒绝结论
242
+ /// errors: 归一路径失败返回 StatePersist;无本地 team 上下文或 spec 缺失返回 TeamSelect
243
+ /// ---
161
244
  pub(crate) fn restart_with_transport_with_session_convergence_deadline(
162
245
  workspace: &Path,
163
246
  allow_fresh: bool,
@@ -270,7 +353,6 @@ fn restart_with_selected_team_and_transport(
270
353
  let spec_workspace = runtime_spec.parent().ok_or_else(|| {
271
354
  LifecycleError::TeamSelect("active team spec workspace not found".to_string())
272
355
  })?;
273
- let safety = crate::lifecycle::launch::effective_runtime_config(&spec)?;
274
356
  // Bug 1 (0.4.2 P0): the rebuilt spec is the single source of truth for the
275
357
  // active roster. Any agent in state.agents that is NOT in the rebuilt
276
358
  // spec is a stale leftover (role doc was deleted between sessions) and
@@ -526,7 +608,6 @@ fn restart_with_selected_team_and_transport(
526
608
  &selected.team_key,
527
609
  &session_name,
528
610
  transport,
529
- &safety,
530
611
  tmux_endpoint_source,
531
612
  &state,
532
613
  )
@@ -551,12 +632,25 @@ fn restart_with_selected_team_and_transport(
551
632
  if let Some(parallel_result) = parallel_result {
552
633
  match parallel_result {
553
634
  Ok(pspawn) => {
635
+ let raw_agent = state
636
+ .get("agents")
637
+ .and_then(|v| v.get(decision.agent_id.as_str()))
638
+ .cloned()
639
+ .unwrap_or(serde_json::Value::Null);
640
+ let rehydrated = rehydrate_agent_command_context_from_spec(
641
+ spec_workspace,
642
+ &decision.agent_id,
643
+ &raw_agent,
644
+ );
645
+ let launched_bypass = matches!(
646
+ rehydrated.get("dangerously_skip_permissions"),
647
+ Some(serde_json::Value::Bool(true))
648
+ );
554
649
  apply_marked_respawn(
555
650
  &selected.run_workspace,
556
651
  &selected.team_key,
557
652
  &mut state,
558
653
  transport,
559
- &safety,
560
654
  &phase_timer,
561
655
  decision,
562
656
  &pspawn.spawn,
@@ -565,6 +659,7 @@ fn restart_with_selected_team_and_transport(
565
659
  &mut successful_agents,
566
660
  &mut failed_agents,
567
661
  &mut fatal_resume_failure,
662
+ launched_bypass,
568
663
  );
569
664
  }
570
665
  Err(error) => {
@@ -709,7 +804,7 @@ fn restart_with_selected_team_and_transport(
709
804
  session_id,
710
805
  session_live,
711
806
  transport,
712
- Some(&safety),
807
+ None,
713
808
  layout_placement.as_ref(),
714
809
  None,
715
810
  tmux_endpoint_source,
@@ -737,6 +832,10 @@ fn restart_with_selected_team_and_transport(
737
832
  }
738
833
  };
739
834
  let verify_start = std::time::Instant::now();
835
+ let launched_bypass = matches!(
836
+ agent.get("dangerously_skip_permissions"),
837
+ Some(serde_json::Value::Bool(true))
838
+ );
740
839
  if let Err(error) = verify_spawned_agent_live(&decision.agent_id, &spawn, transport)
741
840
  .and_then(|_| {
742
841
  mark_agent_respawned(
@@ -745,7 +844,7 @@ fn restart_with_selected_team_and_transport(
745
844
  decision.restart_mode,
746
845
  &spawn,
747
846
  transport,
748
- &safety,
847
+ launched_bypass,
749
848
  )
750
849
  })
751
850
  {
@@ -787,7 +886,16 @@ fn restart_with_selected_team_and_transport(
787
886
  .and_then(|agents| agents.get_mut(decision.agent_id.as_str()))
788
887
  .and_then(serde_json::Value::as_object_mut)
789
888
  {
790
- persist_effective_approval_policy_for_restart(agent, &safety);
889
+ // 0.5.66 bypass 单源:policy 从 agent 行字段派生。
890
+ let agent_provider = agent
891
+ .get("provider")
892
+ .and_then(serde_json::Value::as_str)
893
+ .and_then(crate::provider::wire::parse_canonical_provider)
894
+ .unwrap_or(crate::model::enums::Provider::Codex);
895
+ crate::lifecycle::launch::persist_effective_approval_policy_from_agent(
896
+ agent,
897
+ agent_provider,
898
+ );
791
899
  }
792
900
  // 0.5.32 (`.team/artifacts/restart-resumed-stale-activity-locate.md` §5):
793
901
  // pair the state-side activity clear with a DB `agent_health` clear so
@@ -1958,7 +2066,7 @@ fn mark_agent_respawned(
1958
2066
  restart_mode: StartMode,
1959
2067
  spawn: &SpawnedAgentWindow,
1960
2068
  transport: &dyn crate::transport::Transport,
1961
- safety: &DangerousApproval,
2069
+ launched_bypass: bool,
1962
2070
  ) -> Result<(), LifecycleError> {
1963
2071
  let Some(agent) = state
1964
2072
  .get_mut("agents")
@@ -2081,7 +2189,18 @@ fn mark_agent_respawned(
2081
2189
  }
2082
2190
  }
2083
2191
  crate::lifecycle::launch::persist_command_plan_state(agent, &spawn.plan, &spawn.profile_launch);
2084
- persist_effective_approval_policy_for_restart(agent, safety);
2192
+ // 0.5.66 bypass 单源:policy 从 agent 行字段派生,不再用全队 `DangerousApproval`。
2193
+ let agent_provider = agent
2194
+ .get("provider")
2195
+ .and_then(serde_json::Value::as_str)
2196
+ .and_then(crate::provider::wire::parse_canonical_provider)
2197
+ .unwrap_or(crate::model::enums::Provider::Codex);
2198
+ crate::lifecycle::launch::persist_effective_approval_policy_from_agent(agent, agent_provider);
2199
+ // 0.5.66 bypass 单源 §2.6:fresh spawn(restart)记录运行面 bypass 值。
2200
+ agent.insert(
2201
+ "as_launched_dangerously_skip_permissions".to_string(),
2202
+ serde_json::json!(launched_bypass),
2203
+ );
2085
2204
  if let Some(placement) = spawn.layout_placement.as_ref() {
2086
2205
  agent.insert(
2087
2206
  "layout_window".to_string(),
@@ -2510,7 +2629,6 @@ fn run_bounded_parallel_worker_spawns(
2510
2629
  team_key: &str,
2511
2630
  session_name: &SessionName,
2512
2631
  transport: &(dyn crate::transport::Transport),
2513
- safety: &DangerousApproval,
2514
2632
  tmux_endpoint_source: Option<&str>,
2515
2633
  state: &serde_json::Value,
2516
2634
  ) -> Vec<Option<Result<ParallelSpawnResult, String>>> {
@@ -2589,7 +2707,7 @@ fn run_bounded_parallel_worker_spawns(
2589
2707
  first_input.session_id.as_ref(),
2590
2708
  first_session_live,
2591
2709
  transport,
2592
- Some(safety),
2710
+ None,
2593
2711
  first_input.layout_placement.as_ref(),
2594
2712
  None,
2595
2713
  tmux_endpoint_source,
@@ -2673,7 +2791,7 @@ fn run_bounded_parallel_worker_spawns(
2673
2791
  input.session_id.as_ref(),
2674
2792
  /* into_existing_session */ true,
2675
2793
  transport,
2676
- Some(safety),
2794
+ None,
2677
2795
  input.layout_placement.as_ref(),
2678
2796
  None,
2679
2797
  tmux_endpoint_source,
@@ -2716,7 +2834,6 @@ fn apply_marked_respawn(
2716
2834
  team_key: &str,
2717
2835
  state: &mut serde_json::Value,
2718
2836
  transport: &(dyn crate::transport::Transport),
2719
- safety: &DangerousApproval,
2720
2837
  phase_timer: &RestartPhaseTimer,
2721
2838
  decision: &RestartedAgent,
2722
2839
  spawn: &SpawnedAgentWindow,
@@ -2725,6 +2842,7 @@ fn apply_marked_respawn(
2725
2842
  successful_agents: &mut Vec<RestartedAgent>,
2726
2843
  failed_agents: &mut Vec<RestartFailedAgent>,
2727
2844
  fatal_resume_failure: &mut bool,
2845
+ launched_bypass: bool,
2728
2846
  ) {
2729
2847
  let verify_start = std::time::Instant::now();
2730
2848
  if let Err(error) =
@@ -2735,7 +2853,7 @@ fn apply_marked_respawn(
2735
2853
  decision.restart_mode,
2736
2854
  spawn,
2737
2855
  transport,
2738
- safety,
2856
+ launched_bypass,
2739
2857
  )
2740
2858
  })
2741
2859
  {
@@ -2776,7 +2894,16 @@ fn apply_marked_respawn(
2776
2894
  .and_then(|agents| agents.get_mut(decision.agent_id.as_str()))
2777
2895
  .and_then(serde_json::Value::as_object_mut)
2778
2896
  {
2779
- persist_effective_approval_policy_for_restart(agent, safety);
2897
+ // 0.5.66 bypass 单源:policy 从 agent 行字段派生。
2898
+ let agent_provider = agent
2899
+ .get("provider")
2900
+ .and_then(serde_json::Value::as_str)
2901
+ .and_then(crate::provider::wire::parse_canonical_provider)
2902
+ .unwrap_or(crate::model::enums::Provider::Codex);
2903
+ crate::lifecycle::launch::persist_effective_approval_policy_from_agent(
2904
+ agent,
2905
+ agent_provider,
2906
+ );
2780
2907
  }
2781
2908
  let _ = crate::db::agent_health_capture::clear_agent_health_observation(
2782
2909
  run_workspace,
@@ -2785,6 +2912,13 @@ fn apply_marked_respawn(
2785
2912
  );
2786
2913
  }
2787
2914
 
2915
+ /// ---
2916
+ /// purpose: 写一条 per-worker 的启动分段耗时事件
2917
+ /// params:
2918
+ /// source: 事件来源,launch 或 restart
2919
+ /// command_plan_ms: 命令拼装耗时,调用方给不出真实值时可能是占位 0
2920
+ /// returns: 写事件失败被吞掉
2921
+ /// ---
2788
2922
  /// 0.5.38 Step 1 (`.team/artifacts/startup-latency-locate.md` §5): per-worker
2789
2923
  /// timing tag so operators can pinpoint whether wall time is spent in
2790
2924
  /// command plan compilation, transport spawn, pane verification, or the
@@ -2821,6 +2955,10 @@ pub(crate) fn write_worker_spawn_timing_event(
2821
2955
  );
2822
2956
  }
2823
2957
 
2958
+ /// ---
2959
+ /// purpose: 从 state 里取某席位的 provider wire 名
2960
+ /// returns: 取到的名字,缺失时为 fake
2961
+ /// ---
2824
2962
  pub(crate) fn provider_wire_from_state<'a>(
2825
2963
  state: &'a serde_json::Value,
2826
2964
  agent_id: &str,
@@ -3068,6 +3206,11 @@ fn write_restart_resume_decision_event(
3068
3206
  .map_err(|e| LifecycleError::StatePersist(e.to_string()))
3069
3207
  }
3070
3208
 
3209
+ /// ---
3210
+ /// purpose: 列出本 workspace 里可重启的团队
3211
+ /// returns: 每个团队一条候选;没有活团队但顶层 state 有可重启形状时返回它自己
3212
+ /// errors: 读 runtime state 失败时返回 StatePersist
3213
+ /// ---
3071
3214
  /// `restart_candidates(workspace)`(`restart/selection.py:12`)。从 snapshot + active
3072
3215
  /// state 收集可重启 team。
3073
3216
  pub(crate) fn restart_candidates(workspace: &Path) -> Result<Vec<RestartCandidate>, LifecycleError> {
@@ -3090,6 +3233,13 @@ pub(crate) fn restart_candidates(workspace: &Path) -> Result<Vec<RestartCandidat
3090
3233
  .collect())
3091
3234
  }
3092
3235
 
3236
+ /// ---
3237
+ /// purpose: 选出本次重启的目标团队
3238
+ /// params:
3239
+ /// team: 指定团队名,None 时按唯一性选
3240
+ /// returns: 选中的候选
3241
+ /// errors: 选不出或选中的 state 不具备可重启形状时返回 TeamSelect
3242
+ /// ---
3093
3243
  /// `select_restart_state(workspace, team)`(`restart/selection.py:49`)。按 `--team` 或
3094
3244
  /// 唯一性选一个;歧义/未找到 → `TeamSelect`。
3095
3245
  pub(crate) fn select_restart_state(
@@ -3728,7 +3878,7 @@ tasks:
3728
3878
  StartMode::Resumed,
3729
3879
  &spawn,
3730
3880
  &RespawnEpochTransport,
3731
- &disabled_safety(),
3881
+ false,
3732
3882
  )
3733
3883
  .expect("mark respawned");
3734
3884