@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,206 @@
1
+ version: 1
2
+ team:
3
+ name: "teamspec-full-example"
4
+ mode: "supervisor_worker"
5
+ objective: "Build, research, review, and document a code change with Codex CLI workers."
6
+ workspace: "."
7
+ leader:
8
+ id: "leader"
9
+ role: "leader"
10
+ provider: "codex"
11
+ model: null
12
+ tools:
13
+ - "fs_read"
14
+ - "fs_list"
15
+ - "mcp_team"
16
+ - "provider_builtin"
17
+ context_policy:
18
+ keep_user_thread: true
19
+ receive_worker_outputs: "structured_only"
20
+ max_worker_result_tokens: 4000
21
+ agents:
22
+ - id: "codex_implementer"
23
+ role: "implementation_engineer"
24
+ provider: "codex"
25
+ model: null
26
+ working_directory: "."
27
+ system_prompt:
28
+ inline: |
29
+ You are the implementation worker. Make focused code changes, run relevant tests,
30
+ and report a result_envelope_v1 with changed files, tests, risks, artifacts, and next actions.
31
+ file: null
32
+ tools:
33
+ - "fs_read"
34
+ - "fs_write"
35
+ - "fs_list"
36
+ - "execute_bash"
37
+ - "git_diff"
38
+ - "mcp_team"
39
+ - "provider_builtin"
40
+ permission_mode: "restricted"
41
+ preferred_for:
42
+ - "implementation"
43
+ - "bug_fix"
44
+ - "test"
45
+ avoid_for:
46
+ - "final_risk_signoff"
47
+ output_contract:
48
+ format: "result_envelope_v1"
49
+ required_fields:
50
+ - "task_id"
51
+ - "status"
52
+ - "summary"
53
+ - "artifacts"
54
+ - id: "codex_researcher"
55
+ role: "researcher"
56
+ provider: "codex"
57
+ model: null
58
+ working_directory: "."
59
+ system_prompt:
60
+ inline: |
61
+ You are the research worker. Prefer read-only analysis and summarize findings
62
+ as result_envelope_v1. Do not edit files.
63
+ file: null
64
+ tools:
65
+ - "fs_read"
66
+ - "fs_list"
67
+ - "network"
68
+ - "mcp_team"
69
+ - "provider_builtin"
70
+ permission_mode: "restricted"
71
+ preferred_for:
72
+ - "research"
73
+ - "architecture"
74
+ - "docs"
75
+ avoid_for:
76
+ - "implementation"
77
+ output_contract:
78
+ format: "result_envelope_v1"
79
+ required_fields:
80
+ - "task_id"
81
+ - "status"
82
+ - "summary"
83
+ - "artifacts"
84
+ - id: "codex_reviewer"
85
+ role: "code_reviewer"
86
+ provider: "codex"
87
+ model: null
88
+ working_directory: "."
89
+ system_prompt:
90
+ inline: |
91
+ You are the reviewer. Find correctness, regression, security, and missing-test risks.
92
+ Stay read-only unless the leader explicitly changes your permissions.
93
+ file: null
94
+ tools:
95
+ - "fs_read"
96
+ - "fs_list"
97
+ - "git_diff"
98
+ - "mcp_team"
99
+ - "provider_builtin"
100
+ permission_mode: "restricted"
101
+ preferred_for:
102
+ - "review"
103
+ - "risk_check"
104
+ avoid_for:
105
+ - "implementation"
106
+ output_contract:
107
+ format: "result_envelope_v1"
108
+ required_fields:
109
+ - "task_id"
110
+ - "status"
111
+ - "summary"
112
+ - "artifacts"
113
+ routing:
114
+ default_assignee: "leader"
115
+ rules:
116
+ - id: "implementation-to-codex"
117
+ when: "task.type in [\"implementation\", \"bug_fix\", \"test\"]"
118
+ assign_to: "codex_implementer"
119
+ priority: 100
120
+ - id: "research-to-codex"
121
+ when: "task.type in [\"research\", \"architecture\", \"docs\"]"
122
+ assign_to: "codex_researcher"
123
+ priority: 90
124
+ - id: "review-to-codex"
125
+ when: "task.type in [\"review\", \"risk_check\"]"
126
+ assign_to: "codex_reviewer"
127
+ priority: 90
128
+ communication:
129
+ protocol: "mcp_inbox"
130
+ topology: "leader_centered"
131
+ worker_to_worker: false
132
+ ack_timeout_sec: 60
133
+ result_format: "result_envelope_v1"
134
+ message_store:
135
+ sqlite: ".team/runtime/team.db"
136
+ mirror_files: ".team/messages"
137
+ runtime:
138
+ backend: "tmux"
139
+ display_backend: "none"
140
+ session_name: "teamspec-full-example"
141
+ auto_launch: true
142
+ require_user_approval_before_launch: true
143
+ dangerous_auto_approve: false
144
+ max_active_agents: 3
145
+ startup_order:
146
+ - "codex_implementer"
147
+ - "codex_researcher"
148
+ - "codex_reviewer"
149
+ context:
150
+ state_file: "team_state.md"
151
+ artifact_dir: ".team/artifacts"
152
+ log_dir: ".team/logs"
153
+ summarization:
154
+ worker_full_logs: "retain_outside_leader_context"
155
+ state_update: "after_each_result"
156
+ tasks:
157
+ - id: "task_research"
158
+ title: "Read the task context and identify design risks."
159
+ type: "research"
160
+ assignee: null
161
+ deps: []
162
+ acceptance:
163
+ - "Result envelope includes summary and risks."
164
+ status: "pending"
165
+ requires_tools:
166
+ - "fs_read"
167
+ files:
168
+ - "**/*"
169
+ risk: "medium"
170
+ retry_limit: 1
171
+ human_confirmation: false
172
+ - id: "task_impl"
173
+ title: "Implement the requested code change and run tests."
174
+ type: "implementation"
175
+ assignee: null
176
+ deps:
177
+ - "task_research"
178
+ acceptance:
179
+ - "Changed files and tests are reported."
180
+ status: "pending"
181
+ requires_tools:
182
+ - "fs_write"
183
+ - "execute_bash"
184
+ files:
185
+ - "src/**"
186
+ - "tests/**"
187
+ risk: "medium"
188
+ retry_limit: 1
189
+ human_confirmation: false
190
+ - id: "task_review"
191
+ title: "Review implementation output and identify regressions."
192
+ type: "review"
193
+ assignee: null
194
+ deps:
195
+ - "task_impl"
196
+ acceptance:
197
+ - "Findings are structured with risk and artifacts."
198
+ status: "pending"
199
+ requires_tools:
200
+ - "fs_read"
201
+ - "git_diff"
202
+ files:
203
+ - "**/*"
204
+ risk: "medium"
205
+ retry_limit: 0
206
+ human_confirmation: false
@@ -0,0 +1,206 @@
1
+ version: 1
2
+ team:
3
+ name: teamspec-full-example
4
+ mode: supervisor_worker
5
+ objective: Build, research, review, and document a code change with Codex CLI workers.
6
+ workspace: .
7
+ leader:
8
+ id: leader
9
+ role: leader
10
+ provider: codex
11
+ model: null
12
+ tools:
13
+ - fs_read
14
+ - fs_list
15
+ - mcp_team
16
+ - provider_builtin
17
+ context_policy:
18
+ keep_user_thread: true
19
+ receive_worker_outputs: structured_only
20
+ max_worker_result_tokens: 4000
21
+ agents:
22
+ - id: codex_implementer
23
+ role: implementation_engineer
24
+ provider: codex
25
+ model: null
26
+ working_directory: .
27
+ system_prompt:
28
+ inline: |
29
+ You are the implementation worker. Make focused code changes, run relevant tests,
30
+ and report a result_envelope_v1 with changed files, tests, risks, artifacts, and next actions.
31
+ file: null
32
+ tools:
33
+ - fs_read
34
+ - fs_write
35
+ - fs_list
36
+ - execute_bash
37
+ - git_diff
38
+ - mcp_team
39
+ - provider_builtin
40
+ permission_mode: restricted
41
+ preferred_for:
42
+ - implementation
43
+ - bug_fix
44
+ - test
45
+ avoid_for:
46
+ - final_risk_signoff
47
+ output_contract:
48
+ format: result_envelope_v1
49
+ required_fields:
50
+ - task_id
51
+ - status
52
+ - summary
53
+ - artifacts
54
+ - id: codex_researcher
55
+ role: researcher
56
+ provider: codex
57
+ model: null
58
+ working_directory: .
59
+ system_prompt:
60
+ inline: |
61
+ You are the research worker. Prefer read-only analysis and summarize findings
62
+ as result_envelope_v1. Do not edit files.
63
+ file: null
64
+ tools:
65
+ - fs_read
66
+ - fs_list
67
+ - network
68
+ - mcp_team
69
+ - provider_builtin
70
+ permission_mode: restricted
71
+ preferred_for:
72
+ - research
73
+ - architecture
74
+ - docs
75
+ avoid_for:
76
+ - implementation
77
+ output_contract:
78
+ format: result_envelope_v1
79
+ required_fields:
80
+ - task_id
81
+ - status
82
+ - summary
83
+ - artifacts
84
+ - id: codex_reviewer
85
+ role: code_reviewer
86
+ provider: codex
87
+ model: null
88
+ working_directory: .
89
+ system_prompt:
90
+ inline: |
91
+ You are the reviewer. Find correctness, regression, security, and missing-test risks.
92
+ Stay read-only unless the leader explicitly changes your permissions.
93
+ file: null
94
+ tools:
95
+ - fs_read
96
+ - fs_list
97
+ - git_diff
98
+ - mcp_team
99
+ - provider_builtin
100
+ permission_mode: restricted
101
+ preferred_for:
102
+ - review
103
+ - risk_check
104
+ avoid_for:
105
+ - implementation
106
+ output_contract:
107
+ format: result_envelope_v1
108
+ required_fields:
109
+ - task_id
110
+ - status
111
+ - summary
112
+ - artifacts
113
+ routing:
114
+ default_assignee: leader
115
+ rules:
116
+ - id: implementation-to-codex
117
+ when: task.type in ["implementation", "bug_fix", "test"]
118
+ assign_to: codex_implementer
119
+ priority: 100
120
+ - id: research-to-codex
121
+ when: task.type in ["research", "architecture", "docs"]
122
+ assign_to: codex_researcher
123
+ priority: 90
124
+ - id: review-to-codex
125
+ when: task.type in ["review", "risk_check"]
126
+ assign_to: codex_reviewer
127
+ priority: 90
128
+ communication:
129
+ protocol: mcp_inbox
130
+ topology: leader_centered
131
+ worker_to_worker: false
132
+ ack_timeout_sec: 60
133
+ result_format: result_envelope_v1
134
+ message_store:
135
+ sqlite: .team/runtime/team.db
136
+ mirror_files: .team/messages
137
+ runtime:
138
+ backend: tmux
139
+ display_backend: none
140
+ session_name: teamspec-full-example
141
+ auto_launch: true
142
+ require_user_approval_before_launch: true
143
+ dangerous_auto_approve: false
144
+ max_active_agents: 3
145
+ startup_order:
146
+ - codex_implementer
147
+ - codex_researcher
148
+ - codex_reviewer
149
+ context:
150
+ state_file: team_state.md
151
+ artifact_dir: .team/artifacts
152
+ log_dir: .team/logs
153
+ summarization:
154
+ worker_full_logs: retain_outside_leader_context
155
+ state_update: after_each_result
156
+ tasks:
157
+ - id: task_research
158
+ title: Read the task context and identify design risks.
159
+ type: research
160
+ assignee: null
161
+ deps: []
162
+ acceptance:
163
+ - Result envelope includes summary and risks.
164
+ status: pending
165
+ requires_tools:
166
+ - fs_read
167
+ files:
168
+ - "**/*"
169
+ risk: medium
170
+ retry_limit: 1
171
+ human_confirmation: false
172
+ - id: task_impl
173
+ title: Implement the requested code change and run tests.
174
+ type: implementation
175
+ assignee: null
176
+ deps:
177
+ - task_research
178
+ acceptance:
179
+ - Changed files and tests are reported.
180
+ status: pending
181
+ requires_tools:
182
+ - fs_write
183
+ - execute_bash
184
+ files:
185
+ - "src/**"
186
+ - "tests/**"
187
+ risk: medium
188
+ retry_limit: 1
189
+ human_confirmation: false
190
+ - id: task_review
191
+ title: Review implementation output and identify regressions.
192
+ type: review
193
+ assignee: null
194
+ deps:
195
+ - task_impl
196
+ acceptance:
197
+ - Findings are structured with risk and artifacts.
198
+ status: pending
199
+ requires_tools:
200
+ - fs_read
201
+ - git_diff
202
+ files:
203
+ - "**/*"
204
+ risk: medium
205
+ retry_limit: 0
206
+ human_confirmation: false
@@ -0,0 +1,288 @@
1
+ #![allow(clippy::unwrap_used)]
2
+ use super::*;
3
+
4
+ /// 把一段 YAML 文本经 `dumps(loads(t))` 往返,断言**逐字节**等于 Python golden。
5
+ /// 这是 §4.2 双跑对该方言的字节锁:golden 由
6
+ /// `PYTHONPATH=src python3 -c "from team_agent.simple_yaml import loads,dumps; ..."` 取得。
7
+ fn roundtrip_eq(input: &str, golden: &str) {
8
+ let v = loads(input).unwrap();
9
+ assert_eq!(dumps(&v), golden, "roundtrip mismatch for input:\n{input}");
10
+ }
11
+
12
+ // === 真实语料:examples/team.spec.yaml 的 dumps(loads(t)) golden(逐字节) ===
13
+ #[test]
14
+ fn real_spec_yaml_roundtrip_matches_python_golden() {
15
+ let input = include_str!(concat!(
16
+ env!("CARGO_MANIFEST_DIR"),
17
+ "/src/model/testdata/team.spec.yaml"
18
+ ));
19
+ let golden = include_str!(concat!(
20
+ env!("CARGO_MANIFEST_DIR"),
21
+ "/src/model/testdata/team.spec.golden.yaml"
22
+ ));
23
+ let v = loads(input).unwrap();
24
+ assert_eq!(dumps(&v), golden);
25
+ }
26
+
27
+ // === 富边角 fixture:覆盖 ast.literal_eval 半成功(true/null 非法 → 整列退字符串)、
28
+ // 深层嵌套 map、list-of-map 含内嵌 list/map、block scalar 含空行 等 ===
29
+ #[test]
30
+ fn rich_edge_fixture_roundtrip_matches_python_golden() {
31
+ let input = include_str!(concat!(
32
+ env!("CARGO_MANIFEST_DIR"),
33
+ "/src/model/testdata/fuzz.yaml"
34
+ ));
35
+ let golden = include_str!(concat!(
36
+ env!("CARGO_MANIFEST_DIR"),
37
+ "/src/model/testdata/fuzz.golden.yaml"
38
+ ));
39
+ let v = loads(input).unwrap();
40
+ assert_eq!(dumps(&v), golden);
41
+ }
42
+
43
+ // === SKILL.md front-matter 块(`---` 之间那段)的 loads/dumps ===
44
+ #[test]
45
+ fn skill_front_matter_roundtrip() {
46
+ // 取自 skills/team-agent/SKILL.md 的 front matter。
47
+ let input = "name: team-agent\ndescription: Use only when the user explicitly asks to start, operate, inspect, shutdown, or restart a Team Agent team. Treat the team-agent CLI as a sealed appliance.\n";
48
+ let golden = "name: \"team-agent\"\ndescription: \"Use only when the user explicitly asks to start, operate, inspect, shutdown, or restart a Team Agent team. Treat the team-agent CLI as a sealed appliance.\"\n";
49
+ roundtrip_eq(input, golden);
50
+ }
51
+
52
+ // === 方言怪癖逐一对拍(每个 golden 来自 Python 真相源)===
53
+
54
+ #[test]
55
+ fn block_scalar_basic() {
56
+ roundtrip_eq("msg: |\n line one\n line two\n", "msg: |\n line one\n line two\n");
57
+ }
58
+
59
+ #[test]
60
+ fn block_scalar_blank_line_becomes_padded() {
61
+ // 空行在 dumps 时产生仅含 pad 的行(尾随空格)—— Python 行为,必须复刻。
62
+ roundtrip_eq("msg: |\n a\n\n b\n", "msg: |\n a\n \n b\n");
63
+ }
64
+
65
+ #[test]
66
+ fn inline_unquoted_list_stays_string() {
67
+ // ast.literal_eval('[a, b, c]') 失败 → 原样字符串。
68
+ roundtrip_eq("tools: [a, b, c]\n", "tools: \"[a, b, c]\"\n");
69
+ }
70
+
71
+ #[test]
72
+ fn inline_quoted_list_becomes_list() {
73
+ roundtrip_eq("x: ['a', 'b']\n", "x:\n - \"a\"\n - \"b\"\n");
74
+ }
75
+
76
+ #[test]
77
+ fn ints_canonicalize() {
78
+ // 007 -> 7,-5 保号。
79
+ roundtrip_eq("a: 1\nb: -5\nc: 007\n", "a: 1\nb: -5\nc: 7\n");
80
+ }
81
+
82
+ #[test]
83
+ fn int_plus_and_underscore() {
84
+ roundtrip_eq("a: +3\nb: 1_000\n", "a: 3\nb: 1000\n");
85
+ }
86
+
87
+ #[test]
88
+ fn non_ints_stay_strings() {
89
+ roundtrip_eq("a: 1.5\nb: 0x1f\nc: 1e3\nd: _1\n", "a: \"1.5\"\nb: \"0x1f\"\nc: \"1e3\"\nd: \"_1\"\n");
90
+ }
91
+
92
+ #[test]
93
+ fn bools_and_nulls() {
94
+ roundtrip_eq("a: true\nb: False\nc: NULL\nd: ~\n", "a: true\nb: false\nc: null\nd: null\n");
95
+ }
96
+
97
+ #[test]
98
+ fn empty_collections() {
99
+ roundtrip_eq("a: {}\nb: []\n", "a: {}\nb: []\n");
100
+ }
101
+
102
+ #[test]
103
+ fn quoted_strings_unwrap() {
104
+ roundtrip_eq("a: \"hello\"\nb: 'world'\n", "a: \"hello\"\nb: \"world\"\n");
105
+ }
106
+
107
+ #[test]
108
+ fn nested_map() {
109
+ roundtrip_eq("a:\n b:\n c: 1\n", "a:\n b:\n c: 1\n");
110
+ }
111
+
112
+ #[test]
113
+ fn list_of_maps() {
114
+ roundtrip_eq(
115
+ "items:\n - id: x\n val: 1\n - id: y\n val: 2\n",
116
+ "items:\n - id: \"x\"\n val: 1\n - id: \"y\"\n val: 2\n",
117
+ );
118
+ }
119
+
120
+ #[test]
121
+ fn scalar_list_mixed() {
122
+ roundtrip_eq("a:\n - 1\n - two\n - true\n", "a:\n - 1\n - \"two\"\n - true\n");
123
+ }
124
+
125
+ #[test]
126
+ fn empty_value_is_null() {
127
+ roundtrip_eq("a:\nb: 2\n", "a: null\nb: 2\n");
128
+ }
129
+
130
+ #[test]
131
+ fn inline_comment_not_stripped() {
132
+ // 整行注释被跳过;行内 `#` 不被当注释,留在值里。
133
+ roundtrip_eq("# top\na: 1 # inline?\nb: 2\n", "a: \"1 # inline?\"\nb: 2\n");
134
+ }
135
+
136
+ #[test]
137
+ fn key_no_space_after_colon() {
138
+ roundtrip_eq("a:1\n", "a: 1\n");
139
+ }
140
+
141
+ #[test]
142
+ fn special_chars_json_escaped() {
143
+ roundtrip_eq("a: he said \"hi\"\n", "a: \"he said \\\"hi\\\"\"\n");
144
+ }
145
+
146
+ #[test]
147
+ fn unicode_preserved() {
148
+ roundtrip_eq("name: café ☕\n", "name: \"café ☕\"\n");
149
+ }
150
+
151
+ #[test]
152
+ fn list_item_value_has_colon_and_space() {
153
+ // foo: bar baz —— item_text 看起来是 key-value(key=foo 合法),value = "bar baz"。
154
+ roundtrip_eq("a:\n - foo: bar baz\n", "a:\n - foo: \"bar baz\"\n");
155
+ }
156
+
157
+ // === JSON 顶层路径(`{`/`[` 开头 → json.loads,保留键序)===
158
+
159
+ #[test]
160
+ fn json_object_path_preserves_key_order() {
161
+ roundtrip_eq("{\"a\": 1, \"b\": [1,2]}", "a: 1\nb:\n - 1\n - 2\n");
162
+ }
163
+
164
+ #[test]
165
+ fn json_array_path() {
166
+ roundtrip_eq("[1, 2, 3]", "- 1\n- 2\n- 3\n");
167
+ }
168
+
169
+ #[test]
170
+ fn json_leading_whitespace() {
171
+ roundtrip_eq(" {\"a\": 1}", "a: 1\n");
172
+ }
173
+
174
+ #[test]
175
+ fn json_float_becomes_quoted_string() {
176
+ // json.loads -> float 1.5; dumps -> json.dumps(str(1.5)) = "1.5"。
177
+ roundtrip_eq("{\"a\": 1.5}", "a: \"1.5\"\n");
178
+ }
179
+
180
+ #[test]
181
+ fn json_string_with_newline_becomes_block_scalar() {
182
+ roundtrip_eq("{\"x\": \"with\\nnewline\"}", "x: |\n with\n newline\n");
183
+ }
184
+
185
+ #[test]
186
+ fn json_empty_object_and_array_top_level() {
187
+ // 顶层 {} / [] → _dump 返回空 → "\n"。
188
+ roundtrip_eq("{}", "\n");
189
+ roundtrip_eq("[]", "\n");
190
+ }
191
+
192
+ // === dumps-only 结构(直接构造 Value,golden 来自 Python dumps)===
193
+
194
+ #[test]
195
+ fn dump_nested_list_in_list() {
196
+ let v = Value::Map(vec![(
197
+ "a".to_string(),
198
+ Value::List(vec![
199
+ Value::List(vec![Value::Int(1), Value::Int(2)]),
200
+ Value::List(vec![Value::Int(3)]),
201
+ ]),
202
+ )]);
203
+ assert_eq!(dumps(&v), "a:\n -\n - 1\n - 2\n -\n - 3\n");
204
+ }
205
+
206
+ #[test]
207
+ fn dump_mixed_list() {
208
+ let v = Value::List(vec![
209
+ Value::Int(1),
210
+ Value::Str("two".to_string()),
211
+ Value::List(vec![Value::Int(3), Value::Int(4)]),
212
+ Value::Map(vec![("k".to_string(), Value::Str("v".to_string()))]),
213
+ Value::Map(Vec::new()),
214
+ Value::List(Vec::new()),
215
+ ]);
216
+ assert_eq!(dumps(&v), "- 1\n- \"two\"\n-\n - 3\n - 4\n- k: \"v\"\n- {}\n-\n");
217
+ }
218
+
219
+ #[test]
220
+ fn dump_multiline_string_in_list_item_is_not_block_scalar() {
221
+ // 关键不对称:list-of-dict 上下文**不**对多行字符串走 `|`。
222
+ let v = Value::Map(vec![(
223
+ "items".to_string(),
224
+ Value::List(vec![Value::Map(vec![(
225
+ "prompt".to_string(),
226
+ Value::Str("line1\nline2".to_string()),
227
+ )])]),
228
+ )]);
229
+ assert_eq!(dumps(&v), "items:\n - prompt: \"line1\\nline2\"\n");
230
+ }
231
+
232
+ #[test]
233
+ fn dump_deep_map_in_list_uses_indent_plus_4() {
234
+ let v = Value::Map(vec![(
235
+ "items".to_string(),
236
+ Value::List(vec![Value::Map(vec![
237
+ (
238
+ "a".to_string(),
239
+ Value::Map(vec![("b".to_string(), Value::Int(1))]),
240
+ ),
241
+ ("c".to_string(), Value::Int(2)),
242
+ ])]),
243
+ )]);
244
+ assert_eq!(dumps(&v), "items:\n - a:\n b: 1\n c: 2\n");
245
+ }
246
+
247
+ #[test]
248
+ fn dump_string_that_looks_like_int_or_bool_is_quoted() {
249
+ let v = Value::Map(vec![
250
+ ("a".to_string(), Value::Str("5".to_string())),
251
+ ("b".to_string(), Value::Str("true".to_string())),
252
+ ]);
253
+ assert_eq!(dumps(&v), "a: \"5\"\nb: \"true\"\n");
254
+ }
255
+
256
+ #[test]
257
+ fn dump_string_single_newline_only() {
258
+ // "\n".rstrip("\n") = "" -> splitlines() = [] -> 只有 "a: |"。
259
+ let v = Value::Map(vec![("a".to_string(), Value::Str("\n".to_string()))]);
260
+ assert_eq!(dumps(&v), "a: |\n");
261
+ }
262
+
263
+ // === loads 错误路径(与 Python raise 对齐)===
264
+
265
+ #[test]
266
+ fn unexpected_indentation_errors() {
267
+ assert!(loads("a: 1\n b: 2\n").is_err());
268
+ }
269
+
270
+ #[test]
271
+ fn missing_colon_errors() {
272
+ assert!(loads("just a string\n").is_err());
273
+ }
274
+
275
+ #[test]
276
+ fn json_escape_matches_python_for_control_and_specials() {
277
+ // 锁住 serde_json 字符串转义 == Python json.dumps(ensure_ascii=False)。
278
+ assert_eq!(json_quote("a\"b"), "\"a\\\"b\"");
279
+ assert_eq!(json_quote("a\\b"), "\"a\\\\b\"");
280
+ assert_eq!(json_quote("a\nb"), "\"a\\nb\"");
281
+ assert_eq!(json_quote("tab\there"), "\"tab\\there\"");
282
+ assert_eq!(json_quote("a\rb"), "\"a\\rb\"");
283
+ assert_eq!(json_quote("café"), "\"café\"");
284
+ assert_eq!(json_quote("\u{0001}ctrl"), "\"\\u0001ctrl\"");
285
+ assert_eq!(json_quote("slash/here"), "\"slash/here\"");
286
+ assert_eq!(json_quote("back\u{0008}space"), "\"back\\bspace\"");
287
+ assert_eq!(json_quote("form\u{000c}feed"), "\"form\\ffeed\"");
288
+ }