@team-agent/installer 0.5.60 → 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.
Files changed (265) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/adapters.rs +49 -3
  4. package/crates/team-agent/src/cli/attach_app_server_leader.rs +1 -0
  5. package/crates/team-agent/src/cli/diagnose.rs +184 -0
  6. package/crates/team-agent/src/cli/emit.rs +104 -21
  7. package/crates/team-agent/src/cli/helpers.rs +1 -0
  8. package/crates/team-agent/src/cli/leader.rs +14 -2
  9. package/crates/team-agent/src/cli/leaders.rs +2 -0
  10. package/crates/team-agent/src/cli/mod.rs +296 -8
  11. package/crates/team-agent/src/cli/named_address.rs +26 -2
  12. package/crates/team-agent/src/cli/profile.rs +2 -1
  13. package/crates/team-agent/src/cli/send/coordinator.rs +1 -0
  14. package/crates/team-agent/src/cli/send/mailbox.rs +3 -0
  15. package/crates/team-agent/src/cli/send/persist.rs +1 -0
  16. package/crates/team-agent/src/cli/send/presentation.rs +3 -0
  17. package/crates/team-agent/src/cli/send/resolve.rs +206 -1
  18. package/crates/team-agent/src/cli/send.rs +2 -1
  19. package/crates/team-agent/src/cli/spec.rs +5 -1
  20. package/crates/team-agent/src/cli/status.rs +2 -1
  21. package/crates/team-agent/src/cli/status_port/compact.rs +1 -0
  22. package/crates/team-agent/src/cli/status_port/format.rs +1 -0
  23. package/crates/team-agent/src/cli/status_port/inbox.rs +1 -0
  24. package/crates/team-agent/src/cli/status_port/store.rs +7 -3
  25. package/crates/team-agent/src/cli/tests/named_address.rs +65 -0
  26. package/crates/team-agent/src/cli/tests/verb_profile.rs +38 -0
  27. package/crates/team-agent/src/cli/types.rs +36 -2
  28. package/crates/team-agent/src/communication_mode/mod.rs +54 -0
  29. package/crates/team-agent/src/compiler/tests.rs +5 -5
  30. package/crates/team-agent/src/compiler.rs +54 -1
  31. package/crates/team-agent/src/conpty/backend.rs +1 -0
  32. package/crates/team-agent/src/conpty/mod.rs +1 -0
  33. package/crates/team-agent/src/coordinator/backoff.rs +5 -8
  34. package/crates/team-agent/src/coordinator/conpty_shim.rs +3 -2
  35. package/crates/team-agent/src/coordinator/health.rs +1 -0
  36. package/crates/team-agent/src/coordinator/mod.rs +2 -2
  37. package/crates/team-agent/src/coordinator/orphan.rs +4 -116
  38. package/crates/team-agent/src/coordinator/runtime_detectors.rs +1 -0
  39. package/crates/team-agent/src/coordinator/runtime_observation.rs +1 -0
  40. package/crates/team-agent/src/coordinator/steps/abnormal.rs +6 -5
  41. package/crates/team-agent/src/coordinator/steps/delivery.rs +1 -0
  42. package/crates/team-agent/src/coordinator/steps/health_sync.rs +1 -0
  43. package/crates/team-agent/src/coordinator/steps/mod.rs +2 -0
  44. package/crates/team-agent/src/coordinator/steps/persist.rs +1 -0
  45. package/crates/team-agent/src/coordinator/steps/runtime_prompts.rs +1 -0
  46. package/crates/team-agent/src/coordinator/steps/session_gate.rs +1 -0
  47. package/crates/team-agent/src/coordinator/tests/abnormal.rs +0 -174
  48. package/crates/team-agent/src/coordinator/tests/api_error_recovery.rs +0 -9
  49. package/crates/team-agent/src/coordinator/tests/basics.rs +0 -184
  50. package/crates/team-agent/src/coordinator/tests/mod.rs +2 -17
  51. package/crates/team-agent/src/coordinator/tests/tick_core.rs +0 -42
  52. package/crates/team-agent/src/coordinator/tick.rs +24 -28
  53. package/crates/team-agent/src/coordinator/types.rs +3 -176
  54. package/crates/team-agent/src/db/agent_health_capture.rs +1 -0
  55. package/crates/team-agent/src/db/message_store.rs +47 -2
  56. package/crates/team-agent/src/db/migration.rs +5 -4
  57. package/crates/team-agent/src/db/mod.rs +1 -0
  58. package/crates/team-agent/src/db/schema.rs +1 -0
  59. package/crates/team-agent/src/diagnose/comms.rs +2 -1
  60. package/crates/team-agent/src/diagnose/mod.rs +1 -0
  61. package/crates/team-agent/src/diagnose/orphans.rs +1 -0
  62. package/crates/team-agent/src/fake_worker.rs +21 -1
  63. package/crates/team-agent/src/layout/manager.rs +3 -7
  64. package/crates/team-agent/src/layout/mod.rs +2 -2
  65. package/crates/team-agent/src/layout/overlay.rs +6 -1
  66. package/crates/team-agent/src/layout/placement.rs +1 -0
  67. package/crates/team-agent/src/layout/recovery.rs +3 -0
  68. package/crates/team-agent/src/layout/runtime_sessions.rs +8 -3
  69. package/crates/team-agent/src/layout/sessions.rs +8 -1
  70. package/crates/team-agent/src/layout/tmux_endpoint.rs +3 -0
  71. package/crates/team-agent/src/layout/worker_env.rs +3 -0
  72. package/crates/team-agent/src/layout/worker_window_helpers.rs +2 -0
  73. package/crates/team-agent/src/leader/helpers.rs +1 -0
  74. package/crates/team-agent/src/leader/incident.rs +1 -0
  75. package/crates/team-agent/src/leader/lease.rs +27 -22
  76. package/crates/team-agent/src/leader/mod.rs +2 -3
  77. package/crates/team-agent/src/leader/owner_bind.rs +13 -3
  78. package/crates/team-agent/src/leader/provider_attribution.rs +1 -0
  79. package/crates/team-agent/src/leader/rediscover.rs +4 -17
  80. package/crates/team-agent/src/leader/registry.rs +3 -15
  81. package/crates/team-agent/src/leader/start.rs +1072 -186
  82. package/crates/team-agent/src/leader/takeover.rs +10 -232
  83. package/crates/team-agent/src/leader/tests/claim_leader_mailbox_flush_contract.rs +544 -0
  84. package/crates/team-agent/src/leader/tests/historical_inventory_upgrade_gate_red.rs +624 -0
  85. package/crates/team-agent/src/leader/tests/identity.rs +71 -59
  86. package/crates/team-agent/src/leader/tests/identity_session_names.rs +42 -0
  87. package/crates/team-agent/src/leader/tests/idle.rs +0 -193
  88. package/crates/team-agent/src/leader/tests/lease_api.rs +0 -45
  89. package/crates/team-agent/src/leader/tests/mod.rs +4 -41
  90. package/crates/team-agent/src/leader/tests/rehomed_env.rs +83 -0
  91. package/crates/team-agent/src/leader/tests/team_in_team_state_scope_red.rs +1273 -0
  92. package/crates/team-agent/src/leader/tests/terminal_and_replay_vs_rerender_invariants_red.rs +417 -0
  93. package/crates/team-agent/src/leader/tests/wake_start_owner.rs +22 -103
  94. package/crates/team-agent/src/leader/types.rs +1 -28
  95. package/crates/team-agent/src/lib.rs +7 -0
  96. package/crates/team-agent/src/lifecycle/display.rs +7 -1
  97. package/crates/team-agent/src/lifecycle/helpers.rs +3 -1
  98. package/crates/team-agent/src/lifecycle/launch/add_agent.rs +2 -2
  99. package/crates/team-agent/src/lifecycle/launch/fork_agent/completion.rs +1 -0
  100. package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +1 -1
  101. package/crates/team-agent/src/lifecycle/launch/fork_entry.rs +1 -0
  102. package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +1 -0
  103. package/crates/team-agent/src/lifecycle/launch/plan.rs +2 -2
  104. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +4 -26
  105. package/crates/team-agent/src/lifecycle/launch/readiness.rs +0 -27
  106. package/crates/team-agent/src/lifecycle/launch/spawn.rs +2 -28
  107. package/crates/team-agent/src/lifecycle/launch/spec_state.rs +4 -32
  108. package/crates/team-agent/src/lifecycle/launch/state_projection.rs +1 -0
  109. package/crates/team-agent/src/lifecycle/launch.rs +11 -12
  110. package/crates/team-agent/src/lifecycle/mod.rs +2 -1
  111. package/crates/team-agent/src/lifecycle/restart/agent.rs +4 -4
  112. package/crates/team-agent/src/lifecycle/restart/common.rs +1 -1
  113. package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +2 -2
  114. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +13 -5
  115. package/crates/team-agent/src/lifecycle/restart/remove.rs +1 -1
  116. package/crates/team-agent/src/lifecycle/restart/selection.rs +3 -3
  117. package/crates/team-agent/src/lifecycle/restart.rs +13 -11
  118. package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +1007 -0
  119. package/crates/team-agent/src/lifecycle/tests/b0_legacy_snapshot_nonauthority_contract.rs +265 -0
  120. package/crates/team-agent/src/lifecycle/tests/b0_reader_hideone_audit_contract.rs +459 -0
  121. package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +849 -0
  122. package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +323 -0
  123. package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +423 -0
  124. package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +737 -0
  125. package/crates/team-agent/src/lifecycle/tests/codex_mcp_approval_inheritance_red.rs +1187 -0
  126. package/crates/team-agent/src/lifecycle/tests/codex_weak_window_attribution_red.rs +683 -0
  127. package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +394 -0
  128. package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +1856 -0
  129. package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +917 -0
  130. package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +481 -0
  131. package/crates/team-agent/src/lifecycle/tests/f032_startup_prompt_best_effort_red.rs +301 -0
  132. package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +516 -0
  133. package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +986 -0
  134. package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +651 -0
  135. package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +2 -0
  136. package/crates/team-agent/src/lifecycle/tests/quick_start_worker_readiness_red.rs +332 -0
  137. package/crates/team-agent/src/lifecycle/tests/realmachine_clusters_1_6_red.rs +846 -0
  138. package/crates/team-agent/src/lifecycle/tests/realmachine_residual_g1_g4_red.rs +648 -0
  139. package/crates/team-agent/src/lifecycle/tests/restart_build_before_destroy_0540_contract.rs +910 -0
  140. package/crates/team-agent/src/lifecycle/tests/restart_liveness_red.rs +630 -0
  141. package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +1083 -0
  142. package/crates/team-agent/src/lifecycle/tests/restart_session_capture_red.rs +1677 -0
  143. package/crates/team-agent/src/lifecycle/tests/resume_recover_red.rs +410 -0
  144. package/crates/team-agent/src/lifecycle/tests/stale_team_saveconflict_contract.rs +428 -0
  145. package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +1032 -0
  146. package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +869 -0
  147. package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +1249 -0
  148. package/crates/team-agent/src/lifecycle/tests/swallow_batch4_semantics_red.rs +342 -0
  149. package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +542 -0
  150. package/crates/team-agent/src/lifecycle/tests/team_in_team_sibling_quick_start_red.rs +1103 -0
  151. package/crates/team-agent/src/lifecycle/tests/team_in_team_state_scope_red.rs +1276 -0
  152. package/crates/team-agent/src/lifecycle/tests/team_key_retirement_roster_red.rs +145 -0
  153. package/crates/team-agent/src/lifecycle/tests/team_key_retirement_txn_red.rs +603 -0
  154. package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +837 -0
  155. package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +928 -0
  156. package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +951 -0
  157. package/crates/team-agent/src/lifecycle/tests/worker_dangerous_bypass_argv_red.rs +327 -0
  158. package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +760 -0
  159. package/crates/team-agent/src/lifecycle/tests.rs +59 -0
  160. package/crates/team-agent/src/lifecycle/types.rs +0 -9
  161. package/crates/team-agent/src/lifecycle/worker_command_context.rs +29 -11
  162. package/crates/team-agent/src/mcp_server/helpers.rs +1 -0
  163. package/crates/team-agent/src/mcp_server/lifecycle_tools/mod.rs +1 -0
  164. package/crates/team-agent/src/mcp_server/lifecycle_tools/state_status.rs +1 -0
  165. package/crates/team-agent/src/mcp_server/mod.rs +1 -0
  166. package/crates/team-agent/src/mcp_server/normalize.rs +5 -3
  167. package/crates/team-agent/src/mcp_server/tests/send.rs +26 -0
  168. package/crates/team-agent/src/mcp_server/tests/wire.rs +1 -1
  169. package/crates/team-agent/src/mcp_server/tools.rs +101 -66
  170. package/crates/team-agent/src/mcp_server/types.rs +6 -18
  171. package/crates/team-agent/src/mcp_server/wire.rs +32 -26
  172. package/crates/team-agent/src/messaging/activity.rs +1 -0
  173. package/crates/team-agent/src/messaging/address.rs +1 -0
  174. package/crates/team-agent/src/messaging/delivery.rs +109 -41
  175. package/crates/team-agent/src/messaging/helpers.rs +2 -1
  176. package/crates/team-agent/src/messaging/leader_channel.rs +34 -10
  177. package/crates/team-agent/src/messaging/leader_receiver.rs +42 -24
  178. package/crates/team-agent/src/messaging/mod.rs +10 -14
  179. package/crates/team-agent/src/messaging/peers.rs +2 -0
  180. package/crates/team-agent/src/messaging/persist.rs +3 -1
  181. package/crates/team-agent/src/messaging/presentation.rs +111 -1
  182. package/crates/team-agent/src/messaging/results.rs +166 -17
  183. package/crates/team-agent/src/messaging/scheduler.rs +1 -0
  184. package/crates/team-agent/src/messaging/selftest.rs +1 -1
  185. package/crates/team-agent/src/messaging/send.rs +135 -89
  186. package/crates/team-agent/src/messaging/tests/leader_channel.rs +6 -6
  187. package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +187 -0
  188. package/crates/team-agent/src/messaging/tests/mod.rs +5 -0
  189. package/crates/team-agent/src/messaging/tests/runtime.rs +13 -6
  190. package/crates/team-agent/src/messaging/types.rs +7 -2
  191. package/crates/team-agent/src/messaging/watchers.rs +24 -13
  192. package/crates/team-agent/src/model/enums.rs +1 -0
  193. package/crates/team-agent/src/model/errors.rs +1 -0
  194. package/crates/team-agent/src/model/ids.rs +1 -0
  195. package/crates/team-agent/src/model/mod.rs +2 -0
  196. package/crates/team-agent/src/model/name_similarity.rs +1 -0
  197. package/crates/team-agent/src/model/pane_authority_refusal.rs +359 -0
  198. package/crates/team-agent/src/model/paths.rs +1 -0
  199. package/crates/team-agent/src/model/permissions.rs +3 -2
  200. package/crates/team-agent/src/model/routing.rs +1 -0
  201. package/crates/team-agent/src/model/spec.rs +17 -0
  202. package/crates/team-agent/src/model/task_graph.rs +1 -0
  203. package/crates/team-agent/src/model/yaml/tests.rs +1 -0
  204. package/crates/team-agent/src/model/yaml.rs +1 -0
  205. package/crates/team-agent/src/packaging/install.rs +9 -147
  206. package/crates/team-agent/src/packaging/migrate.rs +2 -0
  207. package/crates/team-agent/src/packaging/mod.rs +1 -0
  208. package/crates/team-agent/src/packaging/repair.rs +2 -0
  209. package/crates/team-agent/src/packaging/tests.rs +29 -218
  210. package/crates/team-agent/src/packaging/types.rs +8 -15
  211. package/crates/team-agent/src/platform/argv.rs +4 -0
  212. package/crates/team-agent/src/platform/errors.rs +10 -1
  213. package/crates/team-agent/src/platform/file_lock.rs +4 -157
  214. package/crates/team-agent/src/platform/mod.rs +0 -61
  215. package/crates/team-agent/src/platform/process.rs +1 -0
  216. package/crates/team-agent/src/provider/adapter.rs +1 -0
  217. package/crates/team-agent/src/provider/adapters/claude.rs +1 -0
  218. package/crates/team-agent/src/provider/adapters/claude_fork.rs +1 -0
  219. package/crates/team-agent/src/provider/adapters/codex.rs +1 -0
  220. package/crates/team-agent/src/provider/adapters/copilot.rs +1 -0
  221. package/crates/team-agent/src/provider/adapters/copilot_fork.rs +1 -0
  222. package/crates/team-agent/src/provider/adapters/fake.rs +1 -0
  223. package/crates/team-agent/src/provider/adapters/mod.rs +1 -0
  224. package/crates/team-agent/src/provider/approvals/mod.rs +1 -0
  225. package/crates/team-agent/src/provider/approvals/parsing.rs +2 -5
  226. package/crates/team-agent/src/provider/approvals/runtime_prompts.rs +6 -5
  227. package/crates/team-agent/src/provider/classify.rs +1 -0
  228. package/crates/team-agent/src/provider/faults.rs +1 -26
  229. package/crates/team-agent/src/provider/helpers.rs +1 -0
  230. package/crates/team-agent/src/provider/mod.rs +1 -1
  231. package/crates/team-agent/src/provider/session/capture.rs +41 -22
  232. package/crates/team-agent/src/provider/session/context_fork/claude.rs +1 -0
  233. package/crates/team-agent/src/provider/session/context_fork/codex.rs +1 -0
  234. package/crates/team-agent/src/provider/session/context_fork/outcome.rs +1 -0
  235. package/crates/team-agent/src/provider/session/context_fork.rs +1 -0
  236. package/crates/team-agent/src/provider/session/mod.rs +2 -4
  237. package/crates/team-agent/src/provider/session/resume.rs +2 -209
  238. package/crates/team-agent/src/provider/session_scan/claude.rs +93 -3
  239. package/crates/team-agent/src/provider/session_scan/codex.rs +1 -0
  240. package/crates/team-agent/src/provider/session_scan/common.rs +24 -7
  241. package/crates/team-agent/src/provider/session_scan/copilot.rs +1 -0
  242. package/crates/team-agent/src/provider/session_scan.rs +6 -42
  243. package/crates/team-agent/src/provider/startup_prompt.rs +1 -0
  244. package/crates/team-agent/src/provider/types.rs +1 -0
  245. package/crates/team-agent/src/provider/wire.rs +1 -0
  246. package/crates/team-agent/src/state/identity.rs +16 -5
  247. package/crates/team-agent/src/state/identity_keys.rs +1 -0
  248. package/crates/team-agent/src/state/mod.rs +2 -0
  249. package/crates/team-agent/src/state/owner_gate.rs +5 -0
  250. package/crates/team-agent/src/state/ownership.rs +10 -4
  251. package/crates/team-agent/src/state/paths.rs +12 -0
  252. package/crates/team-agent/src/state/persist.rs +9 -3
  253. package/crates/team-agent/src/state/projection.rs +15 -2
  254. package/crates/team-agent/src/state/repository/intent.rs +1 -0
  255. package/crates/team-agent/src/state/repository/tests.rs +1 -0
  256. package/crates/team-agent/src/state/repository.rs +7 -0
  257. package/crates/team-agent/src/state/selector.rs +1 -0
  258. package/crates/team-agent/src/tmux_backend/tests.rs +39 -0
  259. package/crates/team-agent/src/tmux_backend.rs +63 -0
  260. package/crates/team-agent/src/topology.rs +3 -0
  261. package/crates/team-agent/src/transport.rs +15 -0
  262. package/package.json +4 -4
  263. package/skills/team-agent/command-coverage.json +379 -0
  264. package/crates/team-agent/src/leader/inject.rs +0 -33
  265. package/crates/team-agent/src/provider/command.rs +0 -80
