@team-agent/installer 0.5.61 → 0.5.63
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/crates/team-agent/src/cli/adapters.rs +5 -2
- package/crates/team-agent/src/cli/attach_app_server_leader.rs +1 -0
- package/crates/team-agent/src/cli/diagnose.rs +1 -0
- package/crates/team-agent/src/cli/emit.rs +41 -7
- package/crates/team-agent/src/cli/helpers.rs +1 -0
- package/crates/team-agent/src/cli/leader.rs +6 -1
- package/crates/team-agent/src/cli/leaders.rs +2 -0
- package/crates/team-agent/src/cli/mod.rs +33 -3
- package/crates/team-agent/src/cli/named_address.rs +8 -1
- package/crates/team-agent/src/cli/profile.rs +2 -1
- package/crates/team-agent/src/cli/send/coordinator.rs +1 -0
- package/crates/team-agent/src/cli/send/mailbox.rs +3 -0
- package/crates/team-agent/src/cli/send/persist.rs +1 -0
- package/crates/team-agent/src/cli/send/presentation.rs +1 -0
- package/crates/team-agent/src/cli/send/resolve.rs +206 -1
- package/crates/team-agent/src/cli/send.rs +2 -1
- package/crates/team-agent/src/cli/spec.rs +1 -0
- package/crates/team-agent/src/cli/status.rs +2 -1
- package/crates/team-agent/src/cli/status_port/compact.rs +1 -0
- package/crates/team-agent/src/cli/status_port/format.rs +1 -0
- package/crates/team-agent/src/cli/status_port/inbox.rs +1 -0
- package/crates/team-agent/src/cli/tests/verb_profile.rs +38 -0
- package/crates/team-agent/src/cli/types.rs +3 -2
- package/crates/team-agent/src/communication_mode/mod.rs +1 -0
- package/crates/team-agent/src/compiler.rs +1 -0
- package/crates/team-agent/src/conpty/backend.rs +1 -0
- package/crates/team-agent/src/conpty/mod.rs +1 -0
- package/crates/team-agent/src/coordinator/backoff.rs +5 -8
- package/crates/team-agent/src/coordinator/conpty_shim.rs +3 -2
- package/crates/team-agent/src/coordinator/health.rs +1 -0
- package/crates/team-agent/src/coordinator/mod.rs +2 -2
- package/crates/team-agent/src/coordinator/orphan.rs +4 -116
- package/crates/team-agent/src/coordinator/runtime_detectors.rs +1 -0
- package/crates/team-agent/src/coordinator/runtime_observation.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/abnormal.rs +15 -866
- package/crates/team-agent/src/coordinator/steps/delivery.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/health_sync.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/mod.rs +2 -0
- package/crates/team-agent/src/coordinator/steps/persist.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/runtime_prompts.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/session_gate.rs +1 -0
- package/crates/team-agent/src/coordinator/tests/abnormal.rs +0 -174
- package/crates/team-agent/src/coordinator/tests/api_error_recovery.rs +139 -375
- package/crates/team-agent/src/coordinator/tests/basics.rs +0 -184
- package/crates/team-agent/src/coordinator/tests/mod.rs +2 -17
- package/crates/team-agent/src/coordinator/tests/tick_core.rs +0 -49
- package/crates/team-agent/src/coordinator/tick.rs +23 -40
- package/crates/team-agent/src/coordinator/types.rs +3 -176
- package/crates/team-agent/src/db/agent_health_capture.rs +1 -0
- package/crates/team-agent/src/db/message_store.rs +2 -1
- package/crates/team-agent/src/db/migration.rs +5 -4
- package/crates/team-agent/src/db/mod.rs +1 -0
- package/crates/team-agent/src/db/schema.rs +1 -0
- package/crates/team-agent/src/diagnose/comms.rs +2 -1
- package/crates/team-agent/src/diagnose/mod.rs +1 -0
- package/crates/team-agent/src/diagnose/orphans.rs +1 -0
- package/crates/team-agent/src/layout/manager.rs +3 -7
- package/crates/team-agent/src/layout/mod.rs +2 -2
- package/crates/team-agent/src/layout/overlay.rs +6 -1
- package/crates/team-agent/src/layout/placement.rs +1 -0
- package/crates/team-agent/src/layout/recovery.rs +3 -0
- package/crates/team-agent/src/layout/runtime_sessions.rs +8 -3
- package/crates/team-agent/src/layout/sessions.rs +8 -1
- package/crates/team-agent/src/layout/tmux_endpoint.rs +3 -0
- package/crates/team-agent/src/layout/worker_env.rs +3 -0
- package/crates/team-agent/src/layout/worker_window_helpers.rs +2 -0
- package/crates/team-agent/src/leader/helpers.rs +1 -0
- package/crates/team-agent/src/leader/incident.rs +1 -0
- package/crates/team-agent/src/leader/lease.rs +27 -22
- package/crates/team-agent/src/leader/mod.rs +2 -3
- package/crates/team-agent/src/leader/owner_bind.rs +13 -3
- package/crates/team-agent/src/leader/provider_attribution.rs +1 -0
- package/crates/team-agent/src/leader/rediscover.rs +4 -17
- package/crates/team-agent/src/leader/registry.rs +3 -15
- package/crates/team-agent/src/leader/start.rs +373 -125
- package/crates/team-agent/src/leader/takeover.rs +10 -232
- package/crates/team-agent/src/leader/tests/claim_leader_mailbox_flush_contract.rs +544 -0
- package/crates/team-agent/src/leader/tests/historical_inventory_upgrade_gate_red.rs +624 -0
- package/crates/team-agent/src/leader/tests/identity.rs +7 -2
- package/crates/team-agent/src/leader/tests/idle.rs +0 -193
- package/crates/team-agent/src/leader/tests/lease_api.rs +0 -45
- package/crates/team-agent/src/leader/tests/mod.rs +4 -41
- package/crates/team-agent/src/leader/tests/rehomed_env.rs +83 -0
- package/crates/team-agent/src/leader/tests/team_in_team_state_scope_red.rs +1273 -0
- package/crates/team-agent/src/leader/tests/terminal_and_replay_vs_rerender_invariants_red.rs +417 -0
- package/crates/team-agent/src/leader/tests/wake_start_owner.rs +22 -103
- package/crates/team-agent/src/leader/types.rs +1 -28
- package/crates/team-agent/src/lib.rs +3 -0
- package/crates/team-agent/src/lifecycle/display.rs +7 -1
- package/crates/team-agent/src/lifecycle/helpers.rs +3 -1
- package/crates/team-agent/src/lifecycle/launch/add_agent.rs +2 -2
- package/crates/team-agent/src/lifecycle/launch/fork_agent/completion.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch/fork_entry.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch/plan.rs +2 -2
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +4 -26
- package/crates/team-agent/src/lifecycle/launch/readiness.rs +0 -27
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +1 -27
- package/crates/team-agent/src/lifecycle/launch/spec_state.rs +4 -32
- package/crates/team-agent/src/lifecycle/launch/state_projection.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch.rs +11 -12
- package/crates/team-agent/src/lifecycle/mod.rs +2 -1
- package/crates/team-agent/src/lifecycle/restart/agent.rs +3 -66
- package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +2 -2
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +13 -5
- package/crates/team-agent/src/lifecycle/restart/remove.rs +1 -1
- package/crates/team-agent/src/lifecycle/restart/selection.rs +3 -3
- package/crates/team-agent/src/lifecycle/restart.rs +13 -15
- package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +1007 -0
- package/crates/team-agent/src/lifecycle/tests/b0_legacy_snapshot_nonauthority_contract.rs +265 -0
- package/crates/team-agent/src/lifecycle/tests/b0_reader_hideone_audit_contract.rs +459 -0
- package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +849 -0
- package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +323 -0
- package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +423 -0
- package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +737 -0
- package/crates/team-agent/src/lifecycle/tests/codex_mcp_approval_inheritance_red.rs +1187 -0
- package/crates/team-agent/src/lifecycle/tests/codex_weak_window_attribution_red.rs +683 -0
- package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +394 -0
- package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +1856 -0
- package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +917 -0
- package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +481 -0
- package/crates/team-agent/src/lifecycle/tests/f032_startup_prompt_best_effort_red.rs +301 -0
- package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +516 -0
- package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +986 -0
- package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +651 -0
- package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +2 -0
- package/crates/team-agent/src/lifecycle/tests/quick_start_worker_readiness_red.rs +332 -0
- package/crates/team-agent/src/lifecycle/tests/realmachine_clusters_1_6_red.rs +846 -0
- package/crates/team-agent/src/lifecycle/tests/realmachine_residual_g1_g4_red.rs +648 -0
- package/crates/team-agent/src/lifecycle/tests/restart_build_before_destroy_0540_contract.rs +910 -0
- package/crates/team-agent/src/lifecycle/tests/restart_liveness_red.rs +630 -0
- package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +1083 -0
- package/crates/team-agent/src/lifecycle/tests/restart_session_capture_red.rs +1677 -0
- package/crates/team-agent/src/lifecycle/tests/resume_recover_red.rs +410 -0
- package/crates/team-agent/src/lifecycle/tests/stale_team_saveconflict_contract.rs +428 -0
- package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +1032 -0
- package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +869 -0
- package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +1249 -0
- package/crates/team-agent/src/lifecycle/tests/swallow_batch4_semantics_red.rs +342 -0
- package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +542 -0
- package/crates/team-agent/src/lifecycle/tests/team_in_team_sibling_quick_start_red.rs +1103 -0
- package/crates/team-agent/src/lifecycle/tests/team_in_team_state_scope_red.rs +1276 -0
- package/crates/team-agent/src/lifecycle/tests/team_key_retirement_roster_red.rs +145 -0
- package/crates/team-agent/src/lifecycle/tests/team_key_retirement_txn_red.rs +603 -0
- package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +837 -0
- package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +928 -0
- package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +951 -0
- package/crates/team-agent/src/lifecycle/tests/worker_dangerous_bypass_argv_red.rs +327 -0
- package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +760 -0
- package/crates/team-agent/src/lifecycle/tests.rs +59 -0
- package/crates/team-agent/src/lifecycle/types.rs +0 -9
- package/crates/team-agent/src/mcp_server/helpers.rs +1 -0
- package/crates/team-agent/src/mcp_server/lifecycle_tools/mod.rs +1 -0
- package/crates/team-agent/src/mcp_server/lifecycle_tools/state_status.rs +1 -0
- package/crates/team-agent/src/mcp_server/mod.rs +1 -0
- package/crates/team-agent/src/mcp_server/normalize.rs +4 -3
- package/crates/team-agent/src/mcp_server/tools.rs +1 -0
- package/crates/team-agent/src/mcp_server/types.rs +1 -18
- package/crates/team-agent/src/mcp_server/wire.rs +5 -5
- package/crates/team-agent/src/messaging/activity.rs +1 -0
- package/crates/team-agent/src/messaging/address.rs +1 -0
- package/crates/team-agent/src/messaging/delivery.rs +4 -3
- package/crates/team-agent/src/messaging/helpers.rs +2 -1
- package/crates/team-agent/src/messaging/leader_channel.rs +1 -0
- package/crates/team-agent/src/messaging/leader_receiver.rs +2 -1
- package/crates/team-agent/src/messaging/mod.rs +10 -14
- package/crates/team-agent/src/messaging/peers.rs +2 -0
- package/crates/team-agent/src/messaging/persist.rs +3 -1
- package/crates/team-agent/src/messaging/presentation.rs +2 -1
- package/crates/team-agent/src/messaging/results.rs +1 -0
- package/crates/team-agent/src/messaging/scheduler.rs +1 -0
- package/crates/team-agent/src/messaging/selftest.rs +1 -1
- package/crates/team-agent/src/messaging/send.rs +41 -8
- package/crates/team-agent/src/messaging/tests/mod.rs +5 -0
- package/crates/team-agent/src/messaging/types.rs +2 -2
- package/crates/team-agent/src/messaging/watchers.rs +19 -13
- package/crates/team-agent/src/model/enums.rs +1 -0
- package/crates/team-agent/src/model/errors.rs +1 -0
- package/crates/team-agent/src/model/ids.rs +1 -0
- package/crates/team-agent/src/model/mod.rs +1 -0
- package/crates/team-agent/src/model/name_similarity.rs +1 -0
- package/crates/team-agent/src/model/pane_authority_refusal.rs +1 -0
- package/crates/team-agent/src/model/paths.rs +1 -0
- package/crates/team-agent/src/model/permissions.rs +3 -2
- package/crates/team-agent/src/model/routing.rs +1 -0
- package/crates/team-agent/src/model/spec.rs +1 -0
- package/crates/team-agent/src/model/task_graph.rs +1 -0
- package/crates/team-agent/src/model/yaml/tests.rs +1 -0
- package/crates/team-agent/src/model/yaml.rs +1 -0
- package/crates/team-agent/src/packaging/install.rs +9 -147
- package/crates/team-agent/src/packaging/migrate.rs +2 -0
- package/crates/team-agent/src/packaging/mod.rs +1 -0
- package/crates/team-agent/src/packaging/repair.rs +2 -0
- package/crates/team-agent/src/packaging/tests.rs +29 -218
- package/crates/team-agent/src/packaging/types.rs +8 -15
- package/crates/team-agent/src/platform/argv.rs +4 -0
- package/crates/team-agent/src/platform/errors.rs +10 -1
- package/crates/team-agent/src/platform/file_lock.rs +4 -157
- package/crates/team-agent/src/platform/mod.rs +0 -61
- package/crates/team-agent/src/platform/process.rs +1 -0
- package/crates/team-agent/src/provider/adapter.rs +1 -0
- package/crates/team-agent/src/provider/adapters/claude.rs +1 -0
- package/crates/team-agent/src/provider/adapters/claude_fork.rs +1 -0
- package/crates/team-agent/src/provider/adapters/codex.rs +1 -0
- package/crates/team-agent/src/provider/adapters/copilot.rs +1 -0
- package/crates/team-agent/src/provider/adapters/copilot_fork.rs +1 -0
- package/crates/team-agent/src/provider/adapters/fake.rs +1 -0
- package/crates/team-agent/src/provider/adapters/mod.rs +1 -0
- package/crates/team-agent/src/provider/approvals/mod.rs +1 -0
- package/crates/team-agent/src/provider/approvals/parsing.rs +2 -5
- package/crates/team-agent/src/provider/approvals/runtime_prompts.rs +6 -5
- package/crates/team-agent/src/provider/classify.rs +1 -0
- package/crates/team-agent/src/provider/faults.rs +1 -26
- package/crates/team-agent/src/provider/helpers.rs +1 -0
- package/crates/team-agent/src/provider/mod.rs +1 -1
- package/crates/team-agent/src/provider/session/capture.rs +1 -4
- package/crates/team-agent/src/provider/session/context_fork/claude.rs +1 -0
- package/crates/team-agent/src/provider/session/context_fork/codex.rs +1 -0
- package/crates/team-agent/src/provider/session/context_fork/outcome.rs +1 -0
- package/crates/team-agent/src/provider/session/context_fork.rs +1 -0
- package/crates/team-agent/src/provider/session/mod.rs +2 -4
- package/crates/team-agent/src/provider/session/resume.rs +2 -209
- package/crates/team-agent/src/provider/session_scan/claude.rs +1 -0
- package/crates/team-agent/src/provider/session_scan/codex.rs +1 -0
- package/crates/team-agent/src/provider/session_scan/common.rs +1 -0
- package/crates/team-agent/src/provider/session_scan/copilot.rs +1 -0
- package/crates/team-agent/src/provider/session_scan.rs +1 -42
- package/crates/team-agent/src/provider/startup_prompt.rs +1 -0
- package/crates/team-agent/src/provider/types.rs +1 -0
- package/crates/team-agent/src/provider/wire.rs +1 -0
- package/crates/team-agent/src/state/identity.rs +16 -5
- package/crates/team-agent/src/state/identity_keys.rs +1 -0
- package/crates/team-agent/src/state/mod.rs +2 -0
- package/crates/team-agent/src/state/owner_gate.rs +5 -0
- package/crates/team-agent/src/state/ownership.rs +10 -4
- package/crates/team-agent/src/state/paths.rs +12 -0
- package/crates/team-agent/src/state/persist.rs +9 -3
- package/crates/team-agent/src/state/projection.rs +15 -2
- package/crates/team-agent/src/state/repository/intent.rs +1 -0
- package/crates/team-agent/src/state/repository/tests.rs +1 -0
- package/crates/team-agent/src/state/repository.rs +7 -13
- package/crates/team-agent/src/state/selector.rs +1 -0
- package/crates/team-agent/src/tmux_backend/tests.rs +39 -0
- package/crates/team-agent/src/tmux_backend.rs +63 -0
- package/crates/team-agent/src/transport.rs +15 -0
- package/package.json +4 -4
- package/crates/team-agent/src/leader/inject.rs +0 -33
- package/crates/team-agent/src/provider/command.rs +0 -80
|
@@ -98,18 +98,6 @@ fn status_enums_serialize_to_exact_python_strings() {
|
|
|
98
98
|
serde_json::to_string(&MetadataSource::Start).unwrap(),
|
|
99
99
|
"\"start\"",
|
|
100
100
|
),
|
|
101
|
-
(
|
|
102
|
-
serde_json::to_string(&AbnormalDecision::Skip).unwrap(),
|
|
103
|
-
"\"skip\"",
|
|
104
|
-
),
|
|
105
|
-
(
|
|
106
|
-
serde_json::to_string(&AbnormalDecision::NotifyBlacklist).unwrap(),
|
|
107
|
-
"\"notify_blacklist\"",
|
|
108
|
-
),
|
|
109
|
-
(
|
|
110
|
-
serde_json::to_string(&AbnormalDecision::NotifyDefault).unwrap(),
|
|
111
|
-
"\"notify_default\"",
|
|
112
|
-
),
|
|
113
101
|
(
|
|
114
102
|
serde_json::to_string(&WholeTeamGoneClass::Alive).unwrap(),
|
|
115
103
|
"\"alive\"",
|
|
@@ -132,178 +120,6 @@ fn status_enums_serialize_to_exact_python_strings() {
|
|
|
132
120
|
}
|
|
133
121
|
}
|
|
134
122
|
|
|
135
|
-
#[test]
|
|
136
|
-
fn coordinator_event_tags_are_byte_stable() {
|
|
137
|
-
// 逐一钉 events.jsonl tag(events.py 稳定契约)。
|
|
138
|
-
let pid = Pid(4242);
|
|
139
|
-
let cases: Vec<(CoordinatorEvent, &str)> = vec![
|
|
140
|
-
(
|
|
141
|
-
CoordinatorEvent::Boot {
|
|
142
|
-
workspace: "/w".into(),
|
|
143
|
-
once: true,
|
|
144
|
-
},
|
|
145
|
-
"coordinator.boot",
|
|
146
|
-
),
|
|
147
|
-
(
|
|
148
|
-
CoordinatorEvent::Started {
|
|
149
|
-
pid,
|
|
150
|
-
log: "/l".into(),
|
|
151
|
-
},
|
|
152
|
-
"coordinator.started",
|
|
153
|
-
),
|
|
154
|
-
(CoordinatorEvent::Stopped { pid }, "coordinator.stopped"),
|
|
155
|
-
(CoordinatorEvent::Exit { stop: true }, "coordinator.exit"),
|
|
156
|
-
(
|
|
157
|
-
CoordinatorEvent::SessionMissing {
|
|
158
|
-
session: "s".into(),
|
|
159
|
-
},
|
|
160
|
-
"coordinator.session_missing",
|
|
161
|
-
),
|
|
162
|
-
(
|
|
163
|
-
CoordinatorEvent::OrphanSelfTerminate {
|
|
164
|
-
initial_ppid: 9,
|
|
165
|
-
current_ppid: 1,
|
|
166
|
-
workspace: "/w".into(),
|
|
167
|
-
},
|
|
168
|
-
"coordinator.orphan_self_terminate",
|
|
169
|
-
),
|
|
170
|
-
(
|
|
171
|
-
CoordinatorEvent::TickError {
|
|
172
|
-
error: "boom".into(),
|
|
173
|
-
exc_type: "OSError".into(),
|
|
174
|
-
consecutive_failures: 1,
|
|
175
|
-
next_sleep_sec: 5.0,
|
|
176
|
-
},
|
|
177
|
-
"coordinator.tick_error",
|
|
178
|
-
),
|
|
179
|
-
(
|
|
180
|
-
CoordinatorEvent::TickErrorSuppressed {
|
|
181
|
-
consecutive_failures: 2,
|
|
182
|
-
next_sleep_sec: 10.0,
|
|
183
|
-
},
|
|
184
|
-
"coordinator.tick_error.suppressed",
|
|
185
|
-
),
|
|
186
|
-
(
|
|
187
|
-
CoordinatorEvent::TickRecovered {
|
|
188
|
-
consecutive_failures: 3,
|
|
189
|
-
},
|
|
190
|
-
"coordinator.tick_recovered",
|
|
191
|
-
),
|
|
192
|
-
(
|
|
193
|
-
CoordinatorEvent::RestartIncompatible {
|
|
194
|
-
pid: Some(pid),
|
|
195
|
-
expected_protocol: 2,
|
|
196
|
-
expected_schema: 3,
|
|
197
|
-
},
|
|
198
|
-
"coordinator.restart_incompatible",
|
|
199
|
-
),
|
|
200
|
-
(
|
|
201
|
-
CoordinatorEvent::RestartIncompatibleStopFailed { pid: Some(pid) },
|
|
202
|
-
"coordinator.restart_incompatible_stop_failed",
|
|
203
|
-
),
|
|
204
|
-
(
|
|
205
|
-
CoordinatorEvent::SchemaIncompatible {
|
|
206
|
-
table: Some("messages".into()),
|
|
207
|
-
missing_columns: vec!["owner_team_id".into()],
|
|
208
|
-
},
|
|
209
|
-
"coordinator.schema_incompatible",
|
|
210
|
-
),
|
|
211
|
-
(
|
|
212
|
-
CoordinatorEvent::IdleTakeoverUnknownPersistent {
|
|
213
|
-
node_id: "w1".into(),
|
|
214
|
-
provider: Some(Provider::Codex),
|
|
215
|
-
auth_mode: None,
|
|
216
|
-
consecutive_ticks: 60,
|
|
217
|
-
rollout_path: None,
|
|
218
|
-
},
|
|
219
|
-
"idle_takeover.unknown_persistent",
|
|
220
|
-
),
|
|
221
|
-
(
|
|
222
|
-
CoordinatorEvent::AbnormalNotify {
|
|
223
|
-
signature: "sig".into(),
|
|
224
|
-
turn_id: None,
|
|
225
|
-
decision: AbnormalDecision::NotifyDefault,
|
|
226
|
-
},
|
|
227
|
-
"abnormal.notify",
|
|
228
|
-
),
|
|
229
|
-
(
|
|
230
|
-
CoordinatorEvent::AbnormalWholeTeamGone {
|
|
231
|
-
classification: WholeTeamGoneClass::UnexpectedExit,
|
|
232
|
-
},
|
|
233
|
-
"abnormal.whole_team_gone",
|
|
234
|
-
),
|
|
235
|
-
(
|
|
236
|
-
CoordinatorEvent::LeaderNotificationLogPruned { removed: 7 },
|
|
237
|
-
"leader_notification.log_pruned",
|
|
238
|
-
),
|
|
239
|
-
(
|
|
240
|
-
CoordinatorEvent::LeaderNotificationPruneFailed { error: "io".into() },
|
|
241
|
-
"leader_notification.prune_failed",
|
|
242
|
-
),
|
|
243
|
-
(
|
|
244
|
-
CoordinatorEvent::RuntimeStateSaveFailed {
|
|
245
|
-
phase: "tick_end".into(),
|
|
246
|
-
error: "replace".into(),
|
|
247
|
-
exc_type: "OSError".into(),
|
|
248
|
-
},
|
|
249
|
-
"runtime.state.save_failed",
|
|
250
|
-
),
|
|
251
|
-
];
|
|
252
|
-
for (evt, want_tag) in &cases {
|
|
253
|
-
let json = serde_json::to_value(evt).unwrap();
|
|
254
|
-
assert_eq!(json["event"], *want_tag, "tag mismatch for {want_tag}");
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
#[test]
|
|
259
|
-
fn tick_error_event_carries_exact_python_fields() {
|
|
260
|
-
// __main__.py:69-74 — error / exc_type / consecutive_failures / next_sleep_sec.
|
|
261
|
-
let evt = CoordinatorEvent::TickError {
|
|
262
|
-
error: "os.replace failed".into(),
|
|
263
|
-
exc_type: "OSError".into(),
|
|
264
|
-
consecutive_failures: 4,
|
|
265
|
-
next_sleep_sec: 40.0,
|
|
266
|
-
};
|
|
267
|
-
let json = serde_json::to_value(&evt).unwrap();
|
|
268
|
-
assert_eq!(json["event"], "coordinator.tick_error");
|
|
269
|
-
assert_eq!(json["error"], "os.replace failed");
|
|
270
|
-
assert_eq!(json["exc_type"], "OSError");
|
|
271
|
-
assert_eq!(json["consecutive_failures"], 4);
|
|
272
|
-
assert_eq!(json["next_sleep_sec"], 40.0);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
#[test]
|
|
276
|
-
fn unknown_persistent_event_provider_none_is_null_not_missing() {
|
|
277
|
-
// lifecycle.py:407 rollout_path=node.get(...) — None 漏穿堵死(bug-085):
|
|
278
|
-
// provider/rollout_path 缺失序列化为 JSON null,绝不省略键。
|
|
279
|
-
let evt = CoordinatorEvent::IdleTakeoverUnknownPersistent {
|
|
280
|
-
node_id: "w7".into(),
|
|
281
|
-
provider: None,
|
|
282
|
-
auth_mode: None,
|
|
283
|
-
consecutive_ticks: 72,
|
|
284
|
-
rollout_path: None,
|
|
285
|
-
};
|
|
286
|
-
let json = serde_json::to_value(&evt).unwrap();
|
|
287
|
-
assert_eq!(json["event"], "idle_takeover.unknown_persistent");
|
|
288
|
-
assert_eq!(json["node_id"], "w7");
|
|
289
|
-
assert!(
|
|
290
|
-
json.get("provider").is_some(),
|
|
291
|
-
"provider key MUST be present (None→null)"
|
|
292
|
-
);
|
|
293
|
-
assert!(json["provider"].is_null(), "provider None → JSON null");
|
|
294
|
-
assert!(
|
|
295
|
-
json.get("auth_mode").is_some(),
|
|
296
|
-
"auth_mode key MUST be present"
|
|
297
|
-
);
|
|
298
|
-
assert!(json["auth_mode"].is_null(), "auth_mode None → JSON null");
|
|
299
|
-
assert!(
|
|
300
|
-
json.get("rollout_path").is_some(),
|
|
301
|
-
"rollout_path key MUST be present"
|
|
302
|
-
);
|
|
303
|
-
assert!(json["rollout_path"].is_null());
|
|
304
|
-
assert_eq!(json["consecutive_ticks"], 72);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
123
|
#[test]
|
|
308
124
|
fn coordinator_metadata_json_field_names_are_stable() {
|
|
309
125
|
// metadata.py:50-57 — 稳定 coordinator.json 契约。
|
|
@@ -25,23 +25,15 @@ fn meta(pid: u32, proto: u32, schema: i64) -> CoordinatorMetadata {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/// `ProviderRegistry` mock —
|
|
29
|
-
/// `adapter_for`/`error_lists` 各记一次调用计数;abnormal-track 只允许触碰 `error_lists`,
|
|
30
|
-
/// 绝不触碰 `adapter_for`(那会走真实 provider client crate)。
|
|
28
|
+
/// `ProviderRegistry` mock — 记录 provider-client adapter 调用 (MUST-NOT-13 / §84).
|
|
31
29
|
struct MockRegistry {
|
|
32
|
-
whitelist: Vec<String>,
|
|
33
|
-
blacklist: Vec<String>,
|
|
34
30
|
adapter_calls: std::cell::Cell<u32>,
|
|
35
|
-
error_list_calls: std::cell::Cell<u32>,
|
|
36
31
|
}
|
|
37
32
|
|
|
38
33
|
impl MockRegistry {
|
|
39
|
-
fn new(
|
|
34
|
+
fn new(_whitelist: &[&str], _blacklist: &[&str]) -> Self {
|
|
40
35
|
Self {
|
|
41
|
-
whitelist: whitelist.iter().map(|s| s.to_string()).collect(),
|
|
42
|
-
blacklist: blacklist.iter().map(|s| s.to_string()).collect(),
|
|
43
36
|
adapter_calls: std::cell::Cell::new(0),
|
|
44
|
-
error_list_calls: std::cell::Cell::new(0),
|
|
45
37
|
}
|
|
46
38
|
}
|
|
47
39
|
}
|
|
@@ -52,13 +44,6 @@ impl ProviderRegistry for MockRegistry {
|
|
|
52
44
|
self.adapter_calls.set(self.adapter_calls.get() + 1);
|
|
53
45
|
crate::provider::get_adapter(_provider)
|
|
54
46
|
}
|
|
55
|
-
fn error_lists(&self, _provider: Provider) -> ErrorLists {
|
|
56
|
-
self.error_list_calls.set(self.error_list_calls.get() + 1);
|
|
57
|
-
ErrorLists {
|
|
58
|
-
whitelist: self.whitelist.clone(),
|
|
59
|
-
blacklist: self.blacklist.clone(),
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
47
|
}
|
|
63
48
|
|
|
64
49
|
/// in-memory `MarkerStore` —— durable marker 落盘探针。
|
|
@@ -106,13 +106,6 @@ fn tick_side_effect_order_is_the_fixed_sequence() {
|
|
|
106
106
|
"detect_drift",
|
|
107
107
|
"detect_api_errors",
|
|
108
108
|
"atomic_save",
|
|
109
|
-
// 0.5.36 (`.team/artifacts/supermarket-api-error-recovery-locate.md` §7.3):
|
|
110
|
-
// post-save recovery step reloads fresh state, consumes due
|
|
111
|
-
// recovery intents written pre-save, and drives the lifecycle
|
|
112
|
-
// helper. Sits between atomic_save and collect_results by design
|
|
113
|
-
// so nested lifecycle saves cannot be clobbered by tick's final
|
|
114
|
-
// in-memory save.
|
|
115
|
-
"attempt_api_error_recoveries",
|
|
116
109
|
"collect_results",
|
|
117
110
|
"prune_dedupe_log",
|
|
118
111
|
];
|
|
@@ -260,45 +253,3 @@ fn p2_render_result_received_truncates_summary_to_80_chars() {
|
|
|
260
253
|
"summary must be truncated to 80 chars"
|
|
261
254
|
);
|
|
262
255
|
}
|
|
263
|
-
|
|
264
|
-
// P1 — idle_takeover.unknown_persistent must carry the auth_mode field (null when absent)
|
|
265
|
-
// (lifecycle.py:401-408). NOTE: the variant currently lacks the field; the porter adds
|
|
266
|
-
// `auth_mode` between provider and consecutive_ticks and updates this construction.
|
|
267
|
-
#[test]
|
|
268
|
-
fn p2_unknown_persistent_event_serializes_auth_mode_key() {
|
|
269
|
-
let evt = CoordinatorEvent::IdleTakeoverUnknownPersistent {
|
|
270
|
-
node_id: "w7".into(),
|
|
271
|
-
provider: None,
|
|
272
|
-
auth_mode: None,
|
|
273
|
-
consecutive_ticks: 72,
|
|
274
|
-
rollout_path: None,
|
|
275
|
-
};
|
|
276
|
-
let json = serde_json::to_value(&evt).unwrap();
|
|
277
|
-
assert!(
|
|
278
|
-
json.get("auth_mode").is_some(),
|
|
279
|
-
"idle_takeover.unknown_persistent must serialize an auth_mode key (null when absent)"
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// P1 — process_abnormal_records matches a LOWERCASED signature too (abnormal_track.py:49,198):
|
|
284
|
-
// raw has no needle but signature 'TimeoutError' matches blacklist 'timeout'. Current is
|
|
285
|
-
// case-sensitive on `raw` only and ignores the signature → NotifyDefault.
|
|
286
|
-
#[test]
|
|
287
|
-
fn p2_abnormal_matches_lowercased_signature_too() {
|
|
288
|
-
let reg = MockRegistry::new(&[], &["timeout"]);
|
|
289
|
-
let records =
|
|
290
|
-
vec![serde_json::json!({"raw":"nothing here","signature":"TimeoutError","kind":"error"})];
|
|
291
|
-
let out = process_abnormal_records(
|
|
292
|
-
&records,
|
|
293
|
-
®,
|
|
294
|
-
Provider::Codex,
|
|
295
|
-
&AbnormalNotificationState::default(),
|
|
296
|
-
)
|
|
297
|
-
.unwrap();
|
|
298
|
-
assert_eq!(out.notifications.len(), 1);
|
|
299
|
-
assert_eq!(
|
|
300
|
-
out.notifications[0].decision,
|
|
301
|
-
AbnormalDecision::NotifyBlacklist,
|
|
302
|
-
"blacklist 'timeout' must match the lowercased signature 'TimeoutError'"
|
|
303
|
-
);
|
|
304
|
-
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//!
|
|
1
2
|
//! Coordinator core:daemon lifecycle 宿主 + 单次 tick 编排(19 步固定顺序)+ health/start/stop。
|
|
2
3
|
|
|
3
4
|
use std::collections::BTreeMap;
|
|
@@ -19,6 +20,7 @@ use super::health::{
|
|
|
19
20
|
pid_is_running, read_coordinator_metadata, write_coordinator_metadata,
|
|
20
21
|
};
|
|
21
22
|
use super::runtime_observation::{self, CapturedRuntimeFact};
|
|
23
|
+
use super::steps::TickStepGroup;
|
|
22
24
|
use super::types::{
|
|
23
25
|
AgentId, CoordinatorHealthStatus, HealthReport, MetadataSource, Pid, ProviderRegistry,
|
|
24
26
|
SchemaHealth, StartError, StartOutcome, StartReport, StopError, StopOutcome, StopReport,
|
|
@@ -225,7 +227,7 @@ impl Coordinator {
|
|
|
225
227
|
/// `if let Some(rec) = &self.order_recorder { rec.lock()...push(STEP_NAME) }`(tick
|
|
226
228
|
/// 副作用 ORDER 测试断言固定序列)。生产两者均 `None`,零开销。
|
|
227
229
|
pub fn tick(&self) -> Result<TickReport, TickError> {
|
|
228
|
-
self.record_step("load_state");
|
|
230
|
+
self.record_step(TickStepGroup::SessionGate, "load_state");
|
|
229
231
|
let raw_state = crate::state::persist::load_runtime_state(self.workspace.as_path())?;
|
|
230
232
|
// Issue 2 (Round 3b gate review §6): when the runtime carries
|
|
231
233
|
// `active_team_key` AND `teams.<key>` exists, project the team-scoped
|
|
@@ -246,7 +248,7 @@ impl Coordinator {
|
|
|
246
248
|
let event_log = EventLog::new(self.workspace.as_path());
|
|
247
249
|
increment_coordinator_tick_iteration_count(&self.workspace);
|
|
248
250
|
|
|
249
|
-
self.record_step("tmux_session_gate");
|
|
251
|
+
self.record_step(TickStepGroup::SessionGate, "tmux_session_gate");
|
|
250
252
|
if let Some(session_name) = state
|
|
251
253
|
.get("session_name")
|
|
252
254
|
.and_then(Value::as_str)
|
|
@@ -268,7 +270,7 @@ impl Coordinator {
|
|
|
268
270
|
}
|
|
269
271
|
}
|
|
270
272
|
|
|
271
|
-
self.record_step("capture_missing");
|
|
273
|
+
self.record_step(TickStepGroup::SessionGate, "capture_missing");
|
|
272
274
|
let pending_context_fork_audits =
|
|
273
275
|
match self.capture_missing_sessions(&mut state, &event_log) {
|
|
274
276
|
Ok(audits) => audits,
|
|
@@ -293,10 +295,10 @@ impl Coordinator {
|
|
|
293
295
|
.unwrap_or_default();
|
|
294
296
|
let has_work_obligation = tick_has_work_obligation(&store);
|
|
295
297
|
|
|
296
|
-
self.record_step("refresh_statuses");
|
|
298
|
+
self.record_step(TickStepGroup::HealthSync, "refresh_statuses");
|
|
297
299
|
// TODO(spine slice 2b): split lightweight runtime status refresh from health sync.
|
|
298
300
|
|
|
299
|
-
self.record_step("startup_prompts");
|
|
301
|
+
self.record_step(TickStepGroup::RuntimePrompts, "startup_prompts");
|
|
300
302
|
self.handle_startup_prompts(&mut state, &event_log, &pane_snapshot, &window_snapshot);
|
|
301
303
|
|
|
302
304
|
// #229 step2-retry: once an agent's `startup_prompts` flipped to `handled`
|
|
@@ -318,7 +320,7 @@ impl Coordinator {
|
|
|
318
320
|
// 否则 deliver_pending(下行投递主干)够不到,消息卡 accepted。
|
|
319
321
|
// bug-084 哲学 + A-6 同族:每步独立 try,失败写 `coordinator.tick.<step>_failed`
|
|
320
322
|
// 事件后继续走下一步;tick 本身仍返 Ok。
|
|
321
|
-
self.record_step("runtime_prompts");
|
|
323
|
+
self.record_step(TickStepGroup::RuntimePrompts, "runtime_prompts");
|
|
322
324
|
if let Err(error) = self.handle_runtime_approval_prompts(
|
|
323
325
|
&mut state,
|
|
324
326
|
&event_log,
|
|
@@ -331,7 +333,7 @@ impl Coordinator {
|
|
|
331
333
|
);
|
|
332
334
|
}
|
|
333
335
|
|
|
334
|
-
self.record_step("sync_health");
|
|
336
|
+
self.record_step(TickStepGroup::HealthSync, "sync_health");
|
|
335
337
|
// P5 (C-P5-1, N3): ONE pane snapshot per tick, shared by sync_health and the
|
|
336
338
|
// abnormal-exit pass (same-tick reuse only — the snapshot does not outlive
|
|
337
339
|
// this tick; every tick re-reads).
|
|
@@ -365,7 +367,7 @@ impl Coordinator {
|
|
|
365
367
|
);
|
|
366
368
|
}
|
|
367
369
|
|
|
368
|
-
self.record_step("deliver_pending");
|
|
370
|
+
self.record_step(TickStepGroup::Delivery, "deliver_pending");
|
|
369
371
|
let delivered = crate::messaging::deliver_pending_messages(
|
|
370
372
|
self.workspace.as_path(),
|
|
371
373
|
&state,
|
|
@@ -376,7 +378,7 @@ impl Coordinator {
|
|
|
376
378
|
.map(|message_id| DeliveredMessage { message_id })
|
|
377
379
|
.collect::<Vec<_>>();
|
|
378
380
|
|
|
379
|
-
self.record_step("fire_scheduled");
|
|
381
|
+
self.record_step(TickStepGroup::Delivery, "fire_scheduled");
|
|
380
382
|
let scheduled = crate::messaging::fire_due_scheduled_events(
|
|
381
383
|
self.workspace.as_path(),
|
|
382
384
|
&store,
|
|
@@ -394,18 +396,18 @@ impl Coordinator {
|
|
|
394
396
|
// (deliver_pending / fire_scheduled / collect_results) above and below this
|
|
395
397
|
// block continue to flow unchanged. `_state` / `_store` here are intentionally
|
|
396
398
|
// unused (the lookups they powered were nag inputs only).
|
|
397
|
-
self.record_step("detect_stuck");
|
|
399
|
+
self.record_step(TickStepGroup::Abnormal, "detect_stuck");
|
|
398
400
|
let stuck: Vec<AgentId> = Vec::new();
|
|
399
|
-
self.record_step("record_unknown_idle");
|
|
400
|
-
self.record_step("evaluate_takeover");
|
|
401
|
+
self.record_step(TickStepGroup::Abnormal, "record_unknown_idle");
|
|
402
|
+
self.record_step(TickStepGroup::Abnormal, "evaluate_takeover");
|
|
401
403
|
let idle_alerts: Vec<IdleAlert> = Vec::new();
|
|
402
|
-
self.record_step("detect_deadlocks");
|
|
404
|
+
self.record_step(TickStepGroup::Abnormal, "detect_deadlocks");
|
|
403
405
|
let deadlock_alerts: Vec<DeadlockAlert> = Vec::new();
|
|
404
406
|
let _ = &store;
|
|
405
407
|
|
|
406
|
-
self.record_step("detect_compaction");
|
|
407
|
-
self.record_step("detect_drift");
|
|
408
|
-
self.record_step("detect_api_errors");
|
|
408
|
+
self.record_step(TickStepGroup::Abnormal, "detect_compaction");
|
|
409
|
+
self.record_step(TickStepGroup::Abnormal, "detect_drift");
|
|
410
|
+
self.record_step(TickStepGroup::Abnormal, "detect_api_errors");
|
|
409
411
|
let leader_capture = self.capture_leader_receiver(&state);
|
|
410
412
|
let observations = runtime_observation::observe(
|
|
411
413
|
self.workspace.as_path(),
|
|
@@ -425,7 +427,7 @@ impl Coordinator {
|
|
|
425
427
|
results: Vec::new(),
|
|
426
428
|
};
|
|
427
429
|
|
|
428
|
-
self.record_step("atomic_save");
|
|
430
|
+
self.record_step(TickStepGroup::Persist, "atomic_save");
|
|
429
431
|
let saved = match &self.save_hook {
|
|
430
432
|
Some(hook) => hook(&self.workspace, &state),
|
|
431
433
|
None => {
|
|
@@ -468,26 +470,13 @@ impl Coordinator {
|
|
|
468
470
|
})?;
|
|
469
471
|
}
|
|
470
472
|
|
|
471
|
-
|
|
472
|
-
// post-save recovery step. Reloads fresh state, consumes due
|
|
473
|
-
// recovery intents that were WRITTEN during the pre-save detector
|
|
474
|
-
// step, and drives the lifecycle helper. Runs OUTSIDE the pre-save
|
|
475
|
-
// window so nested lifecycle saves cannot be clobbered by this
|
|
476
|
-
// tick's final in-memory save (R6 boundary guard).
|
|
477
|
-
self.record_step("attempt_api_error_recoveries");
|
|
478
|
-
crate::coordinator::steps::abnormal::attempt_due_recoveries(
|
|
479
|
-
self.workspace.as_path(),
|
|
480
|
-
&event_log,
|
|
481
|
-
self.transport.as_ref(),
|
|
482
|
-
);
|
|
483
|
-
|
|
484
|
-
self.record_step("collect_results");
|
|
473
|
+
self.record_step(TickStepGroup::Delivery, "collect_results");
|
|
485
474
|
collections.results =
|
|
486
475
|
collect_results(crate::messaging::collect_results_and_notify_watchers(
|
|
487
476
|
self.workspace.as_path(),
|
|
488
477
|
&event_log,
|
|
489
478
|
)?);
|
|
490
|
-
self.record_step("prune_dedupe_log");
|
|
479
|
+
self.record_step(TickStepGroup::Persist, "prune_dedupe_log");
|
|
491
480
|
Ok(base_tick_report(true, false, None, Some(true), collections))
|
|
492
481
|
}
|
|
493
482
|
|
|
@@ -1430,7 +1419,8 @@ impl Coordinator {
|
|
|
1430
1419
|
super::health::message_store_schema_health(&self.workspace)
|
|
1431
1420
|
}
|
|
1432
1421
|
|
|
1433
|
-
fn record_step(&self, step: &'static str) {
|
|
1422
|
+
fn record_step(&self, group: TickStepGroup, step: &'static str) {
|
|
1423
|
+
debug_assert!(TickStepGroup::ordered().contains(&group));
|
|
1434
1424
|
if let Some(recorder) = &self.order_recorder {
|
|
1435
1425
|
if let Ok(mut guard) = recorder.lock() {
|
|
1436
1426
|
guard.push(step);
|
|
@@ -2757,13 +2747,6 @@ mod u1_tests {
|
|
|
2757
2747
|
),
|
|
2758
2748
|
)
|
|
2759
2749
|
}
|
|
2760
|
-
|
|
2761
|
-
fn error_lists(
|
|
2762
|
-
&self,
|
|
2763
|
-
_provider: crate::provider::Provider,
|
|
2764
|
-
) -> super::super::types::ErrorLists {
|
|
2765
|
-
super::super::types::ErrorLists::default()
|
|
2766
|
-
}
|
|
2767
2750
|
}
|
|
2768
2751
|
|
|
2769
2752
|
#[test]
|