@team-agent/installer 0.2.11 → 0.3.1
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 +744 -0
- package/Cargo.toml +34 -0
- package/crates/team-agent/Cargo.toml +33 -0
- package/crates/team-agent/src/cli/adapters.rs +1343 -0
- package/crates/team-agent/src/cli/diagnose.rs +554 -0
- package/crates/team-agent/src/cli/emit.rs +1204 -0
- package/crates/team-agent/src/cli/helpers.rs +88 -0
- package/crates/team-agent/src/cli/leader.rs +216 -0
- package/crates/team-agent/src/cli/mod.rs +1207 -0
- package/crates/team-agent/src/cli/profile.rs +306 -0
- package/crates/team-agent/src/cli/send.rs +215 -0
- package/crates/team-agent/src/cli/status.rs +179 -0
- package/crates/team-agent/src/cli/status_port.rs +502 -0
- package/crates/team-agent/src/cli/tests/base.rs +616 -0
- package/crates/team-agent/src/cli/tests/compile.rs +96 -0
- package/crates/team-agent/src/cli/tests/divergence.rs +509 -0
- package/crates/team-agent/src/cli/tests/lane_c.rs +333 -0
- package/crates/team-agent/src/cli/tests/leader_watch.rs +395 -0
- package/crates/team-agent/src/cli/tests/main_preserved.rs +675 -0
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +390 -0
- package/crates/team-agent/src/cli/tests/mod.rs +97 -0
- package/crates/team-agent/src/cli/tests/peer_allow.rs +137 -0
- package/crates/team-agent/src/cli/tests/repair_state_byte_lock.rs +302 -0
- package/crates/team-agent/src/cli/tests/run_delegation.rs +305 -0
- package/crates/team-agent/src/cli/tests/status_send.rs +385 -0
- package/crates/team-agent/src/cli/tests/verb_profile.rs +182 -0
- package/crates/team-agent/src/cli/tests/verb_settle.rs +236 -0
- package/crates/team-agent/src/cli/tests/verb_validate.rs +184 -0
- package/crates/team-agent/src/cli/types.rs +605 -0
- package/crates/team-agent/src/compiler/tests.rs +701 -0
- package/crates/team-agent/src/compiler.rs +489 -0
- package/crates/team-agent/src/coordinator/backoff.rs +153 -0
- package/crates/team-agent/src/coordinator/health.rs +557 -0
- package/crates/team-agent/src/coordinator/mod.rs +80 -0
- package/crates/team-agent/src/coordinator/orphan.rs +179 -0
- package/crates/team-agent/src/coordinator/tests/abnormal.rs +255 -0
- package/crates/team-agent/src/coordinator/tests/basics.rs +262 -0
- package/crates/team-agent/src/coordinator/tests/daemon.rs +323 -0
- package/crates/team-agent/src/coordinator/tests/health_sync.rs +263 -0
- package/crates/team-agent/src/coordinator/tests/main_preserved.rs +136 -0
- package/crates/team-agent/src/coordinator/tests/mod.rs +310 -0
- package/crates/team-agent/src/coordinator/tests/spine.rs +261 -0
- package/crates/team-agent/src/coordinator/tests/takeover.rs +227 -0
- package/crates/team-agent/src/coordinator/tests/tick_core.rs +256 -0
- package/crates/team-agent/src/coordinator/tests/watch.rs +167 -0
- package/crates/team-agent/src/coordinator/tick.rs +2032 -0
- package/crates/team-agent/src/coordinator/types.rs +584 -0
- package/crates/team-agent/src/db/migration.rs +716 -0
- package/crates/team-agent/src/db/mod.rs +23 -0
- package/crates/team-agent/src/db/schema.rs +378 -0
- package/crates/team-agent/src/event_log.rs +375 -0
- package/crates/team-agent/src/fake_worker.rs +253 -0
- package/crates/team-agent/src/leader/helpers.rs +190 -0
- package/crates/team-agent/src/leader/inject.rs +33 -0
- package/crates/team-agent/src/leader/lease.rs +1084 -0
- package/crates/team-agent/src/leader/mod.rs +99 -0
- package/crates/team-agent/src/leader/owner_bind.rs +292 -0
- package/crates/team-agent/src/leader/rediscover/tests.rs +526 -0
- package/crates/team-agent/src/leader/rediscover.rs +1101 -0
- package/crates/team-agent/src/leader/start.rs +273 -0
- package/crates/team-agent/src/leader/takeover.rs +235 -0
- package/crates/team-agent/src/leader/tests/basics.rs +183 -0
- package/crates/team-agent/src/leader/tests/byte_findings.rs +237 -0
- package/crates/team-agent/src/leader/tests/identity.rs +206 -0
- package/crates/team-agent/src/leader/tests/idle.rs +272 -0
- package/crates/team-agent/src/leader/tests/lease_api.rs +225 -0
- package/crates/team-agent/src/leader/tests/lease_claim.rs +410 -0
- package/crates/team-agent/src/leader/tests/mod.rs +125 -0
- package/crates/team-agent/src/leader/tests/rediscover.rs +351 -0
- package/crates/team-agent/src/leader/tests/wake_start_owner.rs +204 -0
- package/crates/team-agent/src/leader/types.rs +489 -0
- package/crates/team-agent/src/lib.rs +85 -0
- package/crates/team-agent/src/lifecycle/display.rs +228 -0
- package/crates/team-agent/src/lifecycle/helpers.rs +112 -0
- package/crates/team-agent/src/lifecycle/launch/plan.rs +227 -0
- package/crates/team-agent/src/lifecycle/launch.rs +2109 -0
- package/crates/team-agent/src/lifecycle/mod.rs +62 -0
- package/crates/team-agent/src/lifecycle/restart/agent.rs +533 -0
- package/crates/team-agent/src/lifecycle/restart/common.rs +517 -0
- package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +41 -0
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +268 -0
- package/crates/team-agent/src/lifecycle/restart/remove.rs +780 -0
- package/crates/team-agent/src/lifecycle/restart/selection.rs +208 -0
- package/crates/team-agent/src/lifecycle/restart/team_state.rs +242 -0
- package/crates/team-agent/src/lifecycle/restart.rs +76 -0
- package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +455 -0
- package/crates/team-agent/src/lifecycle/tests/core.rs +989 -0
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +583 -0
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +985 -0
- package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +265 -0
- package/crates/team-agent/src/lifecycle/tests.rs +27 -0
- package/crates/team-agent/src/lifecycle/types.rs +710 -0
- package/crates/team-agent/src/main.rs +41 -0
- package/crates/team-agent/src/mcp_server/helpers.rs +228 -0
- package/crates/team-agent/src/mcp_server/mod.rs +183 -0
- package/crates/team-agent/src/mcp_server/normalize.rs +312 -0
- package/crates/team-agent/src/mcp_server/tests/golden.rs +283 -0
- package/crates/team-agent/src/mcp_server/tests/normalize.rs +244 -0
- package/crates/team-agent/src/mcp_server/tests/scoped.rs +189 -0
- package/crates/team-agent/src/mcp_server/tests/send.rs +222 -0
- package/crates/team-agent/src/mcp_server/tests/tools.rs +158 -0
- package/crates/team-agent/src/mcp_server/tests/wire.rs +187 -0
- package/crates/team-agent/src/mcp_server/tests.rs +38 -0
- package/crates/team-agent/src/mcp_server/tools.rs +603 -0
- package/crates/team-agent/src/mcp_server/types.rs +421 -0
- package/crates/team-agent/src/mcp_server/wire.rs +468 -0
- package/crates/team-agent/src/message_store.rs +767 -0
- package/crates/team-agent/src/messaging/activity.rs +433 -0
- package/crates/team-agent/src/messaging/delivery.rs +743 -0
- package/crates/team-agent/src/messaging/helpers.rs +209 -0
- package/crates/team-agent/src/messaging/leader_receiver.rs +329 -0
- package/crates/team-agent/src/messaging/mod.rs +147 -0
- package/crates/team-agent/src/messaging/peers.rs +32 -0
- package/crates/team-agent/src/messaging/results.rs +553 -0
- package/crates/team-agent/src/messaging/scheduler.rs +344 -0
- package/crates/team-agent/src/messaging/selftest.rs +100 -0
- package/crates/team-agent/src/messaging/send.rs +578 -0
- package/crates/team-agent/src/messaging/tests/basic.rs +357 -0
- package/crates/team-agent/src/messaging/tests/main_preserved.rs +122 -0
- package/crates/team-agent/src/messaging/tests/mod.rs +293 -0
- package/crates/team-agent/src/messaging/tests/runtime.rs +1422 -0
- package/crates/team-agent/src/messaging/tests/spine.rs +437 -0
- package/crates/team-agent/src/messaging/trust.rs +192 -0
- package/crates/team-agent/src/messaging/types.rs +355 -0
- package/crates/team-agent/src/messaging/watchers.rs +591 -0
- package/crates/team-agent/src/model/enums.rs +311 -0
- package/crates/team-agent/src/model/errors.rs +17 -0
- package/crates/team-agent/src/model/ids.rs +155 -0
- package/crates/team-agent/src/model/mod.rs +22 -0
- package/crates/team-agent/src/model/paths.rs +228 -0
- package/crates/team-agent/src/model/permissions.rs +567 -0
- package/crates/team-agent/src/model/routing.rs +340 -0
- package/crates/team-agent/src/model/spec.rs +680 -0
- package/crates/team-agent/src/model/task_graph.rs +380 -0
- package/crates/team-agent/src/model/testdata/fuzz.golden.yaml +43 -0
- package/crates/team-agent/src/model/testdata/fuzz.yaml +43 -0
- package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +207 -0
- package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +206 -0
- package/crates/team-agent/src/model/testdata/team.spec.yaml +206 -0
- package/crates/team-agent/src/model/yaml/tests.rs +288 -0
- package/crates/team-agent/src/model/yaml.rs +800 -0
- package/crates/team-agent/src/packaging/install.rs +305 -0
- package/crates/team-agent/src/packaging/migrate.rs +30 -0
- package/crates/team-agent/src/packaging/mod.rs +82 -0
- package/crates/team-agent/src/packaging/repair.rs +24 -0
- package/crates/team-agent/src/packaging/tests.rs +829 -0
- package/crates/team-agent/src/packaging/types.rs +369 -0
- package/crates/team-agent/src/provider/adapter.rs +801 -0
- package/crates/team-agent/src/provider/approvals/mod.rs +2 -0
- package/crates/team-agent/src/provider/approvals/parsing.rs +452 -0
- package/crates/team-agent/src/provider/approvals/runtime_prompts.rs +163 -0
- package/crates/team-agent/src/provider/classify.rs +456 -0
- package/crates/team-agent/src/provider/faults.rs +136 -0
- package/crates/team-agent/src/provider/helpers.rs +41 -0
- package/crates/team-agent/src/provider/mod.rs +53 -0
- package/crates/team-agent/src/provider/startup_prompt.rs +423 -0
- package/crates/team-agent/src/provider/tests/adapter.rs +239 -0
- package/crates/team-agent/src/provider/tests/classify.rs +240 -0
- package/crates/team-agent/src/provider/tests/faults.rs +120 -0
- package/crates/team-agent/src/provider/tests/idle.rs +208 -0
- package/crates/team-agent/src/provider/tests/wire.rs +213 -0
- package/crates/team-agent/src/provider/tests.rs +31 -0
- package/crates/team-agent/src/provider/types.rs +424 -0
- package/crates/team-agent/src/state/identity.rs +659 -0
- package/crates/team-agent/src/state/mod.rs +58 -0
- package/crates/team-agent/src/state/owner_gate.rs +423 -0
- package/crates/team-agent/src/state/persist.rs +712 -0
- package/crates/team-agent/src/state/projection.rs +657 -0
- package/crates/team-agent/src/state/selector.rs +105 -0
- package/crates/team-agent/src/state/testdata/state-rich.canonical.json +133 -0
- package/crates/team-agent/src/tmux_backend/tests.rs +765 -0
- package/crates/team-agent/src/tmux_backend.rs +810 -0
- package/crates/team-agent/src/transport/test_support.rs +252 -0
- package/crates/team-agent/src/transport/tests/behavior.rs +327 -0
- package/crates/team-agent/src/transport/tests/mod.rs +199 -0
- package/crates/team-agent/src/transport/tests/wire.rs +527 -0
- package/crates/team-agent/src/transport.rs +774 -0
- package/npm/install.mjs +118 -112
- package/package.json +15 -13
- package/crates/team-agent-core/Cargo.toml +0 -12
- package/crates/team-agent-core/src/lib.rs +0 -332
- package/crates/team-agent-core/src/main.rs +0 -152
- package/pyproject.toml +0 -18
- package/scripts/install.py +0 -88
- package/scripts/run_regression_tests.py +0 -83
- package/src/team_agent/__init__.py +0 -3
- package/src/team_agent/__main__.py +0 -5
- package/src/team_agent/_legacy_pane_discovery.py +0 -186
- package/src/team_agent/abnormal_track.py +0 -253
- package/src/team_agent/approvals/__init__.py +0 -65
- package/src/team_agent/approvals/constants.py +0 -6
- package/src/team_agent/approvals/parsing.py +0 -176
- package/src/team_agent/approvals/runtime_prompts.py +0 -171
- package/src/team_agent/approvals/status.py +0 -176
- package/src/team_agent/cli/__init__.py +0 -137
- package/src/team_agent/cli/commands.py +0 -481
- package/src/team_agent/cli/e2e.py +0 -202
- package/src/team_agent/cli/helpers.py +0 -226
- package/src/team_agent/cli/parser.py +0 -540
- package/src/team_agent/compiler.py +0 -334
- package/src/team_agent/coordinator/__init__.py +0 -53
- package/src/team_agent/coordinator/__main__.py +0 -119
- package/src/team_agent/coordinator/lifecycle.py +0 -411
- package/src/team_agent/coordinator/metadata.py +0 -61
- package/src/team_agent/coordinator/paths.py +0 -17
- package/src/team_agent/diagnose/__init__.py +0 -48
- package/src/team_agent/diagnose/checks.py +0 -101
- package/src/team_agent/diagnose/comms.py +0 -213
- package/src/team_agent/diagnose/health.py +0 -241
- package/src/team_agent/diagnose/orphan_cleanup.py +0 -364
- package/src/team_agent/diagnose/preflight.py +0 -194
- package/src/team_agent/diagnose/quick_start.py +0 -324
- package/src/team_agent/display/__init__.py +0 -92
- package/src/team_agent/display/adaptive.py +0 -511
- package/src/team_agent/display/backend.py +0 -46
- package/src/team_agent/display/close.py +0 -154
- package/src/team_agent/display/ghostty.py +0 -77
- package/src/team_agent/display/rebuild.py +0 -102
- package/src/team_agent/display/tiling.py +0 -156
- package/src/team_agent/display/worker_window.py +0 -114
- package/src/team_agent/display/workspace.py +0 -382
- package/src/team_agent/errors.py +0 -10
- package/src/team_agent/events.py +0 -84
- package/src/team_agent/fake_worker.py +0 -80
- package/src/team_agent/idle_predicate.py +0 -218
- package/src/team_agent/idle_takeover.py +0 -59
- package/src/team_agent/idle_takeover_wiring.py +0 -114
- package/src/team_agent/launch/__init__.py +0 -41
- package/src/team_agent/launch/bootstrap.py +0 -85
- package/src/team_agent/launch/config.py +0 -106
- package/src/team_agent/launch/core.py +0 -301
- package/src/team_agent/launch/requirements.py +0 -57
- package/src/team_agent/leader/__init__.py +0 -926
- package/src/team_agent/leader_binding.py +0 -183
- package/src/team_agent/lifecycle/__init__.py +0 -5
- package/src/team_agent/lifecycle/agents.py +0 -278
- package/src/team_agent/lifecycle/operations.py +0 -411
- package/src/team_agent/lifecycle/paste_buffer_hygiene.py +0 -39
- package/src/team_agent/lifecycle/start.py +0 -363
- package/src/team_agent/mcp_server/__init__.py +0 -42
- package/src/team_agent/mcp_server/__main__.py +0 -7
- package/src/team_agent/mcp_server/contracts.py +0 -148
- package/src/team_agent/mcp_server/normalize.py +0 -257
- package/src/team_agent/mcp_server/server.py +0 -150
- package/src/team_agent/mcp_server/tools.py +0 -352
- package/src/team_agent/message_store/__init__.py +0 -23
- package/src/team_agent/message_store/agent_health.py +0 -113
- package/src/team_agent/message_store/core.py +0 -497
- package/src/team_agent/message_store/leader_notification_log.py +0 -198
- package/src/team_agent/message_store/result_watchers.py +0 -251
- package/src/team_agent/message_store/schema.py +0 -308
- package/src/team_agent/message_store/schema_migration.py +0 -448
- package/src/team_agent/messaging/__init__.py +0 -1
- package/src/team_agent/messaging/activity_detector.py +0 -262
- package/src/team_agent/messaging/delivery.py +0 -504
- package/src/team_agent/messaging/deps.py +0 -247
- package/src/team_agent/messaging/idle_alerts.py +0 -423
- package/src/team_agent/messaging/internal_delivery.py +0 -46
- package/src/team_agent/messaging/leader.py +0 -497
- package/src/team_agent/messaging/leader_api_errors.py +0 -216
- package/src/team_agent/messaging/leader_panes.py +0 -673
- package/src/team_agent/messaging/owner_bypass.py +0 -29
- package/src/team_agent/messaging/result_delivery.py +0 -539
- package/src/team_agent/messaging/results.py +0 -447
- package/src/team_agent/messaging/scheduler.py +0 -450
- package/src/team_agent/messaging/send.py +0 -532
- package/src/team_agent/messaging/session_drift.py +0 -94
- package/src/team_agent/messaging/tmux_io.py +0 -506
- package/src/team_agent/messaging/tmux_prompt.py +0 -338
- package/src/team_agent/messaging/trust_auto_answer.py +0 -52
- package/src/team_agent/orchestrator/__init__.py +0 -376
- package/src/team_agent/orchestrator/plan.py +0 -122
- package/src/team_agent/orchestrator/state.py +0 -128
- package/src/team_agent/paths.py +0 -45
- package/src/team_agent/permissions.py +0 -123
- package/src/team_agent/profiles/__init__.py +0 -82
- package/src/team_agent/profiles/constants.py +0 -19
- package/src/team_agent/profiles/core.py +0 -407
- package/src/team_agent/profiles/helpers.py +0 -69
- package/src/team_agent/profiles/provider_env.py +0 -188
- package/src/team_agent/profiles/smoke.py +0 -201
- package/src/team_agent/provider_cli/__init__.py +0 -43
- package/src/team_agent/provider_cli/adapter.py +0 -172
- package/src/team_agent/provider_cli/base.py +0 -48
- package/src/team_agent/provider_cli/claude.py +0 -503
- package/src/team_agent/provider_cli/codex.py +0 -336
- package/src/team_agent/provider_cli/copilot.py +0 -8
- package/src/team_agent/provider_cli/fake.py +0 -39
- package/src/team_agent/provider_cli/gemini.py +0 -95
- package/src/team_agent/provider_cli/opencode.py +0 -8
- package/src/team_agent/provider_cli/prompt.py +0 -62
- package/src/team_agent/provider_cli/registry.py +0 -18
- package/src/team_agent/provider_cli/unsupported.py +0 -32
- package/src/team_agent/provider_state/README.md +0 -78
- package/src/team_agent/provider_state/__init__.py +0 -91
- package/src/team_agent/provider_state/claude.py +0 -86
- package/src/team_agent/provider_state/codex.py +0 -84
- package/src/team_agent/provider_state/common.py +0 -207
- package/src/team_agent/provider_state/registry.py +0 -118
- package/src/team_agent/providers.py +0 -163
- package/src/team_agent/quality_gates.py +0 -104
- package/src/team_agent/restart/__init__.py +0 -34
- package/src/team_agent/restart/orchestration.py +0 -554
- package/src/team_agent/restart/selection.py +0 -89
- package/src/team_agent/restart/snapshot.py +0 -70
- package/src/team_agent/routing.py +0 -84
- package/src/team_agent/runtime.py +0 -1243
- package/src/team_agent/rust_core.py +0 -327
- package/src/team_agent/sessions/__init__.py +0 -25
- package/src/team_agent/sessions/capture.py +0 -144
- package/src/team_agent/sessions/inventory.py +0 -44
- package/src/team_agent/sessions/resume.py +0 -135
- package/src/team_agent/simple_yaml.py +0 -236
- package/src/team_agent/spec.py +0 -370
- package/src/team_agent/state.py +0 -693
- package/src/team_agent/status/__init__.py +0 -63
- package/src/team_agent/status/approvals.py +0 -52
- package/src/team_agent/status/compact.py +0 -158
- package/src/team_agent/status/constants.py +0 -18
- package/src/team_agent/status/inbox.py +0 -58
- package/src/team_agent/status/peek.py +0 -117
- package/src/team_agent/status/queries.py +0 -199
- package/src/team_agent/task_graph.py +0 -80
- package/src/team_agent/terminal.py +0 -57
- package/src/team_agent/wake.py +0 -58
- package/src/team_agent/watch/__init__.py +0 -145
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
//! leader 数据层 — lease/owner/incident 枚举 + struct + 错误 + cross-lane 占位/trait + 锁名常量。
|
|
2
|
+
|
|
3
|
+
use std::collections::BTreeMap;
|
|
4
|
+
use std::path::PathBuf;
|
|
5
|
+
|
|
6
|
+
use serde::{Deserialize, Serialize};
|
|
7
|
+
use serde_json::Value;
|
|
8
|
+
use thiserror::Error;
|
|
9
|
+
|
|
10
|
+
use crate::model::ids::{LeaderSessionUuid, OwnerEpoch, TeamKey};
|
|
11
|
+
use crate::provider::{Provider, RolloutPath, TurnState};
|
|
12
|
+
use crate::state::StateError;
|
|
13
|
+
use crate::transport::{PaneId, SessionName, WindowName};
|
|
14
|
+
|
|
15
|
+
// ===========================================================================
|
|
16
|
+
// ENUMS (§19 散字符串态 → 穷尽 enum;serde rename 到精确 Python 字符串,字节对齐)
|
|
17
|
+
// ===========================================================================
|
|
18
|
+
|
|
19
|
+
/// `receiver.mode`(card §22)。现只一种;留 enum 防 transport 扩展。
|
|
20
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
21
|
+
#[serde(rename_all = "snake_case")]
|
|
22
|
+
pub enum ReceiverMode {
|
|
23
|
+
DirectTmux,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// `receiver.status`(card §23)。§19 散字符串 → enum。
|
|
27
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
28
|
+
#[serde(rename_all = "snake_case")]
|
|
29
|
+
pub enum ReceiverStatus {
|
|
30
|
+
Attached,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// `discovery`(card §24)。§19 必须 enum;现 free-string。
|
|
34
|
+
/// 取自 `__init__.py` 写入点:`"attach_readopt"`(:534/550-552)、`"claim_leader"`(:876)
|
|
35
|
+
/// + `_resolve_leader_pane` 的发现路径(env / explicit / current_pane,step 9 transport)。
|
|
36
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
37
|
+
#[serde(rename_all = "snake_case")]
|
|
38
|
+
pub enum Discovery {
|
|
39
|
+
AttachReadopt,
|
|
40
|
+
StaleRediscoveryOwnerIdentity,
|
|
41
|
+
StaleRediscoveryUniqueCandidate,
|
|
42
|
+
ClaimLeader,
|
|
43
|
+
/// `$TEAM_AGENT_LEADER_PANE_ID` / `$TMUX_PANE` 直接命中(autobind / require_current)。
|
|
44
|
+
EnvPane,
|
|
45
|
+
/// 显式 `--pane` 参数指定。
|
|
46
|
+
ExplicitPane,
|
|
47
|
+
/// 当前 pane(`require_current=True`)。
|
|
48
|
+
CurrentPane,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// `claimed_via`(card §25)。§19 enum;`source` 也是 enum(见 [`LeaseSource`])。
|
|
52
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
53
|
+
#[serde(rename_all = "kebab-case")]
|
|
54
|
+
pub enum ClaimedVia {
|
|
55
|
+
/// `"claim-leader"`(`_claim_lease_no_incident` :694 / claim_leader :780)。
|
|
56
|
+
ClaimLeader,
|
|
57
|
+
/// `"attach-leader"`(`_try_readopt_leader_pane` :546)。
|
|
58
|
+
AttachLeader,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/// `attach_leader_to_state(source=...)` / `claimed_via` 的 source 维度(card §25)。
|
|
62
|
+
/// `__init__.py` 的 `source` 取值:`"manual"`(attach_leader :34)、`"launch"`/`"quick_start"`
|
|
63
|
+
/// (first-time 门 :297)、`restart` orchestration、`autobind` 的传入值。
|
|
64
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
65
|
+
#[serde(rename_all = "snake_case")]
|
|
66
|
+
pub enum LeaseSource {
|
|
67
|
+
Launch,
|
|
68
|
+
QuickStart,
|
|
69
|
+
Restart,
|
|
70
|
+
Manual,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// lease refusal `reason`(card §30 / contract C22)。闭枚举 = `_LEASE_REASON_ENUM`
|
|
74
|
+
/// (`__init__.py:372-383`) **并集** 契约 C22 的 `caller_pane_missing`
|
|
75
|
+
/// (`leader_binding.bind_owner_from_caller_pane` 的拒绝 reason)。
|
|
76
|
+
/// 命门:这是闭集,序列化字节必须与 Python 字符串一致 → impl 时锁死测试。
|
|
77
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
78
|
+
#[serde(rename_all = "snake_case")]
|
|
79
|
+
pub enum LeaseReason {
|
|
80
|
+
VacantAcquired,
|
|
81
|
+
PreviousOwnerPaneDead,
|
|
82
|
+
PreviousOwnerAliveRefused,
|
|
83
|
+
OwnerEpochAdvanced,
|
|
84
|
+
ForceConfirmRequired,
|
|
85
|
+
CallerNotLeaderShaped,
|
|
86
|
+
CallerPaneNotLive,
|
|
87
|
+
CallerCwdMismatch,
|
|
88
|
+
NotInTmuxPane,
|
|
89
|
+
/// binding 路径(`leader_binding.py`)的 `$TMUX_PANE` 缺席拒绝。
|
|
90
|
+
CallerPaneMissing,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
impl LeaseReason {
|
|
94
|
+
/// `_LEASE_REBIND_REQUIRED_REASONS`(`__init__.py:384-386`):决定 refusal 事件名
|
|
95
|
+
/// 是 `leader_receiver.rebind_required` 还是 `leader_receiver.claim_refused`。
|
|
96
|
+
pub fn is_rebind_required(self) -> bool {
|
|
97
|
+
matches!(
|
|
98
|
+
self,
|
|
99
|
+
Self::NotInTmuxPane
|
|
100
|
+
| Self::CallerNotLeaderShaped
|
|
101
|
+
| Self::CallerPaneNotLive
|
|
102
|
+
| Self::CallerCwdMismatch
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// lease 结果 `status`(card §31)。§19 enum。
|
|
108
|
+
/// `"already_bound"`/`"claimed"`/`"refused"`/`"dry_run"`(+ ambiguous claim 的 refused 子原因)。
|
|
109
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
110
|
+
#[serde(rename_all = "snake_case")]
|
|
111
|
+
pub enum LeaseStatus {
|
|
112
|
+
AlreadyBound,
|
|
113
|
+
Claimed,
|
|
114
|
+
Refused,
|
|
115
|
+
DryRun,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/// `leader_session_uuid_source`(card §35)。env override vs derived vs env-inherited。
|
|
119
|
+
/// 复刻 `_leader_identity_context`(:206)的 `"override"`/`"derived"` 二值 + caller 身份
|
|
120
|
+
/// 的 `"env"`(state::identity `caller_identity_from_env` 已用 `"explicit-override"`/`"env"`/
|
|
121
|
+
/// `"derived"`)。**NOTE(cross-lane)**:identity lane 用字符串串 `"explicit-override"`,
|
|
122
|
+
/// 此处 leader plan 用 `"override"` —— 二者来源不同函数,leader 集成时复核统一。
|
|
123
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
124
|
+
#[serde(rename_all = "snake_case")]
|
|
125
|
+
pub enum LeaderSessionUuidSource {
|
|
126
|
+
Derived,
|
|
127
|
+
Override,
|
|
128
|
+
Env,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/// wake 重读决策 reason(card §36)。`wake.py:should_reread` 五值穷尽 enum。
|
|
132
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
133
|
+
#[serde(rename_all = "snake_case")]
|
|
134
|
+
pub enum RereadReason {
|
|
135
|
+
NoFile,
|
|
136
|
+
NeverClassified,
|
|
137
|
+
FileChanged,
|
|
138
|
+
QuiescentAlreadyClassified,
|
|
139
|
+
Unchanged,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/// leader start plan 模式(`leader_start_plan` :109/111/116/123)。§19 散字符串 → enum。
|
|
143
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
144
|
+
#[serde(rename_all = "snake_case")]
|
|
145
|
+
pub enum LeaderStartMode {
|
|
146
|
+
/// `os.environ["TMUX"]` 已在 tmux 内 → exec provider in-place。
|
|
147
|
+
ExecProvider,
|
|
148
|
+
/// 无 tmux session → 新建 tmux session。
|
|
149
|
+
NewTmuxSession,
|
|
150
|
+
/// session 已存在 / `--attach-session` → attach。
|
|
151
|
+
AttachExisting,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/// 全部 leader 审计事件名(card §34)。§3 typed event kinds + §40 JSON 名与 Python
|
|
155
|
+
/// **字节级一致**。映射到 [`LeaderEvent::name`] 返回 `EventLog::write` 用的精确字符串。
|
|
156
|
+
/// (既有 `EventLog::write(&str, Value)` 仍吃裸字符串;此 enum 是 type-safe 名表,
|
|
157
|
+
/// impl 时所有 leader 审计点用它而非散字符串字面量。)
|
|
158
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
159
|
+
pub enum LeaderEvent {
|
|
160
|
+
// leader_receiver.* — `__init__.py`
|
|
161
|
+
ReceiverAttached,
|
|
162
|
+
ReceiverRebindApplied,
|
|
163
|
+
ReceiverClaimApplied,
|
|
164
|
+
ReceiverClaimRefused,
|
|
165
|
+
ReceiverRebindRequired,
|
|
166
|
+
ReceiverAttachFailed,
|
|
167
|
+
ReceiverStateDivergenceRepaired,
|
|
168
|
+
ReceiverFirstTimeEnvSeeded,
|
|
169
|
+
ReceiverAutobindSkipped,
|
|
170
|
+
ReceiverRequeuedExhaustedWatchers,
|
|
171
|
+
ReceiverAmbiguousCandidates,
|
|
172
|
+
ReceiverClaimRequeue,
|
|
173
|
+
ReceiverClaimLeaderNotification,
|
|
174
|
+
// owner.* — `__init__.py` + `leader_binding.py`
|
|
175
|
+
OwnerAdoptedOnRestart,
|
|
176
|
+
OwnerBoundFromCallerPane,
|
|
177
|
+
OwnerBindRefused,
|
|
178
|
+
OwnerEpochAdvanced,
|
|
179
|
+
// leader_session_uuid.* / leader.* / result_watcher.*
|
|
180
|
+
LeaderSessionUuidOverride,
|
|
181
|
+
LeaderStart,
|
|
182
|
+
ResultWatcherRequeued,
|
|
183
|
+
// idle_takeover.* — `idle_takeover.py` / `idle_takeover_wiring.py`
|
|
184
|
+
IdleTakeoverClassify,
|
|
185
|
+
IdleTakeoverPing,
|
|
186
|
+
IdleTakeoverReminder,
|
|
187
|
+
IdleTakeoverPushFailed,
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
impl LeaderEvent {
|
|
191
|
+
/// 精确 Python 事件名(`EventLog.write` 第一参)。§40 字节级一致。
|
|
192
|
+
pub fn name(self) -> &'static str {
|
|
193
|
+
match self {
|
|
194
|
+
Self::ReceiverAttached => "leader_receiver.attached",
|
|
195
|
+
Self::ReceiverRebindApplied => "leader_receiver.rebind_applied",
|
|
196
|
+
Self::ReceiverClaimApplied => "leader_receiver.claim_applied",
|
|
197
|
+
Self::ReceiverClaimRefused => "leader_receiver.claim_refused",
|
|
198
|
+
Self::ReceiverRebindRequired => "leader_receiver.rebind_required",
|
|
199
|
+
Self::ReceiverAttachFailed => "leader_receiver.attach_failed",
|
|
200
|
+
Self::ReceiverStateDivergenceRepaired => "leader_receiver.state_divergence_repaired",
|
|
201
|
+
Self::ReceiverFirstTimeEnvSeeded => "leader_receiver.first_time_env_seeded",
|
|
202
|
+
Self::ReceiverAutobindSkipped => "leader_receiver.autobind_skipped",
|
|
203
|
+
Self::ReceiverRequeuedExhaustedWatchers => "leader_receiver.requeued_exhausted_watchers",
|
|
204
|
+
Self::ReceiverAmbiguousCandidates => "leader_receiver.ambiguous_candidates",
|
|
205
|
+
Self::ReceiverClaimRequeue => "leader_receiver.claim_requeue",
|
|
206
|
+
Self::ReceiverClaimLeaderNotification => "leader_receiver.claim_leader_notification",
|
|
207
|
+
Self::OwnerAdoptedOnRestart => "owner.adopted_on_restart",
|
|
208
|
+
Self::OwnerBoundFromCallerPane => "owner.bound_from_caller_pane",
|
|
209
|
+
Self::OwnerBindRefused => "owner.bind_refused",
|
|
210
|
+
Self::OwnerEpochAdvanced => "owner_epoch_advanced",
|
|
211
|
+
Self::LeaderSessionUuidOverride => "leader_session_uuid.override",
|
|
212
|
+
Self::LeaderStart => "leader.start",
|
|
213
|
+
Self::ResultWatcherRequeued => "result_watcher.requeued",
|
|
214
|
+
Self::IdleTakeoverClassify => "idle_takeover.classify",
|
|
215
|
+
Self::IdleTakeoverPing => "idle_takeover.ping",
|
|
216
|
+
Self::IdleTakeoverReminder => "idle_takeover.reminder",
|
|
217
|
+
Self::IdleTakeoverPushFailed => "idle_takeover.push_failed",
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ===========================================================================
|
|
223
|
+
// STRUCTS — §5 单一 typed binding(LeaderReceiver / TeamOwner 不再是 ad-hoc map)
|
|
224
|
+
// ===========================================================================
|
|
225
|
+
|
|
226
|
+
/// `state.json["leader_receiver"]`(card §20)。投递目标 + 身份。
|
|
227
|
+
/// **bug-085**:所有可选字段 `Option<T>`(半状态合法,缺字段不崩)。
|
|
228
|
+
/// 字段集对齐 `__init__.py` 写入的 receiver dict(:282-296 / :861-877)。
|
|
229
|
+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
230
|
+
pub struct LeaderReceiver {
|
|
231
|
+
pub mode: ReceiverMode,
|
|
232
|
+
pub status: ReceiverStatus,
|
|
233
|
+
pub provider: Provider,
|
|
234
|
+
pub pane_id: PaneId,
|
|
235
|
+
pub session_name: Option<SessionName>,
|
|
236
|
+
pub window_index: Option<String>,
|
|
237
|
+
pub window_name: Option<WindowName>,
|
|
238
|
+
pub pane_index: Option<String>,
|
|
239
|
+
pub pane_tty: Option<String>,
|
|
240
|
+
pub pane_current_command: Option<String>,
|
|
241
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
242
|
+
pub tmux_socket: Option<String>,
|
|
243
|
+
/// `_target_fingerprint(pane_info)`。
|
|
244
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
245
|
+
pub fingerprint: Option<String>,
|
|
246
|
+
/// owner 身份(C10/C12:carry 已记录 owner 的 uuid,不重派生)。fake provider 时可缺。
|
|
247
|
+
pub leader_session_uuid: Option<LeaderSessionUuid>,
|
|
248
|
+
pub owner_epoch: Option<OwnerEpoch>,
|
|
249
|
+
pub attached_at: Option<String>,
|
|
250
|
+
pub discovery: Option<Discovery>,
|
|
251
|
+
/// requested vs inferred provider 不一致时记录(`receiver["requested_provider"]`)。
|
|
252
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
253
|
+
pub requested_provider: Option<Provider>,
|
|
254
|
+
/// 非致命校验告警(`validation["warning"]`)。
|
|
255
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
256
|
+
pub warning: Option<String>,
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/// `state.json["team_owner"]`(card §21)。租约权威记录。
|
|
260
|
+
/// 字段集对齐 `__init__.py` owner dict(:538-546 / :686-694)+ `leader_binding` owner(:129-136)。
|
|
261
|
+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
262
|
+
pub struct TeamOwner {
|
|
263
|
+
pub pane_id: PaneId,
|
|
264
|
+
pub provider: Provider,
|
|
265
|
+
pub machine_fingerprint: String,
|
|
266
|
+
pub leader_session_uuid: Option<LeaderSessionUuid>,
|
|
267
|
+
pub owner_epoch: OwnerEpoch,
|
|
268
|
+
pub claimed_at: String,
|
|
269
|
+
pub claimed_via: ClaimedVia,
|
|
270
|
+
/// `leader_binding.bind_owner_from_caller_pane` 还写 `os_user`(Family A owner)。
|
|
271
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
272
|
+
pub os_user: Option<String>,
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/// leader 身份上下文(card §35;`_leader_identity_context` :192-211 的 typed 版)。
|
|
276
|
+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
277
|
+
pub struct LeaderIdentity {
|
|
278
|
+
pub leader_session_uuid: LeaderSessionUuid,
|
|
279
|
+
pub leader_session_uuid_source: LeaderSessionUuidSource,
|
|
280
|
+
pub machine_fingerprint: String,
|
|
281
|
+
pub workspace_abspath: PathBuf,
|
|
282
|
+
pub os_user: String,
|
|
283
|
+
pub team_id: TeamKey,
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/// wake 重读决策(card §36;`wake.should_reread` 返回 dict 的 typed 版)。
|
|
287
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
|
288
|
+
pub struct RereadDecision {
|
|
289
|
+
pub reread: bool,
|
|
290
|
+
pub reason: RereadReason,
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/// `wake.on_file_changed` / `take_pending` 操作的 watch 状态(per-node pending set + mtimes)。
|
|
294
|
+
/// `wake.py` 用 `{pending: sorted list, mtimes: {node_id: mtime}}` dict;此为 typed 版。
|
|
295
|
+
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
|
296
|
+
pub struct WakeWatchState {
|
|
297
|
+
/// 文件变更待处理的 node(`sorted`)。
|
|
298
|
+
pub pending: Vec<String>,
|
|
299
|
+
/// 每 node 最近 mtime。
|
|
300
|
+
pub mtimes: BTreeMap<String, f64>,
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/// leader 启动计划(`leader_start_plan` 返回 dict 的 typed 版)。
|
|
304
|
+
/// `_run_leader_plan` 据此 exec / new-session / attach。
|
|
305
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
306
|
+
pub struct LeaderStartPlan {
|
|
307
|
+
pub mode: LeaderStartMode,
|
|
308
|
+
pub provider: Provider,
|
|
309
|
+
pub workspace: PathBuf,
|
|
310
|
+
pub session_name: Option<SessionName>,
|
|
311
|
+
/// 要 exec 的 argv(provider argv 或 tmux argv)。
|
|
312
|
+
pub argv: Vec<String>,
|
|
313
|
+
/// `new_tmux_session` / `exec_provider` 的 leader env 导出。
|
|
314
|
+
pub leader_env: BTreeMap<String, String>,
|
|
315
|
+
pub identity: Option<LeaderIdentity>,
|
|
316
|
+
/// 非 tty 的 `new_tmux_session` → `-d` detached。
|
|
317
|
+
pub detached: bool,
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/// idle-takeover 的 node 分类行(`build_idle_nodes` / `_leader_node` 产物)。
|
|
321
|
+
/// **bug-085**:`state` 用 `TurnState`(穷尽,`Unknown` 不当 idle);`rollout_path` `Option`。
|
|
322
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
323
|
+
pub struct IdleNode {
|
|
324
|
+
pub node_id: String,
|
|
325
|
+
/// `"worker"` / `"leader"`(C13:leader 也是 provider node)。
|
|
326
|
+
pub role: NodeRole,
|
|
327
|
+
pub state: TurnState,
|
|
328
|
+
pub turn_id: Option<String>,
|
|
329
|
+
pub annotations: Vec<String>,
|
|
330
|
+
pub provider: Option<Provider>,
|
|
331
|
+
pub auth_mode: Option<String>,
|
|
332
|
+
/// bug-085:`None` → 该 node 走 `Unknown` 分支(不猜 idle)。
|
|
333
|
+
pub rollout_path: Option<RolloutPath>,
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/// idle node 角色(`build_idle_nodes` role 字段)。
|
|
337
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
338
|
+
#[serde(rename_all = "snake_case")]
|
|
339
|
+
pub enum NodeRole {
|
|
340
|
+
Worker,
|
|
341
|
+
Leader,
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/// lease 变更结果(attach/claim/takeover/autobind/readopt 统一返回)。
|
|
345
|
+
/// 复刻 `__init__.py` 各路径返回 dict 的并集(成功 receiver/owner/epoch + 拒绝 reason/action)。
|
|
346
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
347
|
+
pub struct LeaseResult {
|
|
348
|
+
pub ok: bool,
|
|
349
|
+
pub status: LeaseStatus,
|
|
350
|
+
pub receiver: Option<LeaderReceiver>,
|
|
351
|
+
pub owner: Option<TeamOwner>,
|
|
352
|
+
pub owner_epoch: Option<OwnerEpoch>,
|
|
353
|
+
/// 成功路径:`vacant_acquired` / `previous_owner_pane_dead`;拒绝路径:闭枚举 reason。
|
|
354
|
+
pub reason: Option<LeaseReason>,
|
|
355
|
+
/// 拒绝时给操作者的 hint(`action` 字段)。
|
|
356
|
+
pub action: Option<String>,
|
|
357
|
+
/// dry-run / refused 时携带的 bound pane。
|
|
358
|
+
pub bound_pane_id: Option<PaneId>,
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/// Family A 正源 owner 绑定结果(`bind_owner_from_caller_pane` 返回 dict 的 typed 版)。
|
|
362
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
363
|
+
pub struct OwnerBindResult {
|
|
364
|
+
pub ok: bool,
|
|
365
|
+
/// 成功时的 owner 记录。
|
|
366
|
+
pub owner: Option<TeamOwner>,
|
|
367
|
+
pub caller_pane_id: PaneId,
|
|
368
|
+
/// 诊断元数据(`#{pane_current_command}` 的单次定向查询结果)。
|
|
369
|
+
pub caller_current_command: String,
|
|
370
|
+
pub team_id: TeamKey,
|
|
371
|
+
/// 拒绝 reason(`caller_pane_missing`)+ hint。
|
|
372
|
+
pub reason: Option<LeaseReason>,
|
|
373
|
+
pub hint: Option<String>,
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// ===========================================================================
|
|
377
|
+
// ERROR — LeaderError(lib 边界,thiserror)
|
|
378
|
+
// ===========================================================================
|
|
379
|
+
|
|
380
|
+
/// step 10 leader 错误。**ADJUDICATION**:不复用 `ModelError`(那是 spec/envelope 校验层)。
|
|
381
|
+
/// lease 变更路径被 launch/restart 同步调用 + 原子双写(bug-084 同源)→ daemon-path,
|
|
382
|
+
/// fallible 操作返 `Result<_, LeaderError>`(§10 实现层禁 unwrap/expect/panic)。
|
|
383
|
+
/// `RuntimeError`(`__init__.py` 抛的 leader pane 校验失败 / tmux scan 失败)→ `Validation`/`Tmux`。
|
|
384
|
+
#[derive(Debug, Error)]
|
|
385
|
+
pub enum LeaderError {
|
|
386
|
+
/// leader pane 校验失败(`_strict_leader_validation_error` / `attach_failed`)。
|
|
387
|
+
#[error("leader pane validation failed: {0}")]
|
|
388
|
+
Validation(String),
|
|
389
|
+
/// provider 命令未安装 / leader 启动前置失败(`leader_start_plan` raise RuntimeError)。
|
|
390
|
+
#[error("leader start error: {0}")]
|
|
391
|
+
Start(String),
|
|
392
|
+
/// tmux target scan / set-environment / send 失败(transport 层冒泡)。
|
|
393
|
+
#[error("tmux error: {0}")]
|
|
394
|
+
Tmux(String),
|
|
395
|
+
/// state 持久化 / 双写 / 锁失败(bug-084 同源,从 state 层冒泡)。
|
|
396
|
+
#[error("state error: {0}")]
|
|
397
|
+
State(#[from] StateError),
|
|
398
|
+
/// 身份派生失败(leader_session_uuid 输入含 NUL)。
|
|
399
|
+
#[error("identity error: {0}")]
|
|
400
|
+
Identity(#[from] crate::model::errors::ModelError),
|
|
401
|
+
#[error("io: {0}")]
|
|
402
|
+
Io(#[from] std::io::Error),
|
|
403
|
+
#[error("json: {0}")]
|
|
404
|
+
Json(#[from] serde_json::Error),
|
|
405
|
+
#[error("event log: {0}")]
|
|
406
|
+
EventLog(#[from] crate::event_log::EventLogError),
|
|
407
|
+
#[error("message store: {0}")]
|
|
408
|
+
MessageStore(#[from] crate::message_store::MessageStoreError),
|
|
409
|
+
#[error("messaging: {0}")]
|
|
410
|
+
Messaging(#[from] crate::messaging::MessagingError),
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// ===========================================================================
|
|
414
|
+
// CROSS-LANE PLACEHOLDERS — 其他并行 lane 的 typed 依赖,leader 集成时 reconcile。
|
|
415
|
+
// (本骨架定义 MINIMAL 本地占位,不猜对方精确命名;见 cross_deps_or_placeholders。)
|
|
416
|
+
// ===========================================================================
|
|
417
|
+
|
|
418
|
+
/// 命名互斥锁句柄占位(step 11 messaging / runtime 的 `_runtime_lock(workspace, name)`)。
|
|
419
|
+
/// `LEADER_OWNERSHIP_LOCK = "send"`:attach/claim/takeover/autobind 共享同一临界区。
|
|
420
|
+
/// **PLACEHOLDER**:真锁类型(文件锁 / RAII guard)在 runtime/messaging lane 落地。
|
|
421
|
+
pub struct RuntimeLockGuard {
|
|
422
|
+
pub _name: String,
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/// MessageStore 占位引用(step 7 已有 `message_store::MessageStore`,但 requeue 方法
|
|
426
|
+
/// `requeue_delivery_exhausted_watchers` / `requeue_after_claim_leader` 属 step 11 messaging)。
|
|
427
|
+
/// **PLACEHOLDER**:claim/attach 后 requeue exhausted result watchers 的接口签名,
|
|
428
|
+
/// 由 messaging lane 落地。
|
|
429
|
+
pub struct RequeueOutcome {
|
|
430
|
+
pub watcher_ids: Vec<String>,
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/// `_resolve_leader_pane` 返回的 pane 信息占位(step 9 transport `PaneInfo` 的相邻产物)。
|
|
434
|
+
/// `__init__.py:276` 调 `runtime._resolve_leader_pane` 返 `(pane_info, discovery)`。
|
|
435
|
+
/// **PLACEHOLDER**:实际 pane_info 字段映射到 `transport::PaneInfo`,resolve 逻辑在 step 9/11。
|
|
436
|
+
pub struct ResolvedLeaderPane {
|
|
437
|
+
pub pane_info: Value,
|
|
438
|
+
pub discovery: Discovery,
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// ===========================================================================
|
|
442
|
+
// 常量 / 锁名
|
|
443
|
+
// ===========================================================================
|
|
444
|
+
|
|
445
|
+
/// `LEADER_OWNERSHIP_LOCK = "send"`(`__init__.py:393`)。一把锁串行化所有 lease 变更
|
|
446
|
+
/// (takeover / claim-leader / attach-leader / autobind)+ 对 send mutator 串行
|
|
447
|
+
/// (旧 owner 并发 send 不能 race rebind)。
|
|
448
|
+
pub const LEADER_OWNERSHIP_LOCK: &str = "send";
|
|
449
|
+
|
|
450
|
+
// ===========================================================================
|
|
451
|
+
// CROSS-LANE TRAIT — turn-state 分类器(注入,MUST-NOT-13 零 provider client)
|
|
452
|
+
// ===========================================================================
|
|
453
|
+
|
|
454
|
+
/// `read_turn_state(provider, session_log_text)` 的注入接口(card §59 / §97)。
|
|
455
|
+
/// **MUST-NOT-13**:coordinator tick 经此 trait 分类,**不**依赖任何 provider client crate;
|
|
456
|
+
/// 测试注入 mock 并断言 provider 调用计数 = 0。
|
|
457
|
+
/// **CROSS-LANE**:真实现是 step 8 provider 的 `provider_state::read_turn_state`;此 trait 是
|
|
458
|
+
/// leader/coordinator 侧的依赖倒置接口,leader 集成时桥接到 step 8 registry。
|
|
459
|
+
pub trait TurnStateClassifier {
|
|
460
|
+
/// 从 provider session-log 文本分类 turn 状态(**unknown ≠ idle**:返回 `TurnState`,
|
|
461
|
+
/// `Unknown` 不当 idle)。
|
|
462
|
+
fn classify(
|
|
463
|
+
&self,
|
|
464
|
+
provider: Provider,
|
|
465
|
+
session_log_text: &str,
|
|
466
|
+
) -> Result<TurnClassification, LeaderError>;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/// `read_turn_state` 的分类结果(card §59;`provider_state` 返回 dict 的 typed 版)。
|
|
470
|
+
/// **CROSS-LANE PLACEHOLDER**:精确字段集对齐 step 8 provider_state lane,leader 集成时 reconcile。
|
|
471
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
472
|
+
pub struct TurnClassification {
|
|
473
|
+
pub state: TurnState,
|
|
474
|
+
pub turn_id: Option<String>,
|
|
475
|
+
pub annotations: Vec<String>,
|
|
476
|
+
/// unknown/abnormal 时的 reason(写 `idle_takeover.classify`)。
|
|
477
|
+
pub reason: Option<String>,
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/// `evaluate_takeover_reminder` 的结果(card §50/§51;`idle_predicate` 返回 dict 的 typed 版)。
|
|
481
|
+
/// **CROSS-LANE PLACEHOLDER**:精确字段集对齐 step 8 provider-neutral idle_predicate lane。
|
|
482
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
483
|
+
pub struct TakeoverReminderResult {
|
|
484
|
+
pub should_ping: bool,
|
|
485
|
+
/// `should_ping` 时投给 leader 的中性提醒消息体。
|
|
486
|
+
pub message: Option<String>,
|
|
487
|
+
pub interrupted_nodes: Vec<String>,
|
|
488
|
+
pub reason: Option<String>,
|
|
489
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
//! Team Agent — Rust 全量重写。
|
|
2
|
+
//!
|
|
3
|
+
//! 真相源: Python `team-agent-public` @ `v0.2.11` (commit `439bef8`),只读快照。
|
|
4
|
+
//! 见 `docs/phase0/snapshot-manifest.md`。
|
|
5
|
+
//!
|
|
6
|
+
//! # 现状: Phase 0
|
|
7
|
+
//! 本 crate 暂空(§13「第一步」: 骨架先分 module 不拆 crate)。实现尚未开始 ——
|
|
8
|
+
//! 先产出 Phase 0 五交付物并机械自审/cr 签字,才动实现(§4 铁律)。
|
|
9
|
+
//!
|
|
10
|
+
//! # 计划 module 地图(§5 单一真相源设计 / §6 15 步依赖序)
|
|
11
|
+
//! 实现按 §6 顺序逐个落地;每个 module 落地时对照 `contracts.yaml` 验。
|
|
12
|
+
//!
|
|
13
|
+
//! ```text
|
|
14
|
+
//! step 2 model typed id/status/envelope/spec/state/DB row/event structs
|
|
15
|
+
//! step 3 db SQLite schema/migration (rusqlite bundled, WAL+busy-timeout)
|
|
16
|
+
//! step 4 event_log events.jsonl append/tail/rotation + 稳定事件名
|
|
17
|
+
//! step 5 state state.json 原子写/锁/self-heal/team projection
|
|
18
|
+
//! step 6 spec TEAM.md/agents/profiles compile/validate
|
|
19
|
+
//! step 7 message_store messages/results/scheduled/tokens/health/watchers/...
|
|
20
|
+
//! step 8 provider 命令生成/MCP config/transcript·status 解析/trust/session
|
|
21
|
+
//! step 9 transport tmux list/capture/inject/send-keys/readiness + 平台能力门
|
|
22
|
+
//! step 10 leader attach/claim/takeover/rebind/rediscover/inject 去重
|
|
23
|
+
//! step 11 messaging send/内部投递/retry/scheduled/collect·report_result/watchers
|
|
24
|
+
//! step 12 coordinator daemon lifecycle/tick/health/stuck·idle fallback/takeover
|
|
25
|
+
//! step 13 lifecycle quick-start/add·fork·reset·stop·remove/restart/display
|
|
26
|
+
//! step 14 mcp+cli stdio MCP/tool/clap 子命令/错误
|
|
27
|
+
//! step 15 packaging 各平台 release/薄 installer shim/migration·repair
|
|
28
|
+
//! ```
|
|
29
|
+
//!
|
|
30
|
+
//! §10 守护进程不崩: `coordinator`/`lifecycle`/`daemon` module 落地时,各自顶加
|
|
31
|
+
//! `#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic)]`,tick 签名
|
|
32
|
+
//! `fn tick(..) -> Result<TickReport, TickError>`。
|
|
33
|
+
//!
|
|
34
|
+
//! §10 不隐藏消耗 token: provider 调用走 trait;`coordinator`/`scheduler` 不依赖任何
|
|
35
|
+
//! provider client crate,测试断言 mock 调用计数 = 0。
|
|
36
|
+
|
|
37
|
+
// step 2 (model) — typed bedrock。其余 step 落地时在此挂载。
|
|
38
|
+
pub mod model;
|
|
39
|
+
|
|
40
|
+
// step 3 (db) — team.db SQLite schema/migration(rusqlite bundled)。
|
|
41
|
+
pub mod db;
|
|
42
|
+
|
|
43
|
+
// step 4 (event_log) — events.jsonl 唯一审计流(append/tail/rotation + 稳定事件名)。
|
|
44
|
+
pub mod event_log;
|
|
45
|
+
|
|
46
|
+
// step 5 (state) — state.json 持久化/identity/owner-gate/projection(bug-084 韧性)。
|
|
47
|
+
pub mod state;
|
|
48
|
+
|
|
49
|
+
// step 6 (compiler) — TEAM.md + agents/*.md → 规范 team.spec dict(doc→spec 纯变换)。
|
|
50
|
+
pub mod compiler;
|
|
51
|
+
|
|
52
|
+
// step 7 (message_store) — team.db 上的核心消息生命周期(create/claim/mark/通知去重)。
|
|
53
|
+
pub mod message_store;
|
|
54
|
+
|
|
55
|
+
// step 8 (provider) — ProviderAdapter trait + typed provider/turn-state/liveness 等(ROUND-0 骨架;
|
|
56
|
+
// fn body unimplemented!(),P2 porter 落实现)。MUST-NOT-13:provider 调用全走 trait。
|
|
57
|
+
pub mod provider;
|
|
58
|
+
|
|
59
|
+
// step 9 (transport) — Transport trait(控制面)+ Target/PaneId/InjectReport 等(ROUND-0 骨架;
|
|
60
|
+
// fn body unimplemented!(),P2 porter 落实现)。tmux/WezTerm/ConPTY 三后端。
|
|
61
|
+
pub mod transport;
|
|
62
|
+
|
|
63
|
+
// step 10-12 (leader/messaging/coordinator) — ROUND-0.5 类型+fn surface 骨架(fn body unimplemented!(),
|
|
64
|
+
// P2 porter 落实现)。leader=lease/owner-bind/idle-takeover;messaging=send/deliver/retry/watchers;
|
|
65
|
+
// coordinator=daemon tick(§10 no-panic,Result<TickReport,TickError>)。
|
|
66
|
+
pub mod leader;
|
|
67
|
+
pub mod messaging;
|
|
68
|
+
pub mod coordinator;
|
|
69
|
+
|
|
70
|
+
// step 13-15 (lifecycle/mcp_server/cli/packaging) — ROUND-0.5b behavioral-rich 骨架(entry-fn 签名 +
|
|
71
|
+
// 富返回类型,fn body unimplemented!(),P2 porter 落实现)。lifecycle=quick-start/restart/display;
|
|
72
|
+
// mcp_server=stdio MCP tool handlers;cli=clap 子命令;packaging=install/migrate/repair。
|
|
73
|
+
pub mod lifecycle;
|
|
74
|
+
pub mod mcp_server;
|
|
75
|
+
pub mod cli;
|
|
76
|
+
pub mod packaging;
|
|
77
|
+
|
|
78
|
+
// fake-worker — subscription-free backing program for Provider::Fake; lets the real spawn path
|
|
79
|
+
// (launch dry_run=false → tmux window) be exercised with no real provider (port of fake_worker.py).
|
|
80
|
+
pub mod fake_worker;
|
|
81
|
+
|
|
82
|
+
// tmux_backend — concrete tmux Transport executor (Command::new tmux via a CommandRunner seam);
|
|
83
|
+
// the real spawn/capture/inject/has_session backend the daemon + launch use (step 9 shipped only
|
|
84
|
+
// the trait + argv-builders). Real subprocess execution is the #[ignore] real-machine boundary.
|
|
85
|
+
pub mod tmux_backend;
|