@team-agent/installer 0.5.66 → 0.5.69
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.
- package/Cargo.lock +8 -1
- package/Cargo.toml +1 -1
- package/crates/team-agent/Cargo.toml +1 -0
- package/crates/team-agent/src/cli/adapters.rs +5 -0
- package/crates/team-agent/src/cli/diagnose.rs +156 -0
- package/crates/team-agent/src/cli/emit.rs +6 -5
- package/crates/team-agent/src/cli/grok_slot.rs +299 -0
- package/crates/team-agent/src/cli/leader.rs +22 -7
- package/crates/team-agent/src/cli/leaders.rs +125 -1
- package/crates/team-agent/src/cli/mod.rs +20 -0
- package/crates/team-agent/src/cli/send/presentation.rs +7 -1
- package/crates/team-agent/src/cli/spec.rs +3 -0
- package/crates/team-agent/src/cli/status_port/compact.rs +28 -0
- package/crates/team-agent/src/cli/status_port/snapshot.rs +25 -1
- package/crates/team-agent/src/cli/tests/base.rs +26 -3
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +129 -19
- package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +387 -6
- package/crates/team-agent/src/cli/tests/status_send.rs +79 -10
- package/crates/team-agent/src/communication_mode/mod.rs +6 -4
- package/crates/team-agent/src/compiler.rs +121 -5
- package/crates/team-agent/src/coordinator/backoff.rs +55 -0
- package/crates/team-agent/src/coordinator/conpty_shim.rs +82 -0
- package/crates/team-agent/src/coordinator/health.rs +173 -0
- package/crates/team-agent/src/coordinator/mod.rs +31 -0
- package/crates/team-agent/src/coordinator/orphan.rs +31 -0
- package/crates/team-agent/src/coordinator/runtime_detectors.rs +31 -0
- package/crates/team-agent/src/coordinator/runtime_observation.rs +25 -0
- package/crates/team-agent/src/coordinator/steps/abnormal.rs +59 -0
- package/crates/team-agent/src/coordinator/steps/delivery.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/health_sync.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/mod.rs +22 -0
- package/crates/team-agent/src/coordinator/steps/persist.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/runtime_prompts.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/session_gate.rs +10 -0
- package/crates/team-agent/src/coordinator/tick.rs +133 -22
- package/crates/team-agent/src/coordinator/types.rs +49 -0
- package/crates/team-agent/src/db/message_store.rs +39 -5
- package/crates/team-agent/src/layout/worker_env.rs +20 -3
- package/crates/team-agent/src/layout/worker_window_helpers.rs +3 -0
- package/crates/team-agent/src/leader/provider_attribution.rs +53 -0
- package/crates/team-agent/src/leader/registry.rs +65 -0
- package/crates/team-agent/src/leader/start.rs +973 -75
- package/crates/team-agent/src/lifecycle/display.rs +56 -0
- package/crates/team-agent/src/lifecycle/helpers.rs +57 -0
- package/crates/team-agent/src/lifecycle/launch/add_agent.rs +398 -26
- package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +80 -0
- package/crates/team-agent/src/lifecycle/launch/agent_state.rs +60 -0
- package/crates/team-agent/src/lifecycle/launch/clone_agent.rs +101 -11
- package/crates/team-agent/src/lifecycle/launch/cursor_create_chat.rs +229 -0
- package/crates/team-agent/src/lifecycle/launch/cursor_mcp.rs +548 -0
- package/crates/team-agent/src/lifecycle/launch/cursor_mcp_iso.rs +120 -0
- package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +208 -456
- package/crates/team-agent/src/lifecycle/launch/fork_entry.rs +24 -0
- package/crates/team-agent/src/lifecycle/launch/grok_per_seat.rs +260 -0
- package/crates/team-agent/src/lifecycle/launch/identity.rs +146 -0
- package/crates/team-agent/src/lifecycle/launch/layout.rs +60 -0
- package/crates/team-agent/src/lifecycle/launch/leader_context.rs +112 -0
- package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +482 -1
- package/crates/team-agent/src/lifecycle/launch/ownership.rs +40 -0
- package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +830 -0
- package/crates/team-agent/src/lifecycle/launch/plan.rs +31 -0
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +66 -0
- package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +87 -3
- package/crates/team-agent/src/lifecycle/launch/readiness.rs +85 -38
- package/crates/team-agent/src/lifecycle/launch/role_source.rs +44 -44
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +127 -25
- package/crates/team-agent/src/lifecycle/launch/spec_state.rs +140 -0
- package/crates/team-agent/src/lifecycle/launch/state_projection.rs +109 -0
- package/crates/team-agent/src/lifecycle/launch/worker_env.rs +214 -1
- package/crates/team-agent/src/lifecycle/launch.rs +107 -29
- package/crates/team-agent/src/lifecycle/lock.rs +42 -1
- package/crates/team-agent/src/lifecycle/mod.rs +11 -0
- package/crates/team-agent/src/lifecycle/pane_input_lock.rs +161 -0
- package/crates/team-agent/src/lifecycle/profile_launch.rs +99 -0
- package/crates/team-agent/src/lifecycle/profile_smoke.rs +52 -1
- package/crates/team-agent/src/lifecycle/restart/agent.rs +214 -160
- package/crates/team-agent/src/lifecycle/restart/common.rs +513 -37
- package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +27 -0
- package/crates/team-agent/src/lifecycle/restart/preflight.rs +25 -0
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +106 -0
- package/crates/team-agent/src/lifecycle/restart/remove.rs +233 -6
- package/crates/team-agent/src/lifecycle/restart/selection.rs +72 -0
- package/crates/team-agent/src/lifecycle/restart/team_state.rs +22 -0
- package/crates/team-agent/src/lifecycle/restart.rs +29 -0
- package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +2 -3
- package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +24 -3
- package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +309 -0
- package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +150 -157
- package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/core.rs +4 -0
- package/crates/team-agent/src/lifecycle/tests/cursor_mcp_overlay.rs +464 -0
- package/crates/team-agent/src/lifecycle/tests/cursor_require_explicit_model_red.rs +247 -0
- package/crates/team-agent/src/lifecycle/tests/cursor_restart_resume_red.rs +353 -0
- package/crates/team-agent/src/lifecycle/tests/fixtures/pi_list_models_g0.stdout.txt +222 -0
- package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +787 -0
- package/crates/team-agent/src/lifecycle/tests/gate_fixtures.rs +562 -0
- package/crates/team-agent/src/lifecycle/tests/grok_effort_argv_red.rs +239 -0
- package/crates/team-agent/src/lifecycle/tests/grok_mcp_overlay_red.rs +485 -0
- package/crates/team-agent/src/lifecycle/tests/grok_require_explicit_model_red.rs +250 -0
- package/crates/team-agent/src/lifecycle/tests/grok_restart_resume_red.rs +293 -0
- package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +63 -38
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +3 -2
- package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +16 -8
- package/crates/team-agent/src/lifecycle/tests/mcp_tool_name_format_red.rs +69 -0
- package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +20 -19
- package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +97 -61
- package/crates/team-agent/src/lifecycle/tests/pi_catalog_red.rs +97 -0
- package/crates/team-agent/src/lifecycle/tests/pi_command_red.rs +128 -0
- package/crates/team-agent/src/lifecycle/tests/pi_compiler_red.rs +207 -0
- package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +838 -0
- package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +320 -0
- package/crates/team-agent/src/lifecycle/tests/pi_lifecycle_doctor_red.rs +98 -0
- package/crates/team-agent/src/lifecycle/tests/pi_session_delivery_red.rs +216 -0
- package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +3 -0
- package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +40 -7
- package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +59 -1
- package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +69 -26
- package/crates/team-agent/src/lifecycle/tests.rs +30 -13
- package/crates/team-agent/src/lifecycle/types.rs +61 -0
- package/crates/team-agent/src/lifecycle/worker_command_context.rs +143 -12
- package/crates/team-agent/src/mcp_server/tests/scoped.rs +100 -1
- package/crates/team-agent/src/mcp_server/tests.rs +196 -2
- package/crates/team-agent/src/messaging/delivery.rs +430 -41
- package/crates/team-agent/src/messaging/helpers.rs +2 -0
- package/crates/team-agent/src/messaging/leader_receiver.rs +53 -1
- package/crates/team-agent/src/messaging/results.rs +4 -0
- package/crates/team-agent/src/messaging/send.rs +34 -0
- package/crates/team-agent/src/messaging/tests/dup_inject.rs +406 -0
- package/crates/team-agent/src/messaging/tests/e23.rs +9 -0
- package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +66 -0
- package/crates/team-agent/src/messaging/tests/mod.rs +1 -0
- package/crates/team-agent/src/messaging/types.rs +4 -1
- package/crates/team-agent/src/model/enums.rs +17 -6
- package/crates/team-agent/src/model/permissions.rs +3 -0
- package/crates/team-agent/src/os_probe.rs +73 -2
- package/crates/team-agent/src/provider/adapter.rs +259 -6
- package/crates/team-agent/src/provider/adapters/cursor_agent.rs +89 -0
- package/crates/team-agent/src/provider/adapters/grok.rs +157 -0
- package/crates/team-agent/src/provider/adapters/mod.rs +3 -0
- package/crates/team-agent/src/provider/adapters/pi.rs +152 -0
- package/crates/team-agent/src/provider/bypass_flags.rs +47 -2
- package/crates/team-agent/src/provider/classify.rs +4 -2
- package/crates/team-agent/src/provider/faults.rs +2 -1
- package/crates/team-agent/src/provider/mod.rs +11 -0
- package/crates/team-agent/src/provider/session/capture.rs +158 -20
- package/crates/team-agent/src/provider/session/context_fork/claude.rs +38 -1
- package/crates/team-agent/src/provider/session/context_fork/codex.rs +72 -1
- package/crates/team-agent/src/provider/session/context_fork/outcome.rs +57 -1
- package/crates/team-agent/src/provider/session/context_fork.rs +78 -3
- package/crates/team-agent/src/provider/session/mod.rs +18 -0
- package/crates/team-agent/src/provider/session/resume.rs +57 -0
- package/crates/team-agent/src/provider/session_scan/claude.rs +125 -1
- package/crates/team-agent/src/provider/session_scan/codex.rs +94 -1
- package/crates/team-agent/src/provider/session_scan/common.rs +205 -2
- package/crates/team-agent/src/provider/session_scan/copilot.rs +33 -1
- package/crates/team-agent/src/provider/session_scan/cursor.rs +538 -0
- package/crates/team-agent/src/provider/session_scan/grok.rs +288 -0
- package/crates/team-agent/src/provider/session_scan/pi.rs +172 -0
- package/crates/team-agent/src/provider/session_scan.rs +12 -0
- package/crates/team-agent/src/provider/submit_now.rs +94 -0
- package/crates/team-agent/src/provider/tests/adapter.rs +384 -0
- package/crates/team-agent/src/provider/types.rs +4 -2
- package/crates/team-agent/src/provider/wire.rs +29 -1
- package/crates/team-agent/src/state/persist.rs +301 -8
- package/crates/team-agent/src/state/repository.rs +5 -0
- package/crates/team-agent/src/tmux_backend/tests.rs +1737 -42
- package/crates/team-agent/src/tmux_backend.rs +1116 -75
- package/crates/team-agent/src/transport/tests/wire.rs +28 -2
- package/crates/team-agent/src/transport.rs +248 -1
- package/npm/install.mjs +129 -73
- package/package.json +4 -4
- package/skills/team-agent/SKILL.md +32 -239
- package/skills/team-agent/command-coverage.json +31 -0
- package/crates/team-agent/src/lifecycle/launch/fork_agent/completion.rs +0 -59
- package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +0 -488
- package/crates/team-agent/src/lifecycle/launch/fork_pending.rs +0 -109
- package/crates/team-agent/src/lifecycle/launch/fork_state.rs +0 -447
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
//! ---
|
|
2
|
+
//! purpose: 对 compatible_api 席位做发车前的 profile 连通性冒烟
|
|
3
|
+
//! contract:
|
|
4
|
+
//! provides:
|
|
5
|
+
//! - name: profile_smoke_checks_for_agents_with_profile_dir
|
|
6
|
+
//! what: 对一组 agent 逐个冒烟,可指定优先查找的 profile 目录
|
|
7
|
+
//! - name: profile_smoke_checks_for_agents
|
|
8
|
+
//! what: 对一组 agent 逐个冒烟,返回逐个结果
|
|
9
|
+
//! - name: smoke_check_agent_profile
|
|
10
|
+
//! what: 单 agent 冒烟,非 compatible_api 直接判 not_required
|
|
11
|
+
//! - name: format_profile_smoke_failures
|
|
12
|
+
//! what: 把失败结果排成一行可读文本
|
|
13
|
+
//! depends:
|
|
14
|
+
//! - crate::lifecycle::profile_launch
|
|
15
|
+
//! - crate::provider::wire
|
|
16
|
+
//! boundary:
|
|
17
|
+
//! - 只读 profile 并发探测请求,不改 profile、不写 runtime state
|
|
18
|
+
//! - 不做重试与退避,超时即判失败
|
|
19
|
+
//! - 结果里不带密钥值
|
|
20
|
+
//! maturity: wired
|
|
21
|
+
//! ---
|
|
1
22
|
use std::collections::BTreeMap;
|
|
2
23
|
use std::io::Write as _;
|
|
3
24
|
use std::path::Path;
|
|
@@ -13,6 +34,13 @@ use crate::provider::wire::provider_wire;
|
|
|
13
34
|
|
|
14
35
|
pub(crate) const DEFAULT_PROFILE_SMOKE_TIMEOUT: Duration = Duration::from_secs(8);
|
|
15
36
|
|
|
37
|
+
/// ---
|
|
38
|
+
/// purpose: 用默认 profile 目录对一组 agent 逐个冒烟
|
|
39
|
+
/// params:
|
|
40
|
+
/// agents: spec 里的 agent 节点列表
|
|
41
|
+
/// timeout: 单次探测的超时
|
|
42
|
+
/// returns: 与入参同序的逐 agent 结果 JSON
|
|
43
|
+
/// ---
|
|
16
44
|
pub(crate) fn profile_smoke_checks_for_agents(
|
|
17
45
|
workspace: &Path,
|
|
18
46
|
agents: &[YamlValue],
|
|
@@ -21,6 +49,12 @@ pub(crate) fn profile_smoke_checks_for_agents(
|
|
|
21
49
|
profile_smoke_checks_for_agents_with_profile_dir(workspace, agents, None, timeout)
|
|
22
50
|
}
|
|
23
51
|
|
|
52
|
+
/// ---
|
|
53
|
+
/// purpose: 用指定 profile 目录对一组 agent 逐个冒烟
|
|
54
|
+
/// params:
|
|
55
|
+
/// profile_dir: 优先查找的 profile 目录,None 表示只用默认查找顺序
|
|
56
|
+
/// returns: 与入参同序的逐 agent 结果 JSON
|
|
57
|
+
/// ---
|
|
24
58
|
pub(crate) fn profile_smoke_checks_for_agents_with_profile_dir(
|
|
25
59
|
workspace: &Path,
|
|
26
60
|
agents: &[YamlValue],
|
|
@@ -33,6 +67,13 @@ pub(crate) fn profile_smoke_checks_for_agents_with_profile_dir(
|
|
|
33
67
|
.collect()
|
|
34
68
|
}
|
|
35
69
|
|
|
70
|
+
/// ---
|
|
71
|
+
/// purpose: 单个 agent 的 profile 冒烟
|
|
72
|
+
/// params:
|
|
73
|
+
/// agent: 单个 agent 节点,缺 provider 按 codex、缺 auth_mode 按 subscription
|
|
74
|
+
/// timeout: 单次 HTTP 探测的超时
|
|
75
|
+
/// returns: 结果 JSON。非 compatible_api 记 not_required,profile 里关掉冒烟记 skipped_by_profile,其余走真实请求
|
|
76
|
+
/// ---
|
|
36
77
|
pub(crate) fn smoke_check_agent_profile(
|
|
37
78
|
workspace: &Path,
|
|
38
79
|
agent: &YamlValue,
|
|
@@ -108,6 +149,10 @@ pub(crate) fn smoke_check_agent_profile(
|
|
|
108
149
|
result
|
|
109
150
|
}
|
|
110
151
|
|
|
152
|
+
/// ---
|
|
153
|
+
/// purpose: 把失败结果拼成一行人类可读的摘要
|
|
154
|
+
/// returns: 以分号分隔的 agent 与原因,缺字段时退化成 agent 与 failed
|
|
155
|
+
/// ---
|
|
111
156
|
pub(crate) fn format_profile_smoke_failures(failures: &[Value]) -> String {
|
|
112
157
|
failures
|
|
113
158
|
.iter()
|
|
@@ -187,7 +232,13 @@ impl SmokeTarget {
|
|
|
187
232
|
}
|
|
188
233
|
// C-7-1 cr verdict: copilot 一期 subscription-only,无 BYOK HTTP smoke
|
|
189
234
|
// 入口;同 GeminiCli/Fake 走 unsupported_provider_smoke_skipped。
|
|
190
|
-
|
|
235
|
+
// 0.5.67: grok/cursor_agent 同走 skipped (一期 subscription 已登录态)。
|
|
236
|
+
Provider::Copilot
|
|
237
|
+
| Provider::Grok
|
|
238
|
+
| Provider::CursorAgent
|
|
239
|
+
| Provider::Pi
|
|
240
|
+
| Provider::GeminiCli
|
|
241
|
+
| Provider::Fake => {
|
|
191
242
|
Err("unsupported_provider_smoke_skipped")
|
|
192
243
|
}
|
|
193
244
|
}
|
|
@@ -1,9 +1,52 @@
|
|
|
1
|
+
//! ---
|
|
2
|
+
//! purpose: 单席位的起、停与重置,全部在 workspace 级生命周期锁下串行
|
|
3
|
+
//! contract:
|
|
4
|
+
//! provides:
|
|
5
|
+
//! - name: start_agent
|
|
6
|
+
//! what: 起或复活一席,按四象限定出 resume 或 fresh
|
|
7
|
+
//! - name: stop_agent
|
|
8
|
+
//! what: 停一席,按 pane、同角色残留 pane、窗口三级收敛并取排空证据
|
|
9
|
+
//! - name: reset_agent
|
|
10
|
+
//! what: 必须显式丢弃会话,停席后换血再起
|
|
11
|
+
//! - name: start_agent_at_paths
|
|
12
|
+
//! what: 起席的实体实现,owner 门、暂停判定、启动模式决策与落 state
|
|
13
|
+
//! - name: drain_old_pane_and_pid
|
|
14
|
+
//! what: 有界轮询等旧 pane 与旧进程消失,产出可核的证据载荷
|
|
15
|
+
//! depends:
|
|
16
|
+
//! - crate::lifecycle::lock
|
|
17
|
+
//! - crate::lifecycle::restart::selection
|
|
18
|
+
//! - crate::lifecycle::restart::remove
|
|
19
|
+
//! - crate::lifecycle::restart::team_state
|
|
20
|
+
//! - crate::lifecycle::launch
|
|
21
|
+
//! - crate::state::projection
|
|
22
|
+
//! - crate::state::persist
|
|
23
|
+
//! - crate::platform::process
|
|
24
|
+
//! - crate::lifecycle::profile_launch
|
|
25
|
+
//! - crate::lifecycle::worker_command_context
|
|
26
|
+
//! - crate::event_log::EventLog
|
|
27
|
+
//! boundary:
|
|
28
|
+
//! - 每个对外入口先取 workspace 级生命周期锁,本文件不做无锁写
|
|
29
|
+
//! - owner 门先于未知席位报错,权限判定不被存在性判定绕过
|
|
30
|
+
//! - reset 未显式丢弃会话时直接拒绝,不擅自换血
|
|
31
|
+
//! - 排空是有界等待,等不到只如实记录,不无限阻塞
|
|
32
|
+
//! maturity: wired
|
|
33
|
+
//! ---
|
|
1
34
|
use super::common::*;
|
|
2
35
|
use super::selection::decide_start_mode;
|
|
3
36
|
use super::team_state::write_team_state;
|
|
4
37
|
use super::*;
|
|
5
38
|
use crate::lifecycle::lock::{acquire_agent_lifecycle_lock, LifecycleLockRequest};
|
|
6
39
|
|
|
40
|
+
/// ---
|
|
41
|
+
/// purpose: 起或复活一席的对外入口
|
|
42
|
+
/// params:
|
|
43
|
+
/// force: 窗口已存在时也重起
|
|
44
|
+
/// open_display: 是否开显示
|
|
45
|
+
/// allow_fresh: resume 依据缺失时允许改跑全新会话
|
|
46
|
+
/// returns: Running、Noop 或 Paused
|
|
47
|
+
/// errors: 选不到 team 返回 TeamSelect,owner 门不过返回 OwnerRefused,席位不存在返回 RequirementUnmet
|
|
48
|
+
/// contract_id: lifecycle.start_agent.entry
|
|
49
|
+
/// ---
|
|
7
50
|
/// `start_agent(workspace, agent_id, force, open_display, allow_fresh, team)`
|
|
8
51
|
/// (`lifecycle/start.py:72`)。`_runtime_lock("start-agent")` 下串行:resume-or-fresh
|
|
9
52
|
/// 决策、resume 窗口退出回退 fresh、起后投递 pending message、起 coordinator。
|
|
@@ -39,6 +82,12 @@ pub fn start_agent(
|
|
|
39
82
|
)
|
|
40
83
|
}
|
|
41
84
|
|
|
85
|
+
/// ---
|
|
86
|
+
/// purpose: 带注入 transport 的起席入口;未指定 team 且解析失败时退回把入参 workspace 当作两个路径
|
|
87
|
+
/// returns: Running、Noop 或 Paused
|
|
88
|
+
/// errors: 指定了 team 而解析失败时透传该错误,其余同 start_agent
|
|
89
|
+
/// contract_id: lifecycle.start_agent.entry
|
|
90
|
+
/// ---
|
|
42
91
|
/// `start_agent` with an injected transport — wires the single-worker resume/fresh spawn +
|
|
43
92
|
/// start_coordinator (rt-host-a sweep: was a stub returning RequirementUnmet at the spawn boundary).
|
|
44
93
|
#[allow(clippy::too_many_arguments)]
|
|
@@ -80,6 +129,14 @@ pub(crate) fn start_agent_with_transport(
|
|
|
80
129
|
)
|
|
81
130
|
}
|
|
82
131
|
|
|
132
|
+
/// ---
|
|
133
|
+
/// purpose: 起席的实体实现,读团队作用域 state、过 owner 门、定启动模式、spawn 并标记已起
|
|
134
|
+
/// params:
|
|
135
|
+
/// spec_workspace: spec 所在目录,用于补回席位的命令上下文
|
|
136
|
+
/// open_display: 当前实现未直接使用,仅参与自适应布局判定
|
|
137
|
+
/// returns: 席位暂停时直接返回 Paused,其余按启动模式返回 Running 或 Noop
|
|
138
|
+
/// errors: 读 state 失败返回 StatePersist,owner 门不过返回 OwnerRefused,席位不存在返回 RequirementUnmet
|
|
139
|
+
/// ---
|
|
83
140
|
#[allow(clippy::too_many_arguments)]
|
|
84
141
|
pub(crate) fn start_agent_at_paths(
|
|
85
142
|
workspace: &Path,
|
|
@@ -342,85 +399,97 @@ pub(crate) fn start_agent_at_paths(
|
|
|
342
399
|
return Err(error);
|
|
343
400
|
}
|
|
344
401
|
let actual_spawn_window = spawn.spawn.window.as_str().to_string();
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
.get("agents")
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
),
|
|
375
|
-
|
|
402
|
+
let post_spawn = (|| -> Result<bool, LifecycleError> {
|
|
403
|
+
mark_agent_started(
|
|
404
|
+
&mut state,
|
|
405
|
+
agent_id,
|
|
406
|
+
&actual_spawn_window,
|
|
407
|
+
&spawn,
|
|
408
|
+
transport,
|
|
409
|
+
&safety,
|
|
410
|
+
start_mode,
|
|
411
|
+
)?;
|
|
412
|
+
// 0.5.66 bypass 单源 §2.7:启动即带 bypass → 审计留痕。
|
|
413
|
+
if safety.enabled {
|
|
414
|
+
let state_agent = state.get("agents").and_then(|v| v.get(agent_id.as_str()));
|
|
415
|
+
let _ = crate::event_log::EventLog::new(workspace).write(
|
|
416
|
+
"worker.spawn_dangerously_skip_permissions",
|
|
417
|
+
serde_json::json!({
|
|
418
|
+
"agent_id": agent_id.as_str(),
|
|
419
|
+
"role": state_agent
|
|
420
|
+
.and_then(|a| a.get("role"))
|
|
421
|
+
.and_then(serde_json::Value::as_str)
|
|
422
|
+
.unwrap_or_default(),
|
|
423
|
+
"provider": state_agent
|
|
424
|
+
.and_then(|a| a.get("provider"))
|
|
425
|
+
.and_then(serde_json::Value::as_str)
|
|
426
|
+
.unwrap_or_default(),
|
|
427
|
+
"trigger": "start-agent",
|
|
428
|
+
"spec_source_path": crate::lifecycle::launch::agent_id_spec_source_path(
|
|
429
|
+
workspace, agent_id.as_str(),
|
|
430
|
+
),
|
|
431
|
+
}),
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
// **0.3.24 add-agent socket drift fix**: keep `state.tmux_endpoint` /
|
|
435
|
+
// `state.tmux_socket` synchronized with the transport actually used for the
|
|
436
|
+
// spawn. Without this, add-agent / fork-agent could spawn to a socket that
|
|
437
|
+
// never gets persisted, and the next coordinator tick would re-resolve to
|
|
438
|
+
// the workspace-hash socket and lose the new pane. Annotation runs inside
|
|
439
|
+
// the same `save_restart_projected_state` window — no parallel "annotate
|
|
440
|
+
// after spawn" race with coordinator and no double source of truth.
|
|
441
|
+
crate::lifecycle::launch::annotate_runtime_tmux_endpoint(&mut state, transport, workspace);
|
|
442
|
+
let team_key = restart_projection_team_key(&state, team);
|
|
443
|
+
// 0.5.32 (`.team/artifacts/restart-resumed-stale-activity-locate.md` §5):
|
|
444
|
+
// clear the matching `agent_health` observation on the new spawn cohort
|
|
445
|
+
// so five-line status summary and status --json do not surface a stale
|
|
446
|
+
// WORKING row from the pre-shutdown process. Best-effort: DB failure
|
|
447
|
+
// must not fail the start-agent path.
|
|
448
|
+
let _ = crate::db::agent_health_capture::clear_agent_health_observation(
|
|
449
|
+
workspace, &team_key, agent_id,
|
|
376
450
|
);
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
451
|
+
let skip_capture_backfill = if matches!(
|
|
452
|
+
start_mode,
|
|
453
|
+
StartMode::Fresh | StartMode::FreshAfterMissingRollout
|
|
454
|
+
) {
|
|
455
|
+
vec![agent_id.as_str()]
|
|
456
|
+
} else {
|
|
457
|
+
Vec::new()
|
|
458
|
+
};
|
|
459
|
+
save_restart_projected_state_with_capture_backfill_skip(
|
|
460
|
+
workspace,
|
|
461
|
+
&mut state,
|
|
462
|
+
&team_key,
|
|
463
|
+
&skip_capture_backfill,
|
|
464
|
+
&[agent_id.as_str()],
|
|
465
|
+
)?;
|
|
466
|
+
write_start_agent_start_event(
|
|
467
|
+
workspace,
|
|
468
|
+
agent_id,
|
|
469
|
+
&agent,
|
|
470
|
+
provider,
|
|
471
|
+
&spawn.plan,
|
|
472
|
+
start_mode,
|
|
473
|
+
&session_name,
|
|
474
|
+
&actual_spawn_window,
|
|
475
|
+
spawn_session_id,
|
|
476
|
+
tmux_start_mode_for_spawn(&spawn, into_existing_session),
|
|
477
|
+
)?;
|
|
478
|
+
replay_worker_target_missing_messages(workspace, agent_id, &team_key, &state, transport)?;
|
|
479
|
+
Ok(start_coordinator_for_workspace(workspace, Some(&team_key))?.ok)
|
|
480
|
+
})();
|
|
481
|
+
let coordinator_started = match post_spawn {
|
|
482
|
+
Ok(started) => started,
|
|
483
|
+
Err(error) => {
|
|
484
|
+
if let Err(rollback_error) = transport.kill_pane(&spawn.spawn.pane_id) {
|
|
485
|
+
return Err(LifecycleError::RequirementUnmet(format!(
|
|
486
|
+
"{error}; failed to roll back spawned pane {}: {rollback_error}",
|
|
487
|
+
spawn.spawn.pane_id.as_str()
|
|
488
|
+
)));
|
|
489
|
+
}
|
|
490
|
+
return Err(error);
|
|
491
|
+
}
|
|
402
492
|
};
|
|
403
|
-
save_restart_projected_state_with_capture_backfill_skip(
|
|
404
|
-
workspace,
|
|
405
|
-
&mut state,
|
|
406
|
-
&team_key,
|
|
407
|
-
&skip_capture_backfill,
|
|
408
|
-
&[agent_id.as_str()],
|
|
409
|
-
)?;
|
|
410
|
-
write_start_agent_start_event(
|
|
411
|
-
workspace,
|
|
412
|
-
agent_id,
|
|
413
|
-
&agent,
|
|
414
|
-
provider,
|
|
415
|
-
start_mode,
|
|
416
|
-
&session_name,
|
|
417
|
-
&actual_spawn_window,
|
|
418
|
-
spawn_session_id,
|
|
419
|
-
tmux_start_mode_for_spawn(&spawn, into_existing_session),
|
|
420
|
-
)?;
|
|
421
|
-
replay_worker_target_missing_messages(workspace, agent_id, &team_key, &state, transport)?;
|
|
422
|
-
let coordinator = start_coordinator_for_workspace(workspace, Some(&team_key))?;
|
|
423
|
-
let coordinator_started = coordinator.ok;
|
|
424
493
|
Ok(StartAgentOutcome::Running {
|
|
425
494
|
env: AgentActionEnvelope {
|
|
426
495
|
agent_id: agent_id.clone(),
|
|
@@ -788,6 +857,13 @@ fn tmux_start_mode_for_spawn(
|
|
|
788
857
|
// 0.4.6 Stage 1: reset/start clean-boundary helpers
|
|
789
858
|
// ═══════════════════════════════════════════════════════════════════════
|
|
790
859
|
|
|
860
|
+
/// ---
|
|
861
|
+
/// purpose: 有界轮询等待旧 pane 不可达且旧进程退出
|
|
862
|
+
/// params:
|
|
863
|
+
/// old_pane: 旧 pane,None 视作已死
|
|
864
|
+
/// old_pid: 旧进程号,None 视作已退出
|
|
865
|
+
/// returns: 证据载荷,含两者是否确认消失与实际等待毫秒数;到上限仍未消失也照实返回
|
|
866
|
+
/// ---
|
|
791
867
|
/// Bounded polling: wait for the old pane to become unreachable AND, when
|
|
792
868
|
/// possible, for the old pane_pid to exit. Returns a JSON evidence blob
|
|
793
869
|
/// recording the observed transition for events.
|
|
@@ -830,6 +906,10 @@ pub(super) fn drain_old_pane_and_pid(
|
|
|
830
906
|
})
|
|
831
907
|
}
|
|
832
908
|
|
|
909
|
+
/// ---
|
|
910
|
+
/// purpose: 尽力探测某进程号是否还活着
|
|
911
|
+
/// returns: 由平台层给出的判定
|
|
912
|
+
/// ---
|
|
833
913
|
/// Best-effort liveness probe for a pid.
|
|
834
914
|
///
|
|
835
915
|
/// 0.5.x Windows portability Batch 3: routes through
|
|
@@ -843,6 +923,10 @@ pub(super) fn pid_is_alive(pid: u32) -> bool {
|
|
|
843
923
|
crate::platform::process::pid_is_alive(pid)
|
|
844
924
|
}
|
|
845
925
|
|
|
926
|
+
/// ---
|
|
927
|
+
/// purpose: 从 state 里读该席位的 pane 进程号
|
|
928
|
+
/// returns: 存在且是无符号整数时返回它,否则 None
|
|
929
|
+
/// ---
|
|
846
930
|
/// Read state.agents[agent_id].pane_pid (u32) from the runtime state.
|
|
847
931
|
pub(super) fn state_pane_pid(state: &serde_json::Value, agent_id: &AgentId) -> Option<u32> {
|
|
848
932
|
state
|
|
@@ -853,6 +937,10 @@ pub(super) fn state_pane_pid(state: &serde_json::Value, agent_id: &AgentId) -> O
|
|
|
853
937
|
.map(|p| p as u32)
|
|
854
938
|
}
|
|
855
939
|
|
|
940
|
+
/// ---
|
|
941
|
+
/// purpose: 算出该席位下一次的 spawn 世代号
|
|
942
|
+
/// returns: 当前值加一,缺失时按 0 起算;世代号用于把捕获与事件归因到本次进程
|
|
943
|
+
/// ---
|
|
856
944
|
/// Read + increment state.agents[agent_id].spawn_epoch. The epoch is a
|
|
857
945
|
/// monotonic counter persisted with the agent row that uniquely tags each
|
|
858
946
|
/// fresh-start / reset / restart cycle. Subsequent capture / event /
|
|
@@ -869,6 +957,12 @@ pub(super) fn next_spawn_epoch(state: &serde_json::Value, agent_id: &AgentId) ->
|
|
|
869
957
|
current.saturating_add(1)
|
|
870
958
|
}
|
|
871
959
|
|
|
960
|
+
/// ---
|
|
961
|
+
/// purpose: 停一席的对外入口
|
|
962
|
+
/// returns: 停止报告
|
|
963
|
+
/// errors: 选不到 team 返回 TeamSelect,席位不存在返回 RequirementUnmet
|
|
964
|
+
/// contract_id: lifecycle.stop_agent.entry
|
|
965
|
+
/// ---
|
|
872
966
|
/// `stop_agent(workspace, agent_id, team)`(`lifecycle/operations.py:62`)。
|
|
873
967
|
/// owner-gate → kill window → **同时关显示** → 写 state。
|
|
874
968
|
pub fn stop_agent(
|
|
@@ -895,6 +989,12 @@ pub fn stop_agent(
|
|
|
895
989
|
)
|
|
896
990
|
}
|
|
897
991
|
|
|
992
|
+
/// ---
|
|
993
|
+
/// purpose: 带注入 transport 的停席入口
|
|
994
|
+
/// returns: 停止报告
|
|
995
|
+
/// errors: 同 stop_agent
|
|
996
|
+
/// contract_id: lifecycle.stop_agent.entry
|
|
997
|
+
/// ---
|
|
898
998
|
pub(crate) fn stop_agent_with_transport(
|
|
899
999
|
workspace: &Path,
|
|
900
1000
|
agent_id: &AgentId,
|
|
@@ -919,6 +1019,11 @@ pub(crate) fn stop_agent_with_transport(
|
|
|
919
1019
|
)
|
|
920
1020
|
}
|
|
921
1021
|
|
|
1022
|
+
/// ---
|
|
1023
|
+
/// purpose: 停席的实体实现,解析席位、收敛杀 pane 与窗口、取排空证据后落 state
|
|
1024
|
+
/// returns: 停止报告;注意报告里的显示已关闭字段恒为真,不反映实际关显示结果
|
|
1025
|
+
/// errors: 席位解析不到实体返回 RequirementUnmet,写 state 失败返回 StatePersist
|
|
1026
|
+
/// ---
|
|
922
1027
|
pub(super) fn stop_agent_at_paths(
|
|
923
1028
|
workspace: &Path,
|
|
924
1029
|
spec_workspace: &Path,
|
|
@@ -1076,6 +1181,13 @@ pub(super) fn stop_agent_at_paths(
|
|
|
1076
1181
|
})
|
|
1077
1182
|
}
|
|
1078
1183
|
|
|
1184
|
+
/// ---
|
|
1185
|
+
/// purpose: 取团队作用域的投影 state,把选择拒绝转成带原因的错误
|
|
1186
|
+
/// params:
|
|
1187
|
+
/// team: 目标团队,None 时按唯一性选
|
|
1188
|
+
/// returns: 投影后的 state
|
|
1189
|
+
/// errors: 目标歧义或选不出时返回 TeamSelect 并在消息里带原因与细节,读取失败返回 StatePersist
|
|
1190
|
+
/// ---
|
|
1079
1191
|
/// golden `resolve_team_scoped_state` (state.py:243): returns the team-scoped projected state, or
|
|
1080
1192
|
/// surfaces the refusal dict (`team_target_ambiguous` / `team_target_unresolved`) as a typed error
|
|
1081
1193
|
/// BEFORE the owner gate / unknown-worker raise (operations.py:64-66). The lifecycle return types are
|
|
@@ -1251,6 +1363,14 @@ fn mark_agent_started(
|
|
|
1251
1363
|
Ok(())
|
|
1252
1364
|
}
|
|
1253
1365
|
|
|
1366
|
+
/// ---
|
|
1367
|
+
/// purpose: 重置一席的对外入口
|
|
1368
|
+
/// params:
|
|
1369
|
+
/// discard_session: 必须为真,否则直接返回拒绝
|
|
1370
|
+
/// returns: 重置结果,未显式丢弃会话时返回 Refused
|
|
1371
|
+
/// errors: 选不到 team 返回 TeamSelect,其余透传实体实现
|
|
1372
|
+
/// contract_id: lifecycle.reset_agent.entry
|
|
1373
|
+
/// ---
|
|
1254
1374
|
/// `reset_agent(workspace, agent_id, discard_session, open_display, team)`
|
|
1255
1375
|
/// (`lifecycle/operations.py:102`)。discard + 重起;**未传 discard_session → 拒绝**。
|
|
1256
1376
|
pub fn reset_agent(
|
|
@@ -1286,6 +1406,14 @@ pub fn reset_agent(
|
|
|
1286
1406
|
)
|
|
1287
1407
|
}
|
|
1288
1408
|
|
|
1409
|
+
/// ---
|
|
1410
|
+
/// purpose: 带注入 transport 的重置入口
|
|
1411
|
+
/// params:
|
|
1412
|
+
/// discard_session: 必须为真,否则直接返回拒绝
|
|
1413
|
+
/// returns: 重置结果
|
|
1414
|
+
/// errors: 同 reset_agent
|
|
1415
|
+
/// contract_id: lifecycle.reset_agent.entry
|
|
1416
|
+
/// ---
|
|
1289
1417
|
pub(crate) fn reset_agent_with_transport(
|
|
1290
1418
|
workspace: &Path,
|
|
1291
1419
|
agent_id: &AgentId,
|
|
@@ -1656,95 +1784,13 @@ fn write_start_agent_start_event(
|
|
|
1656
1784
|
agent_id: &AgentId,
|
|
1657
1785
|
agent: &serde_json::Value,
|
|
1658
1786
|
provider: crate::provider::Provider,
|
|
1787
|
+
plan: &crate::provider::CommandPlan,
|
|
1659
1788
|
start_mode: StartMode,
|
|
1660
1789
|
session_name: &SessionName,
|
|
1661
1790
|
window: &str,
|
|
1662
1791
|
session_id: Option<&SessionId>,
|
|
1663
1792
|
tmux_start_mode: &'static str,
|
|
1664
1793
|
) -> Result<(), LifecycleError> {
|
|
1665
|
-
let auth_mode = agent_auth_mode(agent);
|
|
1666
|
-
let model = agent.get("model").and_then(|v| v.as_str());
|
|
1667
|
-
let adapter = crate::provider::get_adapter(provider);
|
|
1668
|
-
// Contract C / F6.4: event log must record the same context-aware argv that the
|
|
1669
|
-
// actual spawn used — so the role/tools/MCP context appears in `start_agent.agent_start`.
|
|
1670
|
-
let command_agent = crate::lifecycle::worker_command_context::WorkerCommandAgent::from_json(
|
|
1671
|
-
agent,
|
|
1672
|
-
Some(agent_id.as_str()),
|
|
1673
|
-
provider,
|
|
1674
|
-
)?;
|
|
1675
|
-
let system_prompt =
|
|
1676
|
-
crate::lifecycle::worker_command_context::compile_worker_system_prompt(&command_agent)?;
|
|
1677
|
-
let tools = crate::lifecycle::worker_command_context::resolved_tool_strings_for_command(
|
|
1678
|
-
&command_agent,
|
|
1679
|
-
provider,
|
|
1680
|
-
)?;
|
|
1681
|
-
let resolved_tool_refs: Vec<&str> = tools.iter().map(String::as_str).collect();
|
|
1682
|
-
let mcp_config = adapter
|
|
1683
|
-
.mcp_config(auth_mode)
|
|
1684
|
-
.map_err(|e| LifecycleError::Provider(e.to_string()))?;
|
|
1685
|
-
let team_id = agent.get("owner_team_id").and_then(|v| v.as_str());
|
|
1686
|
-
let mcp_config = crate::lifecycle::launch::resolve_mcp_config(
|
|
1687
|
-
mcp_config,
|
|
1688
|
-
workspace,
|
|
1689
|
-
agent_id.as_str(),
|
|
1690
|
-
team_id.unwrap_or(""),
|
|
1691
|
-
);
|
|
1692
|
-
let mcp_config_path = crate::lifecycle::launch::write_worker_mcp_config(
|
|
1693
|
-
workspace,
|
|
1694
|
-
agent_id.as_str(),
|
|
1695
|
-
&mcp_config,
|
|
1696
|
-
)?;
|
|
1697
|
-
let profile_launch =
|
|
1698
|
-
crate::lifecycle::profile_launch::prepare_provider_profile_launch_from_json(
|
|
1699
|
-
workspace,
|
|
1700
|
-
agent_id.as_str(),
|
|
1701
|
-
agent,
|
|
1702
|
-
Some(&mcp_config),
|
|
1703
|
-
)?;
|
|
1704
|
-
let command_model = profile_launch.command_overrides.model.as_deref().or(model);
|
|
1705
|
-
// 0.4.x provider effort MVP: start_agent path preserves effort from the
|
|
1706
|
-
// persisted agent JSON.
|
|
1707
|
-
let start_agent_effort =
|
|
1708
|
-
crate::lifecycle::launch::provider_effort_for_spawn_json(&agent, provider);
|
|
1709
|
-
if let Some(event_value) = crate::lifecycle::launch::provider_effort_event_if_dropped_json(
|
|
1710
|
-
&agent,
|
|
1711
|
-
provider,
|
|
1712
|
-
agent_id.as_str(),
|
|
1713
|
-
) {
|
|
1714
|
-
let _ = crate::event_log::EventLog::new(workspace)
|
|
1715
|
-
.write("provider.effort_unsupported", event_value);
|
|
1716
|
-
}
|
|
1717
|
-
let context = crate::provider::ProviderCommandContext {
|
|
1718
|
-
auth_mode,
|
|
1719
|
-
mcp_config: Some(&mcp_config),
|
|
1720
|
-
system_prompt: Some(system_prompt.as_str()),
|
|
1721
|
-
model: command_model,
|
|
1722
|
-
tools: &resolved_tool_refs,
|
|
1723
|
-
profile_launch: Some(&profile_launch),
|
|
1724
|
-
agent_id_hint: Some(agent_id.as_str()),
|
|
1725
|
-
effort: start_agent_effort,
|
|
1726
|
-
};
|
|
1727
|
-
let mut plan = match session_id {
|
|
1728
|
-
Some(session_id) => adapter
|
|
1729
|
-
.build_resume_command_plan(Some(session_id), context)
|
|
1730
|
-
.map_err(|e| LifecycleError::Provider(e.to_string()))?,
|
|
1731
|
-
None => adapter
|
|
1732
|
-
.build_command_plan(context)
|
|
1733
|
-
.map_err(|e| LifecycleError::Provider(e.to_string()))?,
|
|
1734
|
-
};
|
|
1735
|
-
if !plan.managed_mcp_config && !profile_launch.managed_mcp_config {
|
|
1736
|
-
crate::lifecycle::launch::point_native_mcp_config_at_file(
|
|
1737
|
-
&mut plan.argv,
|
|
1738
|
-
provider,
|
|
1739
|
-
&mcp_config_path,
|
|
1740
|
-
);
|
|
1741
|
-
}
|
|
1742
|
-
crate::lifecycle::launch::fill_spawn_placeholders_full(
|
|
1743
|
-
&mut plan.argv,
|
|
1744
|
-
workspace,
|
|
1745
|
-
agent_id.as_str(),
|
|
1746
|
-
team_id,
|
|
1747
|
-
);
|
|
1748
1794
|
crate::event_log::EventLog::new(workspace)
|
|
1749
1795
|
.write(
|
|
1750
1796
|
"start_agent.agent_start",
|
|
@@ -1783,6 +1829,14 @@ fn write_stop_complete_event(
|
|
|
1783
1829
|
Ok(())
|
|
1784
1830
|
}
|
|
1785
1831
|
|
|
1832
|
+
/// ---
|
|
1833
|
+
/// purpose: 写一条停席排空证据事件
|
|
1834
|
+
/// params:
|
|
1835
|
+
/// target: 被停的目标描述
|
|
1836
|
+
/// drain: 排空证据载荷,其字段被并进事件顶层
|
|
1837
|
+
/// returns: 成功返回空值
|
|
1838
|
+
/// errors: 事件写入失败时返回 StatePersist
|
|
1839
|
+
/// ---
|
|
1786
1840
|
/// 0.4.6 Stage 1: drain evidence for the old pane+pid after stop. Fires
|
|
1787
1841
|
/// during reset/stop so operators can see whether the prior worker really
|
|
1788
1842
|
/// went away or stuck around inside the resp budget.
|