@desplega.ai/agent-swarm 1.149.1 → 1.151.0

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 (538) hide show
  1. package/README.md +18 -3
  2. package/dist/{acp-adapter-vhkzfpjg.js → acp-adapter-ex8hzjfc.js} +5 -5
  3. package/dist/{actions-9d2694yk.js → actions-2bgpyhww.js} +39 -11
  4. package/dist/{app-fq2ggynt.js → app-1706zhr1.js} +7 -7
  5. package/dist/{artifact-gj9arwrr.js → artifact-td4q4dch.js} +1 -1
  6. package/dist/{assistant-edb6n9nn.js → assistant-bavke5p7.js} +44 -20
  7. package/dist/{azure-openai-responses-cqar64rc.js → azure-openai-responses-f38x2avq.js} +13 -13
  8. package/dist/{boot-reembed-msweabbp.js → boot-reembed-3cmrrmpa.js} +9 -9
  9. package/dist/{boot-reembed-q5wd3tha.js → boot-reembed-nafcmmmc.js} +14 -16
  10. package/dist/{boot-scrub-logs-3g1az933.js → boot-scrub-logs-cd6a2sq0.js} +5 -5
  11. package/dist/{claude-adapter-v3rnzsdc.js → claude-adapter-wfp2gzvz.js} +15 -16
  12. package/dist/{claude-managed-adapter-qvsmh6mv.js → claude-managed-adapter-dsmkcrjy.js} +3 -3
  13. package/dist/{claude-sdk-session-qxrpsna1.js → claude-sdk-session-bht9jjak.js} +15 -16
  14. package/dist/{cli-5m0qmvdp.js → cli-0qb1z6s2.js} +1 -1
  15. package/dist/{cli-9d8ntetj.js → cli-2658f6at.js} +1 -1
  16. package/dist/{cli-7evafqvy.js → cli-2tbvf1z1.js} +85 -69
  17. package/dist/{cli-k351hv5k.js → cli-3v9xhjcn.js} +24 -12
  18. package/dist/{cli-1ebpar1q.js → cli-4wppfkcm.js} +350 -20
  19. package/dist/{cli-4260r1tg.js → cli-5jd2z7av.js} +97 -84
  20. package/dist/{cli-cv7s5zdq.js → cli-5tpgq60f.js} +9865 -715
  21. package/dist/{cli-6skz3rk8.js → cli-7tgcstn2.js} +9 -4
  22. package/dist/{cli-01g3x1ca.js → cli-9004vfdf.js} +108 -56
  23. package/dist/{cli-1c94wvcw.js → cli-a1z3h107.js} +124 -99
  24. package/dist/{cli-9br8ypfv.js → cli-czjtgfys.js} +2 -2
  25. package/dist/{cli-5my3bjsd.js → cli-d3p82erb.js} +7 -7
  26. package/dist/{cli-e29gmdmw.js → cli-dv6cdjs2.js} +2 -1
  27. package/dist/{cli-wby1xnnb.js → cli-f1wky6zp.js} +1 -1
  28. package/dist/{cli-zvz62chv.js → cli-fm4ytsdk.js} +4 -4
  29. package/dist/{cli-tg8qj8ee.js → cli-frcta2w4.js} +6 -6
  30. package/dist/{cli-7xx10h0a.js → cli-g69fdc9g.js} +2 -2
  31. package/dist/{cli-cmp8g3sw.js → cli-gbfwcd3k.js} +44 -9
  32. package/dist/{handlers-nsg0bcye.js → cli-gjyvhmmh.js} +97 -45
  33. package/dist/{cli-08b07b4r.js → cli-ht5rs63n.js} +1 -1
  34. package/dist/{cli-jecc01cb.js → cli-j4nv2wqy.js} +2 -4
  35. package/dist/{cli-cd60fv6j.js → cli-j9xczhaq.js} +1 -1
  36. package/dist/cli-pf9q3696.js +172 -0
  37. package/dist/{cli-xm87hzbw.js → cli-pgj4a5fb.js} +1 -1
  38. package/dist/{cli-jezx9b9c.js → cli-ppm4975n.js} +9 -3
  39. package/dist/{cli-3z634pqe.js → cli-q88st9aj.js} +2 -2
  40. package/dist/{cli-3sysyjve.js → cli-r2q6pevn.js} +142 -49
  41. package/dist/{cli-07jd68a1.js → cli-re8z5p8p.js} +1 -1
  42. package/dist/{cli-qgd4sqz5.js → cli-s14agm5s.js} +121 -14
  43. package/dist/{cli-svbrpf5q.js → cli-sjaae6ff.js} +9872 -424
  44. package/dist/{cli-73gq0zxn.js → cli-vwm416m6.js} +13 -13
  45. package/dist/{cli-4wtq5jjv.js → cli-wbyk465z.js} +1 -1
  46. package/dist/{cli-3apbzgyk.js → cli-z61ykvam.js} +19 -14
  47. package/dist/{cli-e06a8a7y.js → cli-zkxymas5.js} +4 -3
  48. package/dist/cli.js +26 -25
  49. package/dist/{codex-adapter-jyw7a91z.js → codex-adapter-jjjk8w4m.js} +8 -9
  50. package/dist/{codex-hook-hfrt9shr.js → codex-hook-8jexc34x.js} +3 -3
  51. package/dist/{codex-session-runner-bmngj0s5.js → codex-session-runner-nd6ayxkx.js} +8 -9
  52. package/dist/{commands-n755g391.js → commands-9v4psyq1.js} +5 -5
  53. package/dist/{db-s1cgh5gv.js → db-wnt58tpe.js} +5 -5
  54. package/dist/dispatcher-05jh1aqk.js +74 -0
  55. package/dist/{e2b-p04vmtx0.js → e2b-413b8t4v.js} +1 -1
  56. package/dist/{google-generative-ai-tsskx7te.js → google-generative-ai-ndjmj5fa.js} +7 -7
  57. package/dist/{google-vertex-ppw8ydpa.js → google-vertex-fr665tqs.js} +10 -10
  58. package/dist/handlers-tw90pkh5.js +65 -0
  59. package/dist/{hook-jf0xe8zh.js → hook-123e2scb.js} +11 -12
  60. package/dist/{hook-h9cqrm8q.js → hook-sxe3r349.js} +11 -12
  61. package/dist/{http-nc6pydw5.js → http-ecsar8ez.js} +1442 -581
  62. package/dist/{index-ezxkds2n.js → index-16js521z.js} +335 -107
  63. package/dist/{index-769nc012.js → index-hw26vj40.js} +25 -19
  64. package/dist/{index-0wdy6gwc.js → index-nnrbpcjp.js} +25 -17
  65. package/dist/index-ymn7em0p.js +25 -0
  66. package/dist/{index-x1zcj09z.js → index-zj518gf9.js} +26 -20
  67. package/dist/{keepalive-nesm3xb6.js → keepalive-asqtcm4y.js} +7 -7
  68. package/dist/{lead-bwy6t2za.js → lead-xbfr7fvt.js} +40 -48
  69. package/dist/{maintenance-8w393zf0.js → maintenance-qma55qvw.js} +9 -9
  70. package/dist/{oauth-refresh-sweep-sh8xjy08.js → oauth-refresh-sweep-3s04c6qw.js} +6 -6
  71. package/dist/{onboard-25ps29h1.js → onboard-drskd386.js} +13 -4
  72. package/dist/{openai-codex-responses-g7w48y30.js → openai-codex-responses-wy6a43wd.js} +13 -13
  73. package/dist/{openai-responses-nmeyptke.js → openai-responses-6xwf7bzg.js} +19 -19
  74. package/dist/{opencode-adapter-dce4wskd.js → opencode-adapter-28axqa09.js} +4 -4
  75. package/dist/{otel-impl-b93gxnz5.js → otel-impl-943c96er.js} +1 -1
  76. package/dist/{pi-mono-adapter-zvshk5cj.js → pi-mono-adapter-jcqt71cg.js} +17 -19
  77. package/dist/{pricing-refresh-5v56x7gb.js → pricing-refresh-mx51az05.js} +7 -7
  78. package/dist/{rbac-roles-x55cnezn.js → rbac-roles-78baecqd.js} +13 -9
  79. package/dist/{rbac-roles-0p0s6pbj.js → rbac-roles-wcmrg6sv.js} +7 -7
  80. package/dist/{render-v2-hyd45w8b.js → render-v2-8zjntgf5.js} +7 -7
  81. package/dist/{seed-pricing-49gbgn96.js → seed-pricing-jqjs6cws.js} +6 -6
  82. package/dist/{setup-qvq64vzq.js → setup-4pks0vfk.js} +2 -2
  83. package/dist/work-objects-wangt792.js +165 -0
  84. package/dist/{worker-scj60cxg.js → worker-p2mr422x.js} +40 -48
  85. package/openapi.json +1365 -268
  86. package/package.json +4 -3
  87. package/src/agentmail/handlers.ts +95 -66
  88. package/src/be/budget-refusal-notify.ts +1 -0
  89. package/src/be/db/tasks/read.ts +3 -0
  90. package/src/be/db/tasks/write.ts +13 -1
  91. package/src/be/db-client.ts +5 -0
  92. package/src/be/db.ts +15 -5
  93. package/src/be/extensions/db.ts +461 -0
  94. package/src/be/extensions/validate.ts +107 -0
  95. package/src/be/memory/boot-reembed.ts +17 -12
  96. package/src/be/memory/index.ts +12 -0
  97. package/src/be/memory/providers/openai-embedding.ts +4 -0
  98. package/src/be/memory/types.ts +2 -0
  99. package/src/be/migrations/153_deferred_task_wait_members.sql +25 -0
  100. package/src/be/migrations/154_routing_source.sql +3 -0
  101. package/src/be/migrations/155_extensions.sql +66 -0
  102. package/src/be/migrations/156_inbox_item_state_read_at.sql +7 -0
  103. package/src/be/rbac-roles.ts +3 -2
  104. package/src/be/scripts/typecheck.ts +59 -41
  105. package/src/be/seed/schedules-seeder.ts +25 -2
  106. package/src/be/seed/workflows-seeder.ts +17 -0
  107. package/src/be/seed-scripts/catalog/delegate.ts +3 -1
  108. package/src/be/seed-skills/bundled-files.generated.json +1 -1
  109. package/src/be/seed-skills/index.ts +7 -0
  110. package/src/be/steering.ts +1 -0
  111. package/src/be/swarm-config-guard.ts +3 -1
  112. package/src/commands/credential-refresh.ts +70 -0
  113. package/src/commands/onboard/compose-generator.ts +14 -2
  114. package/src/commands/onboard/env-generator.ts +7 -0
  115. package/src/commands/provider-credentials.ts +2 -25
  116. package/src/commands/runner.ts +24 -57
  117. package/src/extensions/apply-task-create.ts +135 -0
  118. package/src/extensions/bundle-path.ts +10 -0
  119. package/src/extensions/contract-runtime.ts +7 -0
  120. package/src/extensions/contract-types.generated.ts +4 -0
  121. package/src/extensions/contract.ts +270 -0
  122. package/src/extensions/ctx.ts +186 -0
  123. package/src/extensions/dispatcher.ts +479 -0
  124. package/src/extensions/identity.ts +44 -0
  125. package/src/extensions/lifecycle.ts +281 -0
  126. package/src/extensions/loader.ts +207 -0
  127. package/src/extensions/post-bridge.ts +161 -0
  128. package/src/github/handlers.ts +185 -140
  129. package/src/gitlab/handlers.ts +97 -77
  130. package/src/heartbeat/heartbeat.ts +155 -83
  131. package/src/http/agents.ts +1 -1
  132. package/src/http/all-routes.ts +1 -0
  133. package/src/http/approval-requests.ts +1 -0
  134. package/src/http/apps.ts +14 -9
  135. package/src/http/config.ts +4 -1
  136. package/src/http/core.ts +38 -2
  137. package/src/http/extensions.ts +547 -0
  138. package/src/http/inbox-state.ts +2 -0
  139. package/src/http/index.ts +41 -3
  140. package/src/http/mcp-bridge.ts +96 -62
  141. package/src/http/mcp.ts +1 -1
  142. package/src/http/script-runs.ts +5 -0
  143. package/src/http/status.ts +6 -4
  144. package/src/http/tasks.ts +51 -30
  145. package/src/integrations/kapso/inbound.ts +15 -10
  146. package/src/jira/sync.ts +26 -16
  147. package/src/linear/sync.ts +26 -16
  148. package/src/prompts/session-templates.ts +18 -13
  149. package/src/providers/claude-adapter.ts +21 -8
  150. package/src/rbac/admission.ts +1 -1
  151. package/src/rbac/elevated-agents.ts +24 -0
  152. package/src/rbac/legacy-policy.ts +35 -6
  153. package/src/rbac/permissions.ts +8 -0
  154. package/src/scheduler/deferred-task-waits.ts +138 -27
  155. package/src/scheduler/schedule-task.ts +54 -24
  156. package/src/scheduler/scheduler.ts +108 -125
  157. package/src/scripts-runtime/executors/native.ts +5 -1
  158. package/src/scripts-runtime/executors/types.ts +5 -0
  159. package/src/scripts-runtime/import-allowlist.ts +79 -19
  160. package/src/scripts-runtime/sdk-allowlist.ts +4 -0
  161. package/src/scripts-runtime/swarm-config.ts +8 -0
  162. package/src/scripts-runtime/swarm-sdk.ts +3 -0
  163. package/src/scripts-runtime/types/stdlib.d.ts +16 -3
  164. package/src/scripts-runtime/types/swarm-extension.d.ts +562 -0
  165. package/src/scripts-runtime/types/swarm-sdk.d.ts +16 -3
  166. package/src/server.ts +6 -0
  167. package/src/slack/HEURISTICS.md +3 -1
  168. package/src/slack/actions.ts +21 -16
  169. package/src/slack/app.ts +2 -0
  170. package/src/slack/assistant.ts +4 -12
  171. package/src/slack/blocks.ts +1 -1
  172. package/src/slack/handlers.ts +107 -19
  173. package/src/slack/inbound-files.ts +9 -5
  174. package/src/slack/render-v2.ts +188 -38
  175. package/src/slack/router.ts +13 -3
  176. package/src/slack/steering.ts +3 -3
  177. package/src/slack/thread-buffer.ts +66 -23
  178. package/src/slack/work-objects.test.ts +252 -0
  179. package/src/slack/work-objects.ts +118 -0
  180. package/src/tasks/errors.ts +9 -0
  181. package/src/tasks/sibling-awareness.ts +35 -1
  182. package/src/tasks/worker-follow-up.ts +67 -11
  183. package/src/tests/acp-adapter.test.ts +10 -10
  184. package/src/tests/agent-fs-live-url.test.ts +40 -0
  185. package/src/tests/agent-fs-provision-seeder.test.ts +12 -12
  186. package/src/tests/api-key-tracking.test.ts +18 -18
  187. package/src/tests/api-key.test.ts +4 -2
  188. package/src/tests/apps-rbac.test.ts +1 -1
  189. package/src/tests/apps-spike5.test.ts +1 -1
  190. package/src/tests/apps-sync-engine.test.ts +8 -8
  191. package/src/tests/apps-user-config.test.ts +1 -1
  192. package/src/tests/artifact-sdk.test.ts +8 -8
  193. package/src/tests/asset-key-mcp.test.ts +2 -0
  194. package/src/tests/automation-preflight-alert.test.ts +1 -1
  195. package/src/tests/base-prompt.test.ts +7 -6
  196. package/src/tests/budget-user-scope.test.ts +1 -1
  197. package/src/tests/budgets-routes.test.ts +1 -1
  198. package/src/tests/claude-adapter-binary.test.ts +22 -40
  199. package/src/tests/claude-adapter-otel.test.ts +13 -7
  200. package/src/tests/claude-adapter.test.ts +8 -6
  201. package/src/tests/claude-hook-credentials.test.ts +3 -3
  202. package/src/tests/claude-managed-adapter.test.ts +4 -4
  203. package/src/tests/claude-managed-setup.test.ts +3 -3
  204. package/src/tests/claude-sdk-lifecycle.test.ts +1 -1
  205. package/src/tests/claude-sdk-transport.test.ts +6 -6
  206. package/src/tests/claude-stop-hook.test.ts +8 -8
  207. package/src/tests/claude-worker-parity.test.ts +3 -3
  208. package/src/tests/codex-adapter-pool-auth-revalidate.test.ts +5 -5
  209. package/src/tests/codex-adapter.test.ts +7 -5
  210. package/src/tests/codex-app-server.test.ts +2 -2
  211. package/src/tests/codex-login.test.ts +15 -15
  212. package/src/tests/codex-oauth-credential-info.test.ts +4 -4
  213. package/src/tests/codex-oauth-keep-warm.test.ts +4 -4
  214. package/src/tests/codex-oauth-refresh-lock.test.ts +1 -1
  215. package/src/tests/codex-oauth-storage.test.ts +7 -7
  216. package/src/tests/codex-pool.test.ts +1 -1
  217. package/src/tests/codex-steering-hook.test.ts +1 -1
  218. package/src/tests/codex-swarm-events.test.ts +1 -1
  219. package/src/tests/config-api-only-keys.test.ts +1 -1
  220. package/src/tests/config-session-auth.test.ts +2 -2
  221. package/src/tests/connection-embedded-auth.test.ts +20 -18
  222. package/src/tests/core-auth.test.ts +1 -1
  223. package/src/tests/create-page-tool.test.ts +3 -3
  224. package/src/tests/credential-refresh.test.ts +115 -0
  225. package/src/tests/credential-wait.test.ts +2 -2
  226. package/src/tests/credentials.test.ts +6 -4
  227. package/src/tests/db-queries-oauth.test.ts +40 -40
  228. package/src/tests/defer-task.test.ts +73 -8
  229. package/src/tests/deferred-task-wait-migration.test.ts +64 -0
  230. package/src/tests/deferred-task-wake.test.ts +349 -8
  231. package/src/tests/devin-adapter.test.ts +1 -1
  232. package/src/tests/devin-api.test.ts +1 -1
  233. package/src/tests/docs-index-footprint.test.js +3 -3
  234. package/src/tests/e2b-dispatch.test.ts +21 -19
  235. package/src/tests/e2e-claude-transport.test.ts +3 -3
  236. package/src/tests/e2e-redact.test.ts +6 -6
  237. package/src/tests/ensure-token.test.ts +68 -68
  238. package/src/tests/entrypoint-api-readiness.test.ts +1 -1
  239. package/src/tests/entrypoint-codex-oauth-seed.test.ts +13 -13
  240. package/src/tests/env-flag.test.ts +1 -0
  241. package/src/tests/events-http.test.ts +1 -1
  242. package/src/tests/extensions-db.test.ts +216 -0
  243. package/src/tests/extensions-dispatcher.test.ts +275 -0
  244. package/src/tests/extensions-example-heartbeat-remediate.test.ts +69 -0
  245. package/src/tests/extensions-example-mcp-install.test.ts +63 -0
  246. package/src/tests/extensions-example-no-exclamation-marks.test.ts +72 -0
  247. package/src/tests/extensions-example-rewrite-and-suppress.test.ts +70 -0
  248. package/src/tests/extensions-example-route-slack-channel.test.ts +217 -0
  249. package/src/tests/extensions-heartbeat.test.ts +291 -0
  250. package/src/tests/extensions-http.test.ts +431 -0
  251. package/src/tests/extensions-lead-equivalence.test.ts +49 -0
  252. package/src/tests/extensions-lifecycle.test.ts +209 -0
  253. package/src/tests/extensions-loader.test.ts +95 -0
  254. package/src/tests/extensions-mcp-tools.test.ts +245 -0
  255. package/src/tests/extensions-pre-task.test.ts +487 -0
  256. package/src/tests/extensions-run-context.test.ts +41 -0
  257. package/src/tests/extensions-tool-call.test.ts +288 -0
  258. package/src/tests/extensions-validate.test.ts +196 -0
  259. package/src/tests/fixtures/extensions/bad-import/hooks.ts +8 -0
  260. package/src/tests/fixtures/extensions/bad-import/manifest.json +9 -0
  261. package/src/tests/fixtures/extensions/bad-return-shape/hooks.ts +10 -0
  262. package/src/tests/fixtures/extensions/bad-return-shape/manifest.json +9 -0
  263. package/src/tests/fixtures/extensions/block-tasks-from-source/hooks.ts +22 -0
  264. package/src/tests/fixtures/extensions/block-tasks-from-source/manifest.json +9 -0
  265. package/src/tests/fixtures/extensions/ignore-channel/hooks.ts +22 -0
  266. package/src/tests/fixtures/extensions/ignore-channel/manifest.json +9 -0
  267. package/src/tests/fixtures/extensions/load.ts +10 -0
  268. package/src/tests/fixtures/extensions/minimal/hooks.ts +7 -0
  269. package/src/tests/fixtures/extensions/minimal/manifest.json +9 -0
  270. package/src/tests/fixtures/extensions/never-fail-long-tasks/hooks.ts +11 -0
  271. package/src/tests/fixtures/extensions/never-fail-long-tasks/manifest.json +9 -0
  272. package/src/tests/fixtures/extensions/no-exclamation-marks/hooks.ts +23 -0
  273. package/src/tests/fixtures/extensions/no-exclamation-marks/manifest.json +9 -0
  274. package/src/tests/fixtures/extensions/post-logger/hooks.ts +9 -0
  275. package/src/tests/fixtures/extensions/post-logger/manifest.json +9 -0
  276. package/src/tests/fixtures/extensions/priority-a/hooks.ts +7 -0
  277. package/src/tests/fixtures/extensions/priority-a/manifest.json +9 -0
  278. package/src/tests/fixtures/extensions/priority-b/hooks.ts +7 -0
  279. package/src/tests/fixtures/extensions/priority-b/manifest.json +9 -0
  280. package/src/tests/fixtures/extensions/record-only-on-tag/hooks.ts +16 -0
  281. package/src/tests/fixtures/extensions/record-only-on-tag/manifest.json +9 -0
  282. package/src/tests/fixtures/extensions/reserved-assets/hooks.ts +5 -0
  283. package/src/tests/fixtures/extensions/reserved-assets/manifest.json +10 -0
  284. package/src/tests/fixtures/extensions/rewrite-progress-prefix/hooks.ts +22 -0
  285. package/src/tests/fixtures/extensions/rewrite-progress-prefix/manifest.json +9 -0
  286. package/src/tests/fixtures/extensions/rewrite-task-priority/hooks.ts +7 -0
  287. package/src/tests/fixtures/extensions/rewrite-task-priority/manifest.json +9 -0
  288. package/src/tests/fixtures/extensions/route-channel-to-agent/hooks.ts +26 -0
  289. package/src/tests/fixtures/extensions/route-channel-to-agent/manifest.json +9 -0
  290. package/src/tests/fixtures/extensions/slow/hooks.ts +10 -0
  291. package/src/tests/fixtures/extensions/slow/manifest.json +9 -0
  292. package/src/tests/fixtures/extensions/suppress-lead-follow-up/hooks.ts +12 -0
  293. package/src/tests/fixtures/extensions/suppress-lead-follow-up/manifest.json +9 -0
  294. package/src/tests/fixtures/extensions/throws/hooks.ts +12 -0
  295. package/src/tests/fixtures/extensions/throws/manifest.json +9 -0
  296. package/src/tests/fixtures/extensions/worker-runtime/hooks.ts +5 -0
  297. package/src/tests/fixtures/extensions/worker-runtime/manifest.json +9 -0
  298. package/src/tests/fs-routes.test.ts +1 -1
  299. package/src/tests/gitlab-auth.test.ts +10 -10
  300. package/src/tests/harness-provider-resolution.test.ts +8 -5
  301. package/src/tests/heartbeat-reroute-decision.test.ts +1 -0
  302. package/src/tests/helper-credentials.test.ts +137 -0
  303. package/src/tests/http/context-routes.test.ts +2 -2
  304. package/src/tests/http-api-integration.test.ts +5 -2
  305. package/src/tests/http-users.test.ts +1 -1
  306. package/src/tests/identity-refresh.test.ts +2 -2
  307. package/src/tests/internal-ai/complete-structured.test.ts +2 -2
  308. package/src/tests/internal-ai/credentials.test.ts +19 -17
  309. package/src/tests/jira-metadata.test.ts +1 -1
  310. package/src/tests/jira-oauth.test.ts +5 -5
  311. package/src/tests/jira-sync.test.ts +1 -1
  312. package/src/tests/jira-webhook-lifecycle.test.ts +3 -3
  313. package/src/tests/jira-webhook.test.ts +2 -2
  314. package/src/tests/kapso-inbound.test.ts +2 -2
  315. package/src/tests/kv-http.test.ts +1 -1
  316. package/src/tests/kv-namespace-resolution.test.ts +1 -1
  317. package/src/tests/kv-page-proxy.test.ts +2 -2
  318. package/src/tests/launch-password-rejection.test.ts +2 -2
  319. package/src/tests/linear-webhook.test.ts +1 -1
  320. package/src/tests/mcp-oauth-dcr-reuse.test.ts +6 -6
  321. package/src/tests/mcp-oauth-ensure-token.test.ts +28 -22
  322. package/src/tests/mcp-oauth-manual-client.test.ts +16 -12
  323. package/src/tests/mcp-oauth-queries.test.ts +35 -32
  324. package/src/tests/mcp-oauth-resolve-secrets.test.ts +8 -8
  325. package/src/tests/mcp-oauth-wrapper.test.ts +20 -20
  326. package/src/tests/mcp-user-route.test.ts +1 -1
  327. package/src/tests/memory-edges.test.ts +1 -1
  328. package/src/tests/memory-edit-authorization.test.ts +32 -0
  329. package/src/tests/memory-rate-endpoint.test.ts +1 -1
  330. package/src/tests/memory-rate-tool.test.ts +2 -2
  331. package/src/tests/memory-rater-e2e.test.ts +1 -1
  332. package/src/tests/memory-rater-llm-summarizer.test.ts +3 -3
  333. package/src/tests/memory-rater-llm.test.ts +1 -1
  334. package/src/tests/model-control.test.ts +3 -0
  335. package/src/tests/multi-runtime-enabled-stats.test.ts +2 -2
  336. package/src/tests/multi-runtime-registration.test.ts +111 -17
  337. package/src/tests/oauth-access-token-tool.test.ts +18 -18
  338. package/src/tests/oauth-callback-flow.test.ts +8 -8
  339. package/src/tests/oauth-credential-bindings.test.ts +29 -27
  340. package/src/tests/oauth-keepalive.test.ts +10 -10
  341. package/src/tests/oauth-presets.test.ts +13 -5
  342. package/src/tests/oauth-refresh-failure.test.ts +9 -9
  343. package/src/tests/oauth-refresh-sweep.test.ts +20 -13
  344. package/src/tests/oauth-wrapper.test.ts +1 -1
  345. package/src/tests/onboard-compose.test.ts +47 -3
  346. package/src/tests/onboard-env.test.ts +26 -26
  347. package/src/tests/onboard-non-interactive.test.ts +4 -4
  348. package/src/tests/opencode-adapter.test.ts +1 -1
  349. package/src/tests/opencode-plugin.test.ts +2 -2
  350. package/src/tests/otel-session-cost-metrics.test.ts +1 -1
  351. package/src/tests/page-proxy-authed.test.ts +2 -2
  352. package/src/tests/page-proxy.test.ts +2 -2
  353. package/src/tests/page-session.test.ts +7 -7
  354. package/src/tests/page-viewer-auth.test.ts +2 -2
  355. package/src/tests/pages-authed-mode.test.ts +1 -1
  356. package/src/tests/pages-http.test.ts +1 -1
  357. package/src/tests/pages-password-mode.test.ts +1 -1
  358. package/src/tests/pages-public-authed-401.test.ts +1 -1
  359. package/src/tests/pages-public-html.test.ts +2 -2
  360. package/src/tests/pages-view-count.test.ts +1 -1
  361. package/src/tests/pi-mono-adapter.test.ts +10 -10
  362. package/src/tests/pi-mono-extension.test.ts +2 -2
  363. package/src/tests/preload.ts +5 -0
  364. package/src/tests/pricing-routes.test.ts +1 -1
  365. package/src/tests/profile-sync-warning.test.ts +8 -8
  366. package/src/tests/profile-sync.test.ts +8 -8
  367. package/src/tests/prompt-template-session.test.ts +36 -5
  368. package/src/tests/provider-process-group.test.ts +95 -4
  369. package/src/tests/providers/pi-cost.test.ts +1 -1
  370. package/src/tests/queue-stall-alarm.test.ts +1 -1
  371. package/src/tests/rbac-admission.test.ts +19 -4
  372. package/src/tests/rbac-charact-http.test.ts +1 -1
  373. package/src/tests/rbac-e2e-helpers.ts +1 -1
  374. package/src/tests/rbac-engine.test.ts +39 -0
  375. package/src/tests/realtime-room-auth.test.ts +1 -1
  376. package/src/tests/realtime-room-surfaces.test.ts +1 -1
  377. package/src/tests/reload-config.test.ts +45 -1
  378. package/src/tests/routing-affinity-inventory.test.ts +1 -1
  379. package/src/tests/routing-reason-contract.test.ts +76 -3
  380. package/src/tests/routing-reason-inventory.test.ts +11 -6
  381. package/src/tests/routing-source.test.ts +53 -0
  382. package/src/tests/runner-agent-fs-provision-retry.test.ts +1 -1
  383. package/src/tests/runner-context-preamble.test.ts +1 -1
  384. package/src/tests/runner-deployment-resume.test.ts +1 -1
  385. package/src/tests/runner-fallback-output.test.ts +1 -1
  386. package/src/tests/runner-identity-refresh.test.ts +1 -1
  387. package/src/tests/runner-skills-refresh.test.ts +1 -1
  388. package/src/tests/schedule-target-type.test.ts +3 -3
  389. package/src/tests/scheduled-tasks.test.ts +14 -5
  390. package/src/tests/scheduler-occurrence.test.ts +347 -0
  391. package/src/tests/script-apis-mcp.test.ts +1 -1
  392. package/src/tests/script-connections-http.test.ts +61 -58
  393. package/src/tests/script-connections-mcp.test.ts +1 -1
  394. package/src/tests/script-connections.test.ts +3 -1
  395. package/src/tests/script-runs-http.test.ts +15 -7
  396. package/src/tests/script-workflows-runtime-e2e.test.ts +1 -1
  397. package/src/tests/scripts-boot-reembed.test.ts +4 -0
  398. package/src/tests/scripts-embeddings.test.ts +4 -0
  399. package/src/tests/scripts-external-api.test.ts +1 -1
  400. package/src/tests/scripts-http.test.ts +1 -1
  401. package/src/tests/scripts-import-allowlist.test.ts +44 -1
  402. package/src/tests/scripts-mcp-e2e.test.ts +81 -1
  403. package/src/tests/scripts-only-gating.test.ts +4 -2
  404. package/src/tests/scripts-retention.test.ts +1 -1
  405. package/src/tests/scripts-runtime-identity.test.ts +2 -2
  406. package/src/tests/scripts-runtime-secret-egress.test.ts +1 -1
  407. package/src/tests/scripts-runtime.test.ts +6 -4
  408. package/src/tests/scripts-typecheck.test.ts +21 -0
  409. package/src/tests/sdk-allowlist.test.ts +1 -1
  410. package/src/tests/secret-scrubber.test.ts +38 -31
  411. package/src/tests/seed-registry.test.ts +46 -8
  412. package/src/tests/seed-schedules.test.ts +44 -9
  413. package/src/tests/seed-workflows.test.ts +21 -9
  414. package/src/tests/send-task-output-schema.test.ts +9 -1
  415. package/src/tests/send-task-requested-by.test.ts +1 -0
  416. package/src/tests/send-task-slack-routing-guard.test.ts +2 -0
  417. package/src/tests/session-costs-codex-recompute.test.ts +1 -1
  418. package/src/tests/session-costs-golden.test.ts +2 -2
  419. package/src/tests/session-costs-model-key-normalize.test.ts +2 -2
  420. package/src/tests/session-costs-recompute-all-providers.test.ts +1 -1
  421. package/src/tests/session-tokens.test.ts +1 -1
  422. package/src/tests/shutdown-error-scrubbing.test.ts +1 -1
  423. package/src/tests/slack-blocks.test.ts +12 -1
  424. package/src/tests/slack-file-tools-attachments.test.ts +1 -1
  425. package/src/tests/slack-inbound-files.test.ts +222 -86
  426. package/src/tests/slack-reaction-config.test.ts +5 -4
  427. package/src/tests/slack-read-boundaries.test.ts +1 -1
  428. package/src/tests/slack-render-v2.test.ts +196 -4
  429. package/src/tests/slack-router.test.ts +17 -2
  430. package/src/tests/slack-steering.test.ts +19 -0
  431. package/src/tests/status.test.ts +19 -7
  432. package/src/tests/steering-core.test.ts +1 -1
  433. package/src/tests/steering-enabled.test.ts +6 -8
  434. package/src/tests/steering-transport.test.ts +4 -4
  435. package/src/tests/store-progress-output-guidance.test.ts +34 -0
  436. package/src/tests/swarm-tool-result-gate.test.ts +11 -11
  437. package/src/tests/swarm-x-tool.test.ts +7 -5
  438. package/src/tests/sync-ai-toolbox-skills.test.ts +19 -0
  439. package/src/tests/task-supersede-resume.test.ts +1 -1
  440. package/src/tests/task-tool-preload-mcp.test.ts +4 -1
  441. package/src/tests/task-tools-ctx.test.ts +2 -0
  442. package/src/tests/tasks-requested-by-filter.test.ts +2 -2
  443. package/src/tests/telemetry-init.test.ts +11 -3
  444. package/src/tests/tool-annotations.test.ts +1 -1
  445. package/src/tests/tool-output-agent-id.test.ts +1 -0
  446. package/src/tests/tool-registrar-no-input.test.ts +42 -1
  447. package/src/tests/tracker-fold.test.ts +7 -7
  448. package/src/tests/tracker-tools.test.ts +3 -3
  449. package/src/tests/ui-followup-lead-delegation.test.ts +1 -0
  450. package/src/tests/unified-oauth-migration.test.ts +5 -5
  451. package/src/tests/user-token-rest-auth.test.ts +1 -1
  452. package/src/tests/user-token-routes.test.ts +1 -1
  453. package/src/tests/whoami-route.test.ts +1 -1
  454. package/src/tests/workflow-agent-task.test.ts +15 -13
  455. package/src/tests/workflow-ctx.test.ts +1 -1
  456. package/src/tests/workflow-e2e.test.ts +1 -1
  457. package/src/tests/workflow-engine-v2.test.ts +3 -1
  458. package/src/tests/workflow-executors.test.ts +2 -2
  459. package/src/tests/workflow-http-v2.test.ts +8 -6
  460. package/src/tests/workflow-input-redaction.test.ts +7 -5
  461. package/src/tests/workflow-integration-io.test.ts +2 -2
  462. package/src/tests/workflow-llm.test.ts +5 -5
  463. package/src/tests/workflow-registry.test.ts +1 -1
  464. package/src/tests/workflow-swarm-script.test.ts +1 -1
  465. package/src/tests/workflow-triggers-v2.test.ts +23 -21
  466. package/src/tests/x-composio.test.ts +9 -7
  467. package/src/tests/x402-client.test.ts +1 -1
  468. package/src/tests/x402-config.test.ts +28 -41
  469. package/src/tools/defer-task.ts +156 -24
  470. package/src/tools/extension-common.ts +84 -0
  471. package/src/tools/extension-install.ts +65 -0
  472. package/src/tools/extension-list.ts +66 -0
  473. package/src/tools/script-common.ts +43 -18
  474. package/src/tools/send-task.ts +87 -105
  475. package/src/tools/skills/skill-publish.ts +1 -0
  476. package/src/tools/store-progress.ts +1 -1
  477. package/src/tools/task-action.ts +43 -22
  478. package/src/tools/task-tool-ctx.ts +2 -0
  479. package/src/tools/templates.ts +2 -1
  480. package/src/tools/tool-config.ts +3 -1
  481. package/src/tools/utils.ts +140 -16
  482. package/src/types.ts +144 -0
  483. package/src/utils/constants.ts +7 -1
  484. package/src/utils/credentials.test.ts +16 -16
  485. package/src/utils/multi-runtime.ts +2 -2
  486. package/src/utils/steering-enabled.ts +4 -4
  487. package/src/workflows/executors/agent-task.ts +18 -3
  488. package/templates/ai-toolbox.manifest.json +7 -1
  489. package/templates/extensions/README.md +17 -0
  490. package/templates/extensions/notify-on-complete/README.md +11 -0
  491. package/templates/extensions/notify-on-complete/hooks.ts +61 -0
  492. package/templates/extensions/notify-on-complete/manifest.json +7 -0
  493. package/templates/extensions/require-ticket-ref/README.md +11 -0
  494. package/templates/extensions/require-ticket-ref/hooks.ts +30 -0
  495. package/templates/extensions/require-ticket-ref/manifest.json +7 -0
  496. package/templates/extensions/require-verification-note/README.md +11 -0
  497. package/templates/extensions/require-verification-note/hooks.ts +32 -0
  498. package/templates/extensions/require-verification-note/manifest.json +7 -0
  499. package/templates/schedules/daily-hn-briefing/config.json +1 -1
  500. package/templates/schedules/gtm-weekly-review/config.json +1 -1
  501. package/templates/schedules/weekly-code-health-reports/config.json +1 -1
  502. package/templates/schedules/weekly-dependabot-triage/config.json +1 -1
  503. package/templates/schedules/weekly-dora-metrics/config.json +1 -1
  504. package/templates/schedules/weekly-harness-upgrade-check/config.json +1 -1
  505. package/templates/skills/delegate-work/files/scripts/codex-exec.sh +1 -1
  506. package/templates/skills/scheduling/content.md +2 -0
  507. package/templates/skills/serply-search/SKILL.md +95 -0
  508. package/templates/skills/serply-search/config.json +13 -0
  509. package/templates/skills/serply-search/content.md +90 -0
  510. package/templates/skills/swarm-extensions/config.json +14 -0
  511. package/templates/skills/swarm-extensions/content.md +120 -0
  512. package/templates/skills/swarm-scripts/SKILL.md +2 -2
  513. package/templates/skills/swarm-scripts/content.md +2 -2
  514. package/templates/workflows/claude-code-changelog-watch/config.json +1 -1
  515. package/templates/workflows/gsc-topic-miner/config.json +1 -1
  516. package/templates/workflows/linear-drain-loop/config.json +1 -1
  517. package/templates/workflows/llm-safe-release-context/config.json +1 -1
  518. package/templates/workflows/ralph-loop/config.json +1 -1
  519. package/dist/cli-7fehefdf.js +0 -562
  520. package/dist/cli-ayvy5kde.js +0 -164
  521. package/dist/cli-ddfw1mc4.js +0 -4322
  522. package/dist/cli-hzqmgcm2.js +0 -3066
  523. package/dist/cli-j4d4f6hv.js +0 -338
  524. package/dist/cli-qgm2pfpq.js +0 -6377
  525. package/dist/cli-sdzq01t9.js +0 -823
  526. package/dist/cli-xvkmedgn.js +0 -332
  527. package/dist/cli-y3pq4v9g.js +0 -664
  528. package/dist/{anthropic-messages-vs2rabzp.js → anthropic-messages-2y8nktar.js} +19 -19
  529. package/dist/{claude-managed-setup-f5pmsyrp.js → claude-managed-setup-48dwg9bv.js} +3 -3
  530. package/dist/{cli-81r683bv.js → cli-ch38q5z4.js} +0 -0
  531. package/dist/{cli-6664w7y4.js → cli-kj76p1ez.js} +8 -8
  532. package/dist/{cli-c71mg51n.js → cli-r2fpe7cx.js} +5 -5
  533. package/dist/{cli-4xz3pmrq.js → cli-y6x0gqtg.js} +16 -16
  534. package/dist/{index-aa3sa6s8.js → index-2wsdsnmm.js} +1 -1
  535. package/dist/{mistral-conversations-4ryk7h83.js → mistral-conversations-qhr84ph3.js} +9 -9
  536. package/dist/{openai-completions-0bqmsajw.js → openai-completions-32rdwmze.js} +19 -19
  537. package/dist/{openrouter-images-qx18fyp8.js → openrouter-images-9f9ek4rw.js} +3 -3
  538. package/dist/{pi-messages-79jvzz1d.js → pi-messages-b1mbr6gp.js} +4 -4