@@ -5,12 +5,13 @@ use std::path::Path;
5
5
  use rusqlite::{params, OptionalExtension};
6
6
 
7
7
  use crate::event_log::EventLog;
8
+ use crate::leader::LeaderIncident;
8
9
  use crate::message_store::{MessageStore, NotificationClaimParams};
9
10
  use crate::model::ids::{TaskId, TeamKey};
10
11
  use crate::transport::PaneId;
11
12
 
12
13
  #[derive(Debug, Clone, PartialEq, Eq)]
13
- pub struct RecoveryIncident {
14
+ pub(crate) struct RecoveryIncident {
14
15
  pub incident_id: String,
15
16
  pub occurred_at: String,
16
17
  }
@@ -20,7 +21,7 @@ use super::{MessagingError, WatcherNotice, RESULT_DELIVERY_MAX_ATTEMPTS};
20
21
  /// `notify_result_watchers` (`result_delivery.py:38`):匹配 + 去重 + (有界) 投递 result 给 leader
21
22
  /// watcher。**恰好一次** (Gap 32/38):同 result_id 多 watcher → 1 次注入,余 `superseded`。
22
23
  /// 去重唯一原语 = [`MessageStore::claim_leader_notification_delivery`]。`collect`/coordinator tick 调。
23
- pub fn notify_result_watchers(
24
+ pub(crate) fn notify_result_watchers(
24
25
  workspace: &Path,
25
26
  result: &serde_json::Value,
26
27
  event_log: &EventLog,
@@ -475,20 +476,25 @@ pub fn requeue_after_claim_leader(
475
476
 
476
477
  pub fn recover_watchers_for_incident(
477
478
  workspace: &Path,
478
- store: &MessageStore,
479
479
  event_log: &EventLog,
480
480
  owner_team_id: &TeamKey,
481
481
  claimed_pane_id: &PaneId,
482
- incident: &RecoveryIncident,
482
+ incident: LeaderIncident,
483
483
  ) -> Result<Vec<WatcherNotice>, MessagingError> {
484
- requeue_after_claim_leader(
485
- workspace,
486
- store,
487
- event_log,
488
- owner_team_id,
489
- claimed_pane_id,
490
- Some(&incident.occurred_at),
491
- )
484
+ match incident {
485
+ LeaderIncident::LeaderAttached => Ok(Vec::new()),
486
+ LeaderIncident::LeaderClaimed => {
487
+ let store = MessageStore::open(workspace)?;
488
+ requeue_after_claim_leader(
489
+ workspace,
490
+ &store,
491
+ event_log,
492
+ owner_team_id,
493
+ claimed_pane_id,
494
+ None,
495
+ )
496
+ }
497
+ }
492
498
  }
493
499
 
494
500
  /// 0.5.5 gate054 round-2: attach-leader (and claim-leader) requeue for leader messages
@@ -529,6 +535,11 @@ pub(crate) fn requeue_blocked_leader_messages(
529
535
  "blocked_leader_unbound": counts.blocked_leader_unbound,
530
536
  "queued_until_leader_attach": counts.queued_until_leader_attach,
531
537
  },
538
+ "attach_window_failures": {
539
+ "reason": "leader_not_attached",
540
+ "count": counts.blocked_leader_unbound,
541
+ "status": "requeued_pending_physical_retry",
542
+ },
532
543
  }),
533
544
  )?;
534
545
  }
