@team-agent/installer 0.5.61 → 0.5.62
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 +6 -5
- 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 +0 -9
- 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 -42
- package/crates/team-agent/src/coordinator/tick.rs +24 -28
- 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 -3
- 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 -11
- 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 -0
- 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
|
@@ -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 => {
|
|
@@ -474,20 +476,20 @@ impl Coordinator {
|
|
|
474
476
|
// step, and drives the lifecycle helper. Runs OUTSIDE the pre-save
|
|
475
477
|
// window so nested lifecycle saves cannot be clobbered by this
|
|
476
478
|
// tick's final in-memory save (R6 boundary guard).
|
|
477
|
-
self.record_step("attempt_api_error_recoveries");
|
|
479
|
+
self.record_step(TickStepGroup::Abnormal, "attempt_api_error_recoveries");
|
|
478
480
|
crate::coordinator::steps::abnormal::attempt_due_recoveries(
|
|
479
481
|
self.workspace.as_path(),
|
|
480
482
|
&event_log,
|
|
481
483
|
self.transport.as_ref(),
|
|
482
484
|
);
|
|
483
485
|
|
|
484
|
-
self.record_step("collect_results");
|
|
486
|
+
self.record_step(TickStepGroup::Delivery, "collect_results");
|
|
485
487
|
collections.results =
|
|
486
488
|
collect_results(crate::messaging::collect_results_and_notify_watchers(
|
|
487
489
|
self.workspace.as_path(),
|
|
488
490
|
&event_log,
|
|
489
491
|
)?);
|
|
490
|
-
self.record_step("prune_dedupe_log");
|
|
492
|
+
self.record_step(TickStepGroup::Persist, "prune_dedupe_log");
|
|
491
493
|
Ok(base_tick_report(true, false, None, Some(true), collections))
|
|
492
494
|
}
|
|
493
495
|
|
|
@@ -1430,7 +1432,8 @@ impl Coordinator {
|
|
|
1430
1432
|
super::health::message_store_schema_health(&self.workspace)
|
|
1431
1433
|
}
|
|
1432
1434
|
|
|
1433
|
-
fn record_step(&self, step: &'static str) {
|
|
1435
|
+
fn record_step(&self, group: TickStepGroup, step: &'static str) {
|
|
1436
|
+
debug_assert!(TickStepGroup::ordered().contains(&group));
|
|
1434
1437
|
if let Some(recorder) = &self.order_recorder {
|
|
1435
1438
|
if let Ok(mut guard) = recorder.lock() {
|
|
1436
1439
|
guard.push(step);
|
|
@@ -2757,13 +2760,6 @@ mod u1_tests {
|
|
|
2757
2760
|
),
|
|
2758
2761
|
)
|
|
2759
2762
|
}
|
|
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
2763
|
}
|
|
2768
2764
|
|
|
2769
2765
|
#[test]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//! coordinator 共享数据面:常量 / newtype / 穷尽 enum / metadata / schema health /
|
|
2
|
-
//! report 结构 /
|
|
2
|
+
//! report 结构 / abnormal-track 数据型 / WatchCursor / cross-dep 占位。
|
|
3
3
|
|
|
4
4
|
use std::collections::BTreeSet;
|
|
5
5
|
use std::path::{Path, PathBuf};
|
|
@@ -9,11 +9,10 @@ use serde_json::Value;
|
|
|
9
9
|
use thiserror::Error;
|
|
10
10
|
|
|
11
11
|
// ── REUSE — committed model types(不重定义)──────────────────────────────────
|
|
12
|
-
use crate::model::enums::
|
|
13
|
-
// AuthMode/PaneLiveness 经 provider/transport 间接复用;此处只点名直接用到的。
|
|
12
|
+
use crate::model::enums::Provider;
|
|
14
13
|
|
|
15
14
|
// ── REUSE — step 8 provider(经 trait,MUST-NOT-13:绝不依赖 provider client crate)──
|
|
16
|
-
use crate::provider::{
|
|
15
|
+
use crate::provider::{ProviderAdapter, RolloutPath, TurnState};
|
|
17
16
|
|
|
18
17
|
// ===========================================================================
|
|
19
18
|
// CONSTANTS(metadata.py:13 / __main__.py:101)
|
|
@@ -354,137 +353,10 @@ pub struct StopReport {
|
|
|
354
353
|
pub pid: Option<Pid>,
|
|
355
354
|
}
|
|
356
355
|
|
|
357
|
-
// ===========================================================================
|
|
358
|
-
// CoordinatorEvent(§3/§22:typed event enum,serde tag 与 Python 字节级一致)
|
|
359
|
-
// ===========================================================================
|
|
360
|
-
|
|
361
|
-
/// 本 step 发出的事件(card 表整列;事件名稳定契约由 step 4 EventLog 拥有,本卡只点名
|
|
362
|
-
/// coordinator 发的那批)。serde `tag = "event"` + 精确 rename 锁死字节(与 events.jsonl 一致)。
|
|
363
|
-
/// 渲染(`watch::render_event_line`)是它的 `Display` 投影。
|
|
364
|
-
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] // 无 Eq:某变体含 f64
|
|
365
|
-
#[serde(tag = "event")]
|
|
366
|
-
pub enum CoordinatorEvent {
|
|
367
|
-
#[serde(rename = "coordinator.boot")]
|
|
368
|
-
Boot { workspace: String, once: bool },
|
|
369
|
-
#[serde(rename = "coordinator.started")]
|
|
370
|
-
Started { pid: Pid, log: String },
|
|
371
|
-
#[serde(rename = "coordinator.stopped")]
|
|
372
|
-
Stopped { pid: Pid },
|
|
373
|
-
#[serde(rename = "coordinator.exit")]
|
|
374
|
-
Exit { stop: bool },
|
|
375
|
-
#[serde(rename = "coordinator.session_missing")]
|
|
376
|
-
SessionMissing { session: String },
|
|
377
|
-
#[serde(rename = "coordinator.orphan_self_terminate")]
|
|
378
|
-
OrphanSelfTerminate {
|
|
379
|
-
initial_ppid: u32,
|
|
380
|
-
current_ppid: u32,
|
|
381
|
-
workspace: String,
|
|
382
|
-
},
|
|
383
|
-
#[serde(rename = "coordinator.tick_error")]
|
|
384
|
-
TickError {
|
|
385
|
-
error: String,
|
|
386
|
-
exc_type: String,
|
|
387
|
-
consecutive_failures: u32,
|
|
388
|
-
next_sleep_sec: f64,
|
|
389
|
-
},
|
|
390
|
-
#[serde(rename = "coordinator.tick_error.suppressed")]
|
|
391
|
-
TickErrorSuppressed {
|
|
392
|
-
consecutive_failures: u32,
|
|
393
|
-
next_sleep_sec: f64,
|
|
394
|
-
},
|
|
395
|
-
#[serde(rename = "coordinator.tick_recovered")]
|
|
396
|
-
TickRecovered { consecutive_failures: u32 },
|
|
397
|
-
#[serde(rename = "coordinator.restart_incompatible")]
|
|
398
|
-
RestartIncompatible {
|
|
399
|
-
pid: Option<Pid>,
|
|
400
|
-
expected_protocol: u32,
|
|
401
|
-
expected_schema: i64,
|
|
402
|
-
},
|
|
403
|
-
#[serde(rename = "coordinator.restart_incompatible_stop_failed")]
|
|
404
|
-
RestartIncompatibleStopFailed { pid: Option<Pid> },
|
|
405
|
-
#[serde(rename = "coordinator.schema_incompatible")]
|
|
406
|
-
SchemaIncompatible {
|
|
407
|
-
table: Option<String>,
|
|
408
|
-
missing_columns: Vec<String>,
|
|
409
|
-
},
|
|
410
|
-
#[serde(rename = "idle_takeover.unknown_persistent")]
|
|
411
|
-
IdleTakeoverUnknownPersistent {
|
|
412
|
-
node_id: String,
|
|
413
|
-
provider: Option<Provider>,
|
|
414
|
-
auth_mode: Option<AuthMode>,
|
|
415
|
-
consecutive_ticks: u32,
|
|
416
|
-
rollout_path: Option<RolloutPath>,
|
|
417
|
-
},
|
|
418
|
-
#[serde(rename = "abnormal.notify")]
|
|
419
|
-
AbnormalNotify {
|
|
420
|
-
signature: String,
|
|
421
|
-
turn_id: Option<TurnId>,
|
|
422
|
-
decision: AbnormalDecision,
|
|
423
|
-
},
|
|
424
|
-
#[serde(rename = "worker.abnormal_exit")]
|
|
425
|
-
WorkerAbnormalExit {
|
|
426
|
-
team_id: String,
|
|
427
|
-
agent_id: String,
|
|
428
|
-
provider: Provider,
|
|
429
|
-
path: String,
|
|
430
|
-
provider_process_dead: bool,
|
|
431
|
-
latest_explicit_error: bool,
|
|
432
|
-
signature: String,
|
|
433
|
-
turn_id: Option<TurnId>,
|
|
434
|
-
process_liveness: ProcessLiveness,
|
|
435
|
-
},
|
|
436
|
-
#[serde(rename = "worker.abnormal_exit.check")]
|
|
437
|
-
WorkerAbnormalExitCheck {
|
|
438
|
-
team_id: String,
|
|
439
|
-
agent_id: String,
|
|
440
|
-
provider: Provider,
|
|
441
|
-
path: String,
|
|
442
|
-
provider_process_dead: bool,
|
|
443
|
-
latest_explicit_error: bool,
|
|
444
|
-
notification: bool,
|
|
445
|
-
suppressed_reason: Option<String>,
|
|
446
|
-
},
|
|
447
|
-
#[serde(rename = "abnormal_exit.single_signal_suppressed")]
|
|
448
|
-
AbnormalExitSingleSignalSuppressed {
|
|
449
|
-
team_id: String,
|
|
450
|
-
agent_id: String,
|
|
451
|
-
provider: Provider,
|
|
452
|
-
path: String,
|
|
453
|
-
reason: String,
|
|
454
|
-
provider_process_dead: bool,
|
|
455
|
-
dead_process: bool,
|
|
456
|
-
latest_explicit_error: bool,
|
|
457
|
-
},
|
|
458
|
-
#[serde(rename = "abnormal.whole_team_gone")]
|
|
459
|
-
AbnormalWholeTeamGone { classification: WholeTeamGoneClass },
|
|
460
|
-
#[serde(rename = "leader_notification.log_pruned")]
|
|
461
|
-
LeaderNotificationLogPruned { removed: u64 },
|
|
462
|
-
#[serde(rename = "leader_notification.prune_failed")]
|
|
463
|
-
LeaderNotificationPruneFailed { error: String },
|
|
464
|
-
#[serde(rename = "runtime.state.save_failed")]
|
|
465
|
-
RuntimeStateSaveFailed {
|
|
466
|
-
phase: String,
|
|
467
|
-
error: String,
|
|
468
|
-
exc_type: String,
|
|
469
|
-
},
|
|
470
|
-
}
|
|
471
|
-
|
|
472
356
|
// ===========================================================================
|
|
473
357
|
// 异常轨 abnormal_track(abnormal_track.py)—— provider-neutral 数据型
|
|
474
358
|
// ===========================================================================
|
|
475
359
|
|
|
476
|
-
/// `_classify` 决策(`abnormal_track.py:198-204`)。whitelist > blacklist > default(C9 catch-bias)。
|
|
477
|
-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
478
|
-
#[serde(rename_all = "snake_case")]
|
|
479
|
-
pub enum AbnormalDecision {
|
|
480
|
-
/// whitelist 命中 → 不通知(`abnormal_track.py:201`)。
|
|
481
|
-
Skip,
|
|
482
|
-
/// blacklist 命中 → 通知(`abnormal_track.py:203`)。
|
|
483
|
-
NotifyBlacklist,
|
|
484
|
-
/// 结构化 fault 默认通知(C9 catch-bias,`abnormal_track.py:204`)。
|
|
485
|
-
NotifyDefault,
|
|
486
|
-
}
|
|
487
|
-
|
|
488
360
|
/// `detect_whole_team_gone` 分类(`abnormal_track.py:130/132/143`)。
|
|
489
361
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
490
362
|
#[serde(rename_all = "snake_case")]
|
|
@@ -498,35 +370,6 @@ pub enum WholeTeamGoneClass {
|
|
|
498
370
|
UnexpectedExit,
|
|
499
371
|
}
|
|
500
372
|
|
|
501
|
-
/// `process_abnormal_records` 单条通知(`abnormal_track.py:70-79`)。
|
|
502
|
-
/// dedup key = `(signature, turn_id|fingerprint)`(C8,`abnormal_track.py:64-66`):turn_id 缺失退化为
|
|
503
|
-
/// per-record content fingerprint 桶,**绝不**把不同 fault 折叠进一个全局桶。
|
|
504
|
-
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
505
|
-
pub struct AbnormalNotification {
|
|
506
|
-
pub signature: String,
|
|
507
|
-
pub turn_id: Option<TurnId>,
|
|
508
|
-
/// `kind == "approval"` → blocked_on_human,否则 abnormal(`abnormal_track.py:74`)。
|
|
509
|
-
pub state: TurnState,
|
|
510
|
-
pub decision: AbnormalDecision,
|
|
511
|
-
pub provider: Option<Provider>,
|
|
512
|
-
/// 原始 fault fact(provider reader 产出的结构化记录;本 module 不读屏不命名 provider)。
|
|
513
|
-
pub raw: Value,
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
/// `process_abnormal_records` 返回(`abnormal_track.py:83-88` typed 版)。
|
|
517
|
-
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
518
|
-
pub struct AbnormalProcessOutput {
|
|
519
|
-
pub notifications: Vec<AbnormalNotification>,
|
|
520
|
-
/// 更新后的去重状态(`seen` 集合,`abnormal_track.py:82`)——caller 回存。
|
|
521
|
-
pub notification_state: AbnormalNotificationState,
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/// abnormal 去重状态(`abnormal_track.py:31-32,82`)。`seen` = `signature\0bucket` key 集合。
|
|
525
|
-
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
|
526
|
-
pub struct AbnormalNotificationState {
|
|
527
|
-
pub seen: BTreeSet<String>,
|
|
528
|
-
}
|
|
529
|
-
|
|
530
373
|
/// `detect_whole_team_gone` 返回(`abnormal_track.py:140-147` typed 版)。
|
|
531
374
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
532
375
|
pub struct WholeTeamGoneReport {
|
|
@@ -551,13 +394,6 @@ pub struct TeamPresenceSnapshot {
|
|
|
551
394
|
pub restart_in_progress: bool,
|
|
552
395
|
}
|
|
553
396
|
|
|
554
|
-
/// abnormal track 错误(provider reader 翻译 fault facts 失败)。
|
|
555
|
-
#[derive(Debug, Error)]
|
|
556
|
-
pub enum AbnormalError {
|
|
557
|
-
#[error("provider: {0}")]
|
|
558
|
-
Provider(#[from] crate::provider::ProviderError),
|
|
559
|
-
}
|
|
560
|
-
|
|
561
397
|
// ===========================================================================
|
|
562
398
|
// WatchCursor(watch/__init__.py)
|
|
563
399
|
// ===========================================================================
|
|
@@ -591,15 +427,6 @@ pub use crate::model::ids::AgentId;
|
|
|
591
427
|
pub trait ProviderRegistry {
|
|
592
428
|
/// 拿某 provider 的 adapter(`providers.get_adapter`)。
|
|
593
429
|
fn adapter_for(&self, provider: Provider) -> Box<dyn ProviderAdapter>;
|
|
594
|
-
/// 该 provider 的 error 黑白名单(`get_provider_registry(provider)["error_lists"]`,abnormal_track 用)。
|
|
595
|
-
fn error_lists(&self, provider: Provider) -> ErrorLists;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
/// provider error 黑白名单(`abnormal_track.py:184-195`)。**PLACEHOLDER**(step 8 拥有)。
|
|
599
|
-
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
|
600
|
-
pub struct ErrorLists {
|
|
601
|
-
pub whitelist: Vec<String>,
|
|
602
|
-
pub blacklist: Vec<String>,
|
|
603
430
|
}
|
|
604
431
|
|
|
605
432
|
/// idle take-over 候选 node(`idle_takeover_wiring.build_idle_nodes`,step 8/11 拥有真名)。
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// physical relocation (zero behavior change).
|
|
5
5
|
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
|
|
6
6
|
|
|
7
|
+
//!
|
|
7
8
|
//! step 7 · message_store — core message lifecycle over `team.db`.
|
|
8
9
|
//!
|
|
9
10
|
//! Truth source (READ-ONLY): `team-agent-public` @ v0.2.11,
|
|
@@ -205,7 +206,7 @@ pub struct PersistMessageInput<'a> {
|
|
|
205
206
|
|
|
206
207
|
/// `leader_notification_log._legacy_epoch_from_uuid` (line 145-147):
|
|
207
208
|
/// `int(zlib.crc32(str(uuid or "").encode("utf-8")) & 0x7FFFFFFF)`.
|
|
208
|
-
|
|
209
|
+
fn legacy_epoch_from_uuid(leader_session_uuid: Option<&str>) -> i64 {
|
|
209
210
|
let mut crc = 0xFFFF_FFFFu32;
|
|
210
211
|
for byte in leader_session_uuid.unwrap_or("").as_bytes() {
|
|
211
212
|
crc ^= u32::from(*byte);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//!
|
|
1
2
|
//! `team.db` 列布局迁移(Gap 46;真相源 `message_store/schema_migration.py`)。
|
|
2
3
|
//!
|
|
3
4
|
//! 检测**物理列序漂移**(`pragma table_info` 顺序 vs canonical),在**一个原子事务**
|
|
@@ -141,7 +142,7 @@ fn create_table_ddl(table: &str, name: &str) -> Option<String> {
|
|
|
141
142
|
|
|
142
143
|
/// 一张表的布局 diff。
|
|
143
144
|
#[derive(Debug, Clone)]
|
|
144
|
-
|
|
145
|
+
struct Diff {
|
|
145
146
|
pub table: &'static str,
|
|
146
147
|
pub expected: Vec<&'static str>,
|
|
147
148
|
pub actual: Vec<String>,
|
|
@@ -187,7 +188,7 @@ fn table_count(conn: &Connection, table: &str) -> Result<i64, DbError> {
|
|
|
187
188
|
Ok(conn.query_row(&format!("select count(*) from {table}"), [], |r| r.get(0))?)
|
|
188
189
|
}
|
|
189
190
|
|
|
190
|
-
|
|
191
|
+
fn pragma_user_version(conn: &Connection) -> Result<i64, DbError> {
|
|
191
192
|
Ok(conn.query_row("pragma user_version", [], |r| r.get(0))?)
|
|
192
193
|
}
|
|
193
194
|
|
|
@@ -230,7 +231,7 @@ fn run_version_migrations(conn: &Connection, schema_version: i64) -> Result<(),
|
|
|
230
231
|
|
|
231
232
|
/// `schema_migration.py:_layout_diffs`:按 `table_info` 物理列序检测漂移。
|
|
232
233
|
/// 无任何 managed 表存在(fresh DB)→ 空(initialize 随后建表)。
|
|
233
|
-
|
|
234
|
+
fn layout_diffs(conn: &Connection) -> Result<Vec<Diff>, DbError> {
|
|
234
235
|
let mut any = false;
|
|
235
236
|
for (t, _) in MANAGED_TABLE_LAYOUTS {
|
|
236
237
|
if table_exists(conn, t)? {
|
|
@@ -419,7 +420,7 @@ pub fn ensure_table_layout(
|
|
|
419
420
|
}
|
|
420
421
|
|
|
421
422
|
/// `schema_migration.py:schema_diagnosis`:只读判定(不变更 DB)。
|
|
422
|
-
|
|
423
|
+
fn schema_diagnosis(db_path: &Path, schema_version: i64) -> Result<Diagnosis, DbError> {
|
|
423
424
|
if !db_path.exists() {
|
|
424
425
|
// T3-3 cr verdict (A parity lock, 2026-06-10): a missing db is the LEGAL
|
|
425
426
|
// first-use state — ok:true is layered with the explicit status axis and the
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
use std::path::Path;
|
|
2
3
|
|
|
3
4
|
use serde_json::{json, Value};
|
|
@@ -212,7 +213,7 @@ fn verifies_json(check: &SelftestCheck) -> Value {
|
|
|
212
213
|
serde_json::to_value(check.verifies).unwrap_or_else(|_| json!("unknown"))
|
|
213
214
|
}
|
|
214
215
|
|
|
215
|
-
|
|
216
|
+
fn receiver_binding_mismatches(
|
|
216
217
|
owner_pane_id: &Value,
|
|
217
218
|
caller_pane_id: &Value,
|
|
218
219
|
pane_id: &Value,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//!
|
|
1
2
|
//! 0.3.28 layout step 2 — leader placement.
|
|
2
3
|
//!
|
|
3
4
|
//! Public API for managed-mode leader placement. The runtime calls
|
|
@@ -34,6 +35,7 @@ pub enum LeaderPlacement {
|
|
|
34
35
|
},
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
///
|
|
37
39
|
/// Compute the placement for a leader given its identity, the desired
|
|
38
40
|
/// `LeaderStartMode`, and the environment (used to detect `$TMUX`).
|
|
39
41
|
///
|
|
@@ -58,13 +60,6 @@ pub fn leader_placement(
|
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
/// The leader session name for a given provider + workspace. `LeaderIdentity`
|
|
62
|
-
/// in this codebase does not carry the provider field; the caller supplies it
|
|
63
|
-
/// explicitly (matches how `leader_session_name` itself is shaped).
|
|
64
|
-
pub fn leader_session_for_provider(provider: Provider, workspace: &Path) -> SessionName {
|
|
65
|
-
leader_session_name(provider, workspace)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
63
|
#[allow(dead_code)]
|
|
69
64
|
fn _unused_identity_marker(_id: &LeaderIdentity) {}
|
|
70
65
|
|
|
@@ -74,6 +69,7 @@ use crate::layout::placement::{WorkerSpawnAction, WorkerSpawnTarget};
|
|
|
74
69
|
use crate::model::yaml::Value as YamlValue;
|
|
75
70
|
use crate::transport::Transport;
|
|
76
71
|
|
|
72
|
+
///
|
|
77
73
|
/// Compute the spawn target for a worker. Python parity: one window per
|
|
78
74
|
/// agent in the worker session, named after `agent_id`. First worker
|
|
79
75
|
/// (= session does not yet exist) → NewSession; otherwise NewWindow.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//!
|
|
1
2
|
//! 0.3.28 — Unified adaptive layout manager.
|
|
2
3
|
//!
|
|
3
4
|
//! Single source of truth for tmux topology decisions in the runtime:
|
|
@@ -31,6 +32,5 @@ pub mod worker_env;
|
|
|
31
32
|
pub mod worker_window_helpers;
|
|
32
33
|
|
|
33
34
|
pub use runtime_sessions::{
|
|
34
|
-
LeaderLauncherSession,
|
|
35
|
-
WorkerSession, WorkerSessionError,
|
|
35
|
+
LeaderLauncherSession, RuntimeSessionAnomaly, RuntimeSessions, WorkerSession,
|
|
36
36
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//!
|
|
1
2
|
//! 0.3.28 layout step 8 — display overlay (3-pane tiling).
|
|
2
3
|
//!
|
|
3
4
|
//! Python truth source: 3-pane tiling exists ONLY in the display overlay
|
|
@@ -15,6 +16,7 @@ use crate::transport::{SessionName, WindowName};
|
|
|
15
16
|
/// 3 panes per overlay window — Python parity.
|
|
16
17
|
pub const OVERLAY_PANES_PER_WINDOW: usize = 3;
|
|
17
18
|
|
|
19
|
+
///
|
|
18
20
|
/// Overlay window name for a 0-based group index. Index 0 → `overview`;
|
|
19
21
|
/// N ≥ 1 → `overview-{N+1}`. Names are scoped by `session_tag` so multiple
|
|
20
22
|
/// teams can coexist on one leader session.
|
|
@@ -38,6 +40,7 @@ pub struct OverlayPlacement {
|
|
|
38
40
|
pub window: WindowName,
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
///
|
|
41
44
|
/// Compute the overlay placements for a list of agent_ids. Deterministic by
|
|
42
45
|
/// input order: agent `i` → window `i / 3`, slot `i % 3`.
|
|
43
46
|
pub fn plan_overlay_placements(session_tag: &str, agents: &[&str]) -> Vec<OverlayPlacement> {
|
|
@@ -53,9 +56,10 @@ pub fn plan_overlay_placements(session_tag: &str, agents: &[&str]) -> Vec<Overla
|
|
|
53
56
|
.collect()
|
|
54
57
|
}
|
|
55
58
|
|
|
59
|
+
///
|
|
56
60
|
/// True when a window name belongs to a display overlay (matches
|
|
57
61
|
/// `team-agent:<...>:overview[-N]`).
|
|
58
|
-
|
|
62
|
+
fn is_overlay_window(name: &WindowName) -> bool {
|
|
59
63
|
let n = name.as_str();
|
|
60
64
|
if !n.starts_with("team-agent:") {
|
|
61
65
|
return false;
|
|
@@ -63,6 +67,7 @@ pub fn is_overlay_window(name: &WindowName) -> bool {
|
|
|
63
67
|
n.contains(":overview")
|
|
64
68
|
}
|
|
65
69
|
|
|
70
|
+
///
|
|
66
71
|
/// 0.3.28 Step 8 invariant: `spawn_split` may ONLY be called from the
|
|
67
72
|
/// overlay module. This helper emits a warn-level event when called from
|
|
68
73
|
/// anywhere else (Step 9 promotes to a hard error / panic gate). The
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//!
|
|
1
2
|
//! 0.3.28 layout step 7 — leader pane recovery.
|
|
2
3
|
//!
|
|
3
4
|
//! Python truth source (`leader/__init__.py:885-887` +
|
|
@@ -28,6 +29,7 @@ pub enum RecoveryOutcome {
|
|
|
28
29
|
NeedsUserAttach,
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
///
|
|
31
33
|
/// Compute the recovery outcome from the current environment.
|
|
32
34
|
///
|
|
33
35
|
/// Reads `TMUX_PANE` from the supplied environment iterator (use
|
|
@@ -44,6 +46,7 @@ where
|
|
|
44
46
|
RecoveryOutcome::NeedsUserAttach
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
///
|
|
47
50
|
/// Emit the canonical `leader_receiver.rebind_required` event when the
|
|
48
51
|
/// runtime falls through to `NeedsUserAttach`. Logs to stderr so operators
|
|
49
52
|
/// see the cascade in event logs.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//!
|
|
1
2
|
//! unit-1 (Stage 1) — typed runtime session identity.
|
|
2
3
|
//!
|
|
3
4
|
//! Provides two compile-time-distinct newtypes plus a `RuntimeSessions`
|
|
@@ -35,7 +36,7 @@ pub struct LeaderLauncherSession(SessionName);
|
|
|
35
36
|
|
|
36
37
|
/// Why `WorkerSession::new` rejected a name.
|
|
37
38
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
38
|
-
|
|
39
|
+
enum WorkerSessionError {
|
|
39
40
|
/// The name is empty.
|
|
40
41
|
Empty,
|
|
41
42
|
/// The name carries the leader launcher prefix — must not be a worker
|
|
@@ -45,7 +46,7 @@ pub enum WorkerSessionError {
|
|
|
45
46
|
|
|
46
47
|
/// Why `LeaderLauncherSession::new` rejected a name.
|
|
47
48
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
48
|
-
|
|
49
|
+
enum LeaderLauncherSessionError {
|
|
49
50
|
/// The name is empty.
|
|
50
51
|
Empty,
|
|
51
52
|
/// The name does not carry the required leader launcher prefix.
|
|
@@ -136,6 +137,7 @@ pub enum RuntimeSessionAnomaly {
|
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
impl RuntimeSessions {
|
|
140
|
+
///
|
|
139
141
|
/// Read state.json's session-identity fields and wrap them in typed
|
|
140
142
|
/// values. Never panics on bad state — anomalies are surfaced for
|
|
141
143
|
/// callers to act on.
|
|
@@ -197,11 +199,13 @@ impl RuntimeSessions {
|
|
|
197
199
|
}
|
|
198
200
|
}
|
|
199
201
|
|
|
202
|
+
///
|
|
200
203
|
/// True if any session-identity anomaly was detected in state.
|
|
201
204
|
pub fn has_anomalies(&self) -> bool {
|
|
202
205
|
!self.anomalies.is_empty()
|
|
203
206
|
}
|
|
204
207
|
|
|
208
|
+
///
|
|
205
209
|
/// True if a `state.session_name` looked like a leader launcher session
|
|
206
210
|
/// — the exact 0.3.39 shape unit-3 must refuse before any kill.
|
|
207
211
|
pub fn worker_session_name_is_leader_prefixed(&self) -> bool {
|
|
@@ -214,9 +218,10 @@ impl RuntimeSessions {
|
|
|
214
218
|
}
|
|
215
219
|
}
|
|
216
220
|
|
|
221
|
+
///
|
|
217
222
|
/// True when `name` is a leader launcher session (mirrors
|
|
218
223
|
/// `layout::sessions::is_leader_session` on a raw &str).
|
|
219
|
-
|
|
224
|
+
fn name_is_leader_launcher(name: &str) -> bool {
|
|
220
225
|
let session = SessionName::new(name);
|
|
221
226
|
is_leader_session(&session)
|
|
222
227
|
}
|