@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
@@ -427,7 +427,7 @@ describe("/api/script-connections HTTP", () => {
427
427
  test("oauth-apps GET never includes clientSecret", async () => {
428
428
  await upsertOAuthApp("vendor_oauth", {
429
429
  clientId: "vendor-client",
430
- clientSecret: "oauth-client-secret-should-not-leak",
430
+ clientSecret: "example-oauth-client-secret-should-not-leak",
431
431
  authorizeUrl: "https://oauth.vendor.test/authorize",
432
432
  tokenUrl: "https://oauth.vendor.test/token",
433
433
  redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
@@ -447,21 +447,21 @@ describe("/api/script-connections HTTP", () => {
447
447
  expect(body.oauthApps[0]?.clientId).toBe("vendor-client");
448
448
  expect(body.oauthApps[0]).not.toHaveProperty("clientSecret");
449
449
  expect(body.oauthApps[0]?.lastRefreshedAt).toBeNull();
450
- expect(JSON.stringify(body)).not.toContain("oauth-client-secret-should-not-leak");
450
+ expect(JSON.stringify(body)).not.toContain("example-oauth-client-secret-should-not-leak");
451
451
  });
452
452
 
453
453
  test("oauth-apps GET includes lastRefreshedAt when tokens are stored", async () => {
454
454
  await upsertOAuthApp("vendor_oauth", {
455
455
  clientId: "vendor-client",
456
- clientSecret: "oauth-client-secret-should-not-leak",
456
+ clientSecret: "example-oauth-client-secret-should-not-leak",
457
457
  authorizeUrl: "https://oauth.vendor.test/authorize",
458
458
  tokenUrl: "https://oauth.vendor.test/token",
459
459
  redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
460
460
  scopes: "read,write",
461
461
  });
462
462
  await storeOAuthTokens("vendor_oauth", {
463
- accessToken: "access-token-should-not-leak",
464
- refreshToken: "refresh-token-should-not-leak",
463
+ accessToken: "example-access-token-should-not-leak",
464
+ refreshToken: "example-refresh-token-should-not-leak",
465
465
  expiresAt: new Date(Date.now() + 3_600_000).toISOString(),
466
466
  scope: "read,write",
467
467
  });
@@ -474,8 +474,8 @@ describe("/api/script-connections HTTP", () => {
474
474
  expect(body.oauthApps[0]?.lastRefreshedAt).toBe(
475
475
  (await getOAuthTokens("vendor_oauth"))?.updatedAt,
476
476
  );
477
- expect(res.text).not.toContain("access-token-should-not-leak");
478
- expect(res.text).not.toContain("refresh-token-should-not-leak");
477
+ expect(res.text).not.toContain("example-access-token-should-not-leak");
478
+ expect(res.text).not.toContain("example-refresh-token-should-not-leak");
479
479
  });
480
480
 
481
481
  test("detail returns operations and generated types without secrets", async () => {
@@ -546,15 +546,15 @@ describe("/api/script-connections HTTP", () => {
546
546
  test("DELETE oauth app removes app and tokens", async () => {
547
547
  await upsertOAuthApp("vendor_oauth", {
548
548
  clientId: "vendor-client",
549
- clientSecret: "oauth-client-secret",
549
+ clientSecret: "example-oauth-client-secret",
550
550
  authorizeUrl: "https://oauth.vendor.test/authorize",
551
551
  tokenUrl: "https://oauth.vendor.test/token",
552
552
  redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
553
553
  scopes: "read,write",
554
554
  });
555
555
  await storeOAuthTokens("vendor_oauth", {
556
- accessToken: "access-token",
557
- refreshToken: "refresh-token",
556
+ accessToken: "example-access-token",
557
+ refreshToken: "example-refresh-token",
558
558
  expiresAt: "2035-01-01T00:00:00.000Z",
559
559
  scope: "read write",
560
560
  });
@@ -573,7 +573,7 @@ describe("/api/script-connections HTTP", () => {
573
573
  // First (oldest) app for the provider + its default authorization.
574
574
  await upsertOAuthApp("sibling_oauth", {
575
575
  clientId: "first-client",
576
- clientSecret: "first-secret",
576
+ clientSecret: "example-first-secret",
577
577
  authorizeUrl: "https://oauth.vendor.test/authorize",
578
578
  tokenUrl: "https://oauth.vendor.test/token",
579
579
  redirectUri: "https://api.public.test/api/oauth/callback",
@@ -583,7 +583,7 @@ describe("/api/script-connections HTTP", () => {
583
583
  if (!first) throw new Error("first app not created");
584
584
  const firstAuth = await upsertAuthorization({
585
585
  appId: first.id,
586
- accessToken: "first-access-token",
586
+ accessToken: "example-first-access-token",
587
587
  status: "active",
588
588
  });
589
589
 
@@ -594,14 +594,14 @@ describe("/api/script-connections HTTP", () => {
594
594
  `INSERT INTO oauth_apps
595
595
  (id, provider, clientId, clientSecret, clientSecretEncrypted,
596
596
  authorizeUrl, tokenUrl, redirectUri, scopes, createdAt)
597
- VALUES (?, 'sibling_oauth', 'second-client', 'second-secret', 0,
597
+ VALUES (?, 'sibling_oauth', 'second-client', 'example-second-secret', 0,
598
598
  'https://oauth.vendor.test/authorize', 'https://oauth.vendor.test/token',
599
599
  'https://api.public.test/api/oauth/callback', '[]', ?)`,
600
600
  [secondId, "2035-06-01T00:00:00.000Z"],
601
601
  );
602
602
  const secondAuth = await upsertAuthorization({
603
603
  appId: secondId,
604
- accessToken: "second-access-token",
604
+ accessToken: "example-second-access-token",
605
605
  status: "active",
606
606
  });
607
607
 
@@ -625,7 +625,7 @@ describe("/api/script-connections HTTP", () => {
625
625
  test("manual authorization refresh failure scrubs echoed secrets from the error", async () => {
626
626
  await upsertOAuthApp("leaky_oauth", {
627
627
  clientId: "leaky-client",
628
- clientSecret: "leaky-client-secret-should-not-leak",
628
+ clientSecret: "example-leaky-client-secret-should-not-leak",
629
629
  authorizeUrl: "https://oauth.vendor.test/authorize",
630
630
  tokenUrl: "https://oauth.vendor.test/token",
631
631
  redirectUri: "https://api.public.test/api/oauth/callback",
@@ -635,8 +635,8 @@ describe("/api/script-connections HTTP", () => {
635
635
  if (!app) throw new Error("app not created");
636
636
  const authorization = await upsertAuthorization({
637
637
  appId: app.id,
638
- accessToken: "leaky-access-token",
639
- refreshToken: "refresh-secret-should-not-leak",
638
+ accessToken: "example-leaky-access-token",
639
+ refreshToken: "example-refresh-secret-should-not-leak",
640
640
  status: "active",
641
641
  });
642
642
 
@@ -647,7 +647,7 @@ describe("/api/script-connections HTTP", () => {
647
647
  JSON.stringify({
648
648
  error: "invalid_grant",
649
649
  error_description:
650
- "bad refresh_token=refresh-secret-should-not-leak client_secret=leaky-client-secret-should-not-leak",
650
+ "bad refresh_token=example-refresh-secret-should-not-leak client_secret=example-leaky-client-secret-should-not-leak",
651
651
  }),
652
652
  { status: 400, headers: { "content-type": "application/json" } },
653
653
  )) as typeof fetch;
@@ -657,8 +657,8 @@ describe("/api/script-connections HTTP", () => {
657
657
  agentId: leadAgentId,
658
658
  });
659
659
  expect(res.status).toBe(502);
660
- expect(res.text).not.toContain("refresh-secret-should-not-leak");
661
- expect(res.text).not.toContain("leaky-client-secret-should-not-leak");
660
+ expect(res.text).not.toContain("example-refresh-secret-should-not-leak");
661
+ expect(res.text).not.toContain("example-leaky-client-secret-should-not-leak");
662
662
  });
663
663
 
664
664
  test("oauth app edit (by id) without clientSecret keeps existing secret", async () => {
@@ -666,7 +666,7 @@ describe("/api/script-connections HTTP", () => {
666
666
  // no-id create must NOT — that path always inserts (see the create tests).
667
667
  await upsertOAuthApp("vendor_oauth", {
668
668
  clientId: "vendor-client",
669
- clientSecret: "existing-client-secret",
669
+ clientSecret: "example-existing-client-secret",
670
670
  authorizeUrl: "https://oauth.vendor.test/authorize",
671
671
  tokenUrl: "https://oauth.vendor.test/token",
672
672
  redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
@@ -690,9 +690,9 @@ describe("/api/script-connections HTTP", () => {
690
690
  expect(res.status).toBe(200);
691
691
  const app = await getOAuthAppById(existing.id);
692
692
  expect(app?.clientId).toBe("updated-client");
693
- expect(app?.clientSecret).toBe("existing-client-secret");
693
+ expect(app?.clientSecret).toBe("example-existing-client-secret");
694
694
  expect(app?.scopes).toBe("");
695
- expect(JSON.stringify(await res.json())).not.toContain("existing-client-secret");
695
+ expect(JSON.stringify(await res.json())).not.toContain("example-existing-client-secret");
696
696
  });
697
697
 
698
698
  test("POST without id always creates a new row and never clobbers a same-provider sibling", async () => {
@@ -702,7 +702,7 @@ describe("/api/script-connections HTTP", () => {
702
702
  body: {
703
703
  provider: "multi_vendor",
704
704
  clientId: "first-client",
705
- clientSecret: "first-secret",
705
+ clientSecret: "example-first-secret",
706
706
  authorizeUrl: "https://oauth.vendor.test/authorize",
707
707
  tokenUrl: "https://oauth.vendor.test/token",
708
708
  scopes: ["read"],
@@ -718,7 +718,7 @@ describe("/api/script-connections HTTP", () => {
718
718
  body: {
719
719
  provider: "multi_vendor",
720
720
  clientId: "second-client",
721
- clientSecret: "second-secret",
721
+ clientSecret: "example-second-secret",
722
722
  authorizeUrl: "https://oauth.vendor.test/authorize2",
723
723
  tokenUrl: "https://oauth.vendor.test/token2",
724
724
  scopes: ["write"],
@@ -732,10 +732,10 @@ describe("/api/script-connections HTTP", () => {
732
732
  const firstApp = await getOAuthAppById(firstId);
733
733
  const secondApp = await getOAuthAppById(secondId);
734
734
  expect(firstApp?.clientId).toBe("first-client");
735
- expect(firstApp?.clientSecret).toBe("first-secret");
735
+ expect(firstApp?.clientSecret).toBe("example-first-secret");
736
736
  expect(firstApp?.authorizeUrl).toBe("https://oauth.vendor.test/authorize");
737
737
  expect(secondApp?.clientId).toBe("second-client");
738
- expect(secondApp?.clientSecret).toBe("second-secret");
738
+ expect(secondApp?.clientSecret).toBe("example-second-secret");
739
739
  });
740
740
 
741
741
  test("POST with id updates only the targeted row, leaving siblings intact", async () => {
@@ -745,7 +745,7 @@ describe("/api/script-connections HTTP", () => {
745
745
  body: {
746
746
  provider: "target_vendor",
747
747
  clientId: "orig-a",
748
- clientSecret: "secret-a",
748
+ clientSecret: "example-secret-a",
749
749
  authorizeUrl: "https://oauth.vendor.test/authorize",
750
750
  tokenUrl: "https://oauth.vendor.test/token",
751
751
  scopes: ["read"],
@@ -758,7 +758,7 @@ describe("/api/script-connections HTTP", () => {
758
758
  body: {
759
759
  provider: "target_vendor",
760
760
  clientId: "orig-b",
761
- clientSecret: "secret-b",
761
+ clientSecret: "example-secret-b",
762
762
  authorizeUrl: "https://oauth.vendor.test/authorize",
763
763
  tokenUrl: "https://oauth.vendor.test/token",
764
764
  scopes: ["read"],
@@ -773,7 +773,7 @@ describe("/api/script-connections HTTP", () => {
773
773
  id: firstId,
774
774
  provider: "target_vendor",
775
775
  clientId: "edited-a",
776
- clientSecret: "secret-a-new",
776
+ clientSecret: "example-secret-a-new",
777
777
  authorizeUrl: "https://oauth.vendor.test/authorize",
778
778
  tokenUrl: "https://oauth.vendor.test/token",
779
779
  scopes: ["read"],
@@ -781,10 +781,10 @@ describe("/api/script-connections HTTP", () => {
781
781
  });
782
782
  expect(edit.status).toBe(200);
783
783
  expect((await getOAuthAppById(firstId))?.clientId).toBe("edited-a");
784
- expect((await getOAuthAppById(firstId))?.clientSecret).toBe("secret-a-new");
784
+ expect((await getOAuthAppById(firstId))?.clientSecret).toBe("example-secret-a-new");
785
785
  // Sibling is untouched.
786
786
  expect((await getOAuthAppById(secondId))?.clientId).toBe("orig-b");
787
- expect((await getOAuthAppById(secondId))?.clientSecret).toBe("secret-b");
787
+ expect((await getOAuthAppById(secondId))?.clientSecret).toBe("example-secret-b");
788
788
  });
789
789
 
790
790
  test("POST without id and without clientSecret is rejected (create requires a secret)", async () => {
@@ -792,7 +792,7 @@ describe("/api/script-connections HTTP", () => {
792
792
  // fallback for a no-id create.
793
793
  await upsertOAuthApp("needs_secret", {
794
794
  clientId: "sibling-client",
795
- clientSecret: "sibling-secret",
795
+ clientSecret: "example-sibling-secret",
796
796
  authorizeUrl: "https://oauth.vendor.test/authorize",
797
797
  tokenUrl: "https://oauth.vendor.test/token",
798
798
  redirectUri: "https://api.public.test/api/oauth/needs_secret/callback",
@@ -821,7 +821,7 @@ describe("/api/script-connections HTTP", () => {
821
821
  body: {
822
822
  provider: "linear",
823
823
  clientId: "linear-client",
824
- clientSecret: "linear-secret",
824
+ clientSecret: "example-linear-secret",
825
825
  authorizeUrl: "https://oauth.vendor.test/authorize",
826
826
  tokenUrl: "https://oauth.vendor.test/token",
827
827
  scopes: [],
@@ -843,7 +843,7 @@ describe("/api/script-connections HTTP", () => {
843
843
  body: {
844
844
  provider: "unsafe_vendor",
845
845
  clientId: "unsafe-client",
846
- clientSecret: "unsafe-secret",
846
+ clientSecret: "example-unsafe-secret",
847
847
  authorizeUrl: "https://oauth.vendor.test/authorize",
848
848
  tokenUrl: "http://127.0.0.1/token",
849
849
  scopes: [],
@@ -859,7 +859,7 @@ describe("/api/script-connections HTTP", () => {
859
859
  body: {
860
860
  provider: "safe_vendor",
861
861
  clientId: "safe-client",
862
- clientSecret: "safe-secret",
862
+ clientSecret: "example-safe-secret",
863
863
  authorizeUrl: "https://oauth.vendor.test/authorize",
864
864
  tokenUrl: "https://oauth.vendor.test/token",
865
865
  scopes: [],
@@ -1193,7 +1193,7 @@ describe("/api/script-connections HTTP", () => {
1193
1193
  });
1194
1194
 
1195
1195
  describe("DELETE /api/oauth-apps/{provider}/tokens", () => {
1196
- const ACCESS_TOKEN = "access-token-should-not-leak";
1196
+ const ACCESS_TOKEN = "example-access-token-should-not-leak";
1197
1197
  const realFetch = globalThis.fetch;
1198
1198
 
1199
1199
  afterEach(() => {
@@ -1203,7 +1203,7 @@ describe("DELETE /api/oauth-apps/{provider}/tokens", () => {
1203
1203
  async function seedOAuthApp(metadata?: Record<string, unknown>) {
1204
1204
  await upsertOAuthApp("vendor_oauth", {
1205
1205
  clientId: "vendor-client",
1206
- clientSecret: "oauth-client-secret-should-not-leak",
1206
+ clientSecret: "example-oauth-client-secret-should-not-leak",
1207
1207
  authorizeUrl: "https://oauth.vendor.test/authorize",
1208
1208
  tokenUrl: "https://oauth.vendor.test/token",
1209
1209
  redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
@@ -1215,7 +1215,7 @@ describe("DELETE /api/oauth-apps/{provider}/tokens", () => {
1215
1215
  async function seedTokens() {
1216
1216
  await storeOAuthTokens("vendor_oauth", {
1217
1217
  accessToken: ACCESS_TOKEN,
1218
- refreshToken: "refresh-token-should-not-leak",
1218
+ refreshToken: "example-refresh-token-should-not-leak",
1219
1219
  expiresAt: new Date(Date.now() + 3_600_000).toISOString(),
1220
1220
  scope: "read,write",
1221
1221
  });
@@ -1282,13 +1282,13 @@ describe("DELETE /api/oauth-apps/{provider}/tokens", () => {
1282
1282
  expect(captured?.body).toContain(`token=${ACCESS_TOKEN}`);
1283
1283
  // Tokens and secrets must never leak into the HTTP response.
1284
1284
  expect(res.text).not.toContain(ACCESS_TOKEN);
1285
- expect(res.text).not.toContain("oauth-client-secret-should-not-leak");
1285
+ expect(res.text).not.toContain("example-oauth-client-secret-should-not-leak");
1286
1286
  });
1287
1287
  });
1288
1288
 
1289
1289
  describe("POST /api/oauth-apps/{provider}/refresh", () => {
1290
- const ACCESS_TOKEN = "access-token-should-not-leak";
1291
- const REFRESH_TOKEN = "refresh-token-should-not-leak";
1290
+ const ACCESS_TOKEN = "example-access-token-should-not-leak";
1291
+ const REFRESH_TOKEN = "example-refresh-token-should-not-leak";
1292
1292
  const realFetch = globalThis.fetch;
1293
1293
 
1294
1294
  afterEach(() => {
@@ -1298,7 +1298,7 @@ describe("POST /api/oauth-apps/{provider}/refresh", () => {
1298
1298
  async function seedOAuthApp() {
1299
1299
  await upsertOAuthApp("vendor_oauth", {
1300
1300
  clientId: "vendor-client",
1301
- clientSecret: "oauth-client-secret-should-not-leak",
1301
+ clientSecret: "example-oauth-client-secret-should-not-leak",
1302
1302
  authorizeUrl: "https://oauth.vendor.test/authorize",
1303
1303
  tokenUrl: "https://oauth.vendor.test/token",
1304
1304
  redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
@@ -1356,10 +1356,10 @@ describe("POST /api/oauth-apps/{provider}/refresh", () => {
1356
1356
  };
1357
1357
  return new Response(
1358
1358
  JSON.stringify({
1359
- access_token: "new-access-token-should-not-leak",
1359
+ access_token: "example-new-access-token-should-not-leak",
1360
1360
  token_type: "bearer",
1361
1361
  expires_in: 7200,
1362
- refresh_token: "new-refresh-token-should-not-leak",
1362
+ refresh_token: "example-new-refresh-token-should-not-leak",
1363
1363
  scope: "read,write",
1364
1364
  }),
1365
1365
  { status: 200, headers: { "content-type": "application/json" } },
@@ -1387,16 +1387,16 @@ describe("POST /api/oauth-apps/{provider}/refresh", () => {
1387
1387
 
1388
1388
  // Response carries the NEW expiry from the mocked expires_in=7200.
1389
1389
  const stored = await getOAuthTokens("vendor_oauth");
1390
- expect(stored?.accessToken).toBe("new-access-token-should-not-leak");
1390
+ expect(stored?.accessToken).toBe("example-new-access-token-should-not-leak");
1391
1391
  expect(body.expiresAt).toBe(stored?.expiresAt ?? "");
1392
1392
  expect(new Date(body.expiresAt ?? 0).getTime()).toBeGreaterThan(Date.now() + 3_600_000);
1393
1393
 
1394
1394
  // No token values in the HTTP response.
1395
1395
  expect(res.text).not.toContain(ACCESS_TOKEN);
1396
1396
  expect(res.text).not.toContain(REFRESH_TOKEN);
1397
- expect(res.text).not.toContain("new-access-token-should-not-leak");
1398
- expect(res.text).not.toContain("new-refresh-token-should-not-leak");
1399
- expect(res.text).not.toContain("oauth-client-secret-should-not-leak");
1397
+ expect(res.text).not.toContain("example-new-access-token-should-not-leak");
1398
+ expect(res.text).not.toContain("example-new-refresh-token-should-not-leak");
1399
+ expect(res.text).not.toContain("example-oauth-client-secret-should-not-leak");
1400
1400
  });
1401
1401
 
1402
1402
  test("502 when the provider token endpoint rejects the refresh", async () => {
@@ -1434,7 +1434,7 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
1434
1434
  async function seedRotatingAuthorization() {
1435
1435
  await upsertOAuthApp("rotator", {
1436
1436
  clientId: "rotator-client",
1437
- clientSecret: "rotator-secret-should-not-leak",
1437
+ clientSecret: "example-rotator-secret-should-not-leak",
1438
1438
  authorizeUrl: "https://rotator.test/authorize",
1439
1439
  tokenUrl: "https://rotator.test/token",
1440
1440
  redirectUri: "https://api.public.test/api/oauth/callback",
@@ -1445,8 +1445,8 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
1445
1445
  if (!app) throw new Error("app not created");
1446
1446
  return upsertAuthorization({
1447
1447
  appId: app.id,
1448
- accessToken: "old-access-should-not-leak",
1449
- refreshToken: "old-refresh-should-not-leak",
1448
+ accessToken: "example-old-access-should-not-leak",
1449
+ refreshToken: "example-old-refresh-should-not-leak",
1450
1450
  status: "active",
1451
1451
  });
1452
1452
  }
@@ -1458,7 +1458,10 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
1458
1458
  // refresh token.
1459
1459
  globalThis.fetch = (async () =>
1460
1460
  new Response(
1461
- JSON.stringify({ access_token: "new-access-should-not-leak", token_type: "bearer" }),
1461
+ JSON.stringify({
1462
+ access_token: "example-new-access-should-not-leak",
1463
+ token_type: "bearer",
1464
+ }),
1462
1465
  { status: 200, headers: { "content-type": "application/json" } },
1463
1466
  )) as typeof fetch;
1464
1467
 
@@ -1475,8 +1478,8 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
1475
1478
  // token may be provider-invalidated, so the sweep must retry it.
1476
1479
  const after = await getAuthorizationById(authorization.id);
1477
1480
  expect(after?.lastRefreshedAt).toBeNull();
1478
- expect(after?.accessToken).toBe("old-access-should-not-leak");
1479
- expect(after?.refreshToken).toBe("old-refresh-should-not-leak");
1481
+ expect(after?.accessToken).toBe("example-old-access-should-not-leak");
1482
+ expect(after?.refreshToken).toBe("example-old-refresh-should-not-leak");
1480
1483
  expect(after?.status).toBe("refresh-failed");
1481
1484
  });
1482
1485
 
@@ -1485,10 +1488,10 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
1485
1488
  globalThis.fetch = (async () =>
1486
1489
  new Response(
1487
1490
  JSON.stringify({
1488
- access_token: "new-access-should-not-leak",
1491
+ access_token: "example-new-access-should-not-leak",
1489
1492
  token_type: "bearer",
1490
1493
  expires_in: 7200,
1491
- refresh_token: "rotated-refresh-should-not-leak",
1494
+ refresh_token: "example-rotated-refresh-should-not-leak",
1492
1495
  scope: "read,write",
1493
1496
  }),
1494
1497
  { status: 200, headers: { "content-type": "application/json" } },
@@ -1500,7 +1503,7 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
1500
1503
  });
1501
1504
 
1502
1505
  expect(res.status).toBe(200);
1503
- expect(res.text).not.toContain("rotated-refresh-should-not-leak");
1506
+ expect(res.text).not.toContain("example-rotated-refresh-should-not-leak");
1504
1507
  const body = (await res.json()) as { ok: boolean; status: string };
1505
1508
  expect(body.ok).toBe(true);
1506
1509
  const after = await getAuthorizationById(authorization.id);
@@ -30,7 +30,7 @@ import { registerScriptConnectionsTool } from "../tools/script-connections";
30
30
  import { refreshSecretScrubberCache } from "../utils/secret-scrubber";
31
31
 
32
32
  const TEST_DB_PATH = "./test-script-connections-mcp.sqlite";
33
- const API_KEY = "test-script-connections-mcp-key-1234567890";
33
+ const API_KEY = "example-test-script-connections-mcp-key-1234567890";
34
34
  const SECRET_VALUE = "mcp-secret-value-1234567890";
35
35
 
36
36
  type RegisteredTool = {
@@ -256,7 +256,7 @@ function serveOpenapiSpec(initialBody: string, initialEtag = '"v1"') {
256
256
  }
257
257
 
258
258
  beforeEach(() => {
259
- process.env.AGENT_SWARM_API_KEY = "script-connections-test-key";
259
+ process.env.AGENT_SWARM_API_KEY = "example-script-connections-test-key";
260
260
  delete process.env.API_KEY;
261
261
  process.env.MCP_BASE_URL = "http://localhost:3013";
262
262
  setOpenapiSpecFetchForTesting(fixtureOpenapiFetch);
@@ -570,6 +570,8 @@ describe("script connections", () => {
570
570
  markMigrationApplied(database, "151_repair_scheduled_task_required_params.sql");
571
571
  // 152 indexes task routing context absent from this migration-112-only fixture.
572
572
  markMigrationApplied(database, "152_routing_decisions.sql");
573
+ // 156 alters inbox_item_state, which this migration-112-only fixture does not create.
574
+ markMigrationApplied(database, "156_inbox_item_state_read_at.sql");
573
575
 
574
576
  const id = crypto.randomUUID();
575
577
  const now = new Date().toISOString();
@@ -20,7 +20,7 @@ import { getPathSegments, parseQueryParams } from "../http/utils";
20
20
  import { refreshSecretScrubberCache } from "../utils/secret-scrubber";
21
21
 
22
22
  const TEST_DB_PATH = "./test-script-runs-http.sqlite";
23
- const API_KEY = "test-script-runs-http-key-1234567890";
23
+ const API_KEY = "example-test-script-runs-http-key-1234567890";
24
24
 
25
25
  let agentId: string;
26
26
  let savedEnv: NodeJS.ProcessEnv;
@@ -401,7 +401,10 @@ describe("/api/script-runs HTTP", () => {
401
401
  expect(stepCount.c).toBe(1);
402
402
  });
403
403
 
404
- test("agent-task dispatch preserves existing author pins and records human_pinned", async () => {
404
+ test.each([
405
+ undefined,
406
+ "skill",
407
+ ] as const)("agent-task dispatch preserves author pins and routing provenance for %s", async (routingReason) => {
405
408
  const created = await dispatch("/api/script-runs", {
406
409
  method: "POST",
407
410
  agentId,
@@ -412,7 +415,7 @@ describe("/api/script-runs HTTP", () => {
412
415
  const responsePromise = dispatch(`/api/internal/script-runs/${runId}/agent-task`, {
413
416
  method: "POST",
414
417
  agentId,
415
- body: JSON.stringify({ stepKey: "pinned", task: "do pinned work", agentId }),
418
+ body: JSON.stringify({ stepKey: "pinned", task: "do pinned work", agentId, routingReason }),
416
419
  });
417
420
 
418
421
  let dispatched = await getLatestScriptRunStepTaskByContextKey(`script-run:${runId}:pinned`);
@@ -426,10 +429,15 @@ describe("/api/script-runs HTTP", () => {
426
429
  expect(response.status).toBe(200);
427
430
  const { taskId } = (await response.json()) as { taskId: string };
428
431
  expect(
429
- await getDbClient().get("SELECT agentId, routing_reason FROM agent_tasks WHERE id = ?", [
430
- taskId,
431
- ]),
432
- ).toEqual({ agentId, routing_reason: "human_pinned" });
432
+ await getDbClient().get(
433
+ "SELECT agentId, routing_reason, routing_source FROM agent_tasks WHERE id = ?",
434
+ [taskId],
435
+ ),
436
+ ).toEqual({
437
+ agentId,
438
+ routing_reason: routingReason ?? "human_pinned",
439
+ routing_source: routingReason ? "declared" : "engine_default",
440
+ });
433
441
  });
434
442
 
435
443
  test("agent-task polling returns the step output when a newer completed follow-up shares its context key", async () => {
@@ -32,7 +32,7 @@ import { CHILD_PROCESS_TEST_BUDGET_MS } from "./test-proc";
32
32
 
33
33
  const TEST_DB_PATH = "./test-script-workflows-runtime-e2e.sqlite";
34
34
  const WORKFLOW_RUNTIME_DIR = "./test-script-workflows-runtime";
35
- const API_KEY = "test-script-workflows-runtime-key-1234567890";
35
+ const API_KEY = "example-test-script-workflows-runtime-key-1234567890";
36
36
  const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
37
37
 
38
38
  let agentId: string;
@@ -41,6 +41,10 @@ class FakeEmbeddingProvider implements EmbeddingProvider {
41
41
  return Promise.all(texts.map((text) => this.embed(text)));
42
42
  }
43
43
 
44
+ isConfigured(): boolean {
45
+ return true;
46
+ }
47
+
44
48
  reset(): void {
45
49
  this.calls.length = 0;
46
50
  }
@@ -58,6 +58,10 @@ class FakeEmbeddingProvider implements EmbeddingProvider {
58
58
  return Promise.all(texts.map((text) => this.embed(text)));
59
59
  }
60
60
 
61
+ isConfigured(): boolean {
62
+ return true;
63
+ }
64
+
61
65
  reset(): void {
62
66
  this.calls.length = 0;
63
67
  }
@@ -23,7 +23,7 @@ import { SKIP_SANDBOX_SPAWN_TESTS } from "./sandbox-spawn-test-helpers";
23
23
  const skip = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
24
24
 
25
25
  const TEST_DB_PATH = "./test-scripts-external-api.sqlite";
26
- const API_KEY = "test-external-api-key-1234567890";
26
+ const API_KEY = "example-test-external-api-key-1234567890";
27
27
 
28
28
  const noOpEmbeddingProvider = {
29
29
  name: "test/noop-script-embedding",
@@ -15,7 +15,7 @@ import { SKIP_SANDBOX_SPAWN_TESTS } from "./sandbox-spawn-test-helpers";
15
15
  const skip = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
16
16
 
17
17
  const TEST_DB_PATH = "./test-scripts-http.sqlite";
18
- const API_KEY = "test-scripts-http-key-1234567890";
18
+ const API_KEY = "example-test-scripts-http-key-1234567890";
19
19
 
20
20
  function fakeEmbedding(text: string): Float32Array {
21
21
  const lower = text.toLowerCase();
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
- import { validateScriptImports } from "../scripts-runtime/import-allowlist";
2
+ import { checkImportAllowlist, validateScriptImports } from "../scripts-runtime/import-allowlist";
3
3
 
4
4
  describe("script import allowlist", () => {
5
5
  test("allows relative imports and runtime barrels", () => {
@@ -61,6 +61,49 @@ describe("script import allowlist", () => {
61
61
  if (!result.ok) expect(result.diagnostic).toContain("fs");
62
62
  });
63
63
 
64
+ test("allows literal dynamic imports from the existing script allowlist", () => {
65
+ expect(validateScriptImports("export default async () => import('zod')")).toEqual({
66
+ ok: true,
67
+ });
68
+ });
69
+
70
+ test("allows computed dynamic imports by default", () => {
71
+ expect(validateScriptImports("const x = 'zod'; export default async () => import(x)")).toEqual({
72
+ ok: true,
73
+ });
74
+ });
75
+
76
+ test("strictDynamic rejects computed dynamic imports and requires", () => {
77
+ for (const source of [
78
+ "const name = 'zod'; export default async () => import(name)",
79
+ "const name = 'zod'; export default () => require(name)",
80
+ ]) {
81
+ const result = checkImportAllowlist(source, {
82
+ allowedBare: ["swarm-extension", "stdlib", "zod"],
83
+ allowRelative: false,
84
+ strictDynamic: true,
85
+ });
86
+ expect(result.ok).toBe(false);
87
+ if (!result.ok) expect(result.diagnostic).toContain("Computed");
88
+ }
89
+ });
90
+
91
+ test("strictDynamic checks require and import-equals specifiers", () => {
92
+ for (const source of [
93
+ "export default () => require('node:fs')",
94
+ "import fs = require('node:fs'); export default () => fs",
95
+ ]) {
96
+ expect(validateScriptImports(source)).toEqual({ ok: true });
97
+ const result = checkImportAllowlist(source, {
98
+ allowedBare: ["swarm-extension", "stdlib", "zod"],
99
+ allowRelative: false,
100
+ strictDynamic: true,
101
+ });
102
+ expect(result.ok).toBe(false);
103
+ if (!result.ok) expect(result.diagnostic).toContain("node:fs");
104
+ }
105
+ });
106
+
64
107
  test("rejects Function constructor dynamic import bypasses", () => {
65
108
  const result = validateScriptImports(
66
109
  `export default async () => new Function("return import('node:fs')")()`,