@@ -596,7 +607,7 @@ pub fn requeue_delivery_exhausted_watchers(
596
607
 
597
608
  /// `delivered_result_message` (`result_delivery.py:394`):内容级去重 —— 查某 result_id 是否已有
598
609
  /// 投递的 leader 通知消息。
599
- pub fn delivered_result_message(
610
+ pub(crate) fn delivered_result_message(
600
611
  store: &MessageStore,
601
612
  result_id: &str,
602
613
  task_id: Option<&TaskId>,
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! §19 散字符串态 → 穷尽 enum。每个 variant 与 Python 字符串**一一对应**(`#[serde]`
2
3
  //! rename 到精确字符串),保证 spec/state/event 序列化字节不漂移(§7)。
3
4
  //!
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! 用户面错误。
2
3
  //!
3
4
  //! 陷阱 #6(02-model 卡):Python `errors.py` 用自定义 `RuntimeError` **遮蔽**内建
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! §3 id newtypes —— Python 把 agent/task/team id 全用裸 `str` 混传(route/owner-gate/
2
3
  //! tasks 串台)。newtype 让"混传"编不过。serde `transparent` 保证序列化字节 == 裸字符串。
3
4
 
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! step 2 · model — typed bedrock (REWRITE_PROMPT.md §6 step 2).
2
3
  //!
3
4
  //! 纯数据 + 纯函数核心:Python 的散字符串 / `dict[str,Any]` 在此变 §3 id-newtype +
@@ -18,6 +19,7 @@ pub mod ids;
18
19
  // cli/send.rs (positional adapter), mcp_server/tools.rs (owner-scoped
19
20
  // peer suggestions). Never a routing authority — advisory only.
20
21
  pub(crate) mod name_similarity;
22
+ pub mod pane_authority_refusal;
21
23
  pub mod paths;
22
24
  pub mod permissions;
23
25
  pub mod routing;
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! 0.5.45 naming-addressing (design §3.2/§4.1) — shared pure name
2
3
  //! similarity ranking helper.
3
4
  //!
@@ -0,0 +1,359 @@
1
+ //!
2
+ //! Shared typed catalog for ambient tmux pane authority refusals.
3
+ //!
4
+ //! This module owns identities and payload shape only. Launchers and CLI
5
+ //! presenters remain responsible for collecting facts and rendering them.
6
+
7
+ use std::path::PathBuf;
8
+
9
+ pub const REASON_FIELD: &str = "reason";
10
+ pub const AVAILABILITY_FIELD: &str = "availability";
11
+ pub const CAUSE_FIELD: &str = "cause";
12
+ pub const ACTION_REQUIRED_FIELD: &str = "action_required";
13
+ pub const HINT_ACTION_FIELD: &str = "hint_action";
14
+ pub const ACTION_FIELD: &str = "action";
15
+
16
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
17
+ pub enum PaneAuthorityRefusalField {
18
+ RequestedWorkspace,
19
+ ObservedPaneId,
20
+ ObservedPaneWorkspace,
21
+ Endpoint,
22
+ CallerControllingTty,
23
+ ObservedPaneTty,
24
+ }
25
+
26
+ impl PaneAuthorityRefusalField {
27
+ pub const fn as_str(self) -> &'static str {
28
+ match self {
29
+ Self::RequestedWorkspace => "requested_workspace",
30
+ Self::ObservedPaneId => "observed_pane_id",
31
+ Self::ObservedPaneWorkspace => "observed_pane_workspace",
32
+ Self::Endpoint => "endpoint",
33
+ Self::CallerControllingTty => "caller_controlling_tty",
34
+ Self::ObservedPaneTty => "observed_pane_tty",
35
+ }
36
+ }
37
+ }
38
+
39
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
40
+ pub enum PaneAuthorityRefusalReason {
41
+ AmbientTmuxEndpointUnavailable,
42
+ AmbientPaneIdUnavailable,
43
+ AmbientPaneWorkspaceUnavailable,
44
+ CallerControllingTtyUnavailable,
45
+ ObservedPaneTtyUnavailable,
46
+ PaneTtyMismatch,
47
+ PaneWorkspaceMismatch,
48
+ }
49
+
50
+ impl PaneAuthorityRefusalReason {
51
+ pub const ALL: [Self; 7] = [
52
+ Self::AmbientTmuxEndpointUnavailable,
53
+ Self::AmbientPaneIdUnavailable,
54
+ Self::AmbientPaneWorkspaceUnavailable,
55
+ Self::CallerControllingTtyUnavailable,
56
+ Self::ObservedPaneTtyUnavailable,
57
+ Self::PaneTtyMismatch,
58
+ Self::PaneWorkspaceMismatch,
59
+ ];
60
+
61
+ pub const fn as_str(self) -> &'static str {
62
+ match self {
63
+ Self::AmbientTmuxEndpointUnavailable => "AmbientTmuxEndpointUnavailable",
64
+ Self::AmbientPaneIdUnavailable => "AmbientPaneIdUnavailable",
65
+ Self::AmbientPaneWorkspaceUnavailable => "AmbientPaneWorkspaceUnavailable",
66
+ Self::CallerControllingTtyUnavailable => "CallerControllingTtyUnavailable",
67
+ Self::ObservedPaneTtyUnavailable => "ObservedPaneTtyUnavailable",
68
+ Self::PaneTtyMismatch => "PaneTtyMismatch",
69
+ Self::PaneWorkspaceMismatch => "PaneWorkspaceMismatch",
70
+ }
71
+ }
72
+
73
+ pub const fn required_fact_fields(self) -> &'static [PaneAuthorityRefusalField] {
74
+ use PaneAuthorityRefusalField::{
75
+ CallerControllingTty, Endpoint, ObservedPaneId, ObservedPaneTty, ObservedPaneWorkspace,
76
+ RequestedWorkspace,
77
+ };
78
+
79
+ match self {
80
+ Self::AmbientTmuxEndpointUnavailable => &[RequestedWorkspace, Endpoint],
81
+ Self::AmbientPaneIdUnavailable => &[RequestedWorkspace, ObservedPaneId, Endpoint],
82
+ Self::AmbientPaneWorkspaceUnavailable => &[
83
+ RequestedWorkspace,
84
+ ObservedPaneId,
85
+ ObservedPaneWorkspace,
86
+ Endpoint,
87
+ ],
88
+ Self::CallerControllingTtyUnavailable => &[
89
+ RequestedWorkspace,
90
+ ObservedPaneId,
91
+ Endpoint,
92
+ CallerControllingTty,
93
+ ],
94
+ Self::ObservedPaneTtyUnavailable => &[
95
+ RequestedWorkspace,
96
+ ObservedPaneId,
97
+ Endpoint,
98
+ ObservedPaneTty,
99
+ ],
100
+ Self::PaneTtyMismatch => &[
101
+ RequestedWorkspace,
102
+ ObservedPaneId,
103
+ Endpoint,
104
+ CallerControllingTty,
105
+ ObservedPaneTty,
106
+ ],
107
+ Self::PaneWorkspaceMismatch => &[
108
+ RequestedWorkspace,
109
+ ObservedPaneId,
110
+ ObservedPaneWorkspace,
111
+ Endpoint,
112
+ ],
113
+ }
114
+ }
115
+ }
116
+
117
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
118
+ pub enum PaneAuthorityFactAvailability {
119
+ Unavailable,
120
+ }
121
+
122
+ impl PaneAuthorityFactAvailability {
123
+ pub const fn as_str(self) -> &'static str {
124
+ match self {
125
+ Self::Unavailable => "unavailable",
126
+ }
127
+ }
128
+ }
129
+
130
+ #[derive(Clone, Debug, Eq, PartialEq)]
131
+ pub struct UnavailablePaneAuthorityFact<C> {
132
+ pub cause: C,
133
+ }
134
+
135
+ impl<C> UnavailablePaneAuthorityFact<C> {
136
+ pub const fn new(cause: C) -> Self {
137
+ Self { cause }
138
+ }
139
+
140
+ pub const fn availability(&self) -> PaneAuthorityFactAvailability {
141
+ PaneAuthorityFactAvailability::Unavailable
142
+ }
143
+ }
144
+
145
+ macro_rules! unavailable_causes {
146
+ ($name:ident { $($variant:ident => $wire:literal),+ $(,)? }) => {
147
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
148
+ pub enum $name {
149
+ $($variant),+
150
+ }
151
+
152
+ impl $name {
153
+ pub const fn as_str(self) -> &'static str {
154
+ match self {
155
+ $(Self::$variant => $wire),+
156
+ }
157
+ }
158
+ }
159
+ };
160
+ }
161
+
162
+ unavailable_causes!(AmbientTmuxEndpointUnavailableCause {
163
+ TmuxValueNotUnicode => "tmux_value_not_unicode",
164
+ TmuxTupleFieldCountInvalid => "tmux_tuple_field_count_invalid",
165
+ EndpointMissing => "endpoint_missing",
166
+ EndpointNotAbsolute => "endpoint_not_absolute",
167
+ ServerPidInvalid => "server_pid_invalid",
168
+ SessionIndexInvalid => "session_index_invalid",
169
+ });
170
+
171
+ unavailable_causes!(AmbientPaneIdUnavailableCause {
172
+ EnvironmentValueMissing => "environment_value_missing",
173
+ EnvironmentValueEmpty => "environment_value_empty",
174
+ EnvironmentValueNotUnicode => "environment_value_not_unicode",
175
+ });
176
+
177
+ unavailable_causes!(AmbientPaneWorkspaceUnavailableCause {
178
+ PaneQueryFailed => "pane_query_failed",
179
+ PaneNotFound => "pane_not_found",
180
+ CurrentPathMissing => "current_path_missing",
181
+ });
182
+
183
+ unavailable_causes!(CallerControllingTtyUnavailableCause {
184
+ NoControllingTty => "no_controlling_tty",
185
+ DeviceIdentityUnresolvable => "device_identity_unresolvable",
186
+ PlatformUnsupported => "platform_unsupported",
187
+ });
188
+
189
+ unavailable_causes!(ObservedPaneTtyUnavailableCause {
190
+ PaneTtyMissing => "pane_tty_missing",
191
+ PaneTtyUnresolvable => "pane_tty_unresolvable",
192
+ PaneTtyNotCharacterDevice => "pane_tty_not_character_device",
193
+ });
194
+
195
+ #[derive(Clone, Debug, Eq, PartialEq)]
196
+ pub struct AmbientTmuxEndpointUnavailableFacts {
197
+ pub requested_workspace: PathBuf,
198
+ pub endpoint: UnavailablePaneAuthorityFact<AmbientTmuxEndpointUnavailableCause>,
199
+ }
200
+
201
+ #[derive(Clone, Debug, Eq, PartialEq)]
202
+ pub struct AmbientPaneIdUnavailableFacts {
203
+ pub requested_workspace: PathBuf,
204
+ pub observed_pane_id: UnavailablePaneAuthorityFact<AmbientPaneIdUnavailableCause>,
205
+ pub endpoint: String,
206
+ }
207
+
208
+ #[derive(Clone, Debug, Eq, PartialEq)]
209
+ pub struct AmbientPaneWorkspaceUnavailableFacts {
210
+ pub requested_workspace: PathBuf,
211
+ pub observed_pane_id: String,
212
+ pub observed_pane_workspace: UnavailablePaneAuthorityFact<AmbientPaneWorkspaceUnavailableCause>,
213
+ pub endpoint: String,
214
+ }
215
+
216
+ #[derive(Clone, Debug, Eq, PartialEq)]
217
+ pub struct CallerControllingTtyUnavailableFacts {
218
+ pub requested_workspace: PathBuf,
219
+ pub observed_pane_id: String,
220
+ pub endpoint: String,
221
+ pub caller_controlling_tty: UnavailablePaneAuthorityFact<CallerControllingTtyUnavailableCause>,
222
+ }
223
+
224
+ #[derive(Clone, Debug, Eq, PartialEq)]
225
+ pub struct ObservedPaneTtyUnavailableFacts {
226
+ pub requested_workspace: PathBuf,
227
+ pub observed_pane_id: String,
228
+ pub endpoint: String,
229
+ pub observed_pane_tty: UnavailablePaneAuthorityFact<ObservedPaneTtyUnavailableCause>,
230
+ }
231
+
232
+ #[derive(Clone, Debug, Eq, PartialEq)]
233
+ pub struct PaneTtyMismatchFacts {
234
+ pub requested_workspace: PathBuf,
235
+ pub observed_pane_id: String,
236
+ pub endpoint: String,
237
+ pub caller_controlling_tty: u64,
238
+ pub observed_pane_tty: u64,
239
+ }
240
+
241
+ #[derive(Clone, Debug, Eq, PartialEq)]
242
+ pub struct PaneWorkspaceMismatchFacts {
243
+ pub requested_workspace: PathBuf,
244
+ pub observed_pane_id: String,
245
+ pub observed_pane_workspace: PathBuf,
246
+ pub endpoint: String,
247
+ }
248
+
249
+ #[derive(Clone, Debug, Eq, PartialEq)]
250
+ pub enum PaneAuthorityRefusalFacts {
251
+ AmbientTmuxEndpointUnavailable(AmbientTmuxEndpointUnavailableFacts),
252
+ AmbientPaneIdUnavailable(AmbientPaneIdUnavailableFacts),
253
+ AmbientPaneWorkspaceUnavailable(AmbientPaneWorkspaceUnavailableFacts),
254
+ CallerControllingTtyUnavailable(CallerControllingTtyUnavailableFacts),
255
+ ObservedPaneTtyUnavailable(ObservedPaneTtyUnavailableFacts),
256
+ PaneTtyMismatch(PaneTtyMismatchFacts),
257
+ PaneWorkspaceMismatch(PaneWorkspaceMismatchFacts),
258
+ }
259
+
260
+ impl PaneAuthorityRefusalFacts {
261
+ pub const fn reason(&self) -> PaneAuthorityRefusalReason {
262
+ match self {
263
+ Self::AmbientTmuxEndpointUnavailable(_) => {
264
+ PaneAuthorityRefusalReason::AmbientTmuxEndpointUnavailable
265
+ }
266
+ Self::AmbientPaneIdUnavailable(_) => {
267
+ PaneAuthorityRefusalReason::AmbientPaneIdUnavailable
268
+ }
269
+ Self::AmbientPaneWorkspaceUnavailable(_) => {
270
+ PaneAuthorityRefusalReason::AmbientPaneWorkspaceUnavailable
271
+ }
272
+ Self::CallerControllingTtyUnavailable(_) => {
273
+ PaneAuthorityRefusalReason::CallerControllingTtyUnavailable
274
+ }
275
+ Self::ObservedPaneTtyUnavailable(_) => {
276
+ PaneAuthorityRefusalReason::ObservedPaneTtyUnavailable
277
+ }
278
+ Self::PaneTtyMismatch(_) => PaneAuthorityRefusalReason::PaneTtyMismatch,
279
+ Self::PaneWorkspaceMismatch(_) => PaneAuthorityRefusalReason::PaneWorkspaceMismatch,
280
+ }
281
+ }
282
+ }
283
+
284
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
285
+ pub enum PaneAuthorityRecoveryHint {
286
+ AttachLeader,
287
+ }
288
+
289
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
290
+ pub enum PaneAuthorityRecoveryAction {
291
+ OpenTerminalOutsideCurrentTmuxPaneOrAttachFromMatchingPane,
292
+ }
293
+
294
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
295
+ pub struct PaneAuthorityRecovery {
296
+ pub action_required: bool,
297
+ pub hint_action: PaneAuthorityRecoveryHint,
298
+ pub action: PaneAuthorityRecoveryAction,
299
+ }
300
+
301
+ impl PaneAuthorityRecovery {
302
+ pub const REQUIRED: Self = Self {
303
+ action_required: true,
304
+ hint_action: PaneAuthorityRecoveryHint::AttachLeader,
305
+ action:
306
+ PaneAuthorityRecoveryAction::OpenTerminalOutsideCurrentTmuxPaneOrAttachFromMatchingPane,
307
+ };
308
+ }
309
+
310
+ #[derive(Clone, Debug, Eq, PartialEq)]
311
+ pub struct PaneAuthorityRefusal {
312
+ pub facts: PaneAuthorityRefusalFacts,
313
+ pub recovery: PaneAuthorityRecovery,
314
+ }
315
+
316
+ impl PaneAuthorityRefusal {
317
+ pub const fn new(facts: PaneAuthorityRefusalFacts) -> Self {
318
+ Self {
319
+ facts,
320
+ recovery: PaneAuthorityRecovery::REQUIRED,
321
+ }
322
+ }
323
+
324
+ pub const fn reason(&self) -> PaneAuthorityRefusalReason {
325
+ self.facts.reason()
326
+ }
327
+ }
328
+
329
+ #[cfg(test)]
330
+ mod tests {
331
+ use super::{PaneAuthorityRefusalField as Field, PaneAuthorityRefusalReason as Reason};
332
+
333
+ #[test]
334
+ fn reason_catalog_is_closed_and_mismatch_requires_all_four_workspace_facts() {
335
+ assert_eq!(Reason::ALL.len(), 7);
336
+ assert_eq!(
337
+ Reason::PaneWorkspaceMismatch.required_fact_fields(),
338
+ &[
339
+ Field::RequestedWorkspace,
340
+ Field::ObservedPaneId,
341
+ Field::ObservedPaneWorkspace,
342
+ Field::Endpoint,
343
+ ]
344
+ );
345
+ }
346
+
347
+ #[test]
348
+ fn unavailable_reasons_require_the_fact_they_could_not_observe() {
349
+ assert!(Reason::AmbientTmuxEndpointUnavailable
350
+ .required_fact_fields()
351
+ .contains(&Field::Endpoint));
352
+ assert!(Reason::AmbientPaneIdUnavailable
353
+ .required_fact_fields()
354
+ .contains(&Field::ObservedPaneId));
355
+ assert!(Reason::AmbientPaneWorkspaceUnavailable
356
+ .required_fact_fields()
357
+ .contains(&Field::ObservedPaneWorkspace));
358
+ }
359
+ }
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! `.team/` 布局路径(移植 `paths.py` 的 workspace/team-dir 部分)。
2
3
  //!
