@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,333 @@
1
+ use super::*;
2
+
3
+ // =========================================================================
4
+ // WAVE-2 LANE C — diagnose/status byte-parity DIVERGENCES + target-scan wiring.
5
+ // The status/diagnose handlers are IMPLEMENTED (status) or STUBBED (approvals/inbox/doctor/
6
+ // comms_selftest/orphan_gate/cleanup_orphans/fix_schema) — these REDs lock the EXACT golden JSON
7
+ // shapes (keys/values/insertion-order) each one DIVERGES from. Golden bytes captured via
8
+ // PYTHONPATH=.../src python3 /tmp/lanec_probe*.py on a fresh workspace.
9
+ // =========================================================================
10
+
11
+ /// Seed `.team/runtime/state.json` with `state` so `status_port::status` reads a real fixture.
12
+ fn seed_status_state(state: serde_json::Value) -> std::path::PathBuf {
13
+ let ws = tmp_workspace();
14
+ std::fs::write(
15
+ ws.join(".team").join("runtime").join("state.json"),
16
+ serde_json::to_vec_pretty(&state).unwrap(),
17
+ )
18
+ .unwrap();
19
+ ws
20
+ }
21
+
22
+ // ── status #1: `team` = state["leader"]["id"] (default "leader"), NOT state["team"] ──────────────
23
+ // GOLDEN queries.py:66 `state.get("leader", {}).get("id", "leader")`. RUST mod.rs:94 reads
24
+ // `state.get("team")`. Seed BOTH distinct -> golden binds leader.id, Rust binds the team key. RED.
25
+ #[test]
26
+ fn status_team_is_leader_id_not_team_key() {
27
+ let ws = seed_status_state(json!({"team": "TEAMKEY", "leader": {"id": "LEADERID"}}));
28
+ let v = status_port::status(&ws, /*compact=*/ false, /*detail=*/ true).expect("status");
29
+ assert_eq!(
30
+ v["team"],
31
+ json!("LEADERID"),
32
+ "golden status.team = state['leader']['id'] (queries.py:66), NOT state['team']; got {:?}",
33
+ v["team"]
34
+ );
35
+ let _ = std::fs::remove_dir_all(&ws);
36
+ }
37
+
38
+ // ── status #2: messages = store.message_counts() ({} when empty), results = store.result_counts()
39
+ // ({total,uncollected,collected,invalid,by_status}) — NOT the Rust {"count": N} placeholders. ──────
40
+ // GOLDEN queries.py:73,75. RUST mod.rs:101,103 emit `{"count": N}`. RED.
41
+ #[test]
42
+ fn status_counts_are_store_count_maps_not_count_int() {
43
+ let ws = tmp_workspace(); // empty store
44
+ let v = status_port::status(&ws, false, true).expect("status");
45
+ assert_eq!(
46
+ v["messages"],
47
+ json!({}),
48
+ "golden empty store.message_counts() == {{}} (queries.py:73), NOT {{count:0}}; got {:?}",
49
+ v["messages"]
50
+ );
51
+ assert_eq!(
52
+ v["results"],
53
+ json!({"total": 0, "uncollected": 0, "collected": 0, "invalid": 0, "by_status": {}}),
54
+ "golden store.result_counts() full shape (queries.py:75), NOT {{count:0}}; got {:?}",
55
+ v["results"]
56
+ );
57
+ let _ = std::fs::remove_dir_all(&ws);
58
+ }
59
+
60
+ // ── status #3: coordinator = coordinator_health(ws) FULL 8-key shape in golden order ─────────────
61
+ // GOLDEN coordinator_health: {ok,status,pid,metadata,metadata_ok,schema_ok,schema_error,schema}.
62
+ // RUST mod.rs:105-112 emits a 6-key subset {status,ok,pid,metadata_ok,schema_ok,schema_version}
63
+ // (no metadata/schema_error; flat schema_version instead of nested schema). RED on key-order. ──────
64
+ #[test]
65
+ fn status_coordinator_is_full_health_eight_key_shape() {
66
+ let ws = tmp_workspace();
67
+ let v = status_port::status(&ws, false, true).expect("status");
68
+ let coord = v["coordinator"].as_object().expect("coordinator dict");
69
+ let order: Vec<&str> = coord.keys().map(String::as_str).collect();
70
+ assert_eq!(
71
+ order,
72
+ vec!["ok", "status", "pid", "metadata", "metadata_ok", "schema_ok", "schema_error", "schema"],
73
+ "golden coordinator_health 8-key insertion order; Rust emits a 6-key subset. got {order:?}"
74
+ );
75
+ assert!(
76
+ coord.get("schema_version").is_none(),
77
+ "golden coordinator has NO flat `schema_version` (it nests schema:{{message_store_schema_version}}); \
78
+ Rust emits the flat key. got {coord:?}"
79
+ );
80
+ let _ = std::fs::remove_dir_all(&ws);
81
+ }
82
+
83
+ // ── status #4: last_events = EventLog.tail(10) ([] when no events), NOT the literal placeholder ──
84
+ // GOLDEN queries.py:78 `EventLog(workspace).tail(10)`. RUST mod.rs:113 (non-compact) emits the
85
+ // hardcoded placeholder `[{"event":"status.full"}]`. On a fresh log golden == []. RED. ────────────
86
+ #[test]
87
+ fn status_last_events_is_event_tail_not_status_full_placeholder() {
88
+ let ws = tmp_workspace(); // no events.jsonl
89
+ let v = status_port::status(&ws, false, true).expect("status");
90
+ assert_ne!(
91
+ v["last_events"],
92
+ json!([{"event": "status.full"}]),
93
+ "golden last_events = EventLog.tail(10), NOT the literal [{{event:status.full}}] placeholder"
94
+ );
95
+ assert_eq!(
96
+ v["last_events"],
97
+ json!([]),
98
+ "golden last_events on a fresh event log is [] (tail of empty); got {:?}",
99
+ v["last_events"]
100
+ );
101
+ let _ = std::fs::remove_dir_all(&ws);
102
+ }
103
+
104
+ // ── status #5: the full (non-compact) status dict has NO `detail` key ────────────────────────────
105
+ // GOLDEN queries.py:65-79 builds exactly 13 keys; there is no `detail`. RUST mod.rs:115-119 injects
106
+ // `detail:true` whenever `!compact || detail`. The full --detail call MUST NOT carry detail. RED. ──
107
+ #[test]
108
+ fn status_noncompact_has_no_detail_key() {
109
+ let ws = tmp_workspace();
110
+ let v = status_port::status(&ws, /*compact=*/ false, /*detail=*/ true).expect("status");
111
+ assert!(
112
+ v.as_object().unwrap().get("detail").is_none(),
113
+ "golden status dict has NO `detail` key (queries.py:65-79); Rust injects detail:true. got {v:?}"
114
+ );
115
+ let _ = std::fs::remove_dir_all(&ws);
116
+ }
117
+
118
+ // ── status #6: each agent entry is enriched with an `interacted` marker (C3, queries.py:53-64) ────
119
+ // GOLDEN: valid ISO first_send_at passes through; any other shape (invalid str / missing) -> the
120
+ // literal "never" (_interacted_marker, queries.py:15-30). RUST mod.rs:81-84 passes agents through
121
+ // RAW with no enrichment -> no `interacted` key. RED. ────────────────────────────────────────────
122
+ #[test]
123
+ fn status_agents_enriched_with_interacted_marker() {
124
+ let ws = seed_status_state(json!({
125
+ "leader": {"id": "leader"},
126
+ "agents": {
127
+ "alpha": {"provider": "codex", "first_send_at": "2026-05-27T10:00:00+00:00"},
128
+ "beta": {"provider": "claude", "first_send_at": "not-a-date"},
129
+ "gamma": {"provider": "claude"},
130
+ }
131
+ }));
132
+ let v = status_port::status(&ws, false, true).expect("status");
133
+ let agents = &v["agents"];
134
+ assert_eq!(
135
+ agents["alpha"]["interacted"],
136
+ json!("2026-05-27T10:00:00+00:00"),
137
+ "valid ISO first_send_at must pass through as the interacted marker (queries.py:24-29)"
138
+ );
139
+ assert_eq!(
140
+ agents["beta"]["interacted"],
141
+ json!("never"),
142
+ "an unparseable first_send_at must render as the literal 'never' (queries.py:27-28)"
143
+ );
144
+ assert_eq!(
145
+ agents["gamma"]["interacted"],
146
+ json!("never"),
147
+ "a missing first_send_at must render as 'never' (queries.py:30)"
148
+ );
149
+ let _ = std::fs::remove_dir_all(&ws);
150
+ }
151
+
152
+ // ── status #7 (TARGET-SCAN WIRING, in-process): tmux_session_present uses a LIVE tmux probe ───────
153
+ // GOLDEN queries.py:52 `_tmux_session_exists(session_name)` (real `tmux has-session`). RUST mod.rs:96
154
+ // shortcuts to `session_name.is_some()`. Seed a present-but-nonexistent session -> golden False,
155
+ // Rust True. This is the status-level pane-discovery wiring the dangling list_targets feeds. RED. ──
156
+ #[test]
157
+ fn status_tmux_session_present_uses_live_tmux_probe_not_is_some() {
158
+ let absent = format!("ta-lanec-absent-{}", std::process::id());
159
+ let ws = seed_status_state(json!({"leader": {"id": "leader"}, "session_name": absent}));
160
+ let v = status_port::status(&ws, false, true).expect("status");
161
+ assert_eq!(
162
+ v["tmux_session_present"],
163
+ json!(false),
164
+ "golden tmux_session_present = _tmux_session_exists(name) (a live probe; queries.py:52); a \
165
+ present-but-nonexistent session name must be False, not is_some()==true. got {:?}",
166
+ v["tmux_session_present"]
167
+ );
168
+ let _ = std::fs::remove_dir_all(&ws);
169
+ }
170
+
171
+ // ── approvals: golden 5-key {ok,waiting,waiting_count,approvals,scan} (status/approvals.py:30-36) ──
172
+ // RUST mod.rs:131-133 stub {ok,agent,approvals}. RED. ───────────────────────────────────────────
173
+ #[test]
174
+ fn approvals_golden_shape_has_waiting_count_and_scan_not_agent() {
175
+ let ws = tmp_workspace();
176
+ let v = status_port::approvals(&ws, None, true).expect("approvals");
177
+ let obj = v.as_object().expect("approvals dict");
178
+ let order: Vec<&str> = obj.keys().map(String::as_str).collect();
179
+ assert_eq!(
180
+ order,
181
+ vec!["ok", "waiting", "waiting_count", "approvals", "scan"],
182
+ "golden approvals 5-key order (approvals.py:30-36); Rust stub emits {{ok,agent,approvals}}. got {order:?}"
183
+ );
184
+ assert!(!obj.contains_key("agent"), "golden approvals has NO `agent` key");
185
+ assert_eq!(
186
+ v["scan"],
187
+ json!({"mode": "tail", "lines": 120, "raw_output": false}),
188
+ "golden scan == {{mode:tail,lines:120,raw_output:false}} (APPROVAL_SCAN_LINES=120); got {:?}",
189
+ v["scan"]
190
+ );
191
+ let _ = std::fs::remove_dir_all(&ws);
192
+ }
193
+
194
+ // ── inbox: golden {ok,agent_id,messages,since} (status/inbox.py:35-38) — key is `agent_id`, carries
195
+ // `since` (not `agent`/`limit`). RUST mod.rs:136-144 stub {ok,agent,limit,messages}. RED. ──────────
196
+ #[test]
197
+ fn inbox_golden_shape_is_agent_id_and_since_not_agent_limit() {
198
+ let ws = tmp_workspace();
199
+ let v = status_port::inbox(&ws, "alpha", 20, None, true).expect("inbox");
200
+ let obj = v.as_object().expect("inbox dict");
201
+ let order: Vec<&str> = obj.keys().map(String::as_str).collect();
202
+ assert_eq!(
203
+ order,
204
+ vec!["ok", "agent_id", "messages", "since"],
205
+ "golden inbox 4-key order {{ok,agent_id,messages,since}} (inbox.py:38); Rust stub uses agent/limit. got {order:?}"
206
+ );
207
+ assert_eq!(v["agent_id"], json!("alpha"), "golden key is `agent_id` (not `agent`)");
208
+ assert!(obj.contains_key("since"), "golden inbox carries `since` (echoed, null here)");
209
+ assert!(!obj.contains_key("agent"), "golden inbox has NO bare `agent` key");
210
+ assert!(!obj.contains_key("limit"), "golden inbox has NO `limit` key in the result dict");
211
+ let _ = std::fs::remove_dir_all(&ws);
212
+ }
213
+
214
+ // ── comms_selftest: golden {ok,status,run_id,scope,boundary,checks} (diagnose/comms.py:40-47) ─────
215
+ // RUST mod.rs:525-527 stub {ok,team,gate,provider_sdk_calls:int}. RED. Locks COMMS_BOUNDARY_TEXT +
216
+ // the deterministic check sub-shapes (run_id is a random uuid; not value-locked). ────────────────
217
+ #[test]
218
+ fn comms_selftest_golden_boundary_scope_and_check_shapes() {
219
+ let boundary = "validates live pane binding consistency. Does NOT perform live runtime message \
220
+ round-trip. comms contract suite deferred to 0.2.9 (test files not shipped). \
221
+ (zero token, zero pollution)";
222
+ let ws = tmp_workspace();
223
+ let v = diagnose_port::comms_selftest(&ws, None, None).expect("comms_selftest");
224
+ let obj = v.as_object().expect("comms dict");
225
+ assert_eq!(v["boundary"], json!(boundary), "golden COMMS_BOUNDARY_TEXT prefix (comms.py:11-14)");
226
+ assert_eq!(v["scope"], json!("binding_consistency"), "golden scope");
227
+ assert_eq!(v["status"], json!("pass"), "empty-state selftest passes (all checks pass/deferred)");
228
+ assert!(obj.contains_key("run_id"), "golden carries a run_id (uuid hex[:12])");
229
+ assert!(!obj.contains_key("team"), "golden has NO `team` key");
230
+ assert!(!obj.contains_key("gate"), "golden has NO `gate` key");
231
+ assert_eq!(
232
+ v["checks"]["contract_suite"],
233
+ json!({
234
+ "status": "deferred",
235
+ "deferred_to": "0.2.9",
236
+ "reason": "contract test files not shipped with package",
237
+ "message": "comms contract verification deferred to 0.2.9; contract test files not shipped with package",
238
+ }),
239
+ "golden contract_suite check (comms.py:132-139)"
240
+ );
241
+ assert_eq!(
242
+ v["checks"]["provider_sdk_calls"]["calls"],
243
+ json!({"anthropic": 0, "openai": 0, "httpx": 0}),
244
+ "golden provider_sdk_calls.calls (comms.py:142-151); Rust stub is a bare int 0"
245
+ );
246
+ let _ = std::fs::remove_dir_all(&ws);
247
+ }
248
+
249
+ // ── orphan_gate(fix=true,confirm=false): golden REFUSED envelope (orphan_cleanup.py:304-311) ──────
250
+ // {ok:false,gate:"orphans",status:"refused",reason:"fix_requires_confirm",action:...}. RUST mod.rs:
251
+ // 530-531 stub {ok:true,fix,confirm,orphans:[]}. Fully deterministic (no subprocess). RED. ─────────
252
+ #[test]
253
+ fn orphan_gate_fix_without_confirm_is_refused_envelope() {
254
+ let v = diagnose_port::orphan_gate(/*fix=*/ true, /*confirm=*/ false).expect("orphan_gate");
255
+ assert_eq!(
256
+ v,
257
+ json!({
258
+ "ok": false,
259
+ "gate": "orphans",
260
+ "status": "refused",
261
+ "reason": "fix_requires_confirm",
262
+ "action": "re-run with --gate orphans --fix --confirm",
263
+ }),
264
+ "golden orphan_gate fix-without-confirm refused envelope (orphan_cleanup.py:304-311); got {v:?}"
265
+ );
266
+ let order: Vec<&str> = v.as_object().unwrap().keys().map(String::as_str).collect();
267
+ assert_eq!(order, vec!["ok", "gate", "status", "reason", "action"], "golden refused key order");
268
+ }
269
+
270
+ // ── cleanup_orphans(confirm=false): golden DRY-RUN envelope (orphan_cleanup.py cleanup_…) ─────────
271
+ // {ok,scanned,orphans,dry_run:true,scanned_at,action_required}. RUST mod.rs:534-535 stub
272
+ // {ok,confirm,cleaned}. scanned/scanned_at are machine/clock-derived; lock the deterministic ones. RED.
273
+ #[test]
274
+ fn cleanup_orphans_dryrun_golden_envelope() {
275
+ let v = diagnose_port::cleanup_orphans(/*confirm=*/ false).expect("cleanup_orphans");
276
+ let obj = v.as_object().expect("cleanup dict");
277
+ assert_eq!(v["dry_run"], json!(true), "no --confirm => dry_run:true (cleanup_orphan_coordinators)");
278
+ assert_eq!(v["orphans"], json!([]), "golden lists orphans (empty when none)");
279
+ assert_eq!(
280
+ v["action_required"],
281
+ json!("re-run with --confirm to send SIGTERM"),
282
+ "golden dry-run action_required text"
283
+ );
284
+ assert!(obj.contains_key("scanned_at"), "golden carries scanned_at timestamp");
285
+ assert!(obj.contains_key("scanned"), "golden carries scanned count");
286
+ assert!(!obj.contains_key("confirm"), "golden has NO `confirm` key");
287
+ assert!(!obj.contains_key("cleaned"), "golden has NO `cleaned` key (uses `orphans`)");
288
+ }
289
+
290
+ // ── fix_schema: golden fix_schema_layout diagnosis envelope (schema_migration.py:258) ─────────────
291
+ // {ok,status,db_path,schema_version,user_version,layout_diffs,recommended_action,would_backup_path,
292
+ // fixed,rebuilds}. RUST mod.rs:538-540 stub {ok,fixed:false}. db_path/would_backup_path are
293
+ // path/clock-derived; lock the deterministic fields. SCHEMA_VERSION==3. RED. ─────────────────────
294
+ #[test]
295
+ fn fix_schema_golden_layout_diagnosis_envelope() {
296
+ let ws = tmp_workspace();
297
+ let v = diagnose_port::fix_schema(&ws).expect("fix_schema");
298
+ let obj = v.as_object().expect("fix_schema dict");
299
+ assert_eq!(v["status"], json!("missing"), "missing db: status missing");
300
+ assert_eq!(v["schema_version"], json!(3), "golden schema_version == SCHEMA_VERSION (3)");
301
+ assert_eq!(v["user_version"], json!(0), "missing db user_version == 0");
302
+ assert_eq!(v["layout_diffs"], json!([]), "missing db => empty layout_diffs list");
303
+ assert_eq!(v["recommended_action"], json!("none"), "no drift => recommended_action 'none'");
304
+ assert_eq!(v["fixed"], json!(false), "missing db is diagnostic-only and does not create a db");
305
+ assert_eq!(v["rebuilds"], json!([]), "no rebuilds on a fresh db");
306
+ assert!(obj.contains_key("db_path"), "golden carries db_path");
307
+ assert!(obj.contains_key("would_backup_path"), "golden carries would_backup_path");
308
+ let _ = std::fs::remove_dir_all(&ws);
309
+ }
310
+
311
+ // ── doctor: golden checks dict (diagnose/health.py:179-241) — tmux/workspace/workspace_is_git_repo/
312
+ // providers/mcp/coordinator/ok. RUST mod.rs:520-522 stub {ok,spec,blockers}. Lock the golden
313
+ // top-level keys (values are machine-derived) + absence of the stub's spec/blockers. RED. ─────────
314
+ #[test]
315
+ fn doctor_golden_checks_shape_not_spec_blockers_stub() {
316
+ let ws = tmp_workspace();
317
+ let v = diagnose_port::doctor(&ws, None).expect("doctor");
318
+ let obj = v.as_object().expect("doctor dict");
319
+ let tmux = v["tmux"].as_object().expect("golden doctor.tmux is a dict {installed,path}");
320
+ assert!(tmux.contains_key("installed") && tmux.contains_key("path"), "tmux check shape");
321
+ assert!(v["workspace"].is_string(), "golden doctor.workspace is a string path");
322
+ assert!(v["workspace_is_git_repo"].is_boolean(), "golden doctor.workspace_is_git_repo bool");
323
+ assert!(v["providers"].is_object(), "golden doctor.providers is a dict");
324
+ assert_eq!(
325
+ v["mcp"]["local_module"],
326
+ json!(true),
327
+ "golden doctor.mcp.local_module == true (health.py:197-200)"
328
+ );
329
+ assert!(v["coordinator"].is_object(), "golden doctor.coordinator is the coordinator_health dict");
330
+ assert!(!obj.contains_key("spec"), "golden doctor has NO `spec` key (Rust stub adds it)");
331
+ assert!(!obj.contains_key("blockers"), "golden doctor has NO `blockers` key (Rust stub adds it)");
332
+ let _ = std::fs::remove_dir_all(&ws);
333
+ }