@team-agent/installer 0.5.119 → 0.5.121
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 +1 -1
- package/Cargo.toml +1 -1
- package/README.md +46 -1
- package/README.zh.md +46 -1
- package/crates/team-agent/src/cli/adapters.rs +11 -0
- package/crates/team-agent/src/cli/arguments.rs +401 -0
- package/crates/team-agent/src/cli/emit.rs +241 -142
- package/crates/team-agent/src/cli/intent/runtime.rs +1175 -0
- package/crates/team-agent/src/cli/intent/runtime_tests.rs +698 -0
- package/crates/team-agent/src/cli/intent/tests.rs +654 -0
- package/crates/team-agent/src/cli/intent.rs +642 -0
- package/crates/team-agent/src/cli/mod.rs +53 -6
- package/crates/team-agent/src/cli/named_address.rs +10 -1
- package/crates/team-agent/src/cli/spec.rs +22 -10
- package/crates/team-agent/src/cli/status_port/brief.rs +117 -16
- package/crates/team-agent/src/cli/tests/base.rs +6 -1
- package/crates/team-agent/src/cli/tests/parser_safety.rs +383 -0
- package/crates/team-agent/src/cli/tests/run_delegation.rs +63 -19
- package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +56 -0
- package/crates/team-agent/src/cli/tests/verb_install_skill.rs +3 -2
- package/crates/team-agent/src/cli/tests/verb_profile.rs +3 -1
- package/crates/team-agent/src/contract_runtime/backend.rs +1 -1
- package/crates/team-agent/src/db/message_store.rs +65 -0
- package/crates/team-agent/src/lifecycle/launch/agent_state.rs +8 -0
- package/crates/team-agent/src/lifecycle/launch/cursor_mcp.rs +111 -4
- package/crates/team-agent/src/lifecycle/launch/cursor_mcp_iso.rs +244 -82
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +166 -77
- package/crates/team-agent/src/lifecycle/launch.rs +29 -0
- package/crates/team-agent/src/lifecycle/restart/common.rs +7 -1
- package/crates/team-agent/src/lifecycle/restart.rs +17 -0
- package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +1 -3
- package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +5 -15
- package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +2 -3
- package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +2 -3
- package/crates/team-agent/src/lifecycle/tests/cli_argv_routing_red.rs +10 -2
- package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +8 -1
- package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +3 -2
- package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +6 -9
- package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +7 -5
- package/crates/team-agent/src/lifecycle/tests/cursor_mcp_overlay.rs +64 -19
- package/crates/team-agent/src/lifecycle/tests/cursor_require_explicit_model_red.rs +5 -2
- package/crates/team-agent/src/lifecycle/tests/cursor_restart_resume_red.rs +34 -10
- package/crates/team-agent/src/lifecycle/tests/grok_effort_argv_red.rs +2 -4
- package/crates/team-agent/src/lifecycle/tests/grok_mcp_overlay_red.rs +3 -4
- package/crates/team-agent/src/lifecycle/tests/grok_require_explicit_model_red.rs +5 -4
- package/crates/team-agent/src/lifecycle/tests/grok_restart_resume_red.rs +2 -4
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +78 -36
- package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +8 -4
- package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +6 -12
- package/crates/team-agent/src/lifecycle/tests/pi_fork_session_inheritance_red.rs +4 -0
- package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +1 -3
- package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +7 -0
- package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +47 -4
- package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +1 -3
- package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +2 -1
- package/crates/team-agent/src/lifecycle/types.rs +10 -0
- package/crates/team-agent/src/mcp_server/mod.rs +2 -0
- package/crates/team-agent/src/mcp_server/readiness.rs +432 -0
- package/crates/team-agent/src/mcp_server/readiness_tests.rs +242 -0
- package/crates/team-agent/src/mcp_server/wire.rs +96 -11
- package/crates/team-agent/src/messaging/delivery.rs +62 -0
- package/crates/team-agent/src/messaging/tests/dup_inject.rs +41 -1
- package/crates/team-agent/src/provider/adapter.rs +7 -0
- package/crates/team-agent/src/tmux_backend/tests.rs +37 -0
- package/crates/team-agent/src/tmux_backend.rs +8 -1
- package/package.json +4 -4
- package/skills/team-agent/SKILL.md +71 -54
- package/skills/team-agent/command-coverage.json +283 -13
- package/skills/team-agent/docs/reference/team-agent-operator.md +220 -0
- package/skills/team-agent/references/bug-as-artifact-flow.md +1 -1
- package/skills/team-agent/references/recovery-runbook.md +61 -212
- package/skills/team-agent/references/team-agent-operator.md +181 -48
- package/skills/team-agent/references/team-in-team.md +47 -80
|
@@ -32,7 +32,7 @@ fn enter_hermetic(tag: &str) -> hermetic_guard::HermeticTestEnv {
|
|
|
32
32
|
#[test]
|
|
33
33
|
#[serial_test::serial(env)]
|
|
34
34
|
fn concurrent_reset_discard_session_serializes() {
|
|
35
|
-
let _hermetic =
|
|
35
|
+
let _hermetic = hermetic_guard::HermeticTestEnv::enter_with_leader("phase-b-concurrent-reset");
|
|
36
36
|
let ids = (1..=6).map(|n| format!("w{n}")).collect::<Vec<_>>();
|
|
37
37
|
let role_docs = ids
|
|
38
38
|
.iter()
|
|
@@ -139,7 +139,7 @@ fn concurrent_reset_discard_session_serializes() {
|
|
|
139
139
|
#[test]
|
|
140
140
|
#[serial_test::serial(env)]
|
|
141
141
|
fn add_fork_remove_share_lifecycle_lock_behavior() {
|
|
142
|
-
let _hermetic =
|
|
142
|
+
let _hermetic = hermetic_guard::HermeticTestEnv::enter_with_leader("phase-b-fork");
|
|
143
143
|
let _home = LaneHomeGuard::enter("phase-b-fork");
|
|
144
144
|
let (add_team, add_workspace, add_role, add_transport) = add_fixture();
|
|
145
145
|
let add_agent = aid("w2");
|
|
@@ -324,7 +324,7 @@ fn add_fork_remove_share_lifecycle_lock_behavior() {
|
|
|
324
324
|
#[test]
|
|
325
325
|
#[serial_test::serial(env)]
|
|
326
326
|
fn breal_spawn_ownership_mismatch_fails_without_state_pollution() {
|
|
327
|
-
let _hermetic =
|
|
327
|
+
let _hermetic = hermetic_guard::HermeticTestEnv::enter_with_leader("phase-b-spawn-ownership");
|
|
328
328
|
let (workspace, _team) = breal_workspace();
|
|
329
329
|
let transport = BRealTransport::misowned();
|
|
330
330
|
|
|
@@ -366,7 +366,9 @@ fn breal_spawn_ownership_mismatch_fails_without_state_pollution() {
|
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
#[test]
|
|
369
|
+
#[serial_test::serial(env)]
|
|
369
370
|
fn breal_provider_missing_window_disappeared_fails_closed() {
|
|
371
|
+
let _hermetic = hermetic_guard::HermeticTestEnv::enter_with_leader("phase-b-missing-window");
|
|
370
372
|
let (workspace, _team) = breal_workspace();
|
|
371
373
|
let transport = BRealTransport::dead_after_spawn();
|
|
372
374
|
|
|
@@ -404,7 +406,9 @@ fn breal_provider_missing_window_disappeared_fails_closed() {
|
|
|
404
406
|
}
|
|
405
407
|
|
|
406
408
|
#[test]
|
|
409
|
+
#[serial_test::serial(env)]
|
|
407
410
|
fn breal_reset_rehydrates_role_context_from_compiled_spec() {
|
|
411
|
+
let _hermetic = hermetic_guard::HermeticTestEnv::enter_with_leader("phase-b-reset-context");
|
|
408
412
|
let (workspace, _team) = breal_workspace();
|
|
409
413
|
strip_runtime_command_context(&workspace);
|
|
410
414
|
let transport = BRealTransport::owned();
|
|
@@ -438,7 +442,7 @@ fn breal_reset_rehydrates_role_context_from_compiled_spec() {
|
|
|
438
442
|
#[test]
|
|
439
443
|
#[serial_test::serial(env)]
|
|
440
444
|
fn breal_restart_rehydrates_role_context_from_compiled_spec() {
|
|
441
|
-
let _hermetic =
|
|
445
|
+
let _hermetic = hermetic_guard::HermeticTestEnv::enter_with_leader("phase-b-restart-role-context");
|
|
442
446
|
let (workspace, _team) = breal_one_worker_workspace();
|
|
443
447
|
strip_runtime_command_context(&workspace);
|
|
444
448
|
let transport = BRealTransport::owned();
|
|
@@ -94,8 +94,8 @@ fn hermetic_caller_envs() -> &'static [&'static str] {
|
|
|
94
94
|
|
|
95
95
|
#[test]
|
|
96
96
|
#[serial_test::serial(env)]
|
|
97
|
-
fn
|
|
98
|
-
let diagnose =
|
|
97
|
+
fn phase_golden_missing_registry_requires_index_publication_not_claim() {
|
|
98
|
+
let diagnose = run_diagnose_after_unbound_state_fixture();
|
|
99
99
|
let issues = diagnose
|
|
100
100
|
.get("issues")
|
|
101
101
|
.and_then(Value::as_array)
|
|
@@ -177,22 +177,16 @@ fn cmd_value(result: Result<CmdResult, crate::cli::CliError>) -> Value {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
fn
|
|
180
|
+
fn run_diagnose_after_unbound_state_fixture() -> Value {
|
|
181
181
|
let hermetic = HermeticTestEnv::enter("tombstone-claim-leader");
|
|
182
182
|
let _permission_mode = EnvVarGuard::set(ANCESTRY_ENV, "[]");
|
|
183
183
|
let team = two_worker_team_dir(&hermetic);
|
|
184
184
|
let workspace = team.parent().expect("workspace").to_path_buf();
|
|
185
185
|
seed_healthy_coordinator(&workspace);
|
|
186
186
|
let launch_transport = codex_ready_transport();
|
|
187
|
-
|
|
188
|
-
&workspace,
|
|
189
|
-
|
|
190
|
-
None,
|
|
191
|
-
true,
|
|
192
|
-
None,
|
|
193
|
-
&launch_transport,
|
|
194
|
-
)
|
|
195
|
-
.expect("tombstone fixture must quick-start");
|
|
187
|
+
crate::lifecycle::launch::materialize_unbound_state_for_test(
|
|
188
|
+
&workspace, &team, "teamdir", &launch_transport,
|
|
189
|
+
).expect("materialize the recording-only tombstone fixture, not a callerless public start");
|
|
196
190
|
let mut state = crate::state::persist::load_runtime_state(&workspace)
|
|
197
191
|
.expect("tombstone fixture must persist runtime state");
|
|
198
192
|
crate::lifecycle::launch::seed_launched_owner_from_caller_with_provider_lookup(
|
|
@@ -90,6 +90,7 @@ impl Drop for PathEnvGuard {
|
|
|
90
90
|
struct Fixture {
|
|
91
91
|
#[cfg(unix)]
|
|
92
92
|
_path_guard: PathEnvGuard,
|
|
93
|
+
_caller: hermetic_guard::HermeticTestEnv,
|
|
93
94
|
root: PathBuf,
|
|
94
95
|
team_dir: PathBuf,
|
|
95
96
|
run_workspace: PathBuf,
|
|
@@ -103,6 +104,7 @@ struct Fixture {
|
|
|
103
104
|
|
|
104
105
|
impl Fixture {
|
|
105
106
|
fn new() -> Self {
|
|
107
|
+
let caller = hermetic_guard::HermeticTestEnv::enter_with_leader("pi-fork-owned-caller");
|
|
106
108
|
let root = super::temp_ws();
|
|
107
109
|
#[cfg(unix)]
|
|
108
110
|
let path_guard = PathEnvGuard::with_fake_pi(&root);
|
|
@@ -122,6 +124,7 @@ impl Fixture {
|
|
|
122
124
|
)
|
|
123
125
|
.expect("write referenced profile");
|
|
124
126
|
|
|
127
|
+
super::launch_spawn::seed_healthy_coordinator(&root);
|
|
125
128
|
let setup = team_agent::lifecycle::launch::quick_start_with_transport(
|
|
126
129
|
&team_dir,
|
|
127
130
|
None,
|
|
@@ -198,6 +201,7 @@ impl Fixture {
|
|
|
198
201
|
let fixture = Self {
|
|
199
202
|
#[cfg(unix)]
|
|
200
203
|
_path_guard: path_guard,
|
|
204
|
+
_caller: caller,
|
|
201
205
|
root,
|
|
202
206
|
team_dir,
|
|
203
207
|
run_workspace,
|
|
@@ -468,9 +468,7 @@ struct LaunchLatencyCase {
|
|
|
468
468
|
|
|
469
469
|
impl LaunchLatencyCase {
|
|
470
470
|
fn new(tag: &str, workers: usize) -> Self {
|
|
471
|
-
let env = hermetic_guard::HermeticTestEnv::
|
|
472
|
-
env.scrub_tmux();
|
|
473
|
-
env.assert_no_real_tmux();
|
|
471
|
+
let env = hermetic_guard::HermeticTestEnv::enter_with_leader(tag);
|
|
474
472
|
let workspace = env.workspace(tag);
|
|
475
473
|
let team_dir = workspace.join("teamdir");
|
|
476
474
|
fs::create_dir_all(&team_dir).expect("create launch team dir");
|
|
@@ -355,6 +355,13 @@ fn red6_cli_restart_reports_and_top_level_error_logs_are_redacted() {
|
|
|
355
355
|
combined.push_str(&String::from_utf8_lossy(&output.stdout));
|
|
356
356
|
combined.push_str(&String::from_utf8_lossy(&output.stderr));
|
|
357
357
|
}
|
|
358
|
+
assert!(read_cli_error_logs(&workspace).is_empty(),
|
|
359
|
+
"invalid profile syntax must not create a runtime diagnostic log");
|
|
360
|
+
// Keep the original physical-log redaction assertion on the same actual
|
|
361
|
+
// runtime-error emitter, separately from the new zero-log Usage boundary.
|
|
362
|
+
assert_eq!(crate::cli::emit::__test_runtime_error_emitter(
|
|
363
|
+
"restart", &workspace, &crate::cli::CliError::Runtime(diagnostic.clone())
|
|
364
|
+
), crate::cli::ExitCode::Error);
|
|
358
365
|
let logs = read_cli_error_logs(&workspace);
|
|
359
366
|
let output_safe = !combined.contains(&marker) && combined.contains(REDACTED);
|
|
360
367
|
let logs_safe = !logs.contains(&marker) && logs.contains(REDACTED);
|
|
@@ -720,8 +720,12 @@ fn contract_b_step2_retry_delivers_queued_message_after_startup_trust_is_handled
|
|
|
720
720
|
let ws = tmp_dir("b-step2-trust-retry");
|
|
721
721
|
let mcp_config = ws.join(".team").join("runtime").join("mcp").join("w1.json");
|
|
722
722
|
std::fs::create_dir_all(mcp_config.parent().unwrap()).unwrap();
|
|
723
|
-
|
|
724
|
-
|
|
723
|
+
// This worker genuinely depends on MCP. Bind the controlled receipt to the
|
|
724
|
+
// live test carrier rather than bypassing readiness with an empty config.
|
|
725
|
+
let owner = "subprep-trust-retry";
|
|
726
|
+
let mut state = json!({
|
|
727
|
+
"team_key": owner,
|
|
728
|
+
"active_team_key": owner,
|
|
725
729
|
"session_name": "team-ta-subroot-SUB-PROBE-2-send-turn-idle",
|
|
726
730
|
"team_dir": ws.join("teamdir").to_string_lossy().to_string(),
|
|
727
731
|
"agents": {
|
|
@@ -736,6 +740,21 @@ fn contract_b_step2_retry_delivers_queued_message_after_startup_trust_is_handled
|
|
|
736
740
|
}
|
|
737
741
|
}
|
|
738
742
|
});
|
|
743
|
+
#[cfg(unix)]
|
|
744
|
+
let carrier = {
|
|
745
|
+
let carrier = crate::mcp_server::readiness::test_carrier_pid().unwrap();
|
|
746
|
+
state["agents"]["w1"]["pane_pid"] = json!(carrier);
|
|
747
|
+
state["agents"]["w1"]["spawned_at"] =
|
|
748
|
+
json!((chrono::Utc::now() - chrono::Duration::seconds(10)).to_rfc3339());
|
|
749
|
+
carrier
|
|
750
|
+
};
|
|
751
|
+
state["teams"] = json!({owner: state.clone()});
|
|
752
|
+
std::fs::write(&mcp_config, serde_json::to_vec(&json!({
|
|
753
|
+
"mcpServers": {"team_orchestrator": {
|
|
754
|
+
"command": std::env::current_exe().unwrap().canonicalize().unwrap(),
|
|
755
|
+
"env": {"TEAM_AGENT_WORKSPACE": ws.to_path_buf(), "TEAM_AGENT_ID": "w1", "TEAM_AGENT_OWNER_TEAM_ID": owner}
|
|
756
|
+
}}
|
|
757
|
+
})).unwrap()).unwrap();
|
|
739
758
|
team_agent::state::persist::save_runtime_state(&ws, &state).unwrap();
|
|
740
759
|
|
|
741
760
|
let store = MessageStore::open(&ws).unwrap();
|
|
@@ -748,7 +767,7 @@ fn contract_b_step2_retry_delivers_queued_message_after_startup_trust_is_handled
|
|
|
748
767
|
"SUB step2 probe: reply with one sentence and call report_result exactly once.",
|
|
749
768
|
None,
|
|
750
769
|
true,
|
|
751
|
-
|
|
770
|
+
Some(owner),
|
|
752
771
|
)
|
|
753
772
|
.unwrap();
|
|
754
773
|
let transport = RecordingTransport::new(vec![
|
|
@@ -759,6 +778,10 @@ fn contract_b_step2_retry_delivers_queued_message_after_startup_trust_is_handled
|
|
|
759
778
|
])
|
|
760
779
|
.with_session_present(true)
|
|
761
780
|
.with_windows(vec![WindowName::new("w1")]);
|
|
781
|
+
#[cfg(unix)]
|
|
782
|
+
{
|
|
783
|
+
transport.state.lock().unwrap().carrier = Some(carrier);
|
|
784
|
+
}
|
|
762
785
|
let event_log = EventLog::new(&ws);
|
|
763
786
|
|
|
764
787
|
let deferred =
|
|
@@ -787,6 +810,13 @@ fn contract_b_step2_retry_delivers_queued_message_after_startup_trust_is_handled
|
|
|
787
810
|
"fixture sanity: delivery defer must be observable as delivery.deferred_startup_prompt"
|
|
788
811
|
);
|
|
789
812
|
|
|
813
|
+
// No receipt existed during the actionable trust prompt. Once startup
|
|
814
|
+
// control can progress, model the successful live helper handshake before
|
|
815
|
+
// the coordinator retries this SAME queued row.
|
|
816
|
+
#[cfg(unix)]
|
|
817
|
+
{
|
|
818
|
+
crate::mcp_server::readiness::publish(&ws, owner, "w1", chrono::Utc::now()).unwrap();
|
|
819
|
+
}
|
|
790
820
|
let coord = Coordinator::new(
|
|
791
821
|
WorkspacePath::new(ws.to_path_buf()),
|
|
792
822
|
Box::new(RealAdapterRegistry),
|
|
@@ -1045,6 +1075,7 @@ struct TransportState {
|
|
|
1045
1075
|
session_present: bool,
|
|
1046
1076
|
windows: Vec<WindowName>,
|
|
1047
1077
|
spawn_argv: Vec<Vec<String>>,
|
|
1078
|
+
carrier: Option<u32>,
|
|
1048
1079
|
}
|
|
1049
1080
|
|
|
1050
1081
|
#[derive(Debug, Clone)]
|
|
@@ -1189,7 +1220,19 @@ impl Transport for RecordingTransport {
|
|
|
1189
1220
|
}
|
|
1190
1221
|
|
|
1191
1222
|
fn list_targets(&self) -> Result<Vec<PaneInfo>, TransportError> {
|
|
1192
|
-
Ok(
|
|
1223
|
+
Ok(self.state.lock().unwrap().carrier.map(|carrier| PaneInfo {
|
|
1224
|
+
pane_id: PaneId::new("%7"),
|
|
1225
|
+
session: SessionName::new("team-ta-subroot-SUB-PROBE-2-send-turn-idle"),
|
|
1226
|
+
window_index: None,
|
|
1227
|
+
window_name: Some(WindowName::new("w1")),
|
|
1228
|
+
pane_index: None,
|
|
1229
|
+
tty: None,
|
|
1230
|
+
current_command: None,
|
|
1231
|
+
current_path: None,
|
|
1232
|
+
active: true,
|
|
1233
|
+
pane_pid: Some(carrier),
|
|
1234
|
+
leader_env: BTreeMap::new(),
|
|
1235
|
+
}).into_iter().collect())
|
|
1193
1236
|
}
|
|
1194
1237
|
|
|
1195
1238
|
fn has_session(&self, _session: &SessionName) -> Result<bool, TransportError> {
|
|
@@ -35,10 +35,8 @@ use team_agent::transport::{
|
|
|
35
35
|
#[test]
|
|
36
36
|
#[serial(env)]
|
|
37
37
|
fn quick_start_team_id_persists_requested_team_key_for_lifecycle_selection() {
|
|
38
|
-
let hermetic = hermetic_guard::HermeticTestEnv::enter("team-in-team-requested-key");
|
|
39
|
-
hermetic.scrub_tmux();
|
|
40
|
-
hermetic.assert_no_real_tmux();
|
|
41
38
|
let _env = EnvGuard::unset();
|
|
39
|
+
let _hermetic = hermetic_guard::HermeticTestEnv::enter_with_leader("team-in-team-requested-key");
|
|
42
40
|
let root = tmp_dir("team-id-key");
|
|
43
41
|
seed_healthy_coordinator(&root);
|
|
44
42
|
let team_dir = write_team_dir(&root, "teamdir", "w1");
|
|
@@ -46,8 +46,9 @@ const CLAUDE_ROLE: &str = "---\nname: clauder\nrole: Claude Worker\nprovider: cl
|
|
|
46
46
|
#[test]
|
|
47
47
|
#[serial(env)]
|
|
48
48
|
fn worker_mcp_owner_team_scope_must_match_runtime_team_key_not_spec_name() {
|
|
49
|
-
let hermetic = HermeticTestEnv::
|
|
49
|
+
let hermetic = HermeticTestEnv::enter_with_leader("rs031-mcp-owner-scope");
|
|
50
50
|
let team = mixed_provider_team_dir(&hermetic, "mcp-owner-scope");
|
|
51
|
+
super::launch_spawn::seed_healthy_coordinator(team.parent().unwrap());
|
|
51
52
|
let transport = RecordingTransport::new()
|
|
52
53
|
.with_windows(vec![WindowName::new("clauder"), WindowName::new("codexer")]);
|
|
53
54
|
let launch = ready_launch(
|
|
@@ -512,6 +512,16 @@ pub enum QuickStartReport {
|
|
|
512
512
|
worker_readiness: QuickStartReadiness,
|
|
513
513
|
team: String,
|
|
514
514
|
},
|
|
515
|
+
/// Workers may exist, but post-spawn admission/coordinator completion failed.
|
|
516
|
+
/// Preserve confirmed effects; never disguise this as a preflight refusal.
|
|
517
|
+
Partial {
|
|
518
|
+
workspace: PathBuf,
|
|
519
|
+
session_name: SessionName,
|
|
520
|
+
launch: Box<LaunchReport>,
|
|
521
|
+
team: String,
|
|
522
|
+
error: String,
|
|
523
|
+
coordinator_state: String,
|
|
524
|
+
},
|
|
515
525
|
/// 已有 runtime state → quick-start 拒绝并引导用 restart。
|
|
516
526
|
ExistingRuntime {
|
|
517
527
|
team: Option<String>,
|