@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.
Files changed (326) hide show
  1. package/Cargo.lock +744 -0
  2. package/Cargo.toml +34 -0
  3. package/crates/team-agent/Cargo.toml +33 -0
  4. package/crates/team-agent/src/cli/adapters.rs +1343 -0
  5. package/crates/team-agent/src/cli/diagnose.rs +554 -0
  6. package/crates/team-agent/src/cli/emit.rs +1204 -0
  7. package/crates/team-agent/src/cli/helpers.rs +88 -0
  8. package/crates/team-agent/src/cli/leader.rs +216 -0
  9. package/crates/team-agent/src/cli/mod.rs +1207 -0
  10. package/crates/team-agent/src/cli/profile.rs +306 -0
  11. package/crates/team-agent/src/cli/send.rs +215 -0
  12. package/crates/team-agent/src/cli/status.rs +179 -0
  13. package/crates/team-agent/src/cli/status_port.rs +502 -0
  14. package/crates/team-agent/src/cli/tests/base.rs +616 -0
  15. package/crates/team-agent/src/cli/tests/compile.rs +96 -0
  16. package/crates/team-agent/src/cli/tests/divergence.rs +509 -0
  17. package/crates/team-agent/src/cli/tests/lane_c.rs +333 -0
  18. package/crates/team-agent/src/cli/tests/leader_watch.rs +395 -0
  19. package/crates/team-agent/src/cli/tests/main_preserved.rs +675 -0
  20. package/crates/team-agent/src/cli/tests/missing_subcommands.rs +390 -0
  21. package/crates/team-agent/src/cli/tests/mod.rs +97 -0
  22. package/crates/team-agent/src/cli/tests/peer_allow.rs +137 -0
  23. package/crates/team-agent/src/cli/tests/repair_state_byte_lock.rs +302 -0
  24. package/crates/team-agent/src/cli/tests/run_delegation.rs +305 -0
  25. package/crates/team-agent/src/cli/tests/status_send.rs +385 -0
  26. package/crates/team-agent/src/cli/tests/verb_profile.rs +182 -0
  27. package/crates/team-agent/src/cli/tests/verb_settle.rs +236 -0
  28. package/crates/team-agent/src/cli/tests/verb_validate.rs +184 -0
  29. package/crates/team-agent/src/cli/types.rs +605 -0
  30. package/crates/team-agent/src/compiler/tests.rs +701 -0
  31. package/crates/team-agent/src/compiler.rs +489 -0
  32. package/crates/team-agent/src/coordinator/backoff.rs +153 -0
  33. package/crates/team-agent/src/coordinator/health.rs +557 -0
  34. package/crates/team-agent/src/coordinator/mod.rs +80 -0
  35. package/crates/team-agent/src/coordinator/orphan.rs +179 -0
  36. package/crates/team-agent/src/coordinator/tests/abnormal.rs +255 -0
  37. package/crates/team-agent/src/coordinator/tests/basics.rs +262 -0
  38. package/crates/team-agent/src/coordinator/tests/daemon.rs +323 -0
  39. package/crates/team-agent/src/coordinator/tests/health_sync.rs +263 -0
  40. package/crates/team-agent/src/coordinator/tests/main_preserved.rs +136 -0
  41. package/crates/team-agent/src/coordinator/tests/mod.rs +310 -0
  42. package/crates/team-agent/src/coordinator/tests/spine.rs +261 -0
  43. package/crates/team-agent/src/coordinator/tests/takeover.rs +227 -0
  44. package/crates/team-agent/src/coordinator/tests/tick_core.rs +256 -0
  45. package/crates/team-agent/src/coordinator/tests/watch.rs +167 -0
  46. package/crates/team-agent/src/coordinator/tick.rs +2032 -0
  47. package/crates/team-agent/src/coordinator/types.rs +584 -0
  48. package/crates/team-agent/src/db/migration.rs +716 -0
  49. package/crates/team-agent/src/db/mod.rs +23 -0
  50. package/crates/team-agent/src/db/schema.rs +378 -0
  51. package/crates/team-agent/src/event_log.rs +375 -0
  52. package/crates/team-agent/src/fake_worker.rs +253 -0
  53. package/crates/team-agent/src/leader/helpers.rs +190 -0
  54. package/crates/team-agent/src/leader/inject.rs +33 -0
  55. package/crates/team-agent/src/leader/lease.rs +1084 -0
  56. package/crates/team-agent/src/leader/mod.rs +99 -0
  57. package/crates/team-agent/src/leader/owner_bind.rs +292 -0
  58. package/crates/team-agent/src/leader/rediscover/tests.rs +526 -0
  59. package/crates/team-agent/src/leader/rediscover.rs +1101 -0
  60. package/crates/team-agent/src/leader/start.rs +273 -0
  61. package/crates/team-agent/src/leader/takeover.rs +235 -0
  62. package/crates/team-agent/src/leader/tests/basics.rs +183 -0
  63. package/crates/team-agent/src/leader/tests/byte_findings.rs +237 -0
  64. package/crates/team-agent/src/leader/tests/identity.rs +206 -0
  65. package/crates/team-agent/src/leader/tests/idle.rs +272 -0
  66. package/crates/team-agent/src/leader/tests/lease_api.rs +225 -0
  67. package/crates/team-agent/src/leader/tests/lease_claim.rs +410 -0
  68. package/crates/team-agent/src/leader/tests/mod.rs +125 -0
  69. package/crates/team-agent/src/leader/tests/rediscover.rs +351 -0
  70. package/crates/team-agent/src/leader/tests/wake_start_owner.rs +204 -0
  71. package/crates/team-agent/src/leader/types.rs +489 -0
  72. package/crates/team-agent/src/lib.rs +85 -0
  73. package/crates/team-agent/src/lifecycle/display.rs +228 -0
  74. package/crates/team-agent/src/lifecycle/helpers.rs +112 -0
  75. package/crates/team-agent/src/lifecycle/launch/plan.rs +227 -0
  76. package/crates/team-agent/src/lifecycle/launch.rs +2109 -0
  77. package/crates/team-agent/src/lifecycle/mod.rs +62 -0
  78. package/crates/team-agent/src/lifecycle/restart/agent.rs +533 -0
  79. package/crates/team-agent/src/lifecycle/restart/common.rs +517 -0
  80. package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +41 -0
  81. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +268 -0
  82. package/crates/team-agent/src/lifecycle/restart/remove.rs +780 -0
  83. package/crates/team-agent/src/lifecycle/restart/selection.rs +208 -0
  84. package/crates/team-agent/src/lifecycle/restart/team_state.rs +242 -0
  85. package/crates/team-agent/src/lifecycle/restart.rs +76 -0
  86. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +455 -0
  87. package/crates/team-agent/src/lifecycle/tests/core.rs +989 -0
  88. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +583 -0
  89. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +985 -0
  90. package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +265 -0
  91. package/crates/team-agent/src/lifecycle/tests.rs +27 -0
  92. package/crates/team-agent/src/lifecycle/types.rs +710 -0
  93. package/crates/team-agent/src/main.rs +41 -0
  94. package/crates/team-agent/src/mcp_server/helpers.rs +228 -0
  95. package/crates/team-agent/src/mcp_server/mod.rs +183 -0
  96. package/crates/team-agent/src/mcp_server/normalize.rs +312 -0
  97. package/crates/team-agent/src/mcp_server/tests/golden.rs +283 -0
  98. package/crates/team-agent/src/mcp_server/tests/normalize.rs +244 -0
  99. package/crates/team-agent/src/mcp_server/tests/scoped.rs +189 -0
  100. package/crates/team-agent/src/mcp_server/tests/send.rs +222 -0
  101. package/crates/team-agent/src/mcp_server/tests/tools.rs +158 -0
  102. package/crates/team-agent/src/mcp_server/tests/wire.rs +187 -0
  103. package/crates/team-agent/src/mcp_server/tests.rs +38 -0
  104. package/crates/team-agent/src/mcp_server/tools.rs +603 -0
  105. package/crates/team-agent/src/mcp_server/types.rs +421 -0
  106. package/crates/team-agent/src/mcp_server/wire.rs +468 -0
  107. package/crates/team-agent/src/message_store.rs +767 -0
  108. package/crates/team-agent/src/messaging/activity.rs +433 -0
  109. package/crates/team-agent/src/messaging/delivery.rs +743 -0
  110. package/crates/team-agent/src/messaging/helpers.rs +209 -0
  111. package/crates/team-agent/src/messaging/leader_receiver.rs +329 -0
  112. package/crates/team-agent/src/messaging/mod.rs +147 -0
  113. package/crates/team-agent/src/messaging/peers.rs +32 -0
  114. package/crates/team-agent/src/messaging/results.rs +553 -0
  115. package/crates/team-agent/src/messaging/scheduler.rs +344 -0
  116. package/crates/team-agent/src/messaging/selftest.rs +100 -0
  117. package/crates/team-agent/src/messaging/send.rs +578 -0
  118. package/crates/team-agent/src/messaging/tests/basic.rs +357 -0
  119. package/crates/team-agent/src/messaging/tests/main_preserved.rs +122 -0
  120. package/crates/team-agent/src/messaging/tests/mod.rs +293 -0
  121. package/crates/team-agent/src/messaging/tests/runtime.rs +1422 -0
  122. package/crates/team-agent/src/messaging/tests/spine.rs +437 -0
  123. package/crates/team-agent/src/messaging/trust.rs +192 -0
  124. package/crates/team-agent/src/messaging/types.rs +355 -0
  125. package/crates/team-agent/src/messaging/watchers.rs +591 -0
  126. package/crates/team-agent/src/model/enums.rs +311 -0
  127. package/crates/team-agent/src/model/errors.rs +17 -0
  128. package/crates/team-agent/src/model/ids.rs +155 -0
  129. package/crates/team-agent/src/model/mod.rs +22 -0
  130. package/crates/team-agent/src/model/paths.rs +228 -0
  131. package/crates/team-agent/src/model/permissions.rs +567 -0
  132. package/crates/team-agent/src/model/routing.rs +340 -0
  133. package/crates/team-agent/src/model/spec.rs +680 -0
  134. package/crates/team-agent/src/model/task_graph.rs +380 -0
  135. package/crates/team-agent/src/model/testdata/fuzz.golden.yaml +43 -0
  136. package/crates/team-agent/src/model/testdata/fuzz.yaml +43 -0
  137. package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +207 -0
  138. package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +206 -0
  139. package/crates/team-agent/src/model/testdata/team.spec.yaml +206 -0
  140. package/crates/team-agent/src/model/yaml/tests.rs +288 -0
  141. package/crates/team-agent/src/model/yaml.rs +800 -0
  142. package/crates/team-agent/src/packaging/install.rs +305 -0
  143. package/crates/team-agent/src/packaging/migrate.rs +30 -0
  144. package/crates/team-agent/src/packaging/mod.rs +82 -0
  145. package/crates/team-agent/src/packaging/repair.rs +24 -0
  146. package/crates/team-agent/src/packaging/tests.rs +829 -0
  147. package/crates/team-agent/src/packaging/types.rs +369 -0
  148. package/crates/team-agent/src/provider/adapter.rs +801 -0
  149. package/crates/team-agent/src/provider/approvals/mod.rs +2 -0
  150. package/crates/team-agent/src/provider/approvals/parsing.rs +452 -0
  151. package/crates/team-agent/src/provider/approvals/runtime_prompts.rs +163 -0
  152. package/crates/team-agent/src/provider/classify.rs +456 -0
  153. package/crates/team-agent/src/provider/faults.rs +136 -0
  154. package/crates/team-agent/src/provider/helpers.rs +41 -0
  155. package/crates/team-agent/src/provider/mod.rs +53 -0
  156. package/crates/team-agent/src/provider/startup_prompt.rs +423 -0
  157. package/crates/team-agent/src/provider/tests/adapter.rs +239 -0
  158. package/crates/team-agent/src/provider/tests/classify.rs +240 -0
  159. package/crates/team-agent/src/provider/tests/faults.rs +120 -0
  160. package/crates/team-agent/src/provider/tests/idle.rs +208 -0
  161. package/crates/team-agent/src/provider/tests/wire.rs +213 -0
  162. package/crates/team-agent/src/provider/tests.rs +31 -0
  163. package/crates/team-agent/src/provider/types.rs +424 -0
  164. package/crates/team-agent/src/state/identity.rs +659 -0
  165. package/crates/team-agent/src/state/mod.rs +58 -0
  166. package/crates/team-agent/src/state/owner_gate.rs +423 -0
  167. package/crates/team-agent/src/state/persist.rs +712 -0
  168. package/crates/team-agent/src/state/projection.rs +657 -0
  169. package/crates/team-agent/src/state/selector.rs +105 -0
  170. package/crates/team-agent/src/state/testdata/state-rich.canonical.json +133 -0
  171. package/crates/team-agent/src/tmux_backend/tests.rs +765 -0
  172. package/crates/team-agent/src/tmux_backend.rs +810 -0
  173. package/crates/team-agent/src/transport/test_support.rs +252 -0
  174. package/crates/team-agent/src/transport/tests/behavior.rs +327 -0
  175. package/crates/team-agent/src/transport/tests/mod.rs +199 -0
  176. package/crates/team-agent/src/transport/tests/wire.rs +527 -0
  177. package/crates/team-agent/src/transport.rs +774 -0
  178. package/npm/install.mjs +118 -112
  179. package/package.json +15 -13
  180. package/crates/team-agent-core/Cargo.toml +0 -12
  181. package/crates/team-agent-core/src/lib.rs +0 -332
  182. package/crates/team-agent-core/src/main.rs +0 -152
  183. package/pyproject.toml +0 -18
  184. package/scripts/install.py +0 -88
  185. package/scripts/run_regression_tests.py +0 -83
  186. package/src/team_agent/__init__.py +0 -3
  187. package/src/team_agent/__main__.py +0 -5
  188. package/src/team_agent/_legacy_pane_discovery.py +0 -186
  189. package/src/team_agent/abnormal_track.py +0 -253
  190. package/src/team_agent/approvals/__init__.py +0 -65
  191. package/src/team_agent/approvals/constants.py +0 -6
  192. package/src/team_agent/approvals/parsing.py +0 -176
  193. package/src/team_agent/approvals/runtime_prompts.py +0 -171
  194. package/src/team_agent/approvals/status.py +0 -176
  195. package/src/team_agent/cli/__init__.py +0 -137
  196. package/src/team_agent/cli/commands.py +0 -481
  197. package/src/team_agent/cli/e2e.py +0 -202
  198. package/src/team_agent/cli/helpers.py +0 -226
  199. package/src/team_agent/cli/parser.py +0 -540
  200. package/src/team_agent/compiler.py +0 -334
  201. package/src/team_agent/coordinator/__init__.py +0 -53
  202. package/src/team_agent/coordinator/__main__.py +0 -119
  203. package/src/team_agent/coordinator/lifecycle.py +0 -411
  204. package/src/team_agent/coordinator/metadata.py +0 -61
  205. package/src/team_agent/coordinator/paths.py +0 -17
  206. package/src/team_agent/diagnose/__init__.py +0 -48
  207. package/src/team_agent/diagnose/checks.py +0 -101
  208. package/src/team_agent/diagnose/comms.py +0 -213
  209. package/src/team_agent/diagnose/health.py +0 -241
  210. package/src/team_agent/diagnose/orphan_cleanup.py +0 -364
  211. package/src/team_agent/diagnose/preflight.py +0 -194
  212. package/src/team_agent/diagnose/quick_start.py +0 -324
  213. package/src/team_agent/display/__init__.py +0 -92
  214. package/src/team_agent/display/adaptive.py +0 -511
  215. package/src/team_agent/display/backend.py +0 -46
  216. package/src/team_agent/display/close.py +0 -154
  217. package/src/team_agent/display/ghostty.py +0 -77
  218. package/src/team_agent/display/rebuild.py +0 -102
  219. package/src/team_agent/display/tiling.py +0 -156
  220. package/src/team_agent/display/worker_window.py +0 -114
  221. package/src/team_agent/display/workspace.py +0 -382
  222. package/src/team_agent/errors.py +0 -10
  223. package/src/team_agent/events.py +0 -84
  224. package/src/team_agent/fake_worker.py +0 -80
  225. package/src/team_agent/idle_predicate.py +0 -218
  226. package/src/team_agent/idle_takeover.py +0 -59
  227. package/src/team_agent/idle_takeover_wiring.py +0 -114
  228. package/src/team_agent/launch/__init__.py +0 -41
  229. package/src/team_agent/launch/bootstrap.py +0 -85
  230. package/src/team_agent/launch/config.py +0 -106
  231. package/src/team_agent/launch/core.py +0 -301
  232. package/src/team_agent/launch/requirements.py +0 -57
  233. package/src/team_agent/leader/__init__.py +0 -926
  234. package/src/team_agent/leader_binding.py +0 -183
  235. package/src/team_agent/lifecycle/__init__.py +0 -5
  236. package/src/team_agent/lifecycle/agents.py +0 -278
  237. package/src/team_agent/lifecycle/operations.py +0 -411
  238. package/src/team_agent/lifecycle/paste_buffer_hygiene.py +0 -39
  239. package/src/team_agent/lifecycle/start.py +0 -363
  240. package/src/team_agent/mcp_server/__init__.py +0 -42
  241. package/src/team_agent/mcp_server/__main__.py +0 -7
  242. package/src/team_agent/mcp_server/contracts.py +0 -148
  243. package/src/team_agent/mcp_server/normalize.py +0 -257
  244. package/src/team_agent/mcp_server/server.py +0 -150
  245. package/src/team_agent/mcp_server/tools.py +0 -352
  246. package/src/team_agent/message_store/__init__.py +0 -23
  247. package/src/team_agent/message_store/agent_health.py +0 -113
  248. package/src/team_agent/message_store/core.py +0 -497
  249. package/src/team_agent/message_store/leader_notification_log.py +0 -198
  250. package/src/team_agent/message_store/result_watchers.py +0 -251
  251. package/src/team_agent/message_store/schema.py +0 -308
  252. package/src/team_agent/message_store/schema_migration.py +0 -448
  253. package/src/team_agent/messaging/__init__.py +0 -1
  254. package/src/team_agent/messaging/activity_detector.py +0 -262
  255. package/src/team_agent/messaging/delivery.py +0 -504
  256. package/src/team_agent/messaging/deps.py +0 -247
  257. package/src/team_agent/messaging/idle_alerts.py +0 -423
  258. package/src/team_agent/messaging/internal_delivery.py +0 -46
  259. package/src/team_agent/messaging/leader.py +0 -497
  260. package/src/team_agent/messaging/leader_api_errors.py +0 -216
  261. package/src/team_agent/messaging/leader_panes.py +0 -673
  262. package/src/team_agent/messaging/owner_bypass.py +0 -29
  263. package/src/team_agent/messaging/result_delivery.py +0 -539
  264. package/src/team_agent/messaging/results.py +0 -447
  265. package/src/team_agent/messaging/scheduler.py +0 -450
  266. package/src/team_agent/messaging/send.py +0 -532
  267. package/src/team_agent/messaging/session_drift.py +0 -94
  268. package/src/team_agent/messaging/tmux_io.py +0 -506
  269. package/src/team_agent/messaging/tmux_prompt.py +0 -338
  270. package/src/team_agent/messaging/trust_auto_answer.py +0 -52
  271. package/src/team_agent/orchestrator/__init__.py +0 -376
  272. package/src/team_agent/orchestrator/plan.py +0 -122
  273. package/src/team_agent/orchestrator/state.py +0 -128
  274. package/src/team_agent/paths.py +0 -45
  275. package/src/team_agent/permissions.py +0 -123
  276. package/src/team_agent/profiles/__init__.py +0 -82
  277. package/src/team_agent/profiles/constants.py +0 -19
  278. package/src/team_agent/profiles/core.py +0 -407
  279. package/src/team_agent/profiles/helpers.py +0 -69
  280. package/src/team_agent/profiles/provider_env.py +0 -188
  281. package/src/team_agent/profiles/smoke.py +0 -201
  282. package/src/team_agent/provider_cli/__init__.py +0 -43
  283. package/src/team_agent/provider_cli/adapter.py +0 -172
  284. package/src/team_agent/provider_cli/base.py +0 -48
  285. package/src/team_agent/provider_cli/claude.py +0 -503
  286. package/src/team_agent/provider_cli/codex.py +0 -336
  287. package/src/team_agent/provider_cli/copilot.py +0 -8
  288. package/src/team_agent/provider_cli/fake.py +0 -39
  289. package/src/team_agent/provider_cli/gemini.py +0 -95
  290. package/src/team_agent/provider_cli/opencode.py +0 -8
  291. package/src/team_agent/provider_cli/prompt.py +0 -62
  292. package/src/team_agent/provider_cli/registry.py +0 -18
  293. package/src/team_agent/provider_cli/unsupported.py +0 -32
  294. package/src/team_agent/provider_state/README.md +0 -78
  295. package/src/team_agent/provider_state/__init__.py +0 -91
  296. package/src/team_agent/provider_state/claude.py +0 -86
  297. package/src/team_agent/provider_state/codex.py +0 -84
  298. package/src/team_agent/provider_state/common.py +0 -207
  299. package/src/team_agent/provider_state/registry.py +0 -118
  300. package/src/team_agent/providers.py +0 -163
  301. package/src/team_agent/quality_gates.py +0 -104
  302. package/src/team_agent/restart/__init__.py +0 -34
  303. package/src/team_agent/restart/orchestration.py +0 -554
  304. package/src/team_agent/restart/selection.py +0 -89
  305. package/src/team_agent/restart/snapshot.py +0 -70
  306. package/src/team_agent/routing.py +0 -84
  307. package/src/team_agent/runtime.py +0 -1243
  308. package/src/team_agent/rust_core.py +0 -327
  309. package/src/team_agent/sessions/__init__.py +0 -25
  310. package/src/team_agent/sessions/capture.py +0 -144
  311. package/src/team_agent/sessions/inventory.py +0 -44
  312. package/src/team_agent/sessions/resume.py +0 -135
  313. package/src/team_agent/simple_yaml.py +0 -236
  314. package/src/team_agent/spec.py +0 -370
  315. package/src/team_agent/state.py +0 -693
  316. package/src/team_agent/status/__init__.py +0 -63
  317. package/src/team_agent/status/approvals.py +0 -52
  318. package/src/team_agent/status/compact.py +0 -158
  319. package/src/team_agent/status/constants.py +0 -18
  320. package/src/team_agent/status/inbox.py +0 -58
  321. package/src/team_agent/status/peek.py +0 -117
  322. package/src/team_agent/status/queries.py +0 -199
  323. package/src/team_agent/task_graph.py +0 -80
  324. package/src/team_agent/terminal.py +0 -57
  325. package/src/team_agent/wake.py +0 -58
  326. package/src/team_agent/watch/__init__.py +0 -145