@@ -10,6 +10,7 @@ import { handleCore } from "../http/core";
10
10
  import { handleScriptRuns } from "../http/script-runs";
11
11
  import { handleScripts } from "../http/scripts";
12
12
  import { getPathSegments, parseQueryParams } from "../http/utils";
13
+ import { proxyScriptsApi } from "../tools/script-common";
13
14
  import { registerScriptDeleteTool } from "../tools/script-delete";
14
15
  import { registerScriptRunTool } from "../tools/script-run";
15
16
  import { registerScriptRunsTools } from "../tools/script-runs";
@@ -22,7 +23,7 @@ import { SKIP_SANDBOX_SPAWN_TESTS } from "./sandbox-spawn-test-helpers";
22
23
  import "../prompts/session-templates";
23
24
 
24
25
  const TEST_DB_PATH = "./test-scripts-mcp-e2e.sqlite";
25
- const API_KEY = "test-scripts-mcp-key-1234567890";
26
+ const API_KEY = "example-test-scripts-mcp-key-1234567890";
26
27
  const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
27
28
 
28
29
  function fakeEmbedding(text: string): Float32Array {
@@ -221,6 +222,85 @@ beforeEach(async () => {
221
222
  });
222
223
 
223
224
  describe("script_ MCP HTTP proxy tools", () => {
225
+ test.each([200, 502])("rejects HTML responses with HTTP %i", async (status) => {
226
+ const tools = buildToolServer();
227
+ const html = "<!doctype html><html><body>Static site fallback</body></html>";
228
+ const previousFetch = globalThis.fetch;
229
+ globalThis.fetch = (async () =>
230
+ new Response(html, {
231
+ status,
232
+ headers: { "Content-Type": "text/html; charset=utf-8" },
233
+ })) as typeof globalThis.fetch;
234
+ try {
235
+ const result = (await tools.listScriptRuns.handler(
236
+ { limit: 10, offset: 0 },
237
+ meta(workerId),
238
+ )) as StructuredResult<unknown>;
239
+
240
+ expect(result.isError).toBe(true);
241
+ expect(result.structuredContent.success).toBe(false);
242
+ expect(result.structuredContent.status).toBe(status);
243
+ expect(result.structuredContent.message).toContain("non-JSON");
244
+ expect(result.structuredContent.message).toContain(`HTTP ${status}`);
245
+ expect(result.structuredContent.message).toContain("text/html");
246
+ expect(result.content[0]?.text).toContain(html);
247
+ expect(result.content[0]?.text).not.toContain("Found 0 script run(s)");
248
+ } finally {
249
+ globalThis.fetch = previousFetch;
250
+ }
251
+ });
252
+
253
+ test("caps invalid JSON diagnostics without retaining the full body", async () => {
254
+ const body = `<html>${"x".repeat(20_000)}BODY_TAIL</html>`;
255
+ const previousFetch = globalThis.fetch;
256
+ globalThis.fetch = (async () =>
257
+ new Response(body, {
258
+ status: 200,
259
+ headers: { "Content-Type": "application/json" },
260
+ })) as typeof globalThis.fetch;
261
+ try {
262
+ const result = await proxyScriptsApi({
263
+ method: "GET",
264
+ path: "/api/script-runs",
265
+ requestInfo: {
266
+ sessionId: "s",
267
+ agentId: workerId,
268
+ runtimeInstanceId: undefined,
269
+ sourceTaskId: undefined,
270
+ contextKey: undefined,
271
+ callOrigin: "mcp",
272
+ },
273
+ successMessage: () => {
274
+ throw new Error("Invalid JSON must not reach the success callback");
275
+ },
276
+ uncappedDetails: true,
277
+ });
278
+
279
+ expect(result.ok).toBe(false);
280
+ expect(result.message).toContain("application/json");
281
+ expect(result.details).toContain("<html>");
282
+ expect(result.details).toContain("[truncated");
283
+ expect(result.details?.length).toBeLessThan(16_100);
284
+ expect(JSON.stringify(result)).not.toContain("BODY_TAIL");
285
+ } finally {
286
+ globalThis.fetch = previousFetch;
287
+ }
288
+ });
289
+
290
+ test("reports a legitimate JSON empty run list as success", async () => {
291
+ const tools = buildToolServer();
292
+ const result = (await tools.listScriptRuns.handler(
293
+ { limit: 10, offset: 0 },
294
+ meta(workerId),
295
+ )) as StructuredResult<{ total: number; runs: unknown[] }>;
296
+
297
+ expect(result.isError).toBeFalsy();
298
+ expect(result.structuredContent.success).toBe(true);
299
+ expect(result.structuredContent.status).toBe(200);
300
+ expect(result.structuredContent.data?.runs).toEqual([]);
301
+ expect(result.structuredContent.message).toBe("Found 0 script run(s).");
302
+ });
303
+
224
304
  test("upserts the canonical script authoring contract example verbatim", async () => {
225
305
  const tools = buildToolServer();
226
306
  // The authoring contract lives in the seeded `swarm-scripts` skill since
@@ -17,6 +17,8 @@ import { listenOnFreePort } from "./test-net";
17
17
 
18
18
  const TEST_DB_PATH = "./test-scripts-only-gating.sqlite";
19
19
  const SCRIPT_TOOL_NAMES = [
20
+ "extension-install",
21
+ "extension-list",
20
22
  "get-script-run",
21
23
  "launch-script-run",
22
24
  "list-script-runs",
@@ -193,8 +195,8 @@ beforeEach(async () => {
193
195
  await scriptsOnlyEnvQueue;
194
196
  savedSlackBotToken = process.env.SLACK_BOT_TOKEN;
195
197
  savedSlackAppToken = process.env.SLACK_APP_TOKEN;
196
- process.env.SLACK_BOT_TOKEN = "test-bot-token";
197
- process.env.SLACK_APP_TOKEN = "test-app-token";
198
+ process.env.SLACK_BOT_TOKEN = "example-test-bot-token";
199
+ process.env.SLACK_APP_TOKEN = "example-test-app-token";
198
200
  await getDbClient().run("DELETE FROM swarm_config WHERE key = 'SCRIPTS_ONLY_MCP'");
199
201
  });
200
202
 
@@ -39,7 +39,7 @@ async function addScript(name: string, isScratch: boolean) {
39
39
 
40
40
  describe("scratch script retention", () => {
41
41
  beforeAll(async () => {
42
- process.env.AGENT_SWARM_API_KEY = "scripts-retention-test-key";
42
+ process.env.AGENT_SWARM_API_KEY = "example-scripts-retention-test-key";
43
43
  await clearDb();
44
44
  initDb(TEST_DB_PATH);
45
45
  });
@@ -30,7 +30,7 @@ import { listenOnFreePort } from "./test-net";
30
30
 
31
31
  const TEST_DB_PATH = "./test-scripts-runtime-identity.sqlite";
32
32
  let baseUrl = "";
33
- const API_KEY = "scripts-runtime-identity-key-1234567890";
33
+ const API_KEY = "example-scripts-runtime-identity-key-1234567890";
34
34
  const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
35
35
 
36
36
  const savedEnv = { ...process.env };
@@ -374,7 +374,7 @@ describe("script SDK dispatch hits the real runtime gates", () => {
374
374
  });
375
375
 
376
376
  test("with the flag off, the SDK dispatches without runtime identity as before", async () => {
377
- delete process.env.MULTI_RUNTIME_ENABLED;
377
+ process.env.MULTI_RUNTIME_ENABLED = "false";
378
378
  const agentId = await makeAgent(1);
379
379
  const task = await createTaskExtended("legacy-claim-work");
380
380
 
@@ -14,7 +14,7 @@ const savedEnv = { ...process.env };
14
14
  const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
15
15
 
16
16
  beforeEach(() => {
17
- process.env.AGENT_SWARM_API_KEY = "runtime-egress-secret-1234567890";
17
+ process.env.AGENT_SWARM_API_KEY = "example-runtime-egress-secret-1234567890";
18
18
  refreshSecretScrubberCache();
19
19
  });
20
20
 
@@ -15,7 +15,7 @@ const resources = { memoryMb: 2048, cpuTimeSec: 20, maxStdoutBytes: 1_048_576 };
15
15
  const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
16
16
 
17
17
  beforeEach(() => {
18
- process.env.AGENT_SWARM_API_KEY = "runtime-test-secret-1234567890";
18
+ process.env.AGENT_SWARM_API_KEY = "example-runtime-test-secret-1234567890";
19
19
  delete process.env.API_KEY;
20
20
  process.env.MCP_BASE_URL = "http://localhost:3013";
21
21
  refreshSecretScrubberCache();
@@ -99,7 +99,9 @@ describe("runScript", () => {
99
99
  const server = Bun.serve({
100
100
  port: 0,
101
101
  async fetch(req) {
102
- expect(req.headers.get("authorization")).toBe("Bearer runtime-test-secret-1234567890");
102
+ expect(req.headers.get("authorization")).toBe(
103
+ "Bearer example-runtime-test-secret-1234567890",
104
+ );
103
105
  expect(req.headers.get("x-agent-id")).toBe("agent-1");
104
106
 
105
107
  const url = new URL(req.url);
@@ -280,8 +282,8 @@ describe("runScript", () => {
280
282
  });
281
283
 
282
284
  spawnTest("subprocess env is stripped to the explicit allowlist", async () => {
283
- process.env.API_KEY = "legacy-secret-that-must-not-leak";
284
- process.env.AGENT_SWARM_API_KEY = "preferred-secret-that-must-not-leak";
285
+ process.env.API_KEY = "example-legacy-secret-that-must-not-leak";
286
+ process.env.AGENT_SWARM_API_KEY = "example-preferred-secret-that-must-not-leak";
285
287
  refreshSecretScrubberCache();
286
288
 
287
289
  const output = await runScript({
@@ -47,6 +47,27 @@ afterAll(async () => {
47
47
  });
48
48
 
49
49
  describe("typecheckScript", () => {
50
+ test("task_send requires a routing note for explicit assignments at typecheck", async () => {
51
+ const missing = await typecheckScript(`
52
+ import type { ScriptContext } from "swarm-sdk";
53
+ export default async function(args: unknown, ctx: ScriptContext) {
54
+ return ctx.swarm.task_send({ task: "work", agentId: "worker", routingReason: "skill" });
55
+ }
56
+ `);
57
+ expect(missing.ok).toBe(false);
58
+ if (!missing.ok) expect(missing.diagnostics.join("\n")).toContain("routingNote");
59
+
60
+ const valid = await typecheckScript(`
61
+ import type { ScriptContext } from "swarm-sdk";
62
+ export default async function(args: unknown, ctx: ScriptContext) {
63
+ await ctx.swarm.task_send({ task: "work", agentId: "worker", routingReason: "skill", routingNote: "Owns this code path" });
64
+ await ctx.swarm.task_send({ task: "pool work" });
65
+ await ctx.swarm.task_send({ task: "continue", parentTaskId: "parent" });
66
+ }
67
+ `);
68
+ expect(valid).toEqual({ ok: true });
69
+ });
70
+
50
71
  test("task_defer accepts task wakeOn with a required caller-supplied ceiling", async () => {
51
72
  const result = await typecheckScript(`
52
73
  import type { ScriptContext } from "swarm-sdk";
@@ -220,7 +220,7 @@ describe("script SDK allowlist", () => {
220
220
 
221
221
  describe("mcp-bridge allowlist gate", () => {
222
222
  const TEST_DB_PATH = "./test-sdk-allowlist-bridge.sqlite";
223
- const API_KEY = "test-mcp-bridge-key-1234567890";
223
+ const API_KEY = "example-test-mcp-bridge-key-1234567890";
224
224
  let prevApiKey: string | undefined;
225
225
  let oversizedTaskId: string;
226
226
 
@@ -67,23 +67,23 @@ describe("scrubSecrets — env-based replacement", () => {
67
67
  });
68
68
 
69
69
  test("redacts any key with _API_KEY suffix", () => {
70
- process.env.FOO_SERVICE_API_KEY = "supersecretFooApiKey_longerthan12chars";
70
+ process.env.FOO_SERVICE_API_KEY = "example-supersecretFooApiKey_longerthan12chars";
71
71
  refreshSecretScrubberCache();
72
- const out = scrubSecrets("key=supersecretFooApiKey_longerthan12chars tail");
72
+ const out = scrubSecrets("key=example-supersecretFooApiKey_longerthan12chars tail");
73
73
  expect(out).toBe("key=[REDACTED:FOO_SERVICE_API_KEY] tail");
74
74
  });
75
75
 
76
76
  test("redacts any key with _TOKEN suffix", () => {
77
- process.env.WEIRD_SERVICE_TOKEN = "weirdserviceTOKENvalue_1234567890";
77
+ process.env.WEIRD_SERVICE_TOKEN = "example-weirdserviceTOKENvalue_1234567890";
78
78
  refreshSecretScrubberCache();
79
- const out = scrubSecrets("t=weirdserviceTOKENvalue_1234567890");
79
+ const out = scrubSecrets("t=example-weirdserviceTOKENvalue_1234567890");
80
80
  expect(out).toBe("t=[REDACTED:WEIRD_SERVICE_TOKEN]");
81
81
  });
82
82
 
83
83
  test("redacts any key with _SECRET suffix", () => {
84
- process.env.MY_OAUTH_CLIENT_SECRET = "oauthsecret_verylong_1234567890abcdef";
84
+ process.env.MY_OAUTH_CLIENT_SECRET = "example-oauthsecret_verylong_1234567890abcdef";
85
85
  refreshSecretScrubberCache();
86
- const out = scrubSecrets("secret=oauthsecret_verylong_1234567890abcdef");
86
+ const out = scrubSecrets("secret=example-oauthsecret_verylong_1234567890abcdef");
87
87
  expect(out).toBe("secret=[REDACTED:MY_OAUTH_CLIENT_SECRET]");
88
88
  });
89
89
 
@@ -111,10 +111,11 @@ describe("scrubSecrets — env-based replacement", () => {
111
111
 
112
112
  test("handles comma-separated pool values (scrubs both the full pool and each component)", () => {
113
113
  process.env.POOL_TOKEN =
114
- "ghp_poolfirst1234567890abcdefABCDEF1234567890,ghp_poolsecond1234567890abcdef1234567890AB";
114
+ "example-ghp_poolfirst1234567890abcdefABCDEF1234567890," +
115
+ "example-ghp_poolsecond1234567890abcdef1234567890AB";
115
116
  refreshSecretScrubberCache();
116
- const out = scrubSecrets("using ghp_poolfirst1234567890abcdefABCDEF1234567890");
117
- expect(out).not.toContain("ghp_poolfirst1234567890abcdefABCDEF1234567890");
117
+ const out = scrubSecrets("using example-ghp_poolfirst1234567890abcdefABCDEF1234567890");
118
+ expect(out).not.toContain("example-ghp_poolfirst1234567890abcdefABCDEF1234567890");
118
119
  expect(out).toContain("[REDACTED:");
119
120
  });
120
121
 
@@ -123,7 +124,8 @@ describe("scrubSecrets — env-based replacement", () => {
123
124
  process.env.OPENAI_API_KEY = "sk-proj-abcd1234567890EFGHefgh1234567890";
124
125
  refreshSecretScrubberCache();
125
126
  const input =
126
- "gh=ghp_abcdefghijklmnopqrstuvwxyz0123456789 and openai=sk-proj-abcd1234567890EFGHefgh1234567890";
127
+ "gh=example-ghp_abcdefghijklmnopqrstuvwxyz0123456789 " +
128
+ "and openai=example-sk-proj-abcd1234567890EFGHefgh1234567890";
127
129
  const out = scrubSecrets(input);
128
130
  expect(out).toContain("[REDACTED:GITHUB_TOKEN]");
129
131
  expect(out).toContain("[REDACTED:OPENAI_API_KEY]");
@@ -146,63 +148,65 @@ describe("scrubSecrets — env-based replacement", () => {
146
148
  const out1 = scrubSecrets("no secret yet here_abcdefghij");
147
149
  expect(out1).toBe("no secret yet here_abcdefghij");
148
150
 
149
- process.env.NEW_SERVICE_API_KEY = "here_abcdefghij_andmore1234567890";
151
+ process.env.NEW_SERVICE_API_KEY = "example-here_abcdefghij_andmore1234567890";
150
152
  refreshSecretScrubberCache();
151
- const out2 = scrubSecrets("value=here_abcdefghij_andmore1234567890");
153
+ const out2 = scrubSecrets("value=example-here_abcdefghij_andmore1234567890");
152
154
  expect(out2).toBe("value=[REDACTED:NEW_SERVICE_API_KEY]");
153
155
  });
154
156
  });
155
157
 
156
158
  describe("scrubSecrets — regex patterns", () => {
157
159
  test("redacts github_pat_ fine-grained PATs", () => {
158
- const out = scrubSecrets("PAT: github_pat_11B4WKYAA0Qe95fajGmt3o_ABCDEF1234567890abcdef");
160
+ const token = `github_pat_${"a".repeat(32)}`;
161
+ const out = scrubSecrets(`PAT: ${token}`);
159
162
  expect(out).toContain("[REDACTED:github_pat]");
160
- expect(out).not.toContain("github_pat_11B4WKYAA");
163
+ expect(out).not.toContain(token);
161
164
  });
162
165
 
163
166
  test("redacts ghp_ classic tokens", () => {
164
- const out = scrubSecrets("PAT: ghp_1234567890abcdefABCDEF1234567890ABCD end");
167
+ const out = scrubSecrets("PAT: example-ghp_1234567890abcdefABCDEF1234567890ABCD end");
165
168
  expect(out).toContain("[REDACTED:github_token]");
166
169
  expect(out).not.toContain("ghp_1234567890abcdef");
167
170
  });
168
171
 
169
172
  test("redacts gho_ OAuth tokens", () => {
170
- const out = scrubSecrets("OAuth: gho_abcdef1234567890ABCDEF1234567890abcd");
173
+ const out = scrubSecrets("OAuth: example-gho_abcdef1234567890ABCDEF1234567890abcd");
171
174
  expect(out).toContain("[REDACTED:github_token]");
172
175
  });
173
176
 
174
177
  test("redacts ghs_ installation tokens", () => {
175
- const out = scrubSecrets("Installation: ghs_abcdef1234567890ABCDEF1234567890abcd");
178
+ const out = scrubSecrets("Installation: example-ghs_abcdef1234567890ABCDEF1234567890abcd");
176
179
  expect(out).toContain("[REDACTED:github_token]");
177
180
  });
178
181
 
179
182
  test("redacts glpat- GitLab PATs", () => {
180
- const out = scrubSecrets("GL: glpat-abcdef1234567890ABCDEFgh");
183
+ const out = scrubSecrets("GL: example-glpat-abcdef1234567890ABCDEFgh");
181
184
  expect(out).toContain("[REDACTED:gitlab_pat]");
182
185
  expect(out).not.toContain("glpat-abcdef");
183
186
  });
184
187
 
185
188
  test("redacts sk-ant- Anthropic keys", () => {
186
- const out = scrubSecrets("Anthropic: sk-ant-api03-abc123def456ghi789jkl012mno345");
189
+ const token = `sk-ant-${"a".repeat(32)}`;
190
+ const out = scrubSecrets(`Anthropic: ${token}`);
187
191
  expect(out).toContain("[REDACTED:anthropic_key]");
188
- expect(out).not.toContain("sk-ant-api03");
192
+ expect(out).not.toContain(token);
189
193
  });
190
194
 
191
195
  test("redacts sk-proj- OpenAI project keys (preferred over legacy sk-)", () => {
192
- const out = scrubSecrets("OpenAI: sk-proj-abcdefghijklmnopqrstuvwxyz012345");
196
+ const out = scrubSecrets("OpenAI: example-sk-proj-abcdefghijklmnopqrstuvwxyz012345");
193
197
  expect(out).toContain("[REDACTED:openai_proj_key]");
194
198
  expect(out).not.toContain("sk-proj-abcdefghijkl");
195
199
  });
196
200
 
197
201
  test("redacts legacy sk- keys (catch-all)", () => {
198
- const out = scrubSecrets("Legacy: sk-abcdefghijklmnopqrstuvwxyz0123");
202
+ const out = scrubSecrets("Legacy: example-sk-abcdefghijklmnopqrstuvwxyz0123");
199
203
  expect(out).toContain("[REDACTED:sk_key]");
200
204
  });
201
205
 
202
206
  test("redacts Slack xoxb tokens", () => {
203
- const out = scrubSecrets("slack=xoxb-1234567890-0987654321-abcdefghij");
207
+ const out = scrubSecrets("slack=example-xoxb-1234567890-0987654321-abcdefghij");
204
208
  expect(out).toContain("[REDACTED:slack_token]");
205
- expect(out).not.toContain("xoxb-1234567890");
209
+ expect(out).not.toContain("example-xoxb-1234567890");
206
210
  });
207
211
 
208
212
  test("redacts AWS access key IDs", () => {
@@ -228,7 +232,7 @@ describe("scrubSecrets — regex patterns", () => {
228
232
 
229
233
  test("regex patterns catch tokens even when env is empty", () => {
230
234
  // Fresh env — no secrets registered — regex should still catch well-known shapes.
231
- const out = scrubSecrets("token=ghp_1234567890abcdefABCDEF1234567890ABCD");
235
+ const out = scrubSecrets("token=example-ghp_1234567890abcdefABCDEF1234567890ABCD");
232
236
  expect(out).toContain("[REDACTED:github_token]");
233
237
  });
234
238
 
@@ -241,7 +245,7 @@ describe("scrubSecrets — regex patterns", () => {
241
245
  });
242
246
 
243
247
  test("redacts Linear OAuth tokens", () => {
244
- const out = scrubSecrets("Authorization: Bearer lin_oauth_test123abcdef end");
248
+ const out = scrubSecrets("Authorization: Bearer example-lin_oauth_test123abcdef end");
245
249
  expect(out).toContain("[REDACTED:linear_oauth]");
246
250
  expect(out).not.toContain("lin_oauth_test123");
247
251
  });
@@ -279,7 +283,10 @@ describe("scrubSecrets — regex patterns", () => {
279
283
  });
280
284
 
281
285
  test("redacts tokens in double-encoded JSON with escape sequences", () => {
282
- const inner = JSON.stringify({ access_token: "lin_oauth_test123abcdef", scope: "read" });
286
+ const inner = JSON.stringify({
287
+ access_token: "example-lin_oauth_test123abcdef",
288
+ scope: "read",
289
+ });
283
290
  const content = `{"output":${JSON.stringify(inner)}}`;
284
291
  const out = scrubSecrets(content);
285
292
  expect(out).toContain("[REDACTED:linear_oauth]");
@@ -333,14 +340,14 @@ describe("scrubSecrets — does not over-scrub", () => {
333
340
 
334
341
  describe("scrubObject", () => {
335
342
  test("scrubs nested object and array string leaves", () => {
336
- process.env.NESTED_TOKEN = "nested-secret-value-1234567890";
343
+ process.env.NESTED_TOKEN = "example-nested-secret-value-1234567890";
337
344
  refreshSecretScrubberCache();
338
345
 
339
346
  const out = scrubObject({
340
347
  keep: 1,
341
348
  nested: {
342
- secret: "nested-secret-value-1234567890",
343
- list: ["safe", "nested-secret-value-1234567890"],
349
+ secret: "example-nested-secret-value-1234567890",
350
+ list: ["safe", "example-nested-secret-value-1234567890"],
344
351
  },
345
352
  nullish: null,
346
353
  bool: true,
@@ -371,7 +378,7 @@ describe("registerVolatileSecret", () => {
371
378
  });
372
379
 
373
380
  test("scrubs a runtime-registered volatile secret", () => {
374
- const secret = "volatile_runtime_token_1234567890abcdef";
381
+ const secret = "example-volatile_runtime_token_1234567890abcdef";
375
382
  registerVolatileSecret(secret, "RUNTIME_TOKEN");
376
383
  const out = scrubSecrets(`key=${secret}`);
377
384
  expect(out).toBe("key=[REDACTED:RUNTIME_TOKEN]");
@@ -1,6 +1,6 @@
1
1
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
2
  import { unlink } from "node:fs/promises";
3
- import { closeDb, initDb, listWorkflows } from "../be/db";
3
+ import { closeDb, getScheduledTasks, initDb, listWorkflows } from "../be/db";
4
4
  import { runSeeder, SEEDERS } from "../be/seed";
5
5
  import { schedulesSeeder } from "../be/seed/schedules-seeder";
6
6
  import { workflowsSeeder } from "../be/seed/workflows-seeder";
@@ -38,17 +38,55 @@ describe("seeder registry", () => {
38
38
  ]);
39
39
  });
40
40
 
41
- test("the built-in catalogs expose the expected candidate counts", () => {
42
- expect(workflowsSeeder.items()).toHaveLength(5);
43
- expect(schedulesSeeder.items()).toHaveLength(5);
41
+ test("the bundled catalogs include every workflow and schedule template", async () => {
42
+ for (const [kind, seeder] of [
43
+ ["workflows", workflowsSeeder],
44
+ ["schedules", schedulesSeeder],
45
+ ] as const) {
46
+ const catalogNames: string[] = [];
47
+ const catalogDir = `${import.meta.dir}/../../templates/${kind}`;
48
+ for await (const path of new Bun.Glob("*/config.json").scan(catalogDir)) {
49
+ const config = await Bun.file(`${catalogDir}/${path}`).json();
50
+ catalogNames.push(config.name);
51
+ }
52
+ expect(
53
+ seeder
54
+ .items()
55
+ .map((item) => item.key)
56
+ .sort(),
57
+ ).toEqual(catalogNames.sort());
58
+ }
44
59
  });
45
60
 
46
- test("seeds all starter workflow and schedule rows on a fresh database", async () => {
61
+ test("seeds all 21 automation templates on a fresh database and re-runs as a no-op", async () => {
62
+ expect(await listWorkflows()).toHaveLength(0);
63
+ expect(await getScheduledTasks()).toHaveLength(0);
64
+
47
65
  const workflowResult = await runSeeder(workflowsSeeder, { quiet: true });
48
66
  const scheduleResult = await runSeeder(schedulesSeeder, { quiet: true });
49
67
 
50
- expect(workflowResult).toMatchObject({ created: 5, failed: [] });
51
- expect(scheduleResult).toMatchObject({ created: 5, failed: [] });
52
- expect(await listWorkflows()).toHaveLength(5);
68
+ expect(workflowResult).toMatchObject({ created: 10, failed: [] });
69
+ expect(scheduleResult).toMatchObject({ created: 11, failed: [] });
70
+ expect((await listWorkflows()).map((workflow) => workflow.name).sort()).toEqual(
71
+ workflowsSeeder.items().map((item) => item.key),
72
+ );
73
+ expect((await getScheduledTasks()).map((schedule) => schedule.name).sort()).toEqual(
74
+ schedulesSeeder.items().map((item) => item.key),
75
+ );
76
+
77
+ expect(await runSeeder(workflowsSeeder, { quiet: true })).toMatchObject({
78
+ created: 0,
79
+ updated: 0,
80
+ skippedUnchanged: 10,
81
+ failed: [],
82
+ });
83
+ expect(await runSeeder(schedulesSeeder, { quiet: true })).toMatchObject({
84
+ created: 0,
85
+ updated: 0,
86
+ skippedUnchanged: 11,
87
+ failed: [],
88
+ });
89
+ expect(await listWorkflows()).toHaveLength(10);
90
+ expect(await getScheduledTasks()).toHaveLength(11);
53
91
  });
54
92
  });
@@ -1,6 +1,12 @@
1
1
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
2
  import { unlink } from "node:fs/promises";
3
- import { closeDb, getScheduledTaskByName, initDb, updateScheduledTask } from "../be/db";
3
+ import {
4
+ closeDb,
5
+ getScheduledTaskByName,
6
+ getScheduledTasks,
7
+ initDb,
8
+ updateScheduledTask,
9
+ } from "../be/db";
4
10
  import { runSeeder } from "../be/seed";
5
11
  import {
6
12
  createSchedulesSeeder,
@@ -69,6 +75,7 @@ function zeroConfigScheduleSource(opts?: {
69
75
  const ORIGINAL_SEED_AUTOMATIONS_ENABLED = process.env.SEED_AUTOMATIONS_ENABLED;
70
76
 
71
77
  beforeEach(async () => {
78
+ delete process.env.SEED_AUTOMATIONS_ENABLED;
72
79
  await removeDbFiles();
73
80
  initDb(TEST_DB_PATH);
74
81
  });
@@ -84,9 +91,9 @@ afterEach(async () => {
84
91
  });
85
92
 
86
93
  describe("schedules seeder", () => {
87
- test("loads only the five starter candidates, including the unfenced schedule block", () => {
94
+ test("loads all eleven schedule templates, including the unfenced schedule block", () => {
88
95
  const schedules = loadSeedSchedules();
89
- expect(schedules).toHaveLength(5);
96
+ expect(schedules).toHaveLength(11);
90
97
  // Zero-config, requires:[], placeholders:[], template enabled:true -> auto-enabled
91
98
  // under the default (unset -> on) SEED_AUTOMATIONS_ENABLED switch.
92
99
  expect(schedules.find((schedule) => schedule.name === "daily-status-report")).toMatchObject({
@@ -102,18 +109,46 @@ describe("schedules seeder", () => {
102
109
  requiredParams: [],
103
110
  requires: [],
104
111
  });
105
- expect(schedules.some((schedule) => schedule.name === "weekly-dependabot-triage")).toBe(false);
106
- expect(schedules.some((schedule) => schedule.name === "weekly-harness-upgrade-check")).toBe(
107
- false,
108
- );
112
+ expect(
113
+ schedules.find((schedule) => schedule.name === "weekly-harness-upgrade-check"),
114
+ ).toMatchObject({
115
+ enabled: false,
116
+ requiredParams: ["REPO_URL", "PR_REVIEWER"],
117
+ requires: ["github"],
118
+ });
119
+ expect(
120
+ schedules.filter((schedule) => schedule.enabled).map((schedule) => schedule.name),
121
+ ).toEqual([
122
+ "daily-blocker-digest",
123
+ "daily-compounding-reflection",
124
+ "daily-status-report",
125
+ "daily-swarm-update-check",
126
+ "daily-workflow-health-audit",
127
+ ]);
109
128
  });
110
129
 
111
- test("SEED_AUTOMATIONS_ENABLED=false keeps every candidate disabled, including zero-config ones", () => {
130
+ test("SEED_AUTOMATIONS_ENABLED=false still seeds all schedules disabled", async () => {
112
131
  process.env.SEED_AUTOMATIONS_ENABLED = "false";
113
- const schedules = loadSeedSchedules();
132
+ const result = await runSeeder(createSchedulesSeeder(), { quiet: true });
133
+ expect(result).toMatchObject({ created: 11, failed: [] });
134
+ const schedules = await getScheduledTasks();
135
+ expect(schedules).toHaveLength(11);
114
136
  expect(schedules.every((schedule) => schedule.enabled === false)).toBe(true);
115
137
  });
116
138
 
139
+ test("seeds a disabled schedule whose timezone still needs setup", async () => {
140
+ const result = await runSeeder(createSchedulesSeeder(), { quiet: true });
141
+ expect(result).toMatchObject({ created: 11, failed: [] });
142
+ expect(await getScheduledTaskByName("weekly-dependabot-triage")).toMatchObject({
143
+ cronExpression: "40 3 * * 0",
144
+ timezone: "{{TIMEZONE}}",
145
+ enabled: false,
146
+ nextRunAt: undefined,
147
+ requiredParams: ["REPO_URL", "SLACK_CHANNEL_ID", "TIMEZONE"],
148
+ requires: ["github", "slack"],
149
+ });
150
+ });
151
+
117
152
  test("switch on: a zero-config candidate auto-enables via createSchedulesSeeder/apply", async () => {
118
153
  delete process.env.SEED_AUTOMATIONS_ENABLED;
119
154
  const seeder = createSchedulesSeeder([zeroConfigScheduleSource()]);
@@ -66,6 +66,7 @@ async function getWorkflow(name = "test-seeded-workflow") {
66
66
  const ORIGINAL_SEED_AUTOMATIONS_ENABLED = process.env.SEED_AUTOMATIONS_ENABLED;
67
67
 
68
68
  beforeEach(async () => {
69
+ delete process.env.SEED_AUTOMATIONS_ENABLED;
69
70
  await removeDbFiles();
70
71
  initDb(TEST_DB_PATH);
71
72
  });
@@ -81,24 +82,35 @@ afterEach(async () => {
81
82
  });
82
83
 
83
84
  describe("workflows seeder", () => {
84
- test("loads only the five starter candidates with their setup metadata", () => {
85
+ test("loads all ten workflow templates with their setup metadata", () => {
85
86
  const workflows = loadSeedWorkflows();
86
- expect(workflows).toHaveLength(5);
87
+ expect(workflows).toHaveLength(10);
87
88
  expect(workflows.find((workflow) => workflow.name === "autopilot")).toMatchObject({
88
89
  enabled: false,
89
90
  requiredParams: ["REPO_URL"],
90
91
  requires: ["github"],
91
92
  });
92
- expect(workflows.some((workflow) => workflow.name === "ralph-loop")).toBe(false);
93
- expect(workflows.some((workflow) => workflow.name === "claude-code-changelog-watch")).toBe(
94
- false,
95
- );
96
- expect(workflows.some((workflow) => workflow.name === "gsc-topic-miner")).toBe(false);
93
+ expect(
94
+ workflows.find((workflow) => workflow.name === "claude-code-changelog-watch"),
95
+ ).toMatchObject({
96
+ enabled: false,
97
+ requiredParams: [],
98
+ requires: [],
99
+ });
100
+ expect(workflows.find((workflow) => workflow.name === "gsc-topic-miner")).toMatchObject({
101
+ enabled: false,
102
+ requiredParams: ["GSC_PROPERTY"],
103
+ requires: ["gsc", "agentfs"],
104
+ });
105
+ expect(workflows.every((workflow) => !workflow.enabled)).toBe(true);
97
106
  });
98
107
 
99
- test("SEED_AUTOMATIONS_ENABLED=false keeps every candidate disabled, including zero-config ones", () => {
108
+ test("SEED_AUTOMATIONS_ENABLED=false still seeds all workflows disabled", async () => {
100
109
  process.env.SEED_AUTOMATIONS_ENABLED = "false";
101
- const workflows = loadSeedWorkflows();
110
+ const result = await runSeeder(createWorkflowsSeeder(), { quiet: true });
111
+ expect(result).toMatchObject({ created: 10, failed: [] });
112
+ const workflows = await listWorkflows();
113
+ expect(workflows).toHaveLength(10);
102
114
  expect(workflows.every((workflow) => workflow.enabled === false)).toBe(true);
103
115
  });
104
116