3
4
  //! Python 端 `runtime_dir`/`logs_dir`/`artifacts_dir`/`messages_dir` 把 `.team/<sub>`
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! §19/§3 移植 `permissions.py`:role/provider/alias → 规范化权限矩阵。
2
3
  //!
3
4
  //! Python 全程裸 `str` + `dict[str, Any]`(`expand_tools`/`resolve_permissions`/
@@ -56,7 +57,7 @@ impl Tool {
56
57
  ///
57
58
  /// 注:返回**声明序集合**;Python 返回的是 role 字面顺序的 list,但下游 `resolve_*`
58
59
  /// 立即过 `expand_tools`(去重+排序),顺序不参与对拍,故此处用 `BTreeSet` 即可。
59
- pub fn default_tools_for_role(role: &str) -> BTreeSet<Tool> {
60
+ fn default_tools_for_role(role: &str) -> BTreeSet<Tool> {
60
61
  use Tool::*;
61
62
  let tools: &[Tool] = match role {
62
63
  "leader" | "supervisor" => &[FsRead, FsList, McpTeam, ProviderBuiltin],
@@ -175,7 +176,7 @@ pub fn is_canonical_tool(name: &str) -> bool {
175
176
  ///
176
177
  /// 表里没有的 provider(如 `claude`)= Python 的 `.get(provider, {})` → 空表 →
177
178
  /// 每个 tool 再 `.get(tool, "prompt_only")` → 全 `prompt_only`(对拍 `R-unknownprov`)。
178
- pub fn provider_enforcement(provider: Provider, tool: Tool) -> Enforcement {
179
+ fn provider_enforcement(provider: Provider, tool: Tool) -> Enforcement {
179
180
  use Enforcement::{Hard, PromptOnly};
180
181
  use Tool::*;
181
182
  match provider {
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! 移植 `team_agent/routing.py` 的纯函数 `route_task`(真相源 v0.2.11)。
2
3
  //!
3
4
  //! 操作 spec/task 的 [`yaml::Value`]。返回 [`RouteResult`]{agent_id, reason}。
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! spec / result-envelope 校验(`spec.py`)。
2
3
  //!
3
4
  //! 本 module **操作解析后的 Value**(非 typed struct)——与 Python 一样校验 dict,
@@ -400,6 +401,7 @@ fn check_agent(agent: &Yaml, path: &str, errors: &mut Vec<String>) {
400
401
  "preferred_for",
401
402
  "avoid_for",
402
403
  "output_contract",
404
+ "communication_mode",
403
405
  "paused",
404
406
  "auth_mode",
405
407
  "profile",
@@ -412,6 +414,21 @@ fn check_agent(agent: &Yaml, path: &str, errors: &mut Vec<String>) {
412
414
  if !agent.is_map() {
413
415
  return;
414
416
  }
417
+ if let Some(value) = agent.get("communication_mode") {
418
+ match value.as_str() {
419
+ Some(raw) if crate::communication_mode::CommunicationMode::parse(raw).is_none() => {
420
+ errors.push(format!(
421
+ "{path}/communication_mode: unknown communication_mode '{raw}'"
422
+ ));
423
+ }
424
+ None => {
425
+ errors.push(format!(
426
+ "{path}/communication_mode: unknown communication_mode"
427
+ ));
428
+ }
429
+ Some(_) => {}
430
+ }
431
+ }
415
432
  // 0.4.x provider effort MVP step 3: effort syntactic + semantic validation.
416
433
  if let Some(raw) = agent.get("effort").and_then(Yaml::as_str) {
417
434
  match crate::model::enums::ProviderEffort::parse(raw) {
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! 移植 `team_agent/task_graph.py` 的三个纯函数:`find_dependency_cycle` /
2
3
  //! `ready_tasks` / `update_task_status`(真相源 v0.2.11)。
3
4
  //!
@@ -1,3 +1,4 @@
1
+ //!
1
2
  #![allow(clippy::unwrap_used)]
2
3
  use super::*;
3
4
 
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! step 2 · model — `simple_yaml` 方言移植(真相源 `src/team_agent/simple_yaml.py`)。
2
3
  //!
3
4
  //! Team Agent **不**用标准 YAML:它有一份零依赖、字节级特判的子集 `loads`/`dumps`,