@@ -0,0 +1,421 @@
1
+ //! step 14a · mcp_server::types — wire enums / envelopes / normalized-result carriers.
2
+
3
+ use serde::{Deserialize, Serialize};
4
+ use serde_json::Value;
5
+ use thiserror::Error;
6
+
7
+ // ── REUSE: step 2 model (ids + normalized-envelope value enums) ─────────────
8
+ use crate::model::enums::{ChangeKind, ResultStatus, RiskSeverity, TestStatus};
9
+ use crate::model::ids::{AgentId, TaskId, TeamKey};
10
+
11
+ use super::helpers::tool_error_reason_wire;
12
+
13
+ // ═══════════════════════════════════════════════════════════════════════════
14
+ // ERRORS — McpError is the server-level surface; ToolError is the wire envelope.
15
+ // ═══════════════════════════════════════════════════════════════════════════
16
+
17
+ /// Server/handler-level error (lib boundary, `thiserror`). Distinct from the
18
+ /// per-tool wire envelope [`ToolError`]: this is for I/O / state / delegate
19
+ /// failures that propagate up through `Result`. `handle_mcp`'s `tools/call` path
20
+ /// converts a caught argument/runtime failure into a [`ToolError`] envelope rather
21
+ /// than an `McpError`, mirroring `server.py:69-72`.
22
+ #[derive(Debug, Error)]
23
+ pub enum McpError {
24
+ /// JSON parse of an stdin line failed (`json.loads` raise; surfaced on stdout
25
+ /// as a `-32000`/`-32700` frame per `server.py:135-149`).
26
+ #[error("json: {0}")]
27
+ Json(#[from] serde_json::Error),
28
+ /// State read/write failed (delegated to step 5 persist).
29
+ #[error("state: {0}")]
30
+ State(#[from] crate::state::StateError),
31
+ /// Message store failed (delegated to step 7).
32
+ #[error("message_store: {0}")]
33
+ MessageStore(#[from] crate::message_store::MessageStoreError),
34
+ /// Event log append failed (delegated to step 4).
35
+ #[error("event_log: {0}")]
36
+ EventLog(#[from] crate::event_log::EventLogError),
37
+ /// A delegated messaging op failed (step 11).
38
+ #[error("messaging: {0}")]
39
+ Messaging(#[from] crate::messaging::MessagingError),
40
+ /// stdio transport I/O (read line / write frame / flush).
41
+ #[error("io: {0}")]
42
+ Io(#[from] std::io::Error),
43
+ }
44
+
45
+ // ═══════════════════════════════════════════════════════════════════════════
46
+ // WIRE ENUMS (§19) —散字符串 → 穷尽 enum;契约字节级真相由这些派生。
47
+ // ═══════════════════════════════════════════════════════════════════════════
48
+
49
+ /// The 12 MCP tool names (`server.py:19-43` if-chain = 字符串打地鼠). Exhaustive
50
+ /// match; unknown → [`ToolErrorReason::UnknownTool`]. [`tools_contract`] (the
51
+ /// `TOOLS` wire list returned by `tools/list`) MUST be derived from this enum so
52
+ /// name/inputSchema stay byte-identical to `contracts.py`.
53
+ ///
54
+ /// [`tools_contract`]: super::tools_contract
55
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
56
+ #[serde(rename_all = "snake_case")]
57
+ pub enum McpTool {
58
+ AssignTask,
59
+ SendMessage,
60
+ ReportResult,
61
+ UpdateState,
62
+ GetTeamStatus,
63
+ StopAgent,
64
+ ResetAgent,
65
+ AddAgent,
66
+ ForkAgent,
67
+ RequestHuman,
68
+ StuckList,
69
+ StuckCancel,
70
+ }
71
+
72
+ impl McpTool {
73
+ /// Wire name (`assign_task` … `stuck_cancel`) — the byte-stable string used in
74
+ /// `tools/list` and `tools/call`. Parse failure ⇒ [`ToolErrorReason::UnknownTool`].
75
+ pub fn wire_name(self) -> &'static str {
76
+ match self {
77
+ McpTool::AssignTask => "assign_task",
78
+ McpTool::SendMessage => "send_message",
79
+ McpTool::ReportResult => "report_result",
80
+ McpTool::UpdateState => "update_state",
81
+ McpTool::GetTeamStatus => "get_team_status",
82
+ McpTool::StopAgent => "stop_agent",
83
+ McpTool::ResetAgent => "reset_agent",
84
+ McpTool::AddAgent => "add_agent",
85
+ McpTool::ForkAgent => "fork_agent",
86
+ McpTool::RequestHuman => "request_human",
87
+ McpTool::StuckList => "stuck_list",
88
+ McpTool::StuckCancel => "stuck_cancel",
89
+ }
90
+ }
91
+
92
+ /// Parse a wire tool name into the enum; `None` for an unknown tool (caller maps
93
+ /// to [`ToolErrorReason::UnknownTool`], matching `server.py:43`).
94
+ pub fn parse(name: &str) -> Option<Self> {
95
+ match name {
96
+ "assign_task" => Some(McpTool::AssignTask),
97
+ "send_message" => Some(McpTool::SendMessage),
98
+ "report_result" => Some(McpTool::ReportResult),
99
+ "update_state" => Some(McpTool::UpdateState),
100
+ "get_team_status" => Some(McpTool::GetTeamStatus),
101
+ "stop_agent" => Some(McpTool::StopAgent),
102
+ "reset_agent" => Some(McpTool::ResetAgent),
103
+ "add_agent" => Some(McpTool::AddAgent),
104
+ "fork_agent" => Some(McpTool::ForkAgent),
105
+ "request_human" => Some(McpTool::RequestHuman),
106
+ "stuck_list" => Some(McpTool::StuckList),
107
+ "stuck_cancel" => Some(McpTool::StuckCancel),
108
+ _ => None,
109
+ }
110
+ }
111
+ }
112
+
113
+ /// JSON-RPC method (`server.py:46-91`). `notifications/*` → no reply; unknown →
114
+ /// `-32601`.
115
+ #[derive(Debug, Clone, PartialEq, Eq)]
116
+ pub enum RpcMethod {
117
+ Initialize,
118
+ ToolsList,
119
+ ToolsCall,
120
+ /// `notifications/<rest>` — [`handle_mcp`] returns `None`, loop continues.
121
+ ///
122
+ /// [`handle_mcp`]: super::handle_mcp
123
+ Notification(String),
124
+ /// Anything else → `-32601 unknown method`.
125
+ Unknown(String),
126
+ }
127
+
128
+ impl RpcMethod {
129
+ /// Classify a raw `method` string (`server.py:47-49,87`). `notifications/foo` →
130
+ /// `Notification("foo")` (or full suffix); empty/absent handled by the caller.
131
+ pub fn classify(method: &str) -> Self {
132
+ match method {
133
+ "initialize" => RpcMethod::Initialize,
134
+ "tools/list" => RpcMethod::ToolsList,
135
+ "tools/call" => RpcMethod::ToolsCall,
136
+ m if m.starts_with("notifications/") => {
137
+ RpcMethod::Notification(m.trim_start_matches("notifications/").to_string())
138
+ }
139
+ other => RpcMethod::Unknown(other.to_string()),
140
+ }
141
+ }
142
+ }
143
+
144
+ /// Tool error reason (`server.py:43,69-72`, `tools.py:211`). `reason == error_code`
145
+ /// in the wire envelope; this also maps to the JSON-RPC code on the non-tool path.
146
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
147
+ #[serde(rename_all = "snake_case")]
148
+ pub enum ToolErrorReason {
149
+ /// Unknown tool name in `dispatch` (`server.py:43`).
150
+ UnknownTool,
151
+ /// `TypeError/ValueError/KeyError/AttributeError` caught (`server.py:69-70`).
152
+ InvalidToolArguments,
153
+ /// Any other exception caught (`server.py:71-72`).
154
+ InternalRuntimeError,
155
+ /// Cross-team peer addressed without `scope="workspace"` (`tools.py:211`).
156
+ PeerNotInScope,
157
+ }
158
+
159
+ /// Send scope (`tools.py:165-173`). `Workspace` is the only cross-team opt-in;
160
+ /// absent/`team` resolves to the spawn-time owner team. The `scope` field on
161
+ /// `mcp.scope_resolved` is one of these.
162
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
163
+ #[serde(rename_all = "snake_case")]
164
+ pub enum Scope {
165
+ Team,
166
+ Workspace,
167
+ }
168
+
169
+ // ═══════════════════════════════════════════════════════════════════════════
170
+ // WIRE ENVELOPES (byte-stable) — request/response + tool result/error.
171
+ // ═══════════════════════════════════════════════════════════════════════════
172
+
173
+ /// A JSON-RPC request id: int, string, or null/absent (`request.get("id")`).
174
+ /// Serialized verbatim into the response `id` field.
175
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
176
+ #[serde(untagged)]
177
+ pub enum RpcId {
178
+ Int(i64),
179
+ Str(String),
180
+ Number(serde_json::Number),
181
+ /// `null` / absent — echoed back as `null`.
182
+ Null,
183
+ }
184
+
185
+ /// A JSON-RPC 2.0 response frame (`server.py:52-91`). Exactly one of `result` /
186
+ /// `error` is set. `handle_mcp` returns `Option<RpcResponse>`; `None` ⇒
187
+ /// notifications path (no frame written).
188
+ #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
189
+ pub struct RpcResponse {
190
+ /// Always `"2.0"`.
191
+ pub jsonrpc: String,
192
+ pub id: RpcId,
193
+ #[serde(skip_serializing_if = "Option::is_none")]
194
+ pub result: Option<Value>,
195
+ #[serde(skip_serializing_if = "Option::is_none")]
196
+ pub error: Option<RpcError>,
197
+ }
198
+
199
+ /// JSON-RPC error object (`server.py:90,142`). `-32601` unknown method, `-32000`
200
+ /// stdin-loop catch-all, `-32700` parse error.
201
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
202
+ pub struct RpcError {
203
+ pub code: i64,
204
+ pub message: String,
205
+ }
206
+
207
+ /// The `tools/call` result wrapper (`server.py:74-86`): `{content:[{type:"text",
208
+ /// text:<json>}], isError:<bool>}`. `text` is the JSON-encoded [`ToolResult`]; the
209
+ /// `is_error` flag mirrors `result.get("ok") is False`.
210
+ #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
211
+ pub struct ToolCallResult {
212
+ pub content: Vec<ToolCallContent>,
213
+ #[serde(rename = "isError")]
214
+ pub is_error: bool,
215
+ }
216
+
217
+ /// One `content[]` block — always `{type:"text", text:<json>}` here.
218
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
219
+ pub struct ToolCallContent {
220
+ #[serde(rename = "type")]
221
+ pub kind: String,
222
+ pub text: String,
223
+ }
224
+
225
+ /// A successful tool result body — the compacted delegate result
226
+ /// (`normalize._compact_tool_result`, `normalize.py:6-64`). The whitelist-key
227
+ /// compaction (ok/error key sets + `fanout_*` extras + `acknowledged_count`) lives
228
+ /// in [`compact_tool_result`]; this struct carries the post-compaction object.
229
+ /// `ok` defaults to `true` (an empty compaction yields `{"ok": true}`).
230
+ ///
231
+ /// [`compact_tool_result`]: super::compact_tool_result
232
+ #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
233
+ pub struct ToolOk {
234
+ /// The compacted, byte-stable result object (whitelist keys only).
235
+ #[serde(flatten)]
236
+ pub fields: serde_json::Map<String, Value>,
237
+ }
238
+
239
+ /// The tool error envelope (`server.py:98-106`). **Redundant keys are load-bearing**:
240
+ /// `reason == error_code` and `message == error` are byte-stable downstream
241
+ /// contracts and MUST be serialized verbatim (not deduped). `ok` is always `false`.
242
+ #[derive(Debug, Clone, PartialEq, Eq)]
243
+ pub struct ToolError {
244
+ /// The reason; serialized into BOTH `reason` and `error_code`.
245
+ pub reason: ToolErrorReason,
246
+ /// Exception class name (`exc_type`): `"UnknownTool"`, `"ValueError"`, …
247
+ /// Public-message scrub (`_public_exception_message`, ≤200 chars, newlines → space).
248
+ pub exc_type: String,
249
+ /// The public message; serialized into BOTH `message` and `error`.
250
+ pub message: String,
251
+ /// Extra envelope keys (e.g. the `_refuse_cross_team_peer` `status:"refused"` +
252
+ /// `hint`, `tools.py:208-213`) preserved alongside the canonical keys.
253
+ pub extra: serde_json::Map<String, Value>,
254
+ }
255
+
256
+ impl ToolError {
257
+ /// Build the `{ok:false, reason, error_code, exc_type, message, error, **extra}`
258
+ /// JSON object with the redundant keys filled byte-for-byte (`server.py:98-106`).
259
+ pub fn to_envelope(&self) -> Value {
260
+ let reason = tool_error_reason_wire(self.reason);
261
+ let mut obj = serde_json::Map::new();
262
+ obj.insert("ok".to_string(), Value::Bool(false));
263
+ obj.insert("reason".to_string(), Value::String(reason.to_string()));
264
+ obj.insert("error_code".to_string(), Value::String(reason.to_string()));
265
+ obj.insert("exc_type".to_string(), Value::String(self.exc_type.clone()));
266
+ obj.insert("message".to_string(), Value::String(self.message.clone()));
267
+ obj.insert("error".to_string(), Value::String(self.message.clone()));
268
+ for (k, v) in &self.extra {
269
+ obj.insert(k.clone(), v.clone());
270
+ }
271
+ Value::Object(obj)
272
+ }
273
+
274
+ /// `_tool_error_result(reason, message, exc_type)` (`server.py:98-106`) for the
275
+ /// `unknown_tool` / `peer_not_in_scope` non-exception paths.
276
+ pub fn new(reason: ToolErrorReason, message: impl Into<String>, exc_type: impl Into<String>) -> Self {
277
+ Self {
278
+ reason,
279
+ exc_type: exc_type.into(),
280
+ message: message.into(),
281
+ extra: serde_json::Map::new(),
282
+ }
283
+ }
284
+
285
+ /// `_public_exception_message(exc)` (`server.py:109-111`): strip newlines, trim,
286
+ /// truncate to 200 chars; empty → the exception type name.
287
+ pub fn public_exception_message(raw: &str, exc_type: &str) -> String {
288
+ let cleaned = raw.replace(['\n', '\r'], " ");
289
+ let trimmed = cleaned.trim();
290
+ let base = if trimmed.is_empty() { exc_type } else { trimmed };
291
+ base.chars().take(200).collect()
292
+ }
293
+ }
294
+
295
+ /// A tool handler outcome (`dispatch` return). Maps to `result.get("ok") is False`:
296
+ /// `Ok` ⇒ `isError:false`, `Err(ToolError)` ⇒ `isError:true`. This is the
297
+ /// contract-callable shape — handlers below return it (or a richer typed wrapper).
298
+ pub type ToolResult = Result<ToolOk, ToolError>;
299
+
300
+ /// `send_message` outcome (`tools.py:176-183`). A worker recipient with a
301
+ /// message_id → async `accepted` carrying the byte-stable poll hint; leader / `*` /
302
+ /// broadcast → the compacted delegate result.
303
+ #[derive(Debug, Clone, PartialEq)]
304
+ pub enum SendOutcome {
305
+ /// `{status:"accepted", delivery_pending:true, poll_via:"team-agent inbox <id>",
306
+ /// message_id:<id>}` — worker recipient, `tools.py:177-182`.
307
+ WorkerAccepted {
308
+ message_id: String,
309
+ /// Byte-stable `"team-agent inbox <message_id>"`.
310
+ poll_via: String,
311
+ },
312
+ /// Compacted delegate result (leader / `*` / broadcast / fanout).
313
+ Direct(ToolOk),
314
+ }
315
+
316
+ impl SendOutcome {
317
+ /// Render the outcome into its wire JSON object (`tools.py:177-183`). Folds into
318
+ /// the [`ToolResult`] `Ok` body.
319
+ pub fn to_value(&self) -> Value {
320
+ match self {
321
+ SendOutcome::WorkerAccepted { message_id, poll_via } => {
322
+ let mut obj = serde_json::Map::new();
323
+ obj.insert("status".to_string(), Value::String("accepted".to_string()));
324
+ obj.insert("delivery_pending".to_string(), Value::Bool(true));
325
+ obj.insert("poll_via".to_string(), Value::String(poll_via.clone()));
326
+ obj.insert("message_id".to_string(), Value::String(message_id.clone()));
327
+ Value::Object(obj)
328
+ }
329
+ SendOutcome::Direct(ok) => Value::Object(ok.fields.clone()),
330
+ }
331
+ }
332
+ }
333
+
334
+ // ═══════════════════════════════════════════════════════════════════════════
335
+ // NORMALIZED RESULT ENVELOPE (normalize.py:67-258) — typed carriers of the
336
+ // asserted values. Contracts call the normalize fns and assert these enums/structs.
337
+ // ═══════════════════════════════════════════════════════════════════════════
338
+
339
+ /// A normalized result envelope (`_normalize_report_envelope`, `normalize.py:67-80`).
340
+ /// `schema_version` is fixed `"result_envelope_v1"`; `task_id`/`agent_id` fall back
341
+ /// to `"manual"`/`"unknown"`. `status` is the regularized [`ResultStatus`] (step 2).
342
+ #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
343
+ pub struct NormalizedReportEnvelope {
344
+ pub schema_version: String,
345
+ pub task_id: TaskId,
346
+ pub agent_id: AgentId,
347
+ pub status: ResultStatus,
348
+ pub summary: String,
349
+ pub changes: Vec<NormalizedChange>,
350
+ pub tests: Vec<NormalizedTest>,
351
+ pub risks: Vec<NormalizedRisk>,
352
+ pub artifacts: Vec<NormalizedArtifact>,
353
+ pub next_actions: Vec<NormalizedNextAction>,
354
+ }
355
+
356
+ /// `changes[]` (`normalize.py:126-142`): path + regularized [`ChangeKind`] +
357
+ /// description (falls back to the envelope summary).
358
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
359
+ pub struct NormalizedChange {
360
+ pub path: String,
361
+ pub kind: ChangeKind,
362
+ pub description: String,
363
+ }
364
+
365
+ /// `tests[]` (`normalize.py:180-196`): command + regularized [`TestStatus`] +
366
+ /// optional detail.
367
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
368
+ pub struct NormalizedTest {
369
+ pub command: String,
370
+ pub status: TestStatus,
371
+ #[serde(skip_serializing_if = "Option::is_none")]
372
+ pub detail: Option<String>,
373
+ }
374
+
375
+ /// `risks[]` (`normalize.py:215-230`): regularized [`RiskSeverity`] (out-of-set →
376
+ /// `Low`) + description.
377
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
378
+ pub struct NormalizedRisk {
379
+ pub severity: RiskSeverity,
380
+ pub description: String,
381
+ }
382
+
383
+ /// `artifacts[]` (`normalize.py:233-245`): path + description (defaults to path).
384
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
385
+ pub struct NormalizedArtifact {
386
+ pub path: String,
387
+ pub description: String,
388
+ }
389
+
390
+ /// `next_actions[]` (`normalize.py:248-257`): description only.
391
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
392
+ pub struct NormalizedNextAction {
393
+ pub description: String,
394
+ }
395
+
396
+ /// `get_visible_peers` result (`tools.py:226-247`): the C16 scope-filtered peer list.
397
+ /// Other teams and dead/stopped agents are filtered server-side and never named.
398
+ #[derive(Debug, Clone, PartialEq, Eq)]
399
+ pub struct VisiblePeers {
400
+ /// Sorted live peer ids within the sender's spawn-time owner-team scope.
401
+ pub peers: Vec<AgentId>,
402
+ /// The resolving team scope (`None` when no owner team env is set).
403
+ pub sender_team_id: Option<TeamKey>,
404
+ /// Always [`Scope::Team`] for this query.
405
+ pub scope: Scope,
406
+ }
407
+
408
+ /// Summary of one stdio server run (`main`'s loop accounting) — frames in/out, the
409
+ /// notification skips, and whether the loop exited on EOF cleanly. Rich return so a
410
+ /// harness can assert the session shape without scraping stdout.
411
+ #[derive(Debug, Clone, PartialEq, Eq, Default)]
412
+ pub struct ServerRunReport {
413
+ pub requests_read: u64,
414
+ pub responses_written: u64,
415
+ /// `notifications/*` lines that produced no frame.
416
+ pub notifications_skipped: u64,
417
+ /// Lines that surfaced an error frame (parse / `-32000` / `-32601`).
418
+ pub error_frames: u64,
419
+ /// Clean EOF on stdin (`for line in sys.stdin` exhausted).
420
+ pub clean_eof: bool,
421
+ }