@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
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! E7 (0.5.9 host-leader-registry-design §4.1): `team-agent leaders` command.
2
3
  //!
3
4
  //! Enumerates entries under `~/.team-agent/leaders`, re-validates each
@@ -13,6 +14,7 @@
13
14
  use super::{types::LeadersArgs, CliError, CmdResult};
14
15
  use serde_json::{json, Value};
15
16
 
17
+ ///
16
18
  /// E7 CLI entry point (E7 test 2 marker: `cmd_leaders`).
17
19
  ///
18
20
  /// Reads registry entries, canonical-validates each, and groups by
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! step 14b · cli — `team-agent <subcommand>` clap 命令面(真相源 `cli/`)。
2
3
  //!
3
4
  //! Card: `docs/phase0/subsystems/14-mcp_cli.md`(CLI 半边)。
@@ -78,6 +79,7 @@ pub use send::*;
78
79
  pub use status::*;
79
80
  pub use types::*;
80
81
 
82
+ ///
81
83
  /// Public `attach-leader` CLI handler. It consumes the typed pane/provider args and
82
84
  /// writes/returns a `leader_receiver` binding via the leader lease port.
83
85
  pub fn cmd_attach_leader(args: &AttachLeaderArgs) -> Result<CmdResult, CliError> {
@@ -117,6 +119,7 @@ pub mod lifecycle_port {
117
119
  use super::*;
118
120
  use crate::model::enums::Provider;
119
121
 
122
+ ///
120
123
  /// `runtime.quick_start`(`cmd_quick_start` 委派)。返回 `{ok, summary, ...}` 稳定形状。
121
124
  pub fn quick_start(
122
125
  workspace: &Path,
@@ -140,6 +143,7 @@ pub mod lifecycle_port {
140
143
  Err(e) => Ok(error_value(e)),
141
144
  }
142
145
  }
146
+ ///
143
147
  /// `runtime.start_leader`(`codex`/`claude` passthrough + `cmd_codex`/`cmd_claude`)。
144
148
  pub fn start_leader(
145
149
  provider: Provider,
@@ -151,7 +155,7 @@ pub mod lifecycle_port {
151
155
  .attach_session
152
156
  .as_ref()
153
157
  .map(|name| crate::transport::SessionName::new(name.clone()));
154
- let plan = crate::leader::start::leader_start_plan(
158
+ let prepared = match crate::leader::start::prepare_leader_start_with_nested_attach(
155
159
  provider,
156
160
  provider_args,
157
161
  cwd,
@@ -159,16 +163,29 @@ pub mod lifecycle_port {
159
163
  attach.confirm_attach,
160
164
  attach_session.as_ref(),
161
165
  attach.external_leader,
162
- )
163
- .map_err(|e| CliError::Runtime(e.to_string()))?;
164
- let outcome = crate::leader::start::execute_leader_plan(&plan, cwd)
166
+ attach.allow_nested_attach,
167
+ ) {
168
+ Ok(prepared) => prepared,
169
+ Err(crate::leader::start::PrepareLeaderStartError::PaneAuthorityRefused(refusal)) => {
170
+ return Ok(pane_authority_refusal_value(provider, attach, &refusal));
171
+ }
172
+ Err(crate::leader::start::PrepareLeaderStartError::Leader(error)) => {
173
+ return Err(CliError::Runtime(error.to_string()));
174
+ }
175
+ };
176
+ let outcome = crate::leader::start::execute_prepared_leader_start(&prepared, cwd)
165
177
  .map_err(|e| CliError::Runtime(e.to_string()))?;
178
+ let plan = prepared.plan();
166
179
  let ok = match outcome.status {
167
180
  crate::leader::LeaderLaunchStatus::Exited => outcome.exit_code == Some(0),
168
181
  crate::leader::LeaderLaunchStatus::Detached => true,
169
182
  crate::leader::LeaderLaunchStatus::NotStarted => false,
170
183
  };
171
- let leader_attach_command = leader_attach_command_for_plan(cwd, &plan);
184
+ let leader_attach_command = if outcome.reason.as_deref() == Some("PaneWorkspaceMismatch") {
185
+ Some("team-agent attach-leader".to_string())
186
+ } else {
187
+ leader_attach_command_for_plan(cwd, &plan)
188
+ };
172
189
  Ok(json!({
173
190
  "ok": ok,
174
191
  "provider": provider,
@@ -187,6 +204,251 @@ pub mod lifecycle_port {
187
204
  }))
188
205
  }
189
206
 
207
+ fn pane_authority_refusal_value(
208
+ provider: Provider,
209
+ attach: &LeaderLauncherArgs,
210
+ refusal: &crate::model::pane_authority_refusal::PaneAuthorityRefusal,
211
+ ) -> Value {
212
+ use crate::model::pane_authority_refusal::{
213
+ PaneAuthorityRecoveryAction, PaneAuthorityRecoveryHint, PaneAuthorityRefusalFacts,
214
+ PaneAuthorityRefusalField, ACTION_FIELD, ACTION_REQUIRED_FIELD, HINT_ACTION_FIELD,
215
+ REASON_FIELD,
216
+ };
217
+
218
+ let mut facts = Map::new();
219
+ facts.insert(
220
+ REASON_FIELD.to_string(),
221
+ Value::String(refusal.reason().as_str().to_string()),
222
+ );
223
+ match &refusal.facts {
224
+ PaneAuthorityRefusalFacts::AmbientTmuxEndpointUnavailable(payload) => {
225
+ insert_path_fact(
226
+ &mut facts,
227
+ PaneAuthorityRefusalField::RequestedWorkspace,
228
+ &payload.requested_workspace,
229
+ );
230
+ insert_unavailable_fact(
231
+ &mut facts,
232
+ PaneAuthorityRefusalField::Endpoint,
233
+ payload.endpoint.availability().as_str(),
234
+ payload.endpoint.cause.as_str(),
235
+ );
236
+ }
237
+ PaneAuthorityRefusalFacts::AmbientPaneIdUnavailable(payload) => {
238
+ insert_path_fact(
239
+ &mut facts,
240
+ PaneAuthorityRefusalField::RequestedWorkspace,
241
+ &payload.requested_workspace,
242
+ );
243
+ insert_unavailable_fact(
244
+ &mut facts,
245
+ PaneAuthorityRefusalField::ObservedPaneId,
246
+ payload.observed_pane_id.availability().as_str(),
247
+ payload.observed_pane_id.cause.as_str(),
248
+ );
249
+ insert_string_fact(
250
+ &mut facts,
251
+ PaneAuthorityRefusalField::Endpoint,
252
+ &payload.endpoint,
253
+ );
254
+ }
255
+ PaneAuthorityRefusalFacts::AmbientPaneWorkspaceUnavailable(payload) => {
256
+ insert_path_fact(
257
+ &mut facts,
258
+ PaneAuthorityRefusalField::RequestedWorkspace,
259
+ &payload.requested_workspace,
260
+ );
261
+ insert_string_fact(
262
+ &mut facts,
263
+ PaneAuthorityRefusalField::ObservedPaneId,
264
+ &payload.observed_pane_id,
265
+ );
266
+ insert_unavailable_fact(
267
+ &mut facts,
268
+ PaneAuthorityRefusalField::ObservedPaneWorkspace,
269
+ payload.observed_pane_workspace.availability().as_str(),
270
+ payload.observed_pane_workspace.cause.as_str(),
271
+ );
272
+ insert_string_fact(
273
+ &mut facts,
274
+ PaneAuthorityRefusalField::Endpoint,
275
+ &payload.endpoint,
276
+ );
277
+ }
278
+ PaneAuthorityRefusalFacts::CallerControllingTtyUnavailable(payload) => {
279
+ insert_path_fact(
280
+ &mut facts,
281
+ PaneAuthorityRefusalField::RequestedWorkspace,
282
+ &payload.requested_workspace,
283
+ );
284
+ insert_string_fact(
285
+ &mut facts,
286
+ PaneAuthorityRefusalField::ObservedPaneId,
287
+ &payload.observed_pane_id,
288
+ );
289
+ insert_string_fact(
290
+ &mut facts,
291
+ PaneAuthorityRefusalField::Endpoint,
292
+ &payload.endpoint,
293
+ );
294
+ insert_unavailable_fact(
295
+ &mut facts,
296
+ PaneAuthorityRefusalField::CallerControllingTty,
297
+ payload.caller_controlling_tty.availability().as_str(),
298
+ payload.caller_controlling_tty.cause.as_str(),
299
+ );
300
+ }
301
+ PaneAuthorityRefusalFacts::ObservedPaneTtyUnavailable(payload) => {
302
+ insert_path_fact(
303
+ &mut facts,
304
+ PaneAuthorityRefusalField::RequestedWorkspace,
305
+ &payload.requested_workspace,
306
+ );
307
+ insert_string_fact(
308
+ &mut facts,
309
+ PaneAuthorityRefusalField::ObservedPaneId,
310
+ &payload.observed_pane_id,
311
+ );
312
+ insert_string_fact(
313
+ &mut facts,
314
+ PaneAuthorityRefusalField::Endpoint,
315
+ &payload.endpoint,
316
+ );
317
+ insert_unavailable_fact(
318
+ &mut facts,
319
+ PaneAuthorityRefusalField::ObservedPaneTty,
320
+ payload.observed_pane_tty.availability().as_str(),
321
+ payload.observed_pane_tty.cause.as_str(),
322
+ );
323
+ }
324
+ PaneAuthorityRefusalFacts::PaneTtyMismatch(payload) => {
325
+ insert_path_fact(
326
+ &mut facts,
327
+ PaneAuthorityRefusalField::RequestedWorkspace,
328
+ &payload.requested_workspace,
329
+ );
330
+ insert_string_fact(
331
+ &mut facts,
332
+ PaneAuthorityRefusalField::ObservedPaneId,
333
+ &payload.observed_pane_id,
334
+ );
335
+ insert_string_fact(
336
+ &mut facts,
337
+ PaneAuthorityRefusalField::Endpoint,
338
+ &payload.endpoint,
339
+ );
340
+ facts.insert(
341
+ PaneAuthorityRefusalField::CallerControllingTty
342
+ .as_str()
343
+ .to_string(),
344
+ Value::from(payload.caller_controlling_tty),
345
+ );
346
+ facts.insert(
347
+ PaneAuthorityRefusalField::ObservedPaneTty
348
+ .as_str()
349
+ .to_string(),
350
+ Value::from(payload.observed_pane_tty),
351
+ );
352
+ }
353
+ PaneAuthorityRefusalFacts::PaneWorkspaceMismatch(payload) => {
354
+ insert_path_fact(
355
+ &mut facts,
356
+ PaneAuthorityRefusalField::RequestedWorkspace,
357
+ &payload.requested_workspace,
358
+ );
359
+ insert_string_fact(
360
+ &mut facts,
361
+ PaneAuthorityRefusalField::ObservedPaneId,
362
+ &payload.observed_pane_id,
363
+ );
364
+ insert_path_fact(
365
+ &mut facts,
366
+ PaneAuthorityRefusalField::ObservedPaneWorkspace,
367
+ &payload.observed_pane_workspace,
368
+ );
369
+ insert_string_fact(
370
+ &mut facts,
371
+ PaneAuthorityRefusalField::Endpoint,
372
+ &payload.endpoint,
373
+ );
374
+ }
375
+ }
376
+
377
+ let hint_action = match refusal.recovery.hint_action {
378
+ PaneAuthorityRecoveryHint::AttachLeader => "team-agent attach-leader",
379
+ };
380
+ let action = match refusal.recovery.action {
381
+ PaneAuthorityRecoveryAction::OpenTerminalOutsideCurrentTmuxPaneOrAttachFromMatchingPane => {
382
+ "open a new terminal window outside the current tmux/pane, confirm TMUX and \
383
+ TMUX_PANE are absent, change directory to the requested workspace, and restart \
384
+ the leader; alternatively enter the matching workspace pane and run \
385
+ `team-agent attach-leader`"
386
+ }
387
+ };
388
+ facts.insert(
389
+ ACTION_REQUIRED_FIELD.to_string(),
390
+ Value::Bool(refusal.recovery.action_required),
391
+ );
392
+ facts.insert(
393
+ HINT_ACTION_FIELD.to_string(),
394
+ Value::String(hint_action.to_string()),
395
+ );
396
+ facts.insert(ACTION_FIELD.to_string(), Value::String(action.to_string()));
397
+
398
+ let mut value = json!({
399
+ "ok": false,
400
+ "provider": provider,
401
+ "mode": "exec_provider",
402
+ "leader_topology": if attach.external_leader { "external" } else { "managed" },
403
+ "is_external_leader": attach.external_leader,
404
+ "leader_window": null,
405
+ "leader_attach_command": hint_action,
406
+ "status": "not_started",
407
+ "exit_code": null,
408
+ "attach_existing": attach.attach_existing,
409
+ "confirm_attach": attach.confirm_attach,
410
+ "attach_session": attach.attach_session,
411
+ "session_name": null,
412
+ });
413
+ if let Some(object) = value.as_object_mut() {
414
+ object.extend(facts);
415
+ }
416
+ value
417
+ }
418
+
419
+ fn insert_path_fact(
420
+ facts: &mut Map<String, Value>,
421
+ field: crate::model::pane_authority_refusal::PaneAuthorityRefusalField,
422
+ value: &Path,
423
+ ) {
424
+ insert_string_fact(facts, field, &value.to_string_lossy());
425
+ }
426
+
427
+ fn insert_string_fact(
428
+ facts: &mut Map<String, Value>,
429
+ field: crate::model::pane_authority_refusal::PaneAuthorityRefusalField,
430
+ value: &str,
431
+ ) {
432
+ facts.insert(field.as_str().to_string(), Value::String(value.to_string()));
433
+ }
434
+
435
+ fn insert_unavailable_fact(
436
+ facts: &mut Map<String, Value>,
437
+ field: crate::model::pane_authority_refusal::PaneAuthorityRefusalField,
438
+ availability: &str,
439
+ cause: &str,
440
+ ) {
441
+ use crate::model::pane_authority_refusal::{AVAILABILITY_FIELD, CAUSE_FIELD};
442
+
443
+ let mut value = Map::new();
444
+ value.insert(
445
+ AVAILABILITY_FIELD.to_string(),
446
+ Value::String(availability.to_string()),
447
+ );
448
+ value.insert(CAUSE_FIELD.to_string(), Value::String(cause.to_string()));
449
+ facts.insert(field.as_str().to_string(), Value::Object(value));
450
+ }
451
+
190
452
  pub(crate) fn leader_attach_command_for_plan(
191
453
  cwd: &Path,
192
454
  plan: &crate::leader::LeaderStartPlan,
@@ -198,6 +460,7 @@ pub mod lifecycle_port {
198
460
  let window = plan.leader_window.as_ref()?;
199
461
  crate::tmux_backend::attach_command_for_workspace(cwd, session, window.as_str())
200
462
  }
463
+ ///
201
464
  /// `runtime.shutdown`(`cmd_shutdown`)。
202
465
  ///
203
466
  /// 0.5.x Phase 1d Batch 5: the workspace-transport branch now routes
@@ -289,6 +552,7 @@ pub mod lifecycle_port {
289
552
  },
290
553
  }
291
554
 
555
+ ///
292
556
  /// E12 纯决策(单测下沉):spare = `anchor_sessions` ∪ `team-agent-leader-*` 前缀(并集,锚优先)。
293
557
  /// 全部 session 都不 spare 且非空 → `KillServerExclusive`(独享 socket 兜底);否则逐 session
294
558
  /// kill 非 spare 的(共享 socket / leader 在 → 绝不整 server 拆)。空 session 集 → 逐 kill(no-op)。
@@ -1761,6 +2025,7 @@ pub mod lifecycle_port {
1761
2025
  }
1762
2026
  }
1763
2027
 
2028
+ ///
1764
2029
  /// E4 真机 grounded(任何 team 的 shutdown 都不杀任何 team 的 leader 锚 pane):
1765
2030
  /// 扫 state.json 收集所有 leader-anchor pane_id(top-level team_owner /
1766
2031
  /// leader_receiver + teams[<key>].* 嵌套形态)。返非空 BTreeSet 给
@@ -1972,6 +2237,7 @@ pub mod lifecycle_port {
1972
2237
  protected
1973
2238
  }
1974
2239
 
2240
+ ///
1975
2241
  /// B5/F2 + E4 真机 grounded(任何 team 的 shutdown 都不杀任何 team 的 leader 锚 pane):
1976
2242
  /// the leader terminal's pane process tree joins the protected set (same set, same
1977
2243
  /// mechanism as the invoker ancestry) so the workspace residual sweep's cmdline/cwd
@@ -2337,6 +2603,7 @@ pub mod lifecycle_port {
2337
2603
  let root = root.canonicalize().unwrap_or_else(|_| root.to_path_buf());
2338
2604
  path == root || path.starts_with(root)
2339
2605
  }
2606
+ ///
2340
2607
  /// `runtime.restart`(`cmd_restart`)。
2341
2608
  pub fn restart(
2342
2609
  workspace: &Path,
@@ -2354,6 +2621,7 @@ pub mod lifecycle_port {
2354
2621
  Err(e) => Ok(error_value(e)),
2355
2622
  }
2356
2623
  }
2624
+ ///
2357
2625
  /// `runtime.start_agent`(`cmd_start_agent`)。
2358
2626
  pub fn start_agent(
2359
2627
  workspace: &Path,
@@ -2378,6 +2646,7 @@ pub mod lifecycle_port {
2378
2646
  Err(e) => Ok(error_value(e)),
2379
2647
  }
2380
2648
  }
2649
+ ///
2381
2650
  /// `runtime.stop_agent`(`cmd_stop_agent`)。
2382
2651
  pub fn stop_agent(
2383
2652
  workspace: &Path,
@@ -2390,6 +2659,7 @@ pub mod lifecycle_port {
2390
2659
  Err(e) => Ok(error_value(e)),
2391
2660
  }
2392
2661
  }
2662
+ ///
2393
2663
  /// `runtime.reset_agent`(`cmd_reset_agent`;`--discard-session` 必需)。
2394
2664
  pub fn reset_agent(
2395
2665
  workspace: &Path,
@@ -2440,6 +2710,7 @@ pub mod lifecycle_port {
2440
2710
  Err(e) => Ok(error_value(e)),
2441
2711
  }
2442
2712
  }
2713
+ ///
2443
2714
  /// `runtime.add_agent`(`cmd_add_agent`;`--role-file` 必需)。
2444
2715
  pub fn add_agent(
2445
2716
  workspace: &Path,
@@ -2466,6 +2737,7 @@ pub mod lifecycle_port {
2466
2737
  Err(e) => Ok(error_value(e)),
2467
2738
  }
2468
2739
  }
2740
+ ///
2469
2741
  /// `runtime.fork_agent`(`cmd_fork_agent`;`--as` 必需)。
2470
2742
  pub fn fork_agent(
2471
2743
  workspace: &Path,
@@ -2513,6 +2785,7 @@ pub mod lifecycle_port {
2513
2785
  Err(error) => Ok(error_value(error)),
2514
2786
  }
2515
2787
  }
2788
+ ///
2516
2789
  /// `runtime.remove_agent`(`cmd_remove_agent`;`--from-spec` 须配 `--confirm`)。
2517
2790
  pub fn remove_agent(
2518
2791
  workspace: &Path,
@@ -2684,6 +2957,7 @@ pub mod lifecycle_port {
2684
2957
  format!("'{}'", raw.replace('\'', "'\\''"))
2685
2958
  }
2686
2959
  }
2960
+ ///
2687
2961
  /// `runtime.acknowledge_idle`(`cmd_acknowledge_idle`)。
2688
2962
  pub fn acknowledge_idle(workspace: &Path, team: Option<&str>) -> Result<Value, CliError> {
2689
2963
  let mut state = crate::state::persist::load_runtime_state(workspace)
@@ -3809,6 +4083,7 @@ pub mod lifecycle_port {
3809
4083
  pub mod diagnose_port {
3810
4084
  use super::*;
3811
4085
 
4086
+ ///
3812
4087
  /// `runtime.doctor(spec)` + schema 注入(`cmd_doctor` 默认分支)。
3813
4088
  pub fn doctor(workspace: &Path, spec: Option<&Path>) -> Result<Value, CliError> {
3814
4089
  let tmux_path = which_path("tmux");
@@ -4076,8 +4351,10 @@ pub mod diagnose_port {
4076
4351
  }
4077
4352
  }
4078
4353
  }
4354
+ ///
4079
4355
  /// `run_comms_selftest`(`--comms`/`--gate comms`)。**纯 state-read,零 token**(MUST-NOT-13)。
4080
- pub fn comms_selftest(
4356
+ #[cfg(test)]
4357
+ pub(super) fn comms_selftest(
4081
4358
  workspace: &Path,
4082
4359
  team: Option<&str>,
4083
4360
  gate: Option<&str>,
@@ -4085,14 +4362,19 @@ pub mod diagnose_port {
4085
4362
  crate::diagnose::comms::doctor_comms_json(workspace, team, gate)
4086
4363
  }
4087
4364
 
4365
+ ///
4088
4366
  /// `orphan_gate(fix, confirm)`(`--gate orphans`)。CI gate。
4089
- pub fn orphan_gate(workspace: &Path, fix: bool, confirm: bool) -> Result<Value, CliError> {
4367
+ #[cfg(test)]
4368
+ pub(super) fn orphan_gate(workspace: &Path, fix: bool, confirm: bool) -> Result<Value, CliError> {
4090
4369
  crate::diagnose::orphans::orphan_gate_json(workspace, fix, confirm)
4091
4370
  }
4371
+ ///
4092
4372
  /// `cleanup_orphan_coordinators(confirm)`(`--cleanup-orphans`;dry-run unless `--confirm`)。
4093
- pub fn cleanup_orphans(workspace: &Path, confirm: bool) -> Result<Value, CliError> {
4373
+ #[cfg(test)]
4374
+ pub(super) fn cleanup_orphans(workspace: &Path, confirm: bool) -> Result<Value, CliError> {
4094
4375
  crate::diagnose::orphans::cleanup_orphans_json(workspace, confirm)
4095
4376
  }
4377
+ ///
4096
4378
  /// `fix_schema_layout`(`--fix-schema`)/`schema_diagnosis`。
4097
4379
  pub fn fix_schema(workspace: &Path) -> Result<Value, CliError> {
4098
4380
  let db_path = workspace.join(".team").join("runtime").join("team.db");
@@ -4262,6 +4544,7 @@ pub mod diagnose_port {
4262
4544
  pub mod leader_port {
4263
4545
  use super::*;
4264
4546
 
4547
+ ///
4265
4548
  /// `runtime.takeover(workspace, team, confirm)` 的 CLI `--json` 投影。
4266
4549
  pub fn takeover(
4267
4550
  workspace: &Path,
@@ -4317,6 +4600,7 @@ pub mod leader_port {
4317
4600
  }
4318
4601
  Ok(value)
4319
4602
  }
4603
+ ///
4320
4604
  /// `runtime.claim_leader(...)` 的 CLI `--json` 投影(`cmd_claim_leader`;含 inbox_hint)。
4321
4605
  pub fn claim_leader(
4322
4606
  workspace: &Path,
@@ -4366,6 +4650,7 @@ pub mod leader_port {
4366
4650
  Ok(value)
4367
4651
  }
4368
4652
 
4653
+ ///
4369
4654
  /// `runtime.attach_leader(...)` 的 CLI `--json` 投影。
4370
4655
  pub fn attach_leader(
4371
4656
  workspace: &Path,
@@ -4393,6 +4678,7 @@ pub mod leader_port {
4393
4678
  Ok(value)
4394
4679
  }
4395
4680
 
4681
+ ///
4396
4682
  /// `runtime.leader_identity(workspace, team)`(`cmd_identity`)。
4397
4683
  pub fn leader_identity(workspace: &Path, team: Option<&str>) -> Result<Value, CliError> {
4398
4684
  crate::leader::leader_identity(workspace, team)
@@ -4462,6 +4748,7 @@ pub mod leader_port {
4462
4748
  );
4463
4749
  }
4464
4750
 
4751
+ ///
4465
4752
  /// E7 GC hook: called from shutdown/unbind success paths.
4466
4753
  pub(crate) fn unregister_after_shutdown_success(
4467
4754
  workspace: &Path,
@@ -4733,6 +5020,7 @@ pub mod leader_port {
4733
5020
  Ok(json!([]))
4734
5021
  }
4735
5022
 
5023
+ ///
4736
5024
  /// R8 D6 (decoupled for offline byte-lock — c-lite): project the requeued-exhausted event into the
4737
5025
  /// CLI `requeued_exhausted_watchers` return. golden (leader/__init__.py:56): the `watcher_ids`
4738
5026
  /// STRING list. (Current divergent body — the `requeued` Vec<WatcherNotice> objects — kept until
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! CLI-local stable name resolver for `team-agent send --to-name`.
2
3
 
3
4
  use std::path::{Path, PathBuf};
@@ -54,6 +55,10 @@ pub(crate) struct NamedAddressError {
54
55
  pub action: String,
55
56
  pub log: String,
56
57
  pub candidates: Vec<Value>,
58
+ /// A typed live-channel refusal retained separately from the broader
59
+ /// address error (for example `PaneWorkspaceMismatch` while the address
60
+ /// remains a leader-not-attached refusal).
61
+ pub channel_reason: Option<String>,
57
62
  // E6: when the caller supplied a `<team>/leader` name that isn't a runtime
58
63
  // team_key, echo the requested value + the canonical alternatives so
59
64
  // spec/display-name confusion is visibly diagnosed. Empty for other
@@ -76,6 +81,7 @@ impl NamedAddressError {
76
81
  action: "inspect team-agent status and use an explicit workspace/team name".to_string(),
77
82
  log: "named-address resolver refused before injection".to_string(),
78
83
  candidates: Vec::new(),
84
+ channel_reason: None,
79
85
  requested_team: None,
80
86
  available_team_keys: Vec::new(),
81
87
  suggested_name: None,
@@ -188,6 +194,7 @@ impl NamedAddressError {
188
194
  self.with_scoped_suggestions(requested_display, candidate_values, best)
189
195
  }
190
196
 
197
+ ///
191
198
  /// 0.5.45 naming-addressing (design §3.3/§3.4): attach an
192
199
  /// advisory suggestion payload. `requested` is the original typo
193
200
  /// (surfaced verbatim in JSON + N38 Action); `ranked_candidates`
@@ -237,6 +244,12 @@ impl NamedAddressError {
237
244
  "candidates".to_string(),
238
245
  Value::Array(self.candidates.clone()),
239
246
  );
247
+ if let Some(channel_reason) = self.channel_reason.as_deref() {
248
+ obj.insert(
249
+ "channel_reason".to_string(),
250
+ Value::String(channel_reason.to_string()),
251
+ );
252
+ }
240
253
  if let Some(requested) = self.requested_team.as_deref() {
241
254
  obj.insert(
242
255
  "requested_team".to_string(),
@@ -458,6 +471,7 @@ fn normalize_bare_with_team_scope(
458
471
  }
459
472
  }
460
473
 
474
+ ///
461
475
  /// E6 wiring helper (`cli::send::maybe_enqueue_offline_leader_mailbox`):
462
476
  /// re-parse a `<workspace>::<team>/leader` name and return the resolved
463
477
  /// target workspace + canonical team_key so send.rs can enqueue the
@@ -489,10 +503,14 @@ struct ParsedNamedAddress {
489
503
 
490
504
  impl ParsedNamedAddress {
491
505
  fn display_name(&self) -> String {
492
- match &self.target {
506
+ let target = match &self.target {
493
507
  ParsedTarget::BareAgent(agent) => agent.clone(),
494
508
  ParsedTarget::TeamEntity { team, entity } => format!("{team}/{entity}"),
495
509
  ParsedTarget::SessionWindow { session, window } => format!("{session}:{window}"),
510
+ };
511
+ match &self.workspace {
512
+ Some(workspace) => format!("{}::{target}", workspace.display()),
513
+ None => target,
496
514
  }
497
515
  }
498
516
  }
@@ -987,7 +1005,13 @@ fn resolve_leader(
987
1005
  window,
988
1006
  socket,
989
1007
  );
990
- err.log = format!("{} channel_unbound={reason:?}", err.log);
1008
+ if matches!(
1009
+ &reason,
1010
+ crate::messaging::LeaderChannelUnbound::PaneWorkspaceMismatch(_)
1011
+ ) {
1012
+ err.channel_reason = Some(reason.reason_code().to_string());
1013
+ }
1014
+ err.log = format!("{} channel_unbound={}", err.log, reason.reason_code());
991
1015
  err.candidates =
992
1016
  leader_advisory_candidates(state, team, transport, "state_recorded_socket");
993
1017
  Err(err)
@@ -1,3 +1,4 @@
1
+ //!
1
2
  //! `profile {init,doctor,show}` CLI verb.
2
3
 
3
4
  use super::*;
@@ -159,7 +160,7 @@ fn validate_auth_mode(auth_mode: &str) -> Result<(), CliError> {
159
160
  fn profile_template(name: &str, auth_mode: &str) -> String {
160
161
  match auth_mode {
161
162
  "compatible_api" | "official_api" => {
162
- format!("AUTH_MODE={auth_mode}\nPROFILE_NAME={name}\nAPI_KEY=\nMODEL=\n")
163
+ format!("AUTH_MODE={auth_mode}\nPROFILE_NAME={name}\nBASE_URL=\nAPI_KEY=\nMODEL=\n")
163
164
  }
164
165
  _ => format!("AUTH_MODE=subscription\nPROFILE_NAME={name}\n"),
165
166
  }
@@ -1,3 +1,4 @@
1
+ //!
1
2
  use super::*;
2
3
 
3
4
  pub(super) fn dirty_topology_refusal_value(
@@ -1,3 +1,4 @@
1
+ //!
1
2
  use super::*;
2
3
 
3
4
  pub(super) fn maybe_enqueue_offline_leader_mailbox(
@@ -64,6 +65,7 @@ pub(super) fn maybe_enqueue_offline_leader_mailbox(
64
65
  "to_name": to_name,
65
66
  "target_workspace": target_workspace.display().to_string(),
66
67
  "team_key": team_key,
68
+ "sender": sender,
67
69
  "recipient": "leader",
68
70
  "leader_attached": false,
69
71
  "message_id": message_id,
@@ -78,6 +80,7 @@ pub(super) fn maybe_enqueue_offline_leader_mailbox(
78
80
  "to_name": to_name,
79
81
  "target_workspace": target_workspace.display().to_string(),
80
82
  "team_key": team_key,
83
+ "sender": sender,
81
84
  "recipient": "leader",
82
85
  "leader_attached": false,
83
86
  "message_id": message_id,
@@ -1,3 +1,4 @@
1
+ //!
1
2
  use super::coordinator::{
2
3
  append_loud_ensure_fields, dirty_topology_refusal_value, loud_ensure_coordinator,
3
4
  target_has_known_worker,
@@ -1,3 +1,4 @@
1
+ //!
1
2
  use crate::cli::{CliError, CmdOutput, CmdResult, ExitCode};
2
3
  use crate::messaging::{
3
4
  DeliveryOutcome, DeliveryRefusal, DeliveryStage, DeliveryStatus, MessageTarget, SendOptions,
@@ -169,6 +170,7 @@ pub(super) fn cmd_send_result(value: Value, as_json: bool) -> CmdResult {
169
170
  output: CmdOutput::Human(send_human_output(&value)),
170
171
  exit,
171
172
  as_json: false,
173
+ preserve_json_order: false,
172
174
  }
173
175
  }
174
176
  }
@@ -312,6 +314,7 @@ pub(super) fn delivery_refusal_wire(reason: DeliveryRefusal) -> &'static str {
312
314
  DeliveryRefusal::TmuxTargetMissing => "tmux_target_missing",
313
315
  DeliveryRefusal::MessageAlreadyClaimed => "message_already_claimed",
314
316
  DeliveryRefusal::LeaderNotAttached => "leader_not_attached",
317
+ DeliveryRefusal::PaneWorkspaceMismatch => "PaneWorkspaceMismatch",
315
318
  DeliveryRefusal::CoordinatorUnavailable => "coordinator_unavailable",
316
319
  DeliveryRefusal::NoCallerPane => "no_caller_pane",
317
320
  DeliveryRefusal::TeamOwnerMismatch => "team_owner_mismatch",